目的:对USB作深入学习,在此留下笔记。欢迎讨论。
[Linux 3.2] [driver/usb/core/devio.c]
定义:usbfs_driver
structusb_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.
*/
intusb_register_driver(structusb_driver *new_driver,structmodule *owner,
constchar*mod_name)
{
intretval = 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)
gotoout;
usbfs_update_special();
retval = usb_create_newid_file(new_driver);
if(retval)
gotoout_newid;
retval = usb_create_removeid_file(new_driver);
if(retval)
gotoout_removeid;
pr_info("%s: registered new interface driver %s\n",
usbcore_name, new_driver->name);
out:
returnretval;
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);
gotoout;
}
此函数主要功能实现是通过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.
*/
intbus_add_driver(structdevice_driver *drv)
{
structbus_type *bus;
structdriver_private *priv;
interror = 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;
gotoout_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)
gotoout_unregister;
if(drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if(error)
gotoout_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);
return0;
out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p = NULL;
out_put_bus:
bus_put(bus);
returnerror;
}
其功能是向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