二、usb子系统初始化

来源:互联网 发布:352空气净化器 知乎 编辑:程序博客网 时间:2024/06/07 16:48

在/drivers/usb/core/Usb.c中,subsys_initcall(usb_init)声明了usb子系统入口函数usb_init

  1. static int __init usb_init(void)  
  2. {  
  3.     int retval;  
  4.     if (nousb) {  
  5.         pr_info("%s: USB support disabled\n", usbcore_name);  
  6.         return 0;  
  7.     }  
  8.     retval = usb_debugfs_init();    //1.usb debugfs初始化   
  9.     if (retval)  
  10.         goto out;  
  11.     retval = bus_register(&usb_bus_type);   //2.usb总线注册   
  12.     if (retval)  
  13.         goto bus_register_failed;  
  14.     retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); //3.usb总线通知链注册   
  15.     if (retval)  
  16.         goto bus_notifier_failed;  
  17.     retval = usb_major_init();  //4.注册usb主控器字符设备   
  18.     if (retval)  
  19.         goto major_init_failed;  
  20.     retval = usb_register(&usbfs_driver);   //5.注册usbfs驱动   
  21.     if (retval)  
  22.         goto driver_register_failed;  
  23.     retval = usb_devio_init();  //6.usb设备字符设备初始化   
  24.     if (retval)  
  25.         goto usb_devio_init_failed;  
  26.     retval = usbfs_init();  //7.usbfs初始化   
  27.     if (retval)  
  28.         goto fs_init_failed;  
  29.     retval = usb_hub_init();    //8.usb hub初始化   
  30.     if (retval)  
  31.         goto hub_init_failed;  
  32.     retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);  //9.usb注册同样设备驱动   
  33.     if (!retval)  
  34.         goto out;  
  35.     usb_hub_cleanup();  
  36. hub_init_failed:  
  37.     usbfs_cleanup();  
  38. fs_init_failed:  
  39.     usb_devio_cleanup();  
  40. usb_devio_init_failed:  
  41.     usb_deregister(&usbfs_driver);  
  42. driver_register_failed:  
  43.     usb_major_cleanup();  
  44. major_init_failed:  
  45.     bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);  
  46. bus_notifier_failed:  
  47.     bus_unregister(&usb_bus_type);  
  48. bus_register_failed:  
  49.     usb_debugfs_cleanup();  
  50. out:  
  51.     return retval;  
  52. }   

1.usb_debugfs_init --usb debugfs初始化

  1. static int usb_debugfs_init(void)  
  2. {  
  3.     usb_debug_root = debugfs_create_dir("usb", NULL);   //创建"$(debugfs)/usb"   
  4.     if (!usb_debug_root)  
  5.         return -ENOENT;       
  6.     usb_debug_devices = debugfs_create_file("devices", 0444,usb_debug_root, NULL,&usbfs_devices_fops);  
  7.     //创建"$(debugfs)/usb/device",捆绑usbfs_devices_fops结构体   
  8.     if (!usb_debug_devices) {   //若创建失败   
  9.         debugfs_remove(usb_debug_root); //则必须把“$(debugfs)/usb”也删除掉   
  10.         usb_debug_root = NULL;  
  11.         return -ENOENT;  
  12.     }  
  13.     return 0;  
  14. }  

要使用debugfs下面的usb功能,需要先挂着debugfs(mount -t debugfs none $(debugfs) ),具体初始化了啥调试接口,看下usbfs_devices_fops操作函数集
2.usb总线的注册

  1. struct bus_type usb_bus_type = {  
  2.     .name = "usb",  //总线名   
  3.     .match =    usb_device_match,   //匹配方法   
  4.     .uevent =   usb_uevent, //事件处理   
  5. #ifdef CONFIG_USB_SUSPEND   
  6.     .pm =   &usb_bus_pm_ops,    //电源管理   
  7. #endif   
  8. };  

这里总线的match方法是usb设备与usb驱动匹配的函数.

3.注册usb总线通知链

  1. int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)  
  2. {  
  3.     return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);  
  4. }  

