文章目录
- 枚举顺序
- 枚举过程
- 标准请求
- bmRequestType
- bReqest
- 请求类型
 
- GetDescriptor
- 设备描述符
- 设备描述符定义
- 获取设备描述符
- 返回设备描述符
 
- 配置描述符
- 配置描述符定义
- 获取配置描述符
- 返回配置描述符
 
- 接口描述符&端点描述符&HID描述符
- 接口描述符定义
- 返回接口描述符
- HID描述符定义
- 返回HID描述符
- 端点描述符定义
- 返回端点描述符
 
- 字符串描述符&语言ID
- 语言ID描述符定义
- 字符串描述符定义
- 获取字符串描述符
- 字符串描述符-语言ID
- 字符串描述符-厂商字符串
- 字符串描述符-产品字符串
 
 
 
- SetAddress
- SetConfiguration
- SDX24抓包数据
- 总览
- 虚拟端口
- 网卡
 
枚举顺序
USB的枚举过程中设备需要通过一系列的描述符来告诉主机自己的各种信息。
从上到下,先是通过设备描述符,告知主机自己是什么。紧接着通过配置描述符,告诉主机自己支持一种或多种配置,一般情况下都只有一种配置。随后通过接口描述符,告诉主机自己支持哪些功能。最后通过端点描述符,告诉主机接口具备的端点是什么。
USB中端点就是主从机之间数据交互的桥梁,输入输出分别在不同端点中进行,且不可复用。

枚举过程
从下图可以看出设备在接入host时,首先第一步会使用地址0进行一次复位,并发送获取设备描述符的请求。
第二步会对设备进行第二次复位(可选操作),紧接着设置一个新的地址,该地址唯一。在后续所有的通讯过程中都是使用该地址。设备接收到地址后,会使用该地址用于表明身份。
新地址启用后,会使用新的地址获取设备的各项描述符(设备描述符,配置描述符、接口描述符、端点描述符),开始真正意义上的枚举动作。

下图是抓包的一个键盘的枚举过程。后面将按照顺序对枚举动作进行分析

标准请求
由于USB所有的通信过程都是由主机发起的,枚举过程中所涉及到的动作在USB协议里都有对应的请求报文。
USB协议定义了一个8字节的标准设备请求,主要用在设备的枚举过程中。这8字节的数据是在控制传输的建立过程通过默认控制端点0发出的。
  在这8字节的数据中,包含了数据过程所需要传输数据传输的方向、长度以及数据类型等信息。正是由于8字节标准请求的原因,USB协议规定,端点0的最大包长度至少为8字节。1
 也就是说,任何一个USB设备都能够(而且必须要)接收8字节的标准请求。
