Lock
Block one physical input by classLOCK stops the physical device from driving one input while leaving everything else alone. It's generic over the input class: a relative axis, a mouse button, a keyboard key, or a media usage, plus a blanket lock for a whole class. Host injection still drives a locked input, so a script can take one over; it's fire-and-forget.
LOCK
Lock or unlock a physical inputLOCK picks a class, an id within it, and a direction, then either blocks it or clears the block. A momentary usage shares INJECT's (class, id) space, so a button locks exactly like a key. Opcode 0x0A.
LOCK 0x0A · payload 5 bytes
Fire-and-forget
| Offset | Field | Type | Notes |
|---|---|---|---|
| 0 | class | u8 | the input class (see below) |
| 1 | id | u16 | which input within the class, little-endian; 0xFFFF = the whole class |
| 3 | direction | u8 | which sign or which edge (see below) |
| 4 | state | u8 | 1 = lock, 0 = unlock |
| Class | Value | id is |
|---|---|---|
| button | 0 | a button id (0=Left .. 4=Side2) |
| key | 1 | a HID keyboard usage (0xE0-0xE7 = modifier) |
| media | 2 | a 16-bit Consumer usage |
| axis | 3 | 0=X, 1=Y, 2=wheel (the sign is the direction) |
Classes 0-2 mirror INJECT. An id of 0xFFFF is a blanket: it locks every usage in that class in one command (every button, every key, or every media usage).
What direction means depends on the input. For an axis it's a sign, so you can block scrolling up but not down. For a button, key, or media usage it's an edge, so you can block the press but not the release.
| Direction | Value | Axis | Button / key / media |
|---|---|---|---|
| both | 0 | Both signs. | Press and release. |
| positive | 1 | Positive sign only (+). | Press only (0 to 1). |
| negative | 2 | Negative sign only (-). | Release only (1 to 0). |
A lock blocks the physical device and nothing else. Host injection still reaches a locked input, so a MOVE moves a locked axis and an INJECT drives a locked button or key. Lock an input the user shouldn't touch, then drive it yourself.
unlock you send the matching unlock (state = 0) silence ~1 s with no control-PC frame (same net as injection) RESET a RESET command link loss the inter-chip link drops
A lock isn't permanent. It auto-clears on the same safety net as injection, so hold it with a keepalive if the user has to stay locked out.
Locks are PC-owned and never visible to the game PC. QUERY(LOCKS) reads the active set across every class; the HEALTH LOCK_ON bit is set while any lock, of any class, is active. Library bindings: lock / unlock, and lock_all / unlock_all for a blanket.
Lock the wheel's negative (scroll-down) sign: class = 3 (axis), id = 2 (wheel), direction = 2, state = 1:
+--------+--------+--------+--------+--------+--------+--------+--------+--------+ | A5 | 0A | 00 | 05 00 | 03 | 02 00 | 02 | 01 | lo hi | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ | SOF | TYPE | SEQ | LEN | class | id | dir | state | CRC16 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+