Skip to content

Commit 3765d04

Browse files
committed
usbd: Add hid keypad example from @turmoni .
As contributed in projectgus#1 commit 5c51a9e This version of the hidkeypad module depends on some other code changes from the linked PR that aren't included here, so it won't work here yet.
1 parent 92711ea commit 3765d04

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

Diff for: micropython/usbd/hidkeypad.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# MicroPython USB keypad module
2+
# MIT license; Copyright (c) 2023 Dave Wickham
3+
4+
from .hid import HIDInterface
5+
from .keycodes import KEYPAD_KEYS_TO_KEYCODES
6+
from .utils import STAGE_SETUP, split_bmRequestType
7+
from micropython import const
8+
import micropython
9+
10+
_INTERFACE_PROTOCOL_KEYBOARD = const(0x01)
11+
_REQ_CONTROL_SET_REPORT = const(0x09)
12+
_REQ_CONTROL_SET_IDLE = const(0x0A)
13+
14+
# fmt: off
15+
_KEYPAD_REPORT_DESC = bytes(
16+
[
17+
0x05, 0x01, # Usage Page (Generic Desktop)
18+
0x09, 0x07, # Usage (Keypad)
19+
0xA1, 0x01, # Collection (Application)
20+
0x05, 0x07, # Usage Page (Keypad)
21+
0x19, 0x00, # Usage Minimum (00),
22+
0x29, 0xFF, # Usage Maximum (ff),
23+
0x15, 0x00, # Logical Minimum (0),
24+
0x25, 0xFF, # Logical Maximum (ff),
25+
0x95, 0x01, # Report Count (1),
26+
0x75, 0x08, # Report Size (8),
27+
0x81, 0x00, # Input (Data, Array, Absolute)
28+
0x05, 0x08, # Usage page (LEDs)
29+
0x19, 0x01, # Usage minimum (1)
30+
0x29, 0x05, # Usage Maximum (5),
31+
0x95, 0x05, # Report Count (5),
32+
0x75, 0x01, # Report Size (1),
33+
0x91, 0x02, # Output (Data, Variable, Absolute)
34+
0x95, 0x01, # Report Count (1),
35+
0x75, 0x03, # Report Size (3),
36+
0x91, 0x01, # Output (Constant)
37+
0xC0, # End Collection
38+
]
39+
)
40+
# fmt: on
41+
42+
43+
class KeypadInterface(HIDInterface):
44+
# Very basic synchronous USB keypad HID interface
45+
46+
def __init__(self):
47+
self.numlock = None
48+
self.capslock = None
49+
self.scrolllock = None
50+
self.compose = None
51+
self.kana = None
52+
self.set_report_initialised = False
53+
super().__init__(
54+
_KEYPAD_REPORT_DESC,
55+
protocol=_INTERFACE_PROTOCOL_KEYBOARD,
56+
interface_str="MicroPython Keypad!",
57+
use_out_ep=True,
58+
)
59+
60+
def handle_interface_control_xfer(self, stage, request):
61+
if request[1] == _REQ_CONTROL_SET_IDLE and not self.set_report_initialised:
62+
# Hacky initialisation goes here
63+
self.set_report()
64+
self.set_report_initialised = True
65+
66+
if stage == STAGE_SETUP:
67+
return super().handle_interface_control_xfer(stage, request)
68+
69+
bmRequestType, bRequest, wValue, _, _ = request
70+
recipient, req_type, _ = split_bmRequestType(bmRequestType)
71+
72+
return True
73+
74+
def set_report(self, args=None):
75+
self.out_buffer = bytearray(1)
76+
self.submit_xfer(self._out_ep, self.out_buffer, self.set_report_cb)
77+
return True
78+
79+
def set_report_cb(self, ep_addr, result, xferred_bytes):
80+
buf_result = int(self.out_buffer[0])
81+
self.numlock = buf_result & 1
82+
self.capslock = (buf_result >> 1) & 1
83+
self.scrolllock = (buf_result >> 2) & 1
84+
self.compose = (buf_result >> 3) & 1
85+
self.kana = (buf_result >> 4) & 1
86+
87+
micropython.schedule(self.set_report, None)
88+
89+
def send_report(self, key=None):
90+
if key is None:
91+
super().send_report(bytes(1))
92+
else:
93+
super().send_report(KEYPAD_KEYS_TO_KEYCODES[key].to_bytes(1, "big"))

Diff for: micropython/usbd/keycodes.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Keypad keycodes for use with USB HID
2+
# MIT license; Copyright (c) 2023 Dave Wickham
3+
_KEYPAD_KEYS = [
4+
"<NumLock>",
5+
"/",
6+
"*",
7+
"-",
8+
"+",
9+
"<Enter>",
10+
"1",
11+
"2",
12+
"3",
13+
"4",
14+
"5",
15+
"6",
16+
"7",
17+
"8",
18+
"9",
19+
"0",
20+
".",
21+
]
22+
23+
KEYPAD_KEYCODES_TO_KEYS = {k + 0x53: v for k, v in enumerate(_KEYPAD_KEYS)}
24+
KEYPAD_KEYS_TO_KEYCODES = {v: k for k, v in KEYPAD_KEYCODES_TO_KEYS.items()}

0 commit comments

Comments
 (0)