Linux设备驱动之USBhub驱动
Linux设备驱动之USB hub驱动
------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处: :// linux100.org
------------------------------------------
一:前言
继UHCI的驱动之后,我们对USB Control的运作有了一定的了解.在接下来的分析中,我们对USB设备的驱动做一个全面的分析,我们先从HUB的驱动说起.关于HUB,usb2.0 spec上有详细的定义,基于这部份的代码位于linux-2.6.25/drivers/usb/core下,也确实是说,这部份代码是位于core下,和具体设备是无关的,因为各厂商的hub差不多上按照spec的要求来设计的.
二:UHCI驱动中的root hub
记得在分析UHCI驱动的时候,曾详细分析过root hub的初始化操作.为了分析方便,将代码片段列出如下:
usb_add_hcd() à usb_alloc_dev():
struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *bus, unsigned port1)
{
……
……
//usb_device,内嵌有struct device结构,对那个结构进行初始化
device_initialize(&dev->dev);
dev->dev.bus = &usb_bus_type;
dev->dev.type = &usb_device_type;
……
……
}
一看到前面对dev的赋值,依照我们对设备模型的明白得,一旦那个device进行注册,就会发生driver和device的匹配过程了.
只是,现在还不是分析那个过程的时候,我们先来看一下,USB子系统中的两种驱动.
三:USB子系统中的两种驱动
linux-2.6.25/drivers/usb/core/driver.c中,我们能够找到两种register driver的方式,分别为usb_register_driver()和usb_register_device_driver().分别来分析一下这两个接口.
usb_register_device_driver()接口的代码如下:
int usb_register_device_driver(struct usb_device_driver *new_udriver,
struct module *owner)
{
int retval = 0;
if (usb_disabled())
return -ENODEV;
new_udriver->drvwrap.for_devices = 1;
new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
new_udriver->drvwrap.driver.bus = &usb_bus_type;
new_udriver->drvwrap.driver.probe = usb_probe_device;
new_udriver->drvwrap.driver.remove = usb_unbind_device;
new_udriver->drvwrap.driver.owner = owner;
retval = driver_register(&new_udriver->drvwrap.driver);
if (!retval) {
pr_info(〝%s: registered new device driver %s\n〞,
usbcore_name, new_udriver->name);
usbfs_update_special();
} else {
printk(KERN_ERR 〝%s: error %d registering device 〝
〝 driver %s\n〞,
usbcore_name, retval, new_udriver->name);
}
return retval;
}
第一,通过usb_disabled()来判定一下usb是否被禁用,假如被禁用,因此就不必执行下面的流程了,直截了当退出即可.
从上面的代码,专门明显能够看到, struct usb_device_driver 对struct device_driver进行了一次封装,我们注意一下那个地点的赋值操作:new_udriver->drvwrap.for_devices = 1.等等.这些在后面差不多上用派上用场的.
usb_register_driver()的代码如下:
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) {
pr_info(〝%s: registered new interface driver %s\n〞,
usbcore_name, new_driver->name);
usbfs_update_special();
usb_create_newid_file(new_driver);
} else {
printk(KERN_ERR 〝%s: error %d registering interface 〝
〝 driver %s\n〞,
usbcore_name, retval, new_driver->name);
}
return retval;
}
专门明显,在那个地点接口里,将new_driver->drvwrap.for_devices设为了0.而且两个接口的porbe()函数也不一样.
事实上,关于usb_register_driver()能够看作是usb设备中的接口驱动,而usb_register_device_driver()是一个单纯的USB设备驱动.
四: hub的驱动分析
4.1: usb_bus_type->match()的匹配过程
usb_bus_type->match()用来判定驱动和设备是否匹配,它的代码如下:
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* 整理 by linux100.org */
//usb device的情形
if (is_usb_device(dev)) {
/* interface drivers never match devices */
if (!is_usb_device_driver(drv))
return 0;
/* TODO: Add real matching code */
return 1;
}
//interface的情形
else {
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/*整理 by linux100.org */
if (is_usb_device_driver(drv))
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id(intf, usb_drv->id_table);
if (id)
return 1;
id = usb_match_dynamic_id(intf, usb_drv);
if (id)
return 1;
}
return 0;
}
那个地点的match会区分上面所说的两种驱动,即设备的驱动和接口的驱动.
is_usb_device()的代码如下:
static inline int is_usb_device(const struct device *dev)
{
return dev->type == &usb_device_type;
}
专门明显,关于root hub来说,那个判定是确信会满足的.
static inline int is_usb_device_driver(struct device_driver *drv)
{
return container_of(drv, struct usbdrv_wrap, driver)->
for_devices;
}
回忆一下,我们在分析usb_register_device_driver()的时候,不是将new_udriver->drvwrap.for_devices置为了1么?因此关于usb_register_device_driver()注册的驱动来说,那个地点也是会满足的.
因此,对应root hub的情形,从第一个if就会匹配到usb_register_device_driver()注册的驱动.
关于接口的驱动,我们等遇到的时候再来进行分析.
4.2:root hub的驱动入口
既然我们明白,root hub会匹配到usb_bus_type->match()的驱动,那那个驱动到底是什么呢?我们从usb子系统的初始化开始说起.
在linux-2.6.25/drivers/usb/core/usb.c中.有如此的一段代码:
subsys_initcall(usb_init);
关于subsys_initcall()我们差不多不生疏了,在专门多地点都会遇到它.在系统初始化的时候,会调用到它对应的函数.在那个地点,即为usb_init().
在usb_init()中,有如此的代码片段:
static int __init usb_init(void)
{
……
……
retval = usb_register_devic