usb_register流程
本文编写的背景是分析RTL8152B的驱动程序,所以先给出该驱动程序的基本信息。
/* table of devices that work with this driver */
static struct usb_device_id rtl8152_table[] = {
{USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)},
{}
};
MODULE_DEVICE_TABLE(usb, rtl8152_table);
static struct usb_driver rtl8152_driver = {
.name = MODULENAME, // "r8152"
.probe = rtl8152_probe,
.disconnect = rtl8152_disconnect,
.id_table = rtl8152_table,
.suspend = rtl8152_suspend,
.resume = rtl8152_resume
};
static int __init usb_rtl8152_init(void)
{
return usb_register(&rtl8152_driver);
}
static void __exit usb_rtl8152_exit(void)
{
usb_deregister(&rtl8152_driver);
}
是的,我认为以上就是驱动程序的基本信息。驱动程序入口函数usb_rtl8152_init
中调用了usb_register()
函数,从而引入到了这篇文章。
文章开头贴上整个usb_register的流程图:
usb_register() -> usb_register_driver() ->
driver_register() ->
usb_create_newid_files() ->
usb_register()
从驱动程序中调用usb_register()
传入参数:&rtl8152_driver
。 然后来到一个宏定义:
/* use a define to avoid include chaining to get THIS_MODULE & friends */
#define usb_register(driver) \
usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
需要注意的是,这里是一个宏定义,预处理阶段处理的,也就是说,真正的init函数长这样:
static int __init usb_rtl8152_init(void)
{
usb_register_driver(&rtl8152_driver, THIS_MODULE, KBUILD_MODNAME); // THIS_MODULE是一个指向当前模块的指针,KBUILD_MODNAME是当前模块的名称
}
然后继续往下看:
usb_register_driver()
这个函数中会对usb_driver::drvwrap
成员结构进行填充,usb_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; // usb接口设备
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; // probe
new_driver->drvwrap.driver.remove = usb_unbind_interface; // remove
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;
retval = usb_create_newid_files(new_driver); // 注册ID文件
if (retval)
goto out_newid;
pr_info("%s: registered new interface driver %s\n",
usbcore_name, new_driver->name);
out:
return retval;
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;
}
EXPORT_SYMBOL_GPL(usb_register_driver);
driver_register()
看到driver_register()
函数,其实就已经很明确接下来要干啥了。无非就是寻找设备,进行匹配嘛。
driver_register()
函数接收一个device_driver
类型的指针变量作为参数,根据上面传下来的参数,我们得知这里的drv
就是在usb_register_driver()
函数中填充的new_driver->drvwrap.driver
/**
* driver_register - register driver with bus
* @drv: driver to register
*
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*/
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus);
if (other) {
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret) {
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD);
return ret;
}
EXPORT_SYMBOL_GPL(driver_register);
driver_find()
首先来看第一个调用driver_find
函数 ,这个函数的作用就是去看看当前传进来的这个驱动有没有注册,如果已经注册了那自然不用再次注册,直接返回其已经注册了的地址。否则返回NULL。所以,一般情况下,这个函数不会return,那我们继续……
bus_add_driver()
接下来是bus_add_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;
/* 将该驱动添加到kobject驱动模型里面去 */
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister;
/* 把驱动添加的驱动总线的尾部 */
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
/* 这里涉及到一个变量drivers_autoproce,是否自动探测设备,这个值默认为1 */
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv); // 上面默认自动探测设备,那么这里就开始去寻找这个设备啦。
if (error)
goto out_unregister;
}
/* 从这里往下的操作,只有上述设备探测得到,才会继续,所以对我们来说,今天我们到这里为止,只需要继续去看上面的函数时如何继续的就可以 */
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);
}
}
return 0;
out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p = NULL;
out_put_bus:
bus_put(bus);
return error;
}
在bus_add_driver
中,将驱动程序添加到了驱动总线的尾部,然后自动开始了设备侦测之路。就是如此简单,我们继续看设备侦测之路是如何进行的。
driver_attach()和__driver_attach
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
if (!driver_match_device(drv, dev))
return 0;
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
EXPORT_SYMBOL_GPL(driver_attach);
先从最下面的driver_attach
函数开始看,在这个函数中调用了bus_for_each_dev
函数,在下面。
int bus_for_each_dev(const struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct subsys_private *sp = bus_to_subsys(bus);
struct klist_iter i;
struct device *dev;
int error = 0;
if (!sp)
return -EINVAL;
klist_iter_init_node(&sp->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
while (!error && (dev = next_device(&i)))
error = fn(dev, data);
klist_iter_exit(&i);
subsys_put(sp);
return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);
这部分代码的目的就是让驱动去匹配设备,其实在bus.c中仔细去看的话,还会发现bus_for_each_drv
函数,这个就是设备去匹配驱动的过程。那么具体的匹配过程是怎样的呢?原来调用bus_for_each_dev
的时候,给他传入了一个函数指针,主要动作都在这个函数指针里面。这里需要着重说明的是,bus_for_each_dev
函数会遍历当前总线上所有的设备,来匹配当前的驱动。需要注意的一条语句是dev = next_device(&i)
这条语句会解决你后面的一个疑问!!
然后我们继续来看在__driver_attach
中又是如何进行设备与驱动的匹配的吧!
在展开说attach函数之前,我想先说一下,一个驱动注册,最主要的目的是要干什么?个人认为,做了那么多流程,最终目的就是希望看到,这个流程走了一圈,最终调回到了驱动的probe函数!
driver_match_device()
那么我们从这里开始,就要向着这个方向努力前进了!回到正题,在attach函数中,有这个函数调用driver_match_device
顾名思义,驱动匹配设备,那我们就继续去看这个函数的实现:
居然是个内联函数!!!这个函数定义在drivers/base/base.h
。对哦,上面的函数调用好像没有说明对应的路径,不过没关系,我教你,首先选中函数名,然后按Ctrl+C,然后打开浏览器,打开google.com, 然后Ctrl+V,回车!!! 回归正题!
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
内核的代码真的是往死里绝,这里直接一个三元运算符完事儿。很牛!如果当前驱动对应的驱动总线上的match函数存在,则执行他,去匹配dev和drv. drv我们知道就是我们当前正在注册的驱动,那么这个dev是什么?不要忘了我们现在正在干嘛,我们现在正在bus_for_each_dev
函数里,遍历当前usb总线上的所有设备,有足够的dev给这个函数传参哦。
match() == usb_device_match
到这里就需要选择正确的match函数来匹配设备了,在usb_register_driver
中,配置了当前drv的总线类型: new_driver->drvwrap.driver.bus = &usb_bus_type;
我们可以简单看一下这个总线结构:
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
};
所以当前的总线中的match函数是:usb_device_match
函数。
这个函数中对USB的device和interface做了分开处理。如果当前设备时USB device则继续判断当前驱动是不是USB设备驱动,如果是,就直接返回1,出去调用probe。如果不是USB device,则继续执行。
然后会判断是不是USB interface。
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
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;
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* device drivers never match interfaces */
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;
}
由于RTL8152B是一个实际的USB Device,所以上面的判断中会直接返回1,然后程序出栈。直接返回到:__driver_attach()
函数。进而调用probe函数。
driver_probe_device()
该函数传入了drv和dev。使用really_probe()
函数:
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev))
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
pm_request_idle(dev);
return ret;
}
really_probe()
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
int local_trigger_count = atomic_read(&deferred_trigger_count);
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev);
if (ret)
goto probe_failed;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
// 异常处理部分代码省略:
...
}
这个函数中最主要的就是调用了probe函数:
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
但是这里也有两种不同的probe函数调用途径。首先是查看遍历到的dev所在的总线上有没有定义probe函数。如果有则执行它,当然最后也会调到我们驱动的probe函数中。另外就是查看当前drv参数是不是有probe函数,如果有就执行它。我们直接来看drv->probe
从整个传参过程往回找,找到:new_driver->drvwrap.driver.probe = usb_probe_interface;
usb_probe_interface()
static int usb_probe_interface(struct device *dev)
{
struct usb_driver *driver = to_usb_driver(dev->driver);
struct usb_interface *intf = to_usb_interface(dev);
struct usb_device *udev = interface_to_usbdev(intf);
const struct usb_device_id *id;
int error = -ENODEV;
int lpm_disable_error = -ENODEV;
dev_dbg(dev, "%s\n", __func__);
intf->needs_binding = 0;
if (usb_device_is_owned(udev))
return error;
if (udev->authorized == 0) {
dev_err(&intf->dev, "Device is not authorized for usage\n");
return error;
}
id = usb_match_dynamic_id(intf, driver);
if (!id)
id = usb_match_id(intf, driver->id_table);
if (!id)
return error;
dev_dbg(dev, "%s - got id\n", __func__);
error = usb_autoresume_device(udev);
if (error)
return error;
intf->condition = USB_INTERFACE_BINDING;
/* Probed interfaces are initially active. They are
* runtime-PM-enabled only if the driver has autosuspend support.
* They are sensitive to their children's power states.
*/
pm_runtime_set_active(dev);
pm_suspend_ignore_children(dev, false);
if (driver->supports_autosuspend)
pm_runtime_enable(dev);
/* If the new driver doesn't allow hub-initiated LPM, and we can't
* disable hub-initiated LPM, then fail the probe.
*
* Otherwise, leaving LPM enabled should be harmless, because the
* endpoint intervals should remain the same, and the U1/U2 timeouts
* should remain the same.
*
* If we need to install alt setting 0 before probe, or another alt
* setting during probe, that should also be fine. usb_set_interface()
* will attempt to disable LPM, and fail if it can't disable it.
*/
if (driver->disable_hub_initiated_lpm) {
lpm_disable_error = usb_unlocked_disable_lpm(udev);
if (lpm_disable_error) {
dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
__func__, driver->name);
error = lpm_disable_error;
goto err;
}
}
/* Carry out a deferred switch to altsetting 0 */
if (intf->needs_altsetting0) {
error = usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
if (error < 0)
goto err;
intf->needs_altsetting0 = 0;
}
error = driver->probe(intf, id);
if (error)
goto err;
intf->condition = USB_INTERFACE_BOUND;
/* If the LPM disable succeeded, balance the ref counts. */
if (!lpm_disable_error)
usb_unlocked_enable_lpm(udev);
usb_autosuspend_device(udev);
return error;
err:
usb_set_intfdata(intf, NULL);
intf->needs_remote_wakeup = 0;
intf->condition = USB_INTERFACE_UNBOUND;
/* If the LPM disable succeeded, balance the ref counts. */
if (!lpm_disable_error)
usb_unlocked_enable_lpm(udev);
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
if (driver->supports_autosuspend)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
usb_autosuspend_device(udev);
return error;
}
这个函数中也有好多调用,最主要的就是error = driver->probe(intf, id);
, 成功调用到我们驱动的probe函数里面。
rtl8152_probe()
这个函数就贴出来看看,不说了,这是另外的文章![狗头]
static int rtl8152_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct r8152 *tp;
struct net_device *netdev;
#ifdef LIKE_DEBUG
printk("like: rtl8152 func %s enter! \n", __func__);
#endif
if (udev->actconfig->desc.bConfigurationValue != 1) {
usb_driver_set_configuration(udev, 1);
return -ENODEV;
}
netdev = alloc_etherdev(sizeof(struct r8152));
if (!netdev) {
dev_err(&intf->dev, "Out of memory");
return -ENOMEM;
}
tp = netdev_priv(netdev);
tp->msg_enable = 0x7FFF;
tasklet_init(&tp->tl, rx_fixup, (unsigned long)tp);
INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
tp->udev = udev;
tp->netdev = netdev;
netdev->netdev_ops = &rtl8152_netdev_ops;
netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
netdev->features &= ~NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev, &ops);
tp->speed = 0;
tp->mii.dev = netdev;
tp->mii.mdio_read = read_mii_word;
tp->mii.mdio_write = write_mii_word;
tp->mii.phy_id_mask = 0x3f;
tp->mii.reg_num_mask = 0x1f;
tp->mii.phy_id = R8152_PHY_ID;
tp->mii.supports_gmii = 0;
r8152b_get_version(tp);
r8152b_init(tp);
set_ethernet_addr(tp);
if (!alloc_all_urbs(tp)) {
netif_err(tp, probe, netdev, "out of memory");
goto out;
}
tp->rx_skb = netdev_alloc_skb(netdev,
RTL8152_RMS + sizeof(struct rx_desc));
if (!tp->rx_skb)
goto out1;
usb_set_intfdata(intf, tp);
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) {
netif_err(tp, probe, netdev, "couldn't register the device");
goto out2;
}
netif_info(tp, probe, netdev, "%s", DRIVER_VERSION);
return 0;
out2:
usb_set_intfdata(intf, NULL);
dev_kfree_skb(tp->rx_skb);
out1:
free_all_urbs(tp);
out:
free_netdev(netdev);
return -EIO;
}
附录
附录一 usb_driver
struct usb_driver {
const char *name;
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
void (*disconnect) (struct usb_interface *intf);
int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
void *buf);
int (*suspend) (struct usb_interface *intf, pm_message_t message);
int (*resume) (struct usb_interface *intf);
int (*reset_resume)(struct usb_interface *intf);
int (*pre_reset)(struct usb_interface *intf);
int (*post_reset)(struct usb_interface *intf);
const struct usb_device_id *id_table;
struct usb_dynids dynids;
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
unsigned int disable_hub_initiated_lpm:1;
unsigned int soft_unbind:1;
};
参考文章
https://blog.csdn.net/dxjshr/article/details/80612261
http://www.deansys.com/doc/ldd3/ch13s04.html
https://www.cnblogs.com/liushuhe1990/p/9951513.html