Entry formatCLIP_APPEND bytes

A clip is a byte stream of variable-length entries, little-endian. The first byte of each entry is a tag: 0x00 is a gap run, any other value is a content tick's flags.

GAP RUN
OffsetFieldTypeNotes
0tagu80x00
1countu16frames the endpoint NAKs, byte-identical to an idle mouse; little-endian
CONTENT TICK

Motion, edges, raw reports and control transfers applied on one frame. flags selects which fields follow.

OffsetFieldTypePresent when
0flagsu8always; OR of the bits below, 0x40 and 0x80 reserved
+dx, dyi16 x 2flags & XY (0x01), per-frame cursor delta
+wheeli16flags & WHEEL (0x02), per-frame delta
+pani16flags & PAN (0x08), per-frame delta
+nu8flags & EDGES (0x04), edge count (1-8)
+edgesn x 4 byteseach edge is [class u8][id u16][action u8]
+nu8flags & RAW (0x10), raw item count (1-8)
+rawn itemseach a raw item
+nu8flags & XFER (0x20), transfer item count (≥1)
+xfern itemseach a transfer item

The fields follow in the table's order. An entry is ≤512 bytes, one CLIP_APPEND payload.

An invalid entry (a reserved bit, a count out of range, a length >512 bytes) faults the clip when playback reaches it.

EDGES

An edge reuses INJECT's tuple, so one clip drives every input class.

CLASS
NameValueid is
button0a button id (0=Left .. 4=Side2)
key1a HID keycode (0xE0-0xE7 = modifier)
media2a 16-bit Consumer usage
ActionValueEffect
soft-release0Drop the override. A hold on the real device stays active.
press1Force the usage active.
force-release2Force the usage inactive, masking a hold on the real device too.

An edge is a level: it holds until a later tick changes it, and the box NAKs while the level is unchanged.

COMBINED TICK

Several flag bits stack their fields in one tick: a move, a pan and a press on the same frame, in one report.

0D 0A 00 FC FF 02 00 01 00 00 00 01
   flags=XY|PAN|EDGES   dx=+10 dy=-4   pan=+2   n=1   edge[class=0 button, id=0 Left, action=1 press]
PLAYBACK ORDER
FrameEntryClone emits
0motioncursor moves
1Left pressleft button down
2-4gap 3nothing emitted (NAK); left stays down
5Left releaseleft button up
6motioncursor moves
7key A pressA down
EXAMPLE ENTRIES

Move up-right, press A, idle 5 frames.

01 0A 00 F6 FF        flags=XY,   dx=+10  dy=-10
04 01 01 04 00 01     flags=EDGES n=1  edge[class=1 key, id=0x04 'A', action=1 press]
00 05 00              tag=gap,    count=5  (NAK 5 frames)

Raw and transfer itemsRaw reports and control transfers on a content tick

A raw item is RAW's payload with its length, and a transfer item is TRANSFER's payload. Both need OPTION(IMPERFECT), checked as the tick plays. With the opt-in off, the item is discarded and counted in gated.

RAW ITEM
OffsetFieldTypeNotes
0ep_numu8cloned endpoint number
1diru81 = IN, onto cloned IN endpoint ep_num; 2 = OUT, relayed to the real device
2lenu16length of bytes, little-endian
4bytesu8[]report, verbatim; sent in entry order, ahead of the tick's report
TRANSFER ITEM
OffsetFieldTypeNotes
0epu80 = EP0, or a control endpoint the real device declares
1setupu8[8]setup packet
9datau8[]OUT data: wLength bytes when bit 7 of the first setup byte (the request type) is clear, absent when it is set

The box queues transfers (1 KiB) and runs them one at a time. Each result arrives as a CLIP_XFER event, in drain order.

TRANSFER QUEUE
EventEffect
PAUSE, the natural endstill run
STOP, RESTART, CLEAR, a fault, a hard stopdropped
a 0xFE (no answer) status that took ≥250 msthose behind it dropped into xfer_errs
OPTION(IMPERFECT) turned offdropped, each counted in gated
NATIVE STATE
ReportOn release
a raw IN item on the mouse, keyboard or media report the box injects intoemitted once in its native state, if that differs from the raw bytes outside the relative fields
a raw IN item on any other reportstays as sent, as after a RAW command

The clip releases its held input on STOP, its natural end, a loop wrap, RESTART, CLEAR, a fault and a hard stop. A native report or a later raw report emitted first replaces the raw bytes.

EXAMPLE ENTRIES

One raw report OUT on endpoint 2, then a SET_REPORT with two bytes of OUT data on EP0.

10 01 02 02 03 00 A1 B2 C3
   flags=RAW   n=1   item[ep_num=2, dir=2 OUT, len=3, bytes=A1 B2 C3]
