
Linux usb system(descriptor)
為了更好地描述USB設(shè)備的特征,USB提出了設(shè)備架構(gòu)的概念。從這個角度來看,可以認(rèn)為USB設(shè)備是由一些配置、接口和端點組成,即一個USB設(shè)備可以含有一個或多個配置,在每個配置中可含有一個或多個接口,在每個接口中可含有若干個端點。
這個步驟一般是在設(shè)備接入主機時設(shè)備進行枚舉時完成的這些單元之間的關(guān)系如下:

解釋說明:
- USB設(shè)備可以看作提供了多個串口的設(shè)備,依據(jù)USB的規(guī)范,我們將每個串口稱作端點(Endpoint),要和這個端點通信,我們就要打開到這個端點的連接,這個連接就是管道(Pipe)。
- 由于一個設(shè)備可能要適應(yīng)多種情況,端點的設(shè)置會有多套,以備使用。端點設(shè)置稱為接口(Interface)。USB設(shè)備展現(xiàn)給我們能夠找到的東西就是這些Interface,我們選擇要用的Interface,就可以找到Endpoint,再打開Endpoint,就可以傳輸數(shù)據(jù)了。
- 配置和接口是對USB設(shè)備功能的抽象,實際的數(shù)據(jù)傳輸由端點來完成。在使用USB設(shè)備前,必須指明其采用的配置和接口,在驅(qū)動程序開始的時候,需要記錄下這些Interface,一個接口對應(yīng)一個驅(qū)動。
- 在Linux系統(tǒng)的終端通過輸入
lsusb -v,可以看下詳細的描述信息,可以先輸入查看下,熟悉下框架。
描述符的分類如下,除了比標(biāo)準(zhǔn)的描述符外,如果標(biāo)準(zhǔn)設(shè)備類為HID或Hub,可會有對應(yīng)的HID描述符或Hub描述符:
- 標(biāo)準(zhǔn)描述符(設(shè)備描述符、配置描述符、字符串描述符、接口描述符、端點描述符、設(shè)備限定描述符、其他速率配置描述符)
- HID描述符
- Hub描述符
這邊將描述符的主要四個描述符(設(shè)備描述符、配置描述符、接口描述符、端點描述符)進行說明,這四個是必須的,其他描述符是選配。
1.1 設(shè)備描述符
位于/include/linux/usb/ch9.h中,如下:
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 bcdUSB;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bMaxPacketSize0;
__le16 idVendor;
__le16 idProduct;
__le16 bcdDevice;
__u8 iManufacturer;
__u8 iProduct;
__u8 iSerialNumber;
__u8 bNumConfigurations;
}

各字段含義:
- bLength: 表示描述符的長度,對于設(shè)備描述符來說,其值為18,即0x12。
- bDescriptorType: 描述符類型,對應(yīng)表1中的值,設(shè)備描述符為0x01。
- bcdUSB:該設(shè)備遵循的USB版本號,以BCD碼表示,USB1.1為0x0101,USB2.0為0x0200。
- bDeviceClass:該設(shè)備所屬的標(biāo)準(zhǔn)設(shè)備類,USB協(xié)議中對常見的設(shè)備進行了分類。該字段值為0x01~0xFE時,表示是USB協(xié)議中已定義的設(shè)備類,常用的HID設(shè)備類編號為0x03,其它設(shè)備類編號參考:http://www.usb.org/developers/defined_class
- bDeviceProtocol:用于表示USB設(shè)備類所采用的設(shè)備類協(xié)議,其值和bDeviceClass和
bDeviceSubClass有關(guān)。當(dāng)此字段為0時,表示不使用任何設(shè)備類協(xié)議。如果該USB設(shè)備屬于某個設(shè)
備類和設(shè)備子類,則應(yīng)該繼續(xù)指明所采用的設(shè)備類協(xié)議。當(dāng)該字段為0xFF時,表明設(shè)備類協(xié)議由供應(yīng)商自定義。 - bMaxPacketSize0:用于表示在USB設(shè)備中,端點0所支持最大數(shù)據(jù)包的長度,它以字節(jié)為單位。對于低速USB設(shè) 備,bMaxPacketSize0為8;對于全速USB設(shè)備,bMaxPacketSize0為8、16、32、64;對于高速USB設(shè) 備,bMaxPacketSize0為64。
- IdVendor:用于表示USB設(shè)備供應(yīng)商的ID。USB組織中規(guī)定每種產(chǎn)品都必須包含一個供應(yīng)商ID,這樣可以使主機加載合適的驅(qū)動程序。
- idProduct:用于表示USB產(chǎn)品的ID,由設(shè)備供應(yīng)商提供。idProduct用于表示特定的USB設(shè)備,在USB設(shè)備上電的時候可以幫助USB主機選擇合適的驅(qū)動程序。
- bcdDevice:用于表示USB設(shè)備的版本號,它以BCD碼的形式表示。一般來說bcdDevcie由設(shè)備供應(yīng)商指定,在USB設(shè)備上電的時候可以幫助USB主機選擇合適的驅(qū)動程序。
- iManufacturer:用于表示供應(yīng)商字符串描述符的索引值。具體字符串的內(nèi)容在后面字符串描述符中定義。如果沒有供應(yīng)商字符串,可以置0。
- iSerialNumber:用于表示設(shè)備序列號字符串描述符的索引值,如果沒有,可以置為0。
- bNumConfigurations:用于表示該USB設(shè)備所支持的配置數(shù)。
1.2 配置描述符
位于/include/linux/usb/ch9.h中,如下:
struct usb_config_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 wTotalLength;
__u8 bNumInterfaces;
__u8 bConfigurationValue;
__u8 iConfiguration;
__u8 bmAttributes;
__u8 bMaxPower;
}