USB标准请求的个字节分为5个部分,其变量分别定义为: 1字节的bmRequestType,1 字节的bReqest,2字节的wValue,2字节的wIndex和2字节的wLength。
| item | length(Byte) | 
|---|---|
| bmRequestType | 1 | 
| bReqest | 1 | 
| wValue | 2 | 
| wIndex | 2 | 
| wLength | 2 | 
bmRequestType
bmRequestType字段中D7定义了接下来的数据方向,D6和D5定义了请求类型,D4-D0定义了目标类型
| 数据位 | 功能 | 取值(bit) | 
|---|---|---|
| D7 | 下一步数据的方向 | 0 = 主机到设备(SET) 1 = 设备到主机(GET请求) | 
| D6-D5 | 命令的类型 | 00=标准请求 01=类请求(UVC) 10=用户定义的请求 11=保留 | 
| D4-D0 | 命令接受者的类型 | 00000=接受者为设备 00001=接收者为接口 00010=接受者为端点 00011=其它 其他保留 | 
bReqest
bReqest代表当前请求的功能,部分请求需要和bmRequestType配合理解才能确定具体的含义。
下表列举usb2.0中定义的11种标准请求。
| 请求名 | 请求号(hex) | 功能 | 
|---|---|---|
| GetStatus | 00H | 读取设备、接口或端点的状态 | 
| ClearFeature | 01H | 清除或禁止设备、接口或端点的某些特性 | 
| SetFeature | 03H | 设置或使能设备、接口或端点的某些特性 | 
| SetAddress | 05H | 分配设备地址 | 
| GetDescriptor | 06H | 读取指定描述符 | 
| SetDescriptor | 07H | 更新已有的描述符或添加新的描述符 | 
| GetConfiguration | 08H | 读取USB设备当前的配置值 | 
| SetConfiguration | 09H | 为USB设备选择一个合适的配置 | 
| GetInterface | 0AH | 读取指定接口的当前可替换设置值 | 
| SetInterface | 0BH | 为指定接口选择一个合适的可替换设置 | 
| SynchFrame | 0CH | 读取同步端点所指定的帧序号 | 
在usb3.0中除了上述的请求外,还增加了下表的内容
| 请求名 | 请求号(hex) | 功能 | 
|---|---|---|
| SET_ENCRYPTION | 0DH | 设置加密 | 
| GET_ENCRYPTION | 0EH | 获取加密 | 
| SET_HANDSHAKE | 0FH | 设置握手 | 
| GET_HANDSHAKE | 10H | 获取握手 | 
| SET_CONNECTION | 11H | 设置连接 | 
| SET_SECURITY_DATA | 12H | 设置安全数据 | 
| GET_SECURITY_DATA | 13H | 读取安全数据 | 
| SET_WUSB_DATA | 14H | 设置总线数据 | 
| LOOPBACK_DATA_WRITE | 15H | 回环数据写入 | 
| LOOPBACK_DATA_READ | 16H | 回环数据读取 | 
| SET_INTERFACE_DS | 17H | 设置子接口的描述符 | 
| SET_SEL | 30H | 请求通知设备系统退出时延 | 
| SET_ISOCH_DELAY | 31H | 设置等时时延 | 
不同的请求对于其接收者wValue和wIndex,其各字段的意义是不一样的。需要注意的是wValue、wIndex、wLength这三个域都是两字节的,在USB协议中规定,使用的是小端结构,即低字节在先,高字节在后。
请求类型
下表是各个标准请求的结构以及数据过程需要传输的数据。其中第一列有的有多个,主要是最低5位不同,即表示接收者不同。有的请求只能发送到设备,而有的请求可以发送到设备、接口和端点。
| bmRequestType(bit) | bReqest | wValue | wIndex | wLength | data process | 
|---|---|---|---|---|---|
| b0000 0000 b0000 0001 b0000 0010 | ClearFeature | 特性选择 | 0 接口号 端点号 | 0 | 没有 | 
| b0000 0000 | SetConfiguration | 配置值 | 0 | 0 | 没有 | 
| b1000 0000 | GetConfiguration | 0 | 0 | 1 | 配置值 | 
| b0000 0000 | SetDescriptor | 描述符类型和索引 | 0或者语言ID | 描述符长度 | 描述符 | 
| b1000 0000 | GetDescriptor | 描述符类型和索引 | 0或者语言ID | 描述符长度 | 描述符 | 
| b0000 0001 | SetInterface | 备用接口号 | 接口号 | 0 | 没有 | 
| b1000 0001 | GetInterface | 0 | 接口号 | 1 | 备用接口号 | 
| b1000 0000 b1000 0001 b1000 0010 | GetStatus | 0 | 0 接口号 端点号 | 2 | 设备状态 接口状态 端点状态 | 
| b0000 0000 | SetAddress | 设备地址 | 0 | 0 | 没有 | 
| b0000 0000 b0000 0001 b0000 0010 | SetFeature | 特性选择 | 0 接口号 端点号 | 0 | 没有 | 
| b1000 0010 | SynchFrame | 0 | 端点号 | 2 | 帧号 | 
上面中记录的请求,常用的只有三个分别是GetDescriptor、SetAddress和SetConfiguration
GetDescriptor
GetDescriptor(获取描述符)请求是在枚举过程中用得最多的一个请求。主机通过发送获取描述符请求读取设备的各种描述符,从而可以获知设备类型、端点情况等众多重要信息。
获取描述符的接收者只能是设备,从bmRequestTypee的第7位可以看出,它是请求数据输人的。bRequest的值为0x06(GET_DESCRIPTOR)。
| bmRequestType(1Byte) | bReqest(1Byte) | wValue(2Byte) | wIndex(2Byte) | wLength(2Byte) | 
|---|---|---|---|---|
| 1000 0000(0x80) | GetDescriptor(0x06) | 描述符类型和索引 | 0或者语言ID | 描述符长度 | 
wValue域的第一字节(低字节)表示的是索引号,用来选择同一种描述符(例如字符串描述符和配置描述符)中具体的某个描述符。
wValue域的第二字节,表示描述符的类型编号。各种描述符的类型编号定义如下表所列。对于全速模式和低速模式,获取描述符的标准请求只有三种:获取设备描述符,获取配置描述符和获取字符串描述符。
另外的接口描述符和端点描述符是跟随配置描述符一并返回的,不能单独请求返回(如果单独返回,主机无法确认它们属于哪个配置)
USB描述符分为标准描述符、类描述符、HID相关描述符、厂商自定义描述符。下表是标准描述符中定义的描述符个数。
| 描述符 | 描述符值(Hex) | 
|---|---|
| 设备描述符 | 01 | 
| 配置描述符 | 02 | 
| 字符串描述符 | 03 | 
| 接口描述符 | 04 | 
| 端点描述符 | 05 | 
| 设备限定描述符 | 06 | 
| 其他速率配置描述符 | 07 | 
wlndex域只在获取字符串描述符中有用,它表示字符串的语言ID号,获取除字符串描述符的其他描述符时,wIndex的值为0。
wLength域为请求设备返回数据的字节数,设备实际返回的字节数可以比该域指定的字节数少。设备在收到获取描述符的请求后,应该按照所请求的描述符类型编号,在数据过程中返回相应的描述符。
设备描述符
设备描述符定义
| 地址偏移量 | 字段名 | 长度 | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):12H | 
| 1 | bDescriptorType | 1 | 描述符类型:设备=01H | 
| 2 | bcdUSB | 2 | USB 规范版本号(BCD 码) | 
| 4 | bDeviceClass | 1 | 类代码 | 
| 5 | bDeviceSubClass | 1 | 子类代码 | 
| 6 | bDeviceProtocol | 1 | 协议代码 | 
| 7 | bMaxPacketSize0 | 1 | 端点 0 支持最大数据包长度 | 
| 8 | idVender | 2 | 供应商 ID | 
| 10 | idProduct | 2 | 产品 ID | 
| 12 | bcdDevice | 2 | 设备版本号(BCD 码) | 
| 14 | iManufacturer | 1 | 供应商字符串描述符索引值 | 
| 15 | iProduct | 1 | 产品字符串描述符索引值 | 
| 16 | iSerialNumber | 1 | 设备序列号字符串描述符索引值 | 
| 17 | bNumConfigurations | 1 | 所支持的配置数 | 
bDeviceClass指明USB设备所属的设备类,bDeviceSubClass和bDeviceProtocol子段会根据bDeviceClass字段的不同而不同。bDeviceClass字段代码可查下表:
| 值(Hex) | 说明 | 
|---|---|
| 00 | 由接口描述符提供类的值 | 
| 02 | 通信类 | 
| 09 | 集线器类 | 
| DC | 用于诊断用途的设备类 | 
| E0 | 无限通信设备类 | 
| FF | 厂商定义的设备类 | 
获取设备描述符
| bmRequestType(1Byte) | bReqest(1Byte) | wValue(2Byte) | wIndex(2Byte) | wLength(2Byte) | 
|---|---|---|---|---|
| 1000 0000(0x80) | GetDescriptor(0x06) | 设备描述符(0x0001) | 0或者语言ID | 描述符长度 | 
设备枚举时获取设备描述符一般情况下都会获取两次。
第一次获取设备描述符主机只需要知道端点0的最大包长即可。这里需要注意的是,某些主机为了减少在枚举过程中说产生的开销。只会读取一个数据包的设备描述符。标准的描述符有18字节,有些USB设备的端点0大小不足18字节(低速设备只有8字节)。

