usb驅動開發6之端點描述符


學到這里不容易,先說一段故事吧。

二兄弟住一大樓的第80層,某深夜回家忘看通知(內容今夜停電)。

兄弟倆背着沉重的大背包,在樓底下商量一下,決定一鼓作氣,爬樓梯回家。兩人抖擻精神,開始爬樓。爬到20樓的時候,開始覺得背包很重了。兩人商量,決定把背包存在20樓,到時候再回過頭來取。卸下了背包,兩個人覺得很輕松,說說笑笑地繼續往上爬。

爬到40樓的時候,兩人已經很累了,就開始互相抱怨指責。哥哥說:你為什么不看通知啊?弟弟說:我忘了看通知這件事,你怎么不提醒我昵?兩個人就這樣吵吵鬧鬧,一路吵到60層。

到了這時候,兩人實在疲憊不堪,終於懶得吵了,覺得還是應該安安靜靜地繼續爬樓。當他們終於爬完了最后20層,來到了家門口的時候,兩個人互相一看,不約而同想起了一件事:鑰匙忘在20樓了,在背包里。

其實,這說的就是人的一生。(故事來源 於丹 《論生與死》)

在struct usb_host_interface結構體,我們把struct usb_host_endpoint *endpoint成員忽略了,下面就看這個結構體。

struct usb_host_endpoint {

struct usb_endpoint_descriptor desc;

struct list_head urb_list;

void *hcpriv;

struct ep_device *ep_dev; /* For sysfs info */

unsigned char *extra; /* Extra descriptors */

int extralen;

};

按照我們做事的原則:避重就輕。先不分析usb_interface_descriptor結構體成員,咱們先分析其他簡單的。

urb_list表示端點要處理的urb隊列。urb是什么?urb可是usb通信的主角,它包含了執行urb傳輸所需要的所有信息,若要進行usb通信,就得創建一個urb,並且為它賦好值(專業點就是初始化),交給咱們的usb core,它會找到合適的host controller,從而進行具體的數據傳輸。設備中的每個端點都可以處理一個urb隊列,可以理解為urb是內核里對usb傳輸數據的封裝(或者抽象)。基於urb特殊性,會有專題來分析它。

hcpriv,這是提供給HCD(host controller driver)用的。比如等時端點會在里邊兒放一個ehci_iso_stream,什么意思?鄭板橋告訴我們要難得糊塗,以后會明白的。

ep_dev,這個字段是供sysfs用的。好奇的話可以去/sys下看一看

[root@localhost ep_00]# pwd

/sys/bus/usb/devices/usb1/ep_00

[root@localhost ep_00]# ls

bEndpointAddress bmAttributes direction subsystem wMaxPacketSize

bInterval dev interval type

bLength device power uevent

[root@localhost ep_00]#

ep_00端點目錄下的這些文件從哪兒來的?就是在usb_create_ep_files函數里使用ep_dev創建的。

extra和 extralen,有關一些額外擴展的描述符的,和struct usb_host_interface里差不多,只是這里的是針對端點的,如果你請求從設備里獲得描述符信息,它們會跟在標准的端點描述符后面返回給你。

再回頭看看desc的結構體struct usb_endpoint_descriptor定義

/* USB_DT_ENDPOINT: Endpoint descriptor */

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

這個結構與spec Table 9.13是一一對應的,0號端點仍然保持着它特殊的地位,它沒有自己的端點描述符。

bLength,描述符的字節長度。數一下,前邊兒有7個字節,后邊兒又多了兩個字節__u8 bRefresh; __u8 bSynchAddress;那是針對音頻設備擴展的,不用管它

bDescriptorType,描述符類型,這里對於端點就是USB_DT_ENDPOINT,0x05,緊接在usb_endpoint_descriptor結構體定義后面。還記得對於接口描述符類型是什么嗎?對,值為USB_DT_INTERFACE,也就是0x04。

bEndpointAddress,這個字段描述的信息挺多的,比如這個端點是輸入端點還是輸出端點,這個端點的地址,以及這個端點的端點號。它的bits 0~3表示的就是端點號,你使用0x0f和它相與就可以得到端點號。不過,開發內核的同志想的都很周到,定義好了一個掩碼USB_ENDPOINT_NUMBER_MASK,它的值就是0x0f,當然,這是為了讓咱們更容易去讀他們的代碼,也為了以后的擴展。另外,它的bit 8表示方向,輸入還是輸出,同樣有掩碼USB_ENDPOINT_DIR_MASK,值為0x80,將它和bEndpointAddress相與,並結合USB_DIR_IN和USB_DIR_OUT作判斷就可以得到端點的方向。使用下面兩個定義值表示端點傳輸方向:

#define USB_DIR_OUT 0 /* to device */

#define USB_DIR_IN 0x80 /* to host */

bmAttributes,屬性,總共8位,其中bit1和bit0 共同稱為Transfer Type,即傳輸類型, 00 表示控制,01 表示等時,10 表示批量,11 表示中斷。前面的端點號還有端點方向都有配對兒的掩碼,這里當然也有,就在struct usb_endpoint_descriptor定義的下面。

/*

* USB types, the second of three bRequestType fields

*/

#define USB_TYPE_MASK (0x03 << 5)

#define USB_TYPE_STANDARD (0x00 << 5)

#define USB_TYPE_CLASS (0x01 << 5)

#define USB_TYPE_VENDOR (0x02 << 5)

#define USB_TYPE_RESERVED (0x03 << 5)

wMaxPacketSize,端點一次可以處理的最大字節數。如果你發送的數據量大於端點的這個值,也會分成多次一次一次來傳輸。友情提醒一下,這個字段還是有點門道的,對不同的傳輸類型也有不同的要求,以后可以再說。

bInterval, USB是輪詢式的總線,這個值表達了端點一種美好的期待,希望主機輪詢自己的時間間隔,但實際上批准不批准是host的事。不同的傳輸類型bInterval也有不同的意義,以后碰到各個實際的傳輸類型也可以再說。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM