USB裝置的列舉過程分析——資料結構先行

qq_20376499發表於2020-11-23

      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));

常用來獲取型別和長度,節約記憶體。

 

相關文章