Usb设备驱动3:root hub守护进程2
Hub正常工作后,主控制器就會定時詢問hub是否有中斷產生,當hub端口上有一個設備插入或拔除,hub就向主控制器發送urb請求,即把hub端口的變化狀況告訴主控制器,這是通過urb請求來完成的,主機在處理完了這個urb后,就會調用urb所提供的完成函數,來調用hub的中斷函數,即hub_irq。
?
Hub_irq是hub的中斷處理函數,處理程序首先判斷主控制器處理urb的結果狀態,如果狀態是OK的,則繼續處理。
1.掃描hub的所有端口,確定是哪個端口發生了變化。端口是用位圖來表示的,一個long型數據可以表示32個hub端口(每位表示一個端口),有多少個端口,就用多少位表示,而8位用一個字節表示,因此,最后的使用的位都是轉化成了字節的的,比如一個hub有18個端口,則需要用18位來表示,但是一個字節只有8位,因此,需要用3個字節才能表示完。
2.調用kick_khubd函數,把當前hub加入到hub驅動隊列hub_event_list中,然后喚醒hub守護進程wake_up(khubd_wait),開始解析hub發生的事情了。
3.hub_thread被喚醒后,將得到執行,hub_events也將得到執行
4.hub_events是分析hub事件的主函數,hub分析的相關內容都在這里執行。這個函數是一個大的死循環。
5.Hub_events處理流程
5.1先從hub_event_list中取出此次處理的hub節點,并把hub節點從原來的隊列中刪除,使之獨立于任何鏈表,因為我們處理完事件后,hub結構體就要刪除,因此不能保留在任何隊列中。hub可以是根hub,也可以是接到根hub上的子hub,只是,不論是什么hub,都使用同樣的守護進程了。
5.2.通過宏轉換,找到hub節點對以的hub結構體,進而得到hub結構體對應的usb結構體,以及hub接口結構體usb_intfdev,得到這三個結構體是這個函數處理的關鍵。
5.3.鎖住當前的hub樹,因為hub只有一個守護進程,所有的hub都使用這個守護進程,而守護進程每次只能服務一個hub,因此,只要有一個hub在使用這個守護進程,就需要鎖住,以防止其他hub的使用。
5.4.按位檢索hub每個端口是否正在執行reset或resume操作,注意是從1開始檢索的,位0表示整個hub的情況,如果當前端口正在執行reset或resume操作,則跳過對這端口的檢查,否則,測試這個端口是否有狀態改變,如果沒有狀態改變,也跳過此端口。
5.5.如果端口有狀態改變,則判斷端口是發生了什么狀態的改變,有以下的狀態
#define USB_PORT_STAT_C_CONNECTION??? 0x0001
#define USB_PORT_STAT_C_ENABLE????????????? 0x0002
#define USB_PORT_STAT_C_SUSPEND?????????? 0x0004
#define USB_PORT_STAT_C_OVERCURRENT? 0x0008
#define USB_PORT_STAT_C_RESET???????? 0x0010
?
5.6.確定有狀態改變后,就開始對有改變的端口的狀態進行進一步的處理,此時的處理,就要根據剛剛分析得到的各種狀態,分開進行處理。
5.7.首先要確定端口是否還有設備,如果有,則要把設備刪除,原因是,hub端口上有兩種狀態發生轉換,1為端口從無設備到有設備的狀態,此時設備還在認證中,因此端口不應該有設備,2是端口從有到無設備的轉換,此時檢測到還有設備,表示設備還沒有被移除,因此,需要直接把設備disable掉。
5.8.把設備disable掉的動作,需要進行反彈的檢查,一個設備至少需要100ms的時間,才能表示此狀態是穩定的,因此,等100ms后再判斷端口是否是disable了,就可以判斷了
5.9.判斷設備狀態為無設備插入時,需要檢測是否是端口電源被disable掉了,如果是,則需要開啟端口電源,如果電源是開啟的,則表示設備有誤,結束判斷,返回上層。
5.10.經過上面的判斷,能執行到這里,表示端口是有設備插入了,此時,就需要要分析端口的狀態了,對端口的分析,可以嘗試4次,主要是為了排除各種干擾。
5.11.為即將到來的設備分配空間(struct usb_device),對這個即將到來的設備的設備結構體設置狀態為連接狀態,速度為未知,電源為hub分配給的,這些都是默認狀態。
5.12.準備為設備分配地址,此時是子系統軟件的操作,就是查看總線上128位位圖中,哪位為0的,就選擇出來,查找的方式是從上次記錄的下一位開始查找,如果超過128了還沒有找到,就接著從0開始查找,即如果頻繁的拔插usb設備,即使只有一個設備,則每次插入,設備地址都會增加1,直到到達128后,從0接著開始,此時的設備地址,還不是設備的真實地址,因為還沒有發送給設備。
5.13.復位設備,通過對設備的復位來達到使能設備的目的,此時,如果復位成功,則設備的狀態將成為USB_STATE_DEFAULT狀態,主控制器就可以通過控制端口獲得設備的描述符符,通過對設備描述符的解析,可以得到設備的速度,從而可以根據速度猜測控制端口的空間大小。
5.14.得到控制端點的大小后,就開始準備往控制端點發送urb請求,獲得設備的真正的設備描述符。
5.15.獲得設備描述符時分兩種模式,新模式和舊模式,每種模式最多試兩次,每次可以最多讀三回端口。對于新模式,需要分配一個64字節的空間,用于接收從設備返回的設備描述符。通過獲得的設備描述符來判斷端口的類別是不是確實是設備類別的,如果是,則只需要讀取一次端口,就可以判斷是設備描述符了,把描述符中記錄的端口的空間大小給剛剛申請的空間的對應字節賦值了。
5.16.復位設備,準備給設備設置剛剛系統選擇好,但還沒有設置的那個地址,這個設置可以最多嘗試設置兩次,之間要停留200ms。
5.17.一旦設置成功,就要把設備的狀態轉變為地址狀態(USB_STATE_ADDRESS),同時把控制端口0給disable掉,這樣,這個端口上的urb鏈表都被清除了。
5.18.如果新的模式能走到這里,就表明新模式成功的獲得了設備描述符了,因此舊模式就不要試了,而舊模式是分兩次來獲得設備的描述符的,第一次是發送要求獲得8字節的urb請求,經過這個請求得到的數據,就可以知道設備的端口大小到達是多大,再按照獲得的端口大小,獲得端口的真實的設備描述符。
5.19.接下來,就要開始把這個設備加入設備模式中去了(usb_new_device)。
5.20.首先,要獲得設備的配置描述符,注意,只有設備才有配置,接口,端口都是沒有配置的,接口有設置。設備有多少個配置,就要分配多少個配置的空間,用于接收,而有多少個配置,已經在設備描述符中獲得了,這時只需要從設備中讀取就可以。
5.21.設置配置描述符指針,同樣有多少個配置多少個這樣的指針
5.22.一個配置描述符有9個字節,此時需要分配出這個空間,用于接收從設備中讀回的配置描述符。
5.23.循環讀取設備中的配置描述符,并把讀回的數據放在設備結構體中的相應位置,之后,從配置中獲得接口數,接口設置,以及接口下面的端點,通通都是在這里分析的,好長的幾個函數。
5.24.接著,把設備添加到設備模型中去,這部分工作由設備模型完成,主要包括完成了設備鏈表的添加,和查找設備驅動程序的,此處是設備的驅動,usb系統只有一個設備驅動,而且是系統已經做好的,當設備里的接口被添加時,我們的編寫的驅動,就是在這里被調用,用來判斷驅動是否符合設備的了。
5.25.掃描設備的所有配置,選擇最優的當前配置,再用選中的這個配置去設置設備。
5.26.到此,設備的配置,設置,什么都配置妥當了,系統就可以正常的使用設備了。?
總結
以上是生活随笔為你收集整理的Usb设备驱动3:root hub守护进程2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ 3164 Command
- 下一篇: adoquery.parameters流