QUERYAsk the box for state

QUERY asks for one piece of state, named by its what byte. Opcode 0x05.

QUERY 0x05 · payload 1 byte (2 for OPTIONS, REWRITE_ENTRY and PATCH_ENTRY)

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu8state to read (below)
1idu8option (what = 9), rule (13) or patch (15); omitted otherwise
SELECTORS
whatReadsReply
0Firmware version.VERSION
1Box health.HEALTH
2Cloned device's USB identity, kind, and product.DEVICE_INFO
3Whole-device capabilities (mouse + keyboard).CAPS
4Native report rate.RATE
5Delivery and telemetry counters.STATS
6Active input locks.LOCKS
7Active catch subscription table, its drop counts, and the cross-chip clock estimate.CATCH
8retired; folded into CAPS-
9Persistent box option, by id.OPTIONS
10Buffered-clip ring depth, playback state, and config.CLIP
11Both chips' firmware versions, the slot each runs, and what is staged.FIRMWARE
12Rewrite-rule table summary.REWRITE
13One rewrite rule in full, in the REWRITE command's shape.REWRITE_ENTRY
14Descriptor-patch set summary.PATCHES
15One descriptor patch in full, in the PATCH command's shape.PATCH_ENTRY
16Active field-transform table.TRANSFORMS
EFFECT

The box replies with a RESP carrying the same what and the requested data. Besides QUERY, only UPDATE and TRANSFER reply. Every other command is fire-and-forget.

Library bindings: query_version, query_health, device_info, caps, query_rate, query_stats, query_locks, query_catch, query_imperfect, query_movement_riding, query_bearing, query_emit_pace, the clip status query, firmware_info, query_rewrite, query_rewrite_entry, query_patches, query_patch_entry, and query_transforms.

EXAMPLE

what = 0 (read the version):

A5SOF
05TYPE
00SEQ
01 00LEN
00what
lo hiCRC16

RESPReply from the box

RESP is the box's reply to a QUERY. Opcode 0x06.

RESP 0x06 · box → PC

Reply

PAYLOAD
OffsetFieldTypeNotes
0whatu8echoes the request's selector
1..datavarieslayout for the requested what (see selectors)
EFFECT

At most one RESP per QUERY, its SEQ matching the request's.

VERSIONRESP payload, what = 0

The RESP payload when what = 0: protocol version, firmware version, base mac, then a length-delimited ASCII name tail. The tail is additive. An older box sends it empty.

QUERY what = 0 · RESP 11-byte header + name

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x00
1proto_veru8protocol version, expected 9
2fw_majoru8firmware major
3fw_minoru8firmware minor
4fw_patchu8firmware patch
5macu8[6]the device chip's base MAC; the stable per-box id, rendered as 12 lowercase hex digits
11..nameasciihuman-readable box name, filling the rest of the payload (delimited by the frame LEN); a synthesised Medius-XXXX default when unset, set via OPTION(NAME)
EFFECT

The box also sends this unprompted at boot and on the first frame it receives, as a ready signal. The mac identifies the same box across replugs and port renumbering. Library binding: query_version.

EXAMPLE

Firmware 3.4.6, protocol 9, MAC 123456789abc, name "Loki":

A5SOF
06TYPE
00SEQ
0F 00LEN
00what
09proto
03major
04minor
06patch
......
......
12 34 56 78 9A BCmac (6 bytes)
4C 6F 6B 69"Loki"
lo hiCRC16

HEALTHRESP payload, what = 1

The RESP payload when what = 1: a two-byte flags word (u16, little-endian), each bit an independent status.

QUERY what = 1 · RESP 3 bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x01
1flagsu16status bits below, little-endian
FLAGS
BitMaskSet when
b00x01the host-chip link is up
b10x02a real mouse is attached
b20x04the PC has set up the cloned mouse
b30x08injection is active
b40x10RATE_CONFIDENT: a mouse is bound and the native-rate estimator window is full, so the RATE value is trustworthy
b50x20LOCK_ON: a LOCK scale on ≥1 input differs from a full pass (blocked or merely weighed)
b60x40CATCH_ON: the CATCH subscription table is non-empty, so events are streaming. QUERY(CATCH) reads what is subscribed
b70x80KBD_ATT: a keyboard is attached on the host chip, cloned and injectable
b80x0100REWRITE_ON: the rewrite rule table is non-empty
b90x0200PATCH_ON: the clone is serving a descriptor-patch set, as PATCHES b0
b100x0400TRANSFORM_ON: a field transform is active (the table is non-empty)
EFFECT

