简介
USB技术是一个庞大而复杂的技术体系,需要常年的深入研究才能窥探其中的一角。我们这里先从相对简单
的入手点开始介绍,实现在应用层遍历所有USB接口上的设备。代码基于 WDK
中的 usbview
来实现。
USB描述符
在开始动手之前,我们需要先了解一下USB描述符的概念。USB描述符本身是一组数据的结构体,用来
记录USB设备本身的信息,以及该设备可以用于什么功能。系统会根据这些描述,来加载相关的驱动。
描述符的分类
共分为三大类:标准描述符、设备类描述符、厂商描述符。
类型 | 描述符 | 数值 |
---|---|---|
标准描述符 | 设备描述符(Device Descriptor) | 0x01 |
配置描述符(Configuration Descriptor) | 0x02 | |
字符串描述符(String Descriptor) | 0x03 | |
接口描述符(Interface Descriptor) | 0x04 | |
端点描述符(EndPont Descriptor) | 0x05 | |
设备类描述符 | 人机接口类描述符(HID) | 0x21 |
集线器类描述符(Hub Descriptor) | 0x29 | |
厂商描述符 | 0xFF |
更详细的信息可以从USB标准的相关网站获取(https://www.usb.org),这里只介绍部分信息。
设备描述符
1 | typedef struct _USB_DEVICE_DESCRIPTOR { |
域 | 值 | 描述 |
---|---|---|
bLength | 数字 | 此描述符的字节数。 |
bDecriptorType | 常量 | 描述符类型(此处应为0x01,即设备描述符)。 |
bcdUSB | BCD码 | USB版本号(BCD码)。 |
bDeviceClass | 设备类 | bDeviceClass = 0 时,表示设备类型使用接口描述符中定义 的类型,且各个接口独立工作。 bDeviceClass = 0xFF 时,表示设备类型是由厂商自定义的。 bDeviceClass = 1 ~ 0xFE 时,查表可得对应设备类值, 该设备在不同的接口上支持不同的类。且这些接口可能 不能独立工作。此值指出了这些接口集体的类定义。 |
bDeviceSubClass | 设备子类 | 这些码值的具体含义根据bDeviceClass 域来看。 如bDeviceClass 域为0,此域也须为0。 如bDeviceClass 域为0xFF,此域的所有值保留。 |
bDeviceProtocol | 设备协议 | 这些码的值视bDeviceClass 和 bDeviceSubClass 的值而定。 如果设备支持设备类相关的协议,此码标志了设备类的值。 如果此域的值为0,则此设备不支持设备类相关的协议, 然而,可能它的接口支持设备类相关的协议。 如果此域的值为0xFF,此设备使用厂商定义的协议。 |
bMaxPacketSize0 | 数字 | 端点0的最大包大小(仅8,16,32,64为合法值)。 |
idVendor | ID | 厂商标志(由USB-IF组织赋值)。 |
idProduct | ID | 产品标志(由厂商赋值)。 |
bcdDevice | BCD码 | 设备版本号(BCD 码)。 |
iManufacturer | 索引 | 描述厂商信息的字符串描述符的索引值。 |
iProduct | 索引 | 描述产品信息的字串描述符的索引值。 |
iSerialNumber | 索引 | 描述设备序列号信息的字串描述符的索引值。 |
bNumConfigurations | 数字 | 可能的配置描述符数目。 |
配置描述符
1 | typedef struct _USB_CONFIGURATION_DESCRIPTOR { |
域 | 值 | 描述 |
---|---|---|
bLength | 数字 | 此描述表的字节数长度。 |
bDescriptorType | 常量 | 配置描述符类型(此处为0x02)。 |
wTotalLength | 数字 | 此配置信息的总长(包括配置,接口,端点和设备类及 厂商定义的描述符),即:将要返回的配置信息总长度。 |
bNumInterfaces | 数字 | 此配置所支持的接口个数。 |
bConfigurationValue | 数字 | 在 SetConfiguration() 请求中用作参数来选定此配置。 |
iConfiguration | 索引 | 描述此配置的字串描述符的索引。 |
bmAttributes | 位图 | D7: 保留(设为1) D6: 自给电源 D5: 远程唤醒 D4 ~ D0:保留(设为1) 一个既用总线电源又有自给电源的设备会在MaxPower域 指出需要从总线取的电量。并设置D6为1。运行时期的实际 电源模式可由GetStatus(DEVICE) 请求得到。 |
MaxPower | 毫安 | 在此配置下的总线电源耗费量。以 2mA 为一个单位。 |
字符串描述符
1 | typedef struct _USB_STRING_DESCRIPTOR { |
域 | 值 | 描述 |
---|---|---|
bLength | 数字 | 此描述表的字节数(bString域的数值N+2) |
bDescriptorType | 常量 | 字符串描述符类型(此处应为0x03) |
bString | 字符串 | 宽字符字符串(WCHAR)类型 |
显示语言
的字符串描述符与 显示信息
的字符串描述符的区别在于bStrings
项的不同。
对于 显示语言
的字符串描述符来说 bStrings
项由多个 wLANGID[n]
数组元素组成,
每个 wLANGID[n]
是一个双字节的代表语言的ID值。一般都是 英语(美国)0x0409
。
而对于显示信息的字符串描述符而言,bStrings
则是描述信息的一组 UNICODE
编码。
接口描述符
1 | typedef struct _USB_INTERFACE_DESCRIPTOR { |
域 | 值 | 描述 |
---|---|---|
bLength | 数字 | 接口描述符的字节数大小 |
bDescriptorType | 常量 | 接口描述符的类型编号 |
bInterfaceNumber | 数字 | 接口的编号 |
bAlternateSetting | 数字 | 可替换的接口描述符编号。实际就是接口的描述符的编号。 |
bNumEndpoints | 数字 | 该接口使用的端点数,不包括端点0 |
bInterfaceClass | 接口类 | 接口类,可以通过查表获知 |
bInterfaceSubClass | 接口子类 | 接口子类 |
bInterfaceProtocol | 接口协议 | 接口遵循的协议 |
iInterface | 索引 | 描述该接口的字符串索引值 |
端点描述符
1 | typedef struct _USB_ENDPOINT_DESCRIPTOR { |
域 | 值 | 描述 |
---|---|---|
bLength | 数字 | 端点描述符字节数大小 |
bDescriptorType | 常量 | 端点描述符类型编号 |
bEndpointAddress | 数字 | 端点地址及输入输出属性 |
bmAttributes | 位图 | 端点的传输类型属性:0~1bit定义了传输类型 00=控制传输、01=同步传输、10=批量传输、11=中断传输。 |
wMaxPacketSize | 数字 | 端点收、发的最大包大小 |
bInterval | 毫秒 | 对周期性端点的访问间隔:同步传输,其值必须为1 |
设备类型的种类
设备类别bDeviceClass
值 | 说明 |
---|---|
0x00 | 使用接口描述符中提供的类别 |
0x02 | 通信类(CDC) |
0x09 | 集线器类 |
0xDC | 用于诊断用途的设备类 |
0xFE | 混杂类型设备类 |
0xFF | 厂商定义的设备类 |
接口类别bInterfaceClass
值 | 说明 |
---|---|
0x01 | 音频类 |
0x02 | 通信类(CDC) |
0x03 | 人机接口类(HID) |
0x05 | 物理类 |
0x06 | 图像类 |
0x07 | 打印机类 |
0x08 | 大数据存储类 |
0x09 | 集线器类 |
0x0A | CDC数据类 |
0x0B | 智能卡类 |
0x0D | 安全类 |
0x0E | 视频类 |
0x0F | 个人医疗护理类 |
0x10 | 音频/视频设备类 |
0xDC | 诊断设备类 |
0xE0 | 无线控制器类 |
0xEF | 混杂设备类 |
0xFE | 特定应用类(包括红外的桥接器等) |
0xFF | 厂商定义的设备 |
类别的交叉和独享
Base Class | Usage | Description |
---|---|---|
0x00 | Device | Use class information in the Interface Descriptors |
0x01 | Interface | Audio |
0x02 | Both | Communications and CDC Control |
0x03 | Interface | HID (Human Interface Device) |
0x05 | Interface | Physical |
0x06 | Interface | Image |
0x07 | Interface | Printer |
0x08 | Interface | Mass Storage |
0x09 | Device | Hub |
0x0A | Interface | CDC-Data |
0x0B | Interface | Smart Card |
0x0D | Interface | Content Security |
0x0E | Interface | Video |
0x0F | Interface | Personal Healthcare |
0x10 | Interface | Audio/Video Devices |
0xDC | Both | Diagnostic Device |
0xE0 | Interface | Wireless Controller |
0xEF | Both | Miscellaneous |
0xFE | Interface | Application Specific |
0xFF | Both | Vendor Specific |
(此表也适用于标准命令Get_Descriptor中wValue域高字节的取值含义)