在这种情况下,USB主机也是只发送一次数据输入请求,多余的数据将不会再次请求。因此,如果当设备端点0大小不足18字节时,就需要注意到这个问题。也就是说在第一次获取设备描述符时,只需要返回一次数据即可。
当主机成功获取到设备描述符的前8字节之后(USB协议规定端点0最大包长至少要有8字节),它就知道端点0的最大包长度了,因为端点0最大包长度刚好在设备描述符的第八字节处。

第二次枚举的过程中,主机需要获取全部信息,就会连续发起IN事务,共接收18个字节。

返回设备描述符

Data stage (18 bytes) :
------------------------------------
       DEVICE Descriptor
       -----------------
Offset|       Field        | Value |  Description  
------|--------------------|-------|--------------------
  0   |      bLength       |  0x12 |The size of this descriptor is 18 bytes
------|--------------------|-------|--------------------
  1   |  bDescriptorType   |  0x01 |DEVICE Descriptor Type
------|--------------------|-------|--------------------
  2   |       bcdUSB       | 0x0110|Device compliant to the USB specification version 1.10   
------|--------------------|-------|--------------------
  4   |    bDeviceClass    |  0x00 |Each interface specifies its own class information
------|--------------------|-------|--------------------
  5   |  bDeviceSubClass   |  0x00 |Each interface specifies its own subclass information
