usb裝置的probe全過程

來源:互聯網
上載者:User

本文將詳細講述2.6.22下的一個USB裝置插上linux系統的PC後是如何一步一步調到我們的usb裝置驅動的probe函數的, 我們知道我們的USB驅動的probe函數中的一個參數是interface結構, 因此一般來說,  一個USB裝置中的任何一個介面都應該有對應的一個驅動程式,當然也有例外(如cdc-acm).

我們知道USB裝置都是通過插入上層HUB的一個Port來連入系統並進而被系統發現的, 當USB裝置插入一個HUB時,該HUB的那個port的狀態就會改變, 從而系統就會知道這個改變, 此時會調用hub_port_connect_change()  /*driver/usb/core/hub.c*/

static void hub_connect_change(struct usb_hub *hub, int portl, u16 portstatus, u16 portchange)

{

….

usb_new_device(udev);

…

}

該函數建立一個usb_device的對象udev, 並初始化它,接著調用usb_new_device()來擷取這個usb裝置的各種描述符並為每個interface找到對用的driver.

int usb_new_device(struct usb_device *udev)

{

 ….

err = usb_get_configuration(udev);

 ….

device_add(&udev->dev);

}

該函數首先調用usb_get_configuration()來擷取裝置的各種描述符(裝置描述符,配置描述符等),接著調用device_add()來把這個USB裝置添加到USB系統中去, 也就是在這個過程中系統回去為這個裝置找到相應的驅動. 在2.6的早期的一些版本中在分析配置描述符後得到interface的同時把interface作為裝置來調用device_add()的

int device_add(struct device *dev)

{

….

if((error = bus_add_device(dev)))

…

bus_attach_device(dev);

…

}

這個函數是個通用的裝置管理函數,它會為每個裝置調用bus_add_device來把這個裝置添加到相應bus的裝置列表中去. 接著調用bus_attach_device()來匹配對應的驅動程式, 對於USB裝置來說第一次調用bus_attach_device()時的參數dev代表的是整個usb裝置(以後usb裝置中的interface也會作為裝置調用這個函數).

int bus_attach_device(struct device *dev)

{

…

ret = device_attach(dev);

…

}

這個函數就是用來為裝置找到相應的裝置驅動程式的(通過調用device_attach()實現).

int device_attach(struct device *dev)

{

…

ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);

…

}

該函數調用bus_for_each_drv()來從匯流排上登入的所有驅動中找出匹配的驅動程式.

int bus_for_each_drv(struct bus_type *bus,

struct device_driver *start,

void *data,

int (*fn)(struct device_driver *, void *))

{

       ….

while((drv = next_driver(&i)) && !error)

error = fn(drv, data);  //返回0將繼續搜尋,返回錯誤值將停止搜尋.

…

}

該函數遍曆bus上的所有驅動程式,並為每個驅動調用fn()來查看是否匹配. 這裡的fn就是__device_attach.

static int __device_attach(struct device_driver *drv, void *data)

{

struct device *dev = data;

return driver_probe_device(drv, dev);

}

int driver_probe_device(struct device *drv, struct device *dev)

{

   …

   if(drv->bus->match && !drv->bus_match(dev, drv))

   …

 

   ret = really_probe(dev, drv);

}

   對於usb驅動來說,我們通過usb_registe()r來註冊我們的驅動程式,這個函數會為我們的驅動程式對象(usb_driver)中的bus指定為usb_bus_type:

   Struct bus_type usb_bus_type = {

   …

   .match = usb_device_match,

   ….

}

因此對於usb驅動會首先調用usb_device_match().

static int usb_device_match(struct device *dev, struct device_driver *drv)

{

     if(is_usb_device(dev)) {  /*dev代表整個usb裝置*/

          ….

}

else   /*dev代表一個usb裝置interface*/

{

   …

   usb_match_id();

   …

   usb_match_dynamic_id();

   …

}

}

這個函數只是做一些粗略的匹配, 如果匹配成功則返回1,然後由really_probe來做進一步的匹配, 如果匹配失敗則返回0, 並且really_probe也不會在執行. 這個函數的調用保證了dev, drv要麼都是裝置層級的(即dev代表usb裝置,drv代表usb裝置驅動), 要麼都是介面層級的(即dev代表usb裝置的一個interface,drv代表usb介面驅動).

static int really_probe(struct device *dev, struct device_driver *drv)

{

   …

   dev->driver = drv;  //先賦值,以後的probe過程中會用到

   else if(drv->probe)

          ret = drv->probe(dev);

…

probe_failed:

   dev->drvier = NULL;  //probe失敗, 重設它

   …

}

對於usb來說這個函數的調用有2種分支, 1: dev,drv代表的是裝置層級的, 2 dev,drv代表的是介面層級的. 其他情況組合在usb_device_match中被過濾掉了,

分支1: dev,drv代表的是裝置層級:

此時的drv肯定是usb_generic_driver. 因為在當前的usb系統中只有這個driver是代表整個裝置的驅動,它是在usb_init中被註冊的, 而我們通常寫的usb驅動都是代表一個interface的.

struct usb_device_driver usb_generic_driver = {

   …

   .probe = generic_probe,

   …

}

因此,此時的drv->probe將調用generic_probe().

static int generic_probe(struct usb_device *udev)

{

   …

   c = choose_configuration(dev);

   if(c >= 0) {

   err = usb_set_configuration(udev, c);  //設定配置,並註冊interface.

   …

}

…

}

該函數為這個usb裝置選擇一個合適的配置,並註冊這個配置下面的interface.

int usb_set_configuration(struct usb_device *dev, int configuration)

{

   …

   for(I = 0; I < nintf; i++) {

   struct usb_interface *intf = cp->interface[i];

   …

   device_add(&intf->dev);

   …

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.