Medius - Native APIPatch

Patch

Overwrite bytes in the clone's descriptors

PATCH stores byte overwrites for the descriptors the clone serves at enumeration. The set persists in NVS under the device's VID:PID, and the clone serves the copy taken at its last presentation.

  real device --USB3--> HOST chip
                            |
                            |  snapshot of every descriptor
                            v
  NVS, per VID:PID ---> DEVICE chip    copy the stored set, overwrite in place
  [ stored set ]            |
                            |  clone checks, consistency checks
                            v
  game PC <---USB1----- the clone      patched, or unpatched when a check fails
ActionValueEffect
store0 to 4add, overwrite or remove one patch in the stored set
APPLY0xFEpresent the clone again with the stored set
CLEAR0xFFerase the set; a clone serving patches is presented again without them

The value is the first payload byte. Read the set back with QUERY(PATCHES) and one patch in full with QUERY(PATCH_ENTRY).

A stored set reaches the game PC only under OPTION(IMPERFECT); see the gate.

PATCH

Store, overwrite, or remove one patch

A patch names a descriptor, an offset into it, and the bytes to write there. Opcode 0x1D.

PATCH 0x1D · payload 5 + n bytes

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0sectionu8descriptor (table below)
1cfgu8configuration's position in capture order, 0 first
2indexu8interface number for REPORT, string index for STRING
3offsetu16first byte overwritten, counted from the descriptor's first byte; little-endian
5bytesu8[]overwrite, 0 to 505 bytes, delimited by the frame LEN
SECTION
ValueNameEffect
0DEVICEthe 18-byte device descriptor; cfg and index ignored
1CONFIGconfiguration cfg, every byte of its wTotalLength; index ignored
2REPORTthe HID report descriptor of interface index in configuration cfg
3STRINGstring index, replaced whole; cfg and offset ignored
4BOSthe BOS descriptor; cfg and index ignored
KEY

A patch is stored under (section, cfg, index, offset) exactly as sent, ignored fields included, so send 0 in those.

SentEffect
bytes at a new keyappended to the set
other bytes at a stored keyreplaced and moved to the end of the set
the bytes already stored at that keyno change: the patch keeps its place and NVS is untouched
zero bytes at a stored keyremoved
REFUSALS
Refused whenWhy
no device attachedthe set is keyed on the attached device; a device the box refuses to clone still counts as attached
store payload under 5 bytesthe first five are the address
section is 5 to 0xFDfive descriptor kinds, then APPLY and CLEAR
bytes longer than 505the patch must fit its RESP(PATCH_ENTRY) read-back in one frame
a 17th key16 patches per device; RESP(PATCHES) sets FULL
the set's bytes would pass 1024one pool holds every patch's bytes; FULL is set, and an overwrite that does not fit leaves the old patch in place
zero bytes at an unstored keynothing to remove
EFFECT

A change is written to NVS at once and reaches the game PC at the clone's next presentation. A refused frame has no reply: read RESP(PATCHES) for the patch, or for FULL.

EXAMPLE

Set bcdDevice to 0x0200: section DEVICE, offset = 12, bytes 00 02:

+--------+--------+--------+--------+--------+--------+
| A5     | 1D     | 00     | 07 00  | 00     | 00     |
+--------+--------+--------+--------+--------+--------+
| SOF    | TYPE   | SEQ    | LEN    | section| cfg    |
+--------+--------+--------+--------+--------+--------+

+--------+--------+--------+--------+
| 00     | 0C 00  | 00 02  | lo hi  |
+--------+--------+--------+--------+
| index  | offset | bytes  | CRC16  |
+--------+--------+--------+--------+

Library binding: set_patch.

APPLY

Present the clone again with the stored set

APPLY is a PATCH frame with section 0xFE; the rest of the payload is ignored.

PATCH 0x1D · payload 1 byte

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0sectionu80xFE
EFFECT

When the stored set differs from the one the clone serves, the box presents the clone again with a copy of the stored set and runs the checks. An emptied set presents it unpatched.

REFUSALS
Refused whenWhy
the stored set is the one the clone servesit would change nothing and cost the game PC a re-enumeration
the stored set failed a check at its last presentation and is unchanged sinceit would fail the same way; PATCHES b2 is set
OPTION(IMPERFECT) offthe clone serves no patches without the opt-in
no device attachedthe box rebuilds the clone from the snapshot taken at attach
EXAMPLE

Present the stored set:

+--------+--------+--------+--------+--------+--------+
| A5     | 1D     | 01     | 01 00  | FE     | lo hi  |
+--------+--------+--------+--------+--------+--------+
| SOF    | TYPE   | SEQ    | LEN    | section| CRC16  |
+--------+--------+--------+--------+--------+--------+

Library binding: apply_patch.

CLEAR

Erase the set and present the clone without it

CLEAR is a PATCH frame with section 0xFF. It runs with the opt-in off and with the device unplugged.

PATCH 0x1D · payload 1 byte

Fire-and-forget

PAYLOAD
OffsetFieldTypeNotes
0sectionu80xFF
EFFECT
StateEffect
the clone serves patchesthe set and its NVS key are erased, and the clone is presented again unpatched, as APPLY presents it
the clone serves nonethe set and its NVS key are erased; the clone is unchanged

Either way RESP(PATCHES) then reads with REFUSED and FULL clear. With the device unplugged, CLEAR erases the key of the last device attached since boot, or nothing after a boot with none attached.

