USB枚举是host端为了配置(加载合适的驱动)device进行的一个重要配置,如果枚举成功,那么设备正常工作的可能性约为90%,是USB驱动程序中重要的一项配置。主要进行的操作就是获取配置描述符,解析配置描述符、解析端口描述符;简而言之就是从device端获取device性能和配置。
先介绍一下枚举过程中涉及的结构体和成员:
第一个 usb 配置描述符
struct usb_config_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 wTotalLength;
__u8 bNumInterfaces;
__u8 bConfigurationValue;
__u8 iConfiguration;
__u8 bmAttributes;
__u8 bMaxPower;
} __attribute__ ((packed));
#define USB_DT_CONFIG_SIZE 9
bLength: 表示usb 配置描述符所占字节长度,一般为 9 bytes(标准usb协议),也可能更多,根据usb设备厂商而定
bDdescriptorType: 描述符的类型,表示这是配置描述符,固定为0x02
wTotallLength: 表示所有配置描述符所占字节数的大小,即 配置描述符 + 接口描述符 + 端点描述符 的总字节数
bNumInterfaces:该配置下有多少个接口数,一种配置(config)就代表一种功能(如 U盘),一个功能可能有多个接口
bConfigurationValue: 当前配置
iConfiguration:描述配置的字符串索引
bmAttributes:供电配置,其bit位定义如下:
D7 保留,必须 为 1
D6 自供电模式
D5 远程唤醒
D4~D0 保留
bMaxPower:最大功耗,以2mA为步进,如 0x05 表示的功耗为 5 * 2 = 10mA
第二个 接口描述符
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
} __attribute__ ((packed));
#define USB_DT_INTERFACE_SIZE 9
bLength: 表示usb 端点描述符所占字节长度,一般为 9 bytes(标准usb协议),也可能更多,根据usb设备厂商而定
bDdescriptorType: 描述符的类型,表示这是配置描述符,固定为0x04
bInerfaceNumber:接口编号,一配置下可能有多个接口,这种情况下一般是从0开始编号
bAlternateSetting:当前选中的设置
bNumEndpoints:该接口下的端点数目,一个接口可能有多个端点
bInterfaceclass、bInterfacesubclass、bInterfaceProtocol分别表示接口的类、子类及所支持的协议。
iInterface:该接口的字符串索引值
第三个 端口描述符
struct usb_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress;
__u8 bmAttributes;
__le16 wMaxPacketSize;
__u8 bInterval;
/* NOTE: these two are _only_ in audio endpoints. */
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
bLength: 表示usb 端点描述符所占字节长度,
bDdescriptorType: 描述符的类型,表示这是配置描述符,固定为0x05
bEndpointAddress:端点的地址,根据协议 bit7 表示方向,1为IN,0为OUT,bit6~bit4 保留,bit3~bit0 为端点编号
bmAttributes:表示端点的属性,根据协议,其定义为:
bit0~bit1 传输类型 | 0 | 控制传输 | bit2~bit3 同步类型 | 0 | 不同步 | bit4~bit5 端点类型 | 0 | 数据端点 |
1 | 同步传输 | 1 | 异步 | 1 | 反馈端点 | |||
2 | 块传输 | 2 | 自适应 | 2 | 隐式反馈端点 | |||
3 | 中断传输 | 3 | 同步 | 3 | 保留 |
wPackageSize:该端点所能处理最多字节数的数据
bInterval: 端点访问时间间隔
接了下来两个是和音频相关额外的描述符。
在解析描述符时,还有两个常用的 结构体,
struct usb_host_interface {
struct usb_interface_descriptor desc;
int extralen;
unsigned char *extra; /* Extra descriptors */
/* array of desc.bNumEndpoints endpoints associated with this
* interface setting. these will be in no particular order.
*/
struct usb_host_endpoint *endpoint;
char *string; /* iInterface string, if present */
};
该结构体表示在host端呈现出的接口描述符。
struct usb_descriptor_header {
__u8 bLength;
__u8 bDescriptorType;
} __attribute__ ((packed));
常用来获取类型和长度,节约内存。