<!-- Source: https://medius.k4tech.net/native/commands/raw -->
# Raw

_Verbatim bytes on a cloned endpoint_

[`RAW`](/native/commands/raw.md#raw) places one packet or bulk transfer, byte for byte, on an endpoint named by number and direction: IN to the game PC, OUT to the real device. It enters the path after every stage that reads or rewrites a packet.

```
  IN    native report --> rewrite --> lock, render, inject --> rewrite ---+
                          HID_IN                               EMIT       |
                                                                          v
                                             RAW(ep, 1) ------> [ IN queue ] --> game PC

  OUT   game PC --------> rewrite ----------------------------------------+
                          HID_OUT, VEND_INTR, VEND_BULK                   |
                                                                          v
                                             RAW(ep, 2) ------> [ OUT relay ] --> real device

  rewrite = the rewrite rules and the clip packet triggers on that surface
```

Standard inputs belong in [`INJECT`](/native/commands/inject.md#inject) and [`MOVE`](/native/commands/move.md#move), which the box renders into a faithful report; `RAW` is for bytes no semantic field describes.

> **Warning**
>
> `RAW` runs only under [`OPTION(IMPERFECT)`](/native/commands/option.md#imperfect). Otherwise the box discards the frame with no reply, and discards a [clip raw item](/native/commands/clip.md#items), counted in [`gated`](/native/commands/requests.md#clip).

## RAW

_One packet or bulk transfer on one endpoint_

`RAW` carries an endpoint address and the bytes to put there. [Opcode](/native/frame.md#opcodes) `0x19`.

```text
RAW 0x19 · payload 2 + n bytes
```

_Fire-and-forget_

#### PAYLOAD

| Offset | Field | Type | Notes |
| --- | --- | --- | --- |
| 0 | `ep_num` | `u8` | endpoint number; low four bits used |
| 1 | `dir` | `u8` | `1` IN, `2` OUT (the [`LOCK`](/native/commands/lock.md) direction byte) |
| 2 | `bytes` | `u8[]` | packet, verbatim; delimited by the frame [`LEN`](/native/frame.md#layout), so at most 510 bytes |

#### DIRECTION

| Value | Name | Effect |
| --- | --- | --- |
| `1` | IN | queued on the clone's IN endpoint `ep_num` (HID interrupt, vendor interrupt or bulk) for the game PC to read |
| `2` | OUT | relayed through the host chip to OUT endpoint `ep_num` (HID interrupt, vendor interrupt or bulk) on the real device |

#### REFUSALS

| Refused when | Why |
| --- | --- |
| payload under 2 bytes | no endpoint address |
| clone not yet configured by the game PC | clone endpoints are unarmed until the PC's `SET_CONFIGURATION` |
| `dir` is not `1` or `2` | only `1` (IN) and `2` (OUT) name an address |
| IN: no cloned HID or vendor IN endpoint `ep_num` | the box writes only IN endpoints it cloned |
| OUT: no real-device OUT endpoint `ep_num` | the host chip drops it, with no endpoint to submit to |
| an interrupt packet past its [limit](/native/commands/raw.md#packets) | an interrupt transfer is one packet, so a split would reach the PC as two reports |

#### EFFECT

The bytes reach the endpoint as given. `RAW` has no reply; an [`EMIT`](/native/commands/raw.md#catch) subscription shows an IN packet as the game PC reads it.

#### EXAMPLE

Left button down on HID interrupt IN endpoint 1: `ep_num = 1`, `dir = 1`, a 4-byte report:

```
+--------+--------+--------+--------+--------+--------+-------------+--------+
| A5     | 19     | 00     | 06 00  | 01     | 01     | 01 00 00 00 | lo hi  |
+--------+--------+--------+--------+--------+--------+-------------+--------+
| SOF    | TYPE   | SEQ    | LEN    | ep_num | dir    | bytes       | CRC16  |
+--------+--------+--------+--------+--------+--------+-------------+--------+
```

The release, button bit clear:

```
+--------+--------+--------+--------+--------+--------+-------------+--------+
| A5     | 19     | 01     | 06 00  | 01     | 01     | 00 00 00 00 | lo hi  |
+--------+--------+--------+--------+--------+--------+-------------+--------+
| SOF    | TYPE   | SEQ    | LEN    | ep_num | dir    | bytes       | CRC16  |
+--------+--------+--------+--------+--------+--------+-------------+--------+
```

A keyboard LED report, Caps Lock on, to interrupt OUT endpoint 2: `ep_num = 2`, `dir = 2`, one byte:

```
+--------+--------+--------+--------+--------+--------+--------+--------+
| A5     | 19     | 02     | 03 00  | 02     | 02     | 02     | lo hi  |
+--------+--------+--------+--------+--------+--------+--------+--------+
| SOF    | TYPE   | SEQ    | LEN    | ep_num | dir    | bytes  | CRC16  |
+--------+--------+--------+--------+--------+--------+--------+--------+
```

Library bindings: [`raw`](/library/advanced/raw.md#raw), and [`raw`](/library/advanced/raw.md#async) on `AsyncDevice`.

## Packet size

_Per transfer type_

An OUT packet is the endpoint's `wMaxPacketSize` on the wire, as IN; the inter-chip relay carries a bulk payload in pieces of at most 64 bytes.

| Aspect | `dir = 1`, IN | `dir = 2`, OUT |
| --- | --- | --- |
| Interrupt | one packet, at most the endpoint's `wMaxPacketSize` and at most 64 bytes | one packet, at most the endpoint's `wMaxPacketSize` |
| Bulk | split at `wMaxPacketSize` | split at `wMaxPacketSize` |
| Bulk end | a short packet, or a zero-length packet (ZLP) when the payload is an exact multiple of `wMaxPacketSize`; an empty `bytes` sends one ZLP | a short packet, or a zero-length packet (ZLP) when the payload is an exact multiple of `wMaxPacketSize`; an empty `bytes` sends one ZLP |

#### SPLIT

```
  bulk, wMaxPacketSize = 64

  bytes = 130   -->   [ 64 ] [ 64 ] [ 2 ]      the 2-byte packet ends the transfer
  bytes = 128   -->   [ 64 ] [ 64 ] [ ZLP ]    an exact multiple ends on a ZLP
  bytes = 0     -->   [ ZLP ]
```

#### QUEUES

| Name | Behaviour |
| --- | --- |
| HID IN, 8 reports | drops the oldest native report when full, else the oldest `RAW` one, counted in [`tx_drops`](/native/commands/requests.md#stats) |
| vendor interrupt IN, 8 packets | drops the oldest packet when full, counted in [`relay_drops`](/native/commands/requests.md#stats) |
| vendor bulk IN, 8 packets | drops the new packet when full, counted in `relay_drops`; at 6 queued it pauses the native bulk stream until the queue drains to 2 |
| OUT relay, 8 packets | drops the new packet when full, counted in `relay_drops` |

> **Warning**
>
> A bulk IN transfer longer than the queue's free slots reaches the game PC truncated. At `wMaxPacketSize = 64`, 510 bytes is 8 packets, the whole queue.

## Lifetime

_Held until the next native report_

A `RAW` IN report is the last state the game PC read on that endpoint until the next native report replaces it.

A `RAW` report takes a poll of its own; no native report carries it. On an endpoint the device reports on every poll, it goes after at most two native reports.

```
  native report   [ btn 0 ]                            [ btn 0 ]
  RAW, dir = 1                  [ btn 1 ]
  on the wire     [ btn 0 ]     [ btn 1 ]              [ btn 0 ]
                                |<- last report read ->|
```

#### PIPELINE

A `RAW` packet goes straight to the endpoint, past every [rewrite rule](/native/commands/rewrite.md), [clip packet trigger](/native/commands/clip.md#packet-triggers), [`LOCK`](/native/commands/lock.md), [`TRANSFORM`](/native/commands/transform.md), [rendering](/native/commands/option.md#render) and [injection](/native/injection.md).

| Mechanism | Effect |
| --- | --- |
| report merging | sums motion between other queued reports and keeps each `RAW` report whole, byte for byte |
| change suppression | records a `RAW` report shaped like the mouse, keyboard or media report the box injects into as the last report emitted, the baseline for injected frames |

A [clip raw item](/native/commands/clip.md#items) is the same packet on a clip tick, with its own release rule.

## Catch taps

_Traffic classes a RAW packet raises_

A `RAW` IN packet raises [`TRAFFIC_EVENT`](/native/commands/catch.md#traffic-event)s on the taps it passes. The [`HID_IN`](/native/commands/catch.md#catch) and OUT taps sit upstream of `RAW`'s entry point.

| When | Raises |
| --- | --- |
| the game PC reads a non-empty `RAW` report off a HID IN endpoint | [`EMIT`](/native/commands/catch.md#catch) (`9`), `dir = 1` |
| a `RAW` packet enters a vendor IN queue | [`VEND_INTR`](/native/commands/catch.md#catch) (`6`) or [`VEND_BULK`](/native/commands/catch.md#catch) (`7`), `dir = 1`, stamped [`clk = 1`](/native/commands/catch.md#clocks) by the device chip; bulk carries the end-of-transfer and ZLP [flags](/native/commands/catch.md#traffic-event) |
| the game PC reads a non-empty `RAW` packet off a vendor IN endpoint | `EMIT` (`9`), `dir = 1` |