20 01 00 21 09 00 03 00 00 02 00 04 01
   flags=XFER  n=1   item[ep=0, setup=21 09 00 03 00 00 02 00 (wLength=2), data=04 01]

CLIP_APPENDFill the ring

Appends whole entries to the ring's tail: while stopped to preload, or while playing (streaming mode) to top up. Opcode 0x12.

CLIP_APPEND 0x12 · payload = one or more whole entries

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0entriesbytesa whole number of entries, back to back (up to the 512-byte frame limit)
DROP DETECTION

The frame SEQ doubles as an append sequence number: the box expects each CLIP_APPEND to be the previous SEQ plus one.

The link is fire-and-forget, so a lost frame shows as a SEQ gap. The box then marks the clip faulted in QUERY(CLIP). Recover with CLEAR, then rebuild.

Pack whole entries per frame. Never split one entry across two appends.

FLOW CONTROL

An append that doesn't fit the ring is dropped whole and faults the clip, never written as a partial entry.

Keep an append under QUERY(CLIP)'s free bytes. In streaming mode the head drains while the host appends to the tail, so free recovers as it plays. The ring is 64 KB with PSRAM and 16 KB without. Never assume a size.

  the ring, read by QUERY(CLIP):

       free                        buffered (total)
  +----------------+----------------------------------------+
  |    (append     | [e5][e6][e7][e8][e9] ...               | --> drained
  |    here, <=    |     buffered, not yet played           |     1 / frame
  |    free)       |                                        |
  +----------------+----------------------------------------+
   append > free  -->  dropped whole + clip faulted

Library binding: ClipBuilder + append, which splits a large clip into whole-entry frames.

EXAMPLE

Append one content tick, cursor dx = 10 (a 5-byte entry, so LEN = 5):

A5SOF
12TYPE
00SEQ
05 00LEN
01flags
0A 00dx
00 00dy
lo hiCRC16

SEQ is the append sequence. flags, dx and dy are the one XY content tick.

CLIP_CTRLDrive the playback engine

One byte of op selects an engine verb. Settings live on CLIP_SET. Opcode 0x13.

CLIP_CTRL 0x13 · payload [op u8]

Fire-and-forget

PAYLOAD
opNameEffect
0STARTplay from the ring head, applying the autolock setting
1STOPhalt playback and release the clip's auto-lock; buffered entries survive in retained mode
2PAUSEfreeze the playhead; held levels stay down, motion stops
3RESUMEcontinue a paused clip
4RESTARTplay from the head (retained clip)
5TOGGLEstart if stopped, stop if playing
6CLEARstop and empty the ring, dropping every buffered entry and clearing a fault
7FINALIZEmark the buffered clip complete; the box stops treating an emptied ring as an underrun

Ops 0-5 (START through TOGGLE) double as the action byte a CLIP_TRIGGER fires on a native edge or a matched packet. CLEAR and FINALIZE are host-only.

STATE

QUERY(CLIP) reports one of four states.

ValueStateMeans
0idlenot playing; ring may hold a retained clip
1playingdraining one entry per frame
2pausedfrozen mid-clip by PAUSE, holding its levels
3faulteda SEQ gap, an overflow or an invalid entry broke the stream; CLEAR and rebuild
UNDERRUN

In streaming mode, if the ring drains with no FINALIZE, the box idles (NAKs, holding its levels) and stays playing until refilled. A topping-up host or any keepalive resets the 1 s silence timer.

A finalized clip ends when the ring empties, or replays from the head if loop is set.

STOPS ON
STOP        an explicit STOP or CLEAR op
silence     a full 1 s of control-PC silence
RESET       a RESET command
detach      the real device unplugs
link loss   the inter-chip link drops
re-clone    the box clones a device again

Each halts playback and releases the clip's lock. A hard stop (silence, RESET, detach, link loss, re-clone) also clears the ring, settings and trigger set, which a host reloads.

A hard stop moves the session count.

Library binding: Device::clip().

EXAMPLE

Start playback (op = 0, a single-byte payload so LEN = 1):

A5SOF
13TYPE
00SEQ
01 00LEN
00op
lo hiCRC16

CLIP_SETSet a clip setting

Sets one clip setting, OPTION-shaped. A setting holds until changed or cleared by a hard stop. QUERY(CLIP) reads them all back. Opcode 0x14.

CLIP_SET 0x14 · payload [id u8][value u8]

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0idu8setting (table below)
1valueu8new value
SETTINGS
idSettingvalueEffect
0autolockclass bitmaskthe native-input classes START locks while playing (below)
1loop0 / 1a finalized clip replays from the head instead of ending
2retain0 / 1keep entries after playing so START / RESTART can replay them
3ride0 / 1the clip's motion waits to ride a native report; 0 (the default) plays it on the box's clock (below)
AUTO-LOCK

