1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
//! Frame opcodes and wire constants, pinned to `ctrl_proto.h` / `control-protocol.md`.
use fmt;
/// Start-of-frame byte; the receiver resyncs by scanning for it (§2).
pub const SOF: u8 = 0xA5;
/// Maximum payload length (§2); a larger `LEN` is rejected as bogus.
pub const MAX_PAYLOAD: usize = 512;
/// Protocol version in `RESP(VERSION)` (§4.1); the handshake requires this exact value.
pub const PROTO_VER: u8 = 6;
/// `INJECT` class byte: the momentary-usage field kind.
pub const INJ_BTN: u8 = 0;
pub const INJ_KEY: u8 = 1;
pub const INJ_MEDIA: u8 = 2;
/// `MOVE` motion byte: the relative-axis field kind.
pub const INJ_MOTION_CURSOR: u8 = 0;
pub const INJ_MOTION_WHEEL: u8 = 1;
/// `MOVE` flags byte: the per-command movement-riding override (§3.1).
pub const MV_F_NOW: u8 = 0x01;
pub const MV_F_FLUSH: u8 = 0x02;
pub const MV_F_DISCARD: u8 = 0x04;
pub const Q_VERSION: u8 = 0;
pub const Q_HEALTH: u8 = 1;
/// Cloned device identity: vid/pid/bcd + serial/bos flags + primary kind + product (§4.3).
pub const Q_DEVICE_INFO: u8 = 2;
/// Unified device capabilities (mouse, keyboard, per-class change_driven) for the whole cloned device (§4.4).
pub const Q_CAPS: u8 = 3;
/// Live native report rate + clone poll period + confidence (§4.5).
pub const Q_RATE: u8 = 4;
/// Delivery/telemetry counters (§4.6).
pub const Q_STATS: u8 = 5;
/// Active lock bitmask (§4.8, v1.5.0).
pub const Q_LOCKS: u8 = 6;
/// Active catch subscription mask + dropped-event count (§4.9, v1.6.0).
pub const Q_CATCH: u8 = 7;
// selector 8 retired (was Q_KBD_CAPS; keyboard caps folded into the unified Q_CAPS = 3).
/// Persistent box options, read one at a time by id: `QUERY [Q_OPTIONS][id]` → `RESP [Q_OPTIONS][id][value..]` (§4.14).
pub const Q_OPTIONS: u8 = 9;
/// `OPTION` id: imperfect-clone opt-in. Set value `[allow u8]`; readback adds `over_capacity`/`clone_imperfect`.
pub const OPT_IMPERFECT: u8 = 0;
/// `OPTION` id: movement riding. Value `[timeout u16 LE ms]`; 0 = off, N = ride window in ms.
pub const OPT_MOVE_RIDE: u8 = 1;
/// `OPTION` id: emit-rate pacing. Value `[mode u8][rate_hz u16 LE][force_hz u16 LE]`; mode 0 learnt / 1 bInterval / 2 fixed.
pub const OPT_EMIT: u8 = 2;
/// `OPTION` id: box name. Value `[name ascii]` 1..32 printable ASCII (0 bytes clears to default); set-only, read off `RESP(VERSION)`.
pub const OPT_NAME: u8 = 3;
/// `OPTION` id: the bearing. Value `[window u16 LE ms][mode u8]`; what `LOCK_DIR_WITH`/`AGAINST` are measured against (§3.12).
pub const OPT_BEARING: u8 = 4;
/// `OPTION` id: what the box renders motion with. Value `[mode u8][full u8]`; mode 0 off / 1 stock / 2 de-spiked / 3 unsmoothed.
pub const OPT_RENDER: u8 = 5;
/// `OPTION` id: how far an injected delta is spread across the host's command interval. Value `[percent u16 LE]`.
pub const OPT_SPREAD: u8 = 6;
/// `OPTION(BEARING)` mode: each axis reads its own sign against its own bearing.
pub const BEARING_PER_AXIS: u8 = 0;
/// `OPTION(BEARING)` mode: the physical delta is projected onto the injected XY vector; motion across it is untouched.
pub const BEARING_VECTOR: u8 = 1;
/// Buffered-clip status selector: `QUERY [Q_CLIP]` → `RESP(CLIP)` (§4.15).
pub const Q_CLIP: u8 = 10;
/// Both chips' firmware versions and slot state: `QUERY [Q_FIRMWARE]` → `RESP(FIRMWARE)` (§4.16).
pub const Q_FIRMWARE: u8 = 11;
/// `UPDATE` sub-ops (§3.13).
pub const OTA_OP_BEGIN: u8 = 0;
pub const OTA_OP_DATA: u8 = 1;
pub const OTA_OP_END: u8 = 2;
pub const OTA_OP_ABORT: u8 = 3;
pub const OTA_OP_ACTIVATE: u8 = 4;
/// Image bytes per `DATA` frame: the frame's 512 minus op, target and a 2-byte chunk index, rounded
/// down to a multiple of four so every flash write on the box is aligned.
pub const OTA_CHUNK: usize = 504;
/// `DATA` frames the box accepts before it must acknowledge, when it does not say otherwise.
pub const OTA_CREDIT: usize = 16;
/// `UPDATE_RESP` payload length: op, target, status, arg.
pub const UPD_RESP_LEN: usize = 7;
/// `CLIP_CTRL` engine verbs. Ops 0..5 are the shared action space (also a trigger `action` byte).
pub const CLIP_OP_START: u8 = 0;
pub const CLIP_OP_STOP: u8 = 1;
pub const CLIP_OP_PAUSE: u8 = 2;
pub const CLIP_OP_RESUME: u8 = 3;
pub const CLIP_OP_RESTART: u8 = 4;
pub const CLIP_OP_TOGGLE: u8 = 5;
pub const CLIP_OP_CLEAR: u8 = 6;
pub const CLIP_OP_FINALIZE: u8 = 7;
/// `CLIP_SET` scalar setting ids (OPTION-shaped `[id][value]`).
pub const CLIP_SET_AUTOLOCK: u8 = 0;
pub const CLIP_SET_LOOP: u8 = 1;
pub const CLIP_SET_RETAIN: u8 = 2;
pub const CLIP_SET_RIDE: u8 = 3;
/// `CLIP_TRIGGER` set: max bindings and the flags byte bits.
pub const CLIP_TRIG_MAX: usize = 8;
pub const CLIP_TRIG_F_PRESENT: u8 = 0x01;
pub const CLIP_TRIG_F_CONSUME: u8 = 0x02;
/// `RESP(CLIP)` config-section flags byte.
pub const CLIP_CFG_F_LOOP: u8 = 0x01;
pub const CLIP_CFG_F_RETAIN: u8 = 0x02;
pub const CLIP_CFG_F_FINALIZED: u8 = 0x04;
pub const CLIP_CFG_F_RIDE: u8 = 0x08;
/// Autolock scope bits (`CLIP_SET(AUTOLOCK)` value): which physical-input classes the clip auto-locks (0 = none).
pub const CLIP_LOCK_AIM: u8 = 0x01;
pub const CLIP_LOCK_WHEEL: u8 = 0x02;
pub const CLIP_LOCK_BUTTONS: u8 = 0x04;
pub const CLIP_LOCK_KEYS: u8 = 0x08;
pub const CLIP_LOCK_MEDIA: u8 = 0x10;
/// Trigger binding class/id wildcards: any class, any usage within a class.
pub const CLIP_COND_ANY_CLASS: u8 = 0xFF;
pub const CLIP_COND_ANY_ID: u16 = 0xFFFF;
/// Clip entry tags/flags (see [`ClipBuilder`](crate::ClipBuilder)).
pub const CLIP_TAG_GAP: u8 = 0x00;
pub const CLIP_F_XY: u8 = 0x01;
pub const CLIP_F_WHEEL: u8 = 0x02;
pub const CLIP_F_EDGES: u8 = 0x04;
pub const BTN_LEFT: u8 = 0;
pub const BTN_RIGHT: u8 = 1;
pub const BTN_MIDDLE: u8 = 2;
pub const BTN_SIDE1: u8 = 3;
pub const BTN_SIDE2: u8 = 4;
pub const BTN_COUNT: u8 = 5;
/// Clear our injected press; defer to physical state.
pub const ACT_SOFTREL: u8 = 0;
/// Force the button down regardless of physical state.
pub const ACT_PRESS: u8 = 1;
/// Force the button up, masking a physical hold.
pub const ACT_FORCEREL: u8 = 2;
/// Inter-chip link to the host chip is up.
pub const H_LINK_UP: u8 = 0x01;
/// A real mouse is attached on the host chip.
pub const H_MOUSE_ATT: u8 = 0x02;
/// The clone has been configured by the game PC.
pub const H_CLONE_CFG: u8 = 0x04;
/// Injection is currently active.
pub const H_INJECT_ON: u8 = 0x08;
/// The native-rate estimator window is full, so the `RATE` value is trustworthy (§4.2, v1.4.0).
pub const H_RATE_CONFIDENT: u8 = 0x10;
/// At least one lock is active (§4.2, v1.5.0).
pub const H_LOCK_ON: u8 = 0x20;
/// A catch subscription is active; physical-input events are streaming (§4.2, v1.6.0).
pub const H_CATCH_ON: u8 = 0x40;
/// A keyboard is attached on the host chip, cloned and injectable (§4.2, v2.0.0).
pub const H_KBD_ATT: u8 = 0x80;
/// `CATCH` class: a mouse button (§3.9). Classes 0..3 are `LOCK`'s classes unchanged.
pub const CATCH_CLS_BTN: u8 = 0;
/// `CATCH` class: a keyboard key or modifier (§3.9).
pub const CATCH_CLS_KEY: u8 = 1;
/// `CATCH` class: a media (Consumer) usage (§3.9).
pub const CATCH_CLS_MEDIA: u8 = 2;
/// `CATCH` class: a relative axis (§3.9).
pub const CATCH_CLS_AXIS: u8 = 3;
/// `CATCH` class: raw HID input report bytes, keyed by interface number (§3.9).
pub const CATCH_CLS_HID_IN: u8 = 4;
/// `CATCH` class: interrupt-OUT report bytes, keyed by endpoint address (§3.9).
pub const CATCH_CLS_HID_OUT: u8 = 5;
/// `CATCH` class: vendor-interface interrupt traffic, keyed by endpoint address (§3.9).
pub const CATCH_CLS_VEND_INTR: u8 = 6;
/// `CATCH` class: vendor-interface bulk traffic, keyed by endpoint address (§3.9).
pub const CATCH_CLS_VEND_BULK: u8 = 7;
/// `CATCH` class: a proxied control transaction, keyed by endpoint number (§3.9).
pub const CATCH_CLS_CONTROL: u8 = 8;
/// `CATCH` class: the bytes the clone emitted, keyed by interface number (§3.9).
pub const CATCH_CLS_EMIT: u8 = 9;
/// `CATCH` class: bus lifecycle events (§3.9).
pub const CATCH_CLS_BUS: u8 = 10;
/// `CATCH` class wildcard: every class (§3.9).
pub const CATCH_CLS_ANY: u8 = 0xFF;
/// `CATCH` id wildcard: every id within the class (§3.9), the same sentinel `LOCK` uses.
pub const CATCH_ID_ANY: u16 = 0xFFFF;
/// Entries the box's subscription table holds (`CATCH_TAB_MAX`). Past this the box refuses the entry
/// and says so only in `RESP(CATCH).table_full`, so a caller that never reads that flag would get a
/// silently incomplete subscription.
pub const CATCH_MAX_ENTRIES: usize = 32;
/// `TRAFFIC_EVENT.flags` for a `CATCH_CLS_CONTROL` event: what the real device answered.
pub const CATCH_CTRL_OK: u8 = 0x00;
/// The device STALLed the transfer.
pub const CATCH_CTRL_STALL: u8 = 0xFD;
/// The device NAKed to timeout, or never answered.
pub const CATCH_CTRL_NAK: u8 = 0xFE;
/// `RESP(CATCH).clk_rate_ppb` sentinel: the box has fitted no drift rate. Distinct from a fitted 0,
/// which says the two crystals are matched.
pub const CLK_RATE_NONE: i32 = i32MIN;
/// `LOCK` class byte (§3.8): momentary usages share `INJECT`'s space, plus a relative-axis class.
pub const LOCK_CLS_BTN: u8 = 0;
pub const LOCK_CLS_KEY: u8 = 1;
pub const LOCK_CLS_MEDIA: u8 = 2;
pub const LOCK_CLS_AXIS: u8 = 3;
/// `LOCK` id sentinel: the whole class (a blanket lock).
pub const LOCK_ID_ALL: u16 = 0xFFFF;
/// `LOCK` axis ids (for `LOCK_CLS_AXIS`).
pub const LOCK_AXIS_X: u16 = 0;
pub const LOCK_AXIS_Y: u16 = 1;
pub const LOCK_AXIS_WHEEL: u16 = 2;
/// `LOCK` direction byte: both / positive-or-press / negative-or-release, then the two measured
/// against the bearing rather than a fixed sign (§3.12).
pub const LOCK_DIR_BOTH: u8 = 0;
pub const LOCK_DIR_POS: u8 = 1;
pub const LOCK_DIR_NEG: u8 = 2;
pub const LOCK_DIR_WITH: u8 = 3;
pub const LOCK_DIR_AGAINST: u8 = 4;
/// `LOCK` scale byte (§3.8): percent of the physical value kept. 0 blocks, 100 passes it untouched,
/// above 100 amplifies, to a ceiling of 255 (2.55x).
pub const LOCK_SCALE_BLOCK: u8 = 0;
pub const LOCK_SCALE_PASS: u8 = 100;
pub const LOCK_SCALE_MAX: u8 = 255;
/// `CAPS` kbd_flags: keys are an NKRO bitmap (`n_keys` = 0xFF), else a keycode array (§4.4).
pub const KBC_NKRO: u8 = 0x01;
/// `CAPS` kbd_flags: a Consumer (media-key) collection is present and injectable/catchable.
pub const KBC_CONSUMER: u8 = 0x02;
/// `CAPS` kbd_flags: a System-control collection is present (passthrough-only, not injectable).
pub const KBC_SYSTEM: u8 = 0x04;
/// `CAPS` kbd_flags: the keyboard report sits behind a HID report ID.
pub const KBC_REPORT_ID: u8 = 0x08;
/// `CAPS` change_driven flag: the mouse class is change-driven (never set, mouse motion is continuous).
pub const CAPS_CD_MOUSE: u8 = 0x01;
/// `CAPS` change_driven flag: the keyboard/media class is change-driven (set when a keyboard is bound).
pub const CAPS_CD_KBD: u8 = 0x02;
/// `DEVICE_INFO` flag: the clone serves a serial string (§4.3).
pub const DI_HAS_SERIAL: u8 = 0x01;
/// `DEVICE_INFO` flag: the clone serves a BOS descriptor (§4.3).
pub const DI_HAS_BOS: u8 = 0x02;
/// `CAPS` axis flag: relative X present (§4.4).
pub const CAP_X: u8 = 0x01;
/// `CAPS` axis flag: relative Y present (§4.4).
pub const CAP_Y: u8 = 0x02;
/// `CAPS` axis flag: wheel present (§4.4).
pub const CAP_WHEEL: u8 = 0x04;
/// `CAPS` axis flag: the mouse report sits behind a HID report ID (§4.4).
pub const CAP_REPORT_ID: u8 = 0x08;
/// `RATE` flag: estimator window full (same source as [`H_RATE_CONFIDENT`], §4.5).
pub const RATE_CONFIDENT: u8 = 0x01;
/// `RATE` flag: the active input is change-driven (keyboard/media); no continuous cadence, poll floor only.
pub const RATE_CHANGE_DRIVEN: u8 = 0x02;
pub const LOG_ERROR: u8 = 0;
pub const LOG_WARN: u8 = 1;
pub const LOG_INFO: u8 = 2;
pub const LOG_DEBUG: u8 = 3;
pub const LOG_VERBOSE: u8 = 4;
/// A frame opcode (the `TYPE` byte, §3 / §4).
/// Error returned when a byte does not name a known [`FrameType`].
;