rawOne report on one endpoint, fire-and-forget

fn raw(&self, ep: u8, direction: Direction, bytes: &[u8]) -> Result<()>

Fire-and-forget

ParameterTypeDescription
epu8Cloned endpoint number, 0-15.
directionDirectionIN emits toward the game PC, OUT writes to the real device. Any other value returns Error::RawDirection.
bytes&[u8]The report, sent as given, ≤510 bytes. An interrupt report must fit one packet. A bulk payload is split per packet size.
EXAMPLE
use medius::{Device, Direction};

let device = Device::find()?;
device.allow_imperfect_clones(true)?;
device.raw(1, Direction::IN, &[0x00, 0x01, 0x00, 0x00])?;  // one report on interrupt-IN endpoint 1

Packet sizeBounded by the endpoint

Endpoint typeOver the limit
InterruptDropped by the box if longer than one packet (the endpoint's wMaxPacketSize), IN or OUT. On a HID IN endpoint whose largest Input report is longer than wMaxPacketSize, a full packet gets a zero-length packet after it (as a native report of that length does), so the PC's read ends there.
BulkSplit at wMaxPacketSize in either direction. A short packet ends the payload, or a zero-length packet if the payload is an exact multiple of wMaxPacketSize.

An advanced control layer frame carries ≤512 payload bytes (the frame limit). The C and Python buffers (MEDIUS_MAX_DEV_PAYLOAD) are the same size. raw spends two on endpoint and direction, leaving 510. The wire layout is on the native RAW command.

Raw vs injectionBytes or semantic input

For a standard input in the native report, use inject and move_rel. They describe an input that the box renders into a faithful report. raw sends bytes untouched.

Aspectinject / move_relraw
AddressesAn axis or usage, by semantic idAn endpoint, by number and direction
On the wireMerged into the native report, clamped to the field width, paced to the native report rateThe bytes as given, one report
StateHeld until cleared; rides the native streamStateless; the next native report overwrites it
Rewrite rules, packet triggersApplyBypassed
GateAlways availableImperfect-clone opt-in

raw is for a vendor packet no HID field describes, a byte sequence the real device expects on an OUT endpoint, or a report shape the semantic core does not model.

Imperfect-clone gateOne opt-in enables the whole layer

set_rewrite and apply_patch read the opt-in before sending. raw runs per report, so it sends without reading the opt-in.

ErrorReturned on
ImperfectRequiredset_rewrite or apply_patch, when the box reports the opt-in off. Turn it on with allow_imperfect_clones(true).

The opt-in is a persistent box option, read back with query_imperfect. The native OPTION(IMPERFECT) sets the same gate.

On AsyncDeviceraw is a future over the same send

AsyncDevice makes raw a future. The send stays fire-and-forget.

EXAMPLE
use futures::executor::block_on;
use medius::{AsyncDevice, Direction};

let device = AsyncDevice::open("/dev/ttyACM0")?;
device.allow_imperfect_clones(true)?;
block_on(device.raw(1, Direction::IN, &[0x00, 0x01, 0x00, 0x00]))?;