各個字段含義:
- bLength:用于表示配置描述符的長度,固定為9個字節(jié),即0x09。
- bDescriptorType:用于表示配置描述符的類型值,固定為0x02。
- wTotalLength:用于表示配置信息的總長度,包括配置描述符、接口描述符、端點描述符長度的總和。
- bNumInterfaces:用于表示配置所支持的接口數(shù)。一般來說,USB設(shè)備的接口至少有一個,因此其最小值為1。
- bConfigurationValue:用于表示USB設(shè)備的配置值。
- iConfiguration:用于指出配置字符串描述符的索引值。具體字符串的內(nèi)容在后面字符串描述符中定義。如果沒有配置字符串,可以置為0。
- bmAttributes:用于表示USB設(shè)備特性。bmAttributes是接位尋址的,第6位置1表示使用總線電源;第5位置1表示支持遠程喚醒功能;該字段其他位均保留,一般來說,第0~4位置0即可,第7位置1即可。
- bMaxPower:用于表示USB設(shè)備運行時所需要消耗的總線電流,單位以2mA為基準(zhǔn)。USB設(shè)備可以從USB總線上獲得最大的電流為500mA,因此bMaxPower字段的最大值可以設(shè)置為250。
1.3 接口描述符
位于/include/linux/usb/ch9.h中,如下:
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
}

各字段含義:
- bLength:用于表示接口描述符的長度.固定為9字節(jié),即0x07。
- bDescriptorType: 用于表示接口描述符的類型值.固定為0x04。
- bInterfaceNumber:用于表示該接口的編號。
- bAlternateSetting:用于為上一個字段選擇可供替換的位置.即備用的接口描述符標(biāo)號。
- bNumEndpoints:使用的端點數(shù)目.端點0除外。
- bInterfaceClass:類型代碼(由USB分配)。
- bInerfaceSubclass:子類型代碼(由USB分配)。
- bInterfaceProtocol:協(xié)議代碼(由USB分配)。
- iInterface:字符串描述符的索引。
1.4 端點描述符
位于/include/linux/usb/ch9.h中,如下:
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;
}

