简介
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域高字节的取值含义)