With the first three bits set, input reaches the PC. Library binding: query_health.

EXAMPLE

Ready, with link, mouse, and clone all up (flags = 0x0007):

A5SOF
06TYPE
00SEQ
03 00LEN
01what
07 00flags
lo hiCRC16

DEVICE_INFORESP payload, what = 2

The RESP payload when what = 2: the USB identity, kind, and product string read from the real device, otherwise invisible to the control PC. Every field is zero with nothing cloned. A clone with no HID interface reads primary_kind 0, with its identity filled in.

QUERY what = 2 · RESP 11-byte header + product

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x02
1vidu16idVendor, little-endian
3pidu16idProduct, little-endian
5bcd_deviceu16bcdDevice, the device release
7bcd_usbu16bcdUSB, e.g. 0x0200 or 0x0201
9flagsu8the bits below
10primary_kindu8cloned device kind (below), from its HID report descriptors and Boot declarations. A device carrying both kinds reads keyboard if it has a full key bitmap (unless it declares Boot for both) or declares Boot for the keyboard alone. Otherwise it reads mouse
11..productASCIIproduct string, filling the rest of the payload, with ? for each character outside ASCII. In English if the real device lists English, else in its first language. May be empty
FLAGS
BitMaskSet when
b00x01HAS_SERIAL: the clone serves a serial string
b10x02HAS_BOS: the clone serves a BOS descriptor
PRIMARY_KIND
ValueKind
0unknown: neither a mouse nor a keyboard (a clone with no HID interface reads this), or nothing cloned
1keyboard
2mouse
EFFECT

Library binding: device_info.

EXAMPLE

A Logitech G502 (046D:C08B), USB 2.01, serial and BOS served, kind mouse, product "G502":

A5SOF
06TYPE
00SEQ
0F 00LEN
02what
6D 04vid
8B C0pid
......
......
10 01bcdDev
01 02bcdUSB
03flags
02kind
47 35 30 32"G502"
lo hiCRC16

CAPSRESP payload, what = 3

The RESP payload when what = 3: one summary of the whole cloned device, mouse and keyboard, read from its HID report descriptors. Counts and yes/no flags only, never raw HID field offsets.

An INJECT for a usage the real device lacks reaches no report field. An absent class reads all-zero.

QUERY what = 3 · RESP 7 bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x03
1n_buttonsu8buttons the mouse report carries; the cap on an injectable or lockable button id
2axis_flagsu8mouse axes, the bits below
3n_hidu8cloned HID interfaces. >1 = composite. 0 with nothing cloned, or for a clone with no HID interface (a vendor-class pad); DEVICE_INFO's identity tells the two apart
4n_keysu8keycode-array slots, or 0xFF for NKRO; 0 = no keyboard
5kbd_flagsu8keyboard, the bits below
6change_drivenu8per class: b0 mouse (continuous, 0), b1 keyboard/media (change-driven, 1 when bound)
AXIS_FLAGS
BitMaskSet when
b00x01X: the report carries an X axis
b10x02Y: the report carries a Y axis
b20x04WHEEL: the report carries a wheel
b30x08REPORT_ID: the mouse report sits behind a HID report ID
b40x10PAN: the report carries an AC Pan (horizontal scroll) axis
KBD_FLAGS
BitMaskSet when
b00x01NKRO: the keyboard reports an NKRO bitmap
b10x02CONSUMER: a Consumer collection is present, so media keys are injectable
b20x04SYSTEM: a system-control collection is present (relayed only)
b30x08REPORT_ID: the keyboard report sits behind a HID report ID
EFFECT

Library binding: caps.

EXAMPLE

A 5-button mouse (X/Y/wheel, one interface) plus a 6-key Consumer keyboard (axis_flags = 0x07, kbd_flags = 0x02, keyboard change-driven):

A5SOF
06TYPE
00SEQ
07 00LEN
03what
05n_btn
07axis
01n_hid
06n_keys
02kbdfl
02chgdrv
lo hiCRC16

RATERESP payload, what = 4

The RESP payload when what = 4: how fast the active input reports, plus the poll period the clone advertises. Which field to read depends on the input kind.

