USBHID设备数据包分析
Posted ZHONGCAI0901
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USBHID设备数据包分析相关的知识,希望对你有一定的参考价值。
文章目录
1. USB的一些基本概念
USB设备连接Host时,Host会主动获取设备的Descriptor。这样Host才了解Device支持哪些能力,然后加载对应的驱动。设备的Descriptor的关系大致如下:
下面USB2.0协议里面定义数据包,分析数据时会用到,如下:
- USB标准请求的数据结构
- bRequest字段和Descriptor Types
2. 抓取HID原始数据
通过PC工具Bus Hound抓取HID原始数据如下:
Phase - Phase Type
CTL USB control transfer
IN Data in transfer
OUT Data out transfer
Data - Hex dump of the data transferred
Descr - Description of the phase
Cmd... - Position in the captured data
Device Phase Data Description Cmd.Phase.Ofs(rep)
------ ----- ------------------------------------------------------------------------------------------------------ -------------------------------- ------------------
51.0 CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR 1.1.0
51.0 IN 12 01 00 02 00 00 00 08 6d 04 34 c5 01 29 01 02 00 01 ........m.4..).... 1.2.0
51.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 2.1.0
51.0 IN 09 02 3b 00 02 01 04 a0 31 ..;.....1 2.2.0
51.0 CTL 80 06 00 02 00 00 3b 00 GET DESCRIPTOR 3.1.0
51.0 IN 09 02 3b 00 02 01 04 a0 31 09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3b 00 07 05 81 03 08 ..;.....1..........!....";...... 3.2.0
00 08 09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02 ............!...."......... 3.2.32
51.0 CTL 00 09 01 00 00 00 00 00 SET CONFIG 4.1.0
51.0 CTL 80 06 02 03 09 04 04 00 GET DESCRIPTOR 5.1.0(2)
51.0 IN 1a 03 55 00 ..U. 5.2.0
51.0 CTL 80 06 02 03 09 04 1a 00 GET DESCRIPTOR 6.1.0(2)
51.0 IN 1a 03 55 00 53 00 42 00 20 00 52 00 65 00 63 00 65 00 69 00 76 00 65 00 72 00 ..U.S.B. .R.e.c.e.i.v.e.r. 6.2.0
52.0 CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR 9.1.0
52.0 IN 12 01 00 02 00 00 00 08 6d 04 34 c5 01 29 01 02 00 01 ........m.4..).... 9.2.0
52.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 10.1.0
52.0 IN 09 02 22 00 01 01 04 a0 31 ..".....1 10.2.0
52.0 CTL 80 06 00 02 00 00 22 00 GET DESCRIPTOR 11.1.0
52.0 IN 09 02 22 00 01 01 04 a0 31 09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3b 00 07 05 81 03 08 ..".....1..........!....";...... 11.2.0
00 08 .. 11.2.32
52.0 CTL 00 09 01 00 00 00 00 00 SET CONFIG 12.1.0
52.0 CTL 21 0a 00 00 00 00 00 00 SET IDLE 13.1.0
52.0 CTL 81 06 00 22 00 00 7b 00 GET DESCRIPTOR 14.1.0
52.0 IN 05 01 09 06 a1 01 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 81 03 95 05 05 08 19 01 29 05 ..........)...%.u.............). 14.2.0
91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 a4 00 05 07 19 00 2a a4 00 81 00 c0 ....u.....u...&......*..... 14.2.32
52.0 CTL 21 09 00 02 00 00 01 00 SET REPORT 15.1.0
52.0 OUT 01 . 15.2.0
51.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 16.1.0
51.0 IN 09 02 3b 00 02 01 04 a0 31 ..;.....1 16.2.0
51.0 CTL 80 06 00 02 00 00 3b 00 GET DESCRIPTOR 17.1.0
51.0 IN 09 02 3b 00 02 01 04 a0 31 09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3b 00 07 05 81 03 08 ..;.....1..........!....";...... 17.2.0
00 08 09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02 ............!...."......... 17.2.32
52.1 IN 00 00 0b 00 00 00 00 00 ........ 18.1.0
54 IN 01 00 23 00 00 00 00 00 00 00 00 00 ..#......... 19.1.0
52.1 IN 00 00 00 00 00 00 00 00 ........ 20.1.0
54 IN 01 00 23 00 01 00 00 00 00 00 00 00 ..#......... 21.1.0
52.1 IN 00 00 0f 00 00 00 00 00 ........ 22.1.0
54 IN 01 00 26 00 00 00 00 00 00 00 00 00 ..&......... 23.1.0
52.1 IN 00 00 00 00 00 00 00 00 ........ 24.1.0
54 IN 01 00 26 00 01 00 00 00 00 00 00 00 ..&......... 25.1.0
接下来我们一步一步分析上面数据包的代表的含义。
3. 分析HID数据包
3.1 获取设备描述符:
CTL 80 06 00 01 00 00 12 00
bmRequestType | bRequest | wValue | wIndex | wLength |
0x80 (Device->Host) | 0x06 (GET_DESCRIPTOR) | 0x0100 (0x01:Descriptor Type - DEVICE) (0x00:Descriptor Index) | 0x0000 (Zero or Language ID) | 0x0012 (Descriptor Length) |
IN 12 01 00 02 00 00 00 08 6d 04 34 c5 01 29 01 02 00 01
3.2 获取配置描述符:
CTL 80 06 00 02 00 00 3b 00
bmRequestType | bRequest | wValue | wIndex | wLength |
0x80 (Device->Host) | 0x06 (GET_DESCRIPTOR) | 0x0200 (0x02:Descriptor Type - CONFIGURATION) (0x00:Descriptor Index) | 0x0000 (Zero or Language ID) | 0x003b (Descriptor Length) |
IN
09 02 3b 00 02 01 04 a0 31
09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3b 00 07 05 81 03 08 00 08 09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02
NOTE:配置描述符获取了2次,第一次只获取前面的9Byte,知道配置描述符的总长度后,再次获取所有的数据。它不仅仅有Configuration Descriptor数据,还包含了Interface Descriptor和Endpoint Descriptor的数据。它们直接的关系如下:
3.2 接口描述符:
IN 09 02 3b 00 02 01 04 a0 31
09 04 00 00 01 03 01 01 00
09 21 11 01 00 01 22 3b 00 07 05 81 03 08 00 08 09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02
3.3 HID描述符:
IN 09 02 3b 00 02 01 04 a0 31 09 04 00 00 01 03 01 01 00
09 21 11 01 00 01 22 3b 00
07 05 81 03 08 00 08 09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02
3.4 端点描述符:
IN 09 02 3b 00 02 01 04 a0 31 09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3b 00
07 05 81 03 08 00 08
09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02
3.4 其它描述符:
IN 09 02 3b 00 02 01 04 a0 31 09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3b 00 07 05 81 03 08 00 08
09 04 01 00 01 03 01 02 00 09 21 11 01 00 01 22 b1 00 07 05 82 03 14 00 02
我们可以通过USB Device Tree Viewer可以知道该设备有2个Interface,每个interface都代表一个功能。前面的interface为Keyboard功能,后面的这个Interface为Mouse功能。数据解析如下:
3.5 USB 设置配置 SetConfiguration
SetConfiguration请求,用于主机为USB设备设置一个合适的配置值 ,该请求无数据阶段。
CTL 00 09 01 00 00 00 00 00
bmRequestType | bRequest | wValue | wIndex | wLength |
0x00 (Host->Device) | 0x09 (SET_CONFIGURATION) | 0x0001 (Configuration Value) | 0x0000 (Zero) | 0x0000 (Zero) |
3.6 String描述符:
CTL 80 06 02 03 09 04 1a 00
bmRequestType | bRequest | wValue | wIndex | wLength |
0x80 (Device->Host) | 0x06 (GET_DESCRIPTOR) | 0x0302 (0x03:Descriptor Type - STRING) (0x02:Descriptor Index) | 0x0409 (Language ID) | 0x001a (Descriptor Length) |
3.7 HID 设置空闲SET_IDLE:
SET_IDLE用于设置HID设备空闲速率,默认情况下空闲速率为0。
CTL 21 0a 00 00 00 00 00 00
bmRequestType | bRequest | wValue | wIndex | wLength |
0x21 (Direction:Host->Device) (Class/Interface) | 0x0a (SET_IDLE) | 0x0000 | 0x0000 | 0x0000 |
wValue(2):高字节用于指定空闲速率,以4ms为单位,可选的值为4ms~1020ms,低字节为ReportId.
wIndex(2):接口ID
wLength(2):数据长度,为0
3.8 获取HID Report描述符:
CTL 81 06 00 22 00 00 7b 00
bmRequestType | bRequest | wValue | wIndex | wLength |
0x81 (Direction:Device->Host) (Standard/Interface) | 0x06 (GET_DESCRIPTOR) | 0x2200 (0x22:Descriptor Type - HID_REPORT_DESCRIPTOR_TYPE) (0x00:Descriptor Index) | 0x0000 (Zero or Language ID) | 0x007b (Descriptor Length) |
IN 05 01 09 06 a1 01 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 81 03 95 05 05 08 19 01 29 05 91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 a4 00 05 07 19 00 2a a4 00 81 00 c0
解析如下:
下面是别人HID设备解析的结果,可以对比参考分析:
code char KeyBoardReportDescriptor[63] =
//表示用途页为通用桌面设备
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
//表示用途为键盘
0x09, 0x06, // USAGE (Keyboard)
//表示应用集合,必须要以 END_COLLECTION 来结束它,见最后的 END_COLLECTION
0xa1, 0x01, // COLLECTION (Application)
//表示用途页为按键
0x05, 0x07, // USAGE_PAGE (Keyboard)
//用途最小值,这里为左 ctrl 键
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
//用途最大值,这里为右 GUI 键,即 window 键
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
//逻辑最小值为 0
0x15, 0x00, // LOGICAL_MINIMUM (0)
//逻辑最大值为 1
0x25, 0x01, // LOGICAL_MAXIMUM (1)
//报告大小(即这个字段的宽度)为 1bit,所以前面的逻辑最小值为 0,逻辑最大值为 1
0x75, 0x01, // REPORT_SIZE (1)
//报告的个数为 8,即总共有 8 个 bits
0x95, 0x08, // REPORT_COUNT (8)
//输入用,变量,值,绝对值。像键盘这类一般报告绝对值,
//而鼠标移动这样的则报告相对值,表示鼠标移动多少
0x81, 0x02, // INPUT (Data,Var,Abs)
//上面这这几项描述了一个输入用的字段,总共为 8 个 bits,每个 bit 表示一个按键
//分别从左 ctrl 键到右 GUI 键。这 8 个 bits 刚好构成一个字节,它位于报告的第一个字节。
//它的最低位,即 bit-0 对应着左 ctrl 键,如果返回的数据该位为 1,则表示左 ctrl 键被按下,
//否则,左 ctrl 键没有按下。最高位,即 bit-7 表示右 GUI 键的按下情况。中间的几个位,
//需要根据 HID 协议中规定的用途页表(HID Usage Tables)来确定。这里通常用来表示
//特殊键,例如 ctrl, shift, del 键
//这样的数据段个数为 1
0x95, 0x01, // REPORT_COUNT (1)
//每个段长度为 8bits
0x75, 0x08, // REPORT_SIZE (8)
//输入用,常量,值,绝对值
0x81, 0x03, // INPUT (Cnst,Var,Abs)
//上面这 8 个 bit 是常量,设备必须返回 0
//这样的数据段个数为 5
0x95, 0x05, // REPORT_COUNT (5)
//每个段大小为 1bit
0x75, 0x01, // REPORT_SIZE (1)
//用途是 LED,即用来控制键盘上的 LED 用的,因此下面会说明它是输出用
0x05, 0x08, // USAGE_PAGE (LEDs)
//用途最小值是 Num Lock,即数字键锁定灯
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
//用途最大值是 Kana,这个是什么灯我也不清楚^_^
0x29, 0x05, // USAGE_MAXIMUM (Kana)
//如前面所说,这个字段是输出用的,用来控制 LED。变量,值,绝对值。
//1 表示灯亮, 0 表示灯灭
0x91, 0x02, // OUTPUT (Data,Var,Abs)
//这样的数据段个数为 1
0x95, 0x01, // REPORT_COUNT (1)
//每个段大小为 3bits
0x75, 0x03, // REPORT_SIZE (3)
//输出用,常量,值,绝对
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
//由于要按字节对齐,而前面控制 LED 的只用了 5 个 bit,
//所以后面需要附加 3 个不用 bit,设置为常量。
//报告个数为 6
0x95, 0x06, // REPORT_COUNT (6)
//每个段大小为 8bits
0x75, 0x08, // REPORT_SIZE (8)
//逻辑最小值 0
0x15, 0x00, // LOGICAL_MINIMUM (0)
//逻辑最大值 255
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
//用途页为按键
0x05, 0x07, // USAGE_PAGE (Keyboard)
//使用最小值为 0
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
//使用最大值为 0x65
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
//输入用,变量,数组,绝对值
0x81, 0x00, // INPUT (Data,Ary,Abs)
//以上定义了 6 个 8bit 宽的数组,每个 8bit(即一个字节)用来表示一个按键,所以可以同时
//有 6 个按键按下。没有按键按下时,全部返回 0。如果按下的键太多,导致键盘扫描系统
//无法区分按键时,则全部返回 0x01,即 6 个 0x01。如果有一个键按下,则这 6 个字节中的第一
//个字节为相应的键值(具体的值参看 HID Usage Tables),如果两个键按下,则第 1、 2 两个
//字节分别为相应的键值,以次类推。
//关集合,跟上面的对应
0xc0 // END_COLLECTION
;
4.参考资料
USB 中文网:
http://www.usbzh.com/article/detail-76.html
以上是关于USBHID设备数据包分析的主要内容,如果未能解决你的问题,请参考以下文章