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:
65 HIDKeyboard(bool enable_out_endpoint = false, uint8_t in_ep_interval = 1,
66 uint8_t out_ep_interval = 1,
69 const char* interface_string =
70 HID<sizeof(HID_KEYBOARD_REPORT_DESC), 8, 1>::DEFAULT_INTERFACE_STRING)
71 : HID(enable_out_endpoint, in_ep_interval, out_ep_interval, in_ep_num, out_ep_num,
72 interface_string)
73 {
74 }
75
79 enum Modifier : uint8_t
80 {
81 NONE = 0x00,
82 LEFT_CTRL = 0x01,
83 LEFT_SHIFT = 0x02,
84 LEFT_ALT = 0x04,
85 LEFT_GUI = 0x08,
86 RIGHT_CTRL = 0x10,
87 RIGHT_SHIFT = 0x20,
88 RIGHT_ALT = 0x40,
89 RIGHT_GUI = 0x80
90 };
91
95 enum class KeyCode : uint8_t
96 {
97 NONE = 0x00,
98 ERROR_ROLLOVER = 0x01,
99 POST_FAIL = 0x02,
100 ERROR_UNDEFINED = 0x03,
101
102 // 字母
103 A = 0x04,
104 B = 0x05,
105 C = 0x06,
106 D = 0x07,
107 E = 0x08,
108 F = 0x09,
109 G = 0x0A,
110 H = 0x0B,
111 I = 0x0C,
112 J = 0x0D,
113 K = 0x0E,
114 L = 0x0F,
115 M = 0x10,
116 N = 0x11,
117 O = 0x12,
118 P = 0x13,
119 Q = 0x14,
120 R = 0x15,
121 S = 0x16,
122 T = 0x17,
123 U = 0x18,
124 V = 0x19,
125 W = 0x1A,
126 X = 0x1B,
127 Y = 0x1C,
128 Z = 0x1D,
129
130 // 数字上排
131 NUM_1 = 0x1E,
132 NUM_2 = 0x1F,
133 NUM_3 = 0x20,
134 NUM_4 = 0x21,
135 NUM_5 = 0x22,
136 NUM_6 = 0x23,
137 NUM_7 = 0x24,
138 NUM_8 = 0x25,
139 NUM_9 = 0x26,
140 NUM_0 = 0x27,
141
142 ENTER = 0x28,
143 ESCAPE = 0x29,
144 BACKSPACE = 0x2A,
145 TAB = 0x2B,
146 SPACE = 0x2C,
147 MINUS = 0x2D,
148 EQUAL = 0x2E,
149 LEFT_BRACKET = 0x2F,
150 RIGHT_BRACKET = 0x30,
151 BACKSLASH = 0x31,
152 NON_US_HASH = 0x32,
153 SEMICOLON = 0x33,
154 APOSTROPHE = 0x34,
155 GRAVE = 0x35,
156 COMMA = 0x36,
157 PERIOD = 0x37,
158 SLASH = 0x38,
159 CAPS_LOCK = 0x39,
160
161 // F1-F12
162 F1 = 0x3A,
163 F2 = 0x3B,
164 F3 = 0x3C,
165 F4 = 0x3D,
166 F5 = 0x3E,
167 F6 = 0x3F,
168 F7 = 0x40,
169 F8 = 0x41,
170 F9 = 0x42,
171 F10 = 0x43,
172 F11 = 0x44,
173 F12 = 0x45,
174
175 PRINT_SCREEN = 0x46,
176 SCROLL_LOCK = 0x47,
177 PAUSE = 0x48,
178 INSERT = 0x49,
179 HOME = 0x4A,
180 PAGE_UP = 0x4B,
181 DELETE = 0x4C,
182 END = 0x4D,
183 PAGE_DOWN = 0x4E,
184 RIGHT_ARROW = 0x4F,
185 LEFT_ARROW = 0x50,
186 DOWN_ARROW = 0x51,
187 UP_ARROW = 0x52,
188
189 // 小键盘
190 NUM_LOCK = 0x53,
191 KEYPAD_SLASH = 0x54,
192 KEYPAD_ASTERISK = 0x55,
193 KEYPAD_MINUS = 0x56,
194 KEYPAD_PLUS = 0x57,
195 KEYPAD_ENTER = 0x58,
196 KEYPAD_1 = 0x59,
197 KEYPAD_2 = 0x5A,
198 KEYPAD_3 = 0x5B,
199 KEYPAD_4 = 0x5C,
200 KEYPAD_5 = 0x5D,
201 KEYPAD_6 = 0x5E,
202 KEYPAD_7 = 0x5F,
203 KEYPAD_8 = 0x60,
204 KEYPAD_9 = 0x61,
205 KEYPAD_0 = 0x62,
206 KEYPAD_DOT = 0x63,
207
208 NON_US_BACKSLASH = 0x64,
209 APPLICATION = 0x65,
210 POWER = 0x66,
211 KEYPAD_EQUAL = 0x67,
212
213 F13 = 0x68,
214 F14 = 0x69,
215 F15 = 0x6A,
216 F16 = 0x6B,
217 F17 = 0x6C,
218 F18 = 0x6D,
219 F19 = 0x6E,
220 F20 = 0x6F,
221 F21 = 0x70,
222 F22 = 0x71,
223 F23 = 0x72,
224 F24 = 0x73,
225
226 EXECUTE = 0x74,
227 HELP = 0x75,
228 MENU = 0x76,
229 SELECT = 0x77,
230 STOP = 0x78,
231 AGAIN = 0x79,
232 UNDO = 0x7A,
233 CUT = 0x7B,
234 COPY = 0x7C,
235 PASTE = 0x7D,
236 FIND = 0x7E,
237 MUTE = 0x7F,
238 VOLUME_UP = 0x80,
239 VOLUME_DOWN = 0x81,
240 LOCKING_CAPS_LOCK = 0x82,
241 LOCKING_NUM_LOCK = 0x83,
242 LOCKING_SCROLL_LOCK = 0x84,
243 KEYPAD_COMMA = 0x85,
244 KEYPAD_EQUAL_SIGN = 0x86,
245
246 INTERNATIONAL1 = 0x87,
247 INTERNATIONAL2 = 0x88,
248 INTERNATIONAL3 = 0x89,
249 INTERNATIONAL4 = 0x8A,
250 INTERNATIONAL5 = 0x8B,
251 INTERNATIONAL6 = 0x8C,
252 INTERNATIONAL7 = 0x8D,
253 INTERNATIONAL8 = 0x8E,
254 INTERNATIONAL9 = 0x8F,
255
256 LANG1 = 0x90,
257 LANG2 = 0x91,
258 LANG3 = 0x92,
259 LANG4 = 0x93,
260 LANG5 = 0x94,
261 LANG6 = 0x95,
262 LANG7 = 0x96,
263 LANG8 = 0x97,
264 LANG9 = 0x98,
265
266 ALTERNATE_ERASE = 0x99,
267 SYSREQ_ATTENTION = 0x9A,
268 CANCEL = 0x9B,
269 CLEAR = 0x9C,
270 PRIOR = 0x9D,
271 RETURN = 0x9E,
272 SEPARATOR = 0x9F,
273 OUT = 0xA0,
274 OPER = 0xA1,
275 CLEAR_AGAIN = 0xA2,
276 CRSEL_PROPS = 0xA3,
277 EXSEL = 0xA4,
278
279 // 0xA5~0xDF RESERVED, skip explicit
280 RESERVED_A5 = 0xA5,
281 RESERVED_A6 = 0xA6,
282 RESERVED_A7 = 0xA7,
283 RESERVED_A8 = 0xA8,
284 RESERVED_A9 = 0xA9,
285 RESERVED_AA = 0xAA,
286 RESERVED_AB = 0xAB,
287 RESERVED_AC = 0xAC,
288 RESERVED_AD = 0xAD,
289 RESERVED_AE = 0xAE,
290 RESERVED_AF = 0xAF,
291 RESERVED_B0 = 0xB0,
292 RESERVED_B1 = 0xB1,
293 RESERVED_B2 = 0xB2,
294 RESERVED_B3 = 0xB3,
295 RESERVED_B4 = 0xB4,
296 RESERVED_B5 = 0xB5,
297 RESERVED_B6 = 0xB6,
298 RESERVED_B7 = 0xB7,
299 RESERVED_B8 = 0xB8,
300 RESERVED_B9 = 0xB9,
301 RESERVED_BA = 0xBA,
302 RESERVED_BB = 0xBB,
303 RESERVED_BC = 0xBC,
304 RESERVED_BD = 0xBD,
305 RESERVED_BE = 0xBE,
306 RESERVED_BF = 0xBF,
307 RESERVED_C0 = 0xC0,
308 RESERVED_C1 = 0xC1,
309 RESERVED_C2 = 0xC2,
310 RESERVED_C3 = 0xC3,
311 RESERVED_C4 = 0xC4,
312 RESERVED_C5 = 0xC5,
313 RESERVED_C6 = 0xC6,
314 RESERVED_C7 = 0xC7,
315 RESERVED_C8 = 0xC8,
316 RESERVED_C9 = 0xC9,
317 RESERVED_CA = 0xCA,
318 RESERVED_CB = 0xCB,
319 RESERVED_CC = 0xCC,
320 RESERVED_CD = 0xCD,
321 RESERVED_CE = 0xCE,
322 RESERVED_CF = 0xCF,
323 RESERVED_D0 = 0xD0,
324 RESERVED_D1 = 0xD1,
325 RESERVED_D2 = 0xD2,
326 RESERVED_D3 = 0xD3,
327 RESERVED_D4 = 0xD4,
328 RESERVED_D5 = 0xD5,
329 RESERVED_D6 = 0xD6,
330 RESERVED_D7 = 0xD7,
331 RESERVED_D8 = 0xD8,
332 RESERVED_D9 = 0xD9,
333 RESERVED_DA = 0xDA,
334 RESERVED_DB = 0xDB,
335 RESERVED_DC = 0xDC,
336 RESERVED_DD = 0xDD,
337 RESERVED_DE = 0xDE,
338 RESERVED_DF = 0xDF,
339
340 // 修饰键
341 LEFT_CONTROL = 0xE0,
342 LEFT_SHIFT = 0xE1,
343 LEFT_ALT = 0xE2,
344 LEFT_GUI = 0xE3,
345 RIGHT_CONTROL = 0xE4,
346 RIGHT_SHIFT = 0xE5,
347 RIGHT_ALT = 0xE6,
348 RIGHT_GUI = 0xE7
349 // 0xE8~0xFF 保留
350 };
351
355 struct Report
356 {
357 uint8_t modifiers;
358 uint8_t reserved;
359 uint8_t keys[6];
360 };
361
368 void PressKey(std::initializer_list<KeyCode> keys, uint8_t mods = Modifier::NONE)
369 {
370 ASSERT(keys.size() <= 6);
371 report_ = {static_cast<uint8_t>(mods), 0, {0}};
372 size_t i = 0;
373 for (auto k : keys)
374 {
375 report_.keys[i++] = static_cast<uint8_t>(k);
376 }
378 }
379
384 {
385 Report report = {0, 0, {0}};
386 SendInputReport(ConstRawData{&report, sizeof(report)});
387 }
388
389 protected:
396 {
398 header.data_.bDeviceSubClass = 1;
399 header.data_.bDeviceProtocol = 1;
400 return ErrorCode::OK;
401 }
402
408 {
409 return ConstRawData{HID_KEYBOARD_REPORT_DESC, sizeof(HID_KEYBOARD_REPORT_DESC)};
410 }
411
417 void OnDataOutComplete(bool in_isr, ConstRawData& data) override
418 {
419 if (data.size_ >= 1)
420 {
421 led_state_ = *(static_cast<const uint8_t*>(data.addr_));
423 }
424 }
425
432 ErrorCode OnSetReport(uint8_t report_id,
433 DeviceClass::ControlTransferResult& result) override
434 {
435 UNUSED(report_id);
436 UNUSED(result);
437
438 result.read_data = {&led_state_, 1};
439 return ErrorCode::OK;
440 }
441
448 ErrorCode OnSetReportData(bool in_isr, ConstRawData& data) override
449 {
450 if (data.size_ >= 1)
451 {
452 led_state_ = *(static_cast<const uint8_t*>(data.addr_));
454 return ErrorCode::OK;
455 }
456
458 }
459
460 public:
465 bool GetNumLock() { return (led_state_ & 0x04) != 0; }
466
471 bool GetCapsLock() { return (led_state_ & 0x02) != 0; }
472
477 bool GetScrollLock() { return (led_state_ & 0x01) != 0; }
478
488
489 private:
490 uint8_t led_state_ = 0;
494};
495
496} // namespace LibXR::USB
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:142
常量原始数据封装类。 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:40
Data data_
设备描述符数据实例 / Internal data instance
Definition desc_dev.hpp:109
@ HID
人机接口类 / Human Interface Device
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
@ EP_AUTO
自动分配端点号 / Auto allocate
USB HID(Human Interface Device)基类,支持可选 OUT 端点、自动生成描述符,适合键盘、鼠标、手柄等扩展。 USB HID (Human Interface Device)...
Definition hid.hpp:24
ErrorCode SendInputReport(ConstRawData report)
Definition hid.hpp:600
标准 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 OnSetReport(uint8_t report_id, DeviceClass::ControlTransferResult &result) override
处理 SET_REPORT 请求 / Handle SET_REPORT request
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 WriteDeviceDescriptor(DeviceDescriptor &header) override
写入设备描述符 / Write device descriptor
bool GetCapsLock()
获取 CapsLock 状态 / Get CapsLock status
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, const char *interface_string=HID< sizeof(HID_KEYBOARD_REPORT_DESC), 8, 1 >::DEFAULT_INTERFACE_STRING)
构造函数 / Constructor
KeyCode
按键代码枚举 / KeyCode enum
@ APPLICATION
Application (Menu)
@ ERROR_UNDEFINED
未定义 / ErrorUndefined
@ POST_FAIL
POST 失败 / POSTFail.
@ ERROR_ROLLOVER
错误溢出 / ErrorRollOver
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.
ErrorCode
定义错误码枚举
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
ClassID bDeviceClass
设备类代码 / Device class code
Definition desc_dev.hpp:93
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
Definition desc_dev.hpp:94
uint8_t bDeviceProtocol
协议代码 / Protocol code
Definition desc_dev.hpp:95
输入报告结构体 / Keyboard input report struct
uint8_t keys[6]
最多 6 个按键 / Up to 6 keys
uint8_t modifiers
修饰键 / Modifier
uint8_t reserved
保留 / Reserved