<!-- Source: https://medius.k4tech.net/library/advanced/raw -->
# Raw injection

_Put a report byte-for-byte on a cloned endpoint_

`raw` puts `bytes` verbatim on one cloned endpoint, named by number and direction: `IN` emits toward the game PC, `OUT` relays to the real device. It carries no semantic model and no merge with native motion.

The write is stateless: the next native report overwrites it, and `raw` bypasses the [rewrite rules](/library/advanced/rewrite.md).

```
  native device          the box  (host chip  |  device chip = the clone)         game PC

  HID report  ---IN--->  [ HID_IN ]--> renderer --> [ EMIT ]---interrupt-IN--->  reads report
                                                                    ^
                                                                    +-- raw(n, IN)   <== a report toward the PC

  relayed     <--OUT---  [ HID_OUT ]<-- relay <---------------- interrupt-OUT <--  writes report
                         (VEND_INTR / VEND_BULK)                 ^
                                                                 +-- raw(n, OUT)  <== a report toward the device

  control     <-- EP0 -> [ CONTROL ]<-- proxy ------------------- EP0 <-------->  GET_DESCRIPTOR, SET_*
  enumerate   descriptor patches overwrite what the clone presents
```

> **Warning**
>
> The whole advanced control layer is gated on the imperfect-clone opt-in. With [`allow_imperfect_clones`](/library/options.md#allow-imperfect-clones) off, `raw` returns [`Error::ImperfectRequired`](/library/types/errors.md#errors) rather than sending a frame the box would drop.

## raw

_One report on one endpoint, fire-and-forget_

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

_Fire-and-forget_

| Parameter | Type | Description |
| --- | --- | --- |
| `ep` | `u8` | The cloned endpoint number, 0 to 15. |
| `direction` | [`Direction`](/library/types/enums.md#direction) | `IN` emits toward the game PC, `OUT` relays to the real device. Any other is [`Error::RawDirection`](/library/types/errors.md#errors). |
| `bytes` | `&[u8]` | The report, on the wire as given. At most one interrupt endpoint's `wMaxPacketSize`; a bulk endpoint takes up to the 512-byte frame limit. |

#### EXAMPLE

```rust
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 size

_What the endpoint carries decides what fits_

The report is bounded by the endpoint it goes on, and the two transfer types the box relays treat an over-long payload differently.

| Endpoint type | A payload over the limit |
| --- | --- |
| Interrupt | Past the endpoint's `wMaxPacketSize` the report is dropped box-side. Keep a report within one packet. |
| Bulk | Split at the packet size and terminated with a short packet, or a zero-length packet when the payload is an exact multiple, the way a bulk transfer ends on the wire. |

> **Note**
>
> A single advanced control layer frame carries up to 512 payload bytes (the [frame limit](/native/frame.md#layout)), the bound the C and Python buffers (`MEDIUS_MAX_DEV_PAYLOAD`) are sized to.

## Raw against injection

_When the bytes are the point_

A standard input in the device's own report belongs in [`inject`](/library/inject.md) and [`move_rel`](/library/move.md), not here. Those describe an input and let the box render it into a native-faithful report; `raw` describes bytes and leaves them untouched.

| Aspect | [`inject`](/library/inject.md) / [`move_rel`](/library/move.md) | `raw` |
| --- | --- | --- |
| Addresses | An axis or usage, by [semantic](/library/types/enums.md#axis) id | An endpoint, by number and direction |
| On the wire | Merged into the native report, clamped to the field width, paced to the native rate | The bytes as given, one report |
| State | Held until cleared; rides the native stream | Stateless; the next native report overwrites it |
| Rewrite rules | Apply | Bypassed |
| Gate | Always available | Imperfect-clone opt-in |

Reach for `raw` when the report itself is the point: a vendor packet no HID field describes, a byte sequence a device expects on an OUT endpoint, a report shape the semantic core does not model.

## The imperfect-clone gate

_One opt-in admits the whole layer_

The box admits the advanced control layer under the imperfect-clone opt-in and nothing else. The crate reads that state before it sends, so an off opt-in is a real error rather than a frame the box silently drops.

| Error | Returned on |
| --- | --- |
| [`ImperfectRequired`](/library/types/errors.md#errors) | The box reports the opt-in off. Turn it on with [`allow_imperfect_clones(true)`](/library/options.md#allow-imperfect-clones). |

The opt-in is a persistent [box option](/library/options.md), read back with [`query_imperfect`](/library/options.md#query-imperfect). It is the same gate the native [`OPTION(IMPERFECT)`](/native/commands/option.md#imperfect) sets.

## On AsyncDevice

_raw awaits the opt-in gate_

[`AsyncDevice`](/library/features/async.md) makes `raw` a future: it awaits the imperfect-clone opt-in check, then the send itself is fire-and-forget.

#### EXAMPLE

```rust
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]))?;  // awaits the opt-in gate
```
