最近在深入研究 USB HID 协议, 翻了不少教材和Spec文档,发现很多内容写得过于”照本宣科”----堆砌了一堆 Usage Page/Collection 的定义,读完却依然不知道这串 Hex 数据到底代表什么.
我认为, 理解 HID 最好的方式不是死磕枯燥的定义, 而是结合工具看疗效. 我将抛开晦涩的理论, 以最常见的 USB Keyboard 为例, 通过 Wireshark 抓包实战, 从 Report Descriptor 的解析入手, 一步步拆解 Input Report Raw Data. 当你亲手利用 Descriptor 将那串 0x00 00 20... 的 16 进制代码精准映射到具体的按键动作时, 那些原本枯燥的协议定义也就瞬间”活”过来了. 希望这篇基于实战的总结, 能帮到同样在啃 HID 协议的读者.
HID Report Descriptor
从一个简单的Mouse HID “Report Descriptor”开始. 这段Report Descriptor是微软HID Descriptor Tool提供的一个样例:From:MSDEV\Projects\test\Mouse.hid
再来看一个实际的Mouse Report Descriptor, 一个多功能鼠标(USB Node下有多个HID Node)(DevMgr view)
Winddk HidClient.exe会列出大量相同VID&PID的设备,需要根据UsagePage & Usage来确定当前操作的是哪个HID设备。
对于此例中的USB Mouse,可以通过Wireshark的USB Capture功能获得其Hid Report Descriptor(须拔插USB发射器):读者可下载附件中的usbkeyboardInput.pcapng文件, 打开后在Display filter输入usbhid(只显示usbhid协议), 即可得到HID Report Descriptor。(这是 USB Control Transfer 的一部分)
USB Mouse的HID Report Descriptor中有5组UsagePage/Usage/Collection & End Collection, 可能每一组对应DevMgr/USB Input device下的DevNode(另外设备命名也相似)相较而言,USB keyboard的HID Report Descriptor及其DevNode则简洁很多, 只有一组:另外, 仔细观察Keyboard与Mouse的HID Report Descriptor, 除了UsagePage/Usage/Collection & End Collection组数数量差异, 在Collection & End Collection中还有一个细小的差异:
USB Keyboard的HIDReport Descriptor中只有一组UsagePage/Usage/Collection & End Collection, 基础款USB Keyboard Collection和End Collection之间通常没有Report ID;USB Mouse的HIDReport Descriptor中有5组UsagePage/Usage/Collection & End Collection, 每组的Collection和End Collection之间中都有单独的Report ID. Report ID的作用将在后面的章节中阐述. 2. HID Report Descriptor的作用----解析HID Report 引用<HID跨接口设计与开发>书中(第九章P84)的一段话: 报告描述符用于描述报告的数据格式与数值定义, 一个实例的所有报告信息都包含在同一个报告描述符内.下图是书中HID Mouse的Input Report的示例。鼠标会以此格式为模板, 当发生按键/移动之类的事件, FW会将按键状态/位移相对值填入该模板, 形成一个3字节的Input Report, 发送给OS.
OS收到Input Report后, 以此模板从Input Report中解析各字段, 做出相应的动作. 这段话引出了HID Report Descriptor的模板化的作用: 在device端, device按HID Report Descriptor的规定, 生成Input Report; 在OS端, OS按HID Report Descriptor的规定, 解读Input Report中各个字段的含义. 下图, 是书中表9-2 HID Mouse Input Report对应的HID Report Descriptor:
以上仅是书本中的例子(书是照本宣科的烂书, 远不如问AI有用), 以现实中USB HID Mouse移动引起的HID Input report为例: USBCap抓到的HID Data(Raw data)为0x0201000000000000(下图中红框部分); Wireshark根据USB Mouse汇报的HID Report Descriptor, 解析了Raw data各个字段, 并最终呈现给分析者(下图绿框部分).本文的意图亦是如此:根据USB device 汇报的HID Report Descriptor, 解析Raw Data中的含义(诚然, USB HID device尚可通过Wireshark捕获, 但Wireshark解析将止步与其他使用HID协议的设备—I2C Touch Panel/I2C Touch Pad).
2.1. USB HID Keyboard的输入报告(Input Report)一例 用键盘在Wireshark Display Filter中输入字符1~8a~k, 见下图:
第27帧, Wireshark解析的HID Data如下:Frame 27:HID Data: 0000200000000000 本节将结合USB Keyboard的HID Report Descriptor分析这串Raw data其对应的按键操作.
2.1.1. 解析HID Report Descriptor的步骤解析HID Report Descriptor, 就是构造/解释HID Report模板的过程.a. HID Report Descriptor以UsagePage/Usage/Collection & End Collection进行分组, 每个分组代表一个DevNode(或者说一个功能), 因此第一步是从多个UsagePage/Usage/Collection & End Collection分组中挑选出一组UsagePage/Usage/Collection & End Collection, 对Collection & End Collection之间的内容进行分析;(先选蓝框,再选绿框)
b. Collection & End Collection之间又有3类Main Item, 分别
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289722.htm
[原创] 实战解析 USB HID 协议
99 浏览
3 回复
学习了。之前还是做模拟锁驱动时研究过点,但是没有向你一样系统性整理。
我正好是遇到i2c touch pad有问题,它底层也是hid协议,所以看了一遍
拍拖
学习了。之前还是做模拟锁驱动时研究过点,但是没有向你一样系统性整理。
我正好是遇到i2c touch pad有问题,它底层也是hid协议,所以看了一遍
学习了。之前还是做模拟锁驱动时研究过点,但是没有向你一样系统性整理。
我正好是遇到i2c touch pad有问题,它底层也是hid协议,所以看了一遍