Linux USB驱动分析(一)

本文深入剖析Linux内核5.0中USB总线的初始化过程,包括usb_init()函数、bus_register()、usb_hub_init()以及usb_register_device_driver()等关键步骤。同时,详细阐述了USBHost设备初始化,特别是xHCI(PCI-xHCI)的初始化流程,如xhci_pci_init()、pci_register_driver()和xhci_pci_probe()函数。通过对这些核心函数的解析,揭示了USB设备从注册到配置的完整过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境

  • Linux Kernel 5.0
  • Source Insight 3.5

1 USB总线初始化

1.1 usb_init()函数

在usb_init()函数中主要有如下的三个主要函数,分别注册usb总线,初始化usb hub驱动,注册usb设备通用驱动.

static int __init usb_init(void)
{
	int retval;
	retval = bus_register(&usb_bus_type);
	retval = usb_hub_init();
	retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
}

1.1.1 bus_register()函数

struct bus_type usb_bus_type = {
	.name =		"usb",
	.match =	usb_device_match,
	.uevent =	usb_uevent,
	.need_parent_lock =	true,
};
int bus_register(struct bus_type *bus)
{
	struct subsys_private *priv;

	priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);

	priv->bus = bus;
	bus->p = priv;
	
	//初始化usb kset
	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
	priv->subsys.kobj.kset = bus_kset;
	priv->subsys.kobj.ktype = &bus_ktype;
	priv->drivers_autoprobe = 1;
	
	//注册usb kset
	retval = kset_register(&priv->subsys);

	//初始化devices kset并注册在usb kset下
	priv->devices_kset = kset_create_and_add("devices", NULL,
						 &priv->subsys.kobj);
	//初始化drivers kset并注册在usb kset下					 
	priv->drivers_kset = kset_create_and_add("drivers", NULL,
						 &priv->subsys.kobj);
}
  • 注册usb类型的kset, 然后在usb类型的kset下添加devices和drivers两个kset.

1.1.2 usb_hub_init()函数

static struct usb_driver hub_driver = {
	.name =		"hub",
	.probe =	hub_probe,
	...
	.id_table =	hub_id_table,
	.supports_autosuspend =	1,
};

int usb_hub_init(void)
{
	//#define usb_register(driver) usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
	usb_register(&hub_driver)
	hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0);
}

int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
			const char *mod_name)
{
	//@for_devices: Non-zero for device drivers, 0 for interface drivers.
	new_driver->drvwrap.for_devices = 0;
	new_driver->drvwrap.driver.name = new_driver->name;
	new_driver->drvwrap.driver.bus = &usb_bus_type;
	new_driver->drvwrap.driver.probe = usb_probe_interface;
	...
	retval = driver_register(&new_driver->drvwrap.driver);
	//klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
}
  • 注册hub_driver和创建hub_wq工作队列.
  • 初始化hub中drvwrap中driver的name,bus类型,和probe函数,并注册driver到usb总线klist_drivers链表上.

1.1.3 usb_register_device_driver()函数

struct usb_device_driver usb_generic_driver = {
	.name =	"usb",
	.probe = generic_probe,
	.disconnect = generic_disconnect,
	.supports_autosuspend = 1,
};

int usb_register_device_driver(struct usb_device_driver *new_udriver,
		struct module *owner)
{
	//@for_devices: Non-zero for device drivers, 0 for interface drivers.
	new_udriver->drvwrap.for_devices = 1;
	new_udriver->drvwrap.driver.name = new_udriver->name;
	new_udriver->drvwrap.driver.bus = &usb_bus_type;
	new_udriver->drvwrap.driver.probe = usb_probe_device;

	retval = driver_register(&new_udriver->drvwrap.driver);
	//klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
}

初始化usb_generic_driver 中drvwrap中driver的name, bus类型,以及probe函数,并注册到usb总线klist_drivers链表上.

总结USB总线初始化完后,分别在总线上注册了名为"usb"和“hub"的两个驱动分别对应着usb_probe_deviceusb_probe_interface的probe函数.

2 USB Host 设备初始化

  • 常用的USB Host主要有OHCI, UHCI, EHCI, xHCI。
  • 这里选择PCI方式的xHCI, 即挂接在PCI总线的xHCI设备PCI-xHCI。
  • 对于PCI-xHCI而言,既然是PCI设备,那么就需要注册PCI驱动。
  • 这里我们不讨论PCI相关的代码。

