免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2003 | 回复: 3
打印 上一主题 下一主题

[硬件及驱动] USB模块的疑惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-11 21:22 |只看该作者 |倒序浏览
我看 USB 模块, 有一个地方, 有点疑惑. 请诸位帮忙解答下.

<drivers/usb/storage/usb.c 中间定义了 usb_storage_driver, 声明如下:
  1. static struct usb_driver usb_storage_driver = {
  2.         .name =                "usb-storage",
  3.         .probe =        storage_probe,
  4.         .disconnect =        usb_stor_disconnect,
  5.         .suspend =        usb_stor_suspend,
  6.         .resume =        usb_stor_resume,
  7.         .reset_resume =        usb_stor_reset_resume,
  8.         .pre_reset =        usb_stor_pre_reset,
  9.         .post_reset =        usb_stor_post_reset,
  10.         .id_table =        usb_storage_usb_ids,
  11.         .supports_autosuspend = 1,
  12.         .soft_unbind =        1,
  13. };
复制代码
而其中 storage_probe 函数的定义形式如下:
  1. static int storage_probe(struct usb_interface *intf,
  2.                          const struct usb_device_id *id)
复制代码
<drivers/usb/core/hub.c> 中有一个函数调用过程如下
  1. hub_thread() -> hub_events() -> hub_port_connect_change() ->usb_new_device() -> device_add()
复制代码
函数 usb_new_device 传递给 device_add 函数的参数是
  1. err = device_add(&udev->dev);
复制代码
其中 udev 是 usb_device 类型.

在 device_add 函数中会去匹配 usb bus 上的 driver. 如果匹配上了, 就会调用 driver 的 probe 函数.
调用路径为:
  1. device_add() -> bus_probe_device() -> device_attach() -> __device_attach() -> driver_probe_device() -> really_probe()
复制代码
其中 really_probe 函数定义如下:
  1. static int really_probe(struct device *dev, struct device_driver *drv)
  2. {
  3.         int ret = 0;

  4.         atomic_inc(&probe_count);
  5.         pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
  6.                  drv->bus->name, __func__, drv->name, dev_name(dev));
  7.         WARN_ON(!list_empty(&dev->devres_head));

  8.         dev->driver = drv;
  9.         if (driver_sysfs_add(dev)) {
  10.                 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
  11.                         __func__, dev_name(dev));
  12.                 goto probe_failed;
  13.         }

  14.         if (dev->bus->probe) {
  15.                 ret = dev->bus->probe(dev);
  16.                 if (ret)
  17.                         goto probe_failed;
  18.         } else if (drv->probe) {
  19.                 ret = drv->probe(dev);
  20.                 if (ret)
  21.                         goto probe_failed;
  22.         }

  23.         driver_bound(dev);
  24.         ret = 1;
  25.         pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
  26.                  drv->bus->name, __func__, dev_name(dev), drv->name);
  27.         goto done;

  28. probe_failed:
  29.         devres_release_all(dev);
  30.         driver_sysfs_remove(dev);
  31.         dev->driver = NULL;

  32.         if (ret != -ENODEV && ret != -ENXIO) {
  33.                 /* driver matched but the probe failed */
  34.                 printk(KERN_WARNING
  35.                        "%s: probe of %s failed with error %d\n",
  36.                        drv->name, dev_name(dev), ret);
  37.         }
  38.         /*
  39.          * Ignore errors returned by ->probe so that the next driver can try
  40.          * its luck.
  41.          */
  42.         ret = 0;
  43. done:
  44.         atomic_dec(&probe_count);
  45.         wake_up(&probe_waitqueue);
  46.         return ret;
  47. }
复制代码
我的疑惑在于:

当有U盘插入设备时: 由于 usb bus 并没有定义 probe 函数, 那么会调用 driver 的 probe 函数, 也应该就是 storage_probe 函数.
而storage_probe函数需要的两个参数类型和really_probe 传递给 probe 的不一致.

请问这中间是如何协调的? 还是调用的 probe 函数是 usb-core 的 probe, usb-core 的probe 再去调用 usb-storage 的 probe 的呢?

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
2 [报告]
发表于 2012-09-11 21:59 |只看该作者
>> 由于 usb bus 并没有定义 probe 函数, 那么会调用 driver 的 probe 函数, 也应该就是 storage_probe 函数

看清楚storage_probe是哪个结构体的probe,generic的代码怎么会突然扯到那个结构体上去了。

论坛徽章:
0
3 [报告]
发表于 2012-09-11 22:22 |只看该作者
回复 2# tempname2


   不太好意思, 没有理解你这话的深层含义.

storage_probe 函数是 usb_driver usb_storage_driver 的成员函数.

而 usb_storage_driver 是挂接在 usb bus 上的.

然后, generic的代码? 没理解?

论坛徽章:
0
4 [报告]
发表于 2012-09-11 22:47 |只看该作者
回复 2# tempname2


    我刚看代码了解了. 知道这个问题的答案了.