当总线添加删除设备的时候会调用usb_bus_nb指定的notifier_cal方法,既usb_bus_notify

  1. static int usb_bus_notify(struct notifier_block *nb, unsigned long action,void *data)  
  2. {  
  3.     struct device *dev = data;  
  4.     switch (action) {  
  5.     case BUS_NOTIFY_ADD_DEVICE: //添加设备   
  6.         if (dev->type == &usb_device_type)   //usb设备   
  7.             (void) usb_create_sysfs_dev_files(to_usb_device(dev));  
  8.         else if (dev->type == &usb_if_device_type)   //usb接口   
  9.             (void) usb_create_sysfs_intf_files(to_usb_interface(dev));  
  10.         break;  
  11.     case BUS_NOTIFY_DEL_DEVICE: //删除设备   
  12.         if (dev->type == &usb_device_type)   //usb设备   
  13.             usb_remove_sysfs_dev_files(to_usb_device(dev));  
  14.         else if (dev->type == &usb_if_device_type)   //usb接口   
  15.             usb_remove_sysfs_intf_files(to_usb_interface(dev));  
  16.         break;  
  17.     }  
  18.     return 0;  
  19. }  

4.初始化usb主控器字符设备,USB_MAJOR=180

  1. int usb_major_init(void)  
  2. {  
  3.     int error;  
  4.     error = register_chrdev(USB_MAJOR, "usb", &usb_fops);   //注册usb控制器字符设备,捆绑usb_fops   
  5.     if (error)  
  6.         printk(KERN_ERR "Unable to get major %d for usb devices\n",USB_MAJOR);  
  7.     return error;  
  8. }  

捆绑usb_fops

  1. static const struct file_operations usb_fops = {  
  2.     .owner =    THIS_MODULE,  
  3.     .open = usb_open,  
  4.     .llseek =   noop_llseek,  
  5. };  

5.注册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. };  

6.usb_devio_init     USB_DEVICE_DEV=189

  1. int __init usb_devio_init(void)  
  2. {  
  3.     int retval;  
  4.     retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,"usb_device");   //分配设备号  
  5.     if (retval) {  
  6.         printk(KERN_ERR "Unable to register minors for usb_device\n");  
  7.         goto out;  
  8.     }  
  9.     cdev_init(&usb_device_cdev, &usbdev_file_operations);   //字符设备初始化   
  10.     retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);    //添加字符设备   
  11.     if (retval) {  
  12.         printk(KERN_ERR "Unable to get usb_device major %d\n",USB_DEVICE_MAJOR);  
  13.         goto error_cdev;  
  14.     }  
  15. #ifdef CONFIG_USB_DEVICE_CLASS   
  16.     usb_classdev_class = class_create(THIS_MODULE, "usb_device");   //创建"/sys/class/usb_device"  
  17.     if (IS_ERR(usb_classdev_class)) {  
  18.         printk(KERN_ERR "Unable to register usb_device class\n");  
  19.         retval = PTR_ERR(usb_classdev_class);  
  20.         cdev_del(&usb_device_cdev);   
  21.         usb_classdev_class = NULL;  
  22.         goto out;  
  23.     }  
  24.     usb_classdev_class->dev_kobj = NULL;  
  25. #endif   
  26.     usb_register_notify(&usbdev_nb);    //注册设备通知链   
  27. out:  
  28.     return retval;  
  29. error_cdev:  
  30.     unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);  
  31.     goto out;  
  32. }  

usb注册的通知链

  1. void usb_register_notify(struct notifier_block *nb)  
  2. {  
  3.     blocking_notifier_chain_register(&usb_notifier_list, nb);  
  4. }  

usb通知链表头为usb_notifier_list

在/drivers/usb/core/Notify.c文件中,有四个函数()对usb_notifier_list中发送通知,这四个函数如下:

usb_notify_add_device    //有设备添加
usb_notify_remove_device    //有设备移除
usb_notify_add_bus    //总线添加
usb_notify_remove_bus    //总线移除

当这些事件发生后会调用usbdev_nb指定的notifier_cal方法,既usbdev_notify

  1. static int usbdev_notify(struct notifier_block *self,unsigned long action, void *dev)  
  2. {  
  3.     switch (action) {  
  4.     case USB_DEVICE_ADD:    //设备添加   
  5.         if (usb_classdev_add(dev))  
  6.             return NOTIFY_BAD;  
  7.         break;  
  8.     case USB_DEVICE_REMOVE: //设备删除   
  9.         usb_classdev_remove(dev);  
  10.         usbdev_remove(dev);  
  11.         break;  
  12.     }  
  13.     return NOTIFY_OK;  
  14. }  