Input kindCHANGE_DRIVENReadGives
continuous (moving mouse)0native_period_usHz = 1e6 / period; reads 0 until learned
change-driven (keyboard, media)1poll_period_usno steady cadence, so native_period_us is 0
QUERY what = 4 · RESP 6 bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x04
1native_period_usu16realised native period in µs; 0 = not learned, or change-driven (see flags), Hz = 1e6/period
3poll_period_usu16cloned inject-endpoint bInterval poll period in µs; the figure to read for a change-driven input
5flagsu8the bits below
FLAGS
BitMaskSet when
b00x01CONFIDENT: the estimator window is full, same source as HEALTH RATE_CONFIDENT
b10x02CHANGE_DRIVEN: the active input is event-driven (keyboard / media), so there is no continuous cadence and native_period_us is 0
EFFECT

A 1 kHz mouse reads ~1000 µs once learned. Library binding: query_rate.

EXAMPLE

A 1 kHz mouse, 1000 µs poll, estimator confident (flags = 0x01):

A5SOF
06TYPE
00SEQ
06 00LEN
04what
E8 03native
E8 03poll
01flags
lo hiCRC16

STATSRESP payload, what = 5

The RESP payload when what = 5: delivery counters, the only delivery feedback for fire-and-forget commands.

A nonzero tx_drops or tx_wedges means native input was dropped or stalled on the way to the PC. A nonzero link_rx_drops or host_rx_drops means a native report or injected delta was lost between the two chips.

relay_drops is counted apart from the native-input drop counters, so lost relayed traffic doesn't read as lost native input. The eight narrowed counters clamp at their max instead of wrapping. The three drop counts are full width.

session counts releases of host-set state. A change since the last read means some or all of it is gone and needs setting again.

Most releases drop all of it, and two drop part. Turning OPTION(IMPERFECT) off drops only rewrite rules, consuming packet triggers and queued clip transfers, unless the toggle also presents the clone again. A configuration switch by the game PC that unbinds a role (the mouse, the keyboard, the consumer control) drops only the locks, injected usages and owed motion held on that role.

QUERY what = 5 · RESP 31 bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x05
1inject_emitsu32pure-injection reports emitted, little-endian
5tx_dropsu16reports the clone's IN queue couldn't hold, never reaching the game PC; should stay 0
7tx_mergesu16backed-up reports merged instead of queued
9tx_maxdepthu8TX queue high-water mark
10tx_wedgesu8wedged-endpoint recoveries
11wakeupsu16remote wakeups the clone signalled to the game PC, for the real device or an injection
13reset_countu16USB bus resets seen
15config_countu16SET_CONFIGURATION events (re-enumerations)
17link_rx_dropsu32host-chip input frames the device chip couldn't take off the link; should stay 0
21host_rx_dropsu32the same count on the host chip, relayed over the link; should stay 0
25relay_dropsu32relayed traffic and commands that went no further, none of it native input. IN: a vendor IN packet that found its endpoint's queue full of the control PC's RAW packets, or a native zero-length packet answering a poll the PC did not make (the one poll the box runs ahead of a suspended PC). OUT: a packet the box had no room to queue, that failed three times on the real device's bus, or that a bus reset or SET_INTERFACE overtook; a RAW OUT packet with no room to wait. Other: a relayed request the box could not queue; a flagged MOVE the motion batch could not take; any frame other than native input that either chip's link receive ring dropped; a frame from the control PC its receive ring had no room for (one per frame), or an overrun of the control port's UART (one per overrun, however many frames it cost)
29sessionu16releases of host-set state; wraps at 0xFFFF, so compare for inequality
EFFECT

Library binding: query_stats.

SESSION

Host-set state: injection, locks, CATCH subscriptions, rewrite rules, transforms, the clip with its settings and triggers, and an LED override. The count is 0 at boot, announced by the ready hello. One release counts once, however many of these it clears. A release of everything counts only if a command other than QUERY or RESET arrived since the last count.

EventCounts
RESETonce
the inter-chip link dropsonce per outage
the real device detachesonce. The clone's teardown after the detach grace counts again only if a command arrived during the grace
another device attachesonce
a PATCH APPLY or CLEAR, or an OPTION(IMPERFECT) toggle, that presents the clone againonce
an update takes the clone downonce
control-PC silenceonce per silence, if it released anything
OPTION(IMPERFECT) turned offif it drops rewrite rules, consuming packet triggers or queued clip transfers. A re-clone it causes counts again
a configuration switch by the game PC that unbinds a roleif a host held a lock, an injected usage or owed motion on that role
state the box refused on arrival: a rule with the opt-in off, a patch with no device attachednot counted
a clear from the host: a whole-table REWRITE clear, a CATCH unsubscribe, CLIP_CTRL CLEARnot counted
EXAMPLE

4096 emits, every drop counter at 0, session at 2:

