本文是<实战解析 USB HID 协议>的后续, 文中只有一个细小的新知识点, 主要是补充USB HID Mouse的HID Report Descriptor和Input Report作为例子, 供读者学习参考. 这回我换套工具, 用(昂贵的)Lecroy USB Protocol Suite捕捉/呈现USB Mouse数据(其实USB协议分析仪主要用在硬件产品设计阶段, 用于定位/分析回路或固件设计缺陷; 用来抓USB2.0 Full Speed设备的数据实属杀鸡用牛刀).
1. 解析USB HID Mouse的HID Report Descriptor
下图是USB Protocol Suite在USB发射器插入后捕获的USB设备的SETUP Transfer:

上图中
Transfer 1# ~ Transfer 17#是所有USB2.0设备所共有的Standard Request;
Transfer 18# ~ Transfer 19#: USB Host向USB Device请求USB Keyboard HID Report Descriptor;
Transfer 20# ~ Transfer 21#: USB Host向USB Device请求USB Mouse HID Report Descriptor.
USB Protocol Suite解析得到的Keyboard/Mouse Report Descriptor分别如下:

USB Keyboard HID Report Descriptor (完整Keyboard Report Descriptor 报告见附件html文档)

USB Mouse HID Report Descriptor (完整Mouse Report Descriptor 报告见附件html文档)
USB Protocol Suite 为USB Keyboard生成的HTML文档大小32KB; 为USB Mouse生成的HTML文档大小 80KB. 可见USB Mouse的功能更为复杂(毕竟在设备管理器里HID Keyboard才1个虚拟设备; HID Mouse有5个虚拟设备).

依然使用前一篇文章总结出来的方法, 按以下步骤进行解析:
a). 按UsagePage/Usage/Collection & End Collection进行分组(绿框部分) ;
b). 把Collection & End Collection中相同的Main Item归为一类(红框部分), 同时计算Hid Report将占用的Size;
c). 解读各个字段含义;
Step a). 按UsagePage/Usage/Collection & End Collection进行分组. 按这个规则可以分5组, 如下图. 5个分组中只有第一个分组的用途是Mouse (Usage (Mouse)), 因此我们将注意力集中在此:

Step b). 把Collection & End Collection中相同的Main Item归为一类(下图中所有红框都属于Input Main Item).

b.1 ). 在这个集合中只有一个 Main Item—Input Item.
b.2 ). 计算 HID Input Report 大小. 计算规则在前一篇文章中也有提及: 从上往下解析Report Descriptor, 遇到Report Size/Report Count字段, 作为HID Input Report中某一字段的开始; 遇到Main Item后(本文中为input()), HID Input Report中某一字段的结束.
如前一张截图所示, 这个USB Mouse 是一个多功能设备----有多个Collection/End Collection. 但是所有USB Mouse的数据都是通过同一个USB Endpoint (端点2#)进行传输. FW使用ReportID来区分不同的功能: 基础的鼠标功能还是厂商自定义的功能. 该ReportID固定占用1字节, 位于Input Report的最开始位置(Offset=0)
Descriptor 描述的Input Report字段功能及大小如下:
| 字段 | 大小 | 注释 |
| Usage Page = Button | Report Count=16 * Report Size= 1bit | 该鼠标有16个按键, 用1bit代表每个按键按下/松开情况 |
| Usage Page = Generic Desktop Controls | Report Count=2 * Report Size= 12bit | 12bit代表 X坐标变化值; 12bit 代表Y坐标变化值; |
| Report Count=1 * Report Size= 8bit | 8bit代表纵向滚轮值 |
| Report Count=1 * Report Size= 8bit | 8bit代表横向滚轮值 |
该HID Report Descriptor描述的Input Report的大小=1Byte + 16*1bit+2*12bit+1*8bit+1*8bit=8 Byte. 这个值与USB Protocol Suite捕获的USB Mouse 包的大小一致(下图中最右边绿框所示):

(注: 表格中倒数第二项Usage = Wheel 设置了Global Item: Report Size=8, Report Count =1.
当OS解析到表中最后一项Usage Page = Consumer, Usage = AC Pan时发现它只更新了Global Item: Report Count =1, 根据 HID 协议的状态保持机制(Global Items 状态一旦设置,在遇到新值前持续有效), AC Pan 自动继承了 Wheel 设定的 Report Size=8.
2. Hid Mouse Input Report实例
附件Transfer_235_Fields_HID_Decoder_Interrupt_In_Endp.htm的内容展示了USB Mouse移动时, OS获得的HID Input Report. Lecroy USB Protocol Suite对HID Input Report的展示界面看着挺友好的 (贵有贵的道理).

图中左下角蓝框展示了Transfer #235的USB data payload:
| Hex dump Value (小端序) | 02 00 00 02 F0 00 00 00 |
结合USB Mouse HID Report Descriptor的描述, 可得到各字段值:
| 字段名称 | Raw Data | Note |
| Report ID | 2 | N/A |
| Buttons (0-7) | 0 | 无按键按下 |
| Buttons (8-15) | 0 | 无按键按下 |
| X-Axis | 2 | X 轴移动位置 相对偏移=2 |
| Y-Axis | F | Y 轴移动位置 相对偏移=15 |
| Wheel (Vertical) | 0 | 滚轮无动作 |
| AC Pan (Horiz) | 0 | 横向滚轮无动作 |
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!