USB设备描述符和请求命令
介绍标准的USB设备描述符和请求命令。
标准的USB描述符 |
当USB设备第一次连接到主机上时,要接收主机的枚举和配置,目的就是让主机知道该设备具有什么功能、是哪一类的USB设备、需要占用多少USB的资源、使用了哪些传输方式以及传输的数据量多大等等。只有主机完全确认了这些信息后,设备才能真正开始工作。这些信息是通过存储在设备中的USB描述符来体现的。
USB设备的属性包括很多内容,为了便于管理,USB协议1.1将这些信息做了分类,定义了很多种描述符,其中标准的描述符包括以下几种:
-
设备描述符
-
配置描述符
-
接口描述符
-
端点描述符
-
字符串描述符
USB为这些描述符定义了编号,以便在数据传输中加以识别,如下表:
编号 | 描述符类型 |
1 | 设备描述符 |
2 | 配置描述符 |
3 | 接口描述符 |
4 | 端点描述符 |
5 | 字符串描述符 |
这些描述符之间具有一定的关系,设备描述符是最高级的描述符,而端点描述符是最低级的描述符。
每一个设备只有一个设备描述符,但设备描述符可以包含多个配置描述符;而一个配置描述符又可包含多个接口描述符;一个接口使用了几个端点,就有几个端点描述符。字符串描述符是可选的。
设备描述符 说明:比较特殊的是,默认控制管道的数据包的长度(即USB设备端点0的长度)是在设备描述符中定义的,而不像其他端点一样是在端点描述符中定义。 | ||||
偏移量 | 字段名称 | 长度 (字节) | 字段值 | 意义 |
0 | bLength | 1 | 数字 | 设备描述符的字节数大小。 固定值0x12。 |
1 | bDescriptionType | 1 | 常数 | 设备描述符的类型编号。 固定值0x1。 |
2 | bcdUSB | 2 | BCD码 | USB版本号。 比如,一个符合USB协议1.1的设备,其bcdUSB值为0x0110; 而符合USB协议2.0的设备,其bcdUSB值为0x0200。 |
4 | bDeviceClass | 1 | 类 | 设备的类型代码。 值从0x01~0xFE。0xFF表示该设备为厂商自定义的类型。 此外,如果设备类型不是在设备描述符中定义的,则该值为0。 |
5 | bDeviceSubClass | 1 | 子类 | 设备类中的子类类型。同bDeviceClass一样,该字段值也是由USB规定和分配的。 当bDeviceClass为0时,此值也为0,代表该子类类型不在设备描述符中定义。 0xFF表示子类类型是由厂商所定义的。 |
6 | bDeviceProtocol | 1 | 协议 | 设备所遵循的协议。 该值由USB来规定。0xFF表示设备采用厂商自己为该类定义的协议。 |
7 | bMaxPacketSize0 | 1 | 数字 | 端点0的最大包的大小。 低速设备恒位8,全速设备一般为8、16、32或64,而高速设备则为64。 |
8 | idVendor | 2 | ID编号 | USB设备的生产厂商从USB开发者论坛获得的ID号。 |
10 | idProduct | 2 | ID编号 | 设备的生产厂商所定义的该设备的产品ID号。 |
12 | bcdDevice | 2 | BCD码 | 设备的产品版本号。 由设备的生产厂商来定义。 |
14 | iManufacturer | 1 | 索引 | 设备生产厂商的字符串的。值为0则代表没有使用该字段。 |
15 | iProduct | 1 | 索引 | 该产品的字符串的索引值。值为0则代表没有使用该字段。 |
16 | iSerialNumber | 1 | 索引 | 设备的序列号的索引值。 每个设备都有一个特定的序列号,可供主机来识别不同的设备。 |
17 | bNumConfigurations | 1 | 数字 | 设备总共支持的配置描述符的数量。 |
配置描述符 说明:它用于描述一个USB设备的属性和能力等配置信息。 | ||||
偏移量 | 字段名称 | 长度 (字节) | 字段值 | 意义 |
0 | bLength | 1 | 数字 | 配置描述符的字节长度。 固定值0x9。 |
1 | bDescriptorType | 1 | 常数 | USB给配置描述符分配的类型编号。 固定值0x2。 |
2 | wTotalLength | 2 | 数字 | 配置所返回的所有描述符(包括配置、接口和端点描述符)的大小总和。 |
4 | bNumInterfaces | 1 | 数字 | 配置所支持的接口总数。 |
5 | bConfiguration Value | 1 | 数字 | 该字段的值作为参数,可被Set_Configuration和Get_Configuration命令来调用,用于该命令选定这个配置。 |
6 | iConfiguration | 1 | 索引 | 该字段指向描述此配置描述符的字符串。 如果设备没有用字符串描述此配置,那么此字段值为0。 |
7 | bmAttributes | 1 | 位图 | 该字段1字节二进制数的每一位代表一个固定的含义。 D7,保留值 D6,供电方式的选择,1 = 自供电,0 = 总线供电 D5,远程唤醒功能的选择,1 = 支持远程唤醒,0 = 不支持远程唤醒 D4~D0,没有意义,固定为0 |
8 | MaxPower | 1 | mA | 设备从总线上获取的电流总量。 字段值的2倍才是实际的电流数。如字段值为50,则实际的电流总量为100mA。 需要注意的是,总线能为每个设备提供的最大电流是500mA。 因此,如果此字段值超过500mA的话,主机就会禁止该配置的使用。 |
接口描述符 说明:它用于描述一个特定接口的属性。接口用于实现某种特定的USB的数据传输功能。接口描述符还可以在配置后改变,在设备描述符提到过USB设备类型bDeviceClass,标准的都是在设备描述符中定义,但是有些类是基于接口在接口描述符中定义的,如HID设备。 | ||||
偏移量 | 字段名称 | 长度 (字节) | 字段值 | 意义 |
0 | bLength | 1 | 数字 | 接口描述符的长度。 固定值0x9。 |
1 | bDescriptorType | 1 | 常数 | USB给接口描述符分配的类型编号。 固定值0x4。 |
2 | bInterfaceNumber | 1 | 数字 | 接口的编号。 如果一个配置拥有N个接口,那么这些接口都是互不相干的,每一个接口都有唯一的编号。 USB就是通过此字段来识别不同的接口。默认值为0。 |
3 | bAlternateSetting | 1 | 数字 | 虽然由bInterfaceNumber字段可知,每一个接口都有一个唯一确定的接口编号, 但是,一个接口却可以由不止一个接口描述符来描述它。 即是说,USB允许多个接口描述符来描述同一个接口,而且这些描述符都可以通过命令来切换。 这里,此字段就是每一个这类描述符唯一的编号。 USB可以通过调用这个字段来切换描述同一个接口的不同描述符。 控制传输中的Get_Interface命令可以用来得到目前正在使用的描述一个确定接口的接口描述符编号,即此字段。 而Set_Interface命令则以此字段值为参数,用来使相应的接口描述符描述某个确定的接口。 |
4 | bNumEndpoints | 1 | 数字 | 接口使用的端点总数(除端点0外)。 如果值为0,表示该接口只使用了端口0。 |
5 | bInterfaceClass Value | 1 | 类 | 接口所属的类别。 这个类别由USB分配。0xFF表示该接口是厂商所定义的接口类型。而值0保留。 |
6 | bInterfaceSubClass | 1 | 子类 | 接口的类别中的子类类型。 这个子类编号由USB分配。0xFF表示该接口由厂商自己所定义。而值0保留。 |
7 | bInterfaceProtocol | 1 | 协议 | 该接口类所遵循的类的协议。 该字段的值跟bInterfaceClass和bInterfaceSubClass字段是相关的。 0x1~0xFE由USB分配,代表不同标准的设备类的协议。 0x0表示该接口不遵循任何类协议。 0xFF表示该接口应用了厂商自定义的类协议。 |
8 | iInterface | 1 | 索引 | 该字段值指向字符串描述符中相应的字符串内容,用于描述该接口。 如果没有启用字符串描述符,则该值为0。 |
端点描述符 说明:它用于描述接口所使用的非0端点的属性,包括输入/输出方向、端点号和端点容量及包的大小等。需要注意的是,端点描述符是作为配置描述符的一部分来返回给主机的,而不能直接通过控制传输中的Get_Descriptor或Set_Descriptor命令来访问。 | ||||
偏移量 | 字段名称 | 长度 (字节) | 字段值 | 意义 |
0 | bLength | 1 | 数字 | 端点描述符的长度。 固定值0x7。 |
1 | bDescriptorType | 1 | 常数 | USB为端点描述符分配的类型编号。 固定值0x5。 |
2 | bEndpointAddress | 1 | 端点 | D7,作为该端点号的方向控制位,1 = 输出OUT端点,0 = 输入IN端点。 D6~D4,保留,固定值为0。 D3~D0,表示该端点的端点号。 |
3 | bmAttributes | 1 | 位图 | D1D0,端点的传输类型 00 = 控制传输 01 = 同步传输 10 = 批量传输 11 = 中断传输。 USB1.1中,其余各位是保留不用的,USB2.0中代表新的含义。 |
4 | wMaxPacketSize | 2 | 数字 | 2字节16位的数用来表示该端点最大包的大小。 其中D10~D0位为有效内容。 在USB1.1中D15~D11位保留,值为0,且最大包的大小范围为0~1023。 |
6 | bInterval | 1 | 数字 | 主机轮询设备的周期。 在USB1.1中,对于中断端点,该字段的值为1~255,时间单位为ms,因此假设值为250,则表示时间间隔为250ms; 对于同步端点,该字段值固定为1; 而批量端点和控制端点则忽略该字段,值无效。 |
字符串描述符 说明:它是一个可选的描述符。在前面4种类型的描述符中,已经看到内容为索引的字段,而这些索引正是对应的字符串描述符中一定字符串的编号。输出方向、端点号和端点容量及包的大小等。需要注意的是,端点描述符是作为配置描述符的一部分来返回给主机的,而不能直接通过控制传输中的Get_Descriptor或Set_Descriptor命令来访问。 | ||||
偏移量 | 字段名称 | 长度 (字节) | 字段值 | 意义 |
0 | bLength | 1 | 数字 | 字符串描述符的长度。 |
1 | bDescriptorType | 1 | 常数 | 固定值0x3。 |
2 | bString | N | 数字 | 以UNICODE编码的字符为内容的字符串。 |
标准的USB设备请求命令 |
控制传输的“初始设置步骤”中包含了1个8字节的DATA0数据包,这8字节的数据包是主机用来发送控制阶段中的请求命令的,而这些请求命令是主机配置USB设备的关键。这里就来详细分析这8字节请求命令的结构和内容。
设备请求命令的格式 说明:这些USB设备请求命令都是主机通过缺省的控制管道利用控制传输来发送的。在USB1.1中,这样的命令共有11个,它们的大小多是8字节,都具有相同的数据格式。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 请求命令类型。每一位代表一定的意义。 D7,选择数据传输方向,0 = 主机到设备(即输出OUT),1 = 设备到主机(即输入IN)。 D6D5,命令的类型 00 = 标准请求命令 01 = 类请求命令 10 = 用户定义的请求命令 11 = 保留 D4-D0,命令的接收者类型 00000 = 接收者为设备 00001 = 接收者为接口 00010 = 接收者为端点 00011 = 其他接收者 其他值保留。 | |
1 | bRequest | 1 | 请求命令代码。 在标准的USB请求命令中,USB为每一个命令定义了编号,即为此段的值。 0 = GET_STATUS 1 = CLEAR_FEATURE 3 = SET_FEATURE 5 = SET_ADDRESS 6 = GET_DESCRIPTOR 7 = SET_DESCRIPTOR 8 = GET_CONFIGURATION 9 = SET_CONFIGURATION 10 = GET_INTERFACE 11 = SET_INTERFACE 12 = SYNCH_FRAME | |
2 | wValue | 2 | 命令信息。 每一种请求命令都可以自行来定义这个字段的内容。 | |
4 | wIndex | 2 | 索引信息。 命令也可以自定义该字段的内容,但一般该字段的内容为索引值或偏移值。 当传输一个端点的索引值时: 第一字节 D7,方向位,0 = 输出OUT端点,1 = 输入IN端点 D3-D0,端点号 其他位即第二字节为保留值0。 当传输一个接口的索引值时: 第一字节 D7~D0,接口编号(可以在接口描述符中得到) 第二字节为保留值0。 | |
6 | wLength | 2 | 传输的数据大小。 该字段表示在控制传输的“可选数据步骤”中要传输的数据大小。 当数据发送方向是主机到设备时,字段值便是实际的数据大小; 当数据发送方向是设备到主机时,字段值是设备能够发送的最大数据包的大小 当然,设备实际发送的数据可以比wLength的值小。 |
获取状态请求GET_STATUS 说明:该命令用于返回特定接收者的状态信息,比如端点、接口等的状态。 | |||
偏移量 | 请求 | 大小 | 意义 |
0 | bmRequestType | 1 | 10000000或 10000001或 10000010 该字段值可以有3个。由于D7为1,表示该命令要求设备发送数据给主机; 而D1D0为00、01或10,说明该命令的接收者为设备、接口或端点。 |
1 | bRequest | 1 | 0x00(GET_STATUS) |
2 | wValue | 2 | 0x00 该命令没有包含特殊内容,因此没有启用该字段。 |
4 | wIndex | 2 | 该字段的值要与bmRequestType字段的内容匹配。 当命令接收者是设备时,值为0x00; 当命令接收者是接口时,值为相应接口的编号,即接口描述符的bInterfaceNumber字段值。 当命令接收者是端点时,值为相应端点的端点号,即端点描述符的bEndpointAddress字段值。 |
6 | wLength | 2 | 0x02 该命令要求设备返回相应接收者的状态,则该字段的值即为相应状态信息的大小,这里规定为2字节。 |
返回的状态信息数据: 这些数据不是该命令的一个字段,而是在控制传输的“可选数据步骤”中设备所返回的状态信息数据。 不同的命令接收者返回的状态数据是不一样的,但大小都是2字节,这是由wLength字段决定的。 命令接收者是设备时: 第一字节 D7~D2,保留值0。 D1,用于表示设备的远程唤醒能力 1 = 表示设备被使能并能够远程唤醒 0 = 远程唤醒能力被禁止,系统复位后,默认为0。 主机可以通过SET_FEATURE和CLEAR_FEATURE命令来改变设备的远程唤醒能力。 D0,指示设备的供电模式,1 = 自供电,0 = 总线供电,主机无法改变设备的供电模式。 第二字节为保留值0。 命令接收者是接口时: 返回的数据不带任何信息,第一字节和第二字节都为0。 命令接收者是端点时: 第一字节 D7~D1,保留值0。 D0,指示该端点是否被禁止,1 = 该端点状态正常,0 = 该端点处于禁止状态。 第二字节为保留值0。 |
清除特性请求CLEAR_FEATURE 说明:用于清除或禁用接收者的某些特性。 | ||||||||||||
偏移量 | 请求 | 大小 | 意义 | |||||||||
0 | bmRequestType | 1 | 00000000或 00000001或 00000010 该命令仅用于主机输出给设备,而命令的接收者可以是设备、接口或端点。 因此这3种接收者的某些特性就可以通过这个请求命令来清除或禁用。 | |||||||||
1 | bRequest | 1 | 0x01(CLEAR_FEATURE) | |||||||||
2 | wValue | 2 | 该字段内容是特性选择器。 这个特性选择器其实就是代表了一些特定的需要被清除或禁用的。 特性代码:
由字面意思可知道,要禁用的是特性的接收者和特性本身。 比如DEVICE_REMOVE_WAKEUP为设备的唤醒特性,通过此命令,主机可以禁用设备的远程唤醒功能。 而ENDPOINT_HALT特性选择器选择端点的禁用特性,主机可以利用此命令来解除一个端点的禁用状态。 需要注意的是由于特性选择器的接收者不同,因此,该字段的值要与bmRequestType字段的值相匹配。 | |||||||||
4 | wIndex | 2 | 同GET_STATUS命令一样,该字段的值要与bmRequestType字段的内容匹配。 当命令接收者是设备时,值为0x00; 当命令接收者是接口时,值为相应接口的编号,即接口描述符的bInterfaceNumber字段值。 当命令接收者是端点时,值为相应端点的端点号,即端点描述符的bEndpointAddress字段值。 | |||||||||
6 | wLength | 2 | 该命令没有要求设备返回任何数据,因此该字段值为0。 |
设置特性请求SET_FEATURE 说明:与CLEAR_FEATURE相对应,作用是主机用来启用或激活命令接收者的某些特性。 | ||||||||||||
偏移量 | 请求 | 大小 | 意义 | |||||||||
0 | bmRequestType | 1 | 10000000或 10000001或 10000010 该命令仅用于主机输出给设备,而命令的接收者可以是设备、接口或端点。 因此这3种接收者的某些特性就可以通过这个请求命令来启用或激活。 | |||||||||
1 | bRequest | 1 | 0x03(SET_FEATURE) | |||||||||
2 | wValue | 2 | 该字段内容是特性选择器。 这个特性选择器其实就是代表了一些特定的需要被启用或激活的。 特性代码:
由字面意思可知道,要启用的是特性的接收者和特性本身。 比如DEVICE_REMOVE_WAKEUP为设备的唤醒特性,通过此命令,主机可以启用设备的远程唤醒功能。 而ENDPOINT_HALT特性选择器选择端点的禁用特性,主机可以利用此命令来使一个端点处于禁用状态。 需要注意的是由于特性选择器的接收者不同,因此,该字段的值要与bmRequestType字段的值相匹配。 | |||||||||
4 | wIndex | 2 | 同GET_STATUS命令一样,该字段的值要与bmRequestType字段的内容匹配。 当命令接收者是设备时,值为0x00; 当命令接收者是接口时,值为相应接口的编号,即接口描述符的bInterfaceNumber字段值。 当命令接收者是端点时,值为相应端点的端点号,即端点描述符的bEndpointAddress字段值。 | |||||||||
6 | wLength | 2 | 该命令没有要求设备返回任何数据,因此该字段值为0。 |
设置地址请求SET_ADDRESS 说明:用于主机给设备分配地址。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 固定值0x00。 | |
1 | bRequest | 1 | 0x05(SET_ADDRESS) | |
2 | wValue | 2 | 主机分配给设备的地址。 | |
4 | wIndex | 2 | 由于请求命令的接收者仅为设备,因此该值为0。 | |
6 | wLength | 2 | 该命令没有要求设备返回任何数据,因此该字段值为0。 |
获取描述符请求GET_DESCRIPTOR 说明:主机获取设备的特定描述符。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 10000000 数据方向是输入IN,即设备发送数据给主机。而命令接收者为设备。 | |
1 | bRequest | 1 | 0x06(GET_DESCRIPTOR) | |
2 | wValue | 2 | 高字节为描述符的类型编号,低字节为描述符编号。 这些值可以在描述符中找到字段值对应。 | |
4 | wIndex | 2 | 如果该命令获取的是字符串描述符,则此字段的内容即为与字符串有关的语言ID; 如果该命令获取的是设备或配置描述符,则此字段值为0。 注意,该命令能够获取的描述符只有3类:设备描述符、配置描述符和字符串描述符。 | |
6 | wLength | 2 | 该字段的值即为要求设备返回的数据大小。 | |
返回的描述符数据 此数据即为设备在控制传输的“可选数据步骤”中返回的描述符。 当该命令获取的是配置描述符时,设备将会按顺序返回该配置描述符,以及该配置支持的所有接口描述符和接口使用的所有端点描述符。 发送的顺序是:发送配置描述符,然后发送第一个接口描述符,再发送该接口使用的端点描述符;接下来,才发送配置支持的第二个接口描述符(如果存在的话),再发送该接口使用的所有端点描述符。 |
设置描述符请求SET_DESCRIPTOR 说明:主机利用该请求命令来修改设备中的有关描述符,或者增加新的描述符。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 固定值0x00。 因此数据方向是输出OUT,即主机发送数据给设备,而命令接收者是设备。 | |
1 | bRequest | 1 | 0x07(SET_DESCRIPTOR) | |
2 | wValue | 2 | 高字节为描述符的类型编号,低字节为描述符的字符串索引。 这些值可以在描述符中找到字段值对应。 | |
4 | wIndex | 2 | 如果该命令修改或增加的是字符串描述符,则此字段的内容即为与字符串有关的语言ID; 如果该命令修改或增加的是设备或配置描述符,则此字段值为0。 注意,该命令能够修改或增加的描述符只有3类:设备描述符、配置描述符和字符串描述符。 | |
6 | wLength | 2 | 该字段的值即为主机发送的描述符的大小。 | |
数据 此数据即为主机在控制传输的“可选数据步骤”中发送给设备的新的或修改后的描述符。 |
获取配置请求GET_CONFIGURATION 说明:主机利用此命令得知设备当前的配置值。 请注意该命令与GET_DESCRIPTOR请求的区别: 该命令仅是获取当前设备的配置值,而配置描述符只能通过GET_DESCRIPTOR请求来获取。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 10000000 数据方向是输入IN,即设备返回给主机数据,请求命令的接收者为设备。 | |
1 | bRequest | 1 | 0x08(GET_CONFIGURATION) | |
2 | wValue | 2 | 值为0。 | |
4 | wIndex | 2 | 值为0。 | |
6 | wLength | 2 | 0x01 表示设备返回的大小。 | |
数据 即在控制传输的“可选数据步骤”中设备返回给主机的当前配置值,即配置描述符中的bConfigurationValue字段的值。 |
设置配置请求SET_CONFIGURATION 说明:主机利用此命令来指示设备采用要求的配置。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 00000000 数据方向是输出OUT,即主机发送给设备,请求命令的接收者为设备。 | |
1 | bRequest | 1 | 0x09(SET_CONFIGURATION) | |
2 | wValue | 2 | 值为主机要求设备采用的配置的配置值,即配置描述符中的bConfigurationValue字段内容。 | |
4 | wIndex | 2 | 值为0。 | |
6 | wLength | 2 | 值为0. |
获取接口请求GET_INTERFACE 说明:主机利用命令来获取当前的某个接口的接口描述符编号。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 10000001 数据方向为输入IN,请求命令的接收者为设备。 | |
1 | bRequest | 1 | 0x0A(GET_INTERFACE) | |
2 | wValue | 2 | 值为0。 | |
4 | wIndex | 2 | 值为接收该命令的接口的编号,即接口描述符中的bInterfaceNumber字段的值。 | |
6 | wLength | 2 | 值为1,即表示设备返回的数据大小为1字节。. | |
数据 该数据为设备在“可选数据步骤”中返回给主机的与特定接口描述符一一对应的接口描述符编号,即接口描述符中的bAlternateSetting字段的值。 |
设置接口请求SET_INTERFACE 说明:主机利用此命令来要求设备用某个接口描述符来描述接口。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 00000001 数据方向是输出OUT,即主机发送给设备,请求命令的接收者为设备。 | |
1 | bRequest | 1 | 0x0B(SET_INTERFACE) | |
2 | wValue | 2 | 值为主机希望设定的接口描述符编号,即接口描述符中的bAlternateSetting字段。 | |
4 | wIndex | 2 | 值为接收该命令的接口编号,即接口描述符中的bInterfaceNumber字段的值。 | |
6 | wLength | 2 | 值为0。 |
同步帧请求SYNCH_FRAME 说明:此命令用于设备设置和报告一个端点的同步帧。 | ||||
偏移量 | 请求 | 大小 | 意义 | |
0 | bmRequestType | 1 | 10000010 数据方向为输入IN,请求命令的接收者为端点。 | |
1 | bRequest | 1 | 0x0C(SYNCH_FRAME) | |
2 | wValue | 2 | 值为0。 | |
4 | wIndex | 2 | 值为端点号,即端点描述符中的bEndpointAddress字段的值。 | |
6 | wLength | 2 | 值为2,即表明接下来端点返回的数据大小为2字节。 | |
数据 内容为端点返回帧号。 |