EXAMPLE

Erase the set:

+--------+--------+--------+--------+--------+--------+
| A5     | 1D     | 02     | 01 00  | FF     | lo hi  |
+--------+--------+--------+--------+--------+--------+
| SOF    | TYPE   | SEQ    | LEN    | section| CRC16  |
+--------+--------+--------+--------+--------+--------+

Library binding: clear_patch.

Presentation

When the stored set reaches the game PC

The clone serves the set it was last presented with, every section included. A presentation copies the stored set, runs the checks and re-enumerates the clone on the game PC.

  PATCH   --> stored set        NVS, read back by QUERY(PATCHES)
                  |
                  |  presentation: attach, APPLY, CLEAR, opt-in toggle
                  v
              served set        what the game PC reads at enumeration
EventPresents whenServes
the device attachesalwaysthe stored set, under the opt-in
APPLYthe stored set differs from the served onethe stored set, or none when it is empty
CLEARthe clone serves patchesnone
the opt-in turned onthe stored set differs from the served one and is not refusedthe stored set
the opt-in turned offthe clone serves patchesnone

RESP(PATCHES) lists the stored set; its flags say whether the clone serves it.

A presentation re-clones the device, as a replug does. It releases injection, locks, transforms, rewrite rules, the loaded clip and its triggers, and the CATCH table. The release moves the session count.

Sections

Per-section behaviour

A patch writes over bytes the descriptor already has, except STRING, which replaces the string. One that would run past the descriptor's end is skipped whole, never truncated.

  device descriptor   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11
  offset 12, 2 bytes                                      xx xx                  lands
  offset 17, 2 bytes                                                     xx xx   past the end: skipped
NameBehaviour
DEVICEWrites the served identity, which QUERY(DEVICE_INFO) then reports. The set and every learned setting stay keyed on the real VID:PID. Byte 17, bNumConfigurations, is set to the captured configuration count after the patch lands.
CONFIGWrites the served configuration, which the box then parses for its interfaces and endpoints, so a patched endpoint faces the same clone checks a native one does.
REPORTWrites the report descriptor before the box parses it, so INJECT, LOCK and the emitted report follow the patched layout.
STRINGServes the bytes as the whole string, any length up to 127, one UTF-16 code unit per byte; a 0x00 byte ends it. Index 0, the language list, is not patched.
BOSWrites the BOS descriptor, on a device that has one.

With two STRING patches on one index, the one listed first in RESP(PATCHES) is served. An overwrite moves a patch to the end of that list.

A CONFIG patch to bInterval is served as written, while the box keeps polling the device at the rate OPTION(EMIT) forces.

Checks

What a patched clone must pass

A set that fails a check the device passes without it is refused: the clone is presented unpatched and one LOG line names the check. A device that fails without the set is refused as any device is.

  patched descriptors
        |
        +-- the clone checks every device faces
        +-- framing: length and type fields
        +-- bcdUSB against BOS
        +-- wDescriptorLength against the report descriptor, every configuration
        +-- wMaxPacketSize against the report, the configuration in force
        |
        +-- all hold   -->  clone served patched, PATCHES b0, HEALTH PATCH_ON
        +-- one fails  -->  clone served unpatched, PATCHES b1 + b2, one LOG line
CHECKS
Refused whenWhy
a clone check fails, such as an endpoint wMaxPacketSize above 64the patched descriptors face the checks every device does
a patch changes the device descriptor's bLength or bDescriptorType, or a configuration's or the BOS's bLength, bDescriptorType or wTotalLengththe box serves these as written: a larger length reads the host past the descriptor, a smaller one hides its tail
bcdUSB 0x0201 or above with no BOSa host requests the BOS of any 2.01 device
a HID descriptor's wDescriptorLength differs from its served report descriptor, in any configurationthe game PC would ask for one length and get another
an interrupt-IN endpoint of a HID interface, in the configuration in force, has a wMaxPacketSize below that interface's reportthe report would not fit the packet the endpoint advertises
REFUSED SET

The set stays stored with PATCHES b2 set until it changes, and APPLY skips it until then. Change or remove the failing patch and APPLY, or CLEAR the set.

Opt-in gate

Stored always, presented under the opt-in

OPTION(IMPERFECT) gates whether the stored set reaches the clone.

ItemOpt-in off
PATCHstored and written to NVS
APPLYignored
CLEARruns
a clone of the devicepresented unpatched, with PATCHES b1 set while a set is stored
TOGGLE

A toggle presents the clone again when that changes the set it serves. When the clone needs the opt-in for anything else, the device chip reboots and re-clones, as the option describes.

WHILE APPLIED

While the clone serves a patched set, HEALTH sets PATCH_ON (0x0200) and QUERY(OPTIONS, 0) reports clone_imperfect = 1. A refused set sets neither.

Lifecycle

Stored configuration

A set is stored per device, loaded when that device attaches, and kept until a removal, a CLEAR, or a RESET with the NVS flag erases it.

ERASED BY
remove      a PATCH with zero bytes at the patch's key
CLEAR       a PATCH with section 0xFF: the whole set
RESET       a RESET carrying the NVS flag: the whole store
EventEffect
the device detachesthe clone, PATCH_ON and REFUSED go; the set stays stored and readable until another device attaches
another device attachesthat device's set loads in its place, cloned or refused