------|--------------------|-------|--------------------
  6   |  bDeviceProtocol   |  0x00 |No protocols on the device basis
------|--------------------|-------|--------------------
  7   |  bMaxPacketSize0   |  0x08 |Maximum packet size for endpoint zero is 8
------|--------------------|-------|--------------------
  8   |      idVendor      | 0x03F0|Vendor ID is 1008: Hewlett Packard
------|--------------------|-------|--------------------
  10  |     idProduct      | 0x0324|The Product ID is 0x0324
------|--------------------|-------|--------------------
  12  |     bcdDevice      | 0x0100|The device release number is 1.00
------|--------------------|-------|--------------------
  14  |   iManufacturer    |  0x01 |The index of the string descriptor describing the manufacturer is 1
------|--------------------|-------|--------------------
  15  |      iProduct      |  0x02 |The index of the string descriptor describing the product is 2
------|--------------------|-------|--------------------
  16  |   iSerialNumber    |  0x00 |The device doesn't have the string descriptor describing the serial number
------|--------------------|-------|--------------------
  17  | bNumConfigurations |  0x01 |The device has 1 possible configurations
------|--------------------|-------|--------------------
配置描述符
一般情况下设备都只有一个配置,我这抓包的键盘和模块都是只有一个配置的。
USB设备在下列情况下可能会存在多个配置描述符。
- 多个速度支持:USB设备可能支持不同的传输速度,例如USB 2.0和USB 3.0。在这种情况下,设备可以为每种速度定义一个不同的配置描述符,以便在不同速度下进行适当的配置。
- 多种工作模式:某些USB设备可以在不同的工作模式之间切换,例如存储设备可以在存储模式和MTP(Media Transfer Protocol)模式之间切换。每种工作模式可能需要不同的配置,因此设备可以为每种模式定义一个配置描述符。
- 多个功能:某些USB设备可能具有多个功能,例如同时作为存储设备和音频设备。每个功能可能需要不同的配置描述符来配置其特定的功能。
- 不同的电源模式:某些USB设备可能支持不同的电源模式,例如使用总线供电或外部电源供电。每种电源模式可能需要不同的配置描述符来配置相应的电源设置。
配置描述符定义
| 地址偏移量 | 字段名 | 长度(字节) | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):09H | 
| 1 | bDescriptorType | 1 | 描述符类型:配置=02H | 
| 2 | wTotalLength | 2 | 配置信息的总长度 | 
| 4 | bNumInterfaces | 1 | 所支持的接口数 | 
| 5 | bConfigurationValue | 1 | 配置值 | 
| 6 | iConfiguration | 1 | 配置字符串描述符索引值 | 
| 7 | bmAttributes | 1 | 配置特性 | 
| 8 | bMaxPower | 1 | 所需的最大总线电流(2mA) | 
bmAttributes 字段的信息如下:
| bit | 含义 | 
|---|---|
| D7 | 保留(置 1) | 
| D6 | 总线供电为 0,自给电源为 1 | 
| D5 | 支持远程唤醒为 1,不支持远程唤醒为 0 | 
| D4…0 | 保留(置 0) | 
获取配置描述符
| bmRequestType(1Byte) | bReqest(1Byte) | wValue(2Byte) | wIndex(2Byte) | wLength(2Byte) | 
|---|---|---|---|---|
| 1000 0000(0x80) | GetDescriptor(0x06) | 设备描述符(0x0002) | 0或者语言ID | 描述符长度 | 

返回配置描述符

Data stage (9 bytes) :
------------------------------------
       CONFIGURATION Descriptor
       ------------------------
Offset|        Field        | Value |  Description  
------|---------------------|-------|--------------------
  0   |       bLength       |  0x09 |The size of this descriptor is 9 bytes
------|---------------------|-------|--------------------
  1   |   bDescriptorType   |  0x02 |CONFIGURATION Descriptor Type
------|---------------------|-------|--------------------
  2   |    wTotalLength     | 0x0022|The total length of data for this configuration is 34. This includes the combined length of all the descriptors returned
------|---------------------|-------|--------------------
  4   |   bNumInterfaces    |  0x01 |This configuration supports 1 interfaces
------|---------------------|-------|--------------------
  5   | bConfigurationValue |  0x01 |The value 1 should be used to select this configuration
