USB的设备描述符详解_具体含义

在USB上电枚举的过程中,有几个描述符是经常要用到的,它们分别是:设备描述符、配置描述符、接口描述符、端点描述符、HID描述符、字符串描述符以及语言ID描述符,最后是报告描述符。

其中设备描述符是USB主机申请的第1个描述符,然后配置描述符,接口描述符端点描述符hId描述符,以配置集合的形式返回给USB主机。字符串描述符是可选的,它和语言ID描述符一起发送给主机,告诉主机当前设备的名称是什么。

最麻烦的是报告描述符,它的结构和功能相比前面的几个描述符都发生了很大的变化,理解起来相对困难一些。

在稍后的文章中,我会尽量以通俗的语言来解释这几个描述符。这一节,咱们主要研究下设备描述符。

所谓描述符其实就是C语言里面的数组,数组里包含的信息说明当前的设备具有哪些特征。每个设备有且仅有一个设备描述符,设备描述符的长度是18字节,它的结构我们可以通过下面的表格来描了解。

偏移量 名称 大小 说明
0 bLength 1 描述符长度(18字节)
1 bDescriptorType 1 描述符类型(设备描述符为0x01)
2 bcdUSB 2 设备使用的USB协议版本
4 bDeviceClass 1 类代码
5 bDeviceSubClass 1 子类代码
6 bDeviceProtocol 1 设备使用的协议
7 bMaxPackeSize0 1 端点0最大包长
8 idVender 2 厂商ID
10 idProduct 2 产品ID
12 bcdDevice 2 设备版本号
14 iManufacturer 1 描述厂商的字符串的索引
15 iProduct 1 描述产品的字符串的索引
16 iSerialNumber 1 产品序列号字符串的索引
17 bNumConfigurations 1 可能的配置数

注意:USB协议中,数据格式使用“小端”模式,所以多个字节排列时,低位在前。

18个字节,包含14项内容,通过表格中的说明,我们可以获取很多信息。

bLength,不用说了,0x12=18

bDescriptorType,描述符类型。总共有哪些描述符?我们通过下面代码可以看出:

#define USB_DESC_TYPE_DEVICE 0x01U

#define USB_DESC_TYPE_CONFIGURATION 0x02U

#define USB_DESC_TYPE_STRING 0x03U

#define USB_DESC_TYPE_INTERFACE 0x04U

#define USB_DESC_TYPE_ENDPOINT 0x05U

#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U

#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U

#define USB_DESC_TYPE_BOS 0x0FU

bcdUSB,USB协议版本。如果是USB2.0,写成:

0x00,0x02

如果是USB1.1,写成

0x10,0x01

bDeviceClass和bDeviceSubClass,也就是类代码和子类代码,大部分情况下,这两个值都是0.

bDeviceProtocol,当bDeviceClass和bDeviceSubClass为0时,它也是0.

bMaxPackeSize0,USB协议中有一个端点的定义,你可以理解为通道。我们以高速公路为例:

向前有4个行车道(1,2,3,4),向后有4个行车道(1,2,3,4),这就是4个双向端点。假设它们都属于一条津某高速路(一个USB接口),有的向前有的向后(有的输入有的输出),有向前的1号行车道(有输出的1号端点)

至于最大包长,说白了就是一次最多传多少个字节。USB协议里有规定,端点0最低8字节,不能再少了。

厂商ID,就是个2字节的编号,由USB协议分配,厂商申请时需要交费。自己随便写的话,仅限于学习、测试的情况下,不能用做产品。

产品ID,厂家自己随便定义。

bcdDevice,设备版本,厂家根据自己产品的版本来定义。

后面三个:描述厂商的字符串的索引、描述产品的字符串的索引、产品序列号字符串的索引,如果是0,表示程序里没有这三项内容。如果想添加,这里按顺序设置索引号为1、2、3。为什么是这三个数字,后面讲到字符串描述符的时候会说明。

bNumConfigurations,可能的配置数,一般USB产品,这里都是1。

这里放一个STM32程序中自带的设备描述符来看一下:

/** USB standard device descriptor. */

__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =

{

0x12, /*bLength */

USB_DESC_TYPE_DEVICE, /*bDescriptorType 0x01*/

0x00, /*bcdUSB */

0x02,

0x00, /*bDeviceClass*/

0x00, /*bDeviceSubClass*/

0x00, /*bDeviceProtocol*/

USB_MAX_EP0_SIZE, /*bMaxPacketSize 64*/

LOBYTE(USBD_VID), /*idVendor*/

HIBYTE(USBD_VID), /*idVendor*/

LOBYTE(USBD_PID_FS), /*idProduct*/

HIBYTE(USBD_PID_FS), /*idProduct*/

0x00, /*bcdDevice rel. 2.00*/

0x02,

USBD_IDX_MFC_STR, /*Index of manufacturer string 1*/

USBD_IDX_PRODUCT_STR, /*Index of product string 2*/

USBD_IDX_SERIAL_STR, /*Index of serial number string 3*/

USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations 1*/

};

对照看一下,你会发现很好理解。

好了,打完收工!

《USB的设备描述符详解_具体含义》有2条评论

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据