2.1 xhci_pci_init()函数

static const char hcd_name[] = "xhci_hcd";
static const struct pci_device_id pci_ids[] = { {
	/* handle any USB 3.0 xHCI controller */
	PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0),
	.driver_data =	(unsigned long) &xhci_pci_hc_driver,
	},
};
static struct pci_driver xhci_pci_driver = {
	.name =		(char *) hcd_name,
	.id_table =	pci_ids,
	.probe =	xhci_pci_probe,
	...
};
static int __init xhci_pci_init(void)
{
	xhci_init_driver(&xhci_pci_hc_driver, &xhci_pci_overrides);
	return pci_register_driver(&xhci_pci_driver);
}

xhci_pci_init函数主要是初始化xhci_pci_hc_driver,注册xhci_pci_driver.

2.1.1 xhci_init_driver()函数

static const struct hc_driver xhci_hc_driver = {
	.description =		"xhci-hcd",
	.product_desc =		"xHCI Host Controller",
	.hcd_priv_size =	sizeof(struct xhci_hcd),

	.irq =			xhci_irq,
	.flags =		HCD_MEMORY | HCD_USB3 | HCD_SHARED,

	.urb_enqueue =		xhci_urb_enqueue,
	...
}
void xhci_init_driver(struct hc_driver *drv, const struct xhci_driver_overrides *over)
{
	*drv = xhci_hc_driver;
}

初始化xhci_pci_hc_driver为xhci_hc_driver

2.1.2 pci_register_driver()函数

#define pci_register_driver(driver)	__pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)

int __pci_register_driver(struct pci_driver *drv, struct module *owner,
			  const char *mod_name)
{
	/* initialize common driver fields */
	drv->driver.name = drv->name;
	drv->driver.bus = &pci_bus_type;
	drv->driver.owner = owner;
	drv->driver.mod_name = mod_name;
	drv->driver.groups = drv->groups;

	/* register with core */
	return driver_register(&drv->driver);
}

当系统中存在PCI-xHCI设备时,就会调用pci_driver形式的xhci_pci_driver中的probe()函数.即xhci_pci_probe()函数

2.2 xhci_pci_probe()函数

static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
	int retval;
	struct xhci_hcd *xhci;
	struct hc_driver *driver;
	struct usb_hcd *hcd;
	//获取之前存在id_table中的driver->xhci_hc_driver 
	driver = (struct hc_driver *)id->driver_data;
	retval = usb_hcd_pci_probe(dev, id);

	//创建共享的hcd(TODO), 其流程下面已经分析完了.
	xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev,pci_name(dev), hcd);
	retval = usb_add_hcd(xhci->shared_hcd, dev->irq, IRQF_SHARED);
}

2.2.1 usb_hcd_pci_probe()函数

int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
	struct hc_driver	*driver;
	struct usb_hcd		*hcd;
	int			retval;
	int			hcd_irq = 0;

	//获取PCI类型的xHCI设备
	pci_enable_device(dev)
	//driver = xhci_hc_driver 
	driver = (struct hc_driver *)id->driver_data;
	//__usb_create_hcd(driver, &dev->dev, pci_name(dev));
	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
	usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
	...
}
2.2.1.2 __usb_create_hcd()函数
struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
		struct device *sysdev, struct device *dev, const char *bus_name,
		struct usb_hcd *primary_hcd)
{
	struct usb_hcd *hcd;
	hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);

	if (primary_hcd == NULL) {
		//dev->driver_data = data;
		dev_set_drvdata(dev, hcd);
	}
	//初始化HCD对应的USB BUS.
	usb_bus_init(&hcd->self); 
	hcd->self.controller = dev;
	hcd->self.bus_name = bus_name;
	timer_setup(&hcd->rh_timer, rh_timer_func, 0);
	hcd->driver = driver;
	hcd->product_desc = (driver->product_desc) ? driver->product_desc :"USB Host Controller";
	return hcd;
}

__usb_create_hcd创建并初始化了hcd.

