USB总线专题(四)——枚举过程

1. 概述

USB 描述符信息存储在 USB 设备中,在枚举过程中,USB 主机会向 USB 设备发送 GetDescriptor 请求,USB 设备在收到这个请求之后,会将 USB 描述符信息返回给 USB 主机,USB 主机分析返回来的数据,判断出该设备是哪一种 USB 设备,建立相应的数据链接通道。

USB 设备使用描述符报告其属性。描述符是具有定义格式的数据结构,每个描述符都以字节宽度字段开头,该字段包含描述符中的总字节数,后跟一个标识描述符类型的字节宽度字段。在 USB 设备枚举过程中,主机端的协义软件需要解析从 USB 设备读取的所有描述符信息。在 USB 主向设备发送读取描述符的请求后,USB 设备将所有的描述符以连续的数据流方式传输给 USB 主机。主机从第一个读到的字符开始,根据双方规定好的数据格式,顺序地解析读到的数据流。

每个 USB 设备公开的设备描述符,指示设备的类信息、 供应商和产品标识符,以及多个配置。 每个配置还公开其配置描述符,该值指示大量接口和功耗特征。 每个接口公开其包含类和数量的终结点信息的替代设置的每个接口描述符。 每个接口中的每个终结点公开终结点,描述符可指明终结点类型和最大数据包大小。

描述符类型:

标准的 USB 设备有 5 种 USB 描述符:设备描述符(Device Descriptor)、配置描述符(Configuration Descriptor)、接口描述符(Interface Descriptor)、端点描述符(Endpoint Descriptor)和字符串描述符(String Descriptor)。描述符具有类似的格式,它们的第一个字段都是 bLength,第二个字段都是 bDescriptorType。七种描述符在使用时以 bDescriptorType 字段来区分。一设备至少要包含设备描述符、配置描述符和接口描述符,如果USB 设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。

每个 USB 设备只有一个设备描述符,而一个设备中可包含一个或多个配置描述符,即 USB 设备可以有多种配置。设备的每一个配置中又可以包含一个或多个接口描述符,即 USB 设备可以支持多种功能(接口),接口的特性通过描述符提供。

在 USB 主机访问 USB 设备的描述符时,USB 设备依照设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符顺序将所有描述符传给主机。一设备至少要包含设备描述符、配置描述符和接口描述符,如果 USB 设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。

2. 设备描述符

设备描述符描述的是设备的整体信息,与设备本身一一对应,包括对设备及在设备配置中起全程作用的信息,包括制造商标识号 ID、产品序列号、所属设备类号、默认端点的最大包长度和配置描述符的个数等。一个设备只能有一个设备描述符。在主机对 USB 设备枚举的过程中,首先要做的就是获取设备描述符,以对设备有一个整体的了解。

设备描述符由14个字段组成,总长度18字节:

typedef struct _USB_DEVICE_DESCRIPTOR_
{
    BYTE        bLength,
    BYTE        bDescriptorType,
    WORD        bcdUSB,    //2字节
    BYTE        bDeviceClass,
    BTYE        bDeviceSubClass,
    BYTE        bDeviceProtol,
    BYTE        bMaxPacketSize0,
    WORD        idVenderI,    //2字节
    WORD        idProduct,    //2字节
    WORD        bcdDevice,    //2字节
    BYTE        iManufacturer,
    BYTE        iProduct,
    BYTE        iSerialNumber,
    BYTE        iNumConfiguations
}USB_DEVICE_DESCRIPTOR;

/*
 b  一个字节,=8bits;
 w  两个字节,=16bits;
 bm  按位寻址;
 bcd 用BCD码表示;
 i   索引值
 id  标识码
*/

解释:

