日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Linux那些事儿 之 戏说USB(32)驱动的生命线(四)

發(fā)布時間:2023/11/27 生活经验 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux那些事儿 之 戏说USB(32)驱动的生命线(四) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
設(shè)備自從有了Address,拿到了各種描述符,就在那兒看usb_generic_driver忙活了,不過還算沒白忙,設(shè)備總算是幸福的進入Configured了。
Address有點像你合幾代人之力辛辛苦苦才弄到的一套新房子,你還得想辦法去裝修它,Configured就像是已經(jīng)裝修好的,下面咱就看看usb_generic_driver又對設(shè)備做了些什么。
109行,nintf就是配置里接口的數(shù)目,那么這個for循環(huán)顯然就是在對配置里的每個接口做處理。
114行,這里要明白的是,cp里的兩個數(shù)組interface和intf_cache,一個是沒有初始化的,一個是已經(jīng)動過手術(shù)很飽滿的。正像前面提到的,這里需要為interface動手術(shù),拿intf_cache的內(nèi)容去充實它。
120行,獲得這個接口的0號設(shè)置。咱們已經(jīng)知道,因為某些廠商有特殊的癖好,導(dǎo)致了struct usb_host_config結(jié)構(gòu)里的數(shù)組interface并不一定是按照接口號的順序存儲的,你必須使用usb_ifnum_to_if 來獲得指定接口號對應(yīng)的struct usb_interface結(jié)構(gòu)體?,F(xiàn)在咱們需要再多知道一點,接口里的altsetting數(shù)組也不一定是按照設(shè)置編號來順序存儲的,你必須使用usb_altnum_to_altsetting()來獲得接口里的指定設(shè)置。它在drivers/usb/core/usb.c里定義()
struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf,unsigned int altnum)
{int i;for (i = 0; i < intf->num_altsetting; i++) {if (intf->altsetting[i].desc.bAlternateSetting == altnum)return &intf->altsetting[i];}return NULL;
}
這個函數(shù)依靠一個for循環(huán)來解決問題,就是輪詢接口里的每個設(shè)置,比較它們的編號與你指定的編號是不是一樣。原理簡單,操作也簡單,有點不簡單的是前面調(diào)用它的時候為什么指定編號0,也就是獲得0號設(shè)置。這還要歸咎于spec里說了這么一句,接口的默認(rèn)設(shè)置總是0號設(shè)置,所以這里的目的就是獲得接口的默認(rèn)設(shè)置,如果沒有拿到設(shè)置0,接下來就在128行拿altsetting數(shù)組里的第一項來充數(shù)。
132行,指定剛剛拿到的設(shè)置為當(dāng)前要使用的設(shè)置。
133行,前邊兒遇到過device和endpoint的disable函數(shù),這里遇到個interface的enable函數(shù),同樣在message.c里定義

這個函數(shù)同樣也是靠一個for循環(huán)來解決問題,輪詢前面獲得的那個接口設(shè)置使用到的每個端點,調(diào)用message.c里的usb_enable_endpoint()將它們統(tǒng)統(tǒng)enable。
void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,bool reset_ep)
{int epnum = usb_endpoint_num(&ep->desc);int is_out = usb_endpoint_dir_out(&ep->desc);int is_control = usb_endpoint_xfer_control(&ep->desc);if (reset_ep)usb_hcd_reset_endpoint(dev, ep);if (is_out || is_control)dev->ep_out[epnum] = ep;if (!is_out || is_control)dev->ep_in[epnum] = ep;ep->enabled = 1;
}
這個函數(shù)的前邊兒幾行沒什么好說的,分別獲得端點地址,端點號,還有是不是控制端點。稍微有那么點嚼頭兒的是后面的兩個if,它們分別根據(jù)端點的方向來初始化設(shè)備的ep_in和ep_out數(shù)組。
現(xiàn)在看看為什么兩個if語句里都出現(xiàn)有is_control??刂苽鬏斒褂玫氖莔essage管道,message管道必須對應(yīng)兩個相同號碼的端點,一個用來in,一個用來out。這里使用兩個if,而不是if-else組合,目的就是塞進去一個is_control,表示只要是控制端點,就將它的端點號對應(yīng)的IN和OUT兩個方向上的toggle位還有ep_int和ep_out都給初始化了。當(dāng)然,所謂的控制端點一般也就是指端點0。
endpoint的enable函數(shù)要比disable函數(shù)清爽的多,disable的時候還要深入到HCD的腹地去撤銷掛在它上面的各個urb,而enable的時候就是簡單設(shè)置一下toggle位還有那兩個數(shù)組就好了,要知道它的urb隊列urb_list是早在從設(shè)備那里獲取配置描述符并去解析那一大堆數(shù)據(jù)的時候就初始化好了的。enable之后,接口里的各個端點便都處于了欣欣向榮的可用狀態(tài),你就可以在驅(qū)動里向指定的端點提交urb了。當(dāng)然,到目前這個時候接口還仍然是接口,驅(qū)動(接口驅(qū)動)還仍然是驅(qū)動,它們中間還缺少那根著名的紅線。
然后看看跟在usb_enable_interface()后面的那幾行,接口所屬的總線類型仍然為usb_bus_type,設(shè)備類型變?yōu)閡sb_if_device_type,dma_mask被設(shè)置為你的設(shè)備的dma_mask,而你設(shè)備的dma_mask很早以前就被設(shè)置為了host controller的dma_mask。
142行,device_initialize在初始化設(shè)備struct usb_device結(jié)構(gòu)體的時候遇到過一次,這里初始化接口的時候又遇到了。
148行,for循環(huán)結(jié)束了,new_interfaces的歷史使命也就結(jié)束了。我想你應(yīng)該會明白的是,這里的kfree釋放的只是new_interfaces指針數(shù)組的內(nèi)存,而不包括它里面各個指針?biāo)赶虻膬?nèi)存,至于那些數(shù)據(jù),都已經(jīng)在前面被賦給配置里的interface數(shù)組了。
179行,獲得配置的字符串描述符,怎么獲得?先飄過去把剩下的說了再說它。
194行,這個for循環(huán)結(jié)束,usb_set_configuration()的三個階段也就算結(jié)束了,設(shè)備和大美女usb_generic_driver上上下下忙活了這么久也都很累了,接下來就該接口和接口驅(qū)動去忙活了。
這個for循環(huán)將前面那個for循環(huán)準(zhǔn)備好的每個接口送給設(shè)備模型,Linux設(shè)備模型會根據(jù)總線類型usb_bus_type將接口添加到usb總線的那條有名的設(shè)備鏈表里,然后去輪詢usb總線的另外一條有名的驅(qū)動鏈表,針對每個找到的驅(qū)動去調(diào)用usb總線的match函數(shù),也就是usb_device_match,去為接口尋找另一個匹配的半圓。你說這個時候設(shè)備和接口兩條路它應(yīng)該走哪條?它的類型已經(jīng)設(shè)置成usb_if_device_type了,設(shè)備那條路把門兒的根本就不會讓它進,所以它必須得去走接口那條路。

總結(jié)

以上是生活随笔為你收集整理的Linux那些事儿 之 戏说USB(32)驱动的生命线(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。