A5SOF
06TYPE
00SEQ
1F 00LEN
05what
00 10 00 00inject_emits
00 00drops
00 00merges
00maxdep
00wedges
00 00wakeup
00 00resets
00 00config
00 00 00 00link_rx_drops
00 00 00 00host_rx_drops
00 00 00 00relay_drops
02 00session
lo hiCRC16

LOCKSRESP payload, what = 6

The RESP payload when what = 6: native inputs currently weighed by LOCK, one entry per non-passing direction. An empty list (n = 0) means everything passes.

QUERY what = 6 · RESP 2 + 6n bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x06
1nu8number of entries that follow, ≤85
+classu8per entry: 0=button 1=key 2=media 3=axis (as LOCK)
+idu16weighed field id, or 0xFFFF for a whole-class blanket, little-endian
+directionu8direction, as LOCK
+scalei16percent of the native value kept, little-endian, -255 to 255 (as LOCK); 0 = blocked, >100 amplifies, negative reverses
READBACK

Entries mirror the LOCK frame field for field, so a readback replays as commands.

StateReports as
An axis or button weighed on a directionOne entry under its class and id, per direction.
A target passing on every directionAbsent.
A blanket button or axis lockOne entry per member, under the member's id; never 0xFFFF.
A blanket key lockOne entry per blocked edge, id = 0xFFFF, direction 1 and/or 2; never 0.
A media lock, blanket or specificDirection 0, always. Media has no edges.
A relative direction in vector modeThe effective scale, the lower of X's and Y's, on both axes.
Any momentary usagescale of 0 or 100 only. The box stores the block or pass it renders, not the number sent, and never a negative.
A reversed axisIts negative scale, sign and all. A reader that takes the field as a u8 sees 156 where the box holds -100, and takes a reversal for an amplification.
A relative direction with no bearing liveIts stored scale, unchanged. A lapsed window, or an OPTION(BEARING) window of 0, stops with and against weighing without clearing them, so an entry can report 40 while that axis passes untouched.
BUDGET
OrderSourceMax entries
1Mouse axes and buttons48: 4 axes × 4 directions, plus 16 buttons × 2 edges. A button has no relative pair, so its other two slots are out of reach.
2The blanket key lock2, one per blocked edge
3The blanket media lock1
4Specific media usages8, the whole media-lock table
5Specific keysthe rest of the 85, so ≥26, one per blocked edge

The frame is the cap: 2 + 85 x 6 is exactly the 512-byte payload. The box's tables cap rows 1-4 at 59 combined, so they always fit. Keyboard usages are the one unbounded class: 252 of them, two edges each.

Truncation only hits row 5: n stops short with nothing marking the cut. Compare the key edges requested with those returned.

EFFECT

Library binding: query_locks.

EXAMPLE

One entry: the wheel's negative (scroll-down) sign blocked (class = 3 axis, id = 2 wheel, direction = 2, scale = 0):

A5SOF
06TYPE
00SEQ
08 00LEN
06what
01n
03class
02 00id
02dir
00 00scale
lo hiCRC16

CATCHRESP payload, what = 7

The RESP payload when what = 7: the active CATCH subscription, a fixed scalar header then the table, shaped like RESP(LOCKS). An empty table means nothing is subscribed, matching the CATCH_ON health bit.

QUERY what = 7 · RESP 19 + 7n bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x07
1flagsu8b0 = the table is full and an entry was refused
2droppedu32box-wide events that could not be queued, little-endian
6clk_offset_usi32the host chip's clock minus the device chip's, measured (below), little-endian
10clk_rate_ppbi32relative drift between the two chips in parts per billion; INT32_MIN = no fit made, little-endian
14clk_delay_usu16best measured round trip; the offset's error bound is half this, little-endian
16clk_age_msu16age of the exchange the offset rests on; 0xFFFF = no estimate, little-endian
18nu8number of entries following
+classu8per entry: the address class
+idu16entry id, or 0xFFFF for a class blanket, little-endian
+diru8entry direction
+snaplenu8bytes captured per event, 0 = whole packet
+droppedu16events this entry could not queue, little-endian

The box-wide dropped counts every lost event. The per-entry one attributes them to a subscription.

CONFIRMATION

CATCH is fire-and-forget, so this reply is the only confirmation an entry landed. A refused entry is absent from the list. flags b0 marks a full 32-entry table as the reason. Library binding: query_catch.

CLOCK FIELDS

The two ESP32-S3s boot independently with unrelated timers, and events carry stamps from both (the clk byte).

