USB——usb root hub注册 - awokezhou/LinuxPage GitHub Wiki

usb root hub 注册

在usb host controller driver 初始化文章中,通过对其hcd添加过程进行分析,发现添加过程做了很多事情,大概有这么几件事情比较重要

  • 为root hub数据结构分配内存空间

  • 初始化root hub的0号端点

  • 设置root hub的父设备为hcd,并将hcd->self->root_hub指针指向root hub设备,以关联hcd和root hub

  • hcd reset

  • 注册hcd的中断服务例程

  • hcd start

  • 注册root hub

这几件事情的执行顺序和逻辑如下图所示

以下对root hub的注册过程进行详细分析,搞清楚root hub注册过程中代码的执行逻辑,以及root hub在系统运行过程中的作用

register_root_hub函数分析

root hub注册函数的入口是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;
	memset (&usb_dev->bus->devmap.devicemap, 0,
			sizeof usb_dev->bus->devmap.devicemap);
	set_bit (devnum, usb_dev->bus->devmap.devicemap);
	usb_set_device_state(usb_dev, USB_STATE_ADDRESS);

	mutex_lock(&usb_bus_list_lock);

	usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
	if (retval != sizeof usb_dev->descriptor) {
		mutex_unlock(&usb_bus_list_lock);
		dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
				dev_name(&usb_dev->dev), retval);
		return (retval < 0) ? retval : -EMSGSIZE;
	}

	retval = usb_new_device (usb_dev);
	if (retval) {
		dev_err (parent_dev, "can't register root hub for %s, %d\n",
				dev_name(&usb_dev->dev), retval);
	}
	mutex_unlock(&usb_bus_list_lock);

	if (retval == 0) {
		spin_lock_irq (&hcd_root_hub_lock);
		hcd->rh_registered = 1;
		spin_unlock_irq (&hcd_root_hub_lock);

		/* Did the HC die before the root hub was registered? */
		if (hcd->state == HC_STATE_HALT)
			usb_hc_died (hcd);	/* This time clean up */
	}

	return retval;
}

指针usb_dev指向hcd->self->root_hub,前面分析过,就是root hub设备。指定root hub的设备号为1,总线的下一个设备号为2,猜测如果总线上有其他设备添加上来,设备号就依次加1去分配。这里对一个数据结构devmap进行了初始化,这个结构代表什么含义呢?该结构的定义为

/* USB device number allocation bitmap */
struct usb_devmap {
	unsigned long devicemap[128 / (8*sizeof(unsigned long))];
};

定义看起来很奇怪,定义了一个数组,但是数组的长度是多少呢?

假设unsigned long占4个字节,那么数组的每个成员占4个字节,共有128/(84)=4个成员,所有成员共44=16个字节,也就是128bit;

假设unsigned long占8个字节,那么数组的每个成员占8个字节,共有128/(88)=2个成员,所有成员共82=16个字节,也就是128bit。

所以这里其实是定义了128个bit位,这128个bit位代表的是总线上的所有usb设备,因为USB标准规定在一条usb总线上最多可以存在128个设备,devmap就是用来对设备进行一些记录的。代码中调用了set_bit()对devmap进行了设置,因为devnum的值是1,所以现在devmap的值是0x1,也就是最低位为1。这样的操作说明在usb驱动中,并没有把usb host controller设备当作usb总线上的成员,而根集线器是usb总线上的第一个成员。

调用usb_set_device_state()将root hub的状态设置为USB_STATE_ADDRESS。设置0号端点的最大包大小为64字节。然后调用usb_get_device_descriptor()获取设备描述信息,这里关于设备信息获取的部分,因为其实现比较复杂,后续会专门写一篇文章来分析,现在暂且不深入研究。

然后调用了usb_new_device(),下面进入这个函数

usb_new_device

int usb_new_device(struct usb_device *udev)
{
	int err;

	/* Increment the parent's count of unsuspended children */
	if (udev->parent)
		usb_autoresume_device(udev->parent);

	usb_detect_quirks(udev);
	err = usb_enumerate_device(udev);	/* Read descriptors */
	if (err < 0)
		goto fail;
	dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",
			udev->devnum, udev->bus->busnum,
			(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
	/* export the usbdev device-node for libusb */
	udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
			(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));

	/* Tell the world! */
	announce_device(udev);

	/* 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);
	if (err) {
		dev_err(&udev->dev, "can't device_add, error %d\n", err);
		goto fail;
	}

	(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
	return err;

fail:
	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
	usb_stop_pm(udev);
	return err;
}

首先判断了其usb父设备是否存在,以前分析过root hub没有父usb设备,只有父device设备是hcd,所以这个判断后的函数不会执行。下一步调用了usb_enumerate_device()函数,我们来看看

static int usb_enumerate_device(struct usb_device *udev)
{
	int err;

	if (udev->config == NULL) {
		err = usb_get_configuration(udev);
		if (err < 0) {
			dev_err(&udev->dev, "can't read configurations, error %d\n",
				err);
			goto fail;
		}
	}
	if (udev->wusb == 1 && udev->authorized == 0) {
		udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
		udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
		udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
	}
	else {
		/* read the standard strings and cache them if present */
		udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
		udev->manufacturer = usb_cache_string(udev,
						      udev->descriptor.iManufacturer);
		udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
	}
	err = usb_enumerate_device_otg(udev);
fail:
	return err;
}