7.usbfs初始化

  1. int __init usbfs_init(void)  
  2. {  
  3.     int retval;  
  4.     retval = register_filesystem(&usb_fs_type); //注册文件系统   
  5.     if (retval)  
  6.         return retval;  
  7.     usb_register_notify(&usbfs_nb); //注册通知链   
  8.     usbdir = proc_mkdir("bus/usb", NULL);   //创建"/proc/bus/usb"   
  9.     return 0;  
  10. }  

通知链回调函数

  1. static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)  
  2. {  
  3.     switch (action) {  
  4.     case USB_DEVICE_ADD:    //设备添加   
  5.         usbfs_add_device(dev);  
  6.         break;  
  7.     case USB_DEVICE_REMOVE: //设备移除   
  8.         usbfs_remove_device(dev);  
  9.         break;  
  10.     case USB_BUS_ADD:   //总线添加   
  11.         usbfs_add_bus(dev);  
  12.         break;  
  13.     case USB_BUS_REMOVE:    //总线移除   
  14.         usbfs_remove_bus(dev);  
  15.     }  
  16.     usbfs_update_special();  
  17.     usbfs_conn_disc_event();  
  18.     return NOTIFY_OK;  
  19. }  

8.usb hub初始化

  1. int usb_hub_init(void)  
  2. {  
  3.     if (usb_register(&hub_driver) < 0) { //注册usb hub设备驱动   
  4.         printk(KERN_ERR "%s: can't register hub driver\n",usbcore_name);  
  5.         return -1;  
  6.     }  
  7.     khubd_task = kthread_run(hub_thread, NULL, "khubd");    //创建守护进程   
  8.     if (!IS_ERR(khubd_task))  
  9.         return 0;  
  10.     usb_deregister(&hub_driver);  
  11.     printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);  
  12.     return -1;  
  13. }  

hub也是usb设备,所以需要注册器设备驱动,创建hub_thread守护进程
捆绑的hub usb设备驱动

  1. static struct usb_driver hub_driver = {  
  2.     .name = "hub",  
  3.     .probe =    hub_probe,  //hub连接上   
  4.     .disconnect = hub_disconnect,   //hub断开   
  5.     .suspend = hub_suspend, //hub挂起   
  6.     .resume =   hub_resume, //hub唤醒   
  7.     .reset_resume = hub_reset_resume,   //hub复位唤醒   
  8.     .pre_reset = hub_pre_reset,   
  9.     .post_reset = hub_post_reset,  
  10.     .unlocked_ioctl = hub_ioctl,  
  11.     .id_table = hub_id_table,   //hub设备驱动 id表   
  12.     .supports_autosuspend = 1,  
  13. };  

hub_thread守护进程

  1. static int hub_thread(void *__unused)  
  2. {  
  3.     set_freezable();    //设置可冻结   
  4.     do {  
  5.         hub_events();   //hub事件处理函数   
  6.         wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop());  //进入睡眠   
  7.     } while (!kthread_should_stop() || !list_empty(&hub_event_list));  
  8.     pr_debug("%s: khubd exiting\n", usbcore_name);  
  9.     return 0;  
  10. }  

这里while循环是在hub_event_list不为空时候循环执行