The box measures the difference with a four-timestamp exchange across the inter-chip link, stamped as each frame reaches the wire rather than when it is queued.

  device chip                              host chip
      t1  ------- request -------------------> t2
                                               |
      t4  <---------------- reply ------------ t3

      offset = ((t2 - t1) + (t3 - t4)) / 2
      delay  =  (t4 - t1) - (t3 - t2)     ->  the error bound is delay / 2
FieldUse
clk_delay_usRound trip of the best exchange in the window. The offset is accurate to about half of it, a hard bound.
clk_rate_ppbExtrapolates between exchanges, since two independent crystals drift a stale offset by up to 20 µs/s. INT32_MIN means no fit yet, distinct from a fitted 0 (matched crystals).
clk_age_msAge of the exchange the offset rests on: the least-delayed one in the window, often older than the newest. 0xFFFF marks "no estimate yet", which an offset of 0 alone can't tell from a true zero.

Applying the offset is optional. The clk byte on each event stays authoritative.

EXAMPLE

One entry, every mouse button, both edges, whole packet (class = 0, id = 0xFFFF, dir = 0, snaplen = 0), with no drops and no clock estimate taken yet:

A5SOF
06TYPE
00SEQ
1A 00LEN
07what
00flags
00 00 00 00dropped
00 00 00 00clk_offset
00 00 00 00clk_rate
00 00clk_dly
FF FFclk_age
01n
00class
FF FFid
00dir
00snaplen
00 00dropped
lo hiCRC16

OPTIONSRESP payload, what = 9

The RESP payload when what = 9: one persistent box OPTION value, echoing the queried id. Values are id-specific, so each option is read separately. An unknown id gets no reply.

QUERY what = 9, id · RESP varies

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x09
1idu8option id
2..valuevariesid-specific, mirroring the matching OPTION value
IMPERFECT VALUE

The IMPERFECT opt-in (id 0) plus two derived clone-status bytes. Each is 0 or 1. A faithful clone reads all-zero.

OffsetFieldNotes
2allowedthe opt-in toggle; 1 = opted in
3over_capacitythe attached device has more IN endpoints live at once than the box has transmit FIFOs (four), has >6 HID interfaces, or runs at high speed
4clone_imperfectthe live clone is imperfect: an opted-in device the box can't clone faithfully, a forced rate, or a descriptor-patch set it serves

The value shows why a clone is missing (over_capacity = 1, allowed = 0) or confirms an imperfect clone is live (clone_imperfect = 1). Library binding: query_imperfect.

MOVE_RIDE VALUE

The current MOVE_RIDE window (id 1).

OffsetFieldNotes
2timeoutu16, little-endian; the ride window in ms, 0 = off

Library binding: query_movement_riding.

EMIT VALUE

The current EMIT pace and wire rate (id 2).

OffsetFieldNotes
2modethe pace: 0 learnt, 1 interval, 2 fixed
3fixed_hzu16, little-endian; the configured fixed rate
5resolved_hzu16, little-endian; the ceiling in effect, 0 = learnt/adaptive or no device yet, 1000 once the renderer has a profile
7force_hzu16, little-endian; the requested wire rate, 0 = off
9advertised_hzu16, little-endian; what the clone's input endpoints advertise now, forced or native, 0 = no clone
11force_active1 when a forced interval is in the served descriptor

A force_hz set while IMPERFECT is off reads back with force_active 0 and advertised_hz still the native interval.

Library binding: query_emit_pace.

BEARING VALUE

The current BEARING setting (id 4): window and geometry mode.

OffsetFieldNotes
2windowu16, little-endian; the bearing window in ms, 0 = off
4mode0 per axis, 1 vector

Library binding: query_bearing.

RENDER VALUE

The current RENDER setting (id 5), and whether a render profile has been learned.

OffsetFieldNotes
2modethe texture: 0 off, 1 stock, 2 de-spiked (default), 3 unsmoothed
3full1 when native motion is rendered by the model rather than relayed
4ready1 once a profile has armed for the attached device

Nothing is rendered while ready reads 0. It also reads 0 while the box's two chips have not yet agreed which holds the motion. Until then, motion is relayed and injection takes the paced fill, whatever mode says.

Library binding: query_render.

SPREAD VALUE

The current SPREAD setting (id 6), and the interval injected deltas are released across.

OffsetFieldNotes
2percentu16, little-endian; share of the command interval, 100 = one whole interval (default)
4span_usu32, little-endian; the interval in effect in microseconds, 0 = nothing is being spread