------|---------------------|-------|--------------------
  6   |   iConfiguration    |  0x00 |The device doesn't have the string descriptor describing this configuration
------|---------------------|-------|--------------------
  7   |    bmAttributes     |  0xA0 |Configuration characteristics :
      |                     |       |Bit 7: Reserved (set to one) 1 
      |                     |       |Bit 6: Self-powered          0 
      |                     |       |Bit 5: Remote Wakeup         1 
------|---------------------|-------|--------------------
  8   |      MaxPower       |  0x23 |Maximum power consumption of the device in this configuration is 70 mA
------|---------------------|-------|--------------------
接口描述符&端点描述符&HID描述符
前面提到对于全速模式和低速模式,获取描述符的标准请求只有三种:获取设备描述符,获取配置描述符和获取字符串描述符。
  另外的接口描述符和端点描述符是跟随配置描述符一并返回的,不能单独请求返回(如果单独返回,主机无法确认它们属于哪个配置)
 
接口描述符定义
| 地址偏移量 | 字段名 | 长度(字节) | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):09H | 
| 1 | bDescriptorType | 1 | 描述符类型:接口=04H | 
| 2 | bInterfaceNumber | 1 | 接口号 | 
| 3 | bAlternateSetting | 1 | 可替换设置值 | 
| 4 | bNumEndpoints | 1 | 所使用端点数(不包括端点 0) | 
| 5 | bInterfaceClass | 1 | 类代码 | 
| 6 | bInterfaceSubClass | 1 | 子类代码 | 
| 7 | bInterfaceProtocol | 1 | 协议代码 | 
| 8 | iInterface | 1 | 接口字符串描述符的索引值 | 
bInterfaceClass 指明接口所属的设备类,bInterfaceSubClass 和 bInterfaceProtocol 字段会根据bInterfaceClass 字段的不同而不同。bInterfaceClass 字段代码可查下表:
| 值(Hex) | 类别 | 
|---|---|
| 01 | 音频类 | 
| 02 | CDC 控制类 | 
| 03 | 人机接口类(HID) | 
| 05 | 物理类 | 
| 06 | 图像类 | 
| 07 | 打印机类 | 
| 08 | 大数据存储类 | 
| 09 | 集线器类 | 
| 0A | CDC 数据类 | 
| 0B | 智能卡类 | 
| 0D | 安全类 | 
| DC | 诊断设备类 | 
| E0 | 无线控制器类 | 
| FE | 特定应用类(包括红外的桥接器等) | 
| FF | 厂商定义的设备 | 
返回接口描述符

       INTERFACE Descriptor
       --------------------
Offset|       Field        | Value |  Description  
------|--------------------|-------|--------------------
  0   |      bLength       |  0x09 |The size of this descriptor is 9 bytes
------|--------------------|-------|--------------------
  1   |  bDescriptorType   |  0x04 |INTERFACE Descriptor Type
------|--------------------|-------|--------------------
  2   |  bInterfaceNumber  |  0x00 |The number of this interface is 0
------|--------------------|-------|--------------------
  3   | bAlternateSetting  |  0x00 |The value used to select alternate setting for this interface is 0
------|--------------------|-------|--------------------
  4   |   bNumEndpoints    |  0x01 |The number of endpoints used by this interface is 1 (excluding endpoint zero)
------|--------------------|-------|--------------------
  5   |  bInterfaceClass   |  0x03 |The interface implements HID class
------|--------------------|-------|--------------------
  6   | bInterfaceSubClass |  0x01 |The subclass code is 0x01
------|--------------------|-------|--------------------
  7   | bInterfaceProtocol |  0x01 |The protocol code is 0x01
------|--------------------|-------|--------------------
  8   |     iInterface     |  0x00 |The device doesn't have the string descriptor describing this interface
------|--------------------|-------|--------------------
HID描述符定义
| 地址偏移量 | 字段名 | 长度(字节) | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):0CH | 
| 1 | bDescriptorType | 1 | 描述符类型:人机接口类=21H | 
| 2 | bcdHID | 2 | HID 规范版本号(BCD 码) | 
| 4 | bCountryCode | 1 | 硬件目的国家的识别码(BCD 码) | 
| 5 | bNumDescritors | 1 | 支持附属描述符目录 | 
| 6 | bDescriptorType | 1 | HID 相关描述符类型 21H:HID 描述符 22H:报告描述符 23H:实体描述符 | 
| 7 | wDescriptorLength | 2 | 报告描述符总长度 | 
| 9 | bDescriptorType | 1 | 用于识别描述符类型的常量,使用在有一个以上描述符的设备 | 
| 10 | wDescriptorLength | 2 | 描述符总长度,使用在有一个以上描述符的设备 | 
返回HID描述符

       HID Descriptor
       --------------
