usb_register注册流程分析

发布时间 2023-08-10 13:59:45作者: 可乐klelee

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