span_us reads 0 while percent is 0, while no command period has been learned, and while the box's two chips have not yet agreed which holds the motion. In each case the whole delta is emitted on the next report the box emits.

Library binding: query_spread.

EXAMPLE

Reading id = 0: opted in, an over-capacity device attached and cloned imperfectly:

A5SOF
06TYPE
00SEQ
05 00LEN
09what
00id
01allow
01overcap
01imperf
lo hiCRC16

CLIPRESP payload, what = 10

The RESP payload when what = 10: the buffered-clip ring depth, playback state, and full config. A fixed prefix, then the clip's held-usage snapshot (the same class-tagged list a USAGE_EVENT carries), then the config tail.

QUERY what = 10 · RESP 31-byte prefix + held usages + config

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu810
1stateu80 idle / 1 playing / 2 paused / 3 faulted (recover with CLEAR)
2freeu32ring bytes free; pace CLIP_APPEND top-ups off this, little-endian
6totalu32retained clip size in bytes (streaming: buffered-but-undrained bytes)
10playedu32bytes played from the clip start (retained progress; ~0 while streaming)
14ticksu32content ticks played (diagnostic)
18underrunsu16empty-ring episodes
20overrunsu16appends dropped whole because the ring was full
22seq_gapsu16dropped CLIP_APPEND frames detected (SEQ gaps)
24xfersu16clip transfers the real device completed with status 0
26xfer_errsu16clip transfers that completed with another status, got no answer, found no room in the queue, or were dropped behind a slow 0xFE
28gatedu16raw reports and transfers discarded because OPTION(IMPERFECT) was off
30held_nu8number of held usages that follow
+classu8per held usage: 0=button 1=key 2=media
+idu16held usage id (button id, HID keycode, or Consumer usage), little-endian
+autolocku8config: the CLIP_SET autolock bitmask (CLIP_LOCK_*)
+flagsu8config: b0 loop, b1 retain, b2 finalized, b3 ride
+n_trigu8config: number of bound triggers that follow
+classu8per trigger: 0=button 1=key 2=media 0xFF=any
+idu16per trigger: the usage id, 0xFFFF=any, little-endian
+edgeu8per trigger: 0 both / 1 press / 2 release
+actionu8per trigger: the CLIP_CTRL op 0..5 (start/stop/pause/resume/restart/toggle)
+consumeu8per trigger: 1 = lock the trigger usage while it stays active
+n_pktu8config: number of packet triggers that follow
+classu8per packet trigger: the traffic class, 4-9
+idu16per packet trigger: the class's address, 0xFFFF=any, little-endian
+diru8per packet trigger: 0 both / 1 IN / 2 OUT
+actionu8per packet trigger: the CLIP_CTRL op 0..5
+flagsu8per packet trigger: b0 clear, b1 consume, b2 RUN
+slenu8per packet trigger: the selector length
+mlenu8per packet trigger: the match length, 0-16
+hitsu16per packet trigger: packets it matched as the top-ranked trigger, saturating, little-endian
+match, masku8[mlen] eachper packet trigger: as set
FLAGS
BitMaskSet when
b00x01LOOP: playback restarts from the top on drain instead of stopping
b10x02RETAIN: the buffered content survives a stop instead of clearing
b20x04FINALIZED: the clip is sealed, no more CLIP_APPEND accepted
b30x08RIDE: the clip's motion waits to ride a native report instead of emitting on the box's clock
EFFECT

The held snapshot lists the usages the clip is currently forcing down, one class-tagged entry each (3 bytes). ticks and the six counters count since boot and wrap.

A packet trigger reads back as the command that set it with hits spliced in after mlen and bit0 (present) clear. A host replays it by setting bit0. The whole reply is ≤507 bytes, inside one frame.

Library bindings: query_status (ClipStatus) and query_config (ClipSettings).

EXAMPLE

Idle, empty 64 KB ring, no held usages, no autolock, no triggers of either kind (state = 0, free = 65536):

A5SOF
06TYPE
00SEQ
23 00LEN
0Awhat
00state
00 00 01 00free
00 00 00 00total
00 00 00 00played
00 00 00 00ticks
00 00undrun
00 00ovrrun
00 00seqgap
00 00xfers
00 00xfer_err
00 00gated
00held_n
00autolk
00flags
00n_trig
00n_pkt
lo hiCRC16

One packet trigger entry: HID_IN id 0x0102, IN, TOGGLE, consume and RUN, selector 1, hits saturated.

