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

@@ -501,8 +501,13 @@ def _descriptor_keyboard_report_id(raw):
return False, 0
def find_keyboard_nodes(vid=core.VID):
"""[(hidraw path, keyboard report id)] for every pad keyboard interface."""
def find_keyboard_nodes(vid=None):
"""
[(hidraw path, keyboard report id)] for every pad keyboard interface.
vid narrows it to one vendor; the default is every family we support.
"""
want = {vid.lower()} if vid else core.vendors()
out = []
for node in sorted(glob.glob("/sys/class/hidraw/hidraw*")):
dev = os.path.join(node, "device")
@@ -513,7 +518,7 @@ def find_keyboard_nodes(vid=core.VID):
continue
hid_id = next((l.split("=", 1)[1] for l in uevent.splitlines()
if l.startswith("HID_ID=")), "")
if hid_id.count(":") != 2 or hid_id.split(":")[1][-4:].lower() != vid:
if hid_id.count(":") != 2 or hid_id.split(":")[1][-4:].lower() not in want:
continue
is_kbd, rid = _descriptor_keyboard_report_id(raw)
if is_kbd: