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:
@@ -26,6 +26,8 @@ A pad from a different family fails one of those, and the app leaves it alone ra
|
||||
|
||||
The pad reports how many keys and knobs it has, but not how they're arranged, so the first guess at rows and columns may be wrong. Fix it with [Edit layout](#-if-the-drawing-doesnt-match-your-pad) and the drawing will match your hardware.
|
||||
|
||||
The same button works for the ITPROTECH pads (vendor id `8808`): the app asks the pad for its key records and adopts it if they come back cleanly.
|
||||
|
||||
## If it doesn't answer
|
||||
|
||||
Some pads in this family speak an older protocol and won't answer. Working those out needs a capture of the vendor software, the same process used for this one. You'll need `MINI_KEYBOARD.exe` and Wine.
|
||||
|
||||
71
docs/protocol-itprotech.md
Normal file
71
docs/protocol-itprotech.md
Normal 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.
|
||||
Reference in New Issue
Block a user