当hub_events执行完,会执行wait_event_freezable进入睡眠,其他函数调用wake_up(&khubd_wait)唤醒队列
hub_events函数

  1. static void hub_events(void)  
  2. {  
  3.     struct list_head *tmp;  
  4.     struct usb_device *hdev;  
  5.     struct usb_interface *intf;  
  6.     struct usb_hub *hub;  
  7.     struct device *hub_dev;  
  8.     u16 hubstatus;  
  9.     u16 hubchange;  
  10.     u16 portstatus;  
  11.     u16 portchange;  
  12.     int i, ret;  
  13.     int connect_change;  
  14.   
  15.     while (1) {  
  16.         spin_lock_irq(&hub_event_lock);  
  17.         //第一次执行假设usb主控器还没注册   
  18.         if (list_empty(&hub_event_list)) {  //usb事件链表为空   
  19.             spin_unlock_irq(&hub_event_lock);  
  20.             break;  //跳出循环   
  21.         }  
  22.         tmp = hub_event_list.next;    
  23.         list_del_init(tmp);  
  24.         hub = list_entry(tmp, struct usb_hub, event_list);    
  25.         kref_get(&hub->kref);  
  26.         spin_unlock_irq(&hub_event_lock);  
  27.         hdev = hub->hdev;      
  28.         hub_dev = hub->intfdev;    
  29.         intf = to_usb_interface(hub_dev);  
  30.         usb_lock_device(hdev);  
  31.         if (unlikely(hub->disconnected))  
  32.             goto loop_disconnected;  
  33.         if (hdev->state == USB_STATE_NOTATTACHED) {  
  34.             hub->error = -ENODEV;  
  35.             hub_quiesce(hub, HUB_DISCONNECT);  
  36.             goto loop;  
  37.         }  
  38.         ret = usb_autopm_get_interface(intf);  
  39.         if (ret) {  
  40.             dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);  
  41.             goto loop;  
  42.         }  
  43.         if (hub->quiescing)  
  44.             goto loop_autopm;  
  45.         if (hub->error) {  
  46.             dev_dbg (hub_dev, "resetting for error %d\n",hub->error);  
  47.             ret = usb_reset_device(hdev);     
  48.             if (ret) {  
  49.                 dev_dbg (hub_dev,"error resetting hub: %d\n", ret);  
  50.                 goto loop_autopm;  
  51.             }  
  52.             hub->nerrors = 0;  
  53.             hub->error = 0;  
  54.         }  
  55.         for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {  
  56.             if (test_bit(i, hub->busy_bits))  
  57.                 continue;  
  58.             connect_change = test_bit(i, hub->change_bits);  
  59.             if (!test_and_clear_bit(i, hub->event_bits) &&!connect_change)  
  60.                 continue;  
  61.             ret = hub_port_status(hub, i,&portstatus, &portchange);  
  62.             if (ret < 0)  
  63.                 continue;  
  64.             if (portchange & USB_PORT_STAT_C_CONNECTION) {  
  65.                 clear_port_feature(hdev, i,USB_PORT_FEAT_C_CONNECTION);  
  66.                 connect_change = 1;  
  67.             }  
  68.             if (portchange & USB_PORT_STAT_C_ENABLE) {  
  69.                 if (!connect_change)  
  70.                     dev_dbg (hub_dev,"port %d enable change,status %08x\n",i, portstatus);  
  71.                 clear_port_feature(hdev, i,USB_PORT_FEAT_C_ENABLE);  
  72.                 if (!(portstatus & USB_PORT_STAT_ENABLE)&& !connect_change&& hdev->children[i-1]) {  
  73.                     dev_err (hub_dev,"port %i disabled by hub (EMI?),re-enabling...\n",i);  
  74.                     connect_change = 1;  
  75.                 }  
  76.             }  
  77.             if (portchange & USB_PORT_STAT_C_SUSPEND) {  
  78.                 struct usb_device *udev;  
  79.                 clear_port_feature(hdev, i,USB_PORT_FEAT_C_SUSPEND);  
  80.                 udev = hdev->children[i-1];  
  81.                 if (udev) {  
  82.                     msleep(10);  
  83.                     usb_lock_device(udev);  
  84.                     ret = usb_remote_wakeup(hdev->children[i-1]);  
  85.                     usb_unlock_device(udev);  
  86.                     if (ret < 0)  
  87.                         connect_change = 1;  
  88.                 } else {  
  89.                     ret = -ENODEV;  
  90.                     hub_port_disable(hub, i, 1);  
  91.                 }  
  92.                 dev_dbg (hub_dev,"resume on port %d, status %d\n",i, ret);  
  93.             }  
  94.               
  95.             if (portchange & USB_PORT_STAT_C_OVERCURRENT) {  
  96.                 dev_err (hub_dev,"over-current change on port %d\n",i);  
  97.                 clear_port_feature(hdev, i,USB_PORT_FEAT_C_OVER_CURRENT);  
  98.                 hub_power_on(hub, true);  
  99.             }  
  100.             if (portchange & USB_PORT_STAT_C_RESET) {  
  101.                 dev_dbg (hub_dev,"reset change on port %d\n",i);  
  102.                 clear_port_feature(hdev, i,USB_PORT_FEAT_C_RESET);  
  103.             }  
  104.   
  105.             if (connect_change)  
  106.                 hub_port_connect_change(hub, i,portstatus, portchange);  
  107.         }  
  108.         if (test_and_clear_bit(0, hub->event_bits) == 0)  
  109.             ;             
  110.         else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)  
  111.             dev_err (hub_dev, "get_hub_status failed\n");  
  112.         else {  
  113.             if (hubchange & HUB_CHANGE_LOCAL_POWER) {  
  114.                 dev_dbg (hub_dev, "power change\n");  
  115.                 clear_hub_feature(hdev, C_HUB_LOCAL_POWER);  
  116.                 if (hubstatus & HUB_STATUS_LOCAL_POWER)  
  117.                     hub->limited_power = 1;  
  118.                 else  
  119.                     hub->limited_power = 0;  
  120.             }  
  121.             if (hubchange & HUB_CHANGE_OVERCURRENT) {  
  122.                 dev_dbg (hub_dev, "overcurrent change\n");  
  123.                 msleep(500);  
  124.                 clear_hub_feature(hdev, C_HUB_OVER_CURRENT);  
  125.                             hub_power_on(hub, true);  
  126.             }  
  127.         }  
  128.  loop_autopm:  
  129.         usb_autopm_put_interface_no_suspend(intf);  
  130.  loop:  
  131.         usb_autopm_put_interface(intf);  
  132.  loop_disconnected:  
  133.         usb_unlock_device(hdev);  
  134.         kref_put(&hub->kref, hub_release);  
  135.         }  
  136. }  