在 drivers/usb/core/driver.c 中, usb_register_dirver函数, 将usb_driver 中 drvwrap 成员的 device_driver 的 probe 函数替换了.
  1. int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
  2.                         const char *mod_name)
  3. {
  4.         int retval = 0;

  5.         if (usb_disabled())
  6.                 return -ENODEV;

  7.         new_driver->drvwrap.for_devices = 0;
  8.         new_driver->drvwrap.driver.name = (char *) new_driver->name;
  9.         new_driver->drvwrap.driver.bus = &usb_bus_type;
  10.         new_driver->drvwrap.driver.probe = usb_probe_interface; // here.....
  11.         new_driver->drvwrap.driver.remove = usb_unbind_interface;
  12.         new_driver->drvwrap.driver.owner = owner;
  13.         new_driver->drvwrap.driver.mod_name = mod_name;
  14.         spin_lock_init(&new_driver->dynids.lock);
  15.         INIT_LIST_HEAD(&new_driver->dynids.list);

  16.         retval = driver_register(&new_driver->drvwrap.driver);
  17.         if (retval)
  18.                 goto out;

  19.         usbfs_update_special();

  20.         retval = usb_create_newid_file(new_driver);
  21.         if (retval)
  22.                 goto out_newid;

  23.         retval = usb_create_removeid_file(new_driver);
  24.         if (retval)
  25.                 goto out_removeid;

  26.         pr_info("%s: registered new interface driver %s\n",
  27.                         usbcore_name, new_driver->name);

  28. out:
  29.         return retval;

  30. out_removeid:
  31.         usb_remove_newid_file(new_driver);
  32. out_newid:
  33.         driver_unregister(&new_driver->drvwrap.driver);

  34.         printk(KERN_ERR "%s: error %d registering interface "
  35.                         "        driver %s\n",
  36.                         usbcore_name, retval, new_driver->name);
  37.         goto out;
  38. }
复制代码
usb_probe_interface这个借口函数才会去调用 usb_storage_driver结构的probe 函数. 接口函数为:
  1. static int usb_probe_interface(struct device *dev)
  2. {
  3.         struct usb_driver *driver = to_usb_driver(dev->driver);
  4.         struct usb_interface *intf = to_usb_interface(dev);
  5.         struct usb_device *udev = interface_to_usbdev(intf);
  6.         const struct usb_device_id *id;
  7.         int error = -ENODEV;

  8.         dev_dbg(dev, "%s\n", __func__);

  9.         intf->needs_binding = 0;

  10.         if (usb_device_is_owned(udev))
  11.                 return error;

  12.         if (udev->authorized == 0) {
  13.                 dev_err(&intf->dev, "Device is not authorized for usage\n");
  14.                 return error;
  15.         }

  16.         id = usb_match_id(intf, driver->id_table);
  17.         if (!id)
  18.                 id = usb_match_dynamic_id(intf, driver);
  19.         if (!id)
  20.                 return error;

  21.         dev_dbg(dev, "%s - got id\n", __func__);

  22.         error = usb_autoresume_device(udev);
  23.         if (error)
  24.                 return error;

  25.         intf->condition = USB_INTERFACE_BINDING;

  26.         /* Probed interfaces are initially active.  They are
  27.          * runtime-PM-enabled only if the driver has autosuspend support.
  28.          * They are sensitive to their children's power states.
  29.          */
  30.         pm_runtime_set_active(dev);
  31.         pm_suspend_ignore_children(dev, false);
  32.         if (driver->supports_autosuspend)
  33.                 pm_runtime_enable(dev);

  34.         /* Carry out a deferred switch to altsetting 0 */
  35.         if (intf->needs_altsetting0) {
  36.                 error = usb_set_interface(udev, intf->altsetting[0].
  37.                                 desc.bInterfaceNumber, 0);
  38.                 if (error < 0)
  39.                         goto err;
  40.                 intf->needs_altsetting0 = 0;
  41.         }

  42.         error = driver->probe(intf, id);  // here, to call usb_storage_driver.probe 函数.
  43.         if (error)
  44.                 goto err;

  45.         intf->condition = USB_INTERFACE_BOUND;
  46.         usb_autosuspend_device(udev);
  47.         return error;

  48. err:
  49.         intf->needs_remote_wakeup = 0;
  50.         intf->condition = USB_INTERFACE_UNBOUND;
  51.         usb_cancel_queued_reset(intf);

  52.         /* Unbound interfaces are always runtime-PM-disabled and -suspended */
  53.         if (driver->supports_autosuspend)
  54.                 pm_runtime_disable(dev);
  55.         pm_runtime_set_suspended(dev);

  56.         usb_autosuspend_device(udev);
  57.         return error;
  58. }
复制代码
usb_driver 结构体为:
  1. struct usb_driver {
  2.         const char *name;

  3.         int (*probe) (struct usb_interface *intf,
  4.                       const struct usb_device_id *id);

  5.         void (*disconnect) (struct usb_interface *intf);

  6.         int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
  7.                         void *buf);

  8.         int (*suspend) (struct usb_interface *intf, pm_message_t message);
  9.         int (*resume) (struct usb_interface *intf);
  10.         int (*reset_resume)(struct usb_interface *intf);

  11.         int (*pre_reset)(struct usb_interface *intf);
  12.         int (*post_reset)(struct usb_interface *intf);

  13.         const struct usb_device_id *id_table;

  14.         struct usb_dynids dynids;
  15.         struct usbdrv_wrap drvwrap;
  16.         unsigned int no_dynamic_id:1;
  17.         unsigned int supports_autosuspend:1;
  18.         unsigned int soft_unbind:1;
  19. }
复制代码
struct usbdrv_wrap j结构体为:
  1. struct usbdrv_wrap {
  2.         struct device_driver driver;
  3.         int for_devices;
  4. };
复制代码
当调用 device_add 函数时, 相应的 driver 是 usb-core. 不知道这样理解对不对.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP