ANT ESPORTS APEX 200 Control

disconnected 314B:1026

Device

HID collections

not connected

Report descriptor

Detection check — measured from this device

Vendor / product314B:1026 — APEX APEX200, matches the Windows app's filter
Config interfaceUSB interface 0 → /dev/hidraw0 (the only interface with IN + OUT endpoints)
Usage page0xFF02 (vendor defined) — not a protected usage, so WebHID can reach it
Report IDsnone — the implicit report ID is 0, so sendReport(0, frame)
Report size64 bytes in and out → 58-byte payload budget after the 6-byte header
Other interfaces1 keyboard, 2 pointer, 3 keyboard+digitizer — all protected usages
The keyboard's own HID interface (0x0006) is a protected usage and Chrome will not expose it, which is correct — the config channel is the vendor collection. If the picker lists several entries, choose the one whose collection tree contains usage page 0xFF02.

Lighting

one pass: current effect and levels (0x17), effect names (0x18), per-key table (0x16)
Not read yet — press Read lighting state.

Effect engine

These controls describe one running effect. Each button writes only the fields beside it; everything else is read from the keyboard first and carried through unchanged, then read back to prove it.
ButtonOpcodeChangesKeeps
Apply effect, brightness & speed 0x13 effect index, brightness, speed colour and device-owned bytes
Apply colour to this effect 0x13 R, G, B for this effect brightness, speed, device-owned bytes
Make this the active effect 0x19 which effect is running every config byte
write 0x13 — sliders only · readback verified
write 0x13 — colour only · readback verified
write 0x19 — config unchanged
Advanced reads (raw)
Reads only. The name list is read from the keyboard; twelve of the thirteen names decode, and the remaining slot is shown as undecoded rather than guessed. Index 12 is outside the device's validated 0–11 range, so it is never offered as a write.

Per-key colour table

This is a separate feature from the effect engine. It is a static colour per key, used when the board is in its per-key/custom mode. It does not change the effect, brightness or speed above.

Every byte is named from assembly (§8.13.2): byte 0 = the first keyItem, then (light, R, G, B) per key in ascending order. The command is 0x11; the table is read with 0x16 first, untouched keys are preserved, and the write is split into 14-key pages exactly as the app's builder does. The whole table is read back and compared afterwards.
Write 0x11 — read-modify-write against 0x16, then full-table readback verification. Colour is recoverable by rewriting, unlike keymap layout or actuation records.

Profiles

⚠️ Profile writes (0x55/0x58/0x59) are exposed but can permanently change device state; only recovery is factory reset. Always take a snapshot first.
The Windows app's Export and Import profile buttons are host-side file handling, not protocol operations: export dumps what these four commands read back, and import replays the corresponding writes through a decoded chain (PROTOCOL.md §8.22: a 0x56 name frame, then 0x57/0x50/0x11/ 0x14/0x20/0x23/0x40/ 0x28, each fired by the previous write's last-page ack). It is not wired here, because a correct import is only as safe as the gated writes it replays, and none of them has been hardware-validated.

Device snapshot

read-only — writes nothing
Reads all ten of the device's configuration tables in one pass and shows them decoded. This mirrors what the Windows app's SyncConfigUtil collects before it pushes a configuration back (PROTOCOL.md 8.17).

Take one before changing anything. Writes to this board can only be recovered with a factory reset, which discards every profile and binding. This snapshot is the only record of the current state that can be made from the host.

Every call is a read. Nothing here can damage the device, and the JSON is plain text you can keep or diff.

Global settings

SettingDevice valueNew
Touch optimise-
Dead key down (ms, u16)-
Dead key up (ms, u16)-
Polling rate-
Shake level-
Calibration-
Sports mode-
Current layer-
Eight global settings carried by the 20-byte 0x50/0x5E blob. The field names come from the params_table DDL the app ships inside GameKeyboard.exe, and the widths come from reading that table back out of SQLite (PROTOCOL.md 8.14).

