资源描述
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
点击显示更多内容>>
收藏
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号