USB各种描述符的拓扑关系
- 每一个USB设备只有一个设备描述符,主要向主机说明设备类型、端点0最大包长、设备版本、配置数量等等。
- 每一个USB设备至少有一个或者多个配置描述符 ,但是主机同一时间只能选择某一种配置。标准配置描述符主要向主机描述当前配置下的设备属性、所需电流、支持的接口数、配置描述符集合长度等等。
- 每一个USB配置下至少有一个或者多个接口描述符 。接口描述符主要说明设备类型,此接口下使用的端点数(不包括0号端点),一个接口就是实现一种功能。
- 端点是实现USB设备功能的物理缓冲区实体,USB主机和设备是通过端点进行数据交互的 。每个端点都有一定的属性,其中包括传输方式、总线访问频率、带宽、端点号和数据包的最大容量等。一个USB端点只能在一个方向承载数据,或者从主机到设备(称为输出端点),或者从设备到主机(称为输入端点),因此端点可看作一个单向的管道。端点0通常为控制端点,用于设备初始化参数等。只要设备连接到USB上并且上电端点0就可以被访问。端点1、2等一般用作数据端点,存放主机与设备间往来的数据。
USB设备描述符
USB设备描述符是USB设备在进行插拔和初始化过程中,最先被主机读取的一部分信息,它包含了设备的一些基本属性信息,如USB规范版本、设备类、设备子类、设备协议、最大数据包长度等。
USB设备描述符通常是在设备插入时被主机读取,在获取到设备描述符后,主机可以自动加载相应的驱动程序,完成设备的初始化和配置。
设备描述符是USB设备的第一个描述符,每个USB设备都得具有设备描述符,且只能拥有一个。
设备描述符定义
偏移 | 字段 | 大小(字节) | 说明 |
---|---|---|---|
0 | bLength | 1 | 设备描述符的字节长度 = 18 个字节,固定为0x12 |
1 | bDescriptorType | 1 | 描述符类型编号,固定为0x01 |
2 | bcdUSB | 2 | USB版本号,表示了本设备能适用于那种协议,如USB2.0=0x0200,USB1.1=0x0110等 |
4 | bDeviceClass | 1 | USB分配的设备类代码,0x01~0xfe为标准设备类,0xff为厂商自定义类型,0x00不是在设备描述符中定义的,如HID |
5 | bDeviceSubClass | 1 | 子类型代码(由USB分配),如果bDeviceClass值是0,一定要设置为0.其它情况就跟据USB-IF组织定义的编码 |
6 | bDeviceProtocol | 1 | 协议代码(由USB分配),如果使用USB-IF组织定义的协议,就需要设置这里的值,否则直接设置为0。如果厂商自己定义的可以设置为0xff。 |
7 | bMaxPacketSize0 | 1 | 端点 0 的最大数据包大小(只有8,16,32,64有效) |
8 | idVendor | 2 | 供应商 ID(VID,由 USB-IF 分配) |
10 | idProduct | 2 | 产品 ID(PID,由制造商分配) |
12 | bcdDevice | 2 | 设备出厂编号(BCD) |
14 | iManufacturer | 1 | 厂商描述符字符串索引,索引到对应的字符串描述符, 为0则表示没有 |
15 | iProduct | 1 | 产品描述符字符串索引,索引到对应的字符串描述符, 为0则表示没有 |
16 | iSerialNumber | 1 | 设备序列号字符串索引,索引到对应的字符串描述符, 为0则表示没有 |
17 | bNumConfigurations | 1 | 可能的配置数,定义设备以当前速度支持的配置数量 |
设备描述符示例
c
#define USB_LEN_DEV_DESC 0x12U
#define USB_DESC_TYPE_DEVICE 0x01U
#define USB_MAX_EP0_SIZE 64U
#define USBD_IDX_MFC_STR 0x01U
#define USBD_IDX_PRODUCT_STR 0x02U
#define USBD_IDX_SERIAL_STR 0x03U
#define USBD_MAX_NUM_CONFIGURATION 1U
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_HS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
0x00, /*bcdUSB */
0x02,
0x02, /*bDeviceClass*/
0x02, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_HS), /*idProduct*/
HIBYTE(USBD_PID_HS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
USB配置描述符
配置描述符定义了设备的配置信息,一个设备可以有多个配置描述符。大部分的USB设备只有一个配置描这符,设备存在多个配置描述符时。配置描述符指定设备的供电方式、最大功耗是多少、它拥有的接口数量。因此,可以有两种配置,一种用于设备由总线供电时,另一种用于设备供电时。由于这是接口描述符的"头",因此使一种配置使用与另一种配置不同的传输模式也是可行的。一旦主机检查了所有配置,主机将发送具有非零值的 SetConfiguration 命令,该值与其中一个配置的bConfigurationValue 匹配。这用于选择所需的配置。
第一次只获取配置描述符的基本长度9字节,获取后从wTotalLength字节中解析出配置描述符的总长度,然后再次获取全部的描述符。配置描述数据中不仅包括配置描述符本身,也包括其下的接口描述符和端点描述符。
配置描述符定义
偏移 | 字段 | 大小(字节) | 说明 |
---|---|---|---|
0 | bLength | 1 | 配置描述符的字节数大小 = 9 个字节,固定为0x09 |
1 | bDescriptorType | 1 | 配置描述符类型 ,固定为0x02 |
2 | wTotalLength | 2 | 返回整个数据的长度,指此配置返回的配置描述符,接口描述符 以及端点描述符的全部大小。 |
4 | bNumInterfaces | 1 | 指该配置配备的接口数量,也表示该配置下接口描述符数量 |
5 | bConfigurationValue | 1 | 作为Set Configuration的一个参数选择配置值 |
6 | iConfiguration | 1 | 描述该配置的字符串索引 |
7 | bmAttributes | 1 | 供电模式选择.Bit4-0保留 |
位 7:预留(设置为 1) | |||
位 6:自供电 | |||
位 5:远程唤醒 | |||
8 | bMaxPower | 1 | 本配置所需的最大功耗(单位为 2 mA) |
9 | 接口描述符 | N | 接口描述符说明了接口所提供的配置,一个配置所拥有的接口数量通过配置描述符的bNumInterfaces决定 |
配置描述符示例
c
#define USB_CDC_CONFIG_DESC_SIZ 67U
#define USB_DESC_TYPE_CONFIGURATION 0x02U
#define USBD_SELF_POWERED 0U
#define USBD_MAX_POWER 0x32U /* 100 mA */
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength */
0x00,
0x02, /* bNumInterfaces: 2 interfaces */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/*-------------------------下面的接口描述符省略----------------------------------*/
};
USB接口描述符
接口描述符一般是按设备的运行状态分类,这样设备可以在不同的接口中切换来实现设备运行状态的切换,如在设备在运行状态下使用正常的接口描述符,在停止状态下使用该接口描述符的备用接口描述符。
接口描述符定义
偏移 | 字段 | 大小 (字节) | 说明 |
---|---|---|---|
0 | bLength | 1 | 接口描述符的长度 = 9 个字节,固定为0x09 |
1 | bDescriptorType | 1 | 接口描述符类型,固定为0x04 |
2 | bInterfaceNumber | 1 | 该接口基于零的索引 |
3 | bAlternateSetting | 1 | 用于为上一个字段选择可供替换的位置.即备用的接口描述符编号 |
4 | bNumEndpoints | 1 | 该接口使用端点数,不包括端点0 |
5 | bInterfaceClass | 1 | 接口类别 |
6 | bInterfaceSubclass | 1 | 接口子类别 |
7 | bInterfaceProtocol | 1 | 接口协议 |
8 | iInterface | 1 | 该接口字符串描述符索引 |
接口描述符示例
c
#define USB_DESC_TYPE_INTERFACE 0x04U
/* Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoint used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface */
/* Data class interface descriptor */
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface */
这里有两个接口描述符,关于接口类别,可以参考下表:
类别 | 使用说明 | 说明 | 示例 |
---|---|---|---|
00h | 设备 | 未指定 | 无法确定设备类型,需查看接口描述符 |
01h | 接口 | 音频 | 扬声器、麦克风、声卡、MIDI |
02h | 两者 | 通信和 CDC 控制 | 调制解调器、以太网适配器、无线适配器 |
03h | 接口 | 人机界面设备(HID) | 键盘、鼠标、游戏杆 |
05h | 接口 | 物理接口设备(PID) | 强制反馈游戏杆 |
06h | 接口 | 图像 | 摄像机、扫描仪 |
07h | 接口 | 打印机 | 打印机、CNC 机械 |
08h | 接口 | 大容量存储器 | 外部硬盘、闪存驱动、存储卡 |
09h | 设备 | USB 集线器 | USB 集线器 |
0Ah | 接口 | CDC 数据 | 与类 02h 结合使用 |
0Bh | 接口 | 智能卡 | USB 智能读卡器 |
0Dh | 接口 | 内容安全 | 指纹识别器 |
0Eh | 接口 | 视频 | 摄像头 |
0Fh | 接口 | 个人医疗保健 | 心率监视器、血糖仪 |
DCh | 两者 | 诊断设备 | 符合 USB 规范的测试设备 |
E0h | 接口 | 无线控制器 | 蓝牙适配器 |
EFh | 两者 | 其他 | ActiveSync 设备 |
FEh | 接口 | 专门应用 | IrDA 桥接器、测试测量类、USB DFU |
FFh | 两者 | 供应商特定 | 设备需供应商特定驱动程序 |
USB端点描述符
端点描述符定义
偏移 | 字段 | 大小 (字节) | 说明 |
---|---|---|---|
0 | bLength | 1 | 端点描述符长度,固定为7个字节。 |
1 | bDescriptorType | 1 | 端点描述符类型,固定为0x05 。 |
2 | bEndpointAddress | 1 | 端点地址: - bit3-0:端点号 - bit6-4:预留(复位为零) - bit7:端点方向,0: OUT 端点,1: IN 端点。(控制端点可以忽略该位) |
3 | bmAttributes | 1 | 端点属性: - bit1-0:传输类型(00: 控制, 01: 同步, 10: 批量, 11: 中断) - bit7-2:保留(同步传输时有定义) 当为同步传输时:bit3-2的值不同代表的含义不同: 00:无同步 01:异步 10:适配 11:同步 BIT5:4 00: 表示数据端点 01:表示反馈端点Feedback endpoint 10:表示隐式反馈数据端点 Implicit feedback Data endpoint 11:保留 |
4 | wMaxPacketSize | 2 | 该端点支持的最大数据包尺寸。 |
6 | bInterval | 1 | 中断端点的轮询间隔,以ms为单位(对于同步端点,该间隔为1ms;对于控制或批量端点,此字段可忽略)。 |
传输方式和特点
传输方式 | 用途 | 特点 | 包大小(字节) |
---|---|---|---|
控制传输 | 设备初始化、配置和状态查询 | 可靠、双向 | 8/16/32/64 (全速/高速) |
批量传输 | 大量数据传输,如文件传输 | 可靠、单向 | 8/16/32/64 (全速) / 512 (高速) |
中断传输 | 周期性、实时性要求高的小数据传输 | 单向、定时轮询 | 0~8 (低速) / 0~64 (全速) / 0~1024 (高速) |
同步传输 | 实时性要求极高的数据传输 | 不可靠、保证带宽 | 1023 (全速) / 1024 (高速) |
端点描述符示例
c
#define USB_DESC_TYPE_ENDPOINT 0x05U
#define CDC_CMD_EP 0x82U /* EP2 for CDC commands */
#define CDC_FS_BINTERVAL 0x10U
#define CDC_IN_EP 0x81U /* EP1 for data IN */
#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
/* Endpoint 2 Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_CMD_PACKET_SIZE),
CDC_FS_BINTERVAL, /* bInterval */
/*---------------------------------------------------------------------------*/
/* Endpoint IN Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00 /* bInterval */