Linux那些事儿 之 戏说USB(大结局)还是那个match
生活随笔
收集整理的這篇文章主要介紹了
Linux那些事儿 之 戏说USB(大结局)还是那个match
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
從上次在幾米的向左走向右走遇到usb總線的那個(gè)match函數(shù)usb_device_match()開(kāi)始到現(xiàn)在,遇到了設(shè)備,遇到了設(shè)備驅(qū)動(dòng),遇到了接口,也遇到了接口驅(qū)動(dòng),期間還多次遇到usb_device_match()。
每個(gè)設(shè)備也都有一條共同之路,與hub初戀,失身于usb_generic_driver,嫁給了接口驅(qū)動(dòng),被usb總線保養(yǎng)。設(shè)備沒(méi)有真正自由過(guò),剛開(kāi)始時(shí)在Default狀態(tài)動(dòng)彈不得,稍后步入Address,無(wú)論外頭風(fēng)光多好,都得與usb_generic_driver長(zhǎng)廂廝守,沒(méi)得選擇,終于達(dá)到了Configured,又必須為自己的接口殫精竭慮,以便usb_device_match()能夠?yàn)樗鼈冋乙粋€(gè)好人家。
不管怎么說(shuō),在這里我們會(huì)再次與usb_device_match()相遇,看看它怎么在接口和驅(qū)動(dòng)之間搭起那座橋。
當(dāng)時(shí)講到struct usb_driver結(jié)構(gòu)的時(shí)候并沒(méi)有詳細(xì)講它里面表示動(dòng)態(tài)id的那個(gè)結(jié)構(gòu)體struct usb_dynids,但是做人要厚道,不能太CCTV,所以現(xiàn)在補(bǔ)充一下,這個(gè)結(jié)構(gòu)的定義在include/linux/usb.h里
13行,你可能會(huì)問(wèn)為什么這里不詳細(xì)介紹一下struct usb_device_id結(jié)構(gòu),主要是《我是U盤里》已經(jīng)說(shuō)得非常之詳細(xì)和有趣了,俺這里實(shí)在沒(méi)必要耗費(fèi)時(shí)間和口舌去說(shuō)它,另一方面,它里面的那些元素都相當(dāng)?shù)谋┞逗椭卑?#xff0c;我相信依你的智商一眼就能明白個(gè)八九不離十。
那么這個(gè)for循環(huán)就是輪詢?cè)O(shè)備花名冊(cè)里的每個(gè)設(shè)備,如果符合了條件id->idVendor || id->bDeviceClass || id->bInterfaceClass || id->driver_info,就調(diào)用函數(shù)usb_match_one_id做深層次的匹配。本來(lái),在動(dòng)態(tài)id出現(xiàn)之前這個(gè)地方是沒(méi)有usb_match_one_id這么一個(gè)函數(shù)的,所有的匹配都在這個(gè)for循環(huán)里直接做了,但是動(dòng)態(tài)id出現(xiàn)之后,同時(shí)出現(xiàn)了前面提到的usb_match_dynamic_id函數(shù),要在動(dòng)態(tài)id鏈表里做同樣的匹配,這就要避免代碼重復(fù),于是就將那些重復(fù)的代碼提出來(lái),組成了usb_match_one_id函數(shù)。
for循環(huán)的條件里可能出現(xiàn)的一種情況是,id的其它字段都為空,只有driver_info字段有實(shí)實(shí)在在的內(nèi)容,這種情況下匹配是肯定成功的,不信的話等會(huì)兒你可以看usb_match_one_id(),這種驅(qū)動(dòng)對(duì)usb接口來(lái)說(shuō)是比較隨便的那種,不管啥接口都能和她對(duì)得上眼,為什么會(huì)出現(xiàn)這種情況?咱們已經(jīng)知道,匹配成功后,接著就會(huì)調(diào)用驅(qū)動(dòng)自己的probe函數(shù),驅(qū)動(dòng)在它里面還會(huì)對(duì)接口做進(jìn)一步的檢查,如果真出現(xiàn)了這里所說(shuō)的情況,意思也就是驅(qū)動(dòng)將所有的檢查接口,和接口培養(yǎng)感情的步驟都攬?jiān)谧约旱膒robe函數(shù)里了,它會(huì)在那個(gè)時(shí)候?qū)river_info的內(nèi)容取出來(lái),然后想怎么處理就怎么處理,本來(lái)么,id里邊兒的driver_info就是給驅(qū)動(dòng)保存數(shù)據(jù)用的。
還是看看usb_match_one_id()究竟是怎么匹配的吧,定義也在driver.c里
11行,獲得接口采用的設(shè)置,設(shè)置里可是有接口描述符的,要匹配接口和驅(qū)動(dòng),接口描述符里的信息是必不可少的。
12行,從接口的struct usb_interface結(jié)構(gòu)體獲得usb設(shè)備的struct usb_device結(jié)構(gòu)體,interface_to_usbdev的定義在include/linux/usb.h里
14行,這里又冒出來(lái)個(gè)usb_match_device(),接口和驅(qū)動(dòng)之間的感情還真不是那么好培養(yǎng)的,一層一層的。不過(guò)既然存在就是有來(lái)頭的,它也不會(huì)毫無(wú)根據(jù)的出現(xiàn),這里雖說(shuō)是在接口和接口驅(qū)動(dòng)之間匹配,但是接口的parent也是必須要符合條件的,這即合情也合理啊,你好不容易鼓足了勇氣向一個(gè)走在大街上一見(jiàn)鐘情的mm表白,你覺(jué)得mm的第一反應(yīng)是什么?依照行規(guī),很可能就是:你爸是干嗎的?是大款么?是當(dāng)官的么?你要說(shuō)不,那就別等第二反應(yīng)了。所以說(shuō)接口要想得到驅(qū)動(dòng)的芳心,自己的parent符合驅(qū)動(dòng)的條件也是很重要的,usb_match_device()就是專門來(lái)匹配接口parent的。同樣在driver.c里定義
驅(qū)動(dòng)的花名冊(cè)里每個(gè)設(shè)備都對(duì)應(yīng)了一個(gè)struct usb_device_id結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體里有很多字段,都是驅(qū)動(dòng)設(shè)定好的條條框框,接口必須完全滿足里面的條件才能夠被驅(qū)動(dòng)所接受,所以說(shuō)匹配的過(guò)程就是檢查接口是否滿足這些條件的過(guò)程。
當(dāng)然你可以每次都按照id的內(nèi)容一個(gè)一個(gè)的比較下去,但是經(jīng)常來(lái)說(shuō),一個(gè)驅(qū)動(dòng)往往只是想設(shè)定其中的某幾項(xiàng),并不要求struct usb_device_id結(jié)構(gòu)里的所有那些條件都要滿足。match_flags就是為了方便各種各樣的需求而生的,驅(qū)動(dòng)可以將自己的條件組合起來(lái),match_flags的每一位對(duì)應(yīng)一個(gè)條件,驅(qū)動(dòng)care哪個(gè)條件了,就將那一位置1,否則就置0。當(dāng)然,內(nèi)核里對(duì)每個(gè)驅(qū)動(dòng)可能會(huì)care的條件都定義成了宏,供驅(qū)動(dòng)去組合,它們都在include/linux/mod_devicetable.h里定義
這個(gè)core的故事,從match開(kāi)始,到match結(jié)束,它雖說(shuō)不會(huì)遍及core的邊邊角角所有部分,但應(yīng)該也有那么十之七八。在match的兩端是設(shè)備和設(shè)備的驅(qū)動(dòng),是接口和接口的驅(qū)動(dòng),這個(gè)故事里遇到的人,遇到的事,早就安排在那里了,由不得我們?nèi)ミx擇。在人生的路口上,早已經(jīng)安排了那些人,那些事,決定你向左走還是向右走。既然如此,那就隨便走好了,想那么多干什么呢?
每個(gè)設(shè)備也都有一條共同之路,與hub初戀,失身于usb_generic_driver,嫁給了接口驅(qū)動(dòng),被usb總線保養(yǎng)。設(shè)備沒(méi)有真正自由過(guò),剛開(kāi)始時(shí)在Default狀態(tài)動(dòng)彈不得,稍后步入Address,無(wú)論外頭風(fēng)光多好,都得與usb_generic_driver長(zhǎng)廂廝守,沒(méi)得選擇,終于達(dá)到了Configured,又必須為自己的接口殫精竭慮,以便usb_device_match()能夠?yàn)樗鼈冋乙粋€(gè)好人家。
不管怎么說(shuō),在這里我們會(huì)再次與usb_device_match()相遇,看看它怎么在接口和驅(qū)動(dòng)之間搭起那座橋。
static int usb_device_match(struct device *dev, struct device_driver *drv)
{/* devices and interfaces are handled separately */if (is_usb_device(dev)) {/* interface drivers never match devices */if (!is_usb_device_driver(drv))return 0;/* TODO: Add real matching code */return 1;} else if (is_usb_interface(dev)) {struct usb_interface *intf;struct usb_driver *usb_drv;const struct usb_device_id *id;/* device drivers never match interfaces */if (is_usb_device_driver(drv))return 0;intf = to_usb_interface(dev);usb_drv = to_usb_driver(drv);id = usb_match_id(intf, usb_drv->id_table);if (id)return 1;id = usb_match_dynamic_id(intf, usb_drv);if (id)return 1;}return 0;
}設(shè)備那條路已經(jīng)走過(guò)了,現(xiàn)在走走13行接口那條路。19行,接口驅(qū)動(dòng)的for_devices在usb_register _driver()里被初始化為0,所以這個(gè)把門兒的會(huì)痛痛快快的放行,繼續(xù)往下走,22行,遇到一對(duì)兒似曾相識(shí)的宏to_usb_interface和to_usb_driver,之所以說(shuō)似曾相識(shí),是因?yàn)樵缦纫呀?jīng)遇到過(guò)一對(duì)兒to_usb_device和to_usb_device_driver。這兩對(duì)兒一對(duì)兒用于接口和接口驅(qū)動(dòng),一對(duì)兒用于設(shè)備和設(shè)備驅(qū)動(dòng),意思都很直白,還是看看include/linux/usb.h里的定義
#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
#define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)再往下走,就是兩個(gè)函數(shù)usb_match_id和usb_match_dynamic_id,它們都是用來(lái)完成實(shí)際的匹配工作的,只不過(guò)前一個(gè)是從驅(qū)動(dòng)的id_table里找,看接口是不是被驅(qū)動(dòng)所支持,后一個(gè)是從驅(qū)動(dòng)的動(dòng)態(tài)id鏈表dynids里找。驅(qū)動(dòng)的id表分id_table和dynids兩種。顯然25~31這幾行的意思就是將id_table放在一個(gè)比較高的優(yōu)先級(jí)的位置,從它里面找不到接口了才再?gòu)膭?dòng)態(tài)id鏈表里找。
當(dāng)時(shí)講到struct usb_driver結(jié)構(gòu)的時(shí)候并沒(méi)有詳細(xì)講它里面表示動(dòng)態(tài)id的那個(gè)結(jié)構(gòu)體struct usb_dynids,但是做人要厚道,不能太CCTV,所以現(xiàn)在補(bǔ)充一下,這個(gè)結(jié)構(gòu)的定義在include/linux/usb.h里
struct usb_dynids {spinlock_t lock;struct list_head list;
};它只有兩個(gè)字段,一把鎖,一個(gè)鏈表,都是在usb_register _driver()里面初始化的,這個(gè)list是驅(qū)動(dòng)動(dòng)態(tài)id鏈表的頭兒,它里面的每個(gè)節(jié)點(diǎn)是用另外一個(gè)結(jié)構(gòu)struct usb_dynid來(lái)表示
struct usb_dynid {struct list_head node;struct usb_device_id id;
};這里面就出現(xiàn)了一個(gè)struct usb_device_id結(jié)構(gòu)體,也就是設(shè)備的id,每次添加一個(gè)動(dòng)態(tài)id,就會(huì)向驅(qū)動(dòng)的動(dòng)態(tài)id鏈表里添加一個(gè)struct usb_dynid結(jié)構(gòu)體。你現(xiàn)在應(yīng)該可以想像到usb_match_id和usb_match_dynamic_id這兩個(gè)函數(shù)除了查找的地方不一樣,其它應(yīng)該是沒(méi)什么差別的。所以接下來(lái)咱們只深入探討一下usb_match_id函數(shù),至于usb_match_dynamic_id(),如果你實(shí)在無(wú)聊暫時(shí)找不到人生目標(biāo)也可以去看看。它們都在driver.c里定義
const struct usb_device_id *usb_match_id(struct usb_interface *interface,const struct usb_device_id *id)
{/* proc_connectinfo in devio.c may call us with id == NULL. */if (id == NULL)return NULL;/* It is important to check that id->driver_info is nonzero,since an entry that is all zeroes except for a nonzeroid->driver_info is the way to create an entry thatindicates that the driver want to examine everydevice and interface. */for (; id->idVendor || id->idProduct || id->bDeviceClass ||id->bInterfaceClass || id->driver_info; id++) {if (usb_match_one_id(interface, id))return id;}return NULL;
}5行,參數(shù)id指向的是驅(qū)動(dòng)的那個(gè)設(shè)備花名冊(cè),即id_table,如果它為空,那肯定就是不可能會(huì)匹配成功了。
13行,你可能會(huì)問(wèn)為什么這里不詳細(xì)介紹一下struct usb_device_id結(jié)構(gòu),主要是《我是U盤里》已經(jīng)說(shuō)得非常之詳細(xì)和有趣了,俺這里實(shí)在沒(méi)必要耗費(fèi)時(shí)間和口舌去說(shuō)它,另一方面,它里面的那些元素都相當(dāng)?shù)谋┞逗椭卑?#xff0c;我相信依你的智商一眼就能明白個(gè)八九不離十。
那么這個(gè)for循環(huán)就是輪詢?cè)O(shè)備花名冊(cè)里的每個(gè)設(shè)備,如果符合了條件id->idVendor || id->bDeviceClass || id->bInterfaceClass || id->driver_info,就調(diào)用函數(shù)usb_match_one_id做深層次的匹配。本來(lái),在動(dòng)態(tài)id出現(xiàn)之前這個(gè)地方是沒(méi)有usb_match_one_id這么一個(gè)函數(shù)的,所有的匹配都在這個(gè)for循環(huán)里直接做了,但是動(dòng)態(tài)id出現(xiàn)之后,同時(shí)出現(xiàn)了前面提到的usb_match_dynamic_id函數(shù),要在動(dòng)態(tài)id鏈表里做同樣的匹配,這就要避免代碼重復(fù),于是就將那些重復(fù)的代碼提出來(lái),組成了usb_match_one_id函數(shù)。
for循環(huán)的條件里可能出現(xiàn)的一種情況是,id的其它字段都為空,只有driver_info字段有實(shí)實(shí)在在的內(nèi)容,這種情況下匹配是肯定成功的,不信的話等會(huì)兒你可以看usb_match_one_id(),這種驅(qū)動(dòng)對(duì)usb接口來(lái)說(shuō)是比較隨便的那種,不管啥接口都能和她對(duì)得上眼,為什么會(huì)出現(xiàn)這種情況?咱們已經(jīng)知道,匹配成功后,接著就會(huì)調(diào)用驅(qū)動(dòng)自己的probe函數(shù),驅(qū)動(dòng)在它里面還會(huì)對(duì)接口做進(jìn)一步的檢查,如果真出現(xiàn)了這里所說(shuō)的情況,意思也就是驅(qū)動(dòng)將所有的檢查接口,和接口培養(yǎng)感情的步驟都攬?jiān)谧约旱膒robe函數(shù)里了,它會(huì)在那個(gè)時(shí)候?qū)river_info的內(nèi)容取出來(lái),然后想怎么處理就怎么處理,本來(lái)么,id里邊兒的driver_info就是給驅(qū)動(dòng)保存數(shù)據(jù)用的。
還是看看usb_match_one_id()究竟是怎么匹配的吧,定義也在driver.c里
int usb_match_one_id(struct usb_interface *interface,const struct usb_device_id *id)
{struct usb_host_interface *intf;struct usb_device *dev;/* proc_connectinfo in devio.c may call us with id == NULL. */if (id == NULL)return 0;intf = interface->cur_altsetting;dev = interface_to_usbdev(interface);if (!usb_match_device(dev, id))return 0;return usb_match_one_id_intf(dev, intf, id);
}8行,這個(gè)id指向的就是驅(qū)動(dòng)id_table里的某一項(xiàng)了。
11行,獲得接口采用的設(shè)置,設(shè)置里可是有接口描述符的,要匹配接口和驅(qū)動(dòng),接口描述符里的信息是必不可少的。
12行,從接口的struct usb_interface結(jié)構(gòu)體獲得usb設(shè)備的struct usb_device結(jié)構(gòu)體,interface_to_usbdev的定義在include/linux/usb.h里
#define to_usb_device(d) container_of(d, struct usb_device, dev)static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf)
{return to_usb_device(intf->dev.parent);
}usb設(shè)備和它里面的接口是怎么關(guān)聯(lián)起來(lái)的呢?就是上面的那個(gè)parent,接口的parent早在usb_generic_driver的generic_probe函數(shù)向設(shè)備模型提交設(shè)備里的每個(gè)接口的時(shí)候就被初始化好了,而且指定為接口所在的那個(gè)usb設(shè)備。這么一回顧,interface_to_usbdev的意思就很明顯了。
14行,這里又冒出來(lái)個(gè)usb_match_device(),接口和驅(qū)動(dòng)之間的感情還真不是那么好培養(yǎng)的,一層一層的。不過(guò)既然存在就是有來(lái)頭的,它也不會(huì)毫無(wú)根據(jù)的出現(xiàn),這里雖說(shuō)是在接口和接口驅(qū)動(dòng)之間匹配,但是接口的parent也是必須要符合條件的,這即合情也合理啊,你好不容易鼓足了勇氣向一個(gè)走在大街上一見(jiàn)鐘情的mm表白,你覺(jué)得mm的第一反應(yīng)是什么?依照行規(guī),很可能就是:你爸是干嗎的?是大款么?是當(dāng)官的么?你要說(shuō)不,那就別等第二反應(yīng)了。所以說(shuō)接口要想得到驅(qū)動(dòng)的芳心,自己的parent符合驅(qū)動(dòng)的條件也是很重要的,usb_match_device()就是專門來(lái)匹配接口parent的。同樣在driver.c里定義
int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
{if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&id->idVendor != le16_to_cpu(dev->descriptor.idVendor))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&id->idProduct != le16_to_cpu(dev->descriptor.idProduct))return 0;/* No need to test id->bcdDevice_lo != 0, since 0 is nevergreater than any unsigned number. */if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&(id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&(id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&(id->bDeviceClass != dev->descriptor.bDeviceClass))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&(id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))return 0;return 1;
}這個(gè)函數(shù)采用了排比的修辭手法,美觀的同時(shí)也增加了可讀性。這一個(gè)個(gè)的if條件里都有一部分是將id 的match_flags和一個(gè)宏相與,所以弄明白match_flags的意思就很關(guān)鍵。罷了罷了,本來(lái)說(shuō)不再浪費(fèi)口舌在id里的那些字段上了,不過(guò)為了減少你驀然回首的次數(shù),這里再說(shuō)一下這個(gè)match_flags。
驅(qū)動(dòng)的花名冊(cè)里每個(gè)設(shè)備都對(duì)應(yīng)了一個(gè)struct usb_device_id結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體里有很多字段,都是驅(qū)動(dòng)設(shè)定好的條條框框,接口必須完全滿足里面的條件才能夠被驅(qū)動(dòng)所接受,所以說(shuō)匹配的過(guò)程就是檢查接口是否滿足這些條件的過(guò)程。
當(dāng)然你可以每次都按照id的內(nèi)容一個(gè)一個(gè)的比較下去,但是經(jīng)常來(lái)說(shuō),一個(gè)驅(qū)動(dòng)往往只是想設(shè)定其中的某幾項(xiàng),并不要求struct usb_device_id結(jié)構(gòu)里的所有那些條件都要滿足。match_flags就是為了方便各種各樣的需求而生的,驅(qū)動(dòng)可以將自己的條件組合起來(lái),match_flags的每一位對(duì)應(yīng)一個(gè)條件,驅(qū)動(dòng)care哪個(gè)條件了,就將那一位置1,否則就置0。當(dāng)然,內(nèi)核里對(duì)每個(gè)驅(qū)動(dòng)可能會(huì)care的條件都定義成了宏,供驅(qū)動(dòng)去組合,它們都在include/linux/mod_devicetable.h里定義
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200你用自己的火眼金睛很容易的就能看出來(lái)這些數(shù)字分別表示了一個(gè)u16整數(shù),也就是match_flags中的某一位。驅(qū)動(dòng)比較在意哪個(gè)方面,就可以將match_flags里對(duì)應(yīng)的位置1,在和接口匹配的時(shí)候自動(dòng)就會(huì)去比較驅(qū)動(dòng)設(shè)置的那個(gè)條件是否滿足。那整個(gè)usb_match_device()函數(shù)就沒(méi)什么說(shuō)的了,就是從match_flags那里得到驅(qū)動(dòng)都在意哪些條件,然后將設(shè)備保存在自己描述符里的自身信息與id里的相應(yīng)條件進(jìn)行比較,有一項(xiàng)比較不成功就說(shuō)明匹配失敗,如果一項(xiàng)符合了就接著看下一項(xiàng),接口parent都滿足條件了,就返回1,表示匹配成功了。
還是回到usb_match_one_id()繼續(xù)往下看,假設(shè)你運(yùn)氣還不錯(cuò),parent滿足了驅(qū)動(dòng)的所有條件,那就調(diào)用函數(shù)usb_match_one_id_intf
int usb_match_one_id_intf(struct usb_device *dev,struct usb_host_interface *intf,const struct usb_device_id *id)
{/* The interface class, subclass, protocol and number should never be* checked for a match if the device class is Vendor Specific,* unless the match record specifies the Vendor ID. */if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |USB_DEVICE_ID_MATCH_INT_SUBCLASS |USB_DEVICE_ID_MATCH_INT_PROTOCOL |USB_DEVICE_ID_MATCH_INT_NUMBER)))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&(id->bInterfaceClass != intf->desc.bInterfaceClass))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))return 0;if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&(id->bInterfaceNumber != intf->desc.bInterfaceNumber))return 0;return 1;
}8行。這行的意思是,如果接口的parent,usb設(shè)備是屬于廠商定義的class,也就是不屬于storage等等標(biāo)準(zhǔn)的class,就不再檢查接口的class,subclass和protocol了,除非match_flags里指定了條件USB_DEVICE_ID_MATCH_VENDOR。16行之后的三個(gè)if也不用多說(shuō),前面是檢查接口parent的,這里就是檢查接口本身是不是滿足驅(qū)動(dòng)的條件的。
當(dāng)上面各個(gè)函數(shù)進(jìn)行的所有檢查都完全匹配時(shí),usb總線的match函數(shù)usb_device_match就會(huì)返回1表示匹配成功,之后接著就會(huì)去調(diào)用驅(qū)動(dòng)的probe函數(shù)做更深入的處理,什么樣的處理?這是每個(gè)驅(qū)動(dòng)才知道的事情,反正到此為止,core的任務(wù)是已經(jīng)圓滿完成了,咱們的故事也就該結(jié)束了。
這個(gè)core的故事,從match開(kāi)始,到match結(jié)束,它雖說(shuō)不會(huì)遍及core的邊邊角角所有部分,但應(yīng)該也有那么十之七八。在match的兩端是設(shè)備和設(shè)備的驅(qū)動(dòng),是接口和接口的驅(qū)動(dòng),這個(gè)故事里遇到的人,遇到的事,早就安排在那里了,由不得我們?nèi)ミx擇。在人生的路口上,早已經(jīng)安排了那些人,那些事,決定你向左走還是向右走。既然如此,那就隨便走好了,想那么多干什么呢?
總結(jié)
以上是生活随笔為你收集整理的Linux那些事儿 之 戏说USB(大结局)还是那个match的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 长期吸烟却又喜欢喝茶的人,后来怎么样了?
- 下一篇: 《深入理解Android:Wi-Fi,N