libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
hid.hpp
1#pragma once
2#include <cstring>
3
4#include "dev_core.hpp"
5#include "usb/core/desc_cfg.hpp"
6
7namespace LibXR::USB
8{
9
21template <size_t REPORT_DESC_LEN, size_t TX_REPORT_LEN, size_t RX_REPORT_LEN = 0>
22class HID : public DeviceClass
23{
24 public:
26 enum class HIDDescriptorType : uint8_t
27 {
28 HID = 0x21,
29 REPORT = 0x22,
30 PHYSICAL = 0x23
31 };
32
34 enum class ClassRequest : uint8_t
35 {
36 GET_REPORT = 0x01,
37 GET_IDLE = 0x02,
38 GET_PROTOCOL = 0x03,
39 SET_REPORT = 0x09,
40 SET_IDLE = 0x0A,
41 SET_PROTOCOL = 0x0B
42 };
43
45 enum class Protocol : uint8_t
46 {
47 BOOT = 0x00,
48 REPORT = 0x01
49 };
50
52 enum class ReportType : uint8_t
53 {
54 INPUT = 1,
55 OUTPUT = 2,
56 FEATURE = 3
57 };
58
59#pragma pack(push, 1)
75
86
98#pragma pack(pop)
99
110 HID(bool enable_out_endpoint = false, uint8_t in_ep_interval = 10,
111 uint8_t out_ep_interval = 10,
114 : in_ep_interval_(in_ep_interval),
115 out_ep_interval_(out_ep_interval),
116 in_ep_num_(in_ep_num),
117 out_ep_num_(out_ep_num),
118 enable_out_endpoint_(enable_out_endpoint)
119 {
120 }
121
122 protected:
129 void Init(EndpointPool& endpoint_pool, uint8_t start_itf_num) override
130 {
131 inited_ = false;
132 itf_num_ = start_itf_num;
133 ep_in_ = nullptr;
134 ep_out_ = nullptr;
135
136 // 获取IN端点
137 auto ans = endpoint_pool.Get(ep_in_, Endpoint::Direction::IN, in_ep_num_);
138 ASSERT(ans == ErrorCode::OK);
141
143 {
144 ans = endpoint_pool.Get(ep_out_, Endpoint::Direction::OUT, out_ep_num_);
145 ASSERT(ans == ErrorCode::OK);
148 }
149
150 // 填充接口描述符
151 desc_.intf = {
152 9, // bLength
153 static_cast<uint8_t>(DescriptorType::INTERFACE), // bDescriptorType
154 static_cast<uint8_t>(itf_num_), // bInterfaceNumber
155 0, // bAlternateSetting
156 static_cast<uint8_t>(enable_out_endpoint_ ? 2 : 1), // bNumEndpoints
157 0x03, // bInterfaceClass (HID)
158 0x00, // bInterfaceSubClass
159 0x00, // bInterfaceProtocol (可选键盘/鼠标设置1/2)
160 0 // iInterface
161 };
162
163 // 填充HID描述符
164 desc_.hid = {9,
166 0x0111, // HID v1.11
167 0x00, // 国家码
168 0x01, // 只有一个后续描述符(Report Desc)
170 REPORT_DESC_LEN};
171
172 // 填充IN端点描述符
173 desc_.ep_in = {
174 7,
175 static_cast<uint8_t>(DescriptorType::ENDPOINT),
177 static_cast<uint8_t>(Endpoint::Type::INTERRUPT),
178 TX_REPORT_LEN,
179 in_ep_interval_ // 轮询间隔ms
180 };
181
182 // 填充OUT端点描述符(如启用)
184 {
185 desc_.ep_out = {7,
186 static_cast<uint8_t>(DescriptorType::ENDPOINT),
188 static_cast<uint8_t>(Endpoint::Type::INTERRUPT),
189 RX_REPORT_LEN,
191 }
192
193 // 设置最终数据指针
195 {
196 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_), sizeof(HIDDescBlockINOUT)});
197 }
198 else
199 {
200 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_), sizeof(HIDDescBlockIN)});
201 }
202
203 ep_in_->SetOnTransferCompleteCallback(on_data_in_complete_cb_);
204
206 {
207 ep_out_->SetOnTransferCompleteCallback(on_data_out_complete_cb_);
208 ep_out_->Transfer(RX_REPORT_LEN);
209 }
210
211 inited_ = true;
212 }
213
214 static void OnDataOutCompleteStatic(bool in_isr, HID* self, LibXR::ConstRawData& data)
215 {
216 self->OnDataOutComplete(in_isr, data);
217 self->ep_out_->Transfer(RX_REPORT_LEN);
218 }
219
220 static void OnDataInCompleteStatic(bool in_isr, HID* self, LibXR::ConstRawData& data)
221 {
222 self->OnDataInComplete(in_isr, data);
223 }
224
225 virtual void OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data)
226 {
227 UNUSED(in_isr);
228 UNUSED(data);
229 }
230
231 virtual void OnDataInComplete(bool in_isr, LibXR::ConstRawData& data)
232 {
233 UNUSED(in_isr);
234 UNUSED(data);
235 }
236
242 void Deinit(EndpointPool& endpoint_pool) override
243 {
244 inited_ = false;
245 if (ep_in_)
246 {
247 ep_in_->Close();
248 endpoint_pool.Release(ep_in_);
249 ep_in_ = nullptr;
250 }
251 if (ep_out_)
252 {
253 ep_out_->Close();
254 endpoint_pool.Release(ep_out_);
255 ep_out_ = nullptr;
256 }
257 }
258
264 size_t GetInterfaceNum() override { return 1; }
265
273 bool HasIAD() override { return false; }
274
280 size_t GetMaxConfigSize() override
281 {
282 return enable_out_endpoint_ ? sizeof(HIDDescBlockINOUT) : sizeof(HIDDescBlockIN);
283 }
284
296 ErrorCode OnGetDescriptor(bool in_isr, uint8_t bRequest, uint16_t wValue,
297 uint16_t wLength, ConstRawData& need_write) override
298 {
299 UNUSED(in_isr);
300 UNUSED(bRequest);
301
302 uint8_t desc_type = (wValue >> 8) & 0xFF;
303 // uint8_t desc_index = wValue & 0xFF; // 一般为0,暂不需要
304
305 switch (desc_type)
306 {
307 case static_cast<uint8_t>(HIDDescriptorType::HID): // 0x21
308 {
309 // 返回 HID 描述符
310 ConstRawData desc = GetHIDDesc();
311 need_write.addr_ = desc.addr_;
312 need_write.size_ = (wLength < desc.size_) ? wLength : desc.size_;
313 return ErrorCode::OK;
314 }
315 case static_cast<uint8_t>(HIDDescriptorType::REPORT): // 0x22
316 {
317 // 返回 Report Descriptor
319 need_write.addr_ = desc.addr_;
320 need_write.size_ = (wLength < desc.size_) ? wLength : desc.size_;
321 return ErrorCode::OK;
322 }
323 case static_cast<uint8_t>(HIDDescriptorType::PHYSICAL):
324 // 物理描述符(很少用,未实现)
325 default:
326 return ErrorCode::NOT_SUPPORT;
327 }
328 }
329
341 ErrorCode OnClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue,
342 uint16_t wLength, DeviceClass::RequestResult& result) override
343 {
344 UNUSED(in_isr);
345
346 uint8_t report_id = wValue & 0xFF;
347
348 switch (static_cast<ClassRequest>(bRequest))
349 {
351 {
352 ReportType report_type = static_cast<ReportType>((wValue >> 8) & 0xFF);
353 switch (report_type)
354 {
356 // 查找或生成 Input Report(按你的设备实际逻辑)
357 return OnGetInputReport(report_id, result);
359 // 查找或返回最近收到的 Output Report(通常很少实现GET Output)
360 return OnGetLastOutputReport(report_id, result);
362 // 查找或生成 Feature Report
363 return OnGetFeatureReport(report_id, result);
364 default:
365 return OnCustomClassRequest(in_isr, bRequest, wValue, wLength, result);
366 }
367 }
368
370 if (wLength == 0)
371 {
372 return ErrorCode::ARG_ERR;
373 }
374 // 由OnClassData阶段接收
375 return OnSetReport(report_id, result);
376
378 // 仅支持一个Idle rate
379 if (wLength != 1 || report_id != 0)
380 {
381 return ErrorCode::ARG_ERR;
382 }
383 result.write_data = ConstRawData{&idle_rate_, 1};
384 return ErrorCode::OK;
385
387 if (report_id != 0)
388 {
389 return ErrorCode::ARG_ERR;
390 }
391 idle_rate_ = wValue >> 8;
392 result.write_zlp = true;
393 return ErrorCode::OK;
394
396 result.write_data = ConstRawData{reinterpret_cast<uint8_t*>(&protocol_), 1};
397 return ErrorCode::OK;
398
400 protocol_ = static_cast<Protocol>(wValue & 0xFF);
401 result.write_zlp = true;
402 return ErrorCode::OK;
403
404 default:
405 return ErrorCode::NOT_SUPPORT;
406 }
407 }
408
413 ErrorCode OnClassData(bool in_isr, uint8_t bRequest, LibXR::ConstRawData& data) override
414 {
415 UNUSED(in_isr);
416
417 switch (static_cast<ClassRequest>(bRequest))
418 {
420 {
421 // 通常为 Output Report 或 Feature Report
422 // 你可以区分是 Output 还是 Feature,也可以统一交给
423 // OnSetReportData(推荐如下写法)
424 auto ans = OnSetReportData(in_isr, data);
425 if (ans == ErrorCode::OK)
426 {
427 // 可选:记录最近一次 report id(假定第一个字节是 report id,没有 report id
428 // 就写0)
430 (data.size_ > 0) ? reinterpret_cast<const uint8_t*>(data.addr_)[0] : 0;
431 }
432 return ans;
433 }
434 default:
435 return OnCustomClassData(in_isr, bRequest, data);
436 }
437 }
438
445
452
459 {
460 return ConstRawData{&desc_.hid, sizeof(HIDDescriptor)};
461 }
462
467 virtual ErrorCode OnGetInputReport(uint8_t report_id,
469 {
470 UNUSED(report_id);
471 result.write_data = ConstRawData{nullptr, 0};
472 return ErrorCode::OK;
473 }
474
479 virtual ErrorCode OnGetLastOutputReport(uint8_t report_id,
481 {
482 UNUSED(report_id);
483 result.write_data = ConstRawData{nullptr, 0};
484 return ErrorCode::OK;
485 }
486
491 virtual ErrorCode OnGetFeatureReport(uint8_t report_id,
493 {
494 UNUSED(report_id);
495 result.write_data = ConstRawData{nullptr, 0};
496 return ErrorCode::OK;
497 }
498
510 virtual ErrorCode OnCustomClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue,
511 uint16_t wLength, RequestResult& result)
512 {
513 UNUSED(in_isr);
514 UNUSED(bRequest);
515 UNUSED(wValue);
516 UNUSED(wLength);
517 UNUSED(result);
518 return ErrorCode::NOT_SUPPORT;
519 }
520
521 virtual ErrorCode OnCustomClassData(bool in_isr, uint8_t bRequest, ConstRawData& data)
522 {
523 UNUSED(in_isr);
524 UNUSED(bRequest);
525 UNUSED(data);
526 return ErrorCode::NOT_SUPPORT;
527 }
528
533 virtual ErrorCode OnSetReport(uint8_t report_id, DeviceClass::RequestResult& result)
534 {
535 UNUSED(report_id);
536 UNUSED(result);
537
538 return ErrorCode::NOT_SUPPORT;
539 }
540
545 virtual ErrorCode OnSetReportData(bool in_isr, ConstRawData& data)
546 {
547 UNUSED(in_isr);
548 UNUSED(data);
549
550 return ErrorCode::OK;
551 }
552
561 {
562 if (!inited_ || !ep_in_)
563 {
564 return ErrorCode::FAILED;
565 }
566 if (!report.addr_ || report.size_ == 0 || report.size_ > TX_REPORT_LEN)
567 {
568 return ErrorCode::ARG_ERR;
569 }
570
572 {
573 return ErrorCode::BUSY;
574 }
575
576 // 数据拷贝到端点缓冲区
577 auto buf = ep_in_->GetBuffer();
578 if (report.size_ > buf.size_)
579 {
580 return ErrorCode::NO_BUFF;
581 }
582
583 LibXR::Memory::FastCopy(buf.addr_, report.addr_, report.size_);
584
585 // 启动端点传输
586 return ep_in_->Transfer(report.size_);
587 }
588
595 uint8_t GetIDLERate() const { return idle_rate_; }
596
604
612
617 bool HasOutEndpoint() const { return enable_out_endpoint_; }
618
619 private:
625 Endpoint* ep_in_ = nullptr;
626 Endpoint* ep_out_ = nullptr;
628 bool inited_ = false;
629 size_t itf_num_;
630
632 uint8_t idle_rate_ = 0;
634 0;
635
636 LibXR::Callback<LibXR::ConstRawData&> on_data_out_complete_cb_ =
637 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataOutCompleteStatic, this);
638
639 LibXR::Callback<LibXR::ConstRawData&> on_data_in_complete_cb_ =
640 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataInCompleteStatic, this);
641};
642
643} // namespace LibXR::USB
提供一个通用的回调包装,支持动态参数传递。 Provides a generic callback wrapper, supporting dynamic argument passing.
Definition libxr_cb.hpp:124
static Callback Create(FunType fun, ArgType arg)
创建一个新的回调对象,并绑定回调函数和参数。 Creates a new callback instance, binding a function and an argument.
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).
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:17
原始数据封装类。 A class for encapsulating raw data.
void SetData(RawData data)
设置配置项数据 Set configuration item data
Definition desc_cfg.hpp:197
USB 设备类接口基类,所有自定义 USB 类(如 HID、CDC、MSC)都需派生自本类。 USB device class base interface, all custom device cla...
Definition dev_core.hpp:22
USB端点基类 / USB Endpoint base class.
Definition ep.hpp:22
EPNumber
端点号 / Endpoint number
Definition ep.hpp:39
@ EP_AUTO
自动分配端点号 / Auto allocate
uint8_t GetAddress() const
获取端点地址(方向 + 号) Get endpoint address (dir + num)
Definition ep.hpp:199
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
Definition ep.hpp:273
virtual void Configure(const Config &cfg)=0
二次初始化/配置端点协议参数(由Pool/Manager分配后调用) Configure endpoint protocol parameters (call after pool allocation...
@ INTERRUPT
中断端点 / Interrupt
virtual void Close()=0
关闭端点(软禁用/资源复位) Close (soft disable)
State GetState() const
获取端点状态 Get endpoint state
Definition ep.hpp:212
virtual ErrorCode Transfer(size_t size)=0
传输数据 Transfer data
RawData GetBuffer() const
获取端点缓冲区 Get endpoint buffer
Definition ep.hpp:256
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
ErrorCode Get(Endpoint *&ep_info, Endpoint::Direction direction, Endpoint::EPNumber ep_num=Endpoint::EPNumber::EP_AUTO)
分配端点 / Allocate endpoint
Definition ep_pool.cpp:11
ErrorCode Release(Endpoint *ep_info)
回收端点 / Release endpoint
Definition ep_pool.cpp:37
USB HID(Human Interface Device)基类,支持可选 OUT 端点、自动生成描述符,适合键盘、鼠标、手柄等扩展。 USB HID (Human Interface Device)...
Definition hid.hpp:23
virtual ConstRawData GetHIDDesc()
获取 HID 描述符 Get HID Descriptor
Definition hid.hpp:458
bool enable_out_endpoint_
是否启用 OUT 端点 / Whether OUT endpoint is enabled
Definition hid.hpp:627
virtual ErrorCode OnGetLastOutputReport(uint8_t report_id, DeviceClass::RequestResult &result)
获取最近一次输出报告 Get last Output Report
Definition hid.hpp:479
virtual ErrorCode OnSetReport(uint8_t report_id, DeviceClass::RequestResult &result)
处理 SET_REPORT 请求 Handle SET_REPORT request
Definition hid.hpp:533
ErrorCode OnGetDescriptor(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, ConstRawData &need_write) override
处理标准请求 GET_DESCRIPTOR(HID/Report 描述符)。 Handle standard GET_DESCRIPTOR requests for HID/Report Descrip...
Definition hid.hpp:296
Endpoint * GetOutEndpoint()
获取输出端点 Get OUT endpoint
Definition hid.hpp:611
bool HasIAD() override
检查是否包含IAD Check if IAD is present
Definition hid.hpp:273
uint8_t last_output_report_id_
最近的 Output Report ID / Last Output Report ID
Definition hid.hpp:633
Endpoint * ep_out_
输出端点指针 / OUT endpoint pointer
Definition hid.hpp:626
HID(bool enable_out_endpoint=false, uint8_t in_ep_interval=10, uint8_t out_ep_interval=10, Endpoint::EPNumber in_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber out_ep_num=Endpoint::EPNumber::EP_AUTO)
HID 构造函数 HID class constructor.
Definition hid.hpp:110
virtual ConstRawData GetReportDesc()=0
获取 HID 报告描述符 Get HID Report Descriptor
uint8_t idle_rate_
当前空闲率/ Current idle rate (unit 4ms)
Definition hid.hpp:632
ErrorCode SendInputReport(ConstRawData report)
发送输入报告到主机 Send Input Report to host
Definition hid.hpp:560
Endpoint * ep_in_
输入端点指针 / IN endpoint pointer
Definition hid.hpp:625
virtual ErrorCode OnGetFeatureReport(uint8_t report_id, DeviceClass::RequestResult &result)
获取特征报告 Get Feature Report
Definition hid.hpp:491
virtual ErrorCode OnCustomClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, RequestResult &result)
处理自定义类请求 Handle custom class request
Definition hid.hpp:510
uint8_t out_ep_interval_
输出端点间隔 / OUT endpoint interval
Definition hid.hpp:621
Protocol
HID 协议类型 / HID Protocol Types.
Definition hid.hpp:46
@ REPORT
报告协议 / Report protocol (通用)
@ BOOT
启动协议 / Boot protocol (键盘/鼠标)
virtual ErrorCode OnGetInputReport(uint8_t report_id, DeviceClass::RequestResult &result)
获取输入报告 Get Input Report
Definition hid.hpp:467
size_t GetMaxConfigSize() override
获取最大配置描述符块长度 Get max config descriptor size.
Definition hid.hpp:280
HIDDescBlockINOUT desc_
HID 描述符块/ Descriptor block.
Definition hid.hpp:622
ErrorCode OnClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, DeviceClass::RequestResult &result) override
处理 HID 类请求 Handle HID class-specific requests
Definition hid.hpp:341
uint8_t in_ep_interval_
输入端点间隔 / IN endpoint interval
Definition hid.hpp:620
Endpoint::EPNumber out_ep_num_
输出端点号 / OUT endpoint number
Definition hid.hpp:624
bool HasOutEndpoint() const
查询是否支持OUT端点 Check if OUT endpoint is enabled
Definition hid.hpp:617
void Init(EndpointPool &endpoint_pool, uint8_t start_itf_num) override
初始化 HID 设备,自动选择端点与描述符块 Initialize HID device and select descriptor block (IN or IN+OUT).
Definition hid.hpp:129
size_t itf_num_
接口号 / Interface number
Definition hid.hpp:629
uint8_t GetIDLERate() const
获取IDLE报告率 Get IDLE report rate
Definition hid.hpp:595
ReportType
HID 报告类型 / HID Report Types.
Definition hid.hpp:53
@ OUTPUT
输出报告 / Output report
@ INPUT
输入报告 / Input report
@ FEATURE
特征报告 / Feature report
Endpoint * GetInEndpoint()
获取输入端点 Get IN endpoint
Definition hid.hpp:603
virtual ErrorCode OnSetReportData(bool in_isr, ConstRawData &data)
处理 SET_REPORT 数据阶段 Handle SET_REPORT data stage
Definition hid.hpp:545
Endpoint::EPNumber in_ep_num_
输入端点号 / IN endpoint number
Definition hid.hpp:623
Protocol protocol_
当前协议类型 / Current protocol
Definition hid.hpp:631
uint8_t GetLastOutputReportID() const
获取最近一次 Output Report 的 Report ID Get the last received Output Report ID.
Definition hid.hpp:444
void Deinit(EndpointPool &endpoint_pool) override
反初始化 HID 设备 Deinitialize HID device.
Definition hid.hpp:242
bool inited_
初始化标志 / Initialization flag
Definition hid.hpp:628
HIDDescriptorType
HID 描述符类型 / HID Descriptor Types.
Definition hid.hpp:27
@ HID
HID 类描述符 / HID Class Descriptor.
@ REPORT
报告描述符 / Report Descriptor
@ PHYSICAL
物理描述符 / Physical Descriptor (rarely used)
size_t GetInterfaceNum() override
获取接口数量 Get number of interfaces
Definition hid.hpp:264
ClassRequest
HID 类请求代码 / HID Class-Specific Requests.
Definition hid.hpp:35
@ SET_PROTOCOL
设置协议 / Set Protocol
@ GET_PROTOCOL
获取协议 / Get Protocol
@ GET_REPORT
获取报告 / Get Report
@ SET_REPORT
设置报告 / Set Report
@ SET_IDLE
设置空闲率 / Set Idle
@ GET_IDLE
获取空闲率 / Get Idle
ErrorCode OnClassData(bool in_isr, uint8_t bRequest, LibXR::ConstRawData &data) override
处理类请求数据阶段 Handle class data stage
Definition hid.hpp:413
端点描述符结构体 Endpoint descriptor structure (USB 2.0 Spec 9.6.6)
Definition desc_cfg.hpp:91
接口描述符结构体 Interface descriptor structure (USB 2.0 Spec 9.6.5)
Definition desc_cfg.hpp:73
控制请求结果结构体 / Structure for control transfer results
Definition dev_core.hpp:28
bool write_zlp
写操作是否需要发送 0 长度包 / Send ZLP after write
Definition dev_core.hpp:33
ConstRawData write_data
主机写入设备的数据 / Data to write (from host)
Definition dev_core.hpp:30
包含 IN 端点的描述符块 Descriptor block with IN endpoint.
Definition hid.hpp:81
EndpointDescriptor ep_in
IN 端点描述符 / IN endpoint descriptor.
Definition hid.hpp:84
HIDDescriptor hid
HID 描述符 / HID descriptor.
Definition hid.hpp:83
InterfaceDescriptor intf
接口描述符 / Interface descriptor
Definition hid.hpp:82
包含 IN+OUT 端点的描述符块 Descriptor block with IN and OUT endpoints.
Definition hid.hpp:92
HIDDescriptor hid
HID 描述符 / HID descriptor.
Definition hid.hpp:94
EndpointDescriptor ep_out
OUT 端点描述符 / OUT endpoint descriptor.
Definition hid.hpp:96
EndpointDescriptor ep_in
IN 端点描述符 / IN endpoint descriptor.
Definition hid.hpp:95
InterfaceDescriptor intf
接口描述符 / Interface descriptor
Definition hid.hpp:93
HID描述符结构体 HID descriptor structure.
Definition hid.hpp:65
uint8_t bLength
描述符长度 / Descriptor length
Definition hid.hpp:66
uint8_t bNumDescriptors
后续描述符数量 / Number of subordinate descriptors
Definition hid.hpp:70
uint16_t bcdHID
HID 版本号 / HID class specification release.
Definition hid.hpp:68
HIDDescriptorType bReportDescriptorType
报告描述符类型 / Report descriptor type (0x22)
Definition hid.hpp:72
HIDDescriptorType bDescriptorType
描述符类型 / Descriptor type (0x21)
Definition hid.hpp:67
uint16_t wReportDescriptorLength
报告描述符长度 / Report descriptor length
Definition hid.hpp:73
uint8_t bCountryCode
国家码 / Country code
Definition hid.hpp:69