9.usb注册通用设备驱动

  1. int usb_register_device_driver(struct usb_device_driver *new_udriver,struct module *owner)  
  2. {  
  3.     int retval = 0;  
  4.     if (usb_disabled())  
  5.         return -ENODEV;  
  6.     new_udriver->drvwrap.for_devices = 1;    //usb设备   
  7.     new_udriver->drvwrap.driver.name = (char *) new_udriver->name;    //设备名   
  8.     new_udriver->drvwrap.driver.bus = &usb_bus_type; //总线类型   
  9.     new_udriver->drvwrap.driver.probe = usb_probe_device;    //probe方法   
  10.     new_udriver->drvwrap.driver.remove = usb_unbind_device;  //remove方法   
  11.     new_udriver->drvwrap.driver.owner = owner;   //模块所有者   
  12.     retval = driver_register(&new_udriver->drvwrap.driver);  //注册设备驱动   
  13.     if (!retval) {  
  14.         pr_info("%s: registered new device driver %s\n",usbcore_name, new_udriver->name);  
  15.         usbfs_update_special();  
  16.     } else {  
  17.         printk(KERN_ERR "%s: error %d registering device driver %s\n",usbcore_name, retval, new_udriver->name);  
  18.     }  
  19.     return retval;  
  20. }  

usb_device_driver结构体是usb_driver的简化版本,这里注册的是usb设备(非接口)驱动

usb总线的match方法对usb设备和usb接口做了区分处理,针对usb设备,直接match的,(分析match时候再细化)

然后调用usb设备驱动的probe方法

  1. static int usb_probe_device(struct device *dev)  
  2. {  
  3.     struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);  
  4.     struct usb_device *udev = to_usb_device(dev);  
  5.     int error = 0;  
  6.     dev_dbg(dev, "%s\n", __func__);  
  7.     if (!udriver->supports_autosuspend)  //条件成立   
  8.         error = usb_autoresume_device(udev);  
  9.     if (!error)  
  10.         error = udriver->probe(udev);    //调用usb_device_driver的probe方法   
  11.     return error;  
  12. }  

接着调用usb_generic_driver的probe方法

  1. struct usb_device_driver usb_generic_driver = {  
  2.     .name = "usb",  
  3.     .probe = generic_probe,  
  4.     .disconnect = generic_disconnect,  
  5. #ifdef  CONFIG_PM   
  6.     .suspend = generic_suspend,  
  7.     .resume = generic_resume,  
  8. #endif   
  9.     .supports_autosuspend = 1,  
  10. };  

所以generic_probe函数会接着被调用

  1. static int generic_probe(struct usb_device *udev)  
  2. {  
  3.     int err, c;  
  4.     if (usb_device_is_owned(udev))  
  5.         ;  
  6.     else if (udev->authorized == 0)  //明显不执行   
  7.         dev_err(&udev->dev, "Device is not authorized for usage\n");  
  8.     else {  //   
  9.         c = usb_choose_configuration(udev); //选择一个配置   
  10.         if (c >= 0) {  
  11.             err = usb_set_configuration(udev, c);   //设置一个配置   
  12.             if (err) {  
  13.                 dev_err(&udev->dev, "can't set config #%d, error %d\n",c, err);  
  14.             }  
  15.         }  
  16.     }  
  17.     /* USB device state == configured ... usable */  
  18.     usb_notify_add_device(udev);    //发送设备添加通知   
  19.     return 0;  
  20. }  
0 0
原创粉丝点击