Add the ITPROTECH MK series (8808) as a third pad family

Confirmed on the MK-09 (8808:660a, 9 keys): the vendor's .NET configurator
was decompiled for the wire format and every frame was then written to a
real pad and read back. Keys, media keys and multikey sequences are
supported; lighting from the command line.

The firmware acts on every other output report, so each report is sent
twice (as the vendor software does) and every write is verified by reading
the key back. The app now keeps one state file per pad and starts with a
known layout for a known USB id, and the editor asks the backend whether a
binding fits before offering to write it. The actions listener and the
udev rule cover every supported vendor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 19:24:30 +02:00
parent 2b75543c74
commit 80c6a5da1c
17 changed files with 1085 additions and 23 deletions

View File

@@ -0,0 +1,71 @@
# The ITPROTECH MK series protocol
The ITPROTECH ちょい足しキーボード pads (USB vendor id `8808`) are a different
family from the CH57x pads: different chip, different configurator, different
wire format. This is what an MK-09 (`8808:660a`, 9 keys) speaks. The code is in
`macropad_gui/backends/itprotech_proto.py` and `itprotech.py`.
## How it was worked out
The vendor's configurator (`mk_series_software.zip` from itprotech.jp,
`Run-me.exe`) is a .NET program, so it decompiles cleanly. Its device code
lists product ids `6600` to `6618` and one form per model; the 9 key form
builds exactly the reports below. Everything was then checked against a real
MK-09 by reading it, writing each kind of binding to key 9, and reading it
back. The responses in `tests/test_itprotech.py` are those real bytes.
## Interfaces
The pad has four HID interfaces. The first two are a boot keyboard and a boot
mouse; the third carries an NKRO keyboard, consumer control and a second
vendor page (`0xFFA0`) the configurator never uses. The fourth is the config
channel: usage page `0xFF00`, 64 byte input and output reports, **no report
id**, so a write to `/dev/hidraw` is `00` followed by 64 bytes.
## Reports
Every report, both directions, is `len payload...` zero padded to 64 bytes.
| Host sends | Meaning |
|---|---|
| `01 55` | Read. The pad answers one report per key, then `02 63 <mode>`, then `04 64 <g> <r> <b>`. |
| `0d <key> <type> ...` | Bind one key. `0d` (13) is the record length on the 9 key model; the 12 key model uses `0a`, the 8 key `0f`, and so on. The record is read off the pad before writing. |
| `02 57 <mode>` | Lighting mode 0 to 14. |
| `04 70 <g> <r> <b>` | Custom colour for mode 14. Green first. |
| `01 56` | **Firmware bootloader. Never sent by this app; `frame()` refuses it.** |
Key types:
| Type | Record | |
|---|---|---|
| `01` | `<mods> <keycode>` | keyboard; mods is the HID modifier byte |
| `02` | `<buttons> <x> <y> <wheel>` | mouse, not offered by the app |
| `03` | `04 <lo> <hi> 00` | consumer page usage, little endian |
| `04` | `<mods> <k1> ... <k10>` | several keys in a row, one modifier byte for all |
| `ff` | | a slot the vendor software never wrote |
Examples that were written to the pad and read back identically:
```
0d 09 01 00 10 key 9 -> m
0d 09 03 04 e9 00 00 key 9 -> volume up
0d 09 04 00 0b 08 0f 0f 12 key 9 -> h e l l o
```
## The every-other-report rule
The firmware acts on every **second** output report it receives, whatever the
command. Send a read once and you may get silence; send it again and the dump
arrives. The vendor software sends every command twice, 20 ms apart, which
is why it works, and so does this backend (`REPEAT = 2`). A write is then
confirmed by reading the key back; a pad that holds something else makes the
write fail loudly rather than being believed.
Reading never changes anything. There are no layers, no commit command, and
the bindings are in the pad's flash as soon as the write is accepted.
## Lighting modes
0 off, 1 flow 1, 2 to 8 light on press in red, green, blue, yellow, cyan,
purple, white, 9 flow 2, 10 flow 3, 11 irradiation, 12 colourful gradient,
13 table lamp, 14 custom colour.