目的:对USB进行深入学习,在此留下笔记。欢迎讨论。
[Author: Bo Shen <[email protected]>]
[Linux 3.2: driver/usb/core/driver.c]
定义:usb_bus_type
struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match, .uevent = usb_uevent, };
1. usb_device_match的作用是去判断是usb device (is_usb_device()),还是usb interface (is_usb_interface())。
2. usb_uevent (依赖于CONFIG_HOTPLUG) 的作用,通过判断是usb device 还是usb interface来获取struct usb_device *usb_dev结构体,然后进行两个判断(usb_dev->devnum < 0) 和(!usb_dev->bus),最后调用add_uevent_var(<lib/kobject_uevent.c>)添加PRODUCT和TYPE信息。
附:讲解一下bus_register()函数。
[Linux 3.2: driver/base/bus.c]
函数:bus_register(struct bus_type *bus)
/** * bus_register - register a bus with the system. * @bus: bus. * * Once we have that, we registered the bus with the kobject * infrastructure, then register the children subsystems it has: * the devices and drivers that belong to the bus. */ int bus_register(struct bus_type *bus) { int retval; struct subsys_private *priv; priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); if (!priv) return -ENOMEM; priv->bus = bus; bus->p = priv; BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); if (retval) goto out; priv->subsys.kobj.kset = bus_kset; priv->subsys.kobj.ktype = &bus_ktype; priv->drivers_autoprobe = 1; retval = kset_register(&priv->subsys); if (retval) goto out; retval = bus_create_file(bus, &bus_attr_uevent); if (retval) goto bus_uevent_fail; priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj); if (!priv->devices_kset) { retval = -ENOMEM; goto bus_devices_fail; } priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj); if (!priv->drivers_kset) { retval = -ENOMEM; goto bus_drivers_fail; } klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); klist_init(&priv->klist_drivers, NULL, NULL); retval = add_probe_files(bus); if (retval) goto bus_probe_files_fail; retval = bus_add_attrs(bus); if (retval) goto bus_attrs_fail; pr_debug("bus: '%s': registered\n", bus->name); return 0; bus_attrs_fail: remove_probe_files(bus); bus_probe_files_fail: kset_unregister(bus->p->drivers_kset); bus_drivers_fail: kset_unregister(bus->p->devices_kset); bus_devices_fail: bus_remove_file(bus, &bus_attr_uevent); bus_uevent_fail: kset_unregister(&bus->p->subsys); out: kfree(bus->p); bus->p = NULL; return retval; } EXPORT_SYMBOL_GPL(bus_register);
bus_register的目的主要是处理Linux设备模型的相关事宜。
此函数的主要作用如下:
1. line 21 : 初始化一个blocking的通知链。
2. line 23 ~ 31: 将USB总线加入总线集,并在/sys/bus下面创建usb子目录。
3. line 35 : 在/sys/bus/usb/下面创建uevent的属性文件。
4. line 39 ~ 51: 在usb总线子集上面创建devices, drivers两个子集,同时创建目录。
5. line 53 ~54 : 初始化两条链表:klist_devices, klist_drivers。
6. line 56 : 添加bus的drivers_probe,drivers_autoprobe属性文件。(需要CONFIG_HOTPLUG的支持)
7. line 60 : 添加bus的其余属性文件,对USB来说,没有。
这些完成之后,可以在/sys/bus下面看到usb目录,
在USB目录下面可以看到:
# ls /sys/bus/usb
devices drivers_autoprobe uevent drivers drivers_probe