歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux USB subsystem --- USBFS driver registration

目的:對USB作深入學習,在此留下筆記。歡迎討論。

[Linux 3.2] [driver/usb/core/devio.c]

定義:usbfs_driver

  1. struct usb_driver usbfs_driver = {  
  2.     .name =     "usbfs",  
  3.     .probe =    driver_probe,  
  4.     .disconnect =   driver_disconnect,  
  5.     .suspend =  driver_suspend,  
  6.     .resume =   driver_resume,  
  7. };  

[Linux 3.2] [include/linux/usb.h]

函數:usb_register();

  1. /* use a define to avoid include chaining to get THIS_MODULE & friends */  
  2. #define usb_register(driver) \   
  3.     usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)  

[Linux 3.2] [driver/usb/core/driver.c]

函數:usb_register_driver();

  1. /** 
  2.  * usb_register_driver - register a USB interface driver 
  3.  * @new_driver: USB operations for the interface driver 
  4.  * @owner: module owner of this driver. 
  5.  * @mod_name: module name string 
  6.  * 
  7.  * Registers a USB interface driver with the USB core.  The list of 
  8.  * unattached interfaces will be rescanned whenever a new driver is 
  9.  * added, allowing the new driver to attach to any recognized interfaces. 
  10.  * Returns a negative error code on failure and 0 on success. 
  11.  * 
  12.  * NOTE: if you want your driver to use the USB major number, you must call 
  13.  * usb_register_dev() to enable that functionality.  This function no longer 
  14.  * takes care of that. 
  15.  */  
  16. int usb_register_driver(struct usb_driver *new_driver, struct module *owner,  
  17.             const char *mod_name)  
  18. {  
  19.     int retval = 0;  
  20.   
  21.     if (usb_disabled())  
  22.         return -ENODEV;  
  23.   
  24.     new_driver->drvwrap.for_devices = 0;  
  25.     new_driver->drvwrap.driver.name = (char *) new_driver->name;  
  26.     new_driver->drvwrap.driver.bus = &usb_bus_type;  
  27.     new_driver->drvwrap.driver.probe = usb_probe_interface;  
  28.     new_driver->drvwrap.driver.remove = usb_unbind_interface;  
  29.     new_driver->drvwrap.driver.owner = owner;  
  30.     new_driver->drvwrap.driver.mod_name = mod_name;  
  31.     spin_lock_init(&new_driver->dynids.lock);  
  32.     INIT_LIST_HEAD(&new_driver->dynids.list);  
  33.   
  34.     retval = driver_register(&new_driver->drvwrap.driver);  
  35.     if (retval)  
  36.         goto out;  
  37.   
  38.     usbfs_update_special();  
  39.   
  40.     retval = usb_create_newid_file(new_driver);  
  41.     if (retval)  
  42.         goto out_newid;  
  43.   
  44.     retval = usb_create_removeid_file(new_driver);  
  45.     if (retval)  
  46.         goto out_removeid;  
  47.   
  48.     pr_info("%s: registered new interface driver %s\n",  
  49.             usbcore_name, new_driver->name);  
  50.   
  51. out:  
  52.     return retval;  
  53.   
  54. out_removeid:  
  55.     usb_remove_newid_file(new_driver);  
  56. out_newid:  
  57.     driver_unregister(&new_driver->drvwrap.driver);  
  58.   
  59.     printk(KERN_ERR "%s: error %d registering interface "  
  60.             "   driver %s\n",  
  61.             usbcore_name, retval, new_driver->name);  
  62.     goto out;  
  63. }  

此函數主要功能實現是通過driver_register實現。後面會詳細分析。

其余功能如下:

1. usbfs_update_special() ==> 跟usb文件系統相關,暫時不分析。

2. usb_create_newid_file() ==> 創建newid屬性文件,在/sys/bus/usb/drivers/usbfs/下面可以看到此文件。

3. usb_create_removeid_file() ==> 創建removeid屬性文件,在/sys/bus/usb/drivers/usbfs/下面可以看到此文件。

