libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
hid_keyboard.hpp
1#pragma once
2#include <cstdint>
3#include <cstring>
4
5#include "hid.hpp"
6
7namespace LibXR::USB
8{
9
10// 标准 HID Boot 键盘报告描述符
11// Standard HID Boot keyboard report descriptor.
12static const constexpr uint8_t HID_KEYBOARD_REPORT_DESC[] = {
13 0x05, 0x01, // Usage Page (Generic Desktop)
14 0x09, 0x06, // Usage (Keyboard)
15 0xA1, 0x01, // Collection (Application)
16 0x05, 0x07, // Usage Page (Keyboard/Keypad)
17 0x19, 0xE0, // Usage Minimum (LeftControl)
18 0x29, 0xE7, // Usage Maximum (Right GUI)
19 0x15, 0x00, // Logical Minimum (0)
20 0x25, 0x01, // Logical Maximum (1)
21 0x75, 0x01, // Report Size (1)
22 0x95, 0x08, // Report Count (8)
23 0x81, 0x02, // Input (Data, Variable, Absolute) ; 8 bits: Modifier keys
24 0x95, 0x01, // Report Count (1)
25 0x75, 0x08, // Report Size (8)
26 0x81, 0x03, // Input (Constant, Variable, Absolute) ; 8 bits: Reserved
27 0x95, 0x05, // Report Count (5)
28 0x75, 0x01, // Report Size (1)
29 0x05, 0x08, // Usage Page (LEDs)
30 0x19, 0x01, // Usage Minimum (Num Lock)
31 0x29, 0x05, // Usage Maximum (Kana)
32 0x91, 0x02, // Output (Data, Variable, Absolute) ; 5 bits: LED report
33 0x95, 0x01, // Report Count (1)
34 0x75, 0x03, // Report Size (3)
35 0x91, 0x03, // Output (Constant, Variable, Absolute) ; 3 bits: Padding
36 0x95, 0x06, // Report Count (6)
37 0x75, 0x08, // Report Size (8)
38 0x15, 0x00, // Logical Minimum (0)
39 0x25, 0x65, // Logical Maximum (101)
40 0x05, 0x07, // Usage Page (Keyboard/Keypad)
41 0x19, 0x00, // Usage Minimum (Reserved (no event))
42 0x29, 0x65, // Usage Maximum (Keyboard Application)
43 0x81, 0x00, // Input (Data, Array) ; 6 x KeyCode
44 0xC0 // End Collection
45};
46
53class HIDKeyboard : public HID<sizeof(HID_KEYBOARD_REPORT_DESC), 8, 1>
54{
55 public:
64 HIDKeyboard(bool enable_out_endpoint = false, uint8_t in_ep_interval = 1,
65 uint8_t out_ep_interval = 1,
68 : HID(enable_out_endpoint, in_ep_interval, out_ep_interval, in_ep_num, out_ep_num)
69 {
70 }
71
75 enum Modifier : uint8_t
76 {
77 NONE = 0x00,
78 LEFT_CTRL = 0x01,
79 LEFT_SHIFT = 0x02,
80 LEFT_ALT = 0x04,
81 LEFT_GUI = 0x08,
82 RIGHT_CTRL = 0x10,
83 RIGHT_SHIFT = 0x20,
84 RIGHT_ALT = 0x40,
85 RIGHT_GUI = 0x80
86 };
87
91 enum class KeyCode : uint8_t
92 {
93 NONE = 0x00,
94 ERROR_ROLLOVER = 0x01,
95 POST_FAIL = 0x02,
96 ERROR_UNDEFINED = 0x03,
97
98 // 字母
99 A = 0x04,
100 B = 0x05,
101 C = 0x06,
102 D = 0x07,
103 E = 0x08,
104 F = 0x09,
105 G = 0x0A,
106 H = 0x0B,
107 I = 0x0C,
108 J = 0x0D,
109 K = 0x0E,
110 L = 0x0F,
111 M = 0x10,
112 N = 0x11,
113 O = 0x12,
114 P = 0x13,
115 Q = 0x14,
116 R = 0x15,
117 S = 0x16,
118 T = 0x17,
119 U = 0x18,
120 V = 0x19,
121 W = 0x1A,
122 X = 0x1B,
123 Y = 0x1C,
124 Z = 0x1D,
125
126 // 数字上排
127 NUM_1 = 0x1E,
128 NUM_2 = 0x1F,
129 NUM_3 = 0x20,
130 NUM_4 = 0x21,
131 NUM_5 = 0x22,
132 NUM_6 = 0x23,
133 NUM_7 = 0x24,
134 NUM_8 = 0x25,
135 NUM_9 = 0x26,
136 NUM_0 = 0x27,
137
138 ENTER = 0x28,
139 ESCAPE = 0x29,
140 BACKSPACE = 0x2A,
141 TAB = 0x2B,
142 SPACE = 0x2C,
143 MINUS = 0x2D,
144 EQUAL = 0x2E,
145 LEFT_BRACKET = 0x2F,
146 RIGHT_BRACKET = 0x30,
147 BACKSLASH = 0x31,
148 NON_US_HASH = 0x32,
149 SEMICOLON = 0x33,
150 APOSTROPHE = 0x34,
151 GRAVE = 0x35,
152 COMMA = 0x36,
153 PERIOD = 0x37,
154 SLASH = 0x38,
155 CAPS_LOCK = 0x39,
156
157 // F1-F12
158 F1 = 0x3A,
159 F2 = 0x3B,
160 F3 = 0x3C,
161 F4 = 0x3D,
162 F5 = 0x3E,
163 F6 = 0x3F,
164 F7 = 0x40,
165 F8 = 0x41,
166 F9 = 0x42,
167 F10 = 0x43,
168 F11 = 0x44,
169 F12 = 0x45,
170
171 PRINT_SCREEN = 0x46,
172 SCROLL_LOCK = 0x47,
173 PAUSE = 0x48,
174 INSERT = 0x49,
175 HOME = 0x4A,
176 PAGE_UP = 0x4B,
177 DELETE = 0x4C,
178 END = 0x4D,
179 PAGE_DOWN = 0x4E,
180 RIGHT_ARROW = 0x4F,
181 LEFT_ARROW = 0x50,
182 DOWN_ARROW = 0x51,
183 UP_ARROW = 0x52,
184
185 // 小键盘
186 NUM_LOCK = 0x53,
187 KEYPAD_SLASH = 0x54,
188 KEYPAD_ASTERISK = 0x55,
189 KEYPAD_MINUS = 0x56,
190 KEYPAD_PLUS = 0x57,
191 KEYPAD_ENTER = 0x58,
192 KEYPAD_1 = 0x59,
193 KEYPAD_2 = 0x5A,
194 KEYPAD_3 = 0x5B,
195 KEYPAD_4 = 0x5C,
196 KEYPAD_5 = 0x5D,
197 KEYPAD_6 = 0x5E,
198 KEYPAD_7 = 0x5F,
199 KEYPAD_8 = 0x60,
200 KEYPAD_9 = 0x61,
201 KEYPAD_0 = 0x62,
202 KEYPAD_DOT = 0x63,
203
204 NON_US_BACKSLASH = 0x64,
205 APPLICATION = 0x65,
206 POWER = 0x66,
207 KEYPAD_EQUAL = 0x67,
208
209 F13 = 0x68,
210 F14 = 0x69,
211 F15 = 0x6A,
212 F16 = 0x6B,
213 F17 = 0x6C,
214 F18 = 0x6D,
215 F19 = 0x6E,
216 F20 = 0x6F,
217 F21 = 0x70,
218 F22 = 0x71,
219 F23 = 0x72,
220 F24 = 0x73,
221
222 EXECUTE = 0x74,
223 HELP = 0x75,
224 MENU = 0x76,
225 SELECT = 0x77,
226 STOP = 0x78,
227 AGAIN = 0x79,
228 UNDO = 0x7A,
229 CUT = 0x7B,
230 COPY = 0x7C,
231 PASTE = 0x7D,
232 FIND = 0x7E,
233 MUTE = 0x7F,
234 VOLUME_UP = 0x80,
235 VOLUME_DOWN = 0x81,
236 LOCKING_CAPS_LOCK = 0x82,
237 LOCKING_NUM_LOCK = 0x83,
238 LOCKING_SCROLL_LOCK = 0x84,
239 KEYPAD_COMMA = 0x85,
240 KEYPAD_EQUAL_SIGN = 0x86,
241
242 INTERNATIONAL1 = 0x87,
243 INTERNATIONAL2 = 0x88,
244 INTERNATIONAL3 = 0x89,
245 INTERNATIONAL4 = 0x8A,
246 INTERNATIONAL5 = 0x8B,
247 INTERNATIONAL6 = 0x8C,
248 INTERNATIONAL7 = 0x8D,
249 INTERNATIONAL8 = 0x8E,
250 INTERNATIONAL9 = 0x8F,
251
252 LANG1 = 0x90,
253 LANG2 = 0x91,
254 LANG3 = 0x92,
255 LANG4 = 0x93,
256 LANG5 = 0x94,
257 LANG6 = 0x95,
258 LANG7 = 0x96,
259 LANG8 = 0x97,
260 LANG9 = 0x98,
261
262 ALTERNATE_ERASE = 0x99,
263 SYSREQ_ATTENTION = 0x9A,
264 CANCEL = 0x9B,
265 CLEAR = 0x9C,
266 PRIOR = 0x9D,
267 RETURN = 0x9E,
268 SEPARATOR = 0x9F,
269 OUT = 0xA0,
270 OPER = 0xA1,
271 CLEAR_AGAIN = 0xA2,
272 CRSEL_PROPS = 0xA3,
273 EXSEL = 0xA4,
274
275 // 0xA5~0xDF RESERVED, skip explicit
276 RESERVED_A5 = 0xA5,
277 RESERVED_A6 = 0xA6,
278 RESERVED_A7 = 0xA7,
279 RESERVED_A8 = 0xA8,
280 RESERVED_A9 = 0xA9,
281 RESERVED_AA = 0xAA,
282 RESERVED_AB = 0xAB,
283 RESERVED_AC = 0xAC,
284 RESERVED_AD = 0xAD,
285 RESERVED_AE = 0xAE,
286 RESERVED_AF = 0xAF,
287 RESERVED_B0 = 0xB0,
288 RESERVED_B1 = 0xB1,
289 RESERVED_B2 = 0xB2,
290 RESERVED_B3 = 0xB3,
291 RESERVED_B4 = 0xB4,
292 RESERVED_B5 = 0xB5,
293 RESERVED_B6 = 0xB6,
294 RESERVED_B7 = 0xB7,
295 RESERVED_B8 = 0xB8,
296 RESERVED_B9 = 0xB9,
297 RESERVED_BA = 0xBA,
298 RESERVED_BB = 0xBB,
299 RESERVED_BC = 0xBC,
300 RESERVED_BD = 0xBD,
301 RESERVED_BE = 0xBE,
302 RESERVED_BF = 0xBF,
303 RESERVED_C0 = 0xC0,
304 RESERVED_C1 = 0xC1,
305 RESERVED_C2 = 0xC2,
306 RESERVED_C3 = 0xC3,
307 RESERVED_C4 = 0xC4,
308 RESERVED_C5 = 0xC5,
309 RESERVED_C6 = 0xC6,
310 RESERVED_C7 = 0xC7,
311 RESERVED_C8 = 0xC8,
312 RESERVED_C9 = 0xC9,
313 RESERVED_CA = 0xCA,
314 RESERVED_CB = 0xCB,
315 RESERVED_CC = 0xCC,
316 RESERVED_CD = 0xCD,
317 RESERVED_CE = 0xCE,
318 RESERVED_CF = 0xCF,
319 RESERVED_D0 = 0xD0,
320 RESERVED_D1 = 0xD1,
321 RESERVED_D2 = 0xD2,
322 RESERVED_D3 = 0xD3,
323 RESERVED_D4 = 0xD4,
324 RESERVED_D5 = 0xD5,
325 RESERVED_D6 = 0xD6,
326 RESERVED_D7 = 0xD7,
327 RESERVED_D8 = 0xD8,
328 RESERVED_D9 = 0xD9,
329 RESERVED_DA = 0xDA,
330 RESERVED_DB = 0xDB,
331 RESERVED_DC = 0xDC,
332 RESERVED_DD = 0xDD,
333 RESERVED_DE = 0xDE,
334 RESERVED_DF = 0xDF,
335
336 // 修饰键
337 LEFT_CONTROL = 0xE0,
338 LEFT_SHIFT = 0xE1,
339 LEFT_ALT = 0xE2,
340 LEFT_GUI = 0xE3,
341 RIGHT_CONTROL = 0xE4,
342 RIGHT_SHIFT = 0xE5,
343 RIGHT_ALT = 0xE6,
344 RIGHT_GUI = 0xE7
345 // 0xE8~0xFF 保留
346 };
347
351 struct Report
352 {
353 uint8_t modifiers;
354 uint8_t reserved;
355 uint8_t keys[6];
356 };
357
364 void PressKey(std::initializer_list<KeyCode> keys, uint8_t mods = Modifier::NONE)
365 {
366 ASSERT(keys.size() <= 6);
367 report_ = {static_cast<uint8_t>(mods), 0, {0}};
368 size_t i = 0;
369 for (auto k : keys)
370 {
371 report_.keys[i++] = static_cast<uint8_t>(k);
372 }
374 }
375
380 {
381 Report report = {0, 0, {0}};
382 SendInputReport(ConstRawData{&report, sizeof(report)});
383 }
384
385 protected:
391 ErrorCode WriteDeviceDescriptor(DeviceDescriptor& header) override
392 {
394 header.data_.bDeviceSubClass = 1;
395 header.data_.bDeviceProtocol = 1;
396 return ErrorCode::OK;
397 }
398
404 {
405 return ConstRawData{HID_KEYBOARD_REPORT_DESC, sizeof(HID_KEYBOARD_REPORT_DESC)};
406 }
407
413 void OnDataOutComplete(bool in_isr, ConstRawData& data) override
414 {
415 if (data.size_ >= 1)
416 {
417 led_state_ = *(static_cast<const uint8_t*>(data.addr_));
419 }
420 }
421
428 ErrorCode OnSetReport(uint8_t report_id, DeviceClass::RequestResult& result) override
429 {
430 UNUSED(report_id);
431 UNUSED(result);
432
433 result.read_data = {&led_state_, 1};
434 return ErrorCode::OK;
435 }
436
443 ErrorCode OnSetReportData(bool in_isr, ConstRawData& data) override
444 {
445 if (data.size_ >= 1)
446 {
448 return ErrorCode::OK;
449 }
450
451 return ErrorCode::NOT_SUPPORT;
452 }
453
454 public:
459 bool GetNumLock() { return (led_state_ & 0x04) != 0; }
460
465 bool GetCapsLock() { return (led_state_ & 0x02) != 0; }
466
471 bool GetScrollLock() { return (led_state_ & 0x01) != 0; }
472
482
483 private:
484 uint8_t led_state_ = 0;
488};
489
490} // namespace LibXR::USB
提供一个通用的回调包装,支持动态参数传递。 Provides a generic callback wrapper, supporting dynamic argument passing.
Definition libxr_cb.hpp:124
void Run(bool in_isr, PassArgs &&...args) const
执行回调函数,并传递参数。 Executes the callback function, passing the arguments.
Definition libxr_cb.hpp:207
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
USB描述符基类 USB descriptor base class.
Definition desc_dev.hpp:37
Data data_
设备描述符数据实例 / Internal data instance
Definition desc_dev.hpp:106
@ HID
人机接口类 / Human Interface Device
EPNumber
端点号 / Endpoint number
Definition ep.hpp:39
@ EP_AUTO
自动分配端点号 / Auto allocate
USB HID(Human Interface Device)基类,支持可选 OUT 端点、自动生成描述符,适合键盘、鼠标、手柄等扩展。 USB HID (Human Interface Device)...
Definition hid.hpp:23
ErrorCode SendInputReport(ConstRawData report)
Definition hid.hpp:560
标准 USB HID 键盘派生类 Standard USB HID Keyboard derived class
void PressKey(std::initializer_list< KeyCode > keys, uint8_t mods=Modifier::NONE)
按下指定按键 / Press the specified key(s)
uint8_t led_state_
LED 状态/ LED state.
bool GetNumLock()
获取 NumLock 状态 / Get NumLock status
bool GetScrollLock()
获取 ScrollLock 状态 / Get ScrollLock status
void SetOnLedChangeCallback(LibXR::Callback< bool, bool, bool > cb)
设置 LED 状态变化回调 / Set LED state change callback
ErrorCode OnSetReportData(bool in_isr, ConstRawData &data) override
处理 SET_REPORT 数据阶段 / Handle SET_REPORT data stage
void OnDataOutComplete(bool in_isr, ConstRawData &data) override
OUT 端点回调,处理 LED 状态 / OUT endpoint callback, handle LED status.
Modifier
修饰键枚举 Modifier enum
@ LEFT_CTRL
左 Ctrl / Left Control
@ LEFT_SHIFT
左 Shift / Left Shift
@ RIGHT_ALT
右 Alt / Right Alt
@ LEFT_GUI
左 GUI / Left GUI (Win/Command)
@ LEFT_ALT
左 Alt / Left Alt
@ RIGHT_GUI
右 GUI / Right GUI
@ NONE
无修饰键 / No modifier
@ RIGHT_CTRL
右 Ctrl / Right Control
@ RIGHT_SHIFT
右 Shift / Right Shift
ErrorCode OnSetReport(uint8_t report_id, DeviceClass::RequestResult &result) override
处理 SET_REPORT 请求 / Handle SET_REPORT request
ErrorCode WriteDeviceDescriptor(DeviceDescriptor &header) override
写入设备描述符 / Write device descriptor
bool GetCapsLock()
获取 CapsLock 状态 / Get CapsLock status
KeyCode
按键代码枚举 / KeyCode enum
@ APPLICATION
Application (Menu)
@ ERROR_UNDEFINED
未定义 / ErrorUndefined
@ POST_FAIL
POST 失败 / POSTFail.
@ ERROR_ROLLOVER
错误溢出 / ErrorRollOver
HIDKeyboard(bool enable_out_endpoint=false, uint8_t in_ep_interval=1, uint8_t out_ep_interval=1, Endpoint::EPNumber in_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber out_ep_num=Endpoint::EPNumber::EP_AUTO)
构造函数 / Constructor
void ReleaseAll()
释放所有按键 / Release all keys
ConstRawData GetReportDesc() override
获取报告描述符 / Get Report Descriptor
Report report_
当前输入报告 / Current input report
LibXR::Callback< bool, bool, bool > on_led_change_cb_
LED 状态变化回调 / LED state change callback.
控制请求结果结构体 / Structure for control transfer results
Definition dev_core.hpp:28
RawData read_data
设备返回给主机的数据 / Data to read (to host)
Definition dev_core.hpp:29
ClassID bDeviceClass
设备类代码 / Device class code
Definition desc_dev.hpp:90
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
Definition desc_dev.hpp:91
uint8_t bDeviceProtocol
协议代码 / Protocol code
Definition desc_dev.hpp:92
输入报告结构体 / Keyboard input report struct
uint8_t keys[6]
最多 6 个按键 / Up to 6 keys
uint8_t modifiers
修饰键 / Modifier
uint8_t reserved
保留 / Reserved