autolock locks are clip-owned and released on STOP. A host LOCK is untouched. 0 = no auto-lock; 0x1F = every class.

BitMaskLocks
b00x01the X and Y cursor axes
b10x02the wheel and pan
b20x04every mouse button
b30x08every keyboard key
b40x10every media usage
RIDE

A clip's motion bypasses movement riding by default, so it plays on the box's clock. ride puts it back on the ride: additive to native motion, and dropped while the mouse is still.

While rendering is on with a profile armed, a clip's cursor motion is rendered like a MOVE with no flag and rides the same way. ride then applies to the wheel and pan alone. Edges stay on the clip tick, ahead of the rendered motion.

Library binding: set_autolock, set_loop, set_retain, set_ride.

EXAMPLE

Turn looping on (id = 1, value = 1, so LEN = 2):

A5SOF
14TYPE
00SEQ
02 00LEN
01id
01value
lo hiCRC16

CLIP_TRIGGERBind a native edge or a matched packet to an engine verb

Fires a CLIP_CTRL verb on the box from a native edge (as CATCH reports it) or a matched packet, with no host round-trip, so even the first emitted report is box-timed.

Triggers are a LOCK-shaped managed set. The class byte picks the kind. An input class makes one of up to 8 bindings, keyed by (class, id, edge). A traffic class makes one of up to 8 packet triggers. Opcode 0x15.

CLIP_TRIGGER 0x15 · payload [class u8][id u16][edge u8][action u8][flags u8]

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0classu8input class (below)
1idu16usage within the class, little-endian; 0xFFFF = any
3edgeu8firing edge (below)
4actionu8the CLIP_CTRL op to fire, 0-5
5flagsu8bit0 present, bit1 consume (below)
CLASS
NameValueid is
button0a button id
key1a HID keycode
media2a Consumer usage
any0xFFignored (any input fires)
EdgeValueFires on
both0press and release
press1the native press
release2the native release
FLAGS
BitMaskEffect
b00x01present: set to add or replace the binding, clear to remove it
b10x02consume: lock the trigger usage while it stays active. Press edge only: a release-edge binding stores the flag and never acts on it
KINDS
  class 0..2, 0xFF                          class 4..9
  a native edge                             a packet on a traffic surface
  button, key, media                        HID_IN, HID_OUT, VEND_INTR, VEND_BULK, CONTROL, EMIT
          |                                         |
          v                                         v
  [ 8 input bindings ]                      [ 8 packet triggers ]
    key (class, id, edge)                     key (class, id, dir, mlen, match, mask)
    the most specific acts on the edge        the most specific acts on the packet
          |                                         |
          +------------> one CLIP_CTRL op <---------+
                         0 START .. 5 TOGGLE, run on the box

Re-sending the same (class, id, edge) key replaces that binding. Clearing present removes it.

The clear-all sentinel wipes the whole set, input bindings and packet triggers alike: class = 0xFF, id = 0xFFFF, edge = 0 (both), flags = 0.

Preload the ring (and FINALIZE it for a replayable macro) before binding.

Library binding: bind, unbind, clear_triggers.

EXAMPLE

Bind the A key's press to START (class = 1, id = 0x04, edge = 1 press, action = 0 start, flags = 0x01 present):

A5SOF
15TYPE
00SEQ
06 00LEN
01class
04 00id
01edge
00action
01flags
lo hiCRC16

Packet triggersCLIP_TRIGGER with a traffic class

A traffic class in the class byte makes a packet trigger. A packet on that surface whose head matches runs the verb, as an input edge does. The match follows the six bytes every binding has. Opcode 0x15.

CLIP_TRIGGER 0x15 · packet payload 8 + 2 x mlen bytes

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0classu8traffic class, 4-9 (below)
1idu16class address as in CATCH, little-endian; 0xFFFF = any
3diru8packet direction: 0 both, 1 IN, 2 OUT
4actionu8the CLIP_CTRL op to fire, 0-5
5flagsu8bit0 present, bit1 consume, bit2 RUN (below)
6slenu8selector length: below mlen with RUN, 0 without
7mlenu8match length, 0-16; 0 takes every packet on the address
8matchu8[]mlen head bytes to compare
8+mlenmasku8[]mlen mask bytes: a packet matches when each head byte ANDed with its mask byte equals the match byte; bytes past the mask are ignored
SURFACES
ClassValueCarriesHead
HID_IN4INthe native report as it arrived, ahead of any rewrite
HID_OUT5OUTa report the PC writes to the real device
VEND_INTR6IN, OUTa relayed vendor interrupt packet
VEND_BULK7IN, OUTa relayed vendor bulk packet
CONTROL8IN, OUTa control request: the 8 setup bytes, then the first 8 OUT data bytes
EMIT9INan emitted report, the clip's frames included; a clip's raw items pass unmatched
FLAGS
BitMaskEffect
b00x01present: set to add or replace the trigger, clear to remove it
b10x02consume: drop every packet the trigger is the most specific match for, as a DROP rewrite rule would, before a rule sees it
b20x04RUN: run the verb on the first of a run of matching packets. Without RUN, a trigger runs the verb on every packet it is the most specific match for