字段名 解释
bLength 描述符大小,固定为 0x12
bDescriptorType 设备描述符类型,固定为 0x01
bcdUSB USB 规范发布号,表示了本设备能适用于那种协议,如 2.0=0200,1.1=0110 等
bDeviceClass 该设备所属的标准设备类,USB 协议中对常见的设备进行了分类。该字段值为 0x01~0xFE 时,表示是 USB 协议中已定义的设备类,常用的 HID 设备类编号为 0x03
bDeviceSubClass 子类型代码(由USB分配),如果 bDeviceClass 值是 0,一定要设置为 0.其它情况就跟据 USB-IF 组织定义的编码
bDeviceProtocol 协议代码(由USB分配),如果使用 USB-IF 组织定义的协议,就需要设置这里的值,否则直接设置为 0。如果厂商自己定义的可以设置为 FFH
bMaxPacketSize0 端点 0 最大分组大小(只有 8,16,32,64 有效),对于低速 USB 设备,bMaxPacketSize0 为8;对于全速 USB 设备,bMaxPacketSize0 为 8、16、32、64;对于高速 USB 设备,bMaxPacketSize0 为 64。
idVendor 用于表示 USB 设备供应商的 ID。USB 组织中规定每种产品都必须包含一个供应商 ID,这样可以使主机加载合适的驱动程序。
idProduct 用于表示 USB 产品的 ID,由设备供应商提供。idProduct 用于表示特定的 USB 设备,在 USB 设备上电的时候可以帮助 USB 主机选择合适的驱动程序。
bcdDevice 用于表示 USB 设备的版本号,它以 BCD 码的形式表示。一般来说 bcdDevcie 由设备供应商指定,在 USB 设备上电的时候可以帮助 USB 主机选择合适的驱动程序。
iManufacturer 厂商描述符字符串索引.索引到对应的字符串描述符. 为 0 则表示没有
iProduct 产品描述符字符串索引
iSerialNumber 用于表示设备序列号字符串描述符的索引值,如果没有,可以置为 0
bNumConfigurations 用于表示该 USB 设备所支持的配置数。

一个 USB CCID 设备的描述符为:与上表中的字段是一一对应的。

3. 配置描述符

配置描述符定义了设备的配置信息,一个设备可以有多个配置描述符。配置描述符中包括了描述符的长度(属于此描述符的所有接口描述符和端点描述符的长度的和)、供电方式(自供电/总线供电)、最大耗电量等。主机发出 USB 标准命令 Get_Descriptor 要求得到设备的某个配置描述符,那么除了此配置描述符以外,此配置包含的所有接口描述符与端点描述符都将提供给 USB 主机。

一个 USB 设备可以有多种配置,不同的配置使设备工作在不同的状态下,每个配置必须有一个配置描述符。其格式包括 8 个字段,共 9 字节。

typedef struct _USB_CONFIGURATION_DESCRIPTOR_
{
    BYTE      bLength,
    BYTE      bDescriptorType,
    WORD      wTotalLength,
    BYTE      bNumInterfaces,
    BYTE      bConfigurationValue,
    BYTE      iConfiguration,
    BYTE      bmAttributes,
    BYTE      bMaxPower
}USB_CONFIGURATION_DESCRIPTOR;
字段名 解释
bLength 配置描述符长度,配置描述符长度为 9 字节大小。
bDescriptorType 描述符类型,配置描述符类型为 0x02。
wTotalLength 配置描述符信息总的大小,包括接口描述符、端点描述符等。
bNumInterfaces USB 接口数量。
bConfigurationValue 当使用 SetConfiguration 和 GetConfiguration 请求时所指定的配置索引值。
iConfiguration 描述配置的字符串描述符索引。
bmAttributes 供电配置,位详细定义如下:D7 保留,必须置1;D6 自供电模式; D5 远程唤醒; D4~D0 保留
bMaxPower 最大功耗,以 2mA 为单位,例如 0x32 为 50*2 = 100mA。USB 设备可以从 USB 总线上获得最大的电流为 500mA,因此bMaxPower 字段的最大值可以设置为 250。

示例:

4.接口描述符

如果一个配置描述符不止支持一个接口描述符,并且每个接口描述符都有一个或多个端点描述符,那么在响应 USB主机的配置描述符命令时,USB 设备的端点描述符总是紧跟着相关的接口描述符后面,作为配置描述符的一部分被返回。接口描述符不可直接用 Set_Descriptor 和 Get_Descriptor 来存取。若一个接口仅使用端点 0,则接口描述符以后就不再返回端点描述符,并且此接口表现的是一个控制接口的特性,它使用与端点 0 相关联的默认管道进行数据传输。在这种情况下 bNumberEndpoints 域应被设置成 0。接口描述符在说明端点个数并不把端点 0 计算在内。

接口是端点的集合,负责完成 USB 的特定功能,例如:数据的输入输出。接口描述符用于描述一个接口,包含了接口的特性,如端点个数,所属设备类和子类等。它有 9 个字段,共 9 字节。

