Linux USB subsystem --- USB bus registration

目的:对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

你可能感兴趣的:(linux,usb)