04 02 01 01 05 06 01 02 FF FF 07 20 FF 20
   class=4 HID_IN   id=0x0102   dir=1 IN   action=5 TOGGLE   flags=0x06   slen=1   mlen=2
   hits=65535   match=07 20   mask=FF 20

FIRMWARERESP payload, what = 11

The RESP payload when what = 11: both chips' versions, the slot each is running, and what is staged.

The only source of the host chip's version. VERSION reports the device chip alone.

Read it before an UPDATE: slot_size is the largest image a chip will take, and a chip whose state is pending-verify refuses to open one.

QUERY what = 11 · RESP 17 bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu811
1dev_majoru8
2dev_minoru8
3dev_patchu8
4dev_slotu80 = ota_0, 1 = ota_1
5dev_stateu8image state, below
6host_presentu81 when the host chip has replied over the link
7host_majoru80 when host_present is 0
8host_minoru8
9host_patchu8
10host_slotu80xFF when host_present is 0
11host_stateu8
12slot_sizeu32usable bytes in a spare slot, little-endian; the same on both chips
16stagedu8bit 0 device staged, bit 1 host staged
STATE
ValueStateMeans
0newselected but not yet booted
1pending-verifybooted, on probation: the rollback window
2validconfirmed by the image itself
3invalidthe image asked to be rolled back
4abortedbooted once and never confirmed
0xFFunknownno entry for this slot

Library binding: firmware_info.

EXAMPLE

Both chips on 3.4.6, device on ota_1, host on ota_0, both images valid, nothing staged:

A5SOF
06TYPE
01SEQ
11 00LEN
0Bwhat
03devmaj
04devmin
06devpat
01devslt
02devsta
01hostpr
03hstmaj
04hstmin
06hstpat
00hstslt
02hststa
00 00 0F 00slot_size
00staged
lo hiCRC16

REWRITERESP payload, what = 12

The RESP payload when what = 12: a REWRITE table summary, a four-byte header then twelve bytes per rule in table order.

QUERY what = 12 · RESP 4 + 12n bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x0C
1flagsu8state bits below
2genu8moves when the table changes, not on an identical re-send; see lifecycle
3nu8number of rules that follow, ≤32
+clsu8per rule: the surface, as REWRITE
+idu16class address, little-endian
+diru80 both, 1 IN, 2 OUT
+actionu8the action, 0-8
+mlenu8match length; here before off, the reverse of the command
+offu16patch offset, little-endian
+plenu16payload length, little-endian
+hitsu16packets this rule matched as the top-ranked rule, a PASS included; saturating at 65535
FLAGS
BitMaskSet when
b00x01FULL: the last add was refused for capacity (a 33rd rule, or a payload the 2048-byte pool cannot hold, an overwrite included). The next change to the table clears it: an add, an overwrite, a removal or a clear. An identical re-send is no change, so a keepalive leaves it set
EFFECT

A line carries no match, mask or payload bytes. Read those with QUERY(REWRITE_ENTRY). HEALTH sets REWRITE_ON (0x0100) while the list is non-empty.

The table is PC-owned session state on the same lifecycle as locks, so an empty list can mean the box released it. session counts that release. Library binding: query_rewrite.

EXAMPLE

One rule, DROP on EMIT endpoint 1, after 42 hits, with the table not full:

A5SOF
06TYPE
00SEQ
10 00LEN
0Cwhat
00flags
01gen
01n
09cls
01 00id
01dir
01action
00mlen
00 00off
00 00plen
2A 00hits
lo hiCRC16

REWRITE_ENTRYRESP payload, what = 13

The RESP payload when what = 13: one rule in full. The QUERY carries [13][index], where index is the rule's line in RESP(REWRITE).

QUERY what = 13 · RESP 11 + 2 x mlen + plen bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x0D
1indexu8requested index
2clsu8from here on, the REWRITE payload
3idu16little-endian
5diru80 both, 1 IN, 2 OUT
6stateu8always 1
7actionu80-8
8offu16little-endian
10mlenu80-16
11matchu8[]mlen bytes
11+mlenmasku8[]mlen bytes
11+2 x mlenpayloadu8[]the rest, plen bytes
EFFECT

Past the first two bytes it is a REWRITE payload that reinstalls the rule. An index ≥n gets no reply. Library binding: query_rewrite_entry.

EXAMPLE

Rule 0, the DROP on EMIT endpoint 1:

A5SOF
06TYPE
01SEQ
0B 00LEN
0Dwhat
00index
09cls
01 00id
01dir
01state
01action
00 00off
00mlen
lo hiCRC16

PATCHESRESP payload, what = 14

