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 "libxr_mem.hpp"
6#include "usb/core/desc_cfg.hpp"
7
8namespace LibXR::USB
9{
10
22template <size_t REPORT_DESC_LEN, size_t TX_REPORT_LEN, size_t RX_REPORT_LEN = 0>
23class HID : public DeviceClass
24{
25 public:
26 // 暴露单接口的 HID 功能默认使用这个接口字符串。
27 // Default interface string for HID functions that expose one interface.
28 static constexpr const char* DEFAULT_INTERFACE_STRING = "XRUSB HID";
29
31 enum class HIDDescriptorType : uint8_t
32 {
33 HID = 0x21,
34 REPORT = 0x22,
35 PHYSICAL = 0x23
36 };
37
39 enum class ClassRequest : uint8_t
40 {
41 GET_REPORT = 0x01,
42 GET_IDLE = 0x02,
43 GET_PROTOCOL = 0x03,
44 SET_REPORT = 0x09,
45 SET_IDLE = 0x0A,
46 SET_PROTOCOL = 0x0B
47 };
48
50 enum class Protocol : uint8_t
51 {
52 BOOT = 0x00,
53 REPORT = 0x01
54 };
55
57 enum class ReportType : uint8_t
58 {
59 INPUT = 1,
60 OUTPUT = 2,
61 FEATURE = 3
62 };
63
64#pragma pack(push, 1)
80
91
103#pragma pack(pop)
104
116 HID(bool enable_out_endpoint = false, uint8_t in_ep_interval = 10,
117 uint8_t out_ep_interval = 10,
120 const char* interface_string = DEFAULT_INTERFACE_STRING)
121 : in_ep_interval_(in_ep_interval),
122 out_ep_interval_(out_ep_interval),
123 in_ep_num_(in_ep_num),
124 out_ep_num_(out_ep_num),
125 enable_out_endpoint_(enable_out_endpoint),
126 interface_string_(interface_string)
127 {
128 }
129
130 const char* GetInterfaceString(size_t local_interface_index) const override
131 {
132 // HID 只暴露一个接口。
133 // HID contributes exactly one interface.
134 return (local_interface_index == 0u) ? interface_string_ : nullptr;
135 }
136
137 protected:
145 void BindEndpoints(EndpointPool& endpoint_pool, uint8_t start_itf_num, bool) override
146 {
147 inited_ = false;
148 itf_num_ = start_itf_num;
149 ep_in_ = nullptr;
150 ep_out_ = nullptr;
151
152 // 获取IN端点
153 auto ans = endpoint_pool.Get(ep_in_, Endpoint::Direction::IN, in_ep_num_);
154 ASSERT(ans == ErrorCode::OK);
157
159 {
160 ans = endpoint_pool.Get(ep_out_, Endpoint::Direction::OUT, out_ep_num_);
161 ASSERT(ans == ErrorCode::OK);
164 }
165
166 // 填充接口描述符
167 desc_.intf = {
168 9, // bLength
169 static_cast<uint8_t>(DescriptorType::INTERFACE), // bDescriptorType
170 static_cast<uint8_t>(itf_num_), // bInterfaceNumber
171 0, // bAlternateSetting
172 static_cast<uint8_t>(enable_out_endpoint_ ? 2 : 1), // bNumEndpoints
173 0x03, // bInterfaceClass (HID)
174 0x00, // bInterfaceSubClass
175 0x00, // bInterfaceProtocol (可选键盘/鼠标设置1/2)
176 GetInterfaceStringIndex(0u) // iInterface
177 };
178
179 // 填充HID描述符
180 desc_.hid = {9,
182 0x0111, // HID v1.11
183 0x00, // 国家码
184 0x01, // 只有一个后续描述符(Report Desc)
186 REPORT_DESC_LEN};
187
188 // 填充IN端点描述符
189 desc_.ep_in = {
190 7,
191 static_cast<uint8_t>(DescriptorType::ENDPOINT),
193 static_cast<uint8_t>(Endpoint::Type::INTERRUPT),
194 TX_REPORT_LEN,
195 in_ep_interval_ // 轮询间隔ms
196 };
197
198 // 填充OUT端点描述符(如启用)
200 {
201 desc_.ep_out = {7,
202 static_cast<uint8_t>(DescriptorType::ENDPOINT),
204 static_cast<uint8_t>(Endpoint::Type::INTERRUPT),
205 RX_REPORT_LEN,
207 }
208
209 // 设置最终数据指针
211 {
212 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_), sizeof(HIDDescBlockINOUT)});
213 }
214 else
215 {
216 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_), sizeof(HIDDescBlockIN)});
217 }
218
219 ep_in_->SetOnTransferCompleteCallback(on_data_in_complete_cb_);
220
222 {
223 ep_out_->SetOnTransferCompleteCallback(on_data_out_complete_cb_);
224 ep_out_->Transfer(RX_REPORT_LEN);
225 }
226
227 inited_ = true;
228 }
229
230 static void OnDataOutCompleteStatic(bool in_isr, HID* self, LibXR::ConstRawData& data)
231 {
232 if (self == nullptr || !self->inited_ || self->ep_out_ == nullptr)
233 {
234 return;
235 }
236 self->OnDataOutComplete(in_isr, data);
237 self->ep_out_->Transfer(RX_REPORT_LEN);
238 }
239
240 static void OnDataInCompleteStatic(bool in_isr, HID* self, LibXR::ConstRawData& data)
241 {
242 if (self == nullptr || !self->inited_ || self->ep_in_ == nullptr)
243 {
244 return;
245 }
246 self->OnDataInComplete(in_isr, data);
247 }
248
249 virtual void OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data)
250 {
251 UNUSED(in_isr);
252 UNUSED(data);
253 }
254
255 virtual void OnDataInComplete(bool in_isr, LibXR::ConstRawData& data)
256 {
257 UNUSED(in_isr);
258 UNUSED(data);
259 }
260
267 void UnbindEndpoints(EndpointPool& endpoint_pool, bool) override
268 {
269 inited_ = false;
270 if (ep_in_)
271 {
272 ep_in_->Close();
273 endpoint_pool.Release(ep_in_);
274 ep_in_ = nullptr;
275 }
276 if (ep_out_)
277 {
278 ep_out_->Close();
279 endpoint_pool.Release(ep_out_);
280 ep_out_ = nullptr;
281 }
282 }
283
289 size_t GetInterfaceCount() override { return 1; }
290
298 bool HasIAD() override { return false; }
299
300 bool OwnsEndpoint(uint8_t ep_addr) const override
301 {
302 if (!inited_)
303 {
304 return false;
305 }
306
307 return ep_in_->GetAddress() == ep_addr ||
308 (enable_out_endpoint_ && ep_out_->GetAddress() == ep_addr);
309 }
310
316 size_t GetMaxConfigSize() override
317 {
318 return enable_out_endpoint_ ? sizeof(HIDDescBlockINOUT) : sizeof(HIDDescBlockIN);
319 }
320
332 ErrorCode OnGetDescriptor(bool in_isr, uint8_t bRequest, uint16_t wValue,
333 uint16_t wLength, ConstRawData& need_write) override
334 {
335 UNUSED(in_isr);
336 UNUSED(bRequest);
337
338 uint8_t desc_type = (wValue >> 8) & 0xFF;
339 // uint8_t desc_index = wValue & 0xFF; // 一般为0,暂不需要
340
341 switch (desc_type)
342 {
343 case static_cast<uint8_t>(HIDDescriptorType::HID): // 0x21
344 {
345 // 返回 HID 描述符
346 ConstRawData desc = GetHIDDesc();
347 need_write.addr_ = desc.addr_;
348 need_write.size_ = (wLength < desc.size_) ? wLength : desc.size_;
349 return ErrorCode::OK;
350 }
351 case static_cast<uint8_t>(HIDDescriptorType::REPORT): // 0x22
352 {
353 // 返回 Report Descriptor
355 need_write.addr_ = desc.addr_;
356 need_write.size_ = (wLength < desc.size_) ? wLength : desc.size_;
357 return ErrorCode::OK;
358 }
359 case static_cast<uint8_t>(HIDDescriptorType::PHYSICAL):
360 // 物理描述符(很少用,未实现)
361 default:
363 }
364 }
365
377 ErrorCode OnClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue,
378 uint16_t wLength, uint16_t wIndex,
379 DeviceClass::ControlTransferResult& result) override
380 {
381 UNUSED(in_isr);
382 UNUSED(wIndex);
383
384 uint8_t report_id = wValue & 0xFF;
385
386 switch (static_cast<ClassRequest>(bRequest))
387 {
389 {
390 ReportType report_type = static_cast<ReportType>((wValue >> 8) & 0xFF);
391 switch (report_type)
392 {
394 // 查找或生成 Input Report(按你的设备实际逻辑)
395 return OnGetInputReport(report_id, result);
397 // 查找或返回最近收到的 Output Report(通常很少实现GET Output)
398 return OnGetLastOutputReport(report_id, result);
400 // 查找或生成 Feature Report
401 return OnGetFeatureReport(report_id, result);
402 default:
403 return OnCustomClassRequest(in_isr, bRequest, wValue, wLength, result);
404 }
405 }
406
408 if (wLength == 0)
409 {
410 return ErrorCode::ARG_ERR;
411 }
412 // 由OnClassData阶段接收
413 return OnSetReport(report_id, result);
414
416 // 仅支持一个Idle rate
417 if (wLength != 1 || report_id != 0)
418 {
419 return ErrorCode::ARG_ERR;
420 }
421 result.write_data = ConstRawData{&idle_rate_, 1};
422 return ErrorCode::OK;
423
425 if (report_id != 0)
426 {
427 return ErrorCode::ARG_ERR;
428 }
429 idle_rate_ = wValue >> 8;
430 result.write_zlp = true;
431 return ErrorCode::OK;
432
434 result.write_data = ConstRawData{reinterpret_cast<uint8_t*>(&protocol_), 1};
435 return ErrorCode::OK;
436
438 protocol_ = static_cast<Protocol>(wValue & 0xFF);
439 result.write_zlp = true;
440 return ErrorCode::OK;
441
442 default:
444 }
445 }
446
451 ErrorCode OnClassData(bool in_isr, uint8_t bRequest, LibXR::ConstRawData& data) override
452 {
453 UNUSED(in_isr);
454
455 switch (static_cast<ClassRequest>(bRequest))
456 {
458 {
459 // 通常为 Output Report 或 Feature Report
460 // 你可以区分是 Output 还是 Feature,也可以统一交给
461 // OnSetReportData(推荐如下写法)
462 auto ans = OnSetReportData(in_isr, data);
463 if (ans == ErrorCode::OK)
464 {
465 // 可选:记录最近一次 report id(假定第一个字节是 report id,没有 report id
466 // 就写0)
468 (data.size_ > 0) ? reinterpret_cast<const uint8_t*>(data.addr_)[0] : 0;
469 }
470 return ans;
471 }
472 default:
473 return OnCustomClassData(in_isr, bRequest, data);
474 }
475 }
476
483
490
497 {
498 return ConstRawData{&desc_.hid, sizeof(HIDDescriptor)};
499 }
500
505 virtual ErrorCode OnGetInputReport(uint8_t report_id,
507 {
508 UNUSED(report_id);
509 result.write_data = ConstRawData{nullptr, 0};
510 return ErrorCode::OK;
511 }
512
517 virtual ErrorCode OnGetLastOutputReport(uint8_t report_id,
519 {
520 UNUSED(report_id);
521 result.write_data = ConstRawData{nullptr, 0};
522 return ErrorCode::OK;
523 }
524
529 virtual ErrorCode OnGetFeatureReport(uint8_t report_id,
531 {
532 UNUSED(report_id);
533 result.write_data = ConstRawData{nullptr, 0};
534 return ErrorCode::OK;
535 }
536
548 virtual ErrorCode OnCustomClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue,
549 uint16_t wLength,
551 {
552 UNUSED(in_isr);
553 UNUSED(bRequest);
554 UNUSED(wValue);
555 UNUSED(wLength);
556 UNUSED(result);
558 }
559
560 virtual ErrorCode OnCustomClassData(bool in_isr, uint8_t bRequest, ConstRawData& data)
561 {
562 UNUSED(in_isr);
563 UNUSED(bRequest);
564 UNUSED(data);
566 }
567
572 virtual ErrorCode OnSetReport(uint8_t report_id,
574 {
575 UNUSED(report_id);
576 UNUSED(result);
577
579 }
580
585 virtual ErrorCode OnSetReportData(bool in_isr, ConstRawData& data)
586 {
587 UNUSED(in_isr);
588 UNUSED(data);
589
590 return ErrorCode::OK;
591 }
592
601 {
602 if (!inited_ || !ep_in_)
603 {
604 return ErrorCode::FAILED;
605 }
606 if (!report.addr_ || report.size_ == 0 || report.size_ > TX_REPORT_LEN)
607 {
608 return ErrorCode::ARG_ERR;
609 }
610
612 {
613 return ErrorCode::BUSY;
614 }
615
616 // 数据拷贝到端点缓冲区
617 auto buf = ep_in_->GetBuffer();
618 if (report.size_ > buf.size_)
619 {
620 return ErrorCode::NO_BUFF;
621 }
622
623 LibXR::Memory::FastCopy(buf.addr_, report.addr_, report.size_);
624
625 // 启动端点传输
626 return ep_in_->Transfer(report.size_);
627 }
628
635 uint8_t GetIDLERate() const { return idle_rate_; }
636
644
652
657 bool HasOutEndpoint() const { return enable_out_endpoint_; }
658
659 private:
665 Endpoint* ep_in_ = nullptr;
666 Endpoint* ep_out_ = nullptr;
668 bool inited_ = false;
669 size_t itf_num_;
670 const char* interface_string_ = nullptr;
671
673 uint8_t idle_rate_ = 0;
675 0;
676
677 LibXR::Callback<LibXR::ConstRawData&> on_data_out_complete_cb_ =
678 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataOutCompleteStatic, this);
679
680 LibXR::Callback<LibXR::ConstRawData&> on_data_in_complete_cb_ =
681 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataInCompleteStatic, this);
682};
683
684} // namespace LibXR::USB
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:142
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:159
常量原始数据封装类。 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:5
原始数据封装类。 A class for encapsulating raw data.
void SetData(RawData data)
设置内部数据缓存 / Set internal data cache
Definition desc_cfg.hpp:193
USB 设备类接口基类 / USB device class interface base.
uint8_t GetInterfaceStringIndex(size_t local_interface_index) const
返回已分配的接口字符串索引 Return the assigned USB string index for a local interface.
USB 端点基类 / USB Endpoint base class.
Definition ep.hpp:24
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
@ EP_AUTO
自动分配端点号 / Auto allocate
uint8_t GetAddress() const
获取端点地址(方向 + 号) / Get endpoint address (dir + num)
Definition ep.hpp:195
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
Definition ep.hpp:262
virtual void Configure(const Config &cfg)=0
配置端点协议参数 / Configure endpoint protocol parameters
@ INTERRUPT
中断端点 / Interrupt
virtual void Close()=0
关闭端点 / Close endpoint
State GetState() const
获取端点状态 / Get endpoint state
Definition ep.hpp:208
virtual ErrorCode Transfer(size_t size)=0
启动一次传输 / Start a transfer
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
Definition ep.hpp:246
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:24
virtual ConstRawData GetHIDDesc()
获取 HID 描述符 Get HID Descriptor
Definition hid.hpp:496
const char * GetInterfaceString(size_t local_interface_index) const override
返回本类暴露的第 N 个接口字符串 Return the string for the Nth local interface exposed by this class.
Definition hid.hpp:130
virtual ErrorCode OnGetInputReport(uint8_t report_id, DeviceClass::ControlTransferResult &result)
获取输入报告 Get Input Report
Definition hid.hpp:505
virtual ErrorCode OnSetReport(uint8_t report_id, DeviceClass::ControlTransferResult &result)
处理 SET_REPORT 请求 Handle SET_REPORT request
Definition hid.hpp:572
bool enable_out_endpoint_
是否启用 OUT 端点 / Whether OUT endpoint is enabled
Definition hid.hpp:667
virtual ErrorCode OnGetFeatureReport(uint8_t report_id, DeviceClass::ControlTransferResult &result)
获取特征报告 Get Feature Report
Definition hid.hpp:529
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化 HID 设备 Deinitialize HID device.
Definition hid.hpp:267
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, const char *interface_string=DEFAULT_INTERFACE_STRING)
HID 构造函数 HID class constructor.
Definition hid.hpp:116
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:332
Endpoint * GetOutEndpoint()
获取输出端点 Get OUT endpoint
Definition hid.hpp:651
bool HasIAD() override
检查是否包含IAD Check if IAD is present
Definition hid.hpp:298
uint8_t last_output_report_id_
最近的 Output Report ID / Last Output Report ID
Definition hid.hpp:674
Endpoint * ep_out_
输出端点指针 / OUT endpoint pointer
Definition hid.hpp:666
virtual ConstRawData GetReportDesc()=0
获取 HID 报告描述符 Get HID Report Descriptor
uint8_t idle_rate_
当前空闲率/ Current idle rate (unit 4ms)
Definition hid.hpp:673
ErrorCode SendInputReport(ConstRawData report)
发送输入报告到主机 Send Input Report to host
Definition hid.hpp:600
Endpoint * ep_in_
输入端点指针 / IN endpoint pointer
Definition hid.hpp:665
uint8_t out_ep_interval_
输出端点间隔 / OUT endpoint interval
Definition hid.hpp:661
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化 HID 设备,自动选择端点与描述符块 Initialize HID device and select descriptor block (IN or IN+OUT).
Definition hid.hpp:145
Protocol
HID 协议类型 / HID Protocol Types.
Definition hid.hpp:51
@ REPORT
报告协议 / Report protocol (通用)
@ BOOT
启动协议 / Boot protocol (键盘/鼠标)
size_t GetMaxConfigSize() override
获取最大配置描述符块长度 Get max config descriptor size.
Definition hid.hpp:316
HIDDescBlockINOUT desc_
HID 描述符块/ Descriptor block.
Definition hid.hpp:662
bool OwnsEndpoint(uint8_t ep_addr) const override
可选:端点归属判定 / Optional: endpoint ownership
Definition hid.hpp:300
size_t GetInterfaceCount() override
获取接口数量 Get number of interfaces
Definition hid.hpp:289
const char * interface_string_
接口字符串 / Interface string
Definition hid.hpp:670
virtual ErrorCode OnCustomClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, DeviceClass::ControlTransferResult &result)
处理自定义类请求 Handle custom class request
Definition hid.hpp:548
uint8_t in_ep_interval_
输入端点间隔 / IN endpoint interval
Definition hid.hpp:660
Endpoint::EPNumber out_ep_num_
输出端点号 / OUT endpoint number
Definition hid.hpp:664
bool HasOutEndpoint() const
查询是否支持OUT端点 Check if OUT endpoint is enabled
Definition hid.hpp:657
size_t itf_num_
接口号 / Interface number
Definition hid.hpp:669
uint8_t GetIDLERate() const
获取IDLE报告率 Get IDLE report rate
Definition hid.hpp:635
ReportType
HID 报告类型 / HID Report Types.
Definition hid.hpp:58
@ OUTPUT
输出报告 / Output report
@ INPUT
输入报告 / Input report
@ FEATURE
特征报告 / Feature report
Endpoint * GetInEndpoint()
获取输入端点 Get IN endpoint
Definition hid.hpp:643
virtual ErrorCode OnSetReportData(bool in_isr, ConstRawData &data)
处理 SET_REPORT 数据阶段 Handle SET_REPORT data stage
Definition hid.hpp:585
Endpoint::EPNumber in_ep_num_
输入端点号 / IN endpoint number
Definition hid.hpp:663
Protocol protocol_
当前协议类型 / Current protocol
Definition hid.hpp:672
uint8_t GetLastOutputReportID() const
获取最近一次 Output Report 的 Report ID Get the last received Output Report ID.
Definition hid.hpp:482
ErrorCode OnClassRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, DeviceClass::ControlTransferResult &result) override
处理 HID 类请求 Handle HID class-specific requests
Definition hid.hpp:377
bool inited_
初始化标志 / Initialization flag
Definition hid.hpp:668
HIDDescriptorType
HID 描述符类型 / HID Descriptor Types.
Definition hid.hpp:32
@ HID
HID 类描述符 / HID Class Descriptor.
@ REPORT
报告描述符 / Report Descriptor
@ PHYSICAL
物理描述符 / Physical Descriptor (rarely used)
virtual ErrorCode OnGetLastOutputReport(uint8_t report_id, DeviceClass::ControlTransferResult &result)
获取最近一次输出报告 Get last Output Report
Definition hid.hpp:517
ClassRequest
HID 类请求代码 / HID Class-Specific Requests.
Definition hid.hpp:40
@ 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:451
ErrorCode
定义错误码枚举
@ BUSY
忙碌 | Busy
@ NO_BUFF
缓冲区不足 | Insufficient buffer
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
端点描述符(7 字节)/ Endpoint descriptor (7 bytes)
Definition desc_cfg.hpp:91
接口描述符(9 字节)/ Interface descriptor (9 bytes)
Definition desc_cfg.hpp:75
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
bool write_zlp
发送 STATUS IN(发送 ZLP)/ Send STATUS IN (send ZLP)
包含 IN 端点的描述符块 Descriptor block with IN endpoint.
Definition hid.hpp:86
EndpointDescriptor ep_in
IN 端点描述符 / IN endpoint descriptor.
Definition hid.hpp:89
HIDDescriptor hid
HID 描述符 / HID descriptor.
Definition hid.hpp:88
InterfaceDescriptor intf
接口描述符 / Interface descriptor
Definition hid.hpp:87
包含 IN+OUT 端点的描述符块 Descriptor block with IN and OUT endpoints.
Definition hid.hpp:97
HIDDescriptor hid
HID 描述符 / HID descriptor.
Definition hid.hpp:99
EndpointDescriptor ep_out
OUT 端点描述符 / OUT endpoint descriptor.
Definition hid.hpp:101
EndpointDescriptor ep_in
IN 端点描述符 / IN endpoint descriptor.
Definition hid.hpp:100
InterfaceDescriptor intf
接口描述符 / Interface descriptor
Definition hid.hpp:98
HID描述符结构体 HID descriptor structure.
Definition hid.hpp:70
uint8_t bLength
描述符长度 / Descriptor length
Definition hid.hpp:71
uint8_t bNumDescriptors
后续描述符数量 / Number of subordinate descriptors
Definition hid.hpp:75
uint16_t bcdHID
HID 版本号 / HID class specification release.
Definition hid.hpp:73
HIDDescriptorType bReportDescriptorType
报告描述符类型 / Report descriptor type (0x22)
Definition hid.hpp:77
HIDDescriptorType bDescriptorType
描述符类型 / Descriptor type (0x21)
Definition hid.hpp:72
uint16_t wReportDescriptorLength
报告描述符长度 / Report descriptor length
Definition hid.hpp:78
uint8_t bCountryCode
国家码 / Country code
Definition hid.hpp:74