3.特別的愛給特別的Root Hub

3.特別的愛給特別的Root Hub

不懂Hub是怎麼工作的就等於不知道USB設備驅動是怎麼工作的。這句話一點沒錯,因爲USB設備的初始化都是Hub這邊發起的,通常我們寫USB設備驅動程序都是在已經得到了一個struct usb_interface指針的情況下開始probe工作。可是我要問你,你的struct usb_interface從哪來的?老實說,要想知道從USB設備插入USB口的那一刻開始,這個世界發生了什麼,你必須知道Hub是怎麼工作的,Linux中Hub驅動程序是怎麼工作的。

要說USB Hub,那得從Root Hub說起。什麼是Root Hub?不管你的計算機裏連了多少個USB設備,它們最終是有根的。所有的USB設備最終都是連接到了一個叫做Root Hub的設備上,或者說所有的根源都是從這裏開始的。

Root Hub上可以連接別的設備,可以連接U盤,可以連接USB鼠標,同樣也可以連接另一個Hub。所謂Hub,就是用來級聯。但是普通的Hub,它一頭接上級Hub,另一頭可以有多個口,多個口就可以連多個設備,也可以只有一個口。而Root Hub呢?它比較特殊,它當然也是一種USB設備,但是它屬於一人之下萬人之上的角色,它只屬於主機控制器,換而言之,通常做芯片的人會把主機控制器和Root Hub集成在一起。特別是PC主機上,通常你就只能看到接口,看不到Root Hub,因爲它在主機控制器裏,正如圖2.3.1所示。

當然,我們應該更加準確地評價主機和Root Hub的關係。

別扯遠了,繼續回來,既然Root Hub享有如此特殊的地位,那麼很顯然,整個USB子系統得特別對待它,一開始就會要初始化Hub。所以我們從USB子系統的初始化代碼開始看起,也就是usb_init函數,來自drivers/usb/core/usb.c:

 
圖2.3.1  USB拓撲結構

  1. 863 static int __init usb_init(void)  
  2. 864 {  
  3.         ⋯⋯  
  4. 890     if (retval)  
  5. 891         goto fs_init_failed;  
  6. 892     retval = usb_hub_init();  
  7.         ⋯⋯  
  8. 916 }  

在衆多名叫*init*的函數之中,是有一個屬於Hub的,它在這裏初始化,換而言之,隨着USB Core的初始化,Hub也就開始了它的初始化之路,usb_hub_init()函數得到調用,這個函數來自drivers/usb/core/hub.c:
  1. 2854 int usb_hub_init(void)  
  2. 2855 {  
  3. 2856        if (usb_register(&hub_driver) < 0) {  
  4. 2857        printk(KERN_ERR "%s: can't register hub driver\n",  
  5. 2858                         usbcore_name);  
  6. 2859        return -1;  
  7. 2860    }  
  8. 2861  
  9. 2862    khubd_task = kthread_run(hub_thread, NULL, "khubd");  
  10. 2863        if (!IS_ERR(khubd_task))  
  11. 2864        return 0;  
  12. 2865  
  13. 2866        /* Fall through if kernel_thread failed */  
  14. 2867    usb_deregister(&hub_driver);  
  15. 2868    printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);  
  16. 2869  
  17. 2870    return -1;  
  18. 2871 }  

一路走來的兄弟們不會對這樣一段代碼陌生,是不是有一種似曾相識的感覺?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章