usb驅動開發8之配置描述符


前面分析了usb的四大描述符之端點描述符,接口描述符(每一個接口對應一個功能,與之配備相應驅動),下面是看配置描述符還是看設備描述符呢??我們知道,設備大於配置,配置大於接口,接口可以有多種設置。

我們還是按照從小到大的順序,繼續看配置結構體吧!

struct usb_host_config {

struct usb_config_descriptor desc;

char *string; /* iConfiguration string, if present */

/* the interfaces associated with this configuration,

* stored in no particular order */

struct usb_interface *interface[USB_MAXINTERFACES];

/* Interface information available even when this is not the

* active configuration */

struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];

unsigned char *extra; /* Extra descriptors */

int extralen;

};

和前面分析一下,我們先略過usb_config_descriptor結構體的分析,大餐總是喜歡最后吃。

string,這個字符串保存了配置描述符iConfiguration字段對應的字符串描述符信息。

interface[USB_MAXINTERFACES],配置所包含的接口。注釋里說的很明確,這個數組的順序未必是按照配置里接口號的順序,所以你要想得到某個接口號對應的struct usb_interface結構對象,就必須使用drivers/usb/usb.c里定義的usb_ifnum_to_if函數。

struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,

unsigned ifnum)

{

struct usb_host_config *config = dev->actconfig;

int i;

if (!config)

return NULL;

for (i = 0; i < config->desc.bNumInterfaces; i++)

if (config->interface[i]->altsetting[0]

.desc.bInterfaceNumber == ifnum)

return config->interface[i];

return NULL;

}

這個函數實現,就是用指定的接口號和當前配置的每一個接口可選設置0里的接口描述符的bInterfaceNumber字段做比較,相等了,那個接口就是你要尋找的。

如果你看了協議,可能會在9.6.5里看到,An interface descriptor is always returned as part of a configuration descriptor. Interface descriptors cannot be directly accessed with a GetDescriptor() or SetDescriptor() request…….請求配置描述符時,配置里的所有接口描述符是按照順序一個一個返回的。那為什么這里又明確說明,讓咱們不要期待它就會是接口號的順序那?其實很久很久以前這里並不是這么說地,它就說這個數組是按照0..desc.bNumInterfaces的順序,但同時又說需要通過usb_ifnum_to_if函數來獲得指定接口號的接口對象,為什么改?因為協議歸協議,廠商歸廠商,有些廠商就是有不遵守協議的癖好,它非要先返回接口1再返回接口0,你也沒轍,所以就不得不增加usb_ifnum_to_if函數。

intf_cache[USB_MAXINTERFACES],這是個struct usb_interface_cache對象的結構數組,usb_interface_cache就是usb接口的緩存。緩存些什么?看看include/linux/usb/usb.h里的定義。

struct usb_interface_cache {

unsigned num_altsetting; /* number of alternate settings */

struct kref ref; /* reference counter */

/* variable-length array of alternate settings for this interface,

* stored in no particular order */

struct usb_host_interface altsetting[0];

};

重點看一下成員altsetting[0],它是一個可變長數組,按需分配的那種,當對設備GET_DESCRIPTOR的時候,內核就根據返回的每個接口可選設置的數目(值num_altsetting)分配給intf_cache數組相應的空間。為什么要緩存這些東東?設備的配置會發生變化,為了在配置被取代之后仍然能夠獲取它的一些信息,就需要把一些信息放在intf_cache數組的struct usb_interface_cache對象里。那么誰會需要用到呢?你通過sysfs這個窗口只能看到設備當前配置的一些信息,即使是這個配置下面的接口,也只能看到接口正在使用的那個可選設置的信息,可是你希望能夠看到更多的,怎么辦?usbfs就是這個門,里面顯示有你的系統中所有usb設備的可選配置和端點信息,它就是利用intf_cache這個數組里緩存的東東實現的。

回到配置結構體usb_host_config 的剩下兩個成員extra和extralen,有關額外擴展的描述符的,和struct usb_host_interface里的差不多,只是這里的是針對配置的,如果你使用GET_DESCRIPTOR請求從設備里獲得配置描述符信息,它們會緊跟在標准的配置描述符后面返回給你。

還是老規矩,最后看一下usb_config_descriptor;

struct usb_config_descriptor {

__u8 bLength;

__u8 bDescriptorType;

__le16 wTotalLength;

__u8 bNumInterfaces;

__u8 bConfigurationValue;

__u8 iConfiguration;

__u8 bmAttributes;

__u8 bMaxPower;

} __attribute__ ((packed));

bLength,描述符的長度,值為#define USB_DT_CONFIG_SIZE 9

bDescriptorType,描述符的類型。還記得端點描述符和接口描述符類型是什么嗎??所以多想想就能記住了,記不住也沒關系,知道有這么個東東。這里為什么又要提一下?因為這里有一個轉折,配置描述符的值可以為USB_DT_CONFIG,0x02,也可以為#define USB_DT_OTHER_SPEED_CONFIG 0x07。這么說對不對?0x07描述符描述的是高速設備操作在低速或全速模式時的配置信息,和配置描述符的結構完全相同,區別只是描述符的類型不同,是只有名字不同的孿生兄弟。

wTotalLength,使用GET_DESCRIPTOR請求從設備里獲得配置描述符信息時,返回的數據長度,也就是說對包括配置描述符、接口描述符、端點描述符,class-或vendor-specific描述符在內的所有描述符算了個總帳。

bNumInterfaces,這個配置包含的接口數目。

bConfigurationValue,對於擁有多個配置的幸運設備來說,可以拿這個值為參數,使用SET_CONFIGURATION請求來改變正在被使用的 USB配置,bConfigurationValue就指明了將要激活哪個配置。咱們的設備雖然可以有多個配置,但同一時間卻也只能有一個配置被激活。SET_CONFIGURATION請求也是標准的設備請求之一,專門用來設置設備的配置。

iConfiguration,描述配置信息的字符串描述符的索引值。

bmAttributes,這個字段表征了配置的一些特點,比如bit 6為1表示self-powered,bit 5為1表示這個配置支持遠程喚醒。另外,它的bit 7必須為1,為什么?協議里就這么說的,我也不知道,這個世界上並不是什么事情都找得到原因的。ch9.h里有幾個相關的定義

/* from config descriptor bmAttributes */

#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */

#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */

#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */

#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */

bMaxPower,設備正常運轉時,從總線那里分得的最大電流值,以2mA為單位。設備可以使用這個字段向hub表明自己需要的的電流,但如果設備需求過於旺盛,請求的超出了hub所能給予的,hub就會直接拒絕,不會心軟。你去請求她給你多一點點愛,可她心系天下人,沒有多的分到你身上,於是怎么辦?拒絕你唄,不要說愛情是多么殘酷,這個世界就是很無奈。還記得struct usb_device結構里的bus_mA嗎?它就表示從總線上獲取到的當前值,也就是hub所能夠賦予給設備的值。


免責聲明!

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



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