|
|
做HID开发第一个坎就是报文结构。很多人照着例程改通了,但一问“为什么这么摆字节”就懵。这篇把USB HID的报文结构从头捋一遍,建议配合抓包工具边看边学。
一、先理清三个层次
HID的报文分三个层次,搞混的人基本都是把这三层混为一谈:
| 层次 | 作用 | 出现时机 |
| 描述符 | 定义设备能力与报告格式 | 枚举阶段 |
| 报告 | 实际收发的数据 | 运行阶段 |
| 传输 | USB层面的管道 | 全过程 |
描述符是“合同”,报告是“履约”,传输是“快递通道”。合同签错了,后面履约再认真也白搭。
二、描述符的六种类型
HID描述符规范里定义了六种:
- HID描述符:声明报告描述符长度、HID类别规范版本
- 报告描述符:真正定义报文格式的核心,用“项”(Item)堆叠
- 物理描述符:可选,描述物理控件属性
- 厂商/产品/序列号字符串描述符:设备身份信息
- 接口关联描述符:复合设备用
- 端点描述符:说明中断端点的轮询间隔
重点全在报告描述符。它由一堆短项(1-2字节头+数据)组成,常见的Usage Page(用法页)比如0x01是通用桌面控件(鼠标键盘都属于这页),0x07是键盘按键。
三、报告描述符怎么读
读报告描述符的关键是记住几类“项”的语义:
- Usage / Usage Page:这个字段是干什么的
- Collection / End Collection:把相关字段组织成逻辑集合
- Report Count / Report Size:声明有几个字段、每个几位
- Input / Output / Feature:数据流向
举个最小键盘例子:先声明Usage Page=0x07(键盘页),Usage Minimum=0xE0、Usage Maximum=0xE7(左Ctrl到右GUI共8个修饰键),Logical Minimum=0、Logical Maximum=1,Report Size=1、Report Count=8,Input——这一组就定义了报文第一个字节的8个位图。接着同样手法定义6个普通按键码位。
四、解析错一位的后果
字节数和位偏移算错是新手最常栽的坑:
- 按键码整体偏移一位,按A出B
- 位图顺序反了,修饰键全乱
- 报告长度对不上,主机直接拒收
排查方法就一招:拿已知设备的报告描述符逐项对照,或者干脆用现成的HID解析工具反查。别手算,人脑算位图没有不出错的。
五、实操建议
- 开发环境先用官方SDK的例程跑通,再改
- 抓包工具全程开着,对照描述符看实际报文
- 每改一次描述符,用主机端的“测试页”验证识别
- 版本管理从第一天开始,描述符改动必须留档
描述符吃透了,HID开发就过了一半。更多细节欢迎到手机脚本开发教程版块翻相关帖子。 |
|