第一步判断root hub的config指针是否为空,如果为空执行usb_get_configuration()。因为root hub结构体分配后并没有对config指针赋值过,所以肯定为空。进入usb_get_configuration()函数看看

int usb_get_configuration(struct usb_device *dev)
{
	struct device *ddev = &dev->dev;
	int ncfg = dev->descriptor.bNumConfigurations;
	int result = 0;
	unsigned int cfgno, length;
	unsigned char *buffer;
	unsigned char *bigbuffer;
	struct usb_config_descriptor *desc;

	cfgno = 0;
	if (dev->authorized == 0)	/* Not really an error */
		goto out_not_authorized;
	result = -ENOMEM;
	if (ncfg > USB_MAXCONFIG) {
		dev_warn(ddev, "too many configurations: %d, "
		    "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
		dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
	}

	if (ncfg < 1) {
		dev_err(ddev, "no configurations\n");
		return -EINVAL;
	}

	length = ncfg * sizeof(struct usb_host_config);
	dev->config = kzalloc(length, GFP_KERNEL);
	if (!dev->config)
		goto err2;

	length = ncfg * sizeof(char *);
	dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
	if (!dev->rawdescriptors)
		goto err2;

	buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
	if (!buffer)
		goto err2;
	desc = (struct usb_config_descriptor *)buffer;

	result = 0;
	for (; cfgno < ncfg; cfgno++) {
		/* We grab just the first descriptor so we know how long
		 * the whole configuration is */
		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
		    buffer, USB_DT_CONFIG_SIZE);
		if (result < 0) {
			dev_err(ddev, "unable to read config index %d "
			    "descriptor/%s: %d\n", cfgno, "start", result);
			dev_err(ddev, "chopping to %d config(s)\n", cfgno);
			dev->descriptor.bNumConfigurations = cfgno;
			break;
		} else if (result < 4) {
			dev_err(ddev, "config index %d descriptor too short "
			    "(expected %i, got %i)\n", cfgno,
			    USB_DT_CONFIG_SIZE, result);
			result = -EINVAL;
			goto err;
		}
		length = max((int) le16_to_cpu(desc->wTotalLength),
		    USB_DT_CONFIG_SIZE);

		/* Now that we know the length, get the whole thing */
		bigbuffer = kmalloc(length, GFP_KERNEL);
		if (!bigbuffer) {
			result = -ENOMEM;
			goto err;
		}
		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
		    bigbuffer, length);
		if (result < 0) {
			dev_err(ddev, "unable to read config index %d "
			    "descriptor/%s\n", cfgno, "all");
			kfree(bigbuffer);
			goto err;
		}
		if (result < length) {
			dev_warn(ddev, "config index %d descriptor too short "
			    "(expected %i, got %i)\n", cfgno, length, result);
			length = result;
		}

		dev->rawdescriptors[cfgno] = bigbuffer;

		result = usb_parse_configuration(&dev->dev, cfgno,
		    &dev->config[cfgno], bigbuffer, length);
		if (result < 0) {
			++cfgno;
			goto err;
		}
	}
	result = 0;

err:
	kfree(buffer);
out_not_authorized:
	dev->descriptor.bNumConfigurations = cfgno;
err2:
	if (result == -ENOMEM)
		dev_err(ddev, "out of memory\n");
	return result;
}

首先判断authorized是否为0,因为在root hub分配过程中对authorized成员有过赋值,且值为1,所以该条件满足。然后经过了一些简单的判断后,调用kzalloc()为config成员分配内存空间,然后循环设备的所有配置,获取配置描述信息,并用rawdescriptors[]数组指针记录。这里的获取配置描述信息同上面的获取设备描述符信息,先不深究,只用知道是通过一个通道从设备端读出来的就行了。下一步对于每一个配置,调用了usb_parse_configuration()函数,对配置进行解析,后面代码先不进行分析了。主要就是读取接口和端点的信息,然后对root hub相关结构体进行赋值和空间分配。

最重要的步骤来了,调用了device_add()向系统注册设备,调用usb_create_ep_devs()注册端点设备。注意注册的设备是root hub的device设备,前面分析usb core初始化的时候说过,hub驱动注册过的,此时注册了root hub设备,那么驱动的probe函数会被调用。

root hub probe

首先会被调用的接口是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;

	dev_dbg(dev, "%s\n", __func__);

	intf->needs_binding = 0;

	if (usb_device_is_owned(udev))
		return -ENODEV;

	if (udev->authorized == 0) {
		dev_err(&intf->dev, "Device is not authorized for usage\n");
		return -ENODEV;
	}

	id = usb_match_id(intf, driver->id_table);
	if (!id)
		id = usb_match_dynamic_id(intf, driver);
	if (id) {
		dev_dbg(dev, "%s - got id\n", __func__);

		error = usb_autoresume_device(udev);
		if (error)
			return error;

		/* Interface "power state" doesn't correspond to any hardware
		 * state whatsoever.  We use it to record when it's bound to
		 * a driver that may start I/0:  it's not frozen/quiesced.
		 */
		mark_active(intf);
		intf->condition = USB_INTERFACE_BINDING;

		/* The interface should always appear to be in use
		 * unless the driver suports autosuspend.
		 */
		atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);

		/* 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;
		usb_autosuspend_device(udev);
	}

	return error;

err:
	mark_quiesced(intf);
	intf->needs_remote_wakeup = 0;
	intf->condition = USB_INTERFACE_UNBOUND;
	usb_cancel_queued_reset(intf);
	usb_autosuspend_device(udev);
	return error;
}