轉載出處:http://justmei.blog.163.com/blog/static/11609985320102421659260/?latestBlogcode
USB是個通用的總線,端口都是統一的。可是USB設備卻各類各樣,例如USB鼠標,USB鍵盤,U盤等等,那麼USB主機是如何識別出不一樣的設備的呢?這就要依賴於描述符了。USB的描述符主要有設備描述符,配置描述符,接口描述符,端點描述符,字符串描述符,HID描述符,報告描述符等等。blog
一個USB設備有一個設備描述符,設備描述符裏面決定了該設備有多索引
少種配置,每種配置描述符對應着配置描述符;而在配置描述符中又定義接口
了該配置裏面有多少個接口,每一個接口有對應的接口描述符;在接口描ip
述符裏面又定義了該接口有多少個端點,每一個端點對應一個端點描述符;字符串
端點描述符定義了端點的大小,類型等等。由此咱們能夠看出,USB的get
描述符之間的關係是一層一層的,最上一層是設備描述符,下面是配置同步
描述符,再下面是接口描述符,再下面是端點描述符。在獲取描述符時,產品
先獲取設備描述符,而後再獲取配置描述符,根據配置描述符中的配置it
集合長度,一次將配置描述符、接口描述符、端點描述符一塊兒一次讀回。
其中可能還會有獲取設備序列號,廠商字符串,產品字符串等。
每種描述符都有本身獨立的編號,以下:
#define DEVICE_DESCRIPTOR 0x01 //設備描述符 #define CONFIGURATION_DESCRIPTOR 0x02 //配置描述符 #define STRING_DESCRIPTOR 0x03 //字符串描述符 #define INTERFACE_DESCRIPTOR 0x04 //接口描述符 #define ENDPOINT_DESCRIPTOR 0x05 //端點描述符
下面分別詳細介紹一下各描述符。
1.設備描述符
//定義標準的設備描述符結構
typedef struct _DEVICE_DCESCRIPTOR_STRUCT { BYTE blength; //設備描述符的字節數大小 BYTE bDescriptorType; //設備描述符類型編號 WORD bcdUSB; //USB版本號 BYTE bDeviceClass; //USB分配的設備類代碼 BYTE bDeviceSubClass; //USB分配的子類代碼 BYTE bDeviceProtocol; //USB分配的設備協議代碼 BYTE bMaxPacketSize0; //端點0的最大包大小 WORD idVendor; //廠商編號 WORD idProduct; //產品編號 WORD bcdDevice; //設備出廠編號 BYTE iManufacturer; //設備廠商字符串的索引 BYTE iProduct; //描述產品字符串的索引 BYTE iSerialNumber; //描述設備序列號字符串的索引 BYTE bNumConfigurations; //可能的配置數量 } DEVICE_DESCRIPTOR_STRUCT, * pDEVICE_DESCRIPTOR_STRUCT;
//實際的設備描述符示例
code DEVICE_DESCRIPTOR_STRUCT device_descriptor= //設備描述符 { sizeof(DEVICE_DESCRIPTOR_STRUCT), //設備描述符的字節數大小,這裏是18字節 DEVICE_DESCRIPTOR, //設備描述符類型編號,設備描述符是01 0x1001, //USB版本號,這裏是USB01.10,即USB1.1。因爲51是大端模式,因此高低字節交換 0x00, //USB分配的設備類代碼,0表示類型在接口描述符中定義 0x00, //USB分配的子類代碼,上面一項爲0時,本項也要設置爲0 0x00, //USB分配的設備協議代碼,上面一項爲0時,本項也要設置爲0 0x10, //端點0的最大包大小,這裏爲16字節 0x7104, //廠商編號,這個是須要跟USB組織申請的ID號,表示廠商代號。 0xf0ff, //該產品的編號,跟廠商編號一塊兒配合使用,讓主機註冊該設備並加載相應的驅動程序 0x0100, //設備出廠編號 0x01, //設備廠商字符串的索引,在獲取字符串描述符時,使用該索引號來識別不一樣的字符串 0x02, //描述產品字符串的索引,同上 0x03, //描述設備序列號字符串的索引,同上 0x01 //可能的配置數爲1,即該設備只有一個配置 };
2.配置描述符
//定義標準的配置描述符結構
typedef struct _CONFIGURATION_DESCRIPTOR_STRUCT { BYTE bLength; //配置描述符的字節數大小 BYTE bDescriptorType; //配置描述符類型編號 WORD wTotalLength; //此配置返回的全部數據大小 BYTE bNumInterfaces; //此配置所支持的接口數量 BYTE bConfigurationValue; //Set_Configuration命令所須要的參數值 BYTE iConfiguration; //描述該配置的字符串的索引值 BYTE bmAttributes; //供電模式的選擇 BYTE MaxPower; //設備從總線提取的最大電流 } CONFIGURATION_DESCRIPTOR_STRUCT, * pCONFIGURATION_DESCRIPTOR_STRUCT;
2.接口描述符
//定義標準的接口描述符結構
typedef struct _INTERFACE_DESCRIPTOR_STRUCT { BYTE bLength; //接口描述符的字節數大小 BYTE bDescriptorType; //接口描述符的類型編號 BYTE bInterfaceNumber; //該接口的編號 BYTE bAlternateSetting; //備用的接口描述符編號 BYTE bNumEndpoints; //該接口使用的端點數,不包括端點0 BYTE bInterfaceClass; //接口類型 BYTE bInterfaceSubClass; //接口子類型 BYTE bInterfaceProtocol; //接口遵循的協議 BYTE iInterface; //描述該接口的字符串索引值 } INTERFACE_DESCRIPTOR_STRUCT, * pINTERFACE_DESCRIPTOR_STRUCT;
4.端點描述符
//定義標準的端點描述符結構
typedef struct _ENDPOINT_DESCRIPTOR_STRUCT { BYTE bLegth; //端點描述符字節數大小 BYTE bDescriptorType; //端點描述符類型編號 BYTE bEndpointAddress; //端點地址及輸入輸出屬性 BYTE bmAttributes; //端點的傳輸類型屬性 WORD wMaxPacketSize; //端點收、發的最大包大小 BYTE bInterval; //主機查詢端點的時間間隔 } ENDPOINT_DESCRIPTOR_STRUCT, * pENDPOINT_DESCRIPTOR_STRUCT;
下面是一個配置描述符集合的定義
typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT { CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor; INTERFACE_DESCRIPTOR_STRUCT interface_descritor; ENDPOINT_DESCRIPTOR_STRUCT endpoint_descriptor[ENDPOINT_NUMBER]; }CON_INT_ENDP_DESCRIPTOR_STRUCT; 配置描述符集合的示例 code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor= //配置描述符集合 { //configuration_descriptor //配置描述符 { sizeof(CONFIGURATION_DESCRIPTOR_STRUCT), //配置描述符的字節數大小,這裏爲9 CONFIGURATION_DESCRIPTOR, //配置描述符類型編號,配置描述符爲2 (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+ sizeof(INTERFACE_DESCRIPTOR_STRUCT)+ sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)*256+ (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+ sizeof(INTERFACE_DESCRIPTOR_STRUCT)+ sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)/256, //配置描述符集合的總大小 0x01, //只包含一個接口 0x01, //該配置的編號 0x00, //iConfiguration字段 0x80, //採用總線供電,不支持遠程喚醒 0xC8 //從總線獲取最大電流400mA }, //interface_descritor //接口描述符 { sizeof(INTERFACE_DESCRIPTOR_STRUCT), //接口描述符的字節數大小,這裏爲9 INTERFACE_DESCRIPTOR, //接口描述符類型編號,接口描述符爲3 0x00, //接口編號爲4 0x00, //該接口描述符的編號爲0 ENDPOINT_NUMBER, //非0端點數量爲2,只使用端點主端點輸入和輸出 0x08, //定義爲USB大容量存儲設備 0x06, //使用的子類,爲簡化塊命令 0x50, //使用的協議,這裏使用單批量傳輸協議 0x00 //接口描述符字符串索引,爲0,表示沒有字符串 }, //endpoint_descriptor[] { { //主端點輸入描述 sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端點描述符的字節數大小,這裏爲7 ENDPOINT_DESCRIPTOR, //端點描述符類型編號,端點描述符爲5 MAIN_POINT_IN, //端點號,主輸入端點 ENDPOINT_TYPE_BULK, //使用的傳輸類型,批量傳輸 0x4000, //該端點支持的最大包尺寸,64字節 0x00 //中斷掃描時間,對批量傳輸無效 }, { //主端點輸出描述 sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端點描述符的字節數大小,這裏爲7 ENDPOINT_DESCRIPTOR, //端點描述符類型編號,端點描述符爲5 MAIN_POINT_OUT, //端點號,主輸出端點 ENDPOINT_TYPE_BULK, //使用的傳輸類型,批量傳輸 0x4000, //該端點支持的最大包尺寸,64字節 0x00 //中斷掃描時間,對批量傳輸無效 } } };
其中關於端點的類型定義以下
//定義的端點類型 #define ENDPOINT_TYPE_CONTROL 0x00 //控制傳輸 #define ENDPOINT_TYPE_ISOCHRONOUS 0x01 //同步傳輸 #define ENDPOINT_TYPE_BULK 0x02 //批量傳輸 #define ENDPOINT_TYPE_INTERRUPT 0x03 //中斷傳輸 //端點號的定義以下 #define MAIN_POINT_OUT 0x02 //2號輸出端點 #define MAIN_POINT_IN 0x82 //2號輸入端點