USB描述符介绍
USB描述符是主机识别USB设备的依据,主机根据设备的描述符来加载相应的驱动
USB描述符的作用
USB描述符信息存储在USB设备中,在枚举过程中,USB主机会向USB设备发送GetDescriptor请求,USB设备在收到这个请求之后,会将USB描述符信息返回给USB主机,USB主机分析返回来的数据,判断出该设备是哪一种USB设备,建立相应的数据链接通道。
USB描述符的内容
标准的USB设备总共包括五种USB描述符:设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符。HID设备除了需要标准的USB描述符还需要HID报告描述符,HID物理描述符可选。HID是一种USB通信协议,无需安装驱动就能进行交互,
设备描述符
设备描述符主要包括厂商ID(vendorID)和产品ID(productID)、USB协议等内容。一个设备只有一个设备描述符。
名称 | 字节大小 | 说明 |
---|---|---|
bLength | 1 | 描述符长度(18字节) |
bDescriptorType | 1 | 描述符类型(设备描述符为0x01) |
bcdUSB | 2 | 设备使用的USB协议版本 |
bDeviceClass | 1 | 类代码 |
bDeviceSubClass | 1 | 子类代码 |
bDeviceProtocol | 1 | 设备使用的协议 |
bMaxPackeSize0 | 1 | 端点0最大包长 |
idVender | 2 | 厂商ID |
idProduct | 2 | 产品ID |
bcdDevice | 2 | 设备版本号 |
iManufacturer | 1 | 描述厂商的字符串的索引 |
iProduct | 1 | 描述产品的字符串的索引 |
iSerialNumber | 1 | 产品序列号字符串的索引 |
bNumConfigurations | 1 | 可能的配置数 |
配置描述符
配置描述符,定义了设备的配置信息。一个设备可以有多个配置描述符。配置描述符描述了该配置的接口数、供电模式等信息。
名称 | 字节大小 | 说明 |
---|---|---|
bLength | 1 | 该描述符字节数长度(9字节) |
bDescriptorType | 1 | 描述符类型(配置描述符为0x02) |
wTotalLength | 2 | 此配置信息的总长度,(包括配置,接口,端点和设备类及厂商定义的描述符) |
bNumInterfaces | 1 | 该配置所支持的接口个数 |
bConfigurationValue | 1 | 在SetConfiguration()请求中用做参数来选定此配置 |
iConfiguration | 1 | 描述此配置的字串描述表索引 |
bmAttributes | 1 | 配置特性 |
MaxPower | 1 | 在此配置下的总线电源耗费量 2mA为一个单位 |
接口描述符
接口描述符描述了该接口的端点数目、以及子类代码等。由配置描述符可知一个设备可以有多个接口描述符。
名称 | 字节大小 | 说明 |
---|---|---|
bLength | 1 | 该描述符字节数长度(9字节) |
bDescriptorType | 1 | 描述符类型(接口描述符为0x04) |
bInterfaceNumber | 1 | 接口编号,当前配置支持的接口数组索引 |
bAlternateSetting | 1 | 可选设置的索引值 |
bNumEndpoints | 1 | 此接口用的端点数量 |
bInterfaceClass | 1 | 接口所属的类值 |
bInterfaceSubClass | 1 | 子类代码 |
bInterfaceProtocol | 1 | 接口协议 |
iInterface | 1 | 描述此接口的字串描述表的索引值 |
端点描述符
每个端点都有其端点描述符。主要描述了该端点地址、属性、数据包大小等信息。其数量由接口描述符决定。所以一个设备也可以由多个端点描述符。
名称 | 字节大小 | 说明 |
---|---|---|
bLength | 1 | 该描述符字节数长度(7字节(0X07)) |
bDescriptorType | 1 | 描述符类型(接口描述符为0x05) |
bEndpointAddress | 1 | USB设备的端点地址 |
bmAttributes | 1 | 端点属性 |
wMaxPacketSize | 2 | 本端点接收或发送的最大信息包大小 |
bInterval | 1 | 主机查询端点的时间间隔 |
字符串描述符
字符串描述符是可选的。如果不支持字符串描述符,其设备,配置,接口描述符内的所有字符串描述符索引都必须为0。
名称 | 字节大小 | 说明 |
---|---|---|
bLength | 1 | 该描述符字节数长度 |
bDescriptorType | 1 | 描述符类型(字符串描述符为0x03) |
bString | N | Unicode编码字符串 |
HID报告描述符(HID设备独有的)
USB设备中有一大类就是HID设备,也就是我们常见的Human Interface Devices ,人机接口设备,HID设备的类型定义放在接口描述符中。
当USB一个设备为HID设备时,其设备描述符里面的bDeviceClass、bDeviceSubClass、bDeviceProtocol应为0,具体的定义在接口描述符中,接口描述符bInterfaceClass、bInterfaceSubClass、bInterfaceProtocol三个值如下:
HID设备接口描述符特征
名称(均在接口描述符里) | 值 |
---|---|
bInterfaceClass | 0x03:表示HID为设备 |
bInterfaceSubClass | 0x00:对无需支持引导的HID设备;0x01:对支持引导的USB设备(鼠标、键盘);其他:保留。 |
bInterfaceProtocol | 当bInterfaceSubClass为0x00,此值无效。当bInterfaceSubClass为0x01。设置为0x01:键盘接口 设置为0x02:鼠标接口 |
HID描述符
名称 | 字节大小 | 说明 |
---|---|---|
bLength | 1 | 该描述符字节数长度(由下级描述符多少决定) |
bDescriptorType | 1 | 描述符类型(HID描述符为0x21) |
bcdHID | 2 | HID协议版本 |
bCountryCode | 1 | 国家代码 |
bNumDescriptor | 1 | HID设备支持的下级描述符的数量(也就是HID设备特有的报告描述符和物理描述符的综合) |
bDescriptorType | 1 | 下级描述符类型(第一个必须是报告描述符0X22) |
wDescriptorLength | 2 | 下级描述符的长度 |
… | … | … (这里会根据下级描述符数量罗列) |
HID报告描述符
如下为一个HID鼠标的报告描述符
报告描述符解析
这是一个鼠标的HID报告描述符。首先去除中间的观察它的头尾部分可以看的出头尾部分主要表述这是一个鼠标设备。
USAGE_PAGE (Generic Desktop) 05 01
USAGE (Mouse) 09 02
COLLECTION (Application) A1 01
USAGE (Pointer) 09 01
COLLECTION (Physical) A1 00
.......
END_COLLECTION C0
END_COLLECTION C0
中间部分描述符了相关细节
USAGE_PAGE (Button) 05 09
USAGE_MINIMUM (Button 1) 19 01
USAGE_MAXIMUM (Button 3) 29 03
LOGICAL_MINIMUM (0) 15 00
LOGICAL_MAXIMUM (1) 25 01
REPORT_COUNT (3) 95 03
REPORT_SIZE (1) 75 01
INPUT (Data,Var,Abs) 81 02
REPORT_COUNT (1) 95 01
REPORT_SIZE (5) 75 05
INPUT (Cnst,Var,Abs) 81 03
USAGE_PAGE (Generic Desktop) 05 01
USAGE (X) 09 30
USAGE (Y) 09 31
LOGICAL_MINIMUM (-127) 15 81
LOGICAL_MAXIMUM (127) 25 7F
REPORT_SIZE (8) 75 08
REPORT_COUNT (2) 95 02
INPUT (Data,Var,Rel) 81 06
内容的详细介绍如下:
USAGE_PAGE (Button)
表示一个数据描述的开始,所描述的数据用于按键。在左侧【HID Items】栏中双击【USAGE_PAGE】项时,弹出的窗口中选择【Button】项即可。
USAGE_MINIMUM (Button 1)
表示最小按键为Button 1。前面选择了【Button】,然后再单击【USAGE_MINIMUM】项时,窗口中则可以选择【Button 1】~【Button 63】。
USAGE_MAXIMUM (Button 3)
表示最大按键为Button 3。实际上第二和第三行表示了一共有三个按键:Button 1 ~ Button3。
LOGICAL_MINIMUM (0)
表示按键状态的最小值为 0。
LOGICAL_MAXIMUM (1)
表示按键状态的最大值为 1。
REPORT_COUNT (3)
表示数量为 3。
REPORT_SIZE (1)
表示占用空间,单位为 bit,1 表示占用空间为 1-bit。
INPUT (Data,Var,Abs)
表示以上 3-bit 数据为发送给电脑的数据,Data表示这个数据是可变的,由用户决定。6、7、8三行代码表明:表示三个按钮状态的数据占用 3-bit 的空间,分别是 bit0 ~ bit2,数据是可变的。
REPORT_COUNT (1)
表示数量 1。
REPORT_SIZE (5)
表示占用空间为 5-bit。
INPUT (Cnst,Var,Abs)
表示以上 5-bit 数据为发送给上位机的固定数据,Cnst即为 Const 常量的意思。9、10、11行代码表示还有 5-bit 的不可变数据。即图 1 中第一个字节中的 5 个 bit 的不使用数据。
USAGE_PAGE (Generic Desktop)
表示开始描述一个新的数据了。
USAGE (X)
表示描述的是 X 坐标,在USAGE_PAGE中选择了Generic Desktop后,双击【USAGE】项则可以选择【X】。
USAGE (Y)
表示描述的是 Y 坐标,由于 X、Y 坐标格式一致,所以放在一起描述了,这是省略的写法,完全可以单独定义 Y 坐标数据。
LOGICAL_MINIMUM (-127)
表示最小值为 -127。
LOGICAL_MAXIMUM (127)
表示最大值为 127。我们知道一个字节可存储的有符号整数范围为-128~127。这里只是为了对称,将最小值设为 -127。
REPORT_SIZE (8)
表示以上 X、Y数据占用 8-bit 空间。
REPORT_COUNT (2)
数量为 2。
INPUT (Data,Var,Rel)
表示以上2个字节是发送给上位机的可变数据,Rel表示这是相对值
键盘报告描述符
后续补齐。
写HID报告描述符和分析HID报告描述符很麻烦吧
附 HID报告描述符分析工具:USB中文网出品
https://www.usbzh.com/article/detail-537.html