Offset|       Field       | Value |  Description  
------|-------------------|-------|--------------------
  0   |      bLength      |  0x09 |The size of this descriptor is 9 bytes
------|-------------------|-------|--------------------
  1   |  bDescriptorType  |  0x21 |HID Descriptor Type
------|-------------------|-------|--------------------
  2   |      bcdHID       | 0x0100|Device compliant to the HID specification version 1.00   
------|-------------------|-------|--------------------
  4   |   bCountryCode    |  0x00 | Localisation Not Supported
------|-------------------|-------|--------------------
  5   |  bNumDescriptors  |  0x01 |The number of class descriptors is 1
------|-------------------|-------|--------------------
  6   |  bDescriptorType  |  0x22 |The class descriptor is Report descriptor
------|-------------------|-------|--------------------
  7   | wDescriptorlength | 0x0041|The total size of the class descriptor is 65
------|-------------------|-------|--------------------
端点描述符定义
| 地址偏移量 | 字段名 | 长度(字节) | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):07H | 
| 1 | bDescriptorType | 1 | 描述符类型:端点=05H | 
| 2 | bEndpointAddress | 1 | 端点号及传输方向 D3…0 : 端点号 D6…4 : 保留,为零 D7=0:输出端点(主机到设备) D7=1:输入端点(设备到主机) | 
| 3 | bmAttributes | 1 | 端点特性 D 1…0 :传送类型 00=控制传送 01=同步传送 10=批传送 11=中断传送 所有其它的位都保留。 | 
| 4 | wMaxPacketSize | 2 | 端点支持的最大数据包长度 | 
| 6 | bInterval | 1 | 端点数据传输的访问间隔 | 
返回端点描述符

       ENDPOINT Descriptor
       -------------------
Offset|      Field       | Value |  Description  
------|------------------|-------|--------------------
  0   |     bLength      |  0x07 |The size of this descriptor is 7 bytes
------|------------------|-------|--------------------
  1   | bDescriptorType  |  0x05 |ENDPOINT Descriptor Type
------|------------------|-------|--------------------
  2   | bEndpointAddress |  0x81 |This is an IN endpoint with address (endpoint number) 1
------|------------------|-------|--------------------
  3   |   bmAttributes   |  0x03 |Types - 
      |                  |       |Transfer:INTERRUPT 
      |                  |       |Sync:No Sync 
      |                  |       |Usage:Data EP
------|------------------|-------|--------------------
  4   |  wMaxPacketSize  | 0x0008|Maximum packet size 
      |                  |       |value for this 
      |                  |       |endpoint is 0x8 
      |                  |       |(Bits 12-11: Addtl. Transactions/frame)
------|------------------|-------|--------------------
  6   |    bInterval     |  0x18 |bInterval:24. The 
      |                  |       |polling interval 
      |                  |       |value is bInterval 
      |                  |       |or 2**(bInterval-1)
------|------------------|-------|--------------------
字符串描述符&语言ID
在USB协议中,字符串描述符是可选的。当某个描述符中的字符串索引值为非0时,就表示它具有那个字符串描述符,注意索引值不能重复。
在上面提到的设备描述符中,申请了2个非0的索引值,分别是厂商字符串、产品字符串,其索引值分别为1,2。

USB主机使用获取字符串描述符和索引值来获取对应的字符串。当索引值为0时,表示获取语言ID。语言ID是一个描述该设备支持的语言种类的数。
语言ID描述符定义
| 地址偏移量 | 字段名 | 长度(字节) | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):N+2 | 
| 1 | bDescriptorType | 1 | 描述符类型:字符串=03H | 
| 2 | wLANGID[0] | 2 | 语言ID号0 | 
| … | … | 2 | … | 
| 2*n+2 | wLANGID[n] | 2 | 语言ID号n | 
语言ID可跟随多个,一般情况下都是使用美式英语这一种,既0x0409。如果使用中文,则部分主机可能不会获取后续的字符串描述符。
字符串描述符定义
| 地址偏移量 | 字段名 | 长度(字节) | 说明 | 
|---|---|---|---|
| 0 | bLength | 1 | 描述符长度(字节):N+2 | 
| 1 | bDescriptorType | 1 | 描述符类型:字符串=03H | 
| 2 | bString | N | UNICODE 编码的字符串 | 
字符串描述符中的bString字段是使用UNICODE编码的字符串。UNICODE用2字节来表示一个字符,如果是英文字符,则直接在ASCII码前补1字节的0扩充为2字节的UNICODE码。
获取字符串描述符
| bmRequestType(1Byte) | bReqest(1Byte) | wValue(2Byte) | wIndex(2Byte) | wLength(2Byte) | 
|---|---|---|---|---|
| 1000 0000(0x80) | GetDescriptor(0x06) | 字符串描述符(0x0X03) | 0或者语言ID | 描述符长度 | 
字符串描述符-语言ID

