<!-- Source: https://medius.k4tech.net/native/commands/catch -->
# Catch

_Stream the physical mouse, keyboard, and media input to the PC_

[`CATCH`](/native/commands/catch.md#catch) subscribes to the user's real input. While subscribed, the box pushes a [`MOTION_EVENT`](/native/commands/catch.md#motion-event) for movement and the wheel, and a [`USAGE_EVENT`](/native/commands/catch.md#usage-event) for buttons, keys, and media, captured at the merge point _before_ any [`LOCK`](/native/commands/lock.md) suppression or [injection](/native/injection.md), so you can lock an input and still see it to rebind it. Subscribing is [fire-and-forget](/native/injection.md#fire-and-forget); the box streams until you unsubscribe.

## CATCH

_Subscribe to the physical-input event stream_

`CATCH` sends a one-byte class mask. A non-zero mask subscribes; `0` unsubscribes. [Opcode](/native/frame.md#opcodes) `0x0B`.

```text
CATCH 0x0B · payload 1 byte
```

_Fire-and-forget_

#### PAYLOAD

| Offset | Field | Type | Notes |
| --- | --- | --- | --- |
| 0 | `mask` | `u8` | which classes to stream (see below); `0` = unsubscribe |

#### MASK

Each bit turns on one class of change. The mask only chooses which reports _trigger_ an event (every event carries the full held-usage snapshot), so a buttons-only subscription stays sparse even though the mouse reports at ~1 kHz. Combine bits with OR; `0x1F` subscribes to every class.

| Class | Bit | Triggers on |
| --- | --- | --- |
| Motion | `0x01` | a non-zero X or Y delta (a [`MOTION_EVENT`](/native/commands/catch.md#motion-event)). |
| Wheel | `0x02` | a non-zero wheel delta (a [`MOTION_EVENT`](/native/commands/catch.md#motion-event)). |
| Buttons | `0x04` | a mouse-button edge (a [`USAGE_EVENT`](/native/commands/catch.md#usage-event)). |
| Keys | `0x08` | a keyboard key or modifier change (a [`USAGE_EVENT`](/native/commands/catch.md#usage-event)). |
| Media | `0x10` | a media (Consumer) usage change (a [`USAGE_EVENT`](/native/commands/catch.md#usage-event)). |

#### PHYSICAL ONLY

The stream reports the user's _physical_ input, never your injected overrides, and it reads the report before [`LOCK`](/native/commands/lock.md) clamps it, so a locked axis or blocked button is still reported here. That's the intercept-and-rebind loop: lock an input to hide it from the game, catch it to act on it.

#### EFFECT

The box streams from the moment a non-zero mask arrives until you send `0`. The subscription is PC-owned and clears on the same triggers as injection: control-PC silence (the ~1 s timeout), a [`RESET`](/native/commands/admin.md#reset), a mouse detach, or inter-chip link loss, plus an explicit unsubscribe. The host library holds an open subscription alive with its keepalive (re-asserting it after a device-side blip) and across a reconnect. [`QUERY(CATCH)`](/native/commands/requests.md#catch) reads the active mask and a dropped-event count; the HEALTH [`CATCH_ON`](/native/commands/requests.md#health) bit is set while subscribed. Library binding: [`catch_events`](/library/catch.md#catch-events).

#### EXAMPLE

Subscribe to every class (`mask = 0x1F`):

```
+--------+--------+--------+--------+--------+--------+
| A5     | 0B     | 00     | 01 00  | 1F     | lo hi  |
+--------+--------+--------+--------+--------+--------+
| SOF    | TYPE   | SEQ    | LEN    | mask   | CRC16  |
+--------+--------+--------+--------+--------+--------+
```

## MOTION_EVENT

_One physical relative-axis snapshot, box → PC_

While a subscription with `Motion` or `Wheel` is active the box pushes a `MOTION_EVENT` for each physical report whose motion changed. It's unsolicited (there's no [`QUERY`](/native/commands/requests.md#requests) to correlate), so [`SEQ`](/native/frame.md#seq) is a rolling per-event counter shared with [`USAGE_EVENT`](/native/commands/catch.md#usage-event): a host detects dropped events as `SEQ` gaps. [Opcode](/native/frame.md#opcodes) `0x0C`.

```text
MOTION_EVENT 0x0C · payload 6 bytes
```

_Unsolicited_

#### PAYLOAD

| Offset | Field | Type | Notes |
| --- | --- | --- | --- |
| 0 | `dx` | `i16` | physical X this report; + = right, little-endian |
| 2 | `dy` | `i16` | physical Y this report; + = down, little-endian |
| 4 | `dz` | `i16` | physical wheel delta this report; + = up, little-endian |

#### BEST-EFFORT

Delivery is best-effort: under back-pressure the box drops events (counted in [`QUERY(CATCH)`](/native/commands/requests.md#catch)) rather than stalling the report path, so the stream never delays the game-PC-facing reports.

#### EXAMPLE

The user moves +10 right, no vertical or wheel motion (`dx = 10`):

```
+--------+--------+--------+--------+--------+--------+--------+--------+
| A5     | 0C     | 2A     | 06 00  | 0A 00  | 00 00  | 00 00  | lo hi  |
+--------+--------+--------+--------+--------+--------+--------+--------+
| SOF    | TYPE   | SEQ    | LEN    | dx     | dy     | dz     | CRC16  |
+--------+--------+--------+--------+--------+--------+--------+--------+
```

## USAGE_EVENT

_One physical held-usage snapshot, box → PC_

While a subscription with `Buttons`, `Keys`, or `Media` is active the box pushes a `USAGE_EVENT` when that class changes: a class-tagged snapshot of the usages currently held, so a mouse-button press and a key press have the same shape. It's a full snapshot, not edge deltas, so a dropped frame self-corrects on the next one; diff successive snapshots per class for press / release edges. [Opcode](/native/frame.md#opcodes) `0x0F`.

```text
USAGE_EVENT 0x0F · payload 1 + 3n bytes
```

_Unsolicited_

#### PAYLOAD

| Offset | Field | Type | Notes |
| --- | --- | --- | --- |
| 0 | `n` | `u8` | number of held usages that follow |
| + | `class` | `u8` | per usage: 0=button 1=key 2=media (as [`INJECT`](/native/commands/inject.md#inject)) |
| + | `id` | `u16` | the held usage's id (a button id, HID keycode with 0xE0-0xE7 modifiers, or Consumer usage), little-endian |

#### ONE CLASS PER EVENT

Each entry is 3 bytes; the snapshot is `n` of them, all one class (one physical report is one class), so a `Keys` event lists every held key and a `Buttons` event every held button. Best-effort like [`MOTION_EVENT`](/native/commands/catch.md#motion-event): dropped events are counted in [`QUERY(CATCH)`](/native/commands/requests.md#catch).

#### EXAMPLE

Left Shift held while pressing `A` (a keys snapshot, two usages both `class = 1`: Left Shift `id = 0xE1`, then A `id = 0x04`):

```
+--------+--------+--------+--------+--------+----------+----------+--------+
| A5     | 0F     | 2B     | 07 00  | 02     | 01 E1 00 | 01 04 00 | lo hi  |
+--------+--------+--------+--------+--------+----------+----------+--------+
| SOF    | TYPE   | SEQ    | LEN    | n      | usage[0] | usage[1] | CRC16  |
+--------+--------+--------+--------+--------+----------+----------+--------+
```