4. 輸出信息:usbcore: registered new interface driver usbfs

問題:newid與removeid屬性文件的作用是什麼?

回答:等待解答。

現在分析driver_register功能:

1. 首先判斷,些驅動所屬bus的subsys_private結構有沒有初始化。如果沒有,報bug信息。

2. 判斷需要注冊的driver和driver所屬的bus是否都有probe, remove, shutdown函數。如有,打印kernel warning信息。

3. 判斷此driver已經在driver所屬的bus上面注冊過了。如果注冊過了,打印錯誤信息,並返回。

4. 調用bus_add_driver來注冊driver。

5. 調用driver_add_groups來添加組屬性。

6. 返回。

最後對bus_add_driver進行分析。

  1. /** 
  2.  * bus_add_driver - Add a driver to the bus. 
  3.  * @drv: driver. 
  4.  */  
  5. int bus_add_driver(struct device_driver *drv)  
  6. {  
  7.     struct bus_type *bus;  
  8.     struct driver_private *priv;  
  9.     int error = 0;  
  10.   
  11.     bus = bus_get(drv->bus);  
  12.     if (!bus)  
  13.         return -EINVAL;  
  14.   
  15.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  16.   
  17.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  18.     if (!priv) {  
  19.         error = -ENOMEM;  
  20.         goto out_put_bus;  
  21.     }  
  22.     klist_init(&priv->klist_devices, NULL, NULL);  
  23.     priv->driver = drv;  
  24.     drv->p = priv;  
  25.     priv->kobj.kset = bus->p->drivers_kset;  
  26.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  27.                      "%s", drv->name);  
  28.     if (error)  
  29.         goto out_unregister;  
  30.   
  31.     if (drv->bus->p->drivers_autoprobe) {  
  32.         error = driver_attach(drv);  
  33.         if (error)  
  34.             goto out_unregister;  
  35.     }  
  36.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  37.     module_add_driver(drv->owner, drv);  
  38.   
  39.     error = driver_create_file(drv, &driver_attr_uevent);  
  40.     if (error) {  
  41.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  42.             __func__, drv->name);  
  43.     }  
  44.     error = driver_add_attrs(bus, drv);  
  45.     if (error) {  
  46.         /* How the hell do we get out of this pickle? Give up */  
  47.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  48.             __func__, drv->name);  
  49.     }  
  50.   
  51.     if (!drv->suppress_bind_attrs) {  
  52.         error = add_bind_files(drv);  
  53.         if (error) {  
  54.             /* Ditto */  
  55.             printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  56.                 __func__, drv->name);  
  57.         }  
  58.     }  
  59.   
  60.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  61.     return 0;  
  62.   
  63. out_unregister:  
  64.     kobject_put(&priv->kobj);  
  65.     kfree(drv->p);  
  66.     drv->p = NULL;  
  67. out_put_bus:  
  68.     bus_put(bus);  
  69.     return error;  
  70. }  

其功能是向bus中添加一個driver。

1. bus_get() ==> bus的計數加1;

2. kzalloc,分配driver_private內存空間。

3. 初始化此driver的klist_devices鏈表。

4. kobject_init_and_add() ==> 在/sys/bus/usb/drivers/下面創建usbfs文件夾。

5. 如果總線支持drivers_autoprobe,調用driver_attach。(USB 總線支持)

6. driver_create_file ==> 在/sys/bus/usb/drivers/usbfs下面創建uevent屬性文件。

7. driver_add_attrs() ==> 將總線的屬性也加到/sys/bus/usb/drivers/usbfs

8. add_bind_files() ==> 在/sys/bus/usb/drivers/usbfs創建bind和unbind屬性文件。

9. kobject_uevent() ==> 發送一個KOBJ_ADD的事件。

在/sys/bus/usb/drivers/usbfs下面的文件:

bind       module     new_id     remove_id  uevent     unbind

Copyright © Linux教程網 All Rights Reserved