2.2.1.3 usb_add_hcd()函数
int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags)
{
	int retval;
	struct usb_device *rhdev;


	retval = hcd_buffer_create(hcd);
	//bus->busnum = busnum;
	retval = usb_register_bus(&hcd->self);
	
	rhdev = usb_alloc_dev(NULL, &hcd->self, 0);
	hcd->self.root_hub = rhdev;

	/* initialize tasklets */
	init_giveback_urb_bh(&hcd->high_prio_bh);
	init_giveback_urb_bh(&hcd->low_prio_bh);
	
	/* starting here, usbcore will pay attention to this root hub */
	retval = register_root_hub(hcd);
	return retval;
}

继续初始化HCD,这里初始化了两个tasklets, 有什么用呢?(答案后面揭晓)
然后初始化并注册root hub, 对于HCD而言,root hub也是一种USB 设备.

2.2.1.3.1 usb_alloc_dev()函数
struct usb_device *usb_alloc_dev(struct usb_device *parent,
				 struct usb_bus *bus, unsigned port1)
{
	struct usb_device *dev;
	struct usb_hcd *usb_hcd = bus_to_hcd(bus);
	unsigned root_hub = 0;
	unsigned raw_port = port1;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);

	device_initialize(&dev->dev);
	dev->dev.bus = &usb_bus_type;
	dev->dev.type = &usb_device_type;
	
	dev->dev.dma_mask = bus->sysdev->dma_mask;
	dev->dev.dma_pfn_offset = bus->sysdev->dma_pfn_offset;
	set_dev_node(&dev->dev, dev_to_node(bus->sysdev));
	dev->state = USB_STATE_ATTACHED;

	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
	/* ep0 maxpacket comes later, from device descriptor */
	usb_enable_endpoint(dev, &dev->ep0, false);
	dev->can_submit = 1;

	if (unlikely(!parent)) {
		dev->devpath[0] = '0';
		dev->route = 0;
		dev->dev.parent = bus->controller;
		device_set_of_node_from_dev(&dev->dev, bus->sysdev);
		dev_set_name(&dev->dev, "usb%d", bus->busnum);
		root_hub = 1;
	} else {
		..
		dev->dev.parent = &parent->dev;
		dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
	}

	dev->portnum = port1;
	dev->bus = bus;
	dev->parent = parent;

}
2.2.1.3.2 register_root_hub()函数
static int register_root_hub(struct usb_hcd *hcd)
{
	struct device *parent_dev = hcd->self.controller;
	struct usb_device *usb_dev = hcd->self.root_hub;
	const int devnum = 1;
	int retval;
	usb_dev->devnum = devnum;
	usb_dev->bus->devnum_next = devnum + 1;
	set_bit (devnum, usb_dev->bus->devmap.devicemap);
	usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
	usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
	retval = usb_new_device (usb_dev);
	return retval;
}
2.2.1.3.2.1 usb_new_device ()函数
int usb_new_device(struct usb_device *udev)
{
	int err;
	
	//usb_enumerate_device - Read device configs/intfs 
	err = usb_enumerate_device(udev);	/* Read descriptors */

	/* export the usbdev device-node for libusb */
	udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));

	/* Register the device.  The device driver is responsible
	 * for configuring the device and invoking the add-device
	 * notifier chain (used by usbfs and possibly others).
	 */
	err = device_add(&udev->dev);
	//klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
	//bus_probe_device(dev);
}

通过device_add就注册到了USB 总线klist_devices中, 然后调用到driver_match_device()和driver_probe_device()函数

bus_probe_device(dev)-->device_initial_probe(dev)-->__device_attach(dev, true)-->bus_for_each_drv(...)-->__device_attach_driver(...)
static int __device_attach_driver(struct device_driver *drv, void *_data)
{
	struct device_attach_data *data = _data;
	struct device *dev = data->dev;
	//return drv->bus->match ? drv->bus->match(dev, drv) : 1; -->usb_device_match(dev, drv)
	ret = driver_match_device(drv, dev);
	return driver_probe_device(drv, dev);
}
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
	//return dev->type == &usb_device_type;
	if (is_usb_device(dev)) {
		//return container_of(drv, struct usbdrv_wrap, driver)->for_devices
		if (!is_usb_device_driver(drv))
			return 0;
		return 1;
		
		//return dev->type == &usb_if_device_type;
	} else if (is_usb_interface(dev)) {
		struct usb_interface *intf;
		struct usb_driver *usb_drv;
		const struct usb_device_id *id;
		
		//return container_of(drv, struct usbdrv_wrap, driver)->for_devices;
		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;
}