Values are shown as raw device numbers, not decoded. The columns tell us which byte is which, but not what 0 and 1 mean for the switches, nor which polling rate maps to which byte - so the form does not pretend otherwise.

Applying reads the device first and rewrites only the rows you changed; the other six settings and the reserved bytes come from the device unchanged. Every write is read back and reported.

Key map

read-only
The per-key remap table, the same data behind the Windows app's KeySetForm. Records are 3 bytes and the third is a HID usage ID, so entries decode to real key names; anything unmapped stays numeric rather than being guessed.

Writes are not offered: 0x20 and 0x24 are two distinct commands, and both are now decoded byte-for-byte (§8.19, §8.21.3-8.21.4). They stay gated because neither has run against hardware and each replaces a whole layer. The first test must be read → write back byte-identical → read and compare.
compare one read against another
A read alone cannot tell you which keys are remapped: the record carries no changed flag, and a key index is not a HID usage. Read the board, set that as the reference, change something, then read again — the keys that differ are listed.

keyItem is implied by position and never sent; the three wire bytes are type, hValue, lValue (§8.19).

Macros

#KeyActionDelay (ms)
Ten slots, M1–M10, matching the Windows app's macro editor. Each step is one 6-byte record — type, state, lValue, hValue, and a 16-bit little-endian time in milliseconds. The key is a HID usage split across lValue/hValue, and state is 1 for down, 0 for up.

Bytes 0 and 1 are transposed on the wire. This form works in struct order and the driver applies the transposition, so what you see here is what is stored.

The field names come from the key_macro_table DDL that the app ships inside GameKeyboard.exe to persist exactly this data (PROTOCOL.md 8.12).

Fn layer and advanced modifiers

⚠️ Fn-layer writes (0x22/0x25) modify bindings; take a snapshot before changes. 0x23 is not a per-key edit: it is a paged 19-byte bulk write used only by the Windows app's config-import worker, and is not wired here (§8.21.8).
The Windows app's HighKeyForm stores six advanced per-key modifiers here — DKS (Dynamic Key Stroke), MT (Hold/Click), TGL (Toggle), RS (Radial Sensing), SOCD (Simultaneous Opposing Cardinal Directions, with four resolution modes) and OKS (Key Override on Release). They live in these bindings rather than in the plain keymap, so a driver that only exposes keycodes cannot express them.

Every modifier's record code and length are decoded (PROTOCOL.md §8.3.2). The codes do not run in label order: TGL=0, MT=1, DKS=2, RS=3, OKS=4, SOCD=5, while the app lays the dialogs out as DKS, MT, TGL, RS, SOCD, OKS. SOCD is fully specified (key, type, key1, key2, resolution mode); the other modifiers' data bytes are still unnamed, so those stay a raw hex field.

Actuation points

Product table ranges: trigger 10–359, quick-trigger release 4–330, reset 4–330.
⛔ WRITING ACTUATION POINTS IS DISABLED. The decompiled frame builders show 0x26, 0x27 and 0x28 are paged writes. Their record packing is now fully decoded (§8.21.5), so the remaining gate is hardware validation, not missing knowledge — a wrong write can corrupt your layout and is only recoverable by a factory reset. DO NOT ENABLE WRITES without a byte-identical readback test on real hardware. Reads above are safe.

Key selector

Key indices come from the app's keyboard_default_table (556 rows). The grid uses the APEX product record's 85 keys; the index mapping is assumed to be 0..84.

⚠️ Unsafe / Advanced Console

WARNING: This console sends raw frames. REFUSED: Firmware (0x60,0x65,0x66) and unclassified opcodes. DANGEROUS: Actuation (0x26-0x28), calibration (0x53,0x54), transport/config (0x56), keymap (0x20,0x24). Only use if you understand the risks. Gated writes not enabled by default.

Send frame

Response opcode = request + 0x80. Timeout 1 s.

Known opcodes


    

Traffic log

Newest first. → host to device, ← device to host.