语言ID,这里只使用美式英语一种,即0x0409。

字符串描述符-厂商字符串

获取到的厂商描述符字符串是:LiteON

字符串描述符-产品字符串

获取到的产品描述符字符串是:HP Basic USB Keyboard

SetAddress
SetAddress(设置地址)请求是主机请求设备使用指定地址的请求,指定的地址就包含在8字节数据中的wValue字段中。设置地址请求是没有数据过程的,因而wLength的值为0。wIndex也用不着,值为0。
| bmRequestType(1Byte) | bReqest(1Byte) | wValue(2Byte) | wIndex(2Byte) | wLength(2Byte) | 
|---|---|---|---|---|
| 0000 0000(0x00) | SetAddress(0x05) | 设备地址 | 0 | 0 | 
每个连接在同一个主控制器上的USB设备都需要具有一个唯一的设备地址,这样主机才能区分每个不同的设备。当设备复位后,都使用默认的地址0。主机从地址为0的设备获取设备描述符,一旦收到第一次设备描述符之后,主机就会发送设置地址的请求,以尽量诚少设备使用公共地址0的时间。
当设备收到设置地址请求后,就直接进人状态过程,等待主机读取0长度的状态数据包。主机成功读取到状态数据包(用ACK响应设备)后,设备将启用新的地址。这以后的传输中,主机都将使用新的地址与设备进行通信。

SetConfiguration
SetConfiguration(设置配置)请求和设置地址请求很类似。区别在于wValue域的意义。在设置地址请求中,wValue的第一字节(低字节)为设备的地址;而在设置配置请求中,wValue的第一字节为配置的值。
| bmRequestType(1Byte) | bReqest(1Byte) | wValue(2Byte) | wIndex(2Byte) | wLength(2Byte) | 
|---|---|---|---|---|
| 0000 0000(0x00) | SetAddress(0x09) | 配置值 | 0 | 0 | 
当wValue值与某配置描述符中的配置编号一致时,表示选中该配置。该值通常为1,因为大多数USB设备只有一种配置,配置编号为1;如果该值为0,则会让设备进入设置地址状态。设备只有在收到非0的配置值后,才能启用它的非0端点。


SDX24抓包数据
枚举的流程和键盘枚举流程基本一致,区别就是接口描述符存在多个,每一个虚拟端口和网卡都是一个独立的接口,每个接口里面都会有独立的端点。
总览