The key is (class, id, dir, mlen, match, mask). The same key overwrites, and the same key with present clear removes. The box holds 8 packet triggers beside the 8 bindings, with 112 match bytes between them.

PACKET PATH
  packet at a surface
        |
        v
  [ packet triggers ]   read the bytes as they arrived; only the most specific one acts
        |     |
        |     +--> the top-ranked trigger's verb, run on the frame clock's next tick
        |     +--> consume: the packet stops here
        v
  [ rewrite table ]     sees the packet next, and applies the top-ranked rule
        |
        v
  delivered             to the game PC (IN) or the real device (OUT)
RULES
NameBehaviour
surfacesA trigger sees a packet at every surface a rewrite rule does, ahead of it. The two are independent: one packet can run a verb and then match a rule.
rankOnly the most specific trigger a packet matches acts on it, ranked in the rewrite table's order: an exact id over 0xFFFF, more masked bits over fewer, a named dir over both, then the earlier one. One verb runs per packet.
tickThe verb runs on the frame clock's next tick, within one frame of the matching packet (1 ms at the default pace). A verb that starts the clip plays its first entry on that tick.
consumeA consumed HID_IN report is the whole report, so a release edge in it is emitted with the next report. Consuming needs OPTION(IMPERFECT). Turning the opt-in off removes the consuming triggers. A trigger that only watches works with the opt-in off.
catchCATCH reports a consumed HID_IN or OUT packet, whose taps sit ahead of the triggers. A consumed vendor IN packet or emitted report goes unreported.
runWith RUN, a device that repeats a held state every poll fires once per hold. The release is a second trigger matching the released bytes. The first slen match bytes select the stream within the address (a report ID) and the rest are the condition. A packet that fails the selector leaves the run as it was.
first packetA run starts on the first matching packet the trigger sees. A trigger whose condition already holds when it is set fires on the next packet. A trigger matching the at-rest bytes of a device that reports every poll therefore fires once, when it is set.
shadowedA trigger a more specific one outranks still tracks its run, so removing that trigger mid-hold fires nothing.
re-sendAn identical re-send keeps the run and the count. An overwrite starts both again, and a bus reset or a configuration change starts every run again.
hitsEach trigger counts the packets it matched as the top-ranked trigger, saturating at 65535, read back in QUERY(CLIP). An outranked trigger's count stays still while it tracks its run.
lifetimePacket triggers are clip config: soft state, cleared with the rest of it on a hard stop.
REFUSED

A refused frame is dropped whole, with no reply, and leaves the set unchanged: a new key isn't added and an existing key keeps its trigger. Compare what QUERY(CLIP) reads back with what was sent.

FrameWhy
shorter than 8 + 2 x mlen, mlen >16, dir >2, action >5, a reserved flag bitMalformed.
a ninth trigger, or match bytes past the pool of 112The set is full.
consume with OPTION(IMPERFECT) offConsuming is dropping traffic.
consume on CONTROLA control transfer always runs to completion.
RUN on CONTROL, with id = 0xFFFF, or with dir = 0A run is over one stream: a report class, a concrete id and a concrete dir.
RUN with slen at or above mlen, or slen above 0 without RUNThe bytes past the selector are the condition.
RUN whose condition bytes have no masked bitEvery packet of the stream would meet it, so the run would never end.
a match bit outside its maskNo packet can match it.
dir = 2 on HID_IN or EMIT, dir = 1 on HID_OUTThe class never carries that direction.
EFFECT

No reply. Library binding: bind_packet, unbind_packet, clear_triggers.

EXAMPLE

Bind HID_IN interface 2, IN, to START, with consume and RUN (flags = 0x07): report ID 0x07 is the selector (slen = 1) and bit 5 of the next byte is the condition, so LEN = 12.

A5SOF
15TYPE
00SEQ
0C 00LEN
04class
02 00id
01dir
00action
07flags
01slen
02mlen
07 20match
FF 20mask
lo hiCRC16

To remove the same trigger, keep the key and zero action, flags and slen.

04 02 00 01 00 00 00 02 07 20 FF 20
   class=4 HID_IN   id=2   dir=1 IN   action=0   flags=0   slen=0   mlen=2   match=07 20   mask=FF 20