根据以上分析会调用usb_device_match(…)来匹配驱动. 由于在2.2.1.3.1dev->type == &usb_device_type;然后又会判断for_devices,在1.1.3for_devices=1的,所以满足条件驱动的probe函数为usb_probe_device(),其最后会调用到usb_generic_driver 中的 probe函数generic_probe()

static int usb_probe_device(struct device *dev)
{
	//udriver  = usb_generic_driver;
	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
	struct usb_device *udev = to_usb_device(dev);

	error = udriver->probe(udev);
}

2.3 generic_probe()函数

static int generic_probe(struct usb_device *udev)
{
	int err, c;
	//获取coniguration
	c = usb_choose_configuration(udev);
	err = usb_set_configuration(udev, c);
	/* USB device state == configured ... usable */
	usb_notify_add_device(udev);
	return 0;
}
int usb_set_configuration(struct usb_device *dev, int configuration)
{
	int i, ret;
	struct usb_host_config *cp = NULL;
	struct usb_interface **new_interfaces = NULL;
	struct usb_hcd *hcd = bus_to_hcd(dev->bus);
	int n, nintf;

	n = nintf = 0;
	if (cp) {
		nintf = cp->desc.bNumInterfaces;
		new_interfaces = kmalloc_array(nintf, sizeof(*new_interfaces), GFP_NOIO);

		for (; n < nintf; ++n) 
			new_interfaces[n] = kzalloc(sizeof(struct usb_interface),GFP_NOIO);

	}	
	for (i = 0; i < nintf; ++i) {
		struct usb_interface_cache *intfc;
		struct usb_interface *intf;
		struct usb_host_interface *alt;
		u8 ifnum;

		cp->interface[i] = intf = new_interfaces[i];
		intfc = cp->intf_cache[i];
		intf->altsetting = intfc->altsetting;
		intf->num_altsetting = intfc->num_altsetting;
		intf->authorized = !!HCD_INTF_AUTHORIZED(hcd);

		ifnum = alt->desc.bInterfaceNumber;
		intf->intf_assoc = find_iad(dev, cp, ifnum);
		intf->cur_altsetting = alt;
		usb_enable_interface(dev, intf, true);
		intf->dev.parent = &dev->dev;

		intf->dev.driver = NULL;
		intf->dev.bus = &usb_bus_type;
		intf->dev.type = &usb_if_device_type;
		intf->dev.groups = usb_interface_groups;

		intf->dev.dma_mask = dev->dev.dma_mask;
		intf->dev.dma_pfn_offset = dev->dev.dma_pfn_offset;
		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
		device_initialize(&intf->dev);
	}

	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
			      			NULL, 0, USB_CTRL_SET_TIMEOUT);
	if (!cp) {
		usb_set_device_state(dev, USB_STATE_ADDRESS);
	}
	usb_set_device_state(dev, USB_STATE_CONFIGURED);

	for (i = 0; i < nintf; ++i) {
		struct usb_interface *intf = cp->interface[i];
		ret = device_add(&intf->dev);
	}
	return 0;
}

我们直接看usb_set_configuration函数. 从Spec 能够可以知道HUB有1个configuration, 至少1个interface.所以最后调到device_add()中. 然后调到usb_device_match中,然后调用is_usb_interface()usb_match_id(), 而此时满足条件的驱动只有usb_probe_interface().

2.4 usb_probe_interface()函数

static int usb_probe_interface(struct device *dev)
{
	//#define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
	//想想这个地方,如果device是hub,为什么会得到hub_driver?
	//首先在usb_register(&hub_driver)注册中,就会取得hub_driver相应的地址,
	//然后用	hub_driver内部的drvwrap注册,
	//然后hub intf 和 hub driver, 通过usb_match_id(),得到的是hub_driver
	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;
	
	/* 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);
}

由于usb interface 是hub, 所以to_usb_driver(), 就会取得hub_driver, 然后driver->probe(...)就会调用hub_probe()来初始化hub.

USB驱动分析(一)总结

  • 初始化xHCI, 对其参数初始化,并且初始化Root Hub。
  • 初始化Root Hub, 首先把Root Hub当作usb 设备,调用device驱动的wrapper函数usb_probe_device(), 然后调用其中generic_probe来初始化interface,然后调用interface驱动的wrapper中函数usb_probe_interface(),然后调用Root hub自己的驱动hub_probe()

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值