Frame
DE AD | LEN:u16 | CMD:u8 | PAYLOAD[LEN]
LEN is the payload length and does not include CMD. Requests with no payload use LEN=0.
Exception — legacy baud frames 0xA5 / 0xA4. The V3 AIO set-baud frame is DE AD 05 00 A5 <baud:u32 LE>, whose LEN=5 follows the older V3 convention that counts the command byte, not this document's rule. From V4.039 the firmware reads the 0xA5 / 0xA4 fixed payload regardless of the declared LEN, so the AIO frame works. Before V4.039 the mismatch made it unusable: V4.032 / V4.035 have no handler (FF); V4.030 and V4.036–V4.038 have a handler that requires a 4-byte payload, so the 5-byte frame is rejected (FF) and consumes the first byte of the next command (tk-0454). See the legacy baud entries below.
There is no GET/SET field. CMD and the exact payload shape select the operation. Do not treat every empty payload as GET: for example, empty KEY_INIT is SET, while INPUT_STREAM GET carries kind:u8. The Operation column below defines each valid form.
Successful GET replies use the same frame:
DE AD | LEN:u16 | CMD:u8 | RESULT[LEN]
SET operations do not reply when accepted. A rejected GET or SET returns DE AD | 01 00 | CMD | FF. No success-status byte is used.
COM and plaintext UDP carry the complete frame. Raw UDP prepends its transaction header before the frame. Ethernet and Wi-Fi use the same UDP payload, including when the selected interface is VLAN tagged.
BLE carries CMD + PAYLOAD; ATT supplies the length. SDKs automatically combine commands that are already queued, use the negotiated write size, and restore individual replies in request order. A lone command is sent immediately. Applications use the normal MAK_API calls and do not select a batch size or enable a batching mode.
AES-128 transport encryption is available on MAKXD COM and UDP; MAKCU uses plaintext COM and supports encrypted UDP. Encryption wraps the command record and authenticates replies with the request nonce. BLE uses BLE link security and does not accept a MAKXD AES key.
Connect and learn
Connect by issuing DEVICE once and cache its result for the connection. Typed commands use this cached information; they do not query the device before each call.
| Operation | Command | Value | Payload | Returned data |
|---|
| GET | DEVICE | 0x02 | empty | kinds:u8 |
| GET | FIRMWARE_VERSION | 0x04 | empty | version:u32 |
FIRMWARE_VERSION returns the installed application firmware version.
kinds is a bitmask. Multiple device kinds are ORed together. It reports the active routed kinds, including saved mouse/keyboard injection assignments and linked-device kinds. Reconnect after changing routes to refresh an SDK's cached result.
| Device kind | Bit |
|---|
| mouse | 0x01 |
| keyboard | 0x02 |
| generic HID controller | 0x04 |
| DS4 | 0x08 |
| DualSense / DS5 | 0x10 |
| DualSense Edge | 0x20 |
| Xbox GIP | 0x40 |
| Xbox 360 / XInput | 0x80 |
Stability promise
A host bridge and long-lived integrations may rely on these staying compatible: the connect/version query (0x09, and 0x01 on the KM text port), the firmware version reply (0x04), the interface/capability query (0x02), and the change- stream control and event framing (0x52 / 0x53, the DE AD .. 53 record). Their request and reply payloads are fixed. Every other opcode documented here keeps its payload layout across releases; new behaviour is added as new opcodes (for example 0x55 / 0x56 in V4.036), not by changing an existing one. The reserved 0x34–0x36 signal-analysis family is the only range that may still change.
Timing
Mouse, keyboard, and controller commands do not accept caller-supplied dt. Use the exact argument counts and payload lengths below. A legacy DT argument or two-byte trailer is rejected, including an explicit zero.
Keyboard press durations (hold_ms and random_range) remain in milliseconds. The polling intervals returned by km.device() use USB microframes. Change events contain only kind, control ID, and value.
Mouse
| Operation | Command | Value | Payload | Returned data |
|---|
| GET | BUTTONS | 0x10 | empty | enabled:u8 |
| SET | BUTTONS | 0x10 | enabled:u8 | none |
| GET | LEFT | 0x11 | empty | state:u8 |
| GET | RIGHT | 0x12 | empty | state:u8 |
| GET | MIDDLE | 0x13 | empty | state:u8 |
| GET | SIDE1 | 0x14 | empty | state:u8 |
| GET | SIDE2 | 0x15 | empty | state:u8 |
| SET | LEFT..SIDE2 | 0x11..0x15 | state:u8 | none |
| SET | MOVE_MASK | 0x16 | left:u8 right:u8 down:u8 up:u8 | none |
| SET | WHEEL_MASK | 0x17 | down:u8 up:u8 | none |
| SET | MOVE | 0x18 | x:i16 y:i16 | none |
| SET | WHEEL | 0x19 | delta:i16 | none |
| SET | LEFT_MASK | 0x1A | enabled:u8 | none |
| SET | RIGHT_MASK | 0x1B | enabled:u8 | none |
| SET | MIDDLE_MASK | 0x1C | enabled:u8 | none |
| SET | SIDE1_MASK | 0x1D | enabled:u8 | none |
| SET | SIDE2_MASK | 0x1E | enabled:u8 | none |
| GET | INTERPOLATE | 0x1F | empty | spread:u8 |
| SET | INTERPOLATE | 0x1F | spread:u8 | echo spread:u8 |
| GET | LOCK | 0x60 | target:u8 | state:u8 |
| SET | LOCK | 0x60 | target:u8 state:u8 | none |
| SET | CLICK | 0x61 | button:u8 [count:u8 [hold_ms:u16]] | none |
| SET | MOVETO | 0x62 | x:u16 y:u16 | none |
| GET | GETPOS | 0x63 | empty | x:u16 y:u16 |
| GET | SCREEN | 0x64 | empty | width:u16 height:u16 |
| SET | SCREEN | 0x64 | width:u16 height:u16 | none |
| SET | SILENT | 0x65 | x:u16 y:u16 | none |
| GET | MOVING | 0x66 | empty | moving:u8 |
| SET | MOVE_NOW | 0x67 | x:i16 y:i16 | none |
| SET | FLICK | 0x68 | dx:i16 dy:i16 back:u8 [button:u8] | none |
| GET | PHYS_BUTTONS | 0x55 | empty | mask:u8 |
| GET | INJECT_SNAPSHOT | 0x56 | empty | 40 bytes, see below |
Boolean values are 0 or 1. X, Y, and wheel use the signed 16-bit range. Masks affect physical input only; injected values bypass them.
GET LEFT..SIDE2 (0x11..0x15) returns only the injected button shadow: state is 1 while software is holding that button and 0 otherwise — it does not report the physical button. The text commands km.left()..km.side2() instead return 0 none / 1 physical / 2 injected / 3 both, because the text layer also reads the physical snapshot. To read the physical mask over the binary API use GET PHYS_BUTTONS (0x55, bit0 left .. bit4 side2), or take it from the input snapshot or the mouse stream — not from the 0x11..0x15 GETs.
GET PHYS_BUTTONS (0x55) and GET INJECT_SNAPSHOT (0x56) are V4.036 read-only queries for a host bridge to align on connect/reconnect. 0x56 returns a fixed 40-byte little-endian record: mouse_buttons:u8 (injected, bit0..4), locks:u16 (the 14 km.lock targets 0..13, one bit each), keyboard_modifiers:u8 (HID usages 0xE0..0xE7), keyboard_keys[32] (the injected key bitmap, 8×u32, the key_values layout), spread:u8 (mouse injection interpolate percent; 255 = AUTO, the V4.041 default, which follows the injection-command interval — see KM_API), then reserved zero bytes to 40. Both leave 0x11..0x15 and every other opcode unchanged.
INTERPOLATE (0x1F) reads/writes the mouse injection spread: 0..100 = a fixed interpolation percent, 255 = AUTO (the V4.041 default, follows the injection-command interval). SET accepts 0..100 or 255 and echoes the value; 101..254 are rejected. Read-back caveat (v1): AUTO reads back as 255 = 0xFF, which is byte-identical to the generic v1 rejection reply (a lone 0xFF). A v1 client MUST interpret a 0xFF read-back of 0x1F as AUTO, not as a rejection — the v1 reply carries no framing to disambiguate, and a 0x1F GET or a 0..100/255 SET is never actually rejected. Display 255 as "Auto"; to set a fixed percent send 0..100; to restore AUTO send 255. (Under the V4.043 management-protocol v2 the reply carries frame flags, so a reply vs a NAK is unambiguous there.)
0x60..0x65 exist on MAKCU V4.026 and later and follow the V3 text commands described in KM_API (km.lock_*, km.click, km.moveto, km.getpos, km.screen, km.silent). LOCK targets: 0 left, 1 right, 2 middle, 3 side1, 4 side2, 5 X, 6 +X, 7 -X, 8 Y, 9 +Y, 10 -Y, 11 wheel, 12 wheel up, 13 wheel down; a lock is the same state as the matching mask. MOVING (V4.028) is 1 while injected movement is still queued, MOVE_NOW (V4.028) sends a move in the next report instead of spreading it. FLICK (V4.029 test) sends the move and the press in one report and the release (and, with back 1, the move reversed) in the next; button 1..5, default 1. CLICK button is 1..5, count 1..255 (default 1), hold 0 = random 35-75 ms or 1..5000 ms. Screen sizes are 1..32767.
Keyboard
Keys are USB HID usages 0..255. SDK key names are converted before framing.
| Operation | Command | Value | Payload | Returned data |
|---|
| SET | KEY_DOWN | 0x20 | key:u8 | none |
| SET | KEY_UP | 0x21 | key:u8 | none |
| SET | KEY_INIT | 0x22 | empty | none |
| SET | KEY_PRESS | 0x23 | key:u8 [hold_ms:u32 [random_range:u32]] | none |
| SET | KEY_STRING | 0x24 | text:ASCII[0..248] | none |
| GET | KEY_IS_DOWN | 0x25 | key:u8 | state:u8 |
| SET | KEY_MULTI_DOWN | 0x26 | keys:u8[1..14] | none |
| SET | KEY_MULTI_UP | 0x27 | keys:u8[1..14] | none |
| SET | KEY_MULTI_PRESS | 0x28 | keys:u8[1..14] | none |
| SET | KEY_MASK | 0x29 | key:u8 mode:u8 | none |
| SET | KEY_REMAP | 0x2A | source:u8 target:u8 | none |
| GET | KEY_KEYS | 0x2B | empty | enabled:u8 |
| SET | KEY_KEYS | 0x2B | enabled:u8 | none |
Keyboard masks and remaps affect physical input only. KEY_INIT clears injected keyboard state and keyboard policies.
Controller
Names describe physical position, not product artwork.
| ID | Control | Value |
|---|
| 0 | SOUTH | 0 or 1 |
| 1 | EAST | 0 or 1 |
| 2 | WEST | 0 or 1 |
| 3 | NORTH | 0 or 1 |
| 4 | DPAD_UP | 0 or 1 |
| 5 | DPAD_DOWN | 0 or 1 |
| 6 | DPAD_LEFT | 0 or 1 |
| 7 | DPAD_RIGHT | 0 or 1 |
| 8 | LEFT_SHOULDER | 0 or 1 |
| 9 | RIGHT_SHOULDER | 0 or 1 |
| 10 | LEFT_TRIGGER | 0..1023 |
| 11 | RIGHT_TRIGGER | 0..1023 |
| 12 | LEFT_STICK_X | -32768..32767 |
| 13 | LEFT_STICK_Y | -32768..32767 |
| 14 | RIGHT_STICK_X | -32768..32767 |
| 15 | RIGHT_STICK_Y | -32768..32767 |
| 16 | LEFT_STICK_BUTTON | 0 or 1 |
| 17 | RIGHT_STICK_BUTTON | 0 or 1 |
| 18 | SELECT | 0 or 1 |
| 19 | START | 0 or 1 |
| 20 | MODE | 0 or 1 |
| 21 | GRIP_LEFT | 0 or 1 |
| 22 | GRIP_RIGHT | 0 or 1 |
| 23..54 | EXTRA_1..EXTRA_32 | 0 or 1 |
Complete controller state is:
digital_low:u32
digital_high:u32
left_trigger:u16
right_trigger:u16
left_stick_x:i16
left_stick_y:i16
right_stick_x:i16
right_stick_y:i16
Digital bit N is control ID N. Mask modes are DISABLED=0, COMPLETE=1, NEGATIVE=2, POSITIVE=3, and BOTH=4. Digital and trigger controls accept disabled or complete. Axes accept disabled, negative, positive, or both; complete is not valid for an axis.
Trigger fields remain u16 on the wire but their canonical value range is 0..1023 for both injection and input streaming. MAKXD maps that 10-bit value to and from the selected controller's native trigger width. Stick axes remain signed -32768..32767. Stick direction is the same for every controller family: positive X is right and positive Y is down (the mouse convention). Since firmware V4.008 MAKCU mirrors the Y axis of Xbox-protocol (GIP) and XInput controllers, whose native +Y is up, both on injection and in CONTROLLER_PHYSICAL; software must not invert Y per controller type. MAKCU V4.008 through V4.023 also mirrored generic HID controllers (for example a SCUF Envision in PC mode, whose native +Y is already down) by mistake, so on those builds their injected and reported Y was upside down; fixed in V4.024 (and V4.025 on the V4.017 line). MAKXD follows the same convention from firmware 0.2.0 (injection, CONTROLLER_PHYSICAL and the axis mask modes); earlier MAKXD firmware passed native Y through, so on Xbox-protocol and XInput pads positive Y was up.
Generic HID controllers take their right-stick and trigger axes from their own report descriptor since V4.009 (DInput-style pads with the right stick on Z/Rz and triggers on Rx/Ry, Xbox-style pads with the right stick on Rx/Ry, and pads with Simulation-page triggers are all handled); canonical control IDs are the same for every layout. MAKXD does the same from 0.2.0 and also accepts generic HID axes with any 16-bit logical range (earlier MAKXD firmware injected analog values only into axes spanning exactly -32768..32767 or 0..65535).
Mouse/keyboard-to-controller translation. When a controller is the active target and translation is enabled, LEFT/RIGHT (0x11/0x12) drive the triggers, MOVE (0x18) the right stick and WASD key state the left stick instead of reaching a mouse. Translation is off by default since V4.009 (earlier firmware shipped it on) and is configured and saved in MAKUI under "Mouse and keyboard to controller"; a device upgraded from earlier firmware that never saved a translation runs with it off until one is saved. MAKXD 0.2.0 and later behave the same way: translation is off by default, and a device upgraded from earlier MAKXD firmware whose four channels still hold the old factory values runs with it off. MAKXD smooths translated right-stick motion (a quarter step per update, returning to centre in 4 ms steps after movement stops).
The two stick channels (0 = WASD to left stick, 1 = MOVE to right stick) have an optional anti-deadzone (MAKCU V4.023+, off by default): a percentage 0..50 of full deflection at which any non-zero translated stick vector starts, so small corrections are not lost in the game's stick deadzone. The vector is rescaled radially, |v'| = lo + |v| * (1 - lo/32767) with lo = 32767 * percent / 100, keeping its direction; zero stays zero and full deflection is unchanged. It is read and staged through the connection record 0x1C of API_CONNECTION (0x3E): payload 1C ch reads, 1C ch percent stages; both answer 1C ch percent pending, where pending is 1 until the value is saved. Earlier firmware answers FF. The existing translation record 0x1A and its 8-byte reply are unchanged.
| Operation | Command | Value | Payload | Returned data |
|---|
| GET | CONTROLLER_STATE | 0x40 | empty | complete state |
| SET | CONTROLLER_STATE | 0x40 | complete state (20 bytes) | none |
| GET | CONTROLLER_STREAM | 0x41 | empty | enabled:u8 |
| SET | CONTROLLER_STREAM | 0x41 | enabled:u8 | none |
| SET | CONTROLLER_MASK | 0x51 | control:u8 mode:u8 | none |
CONTROLLER_STREAM accepts only on/off (1/0) or an empty query. The previous named/individual-control command and its 3- or 5-byte payloads are removed. Use CONTROLLER_STATE for injection and CONTROLLER_MASK for physical-input masks. Update firmware and SDKs together.
MAKCU controller handoff
MAKCU V17 (firmware 1415209727) introduces zero-state handoff. Earlier MAKCU firmware, including 355179621, holds zero analogue values instead. Update the firmware before relying on the completion sequence below.
MAKXD requires V12 or later for full CONTROLLER_STATE zero handoff. V11 and earlier have a separate zero-release path for individual controls; their full-state command does not provide the completion semantics below. Use matching updated firmware on both units when routing across a MAKXD pair.
CONTROLLER_STATE sends a complete target state, not a relative movement or a timed action. Keep sending the desired state while controlling the pad. When a stick's movement finishes, send both coordinates as zero. A single zero coordinate with the other nonzero still controls the entire stick. Send zero for a trigger when its action finishes. Other nonzero controls remain active.
The firmware moves from the last accepted output toward the latest physical value using its saved handoff processing, then releases the override after the matching final output is accepted. Zero does not command a centre jump. With processing disabled, handoff is immediate. An untouched zero group passes physical input through. Physical-input masks remain a separate setting.
The caller owns completion: silence, returning from the setter, and sending a single nonzero state do not request handoff. There are no trailing duration or release bytes. Do not append extra bytes or automatically zero every setter: that would interrupt ongoing movement. Send the final zero state from the application's movement-complete/cancel path while the connection is available, and handle send failures. Setter success does not acknowledge USB completion.
// While this application's right-stick/trigger action is active:
makxd::ControllerState state{};
state.rightStickX = x;
state.rightStickY = y;
state.rightTrigger = trigger; // 0..1023
if (!device.setControllerState(state)) {
// Handle the transport failure in your application.
}
// In the action's completion/cancel path, when all its controls are finished:
if (!device.setControllerState(makxd::ControllerState{})) {
// Handoff was not successfully sent; handle the failure.
}
// If other controls are still active, retain their values in the final state
// and zero only the completed stick pair / trigger instead.
MAKXD rejects unsupported controls, invalid values or modes, and incorrect payload lengths. Controller injection requires a routed controller with a successfully parsed current report.
Input change streams
Mouse, keyboard, and controller subscriptions are independent. Set one kind on/off; query one kind. Enabling a kind does not disable the others.
| Operation | Command | Value | Payload | Returned data |
|---|
| GET | INPUT_STREAM | 0x52 | kind:u8 | enabled:u8 |
| SET | INPUT_STREAM | 0x52 | kind:u8 enabled:u8 | none |
| EVENT | INPUT_CHANGE | 0x53 | kind:u8 id:u8 value | unsolicited |
| Kind | ID | On/off alias | Changed controls |
|---|
| mouse | 1 | BUTTONS (0x10) | Button IDs 0..31; 0 released, 1 pressed |
| keyboard | 2 | KEY_KEYS (0x2B) | HID usages 0..255, including modifiers; 0 released, 1 pressed |
| controller | 3 | CONTROLLER_STREAM (0x41) | Canonical button IDs and triggers 10/11 |
Controller IDs use the table above. IDs 12..15 (stick axes) are not emitted. D-pad directions and stick clicks are buttons. Extras are emitted where the connected controller supports them. Mouse motion and wheel are not emitted.
Every event is a complete MAK frame:
DE AD 03 00 53 kind id state:u8 # 8 bytes, digital state 0 or 1
DE AD 04 00 53 03 id trigger:u16le # 9 bytes, IDs 10/11, 0..1023
DE AD 03 00 53 kind FF FF # overflow for this kind
LEN determines the frame boundary. Dispatch 0x53 separately from command replies, then read kind and ID. A trigger value above 1023 is invalid. There are no event bitmaps, timestamps, CR/LF, or prompts.
Enable controller changes, observe a full left-trigger press, then disable:
DE AD 01 00 41 01
DE AD 04 00 53 03 0A FF 03
DE AD 01 00 41 00
Enable keyboard independently and query controller subscription state:
request: DE AD 02 00 52 02 01
request: DE AD 01 00 52 03
response: DE AD 01 00 52 01
Events describe changed physical controls before masks, remaps, or injection. Unchanged values emit nothing. Each enable starts from released/zero; the next physical report emits held buttons and nonzero triggers. Detach releases known active controls. Trigger native ranges are normalized to 0..1023, rounded to the nearest integer. An overflow disables only its kind and invalidates its queued changes; discard that kind's cached state and explicitly enable it again.
All enabled kinds share one destination: the caller of the last successful subscription change. Queries and disabling an already-disabled kind do not transfer ownership. Disconnect invalidates the destination. No automatic fallback to another transport occurs.
COM, UDP, BLE Command TX, and WebSocket carry the same full event frame. BLE command records still omit the length header; event notifications retain it. Raw UDP retains the subscription transaction header; events do not consume a pending query transaction. WebSocket uses the unsolicited request ID 0xffff. Encrypted MAKXD COM and encrypted UDP events are authenticated using their carried event nonce, which is distinct from a command reply nonce. Authenticate before decoding the event; continue matching normal replies to the requested opcode and transaction nonce.
| SDK | Set kind | Query kind | Receive changes |
|---|
| Python | device.input_stream(StreamKind.CONTROLLER, True) | device.input_stream(StreamKind.CONTROLLER) | set_input_callback(fn) or read_input_change(timeout) |
| Rust | device.input_stream(StreamKind::Controller, true) | input_stream_state(kind) | input_changes() channel |
| C++ | device.inputStream(StreamKind::Controller, true) | inputStream(kind) | setInputCallback(fn) |
| C | makxd_input_stream(device, MAKXD_STREAM_CONTROLLER, true) | makxd_input_stream_get(...) | makxd_set_input_callback(...) |
| C# | device.input_stream(StreamKind.Controller, true) | device.input_stream(kind) | device.read_input_change() |
Callbacks run on the reader thread; keep them short and send synchronous queries from another thread. C# polling uses the configured transport timeout. The standalone StreamFrameDecoder helpers handle fragmented or concatenated frames. The former raw km. events and general full-report stream helpers are not part of this public subscription contract.
V30 released · baseline
source来源: [email protected] (blob cb9fc22a == 8aff64b shipping V30)
35 km.* · 57 opcodes
- query always echoes the command line (tk-0380): km.version() returns 'km.version()\r\nkm.MAKCU\r\n>>> ' (~28 bytes) regardless of km.echo
- km.buttons(1) has no ASCII legacy stream; it enables the binary DE AD .. 53 event frame (ascii_buttons_1=framed)
- 35 km commands; no lock/click/moveto/getpos/screen/silent/moving/move_now/flick
- button merge last_change_wins: a physical release cuts an injected click (tk-0416, fixed later in V4.030)
- 0xA5 baud frame and 0x34/0x35/0x55/0x56 all rejected (reply DE AD 01 00 <op> FF)
V4.024 released · shipping
source来源: [email protected]
35 km.* · 57 opcodes
- same 35 km commands as V30; only behaviour fixes (V4.018 query echo, V4.020 button query + legacy stream)
- query echo honours km.echo (V4.018); default off -> km.version() returns 'km.MAKCU\r\n>>> ' (14 bytes)
- km.left()..side2() text query returns 0/1/2/3 (none/physical/injected/both) (V4.020, tk-0394)
- km.buttons(1) emits a bare 1-byte mask (bit0 left..bit4 side2) (V4.020); prefix-seeking clients miss it
- rapid-click release bug (tk-0416): last_change_wins, physical release cuts an injected click
V4.026 released · shipping
source来源: [email protected]
41 km.* · 63 opcodes
- adds lock_<t> (0x60), click (0x61), moveto (0x62), getpos (0x63), screen (0x64), silent (0x65)
- lock_<t> targets: ml/mr/mm/ms1/ms2/mx/mx+/mx-/my/my+/my-/mw/mw+/mw-
- km.moveto path params (seg,cx1,cy1,cx2,cy2) accepted but ignored
- km.buttons(1) still a bare 1-byte mask
- rapid-click release bug (tk-0416) still present (last_change_wins)
V4.030 released · shipping
source来源: [email protected]
46 km.* · 67 opcodes
- adds moving (0x66), move_now (0x67), flick (0x68) and ms1/ms2 side-button aliases
- km.buttons(1) emits 'km.' + mask + '\r\n' (6 bytes, prefixed)
- km.buttons(mode[,period]) accepts mode 0-2 + optional period 0-1000 (ignored) -> 2 args OK
- km.version() never echoes even with km.echo(1)
- echo default ON: esp32s3_settings_echo_get returns 1u for an unsaved record ('echo is on unless km.echo(0) was saved'); a settings format writes ECHO_SETTING=off, so a formatted device then reads 0. echo_default=1 reflects the fresh-record default (bridge M1 reads this field). Applies to the 4030 line (4030/4031/4033); the 4032 line defaults 0.
- 0xA5 set-baud: 'DE AD 05 00 A5 <baud u32 LE>', baud 115200 or 4000000, not persisted
- km.move accepts 2-7 args (path params ignored); km.left(2)..side2(2) silently release the injected bit
- button merge fixed to physical-OR-injected (tk-0416, commit dc6667e4)
- tolerant_line writings (bridge parser test vectors): (a) leading whitespace; (b) trailing junk after ')' e.g. 'km.left(1))#12'; (c) missing ')' treated as closed; (d) decimal args e.g. 'km.move(1.5,2)' fractional part skipped; a lone ')' line gets no reply
V4.031 test · test-v4.030
source来源: eaa2b6-confirmed (git-verified per-branch)
46 km.* · 67 opcodes
- 4030 line: prefixed stream, 2-arg km.buttons, 0xA5 present, tolerant_line, physical-OR merge
V4.032 released · shipping
source来源: eaa2b6-confirmed (git-verified per-branch)
41 km.* · 63 opcodes
- official shipping release; endpoint line, NOT a superset of 4030 (no 4030-line V3-compat commands)
- rejects 2-arg km.buttons: km.buttons(1,period) returns ERR (tk-0437); use km.buttons(1)
- km.buttons(1) emits a bare 1-byte mask
- 0xA5 set-baud REJECTED: replies DE AD 01 00 A5 FF, does not switch baud
- no line tolerance (leading space / trailing junk / missing paren / decimal)
- button merge physical-OR-injected (tk-0416 cherry-picked)
V4.033 test · test-v4.030
source来源: eaa2b6-confirmed (git-verified per-branch)
46 km.* · 67 opcodes
- 4030 line (m-o-o-n test): prefixed stream, 2-arg km.buttons, 0xA5 present, tolerant_line, physical-OR merge
V4.035 test · test-v4.032
source来源: eaa2b6-confirmed (git-verified per-branch)
41 km.* · 63 opcodes
- 4032 line (aim test): bare-byte stream, rejects 2-arg km.buttons (ERR), 0xA5 rejected, no line tolerance, physical-OR merge
V4.036 released · shipping
source来源: eaa2b6-confirmed (tag makcu-v4.036); official + default in the makcu-devinfo catalog 2026-09-28
42 km.* · 68 opcodes
- assembled (tag makcu-v4.036), not yet shipped; recheck if the branch moves
- unified km.buttons stream: mode 1/2 = 'km.'+mask prefixed, mode 3 = bare byte; 2-arg accepted (period ignored)
- restores 0xA5 set-baud; adds move_now (0x67), 0x34 mouse history read, 0x55 PHYS_BUTTONS, 0x56 INJECT_SNAPSHOT
- 0x35 raw-report ring NOT in this build (backport after V4.036)
- does NOT carry flick/moving/ms1/ms2/left(2)-release/line-tolerance; those V3 conveniences live in the bridge
- button merge physical-OR-injected
V4.037 test · shipping
source来源: eaa2b6-confirmed (makcu-v4037 f4f1030c, ver 4037)
42 km.* · 68 opcodes
- V4.036 + full-speed endpoint clamp (tk-0460): interrupt/bulk endpoints declaring wMaxPacketSize > 64 are presented and read at 64 instead of the device being rejected (e.g. Rapoo 24AE:1412, 512 B); isochronous and <=64 endpoints unchanged
- descriptor-proxy behaviour only; no API/opcode change vs 4036
- non-official test build (published to catalog, not default); assigned to MK-HFWT-QGTG for Rapoo re-test
V4.038 test · shipping
source来源: eaa2b6-confirmed (makcu-v4037 0892ca76, ver 4038)
42 km.* · 69 opcodes
- V4.037 (full-speed endpoint clamp) + 0x35 raw-report passthrough: armed per-kind 8-deep ring of raw HID reports (raw axes / report rate) read via ARM/READ/DISARM; needs a 0x35-aware client
- non-official test build (published to catalog, not default); test build only
V4.039 test · shipping
source来源: eaa2b6-confirmed (makcu-v4039, ver 4039)
42 km.* · 70 opcodes
- V4.038 + 4030-line V3 compatibility restored so V3-era tools (Blurred/AIO) work without the bridge: tolerant line syntax (leading/trailing blanks, trailing junk after ')', a missing ')' taken as closed, decimal args truncated to int), km.move path args accepted and ignored, km.left(2)..side2(2) silent release, ms1/ms2 aliases, moving(0x66)
- default injection interpolation 0 (4036 was 50%, which reproduced closed-loop overshoot, tk-0350); interpolation semantics: 0-25% ~= 4 frames, 50% ~= 17 ms, 80% ~= 42 ms
- guardrail: every canonical write v4.036 accepts replies byte-identically on v4.039; the only differences are the V3-syntax subset v4.036 rejected (tools/tests/test_km_v3compat.py)
- A5/A4 V3 baud frames (DE AD 05 00 A5 + 4 bytes) no longer eat the next command's first byte (tk-0454; tools/tests/test_uart0_frame.py)
- flick(0x68) NOT included: it needs a USBPT_INPUT_FLICK engine mode absent from the 4036/4037 engine; not a V3-tool dependency, deferred
- km.buttons stream format stays 4036-unified (mode 1/2 prefixed, mode 3 bare, 2-arg period ignored); echo default stays off (4036), not the 4030 always-on; km.version() never echoes even with echo on (restored from 4030)
- no adaptive V3 echo mode (evaluated, not done): AIO is a binary write-only client that does not gate on replies, so the A5 baud fix is the substantive fix; a4 has no handler (see legacy_baud_frame)
- non-official test build (published to catalog, not default); V3-tool compatibility, roll-back safe
V4.040 test · shipping
source来源: eaa2b6-confirmed (makcu-v4039 c392f851, ver 4040)
42 km.* · 70 opcodes
- V4.039 + downstream enumeration tolerates a STALLed SET_PROTOCOL (HID 1.11 7.2.6): a boot-subclass device that does not implement Set_Protocol keeps the default report protocol and enumeration continues instead of failing the whole device (tk-0456 root fix)
- enumeration-control failure now latches a discoveryFailed fault (records SETUP / VID:PID / status); server triage: enum-aborted / set-protocol-stall
- opcodes, km_names, text and streams identical to 4039
- non-official test build; sha256 34e6e673..., 331344 bytes
V4.041 released · shipping
source来源: eaa2b6-confirmed (makcu-v4039 b52eb6e5, ver 4041; tag makcu-v4.041 = 70ee2b56); official + default in the makcu-devinfo catalog 2026-09-29
42 km.* · 70 opcodes
- V4.040 + both chips enable a 2s watchdog (main-loop feed + 250ms heartbeat; storm guard: 3 consecutive abnormal resets skip enabling it for that boot; 30s healthy clears the counter); an abnormal reset records USBPT_FAULT_RESET (reason 512), server triage labels it by cause: wdt-reset (watchdog) / brownout-reset (power dip) / abnormal-reset (other) since devinfo 1.10.9; faultdecode: abnormalReset
- mouse injection interpolate default changed to AUTO: the spread get/set sentinel 255 = AUTO, which adapts 1-64 ms to the injection-command interval, replacing 4039's default 0. Controller injection interpolate already defaulted AUTO (usbpt_controller_config), unchanged. default_interpolate_percent=255 encodes the AUTO sentinel
- opcodes, km_names, text and streams identical to 4039 (no new opcode)
- official release since 2026-09-29 (user-approved; includes everything in 4037-4040): catalog id v4.041, sha256 a967042d..., 332672 bytes. The earlier 4041 test package was sha256 380696e9..., 332704 bytes
V4.042 withdrawn · shipping
source来源: release-window git diff (makcu-v4042 b0534dd6, ver 4042): code differs from tag makcu-v4.041 only in usbpt_interface_budget.h
42 km.* · 70 opcodes
- WITHDRAWN 2026-09-29: failed a controlled test on 054C:0CE6 (DualSense, tk-0446: configuration never completed, paired detach); marked withdrawn in the catalog, never assigned; use V4.041
- V4.041 + controllers no longer forward their USB audio interfaces (speaker, microphone, USB haptics) through MAKCU; fixes DualSense / DualShock 4 dropouts (tk-0446, port of the V4.028 controller USB-audio suppression). Rumble and adaptive triggers run over HID and are unaffected
- opcodes, km_names, text and streams identical to 4041
- non-official test build (published to catalog, assigned per device); sha256 7147188b..., 333152 bytes
V4.043 test · shipping
source来源: release-window git log (makcu-v4043 abc4316b built with MAKCU_ADVERTISE_V2, ver 4043): V4.041 tip + management protocol v2 commits only
42 km.* · 70 opcodes
- V4.041 + management protocol v2 on the management port: framed request/reply with sequence numbers, bad-length resync to NAK, NOACK/diagnostic reject, BUSY cadence, INFO page 2; for MAKCU Bridge 0.1.6+
- field-test build: features bit7 set (MAKCU_ADVERTISE_V2); does NOT contain the V4.042 controller-audio change
- non-official test build (published to catalog, assigned per device); sha256 3fb4401b..., 334480 bytes
V4.044 test · shipping
source来源: release-window git diff (makcu-v4044 c4c79a7d, ver 4044): code differs from tag makcu-v4.041 only in the downstream over-current debounce
42 km.* · 70 opcodes
- V4.041 + downstream over-current teardown is debounced (5 ms): high-inrush controllers (DualSense) on USB3 are no longer cut off repeatedly at power-on (tk-0484)
- does NOT contain V4.042 (controller audio) or V4.043 (protocol v2)
- non-official single-customer test build; sha256 b620eebd..., 332704 bytes
V4.046 test · shipping
source来源: release-window git diff (makcu-v4046 f75c37d3, ver 4046): code differs from tag makcu-v4.041 only in the downstream over-current handling
42 km.* · 70 opcodes
- DIAGNOSTIC build: V4.041 with the USB3 downstream over-current teardown disabled, for one support troubleshooting step (tk-0484); not for general use
- does NOT contain V4.042, V4.043 or V4.044
- non-official single-customer diagnostic build; sha256 65ad464e..., 332656 bytes
V4.047 test · shipping
source来源: release-window git log (makcu-v4047 ca9d065a, receipt 603d3c63, ver 4047): V4.041 tip + tuning record 0x1D Auto + update-time watchdog off
42 km.* · 70 opcodes
- V4.041 + the TIMG0 watchdog stays off for the whole firmware update (fixes 'right side did not join recovery' when updating from V4.041)
- tuning record 0x1D via 0x3E accepts mouse spread AUTO (255), so imported settings saved with Auto interpolation apply (record id, not opcode 0x1D)
- does NOT contain V4.042, V4.043, V4.044 or V4.046
- non-official test build; sha256 4359aeab..., 332976 bytes
V4.048 test · shipping
source来源: firmware window receipt (makcu-v4048-draft e4bd6c14, source 90032d2f, ver 4048): V4.047 ca9d065a + controller override/merge, link re-arm (off by default), peer counters kind 12
42 km.* · 70 opcodes
- V4.047 + controller buttons held on the physical pad stay pressed while software injects (physical-or-injected, D-pad never merged); an injection override is cleared on re-plug / USB reset
- a composite controller that also exposes a mouse interface (some GameSir pads) no longer shows a phantom mouse: injected movement is not sent on a mouse interface the device never reports on (tk-0499)
- diagnostics: the right chip's event counters over the inter-chip link (snapshot kind 12) and a compact reset-loop history
- does NOT contain V4.042, V4.043, V4.044 or V4.046
- non-official test build; sha256 65fe74d4..., 334928 bytes
V4.049 test · shipping
source来源: firmware window receipt (makcu-v4049-tk0527 4ffc4b55, source df0f2c69, ver 4049): V4.048 + config descriptor truncated to wTotalLength (tk-0527)
42 km.* · 70 opcodes
- V4.048 + a device that returns an oversized USB configuration descriptor (YICHIP 3151:xxxx receivers such as the Attack Shark R3) is trimmed to its own wTotalLength and enumerates (tk-0527); correctly sized configurations are unchanged
- non-official test build; sha256 1846d9e2..., 335072 bytes
V4.050 test · shipping
source来源: firmware window receipt (makcu-v4050-ocdebounce a6ffdeb7, source ed8aa613, ver 4050): V4.049 + v4044 USB3 over-current debounce ported verbatim (Ports: c4c79a7d)
42 km.* · 70 opcodes
- V4.049 + USB3 over-current debounce: a brief power-up surge (up to 5 ms, e.g. PowerA wired Xbox pads) no longer cuts the port; a sustained short still does
- does NOT fix the DualSense (DS5): that is an enumeration problem, investigated with the V4.052-diag build (fault-analysis FIRMWARE-VERSION-MATRIX.md)
- non-official test build; sha256 4033fc09..., 335120 bytes
V4.051 test · shipping
source来源: firmware window receipt (makcu-v4051-idlerelease cd33c19f, source 323c3872, ver 4051): V4.050 + controller override idle-release (a-2)
42 km.* · 70 opcodes
- V4.050 + an abandoned controller injection override returns to the physical pad after about 1 s without new commands (sticks, triggers, buttons); continuous injection is unaffected. On by default; the controller device-tuning byte bit 1 turns it off for set-and-hold use (tk-0466 / tk-0342)
- contains V4.047 - V4.050
- the idle-release off bit is 0x1D settings image byte 397 bit 1 (values 2/3): needs MAKUI >= 5c9f12fd, which reads and writes bytes 397-399 as they are; older MAKUI failed the whole settings read on 2/3 and cleared the bit on write-back (same class as 4041 AUTO=255). The MAKUI UI has no switch for it; only a raw 0x1D write sets it
- assigned only to customers with the matching symptom; not the recommended build until verified (FIRMWARE-VERSION-MATRIX.md section 3)
- non-official test build; sha256 8adedb5d..., 335232 bytes
V4.053 test · shipping
source来源: [email protected] (33d88be3; source 2b00bf30)
42 km.* · 70 opcodes
- V4.051 lineage plus preset preservation, controller idle/static release, peer-silence neutralization and AUTO interpolation fixes. Includes enumeration tracing with normal over-current protection enabled.
- A customer still reports controller stoppage after installation; field resolution is not confirmed.
- Test build; 339248 bytes; sha256 b5f17d87a40f5a8cda9bc0d9f7ecfe323ae9f64f9d4a566d42d7b3cc207cf812
V4.054 test · shipping
source来源: V4.054 source 3c4986cf, based on V4.053
42 km.* · 70 opcodes
- Fixes controller_mask mapping on generic HID controllers with right stick on Z/Rz and triggers on Rx/Ry or Simulation usages.
- Adds bounded support-report pipeline counters, command rejection/handoff metadata and upstream public security configuration. No command syntax or settings layout change.
- Keyboard injection stalls and controller stoppage remain under investigation; this test build does not claim they are resolved. XTS-encrypted custom-board migration remains unsupported by the standard installer.
- Test build; 340656 bytes; sha256 e5b462a8b295c827a83d99424d22e4683e2854a7a19dad64de7291a24a55589b
V4.055 test · shipping
source来源: V4.055 source 7d0b0662, based on V4.054
42 km.* · 70 opcodes
- Adds diagnostic boot/time context and retained first no-progress pipeline evidence; no command syntax or settings layout changes.
- Toolkit 1.12.0 adds linked reproduction phases and controlled keyboard/passive controller tests.
- Keyboard/controller field failures remain under investigation. A no-progress candidate is not proof of a firmware fault. XTS custom-board migration remains unsupported.
- Test build; 341664 bytes; sha256 f9c3a9e5748c7ccfcb20e1a9e8f94423946d82d28f50785c8db997e7e571bd6d
V4.056 test · shipping
source来源: V4.056 source 64d55f96, based on V4.055
42 km.* · 70 opcodes
- Reserves 32 of 128 FIFO slots for release/unmask and all-zero controller state; ordinary outstanding commands are limited to 96. FIFO order is preserved.
- Recovery capacity is finite; clients must handle rejection and retry. Existing command, settings and diagnostic formats are unchanged.
- Software regression tested; not a verified fix for UART loss, USB hardware stalls or CPU hangs. XTS custom-board migration remains unsupported.
- Test build; 342096 bytes; sha256 c22b76444ef6f6a61b34926de3a497e665239ab6dd29b5ebf8876335a5068863
V4.057 test · shipping
source来源: V4.057 source be217107, based on V4.056
42 km.* · 70 opcodes
- Passive no-progress diagnostics observe active interrupt IN only; audio ISO/bulk endpoints are excluded.
- Suspend, reconfiguration, endpoint epoch and session changes reset the observation window. First frozen evidence and event counts remain available; no automatic recovery.
- 32 software test scripts pass; hardware validation pending. Not a proven passthrough stall fix. API, settings and diagnostic wire formats are unchanged.
- Test build; 342256 bytes; sha256 352f716f32066bdd4ccba1e7179e9fc2bffc6b48f73920940dd8a1de45c0f498
V4.058 test · shipping
source来源: V4.058 source 99c6ad13, based on V4.057
42 km.* · 70 opcodes
- D2: bounded per-endpoint receipt, preparation, submission and completion correlation; separate physical/synthetic and opaque forwarding.
- Snapshot kinds 17/18 carry live/frozen first-candidate evidence with boot, session, route, parse validity and cell replacement counters. USB3 clock is separate; USB completion is not application delivery.
- 33 software regression scripts and dual-chip build pass; physical mouse/controller stress validation pending. No automatic recovery; API and settings unchanged.
- Test build; 343760 bytes; sha256 992349e4d23a238fb00399f19640ded3291334f93cf21e5496f7a069c7b4de04
V4.059 test · shipping
source来源: V4.059 source 848b8740, based on V4.058
42 km.* · 70 opcodes
- C1: a stalled proxy-expanded 512-byte configuration read can fall back to a 9-byte header and validated declared length. At most two extra transfers; successful original reads are unchanged.
- Failed or malformed fallback remains an error. No automatic reset; request cancellation, input APIs, settings, topology mapping and D2 diagnostics retained.
- 34 software regression scripts and dual-chip build pass. Physical receiver recovery and broader compatibility are not yet confirmed.
- Test build; 344096 bytes; sha256 3a15b33f10714c862fabc0a32bf1e9bba5afdc0ee79bcfae1cb64981fd44db7b
V4.060 test · shipping
source来源: V4.060 source 0ea4e03f, build 10dc7a8f, based on V4.059
42 km.* · 70 opcodes
- C2 first increment: stable injection ownership is separate from report observation. Alternating reports preserve accepted mouse movement and held controller buttons without cross-report injection.
- Physical buttons aggregate by compatible report slots. Stable mouse target prefers XY; true lifecycle release, slot compaction and silent-peer neutralization retained.
- 35 software scripts pass, including 11 multi-report cases; dual-chip build passes. No physical hardware validation. Controller physical-state query may reject while latest report differs from the injection target; full axis/hat aggregation is follow-up work.
- Test build; 345488 bytes; sha256 f1a765e8acdbe5c97a2ee651fb8ad886a0775ad8c069eb3638a336cedba36931
V4.061 test · shipping
source来源: V4.061 source f8e56c55, build 74d13320, based on V4.060
42 km.* · 70 opcodes
- C2b: controller physical queries use observation-specific capabilities and ranges, published coherently with the physical snapshot. Report alternation no longer requires a matching injection target.
- 32-byte response, injection target isolation, physical reads with injection disabled and detach rejection retained. No new opcode or setting.
- 36 software scripts, dual-chip builds and linked SRAM bounds pass; 100 bytes of additional query metadata. Hardware timing/stack high-water unmeasured. Full cross-report axis/hat aggregation remains future work.
- Test build; 345584 bytes; sha256 4f40fdf45a5cecf77c85d6424e1bca074ee180df068c0a284ff3b8884061bf45
V4.062 test · shipping
source来源: V4.062 source da398b9c, build 1eee730a, based on V4.061
42 km.* · 70 opcodes
- C3 first increment: protect recognized GIP FF/47/D0 and XInput FF/5D/01 interfaces with alternate-zero interrupt IN during resource pruning; associated IAD groups inherit protection.
- Configurations that fit remain byte-identical. Unknown vendor interfaces remain droppable. Impossible protected configurations fail rather than silently removing main input. No resource limit increase or blanket audio removal.
- 37 software scripts, including 5 controller-budget test groups; existing 32 budget cases and dual-chip builds pass. Linked SRAM bounds unchanged. Hardware recovery and timing unverified. Generic HID scoring, class-specific reference rewriting and broader alternate-setting support remain pending.
- Test build; 345728 bytes; sha256 b1e8f75ea56c84d91559bc2465cc22ba16ed82fd02c43cbcbd3a5beb2a6d590c
V4.063 test · shipping
source来源: V4.063 source bd751535, build c56c7dd6, based on V4.062
42 km.* · 70 opcodes
- C3b: preserve UAC1 AudioControl/AudioStreaming/MIDIStreaming collections during resource pruning, including configurations without IADs. Existing IAD groups and strongest-member protection are preserved.
- Rewrite retained UAC1 collection references to PC-side interface numbers. Fitting configurations stay byte-identical. Invalid UAC1 references reject partial planning. Entity IDs and other classes/protocols are not treated as UAC1 interface references.
- 38 software scripts, nine audio-budget test groups, original 32 budget cases and dual-chip builds pass. Hardware acceptance unverified. Other class-specific references, generic HID scoring and complete alternate-setting support remain pending.
- Test build; 346544 bytes; sha256 4c0820f555084d62ab5ea76dc32e6acc50711cdfbfaae3de3d41074035632635
V4.064 test · shipping
source来源: V4.064 source cc1519e0, build 1e6ec16c, based on V4.063
42 km.* · 70 opcodes
- C3c: preserve CDC Union functional groups, including HID members and transitive IAD/UAC1 dependencies, during resource pruning. Rewrite retained Union and active Call Management interface references.
- Fitting configurations stay byte-identical. Invalid recognized references reject partial planning. Inactive Call Management fields stay opaque. No API/settings changes or endpoint/FIFO limit increase.
- 39 software scripts, 12 CDC regression groups, original 32 budget cases and dual-chip builds pass. Hardware acceptance unverified. CDC runtime notification indices, other class references, generic HID scoring and complete alternate-setting admission remain pending.
- Test build; 347152 bytes; sha256 0eef25a5b61199f813e34c2eee24c8e6710f1911b36f89e39c05c73adc9cefc5
V4.065 test · shipping
source来源: V4.065 source 2112fc12, build 589ba0a5, based on V4.064
42 km.* · 70 opcodes
- C3d: translate NetworkConnection, ResponseAvailable, SerialState and ConnectionSpeedChange wIndex after interface pruning. Direct alternate-zero CDC interrupt-IN endpoints only; notification must name its owning interface.
- Bounded per-pipe continuation tracking and once-per-buffer preparation avoid corrupting continuation data or remapping on UART retries. Errors/short termination and pipe retirement reset framing. Unknown notifications stay opaque.
- 40 software scripts, seven runtime test groups, original 32 budget cases and dual-chip builds pass. Hardware latency and stability unverified. Other alternates, hub-local routes, vendor notification layouts, generic HID scoring and full alternate admission remain pending.
- Test build; 347152 bytes; sha256 902605b869ef44febfb86dc6310eba5fa7f4c5da1d55f082ab71f23e7043628d
V4.066 test · shipping
source来源: V4.066 source 2770f569, build 3950e5d2, based on V4.065
42 km.* · 70 opcodes
- C3e: preserve SET_CONFIGURATION reserved index zero after physical interface zero is pruned. Only SET_INTERFACE translates the stage index; each retained pipe still uses PC interface numbering.
- Four production sender regression groups cover dropped interface zero, nonzero and zero alternates, identity/unconfiguration, UART retry and prepare rejection. 41 host scripts and dual-chip builds pass; hardware acceptance pending.
- No new state, buffer, API, settings or wire format. Generic HID main-input classification, alternate resource admission coverage and controller cross-report axis/hat aggregation remain pending.
- Test build; 347216 bytes; sha256 71a1a63af60ac980d225ee68a38fc4313eda852fc6d7bdd7d4b9fc12fe45e314
V4.067 test · shipping
source来源: V4.067 source 03a90703, build 8f4a6e15, based on V4.066
42 km.* · 70 opcodes
- C3f: configuration budget retains ISO bInterval 8..16, matching existing topology and runtime support. The 64-entry frame list is a publication window, not the maximum service interval.
- 42 host scripts and five ISO regression groups pass, covering both directions, default/nonzero alternates, retained mouse phase, resource rejection and extracted service-window/clock-wrap arithmetic. One of 32 historical budget expectations corrected; other 31 unchanged.
- Scheduling, FIFO/bandwidth limits, API, settings and bootloaders unchanged. No new static state. Real USB timing and hardware acceptance pending; alternate transaction recovery and generic HID semantics remain follow-up work.
- Test build; 347216 bytes; sha256 d21f5889029d9fa41de64aacd32628cbf5852d72ee0d88f6bd093a226191325d
V4.068 test · shipping
source来源: V4.068 source b4cc9115, build 7709484b, based on V4.067
42 km.* · 70 opcodes
- C2c: physical controller queries retain disjoint report fields within one unambiguous HID Application Collection, with per-field ranges and a group axis profile. Different logical controllers do not inherit query buttons.
- Raw USB bytes, per-report raw observations and injection targets unchanged. Mixed/unknown collections, overlapping fields and relative controller reports remain per-report. Source and topology lifecycle changes invalidate cached observations.
- 45 host scripts, eight actual-engine/API UBSan groups and dual-chip builds pass. Query fields are internal validity; legacy 32-byte API has no per-field freshness/validity extension and time denotes the latest update. Physical USB timing and hardware acceptance pending.
- Test build; 348832 bytes; sha256 954aaf04bb9ae075ad6246aa6eee2636061fa4feb5589175ed9af16d1e40a45d
V4.069 test · shipping
source来源: V4.069 source 3167857b, build e862b346, based on V4.068
42 km.* · 70 opcodes
- C4a: four-position physical HID hats map to cardinal directions. Captured ROG PUGIO II 0B05:1908 and CHAKRAM 0B05:18E5 descriptors reproduce the old right-to-up-right query error. Raw observations, physical queries and output shadow now agree.
- Native USB bytes and eight-way behavior unchanged. Four-way hat injection/capability remains unsupported; no guessed axis-family mapping or diagonal projection. No new state, settings, wire format or bootloader changes.
- 46 host scripts and dual-chip builds pass; captured descriptor, zero/one-based four/eight-way ranges, null states and unsupported injection covered. Input vectors are synthetic; physical device timing and acceptance remain pending.
- Test build; 348880 bytes; sha256 064bfeae80f2adff09d29fb0a189f8194b088ca0d92c24aa239c6ce2cfa703e5
V4.070 test · shipping
source来源: V4.070 source 12d49f19, build b6dc2b88, based on V4.069
42 km.* · 70 opcodes
- Raw diagnostic capture lifecycle: Core0 owns ARM/READ/DISARM and publication. A fixed mailbox delays success until owner execution. Reset invalidates pending commands and unread replies; generations no longer restart on reconnect and exhaustion fails closed within a boot.
- Existing wire format, physical USB forwarding and controller axis mappings unchanged. No new source metadata, queue depth, settings or bootloader changes. This is diagnostic consistency repair, not a proven USB disconnect or hardware lockup fix.
- 48 host scripts, actual API dispatch, deterministic in-flight-stop/reset regressions and dual-chip builds pass. Upstream linked memory grows 112 bytes; no physical USB or multicore stress acceptance.
- Test build; 349296 bytes; sha256 88fab5848e5f7f5b6658c23114fa810de28b0fc7c9419ee1c5ff8591dea93618
V4.071 test · shipping
source来源: V4.071 source 37a4b622, build 15a704e1, based on V4.070
42 km.* · 70 opcodes
- Versioned raw diagnostics add per-report source/interface/alternate/collection, descriptor FNV32 candidate hint, original length/truncation, timing validity and boot/session identity. Legacy 0x35 commands unchanged.
- Toolkit 1.13.0 labeled mouse/controller sample upload and server evidence validation. Unknown or keyboard-shared payloads redacted. Samples are not continuous recording or verified calibration.
- 48 host scripts and dual-chip build pass; linked memory grows 2112 bytes upstream and 16 bytes downstream. No physical USB or stress acceptance; forwarding and axis mapping unchanged.
- Test build; 349968 bytes; sha256 4e6c2c3bc15900f573f629996936ecd99377f79705801205a98efecf2e798ecb
V4.072 test · shipping
source来源: V4.072 source fe430e87, build 31353a00, based on V4.071
42 km.* · 70 opcodes
- Controller peer-silence protection fences queued commands at entry and exit. Injection processed during protection is rejected; old queued buttons no longer reappear after heartbeat recovery.
- A previously frozen frame may still complete; it cannot acknowledge newer neutral/recovery output. Existing API wire, normal mouse behavior, queue capacity and bootloaders unchanged.
- 49 host scripts and dual-chip build pass, including 14 real API/engine recovery cases and production power-state backpressure/suspend/resume with 40s watchdog mock feed. Physical USB/DMA/watchdog and mixed-device hardware stress remain pending.
- Test build; 350112 bytes; sha256 882de2a8eeaf0699e1754cc8dcdbd90e48cb6eaf29bfec605083d09b6c6ca9bf
V4.073 released · shipping
source来源: V4.073 source 83c680c6, based on V4.072
42 km.* · 70 opcodes
- km.baud() returns applied decimal rate; setters accept 115200, 4000000 and 0 (115200). Volatile; existing transport drains before switching. No boot-default or USB change.
- A4 query returns LE32 applied baud; V3 length-inclusive and modern length-exclusive query envelopes supported. Version identity reply unchanged.
- 50 host scripts pass; 54 V27/V29 parser comparison cases. Physical adapter and third-party application validation pending.
- Promoted to official by user decision on 2026-10-02; unchanged package; 350240 bytes; sha256 48f08cbe37baaad9b092b3994bc4597ad81ce5ca40b6febc757f4edfd45e0b51
V4.074 test · shipping
source来源: V4.074 source 799a092b (runtime ed8f773e), signed build ded12fdb; based on V4.073
42 km.* · 72 opcodes
- Opt-in binary Raw XY: FIFO-ordered, one complete relative report after older AUTO debt drains; existing KM and AUTO unchanged. Full API contract: /api/raw-v4074.md. SDK convenience methods are not added.
- 0x69 payload LE u32 id, i16 x, i16 y, u16 timeout_uf (10 bytes). 0x6A payload LE u32 id, u8 consume (5 bytes). States: queued=1, endpoint-submitted=2, rejected=3, immediate-error=255; queued is not sent.
- IDs strictly increase globally per device boot. At most 16 live/unread results. Peek and save terminal results before consume. Boot clears RAM history; timeout starts at processing head, not enqueue.
- 50 native host scripts plus Raw engine/API/runner/UART tests and full dual-chip canonical build pass. Physical UART/USB, 1kHz throughput and long-run stability pending user testing. No settings/bootloader changes; V4.073 official rollback retained.
- Signed test; 353056 bytes; sha256 153562e1f7e1195af79b2772b2ddb38c6cd1edcc44321cd0b16abedd41a94c22
V4.075 test · shipping
source来源: V4.075 source 99b4537d, signed build 51eb2ed1; based on V4.074
42 km.* · 72 opcodes
- Legacy A4/A5 baud frames consume their full declared V3 payload length. Over-long frames no longer leave tail bytes that can shift km.version() or the next handshake command; standard frames are unchanged.
- USB identity, km.version() reply, boot baud selection, persistent baud settings, the V4.074 opt-in Raw API and bootloaders are unchanged.
- 50 native host scripts, targeted UART/V3 KM/API tests and a clean dual-chip canonical build pass. Closed-source application detection still depends on COM-port and baud probing; no physical-device validation has been recorded.
- Signed test and default for ordinary users; V4.073 remains official rollback. 353056 bytes; sha256 9ac9b740a9ec631d7c6e578d9c268bbf8cecab6e713572b3709c2de43535b933
V4.076 released · shipping
source来源: V4.076 source 9470834c, signed build 3c04c976; based on V4.075
42 km.* · 72 opcodes
- Includes V4.075 legacy A4/A5 baud-frame compatibility.
- Raw 0x69 movement is applied at most once across repeated frame builds; rejected requests do not leave movement in a second pending frame. Reset invalidates stale stamps with bounded endpoint indexing.
- 52 host regression scripts, dual-chip build and P-256 signing pass. Physical UART/USB and third-party application compatibility remain unverified.
- Official 2026-10-04; default for ordinary users. Manual rollback/diagnostic assignments preserved; V4.073 retained for rollback. 353184 bytes; sha256 36efb12a446e34f9c319f6c34087e9c17578692b110d7c839f1051176ff2eb7d
V4.077 test · shipping
source来源: V4.077 source 87e28b856521c5d2573e01efa956c38993d3ddc0; signed build 06704fa7c47f70653a9fc6dc00e065f021f1c983; based on V4.076
42 km.* · 72 opcodes
- Targeted DualSense 054C:0CE6 and DualSense Edge 054C:0DF2 compatibility test. Complete pure USB audio functions are hidden on both chips; HID input/output remains supported.
- Controller speaker, microphone, headset audio and USB audio-based haptics are unavailable through MAKCU. Test vibration/adaptive triggers in-game.
- 53 host regression scripts and paired signed build pass; physical hardware improvement remains unverified. Failure rollback uses each device's previously verified working firmware.
- Targeted rollout only. Official and general default remain V4.076. 353728 bytes; sha256 27761d768fcaf273b264257756f8ff4d48729df46a24195cd1c5de78fac13d34
V4.078 released · shipping
source来源: Source 84f48aaeb873ece569ccead4ca77355a749947a5; signed build 616045134c6b9c22914af02d2862bad7636c2178; based on V4.077
42 km.* · 72 opcodes
- Mouse button masks immediately refresh the cached physical state and queue a digital report. Software release under the mask works without waiting for another mouse report; unmasking restores the latest physical state.
- Inherits V4.077 DualSense/Edge USB audio isolation. Controller speaker, microphone, headset audio and USB audio-based haptics remain unavailable.
- 54 native host regression scripts, paired canonical build and P-256 signature verified. Real Neptune/Paint and USB hardware results pending feedback.
- Official release from 2026-10-04. General default and existing assignments unchanged. 353808 bytes; SHA256 ad8b6d35059127aeb6839156ffb154b52185c3ffae174977c483c366805f64c2