Linux USB subsystem --- USBFS driver registration

目的:对USB进行深入学习,在此留下笔记。欢迎讨论。

[Author: Bo Shen <voice.shen@gmail.com>]


注:不知道为什么usbfs_init()已经被移除,为什么还是保留此函数?(暂时不分析此函数)

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

定义:usbfs_driver

struct usb_driver usbfs_driver = {
	.name =		"usbfs",
	.probe =	driver_probe,
	.disconnect =	driver_disconnect,
	.suspend =	driver_suspend,
	.resume =	driver_resume,
};

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

函数:usb_register();

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

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

函数:usb_register_driver();

/**
 * usb_register_driver - register a USB interface driver
 * @new_driver: USB operations for the interface driver
 * @owner: module owner of this driver.
 * @mod_name: module name string
 *
 * Registers a USB interface driver with the USB core.  The list of
 * unattached interfaces will be rescanned whenever a new driver is
 * added, allowing the new driver to attach to any recognized interfaces.
 * Returns a negative error code on failure and 0 on success.
 *
 * NOTE: if you want your driver to use the USB major number, you must call
 * usb_register_dev() to enable that functionality.  This function no longer
 * takes care of that.
 */
int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
			const char *mod_name)
{
	int retval = 0;

	if (usb_disabled())
		return -ENODEV;

	new_driver->drvwrap.for_devices = 0;
	new_driver->drvwrap.driver.name = (char *) new_driver->name;
	new_driver->drvwrap.driver.bus = &usb_bus_type;
	new_driver->drvwrap.driver.probe = usb_probe_interface;
	new_driver->drvwrap.driver.remove = usb_unbind_interface;
	new_driver->drvwrap.driver.owner = owner;
	new_driver->drvwrap.driver.mod_name = mod_name;
	spin_lock_init(&new_driver->dynids.lock);
	INIT_LIST_HEAD(&new_driver->dynids.list);

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

	usbfs_update_special();

	retval = usb_create_newid_file(new_driver);
	if (retval)
		goto out_newid;

	retval = usb_create_removeid_file(new_driver);
	if (retval)
		goto out_removeid;

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

out:
	return retval;

out_removeid:
	usb_remove_newid_file(new_driver);
out_newid:
	driver_unregister(&new_driver->drvwrap.driver);

	printk(KERN_ERR "%s: error %d registering interface "
			"	driver %s\n",
			usbcore_name, retval, new_driver->name);
	goto out;
}

此函数主要功能实现是通过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进行分析。

/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
	struct bus_type *bus;
	struct driver_private *priv;
	int error = 0;

	bus = bus_get(drv->bus);
	if (!bus)
		return -EINVAL;

	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		error = -ENOMEM;
		goto out_put_bus;
	}
	klist_init(&priv->klist_devices, NULL, NULL);
	priv->driver = drv;
	drv->p = priv;
	priv->kobj.kset = bus->p->drivers_kset;
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
				     "%s", drv->name);
	if (error)
		goto out_unregister;

	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
	module_add_driver(drv->owner, drv);

	error = driver_create_file(drv, &driver_attr_uevent);
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
			__func__, drv->name);
	}
	error = driver_add_attrs(bus, drv);
	if (error) {
		/* How the hell do we get out of this pickle? Give up */
		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
			__func__, drv->name);
	}

	if (!drv->suppress_bind_attrs) {
		error = add_bind_files(drv);
		if (error) {
			/* Ditto */
			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
				__func__, drv->name);
		}
	}

	kobject_uevent(&priv->kobj, KOBJ_ADD);
	return 0;

out_unregister:
	kobject_put(&priv->kobj);
	kfree(drv->p);
	drv->p = NULL;
out_put_bus:
	bus_put(bus);
	return error;
}

其功能是向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


 

 


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值