typedef struct _USB_INTERFACE_DESCRIPTOR_
{
    BYTE      bLength,
    BYTE      bDescriptorType,
    BYTE      bInterfaceNumber,
    BYTE      bAlternateSetting,
    BYTE      bNumEndpoint,
    BYTE      bInterfaceClass,
    BYTE      bInterfaceSubClass,
    BYTE      bInterfaceProtocol,
    BYTE      iInterface
}USB_INTERFACE_DESCRIPTOR;
字段名 解释
bLength 描述符大小.固定为 0x09
bDescriptorType 接口描述符类型.固定为 0x04
bInterfaceNumber 该接口的编号,接口编号从 0 开始分配,当一个配置有多个接口时,就用该字段来区分不同的接口。
bAlternateSetting 用于为上一个字段选择可供替换的位置,即备用的接口描述符标号
bNumEndpoint 使用的端点数目.端点 0 除外,如果此值为 0 ,此接口仅仅只能被用为控制管道
bInterfaceClass 接口所属的类值: 零值为将来的标准保留,如果此域的值设为 FFH,则此接口类由厂商说明,所有其它的值由 USB 说明保留。
bInterfaceSubClass 子类码 :这些值的定义视 bInterfaceClass 域而定。 如果 bInterfaceClass 域的值为零则此域的值必须为零。 bInterfaceClass 域不为 FFH 则所有值由 USB 所保留。
bInterfaceProtocol 协议码:bInterfaceClass 和 bInterfaceSubClass 域的值而定.如果一个接口支持设备类相关的请求此域的值指出了设备类说明中所定义的协议.
iInterface 描述此接口的字串描述表的索引值。

接口描述符返回示例:

对于 bInterfaceClass 字段,表示接口所属的类别,USB 协议根据功能将不同的接口划分成不的类,其具体含义如下表所示:

类别
0x01 音频类
0x02 CDC控制类
0x03 人机接口类(HID)
0x05 物理类
0x06 图像类
0x07 打印机类
0x08 大数据存储类
0x09 集线器类
0x0A CDC数据类
0x0B 智能卡类
0x0D 安全类
0xDC 诊断设备类
0xE0 无线控制器类
0xFE 特定应用类(包括红外的桥接器等)
0xFF 厂商定义的设备

5.端点描述符

端点是设备与主机之间进行数据传输的逻辑接口,除配置使用的端点 0(控制端点,一般一个设备只有一个控制端点)为双向端口外,其它均为单向。端点描述符描述了数据的传输类型、传输方向、数据包大小和端点号(也可称为端点地址)等。

除了描述符中描述的端点外,每个设备必须要有一个默认的控制型端点,地址为 0,它的数据传输为双向,而且没有专门的描述符,只是在设备描述符中定义了它的最大包长度。主机通过此端点向设备发送命令,获得设备的各种描述符的信息,并通过它来配置设备。

USB 设备中的每个端点都有自己的端点描述符,由接口描述符中的 bNumEndpoint 决定其数量。

