0%

应用层遍历所有接入的USB设备(1)

简介

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct _USB_DEVICE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEVICE_DESCRIPTOR, *PUSB_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
2
3
4
5
6
7
8
9
10
typedef struct _USB_CONFIGURATION_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_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
2
3
4
5
typedef struct _USB_STRING_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
WCHAR bString[1];
} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;
描述
bLength 数字 此描述表的字节数(bString域的数值N+2)
bDescriptorType 常量 字符串描述符类型(此处应为0x03)
bString 字符串 宽字符字符串(WCHAR)类型

显示语言 的字符串描述符与 显示信息 的字符串描述符的区别在于bStrings项的不同。
对于 显示语言 的字符串描述符来说 bStrings 项由多个 wLANGID[n] 数组元素组成,
每个 wLANGID[n] 是一个双字节的代表语言的ID值。一般都是 英语(美国)0x0409
而对于显示信息的字符串描述符而言,bStrings 则是描述信息的一组 UNICODE 编码。

接口描述符
1
2
3
4
5
6
7
8
9
10
11
typedef struct _USB_INTERFACE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
描述
bLength 数字 接口描述符的字节数大小
bDescriptorType 常量 接口描述符的类型编号
bInterfaceNumber 数字 接口的编号
bAlternateSetting 数字 可替换的接口描述符编号。实际就是接口的描述符的编号。
bNumEndpoints 数字 该接口使用的端点数,不包括端点0
bInterfaceClass 接口类 接口类,可以通过查表获知
bInterfaceSubClass 接口子类 接口子类
bInterfaceProtocol 接口协议 接口遵循的协议
iInterface 索引 描述该接口的字符串索引值
端点描述符
1
2
3
4
5
6
7
8
typedef struct _USB_ENDPOINT_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bEndpointAddress;
UCHAR bmAttributes;
USHORT wMaxPacketSize;
UCHAR bInterval;
} USB_ENDPOINT_DESCRIPTOR, *PUSB_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域高字节的取值含义)