Linux那些事儿 之 戏说USB(13)接口是设备的接口(二)
struct usb_host_interface {struct usb_interface_descriptor desc;int extralen;unsigned char *extra; /* Extra descriptors *//* array of desc.bNumEndpoint endpoints associated with this* interface setting. these will be in no particular order.*/struct usb_host_endpoint *endpoint;char *string; /* iInterface string, if present */
};desc,接口的描述符。什么叫描述符?usb的描述符是一個帶有預定義格式的數據結構,里面保存了usb設備的各種屬性還有相關信息,姓甚名誰啊,哪兒生產的啊等等,我們可以通過向設備請求獲得它們的內容來深刻的了解感知一個usb設備。主要有四種usb描述符,設備描述符,配置描述符,接口描述符和端點描述符,協議里規定一個usb設備是必須支持這四大描述符的,當然也有其它一些描述符來讓設備可以顯得個性些,但這四大描述符是一個都不能少的。
這些描述符放哪兒?描述符就在設備里,等著主機去拿。具體在哪兒?usb設備里都會有一個叫EEPROM的東東,沒錯,就是放在它那兒,它就是用來存儲設備本身信息的。你應該還會記得EEPROM就是電可擦寫的可編程ROM,它與Flash雖說都是要電擦除的,但它可以按字節擦除,Flash只能一次擦除一個block,所以如果要改動比較少的數據的話,使用它還是比較合適的,但是世界上沒有完美的東西,此物成本相對Flash比較高,所以一般來說usb設備里只拿它來存儲一些本身特有的信息,要想存儲數據,還是用Flash吧。
具體到接口描述符,它當然就是描述接口本身的信息的。一個接口可以有多個設置,使用不同的設置,描述接口的信息會有些不同,所以接口描述符并沒有放在struct usb_interface結構里,而是放在表示接口設置的struct usb_host_interface結構里。struct usb_interface_descriptor定義在/include/uapi/linux/usb/ch9.h文件里/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {__u8 bLength;__u8 bDescriptorType;__u8 bInterfaceNumber;__u8 bAlternateSetting;__u8 bNumEndpoints;__u8 bInterfaceClass;__u8 bInterfaceSubClass;__u8 bInterfaceProtocol;__u8 iInterface;
} __attribute__ ((packed));看到了__attribute__,意思就是告訴編譯器,這個結構的元素都是1字節對齊的,不要再添加填充位了。因為這個結構和spec里的Table 9.12是完全一致的,包括字段的長度,如果不給編譯器這么個暗示,編譯器就會依據你平臺的類型在結構的每個元素之間添加一定的填充位,如果你拿這個添加了填充位的結構去向設備請求描述符,你想想會是什么結果。
bLength,描述符的字節長度。協議里規定,每個描述符必須以一個字節打頭來表明描述符的長度。那可以扳著指頭數一下,接口描述符的bLength應該是9,兩個巴掌就數完了,沒錯,ch9.h文件里緊挨著接口描述符的定義就定義了這個長度
#define USB_DT_INTERFACE_SIZE 9
bDescriptorType,描述符的類型。各種描述符的類型都在ch9.h文件里有定義,對應spec Table 9.5。對于接口描述符來說,值為USB_DT_INTERFACE,也就是0x04。
bAlternateSetting,接口使用的是哪個可選設置。協議里規定,接口默認使用的設置總為0號設置。
bNumEndpoints,接口擁有的端點數量。這里并不包括端點0,端點0是所有的設備都必須提供的,所以這里就沒必要多此一舉的包括它了。
bInterfaceClass,bInterfaceSubClass,bInterfaceProtocol。這個世界上有許許多多的usb設備,它們各有各的特點,為了區分它們,usb規范,或者說usb協議,把usb設備分成了很多類,然而每個類又分成子類,這很好理解,我們一個大學也是如此,先是分成很多個學院,然后每個學院又被分為很多個系,然后可能每個系下邊又分了各個專業,usb協議也是這樣干的,首先每個Device或Interface屬于一個Class,然后Class下面又分了SubClass,完了SubClass下面又按各種設備所遵循的不同的通信協議繼續細分。usb協議里邊為每一種Class,每一種SubClass,每一種Protocol定義一個數值,比如mass storage 的Class就是0x08,hub的Class就是0x09。
iInterface,接口對應的字符串描述符的索引值。疑?這里怎么又跳出來一個叫字符串描述符的東東?你沒看錯我也沒說錯,除了前面提到的四大描述符,是還有字符串描述符,不過那四大描述符是每個設備必須支持的,這個字符串描述符卻是可有可無的,有了你歡喜我也歡喜,沒有也不是什么問題。使用lsusb命令看一下
localhost:/usr/src/linux/drivers/usb/core # lsusbBus 001 Device 013: ID 04b4:1081 Cypress Semiconductor Corp.
Bus 001 Device 001: ID 0000:0000
第一行里顯示的是我手邊兒的Cypress USB開發板,看里面的Cypress Semiconductor Corp.,這么一長串的東東從哪里來?是不是應該從設備里來?設備的那幾個標準描述符,整個描述符的大小也不一定放得下這么一長串,所以,一些設備專門準備了一些字符串描述符(string descriptor),就用來記這些長串的東西。字符串描述符主要就是提供一些設備接口相關的描述性信息,比如廠商的名字,產品序列號等等。字符串描述符當然可以有多個,這里的索引值就是用來區分它們的。
說過了接口描述符,回到struct usb_host_interface,endpoint,一個數組,表示這個設置所使用到端點。至于端點的結構struct usb_host_endpoint,天這么熱,讓它先一邊兒涼快涼快吧,咱們先看完struct usb_host_interface再去說它。
string,用來保存從設備里取出來的字符串描述符信息的,既然字符串描述符可有可無,那這里的指針也有可能為空了。extra,extralen,關于額外的描述符。除了前面提到的四大描述符還有字符串描述符外,還有為一組設備也就是一類設備定義的描述符,和廠商為設備特別定義的描述符,extra指的就是它們,extralen表示它們的長度。比如上海規定了,社保必須得交多少多少,公積金多少多少,有個最低的比例,有地兒覺得太少,給你多交些,叫補充什么金的,還有些地兒,覺得補充都不過癮,像公務員........
總結
以上是生活随笔為你收集整理的Linux那些事儿 之 戏说USB(13)接口是设备的接口(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux那些事儿 之 戏说USB(12
- 下一篇: Linux那些事儿 之 戏说USB(14