typedef struct _USB_ENDPOINT_DESCRIPTOR_
{
    BYTE        bLength,
    BYTE        bDescriptorType,
    BYTE        bEndpointAddress,
    BYTE        bmAttributes,
    WORD        wMaxPacketSize,
    BYTE        bInterval
}USB_ENDPOINT_DESCRIPTOR;
字段名 解释
bLength 描述符大小.固定为 0x07。
bDescriptorType 接口描述符类型.固定为 0x05。
bEndpointAddress 此描述表所描述的端点的地址、方向: Bit 3..0 : 端点号;Bit 6..4 : 保留,为零 ;Bit 7: 方向,如果控制端点则略。 0:输出端点(主机到设备) ;1:输入端点(设备到主机)
bmAttributes 此域的值描述的是在 bConfigurationValue 域所指的配置下端点的特性。 Bit 1..0 :传送类型 (00=控制传送 ;01=同步传送 ;10=批量传送 ;11=中断传送 ,所有其它的位都保留。
wMaxPacketSize 当前配置下此端点能够接收或发送的最大数据包的大小。 对于实进传输,此值用于为每帧的数据净负荷预留时间。在实际运行时,管道可能不完全需要预留的带宽,实际带宽可由设备通过一种非 USB 定义的机制汇报给主机。对于中断传输,批量传输和控制传输,端点可能发送比之短的数据包
bInterval 周期数据传输端点的时间间隙。 此域的值对于批传送的端点及控制传送的端点无意义。对于同步传送的端点此域必需为 1,表示周期为 1ms。对于中断传送的端点此域值的范围为 1ms 到 255ms。

端点描述符实例,一个输入、一个输出:

6.字符串描述符

字符串描述符是一种可选的 USB 标准描述符,描述了如制商、设备名称或序列号等信息。如果一个设备无字符串描述符,则其它描述符中与字符串有关的索引值都必须为 0。字符串使用的是 Unicode 编码。

主机请示得到某个字符串描述符时一般分成两步:首先主机向设备发出 USB 标准命令 Get_Descriptor,其中所使用的字符串的索引值为 0,设备返回一个字符串描述符,此描述符的结构如下:

USB 设备中的字符串可能支持多种语言。请求字符串描述符时,请求者使用 USB-IF 定义的 16 位语ID(LANGID)指定所需的语言。所有语言的字符串索引零都返回一个字符串描述符,该描述符包含设备支持的双字节 LANGID 代码数组。上图表显示了 LANGID 代码数组。 USB 设备可以省略所有字符串描述符。省略所有字符串描述符的 USB 设备不得返回 LANGID 代码数组。

LANGID 代码数组不以 NULL 结尾。通过从描述符的第一个字节的值中减去两个来计算数组的大小(以字节为单位)。

UNICODE字符串描述符:

typedef struct _USB_STRING_DESCRIPTION_
{
    BYTE      bLength,
    BYTE      bDescriptionType,
    BYTE      bString[1];
}USB_STRING_DESCRIPTION;
字段名 解释
bLength 描述符大小.由整个字符串的长度加上 bLength 和 bDescriptorType 的长度决定(N+2)
bDescriptorType 接口描述符类型.固定为 0x03
bString Unicode 编码字符串(长度为 N)

7.设备限定描述符

device_qualifier 描述符描述了有关高速设备的信息,如果设备以其他速度运行,该设备将发生变化。如果设备当前正以全速运行,则 device_qualifier 将返回有关其如何以高速运行的信息。

标准设备描述符的供应商,产品,设备,制造商,产品和序列号字段不包含在此描述符中,因为该信息对于所有支持的速度的设备是恒定的。 此描述符的版本号必须至少为2.0(0200H)。主机使用GetDescriptor()请求访问此描述符。

如果仅全速设备(设备描述符版本号等于0200H)收到对 device_qualifier 的 GetDescriptor()请求,则它必须响应请求错误。 除非首先成功检索 device_qualifier 描述符,否则主机不得请求 other_speed_configuration 描述符。


struct USB_QUALIFIER_DESCRIPTOR
 {
    BYTE  bLength;
    BYTE  bDescriptorType;
    WORD bcdUSB;
    BYTE  bDeviceClass;
    BYTE  bDeviceSubClass;
    BYTE  bDeviceProtocol;
    BYTE  bMaxPacketSize0;
    BYTE  bNumConfigurations;
    BYTE  bRESERVED;
}
字段名 解释
bLength 设备限定描述符长度,10 个字节(0AH)
bDescriptorType 限定描述符类型,固定为 06H
bcdUSB USB 设备及其描述符遵循的 USB 规范版本号,以 BCD 码形式表示,版本必须在 2.0 以上
bDeviceClass USB 所属的设备类
bDeviceSubClass USB 所属的设备子类,设备类再细分
bDeviceProtocol 协议代码(由USB分配),如果使用 USB-IF 组织定义的协议,就需要设置这里的值,否则直接设置为 0。如果厂商自己定义的可以设置为 FFH
bMaxPacketSize0 端点 0 最大分组大小(只有 8,16,32,64 有效),对于低速 USB 设备,bMaxPacketSize0 为8;对于全速 USB 设备,bMaxPacketSize0 为 8、16、32、64;对于高速 USB 设备,bMaxPacketSize0 为 64。
bNumConfigurations 表示 USB 设备另一个速率所支持的配置数
bRESERVED 保留项,置0

注:此处针对 USB2.0 协议

欢迎关注公众号:【千艺千寻】,共同成长


参考:

1.从零开始学USB(十、USB的描述符)
2.USB描述符
3.USB描述符详解
4.USB命令请求及描述符详解(速查手册)
5.USB中的描述符详解 一
6.USB请求和USB描述符
7.从零开始学USB(十、USB的描述符)


   转载规则


《USB总线专题(四)——枚举过程》 霁风 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Keil使用总结(一)——拷贝调试中内存数据到文本文件 Keil使用总结(一)——拷贝调试中内存数据到文本文件
1. 简介我们在调试过程中,不免需要查看从一些设备(比如:传感器,采集器等设备)读取的数据,在使用 Keil 调试的时候,就可以从 Memory 窗口将数据保存到计算机本地,对应进行分析。 2. 步骤2.1 打开 Command 窗口在调
2020-01-14
下一篇 
USB总线专题(四)——枚举过程 USB总线专题(四)——枚举过程
1. 定义 枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序。枚举过程包括设备地址的分配,从设备读取设备描述符,分配加载驱动程序,选择规定的设备功耗要求和接口配置信息。 US
2019-09-06
  目录