虚拟端口
其中的虚拟端口的接口描述符中使用的是vendor-specific(厂商定义的设备)
| Field | Length (bits) | Offset (bits) | Decoded | Hex Value | Description | 
|---|---|---|---|---|---|
| bLength | 8 | 2120 | 0x09 | 0x09 | Descriptor size is 9 bytes | 
| bDescriptorType | 8 | 2128 | 0x04 | 0x04 | INTERFACE Descriptor Type | 
| bInterfaceNumber | 8 | 2136 | 0x06 | 0x06 | The number of this interface is 6. | 
| bAlternateSetting | 8 | 2144 | 0x00 | 0x00 | The value used to select the alternate setting for this interface is 0 | 
| bNumEndpoints | 8 | 2152 | 0x02 | 0x02 | The number of endpoints used by this interface is 2 (excluding endpoint zero) | 
| bInterfaceClass | 8 | 2160 | 0xFF | 0xFF | The interface class is vendor-specific | 
| bInterfaceSubClass | 8 | 2168 | 0x42 | 0x42 | The Subclass code is 66 | 
| bInterfaceProtocol | 8 | 2176 | 0x01 | 0x01 | The Protocol code is 1 | 
| iInterface | 8 | 2184 | 0x09 | 0x09 | The interface string descriptor index is 9 | 
网卡
一个网卡中会存在多个接口,相比虚拟串口会多出一个接口关联描述符。
关联(association)包括两个或多个接口及其所有备用设置接口。设备必须对需要多个接口的每个设备功能使用接口关联描述符 (Interface Association Descriptor)。接口关联描述符(Interface Association Descriptor)总是通过GetDescriptor(Configuration) 请求,作为配置信息的一部分返回。接口关联描述符 (Interface Association Descriptor)不能直接通过 GetDescriptor()或SetDescriptor()请求进行访问。接口关联描述符必须位于与其关联的接口的接口描述符集(包括所有备用设置接口)之前。所有关联接口集的接口号必须是连续的。
| Length (bits) | Offset (bits) | Decoded | Hex Value | Description |
 | --------------------- | ------------- | ------------- | ------- | --------- | ------------------------------------------------------------ |
 | bLength | 8 | 1432 | 0x08 | 0x08 | Descriptor size is 8 bytes |
 | bDescriptorType | 8 | 1440 | 0x0B | 0x0B | INTERFACE_ASSOCIATION Descriptor Type |
 | bFirstInterface | 8 | 1448 | 0x04 | 0x04 | The first interface number associated with this function is 4 |
 | bInterfaceCount | 8 | 1456 | 0x02 | 0x02 | The number of contiguous interfaces associated with this function is 2 |
 | bFunctionClass | 8 | 1464 | 0x02 | 0x02 | The function belongs to the Communication Device/Interface Class |
 | bFunctionSubClass | 8 | 1472 | 0x0E | 0x0E | The function belongs to the Mobile Broadband Interface Model Subclass |
 | bFunctionProtocol | 8 | 1480 | 0x00 | 0x00 | The function uses the No class specific protocol required Protocol |
 | iFunction | 8 | 1488 | 0x00 | 0x00 | The Function string descriptor index is 0 |
其中控制接口使用的是cdc控制类,数据接口是cdc数据类。
| Field | Length (bits) | Offset (bits) | Decoded | Hex Value | Description | 
|---|---|---|---|---|---|
| bLength | 8 | 1496 | 0x09 | 0x09 | Descriptor size is 9 bytes | 
| bDescriptorType | 8 | 1504 | 0x04 | 0x04 | INTERFACE Descriptor Type | 
| bInterfaceNumber | 8 | 1512 | 0x04 | 0x04 | The number of this interface is 4. | 
| bAlternateSetting | 8 | 1520 | 0x00 | 0x00 | The value used to select the alternate setting for this interface is 0 | 
| bNumEndpoints | 8 | 1528 | 0x01 | 0x01 | The number of endpoints used by this interface is 1 (excluding endpoint zero) | 
| bInterfaceClass | 8 | 1536 | 0x02 | 0x02 | The interface implements the Communication Device/Interface class | 
| bInterfaceSubClass | 8 | 1544 | 0x0E | 0x0E | The interface implements the Mobile Broadband Interface Model Subclass | 
| bInterfaceProtocol | 8 | 1552 | 0x00 | 0x00 | The interface uses the No class specific protocol required Protocol | 
| iInterface | 8 | 1560 | 0x07 | 0x07 | The interface string descriptor index is 7 | 
| Field | Length (bits) | Offset (bits) | Decoded | Hex Value | Description | 
|---|---|---|---|---|---|
| bLength | 8 | 1864 | 0x09 | 0x09 | Descriptor size is 9 bytes | 
| bDescriptorType | 8 | 1872 | 0x04 | 0x04 | INTERFACE Descriptor Type | 
| bInterfaceNumber | 8 | 1880 | 0x05 | 0x05 | The number of this interface is 5. | 
| bAlternateSetting | 8 | 1888 | 0x00 | 0x00 | The value used to select the alternate setting for this interface is 0 | 
| bNumEndpoints | 8 | 1896 | 0x00 | 0x00 | The number of endpoints used by this interface is 0 (excluding endpoint zero) | 
| bInterfaceClass | 8 | 1904 | 0x0A | 0x0A | The interface implements the Data Interface class | 
| bInterfaceProtocol | 8 | 1920 | 0x02 | 0x02 | The interface uses the Reserved Protocol | 
| bInterfaceSubClass | 8 | 1912 | 0x00 | 0x00 | The Subclass code is 0 | 
| iInterface | 8 | 1928 | 0x00 | 0x00 | The device doesn’t have a string descriptor describing this iInterface | 


















