-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathxzkj.py
More file actions
100 lines (81 loc) · 3.79 KB
/
Copy pathxzkj.py
File metadata and controls
100 lines (81 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python3
"""
Protokollbibliotek for XZKJ-makropad (VID 0x514C, PID 0x8850).
Protokoll (reverse-engineeret, jf. kriomant/ch57x-keyboard-tool issue #153):
65-byte HID output-rapporter på vendor-grensesnittet (usage page 0xFF00).
Tastebinding (type 0x01 = tastatur):
[0x03, 0xFD, key_id, layer, 0x01, 0x00, count,
(delay_hi, delay_lo, hid_code) * count, ... 0-padding til 65]
Modifikatorer er egne koder i sekvensen og gjelder neste vanlige tast:
0xF1 LCtrl 0xF2 LShift 0xF3 LAlt 0xF4 LMeta(Cmd)
0xF5 RCtrl 0xF6 RShift 0xF7 RAlt 0xF8 RMeta
"""
import time
import hid
VID, PID = 0x514C, 0x8850
REPORT_LEN = 65 # inkl. report-ID 0x03
MODIFIERS = {
"lctrl": 0xF1, "ctrl": 0xF1,
"lshift": 0xF2, "shift": 0xF2,
"lalt": 0xF3, "alt": 0xF3, "opt": 0xF3, "option": 0xF3,
"lmeta": 0xF4, "meta": 0xF4, "cmd": 0xF4, "win": 0xF4,
"rctrl": 0xF5, "rshift": 0xF6, "ralt": 0xF7, "rmeta": 0xF8, "rcmd": 0xF8,
}
# HID Usage IDs (Keyboard/Keypad page)
HID_CODES = {
**{chr(ord('a') + i): 0x04 + i for i in range(26)},
**{str(d): 0x1E + d - 1 for d in range(1, 10)},
"0": 0x27,
"enter": 0x28, "esc": 0x29, "backspace": 0x2A, "tab": 0x2B, "space": 0x2C,
"minus": 0x2D, "equal": 0x2E, "lbracket": 0x2F, "rbracket": 0x30,
"backslash": 0x31, "semicolon": 0x33, "quote": 0x34, "grave": 0x35,
"comma": 0x36, "dot": 0x37, "slash": 0x38, "capslock": 0x39,
**{f"f{i}": 0x3A + i - 1 for i in range(1, 13)},
**{f"f{i}": 0x68 + i - 13 for i in range(13, 25)},
"printscreen": 0x46, "scrolllock": 0x47, "pause": 0x48,
"insert": 0x49, "home": 0x4A, "pageup": 0x4B,
"delete": 0x4C, "end": 0x4D, "pagedown": 0x4E,
"right": 0x4F, "left": 0x50, "down": 0x51, "up": 0x52,
# Media via keyboard usage page — verifisert på denne enheten:
"mute": 0x7F, "volumeup": 0x80, "volumedown": 0x81,
}
# Media/consumer-koder (type 0x02, jf. k884x: 16-bit little-endian)
MEDIA_CODES = {
"play": 0xCD, "playpause": 0xCD, "next": 0xB5, "prev": 0xB6, "stop": 0xB7,
"mute": 0xE2, "volumeup": 0xE9, "volumedown": 0xEA,
"brightnessup": 0x6F, "brightnessdown": 0x70,
"calculator": 0x192, "browser": 0x196, "mail": 0x18A,
}
def open_vendor_interface():
devs = [d for d in hid.enumerate(VID, PID) if d["usage_page"] == 0xFF00]
if not devs:
raise RuntimeError("Fant ikke vendor-grensesnittet (0xFF00). Er tastaturet koblet til?")
h = hid.device()
h.open_path(devs[0]["path"])
return h
def _send(h, msg: bytes):
buf = bytearray(REPORT_LEN)
buf[: len(msg)] = msg
n = h.write(bytes(buf))
if n not in (REPORT_LEN, REPORT_LEN - 1):
raise RuntimeError(f"Kort skriving: {n} byte")
time.sleep(0.02)
def bind_key_sequence(h, key_id: int, entries, layer: int = 1):
"""entries: liste av (delay_ms, hid_code). Maks 18."""
assert 1 <= len(entries) <= 18, "1–18 tastetrykk per binding"
msg = bytearray([0x03, 0xFD, key_id, layer, 0x01, 0x00, len(entries)])
for delay_ms, code in entries:
msg += bytes([(delay_ms >> 8) & 0xFF, delay_ms & 0xFF, code])
_send(h, bytes(msg))
def bind_media(h, key_id: int, media_code: int, layer: int = 1):
"""Media/consumer-binding (type 0x02) — antatt lik k884x, verifiseres."""
lo, hi = media_code & 0xFF, (media_code >> 8) & 0xFF
_send(h, bytes([0x03, 0xFD, key_id, layer, 0x02, 0x00, 0x00, lo, hi]))
def bind_mouse_click(h, key_id: int, buttons: int = 1, layer: int = 1):
"""Mus-binding (type 0x03), buttons bitmask: 1=venstre 2=høyre 4=midt."""
_send(h, bytes([0x03, 0xFD, key_id, layer, 0x03, 0x00, 0x01, 0x00, buttons]))
def finish(h):
"""Avslutt programmeringssekvens (rammeverk fra k884x — verifiseres for 8850)."""
_send(h, bytes([0x03, 0xAA, 0xAA]))
_send(h, bytes([0x03, 0xFD, 0xFE, 0xFF]))
_send(h, bytes([0x03, 0xAA, 0xAA]))