The RESP payload when what = 14: a stored PATCH set summary, a three-byte header then seven bytes per patch in set order. An overwrite moves a patch to the end.

QUERY what = 14 · RESP 3 + 7n bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x0E
1flagsu8state bits below
2nu8number of patches that follow, ≤16
+sectionu8per patch, as PATCH
+cfgu8configuration index
+indexu8interface number (REPORT) or string index (STRING)
+offsetu16little-endian
+lenu16length, little-endian
FLAGS
BitMaskSet when
b00x01APPLIED: the clone is serving a non-empty patched set
b10x02PENDING: the stored set differs from the one the clone serves (in its patches, their bytes or their order). Causes: not yet applied, changed or emptied since, refused, or stored with the opt-in off
b20x04REFUSED: the stored set failed a check at the clone's last presentation and has not changed since, so the clone serves the descriptors unpatched. The LOG line names the check. A change to the set, CLEAR, a presentation that does not refuse it, or a detach clears it
b30x08FULL: the last add was refused for capacity (a 17th patch, or bytes the 1024-byte pool cannot hold, an overwrite included). The next change to the set, or CLEAR, clears it
EFFECT

A line carries no patch bytes. Read those with QUERY(PATCH_ENTRY). HEALTH sets PATCH_ON (0x0200) while b0 is set.

The list is the stored set. The clone serves the same set while b1 is clear, and none while b0 is clear. With the real device unplugged, the list is the last attached device's set. Library binding: query_patches.

EXAMPLE

One applied patch, bcdDevice in the device descriptor (offset = 12, len = 2):

A5SOF
06TYPE
00SEQ
0A 00LEN
0Ewhat
01flags
01n
00section
00cfg
00index
0C 00offset
02 00len
lo hiCRC16

PATCH_ENTRYRESP payload, what = 15

The RESP payload when what = 15: one patch in full. The QUERY carries [15][entry], where entry is the patch's line in RESP(PATCHES).

QUERY what = 15 · RESP 7 + len bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x0F
1entryu8requested entry
2sectionu8from here on, the PATCH payload
3cfgu8configuration index
4indexu8interface number (REPORT) or string index (STRING)
5offsetu16little-endian
7bytesu8[]the rest, len bytes
EFFECT

Past the first two bytes it is a PATCH payload that restores the patch. An entry ≥n gets no reply. Library binding: query_patch_entry.

EXAMPLE

Entry 0, the bcdDevice patch setting 0x0200:

A5SOF
06TYPE
01SEQ
09 00LEN
0Fwhat
00entry
00section
00cfg
00index
0C 00offset
00 02bytes
lo hiCRC16

TRANSFORMSRESP payload, what = 16

The RESP payload when what = 16: the installed TRANSFORM table, a three-byte header then seven bytes per entry in install order.

QUERY what = 16 · RESP 3 + 7n bytes

Returns RESP

PAYLOAD
OffsetFieldTypeNotes
0whatu80x10
1flagsu8b0 = the table is full and an entry was refused
2nu8number of entries that follow, ≤32
+opu8per entry: 0 remap, 1 swap (as TRANSFORM)
+sclassu8per entry: source class, 0=button 1=key 2=media 3=axis
+sidu16source id within the class, little-endian
+dclassu8destination class
+didu16destination id, little-endian
READBACK

An entry mirrors the TRANSFORM frame field for field except the state byte, so a readback replays as commands.

StateReports as
An installed entryOne 7-byte line, under its (source, dest) key.
An entry the box refusedAbsent. TRANSFORM is fire-and-forget, so this reply is the only confirmation an entry landed.
An entry the 32-slot table turned awayAbsent, with flags b0 (full) set.
An entry whose destination this configuration doesn't declarePresent and unchanged. It is inert, not removed, and works again once the destination binds.
FLAGS
BitMaskSet when
b00x01FULL: an entry was refused because the table already held 32. Nothing is evicted, and removing any entry clears the bit
EFFECT

HEALTH sets its TRANSFORM_ON bit (0x0400) while the table is non-empty.

The table is PC-owned session state on the same lifecycle as locks and the catch subscription, so an empty list can mean the box released it. session counts that release. Library binding: query_transforms.

EXAMPLE

One entry, X and Y swapped (op = 1, source (axis 3, id 0), dest (axis 3, id 1)), with the table not full:

A5SOF
06TYPE
00SEQ
0A 00LEN
10what
00flags
01n
01op
03sclass
00 00sid
03dclass
01 00did
lo hiCRC16