各字段含義:
- bLength:用于表示端點描述符的長度,固定為7字節(jié),即0x07。
- bDescriptorType:用于表示接口描述符的類型值,固定為0x05。
- bEndpointAddress:用于表示端點的端點號以及端點的數(shù)據(jù)傳輸方向。第七位表示端點的數(shù)據(jù)傳輸方向,0表示OUT數(shù)據(jù)傳輸,1表示IN數(shù)據(jù)傳輸;第0~位表示端點號,例如001B表示端點1、010B表示端點2;其余位均保留,必須置0。
- bmAttributes:用于表示端點的特性。其中第0位和第1位表示端點的數(shù)據(jù)傳輸類型,00B表示控制傳輸、01B表示同步傳輸、10B表示塊傳輸、11B表示中斷傳輸;如果是同步傳輸,第2位和第3位表示同步類型,00B表示非同步、01B表示異步、10B表示自適應(yīng)、11B表示同步;第4、5 位表示端點的用法類型,00B表示數(shù)據(jù)端點、01B表示顯示反饋端點、10B表示隱匿反饋端點、11B保留。其余位保留。
- wMaxPacketSize:用于表示端點所支持最大數(shù)據(jù)包的長度。其中第0~10位表示數(shù)據(jù)包的長度,第11位和12位指出每小幀最多傳輸?shù)氖聞?wù)數(shù),其余位均保留,必須置0。
- bInterval:用于指定端點數(shù)據(jù)傳輸?shù)脑L問間隔。低速中斷端點,取值范圍為10~255,對應(yīng)的訪問間隔為10~255ms;對于全速中斷端點,取值范圍為1~255,對應(yīng)的訪問間隔為1~255ms;對于其他端點,可以參閱USB相關(guān)協(xié)議。
1.5 USB端點分類
USB 通訊的最基本形式是通過端點。一個USB端點只能向一個方向傳輸數(shù)據(jù)(從主機到設(shè)備(稱為輸出端點)或者從設(shè)備到主機(稱為輸入端點)),端點可被看作一個單向的管道。
USB 端點有 4 種不同類型, 分別具有不同的數(shù)據(jù)傳送方式:
1.控制CONTROL
控制端點被用來控制對USB設(shè)備的不同部分訪問.通常用作配置設(shè)備、獲取設(shè)備信息、發(fā)送命令到設(shè)備或獲取設(shè)備狀態(tài)報告。這些端點通常較小。每個USB設(shè)備都有一個控制端點稱為"端點 0", 被 USB 核心用來在插入時配置設(shè)備。USB協(xié)議保證總有足夠的帶寬留給控制端點傳送數(shù)據(jù)到設(shè)備。
2.中斷INTERRUPT
每當(dāng) USB 主機向設(shè)備請求數(shù)據(jù)時,中斷端點以固定的速率傳送小量的數(shù)據(jù)。此為USB鍵盤和鼠標(biāo)的主要的數(shù)據(jù)傳送方法。它還用以傳送數(shù)據(jù)到USB設(shè)備來控制設(shè)備。通常不用來傳送大量數(shù)據(jù)。USB協(xié)議保證總有足夠的帶寬留給中斷端點傳送數(shù)據(jù)到設(shè)備。
3.批量BULK
批量端點用以傳送大量數(shù)據(jù),這些端點通常比中斷端點大得多,它們普遍用于不能有任何數(shù)據(jù)丟失的情況。USB協(xié)議不保證傳輸在特定時間范圍內(nèi)完成。如果總線上沒有足夠的空間來發(fā)送整個BULK包,它被分為多個包進行傳輸。這些端點普遍用于打印機、USB Storage和USB網(wǎng)絡(luò)設(shè)備上。
4.等時ISOCHRONOUS
等時端點也批量傳送大量數(shù)據(jù),但是這個數(shù)據(jù)不被保證能送達。這些端點用在可以處理數(shù)據(jù)丟失的設(shè)備中,并且更多依賴于保持持續(xù)的數(shù)據(jù)流。如音頻和視頻設(shè)備等等??刂坪团慷它c用于異步數(shù)據(jù)傳送,而中斷和等時端點是周期性的。這意味著這些端點被設(shè)置來在固定的時間連續(xù)傳送數(shù)據(jù),USB 核心為它們保留了相應(yīng)的帶寬。
Linux usb system(descriptor)的分析就到這邊,有感悟時會持續(xù)會更新。
注:以上內(nèi)容都是本人在學(xué)習(xí)過程積累的一些心得,難免會有參考到其他文章的一些知識,如有侵權(quán),請及時通知我,我將及時刪除或標(biāo)注內(nèi)容出處,如有錯誤之處也請指出,進行探討學(xué)習(xí)。文章只是起一個引導(dǎo)作用,詳細的數(shù)據(jù)解析內(nèi)容還請查看Linux相關(guān)教程,感謝您的查閱。