root hub设备注册(三)

本文是基于mini2440开发板Linux版本号是linux-2.6.32.2的学习笔记

一. 申请并初始化root hub设备
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 = container_of(bus, struct usb_hcd, self);
	unsigned root_hub = 0;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return NULL;
	//增加主控制器的引用计数
	if (!usb_get_hcd(bus_to_hcd(bus))) {
		kfree(dev);
		return NULL;
	}
	/* Root hubs aren't true devices, so don't allocate HCD resources */
	if (usb_hcd->driver->alloc_dev && parent &&
		!usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
		usb_put_hcd(bus_to_hcd(bus));
		kfree(dev);
		return NULL;
	}

	device_initialize(&dev->dev);
	dev->dev.bus = &usb_bus_type;
	dev->dev.type = &usb_device_type;
	dev->dev.groups = usb_device_groups;
	//主控器能否进行DMA传输
	dev->dev.dma_mask = bus->controller->dma_mask;
	set_dev_node(&dev->dev, dev_to_node(bus->controller));
	//表示设备已经连接到usb接口上,是hub检测到设备时的初始状态
	dev->state = USB_STATE_ATTACHED;
	atomic_set(&dev->urbnum, 0);

	INIT_LIST_HEAD(&dev->ep0.urb_list);
	//端点0需要特殊化处理
	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
	/* ep0 maxpacket comes later, from device descriptor */
	//端点0是双向的,既可以收也可以发.所以对它,我们需要以ep_in[0]和ep_out[0]来记录.
	usb_enable_endpoint(dev, &dev->ep0, false);
	dev->can_submit = 1;

	/* Save readable and stable topology id, distinguishing devices
	 * by location for diagnostics, tools, driver model, etc.  The
	 * string is a path along hub ports, from the root.  Each device's
	 * dev->devpath will be stable until USB is re-cabled, and hubs
	 * are often labeled with these port numbers.  The name isn't
	 * as stable:  bus->busnum changes easily from modprobe order,
	 * cardbus or pci hotplugging, and so on.
	 */
	 //如果是root hub,name设置为usb0
	if (unlikely(!parent)) {
		dev->devpath[0] = '0';
		dev->route = 0;

		dev->dev.parent = bus->controller;
		dev_set_name(&dev->dev, "usb%d", bus->busnum);
		root_hub = 1;
	} else {
		/* match any labeling on the hubs; it's one-based */
		//设备连接的那个hub是直接连到root hub上的,则dev->devpath就等于端口号
		if (parent->devpath[0] == '0') {
			snprintf(dev->devpath, sizeof dev->devpath,
				"%d", port1);
			/* Root ports are not counted in route string */
			dev->route = 0;
		} else { //dev->devpath就等于在父hub的devpath基础上加一个‘.’再加一个端口号
			snprintf(dev->devpath, sizeof dev->devpath,
				"%s.%d", parent->devpath, port1);
			/* Route string assumes hubs have less than 16 ports */
			if (port1 < 15)
				dev->route = parent->route +
					(port1 << ((parent->level - 1)*4));
			else
				dev->route = parent->route +
					(15 << ((parent->level - 1)*4));
		}

		dev->dev.parent = &parent->dev;
		//名字设置,例如为0-2.2
		dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);

		/* hub driver sets up TT records */
	}

	dev->portnum = port1;
	dev->bus = bus;
	dev->parent = parent;
	//usbfs用到
	INIT_LIST_HEAD(&dev->filelist);

#ifdef	CONFIG_PM
	mutex_init(&dev->pm_mutex);
	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
	//设置延时调用函数usb_autoresume_work
	INIT_WORK(&dev->autoresume, usb_autoresume_work);
	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
	dev->connect_time = jiffies;
	dev->active_duration = -jiffies;
#endif
	if (root_hub)	/* Root hub always ok [and always wired] */ //root hub的值为1
		dev->authorized = 1;
	else {
		//取决于设备链接的那个hub的authorized_default的值
		dev->authorized = usb_hcd->authorized_default;
		dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
	}
	return dev;
}
  • 申请usb设备内存
    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  • usb设备的初始化
二. 注册root hub设备

调用函数register_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;
	//将root hub的设备号devnum设置为1
	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);
	//将root hub的状态设置为USB_STATE_ADDRESS
	usb_set_device_state(usb_dev, USB_STATE_ADDRESS);

	mutex_lock(&usb_bus_list_lock);
	//将root hub端口0的最大字符长度设置为64
	usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
	//获取root hub的设备描述符,长度是18个字节
	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);
		//root hub 已经注册了
		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;
}
  • root hub的设备编号设置为1;
  • set_bit (devnum, usb_dev->bus->devmap.devicemap),这个函数的意思把devmap.devicemap的第一位设置为1,表明这一位已经有设备占了,没有占的用0表示。devmap.devicemap最多可以标记128个设备。
  • 将root hub设备的状态设置为USB_STATE_ADDRESS,表明这个设备已经有地址了。
void usb_set_device_state(struct usb_device *udev, enum usb_device_state new_state)
{
	unsigned long flags;

	spin_lock_irqsave(&device_state_lock, flags);
	//设备已经断开了,啥都不做
	if (udev->state == USB_STATE_NOTATTACHED)
		;	/* do nothing */
	else if (new_state != USB_STATE_NOTATTACHED) {

		/* root hub wakeup capabilities are managed out-of-band
		 * and may involve silicon errata ... ignore them here.
		 */
		//如果是root hub 不走这里
		if (udev->parent) {
			//如果原来的状态是USB_STATE_SUSPENDED,现在设置的状态也是USB_STATE_SUSPENDED,什么都不做
			if (udev->state == USB_STATE_SUSPENDED
					|| new_state == USB_STATE_SUSPENDED)
				;	/* No change to wakeup settings */
			//如果设置的状态是USB_STATE_CONFIGURED,调用device_init_wakeup函数
			//bmAttributes,的D5表明的就是一个USB设备是否具有被唤醒的能力(USB_CONFIG_ATT_WAKEUP = 1<<5)
			else if (new_state == USB_STATE_CONFIGURED)
				device_init_wakeup(&udev->dev,
					(udev->actconfig->desc.bmAttributes
					 & USB_CONFIG_ATT_WAKEUP));
			//先不打开这个设备的wakeup能力
			else
				device_init_wakeup(&udev->dev, 0);
		}
		if (udev->state == USB_STATE_SUSPENDED &&
			new_state != USB_STATE_SUSPENDED)
			udev->active_duration -= jiffies;
		else if (new_state == USB_STATE_SUSPENDED &&
				udev->state != USB_STATE_SUSPENDED)
			udev->active_duration += jiffies;
		udev->state = new_state;
	} else //原来的状态不是USB_STATE_NOTATTACHED而现在要设置成USB_STATE_NOTATTACHED
		recursively_mark_NOTATTACHED(udev); //递归的把各设备都设置成NOTATTACHED状态
	spin_unlock_irqrestore(&device_state_lock, flags);
}
  • 将root hub端口0的最大字符长度设置为64
    usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);cpu_to_le16这个函数是把一个数字转化成小端存放在内存中,因为usb的描述符都是按照小端存储的。

  • 获取root hub的设备描述符,长度是18个字节
    retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);

int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
{
	……
	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
	if (ret >= 0)
		memcpy(&dev->descriptor, desc, size);
}

int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
{
	int i;
	int result;

	memset(buf, 0, size);	/* Make sure we parse really received data */

	for (i = 0; i < 3; ++i) {
		/* retry on length 0 or error; some devices are flakey */
		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
				(type << 8) + index, 0, buf, size,
				USB_CTRL_GET_TIMEOUT);
		if (result <= 0 && result != -ETIMEDOUT)
			continue;
		if (result > 1 && ((u8 *)buf)[1] != type) {
			result = -ENODATA;
			continue;
		}
		break;
	}
	return result;
}

上面通过usb_control_msg函数获取设备描述符,循环了三次,以防有的设备一次不能成功。
看一下usb_control_msg函数的原型:

int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data,__u16 size, int timeout)

dev:usb设备
pipe:管道
管道有8种类型:
usb_sndctrlpipe(dev,endpoint)=((2 << 30) | (dev->devnum << 8) | (endpoint << 15)
usb_rcvctrlpipe(dev,endpoint) =((2 << 30) | (dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN)
usb_sndisocpipe(dev,endpoint)=((0 << 30) | (dev->devnum << 8) | (endpoint << 15)
usb_rcvisocpipe(dev,endpoint)=((0 << 30) | (dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN)
usb_sndbulkpipe(dev,endpoint)=((3 << 30) | (dev->devnum << 8) | (endpoint << 15)
usb_rcvbulkpipe(dev,endpoint)=((3 << 30) |(dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN)
usb_sndintpipe(dev,endpoint) =((1 << 30) | (dev->devnum << 8) | (endpoint << 15)
usb_rcvintpipe(dev,endpoint)=((1 << 30) | (dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN)

request:
表示具体是哪个request,如下
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C

requesttype:
bit7就表示了控制传输中DATA transaction阶段的方向
#define USB_DIR_OUT 0 /* to device /
#define USB_DIR_IN 0x80 /
to host */
bit5~6表示request的类型,是标准的,class-specific的还是vendor-specific的
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
bit0~4表示了这个请求针对的是设备,接口,还是端点
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03

value:
这个字段是request的参数,request不同,wValue就不同

index:
bRequestType指明request针对的是设备上的某个接口或端点的时候,wIndex就用来指明是哪个接口或端点

data:
请求buffer

size:
请求buffer的大小

timeout:
请求超时时间

int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,__u8 requesttype, __u16 value, __u16 index, void *data,
		    __u16 size, int timeout)
{
	struct usb_ctrlrequest *dr;
	int ret;
	//为一个struct usb_ctrlrequest结构体申请了内存
	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
	if (!dr)
		return -ENOMEM;
	//bit7就表示了控制传输中DATA transaction阶段的方向
	//bit5~6表示request的类型,是标准的,class-specific的还是vendor-specific的
	//bit0~4表示了这个请求针对的是设备,接口,还是端点
	dr->bRequestType = requesttype;
	//表示具体是哪个request
	//对于刚开始提到的SET_ADDRESS来说,bRequest的值就是USB_REQ_SET_ADDRESS
	dr->bRequest = request;
	//这个字段是request的参数,request不同,wValue就不同
	//对于刚开始提到的SET_ADDRESS,wValue就是之前hub已经你的设备指定好的devnum
	dr->wValue = cpu_to_le16(value);
	//也是request的参数,bRequestType指明request针对的是设备上的某个接口或端点的时候,wIndex就用来指明是哪个接口或端点
	dr->wIndex = cpu_to_le16(index);
	//控制传输中DATA transaction阶段的长度,方向已经在bRequestType那儿指明了。如果这个值为0,
	//就表示没有DATA transaction阶段,bRequestType的方向位也就无效了
	dr->wLength = cpu_to_le16(size);

	/* dbg("usb_control_msg"); */

	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);

	kfree(dr);

	return ret;
}

上面的函数调用usb_internal_control_msg函数

static int usb_internal_control_msg(struct usb_device *usb_dev,unsigned int pipe, struct usb_ctrlrequest *cmd, void *data, int len, int timeout)
{
	struct urb *urb;
	int retv;
	int length;
	//创建一个urb
	urb = usb_alloc_urb(0, GFP_NOIO);
	if (!urb)
		return -ENOMEM;
	//初始化一个控制urb,urb被创建之后,使用之前必须要正确的初始化
	usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
			     len, usb_api_blocking_completion, NULL);
	//将urb提交给咱们的usb core,以便分配给特定的主机控制器驱动进行处理,然后默默的等待处理结果,或者超时
	retv = usb_start_wait_urb(urb, timeout, &length);
	if (retv < 0)
		return retv;
	else
		return length;
}

调用usb_start_wait_urb函数

static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
{
	//ctx.completion是内核里一个比较简单的同步机制,一个线程可以通过它来通知另外一个线程某件事情已经做完了
	struct api_context ctx;
	unsigned long expire;
	int retval;

	init_completion(&ctx.done);
	urb->context = &ctx;
	urb->actual_length = 0;
	//提交urb,并返回一个值表示是否提交成功了
	retval = usb_submit_urb(urb, GFP_NOIO);
	if (unlikely(retval))
		goto out;
	//函数wait_for_completion_timeout里的超时参数是必须以jiffy为单位的
	expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
	//设定一个超时时间,等候usb core和HCD的处理结果。
	//urb代表的控制传输完成之后会调用结束处理函数usb_api_blocking_completion,
	//从而调用complete来通知usb_start_wait_urb说不用再等了,传输已经完成了
	if (!wait_for_completion_timeout(&ctx.done, expire)) {
		usb_kill_urb(urb);
		retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);

		dev_dbg(&urb->dev->dev,
			"%s timed out on ep%d%s len=%u/%u\n",
			current->comm,
			usb_endpoint_num(&urb->ep->desc),
			usb_urb_dir_in(urb) ? "in" : "out",
			urb->actual_length,
			urb->transfer_buffer_length);
	} else
		retval = ctx.status;
out:
	if (actual_length)
		//用来记录实际传输的数据长度
		*actual_length = urb->actual_length;

	usb_free_urb(urb);
	return retval;
}

调用usb_start_wait_urb函数提交一个urb到hcd,没有阻塞,直接返回。然后wait_for_completion_timeout函数来等待。
usb_fill_control_urb函数中,将usb_api_blocking_completion设置为urb的complete函数。urb代表的控制传输完成之后会调用结束处理函数usb_api_blocking_completion,usb_api_blocking_completion函数中将tx->done++,wait_for_completion_timeout函数满足条件退出等待。
那么urb通过usb_submit_urb函数提交给了hcd处理。

int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
	……
	usb_hcd_submit_urb(urb, mem_flags)
		//root hub调用rh_urb_enqueue进行USB通信
		if (is_root_hub(urb->dev))
			status = rh_urb_enqueue(hcd, urb);
		//如果不是root hub,调用对应的控制器的urb_enqueue函数
		else
			status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
}

usb_submit_urb最终调用的是rh_urb_enqueue函数。

static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
{
	//如果是中断传输
	if (usb_endpoint_xfer_int(&urb->ep->desc))
		return rh_queue_status (hcd, urb);
	//如果是控制传输
	if (usb_endpoint_xfer_control(&urb->ep->desc))
		return rh_call_control (hcd, urb);
	return -EINVAL;
}

rh_urb_enqueue 调用的又是rh_call_control 函数。

static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
{
	……
	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
		switch (wValue & 0xff00) {
		case USB_DT_DEVICE << 8:
			switch (hcd->driver->flags & HCD_MASK) {
			case HCD_USB3:
				bufp = usb3_rh_dev_descriptor;
				break;
			case HCD_USB2:
				bufp = usb2_rh_dev_descriptor;
				break;
			case HCD_USB11:
				bufp = usb11_rh_dev_descriptor;
				break;
			default:
				goto error;
			}
			len = 18;
			if (hcd->has_tt)
				patch_protocol = 1;
			break;
		case USB_DT_CONFIG << 8:
			switch (hcd->driver->flags & HCD_MASK) {
			case HCD_USB3:
				bufp = ss_rh_config_descriptor;
				len = sizeof ss_rh_config_descriptor;
				break;
			case HCD_USB2:
				bufp = hs_rh_config_descriptor;
				len = sizeof hs_rh_config_descriptor;
				break;
			case HCD_USB11:
				bufp = fs_rh_config_descriptor;
				len = sizeof fs_rh_config_descriptor;
				break;
			default:
				goto error;
			}
			if (device_can_wakeup(&hcd->self.root_hub->dev))
				patch_wakeup = 1;
			break;
		case USB_DT_STRING << 8:
			if ((wValue & 0xff) < 4)
				urb->actual_length = rh_string(wValue & 0xff,
						hcd, ubuf, wLength);
			else /* unsupported IDs --> "protocol stall" */
				goto error;
			break;
		default:
			goto error;
		}
		break;
}

usb3_rh_dev_descriptor,usb2_rh_dev_descriptor,ss_rh_config_descriptor等都是定义在hcd.c里面的全局变量。因为root hub是集成在主机控制器里面了,所以跟主机控制器通信获取root hub的信息实际上驱动软件里面写死了,而不是获取的硬件上的信息。

/* usb 1.1 root hub device descriptor */
static const u8 usb11_rh_dev_descriptor [18] = {
	0x12,       /*  __u8  bLength; */
	0x01,       /*  __u8  bDescriptorType; Device */
	0x10, 0x01, /*  __le16 bcdUSB; v1.1 */

	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
	0x00,	    /*  __u8  bDeviceSubClass; */
	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */

	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
	0x01, 0x00, /*  __le16 idProduct; device 0x0001 */
	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */

	0x03,       /*  __u8  iManufacturer; */
	0x02,       /*  __u8  iProduct; */
	0x01,       /*  __u8  iSerialNumber; */
	0x01        /*  __u8  bNumConfigurations; */
};
static const u8 ss_rh_config_descriptor[] = {
	/* one configuration */
	0x09,       /*  __u8  bLength; */
	0x02,       /*  __u8  bDescriptorType; Configuration */
	0x19, 0x00, /*  __le16 wTotalLength; FIXME */
	0x01,       /*  __u8  bNumInterfaces; (1) */
	0x01,       /*  __u8  bConfigurationValue; */
	0x00,       /*  __u8  iConfiguration; */
	0xc0,       /*  __u8  bmAttributes;
				 Bit 7: must be set,
				     6: Self-powered,
				     5: Remote wakeup,
				     4..0: resvd */
	0x00,       /*  __u8  MaxPower; */

	/* one interface */
	0x09,       /*  __u8  if_bLength; */
	0x04,       /*  __u8  if_bDescriptorType; Interface */
	0x00,       /*  __u8  if_bInterfaceNumber; */
	0x00,       /*  __u8  if_bAlternateSetting; */
	0x01,       /*  __u8  if_bNumEndpoints; */
	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
	0x00,       /*  __u8  if_bInterfaceSubClass; */
	0x00,       /*  __u8  if_bInterfaceProtocol; */
	0x00,       /*  __u8  if_iInterface; */

	/* one endpoint (status change endpoint) */
	0x07,       /*  __u8  ep_bLength; */
	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
		    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
		     * see hub.c:hub_configure() for details. */
	(USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
	0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
	/*
	 * All 3.0 hubs should have an endpoint companion descriptor,
	 * but we're ignoring that for now.  FIXME?
	 */
};

根据上面的描述信息,可以得到:
root hub只有一种配置,一个接口,一种设置,一个端口;
DeviceClass = 0x9;
InterfaceClass = 0x09;
配置描述符的总长度是25;
设备描述符的长度是18;
最终得到的设备描述符信息保存在dev->descriptor结构体中。

  • 创建新的usb device设备
    retval = usb_new_device (usb_dev);
int usb_new_device(struct usb_device *udev)
{
	int err;

	/* Increment the parent's count of unsuspended children */
	//如果该设备不是Root Hub,则调用usb_autoresume_device(),唤醒它的父设备
	if (udev->parent)
		usb_autoresume_device(udev->parent);
	//usb_detect_quirks会为在黑名单中找得到的设备的struct usb_device结构体中的quirks赋值
	usb_detect_quirks(udev);		/* Determine quirks */
	//获得配置描述符
	err = usb_configure_device(udev);	/* detect & probe dev/intfs */
	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 */
	//minor=((dev->bus->busnum-1)*128)+(dev->devnum-1);
	//USB_DEVICE_MAJOR = 189
	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_configure_device函数

static int usb_configure_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_configure_device_otg(udev);
fail:
	return err;
}

usb_configure_device函数调用usb_get_configuration获取配置信息。根据设备描述符知道有多少个配置。然后for循环,读取每一个配置描述符。在配置描述符里面有一个成员wTotalLength,它表示配置信息的总长(包括配置,接口,端点和设备类及厂商定义的描述符)。有了这个长度,我们可以把所有的配置信息全部读出来。读出来后,我们可以知道每个配置里面有几个接口,每个接口里面有几个设置,每个设置里面有几个端口,挨个挨个去解析,然后把解析出来的信息保存起来。

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;
	}
	//申请内存,存放ncfg个配置
	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;

	//因为usb_config_descriptor的长度是9,申请9个字节的buffer存放usb_config_descriptor
	buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
	if (!buffer)
		goto err2;
	desc = (struct usb_config_descriptor *)buffer;

	result = 0;
	//循环读出ncfg个config
	for (; cfgno < ncfg; cfgno++) {
		/* We grab just the first descriptor so we know how long
		 * the whole configuration is */
		//读取config文件,类型是USB_DT_CONFIG,长度是9个字节
		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) {  //为什么是小于4呢,因为wTotalLength所在的位置刚好是第四个字节,
								  //把wTotalLength读出来了后面的都可以出来
			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);
		 
		//length是所有描述符的总长度,申请buffer
		/* Now that we know the length, get the whole thing */
		bigbuffer = kmalloc(length, GFP_KERNEL);
		if (!bigbuffer) {
			result = -ENOMEM;
			goto err;
		}
		//获取config描述符获取后面所有的描述符数据
		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;
}

解析读出来的描述符信息,调用函数usb_parse_configuration

static int usb_parse_configuration(struct device *ddev, int cfgidx, struct usb_host_config *config, 
unsigned char *buffer, int size)
{
	unsigned char *buffer0 = buffer;
	int cfgno;
	int nintf, nintf_orig;
	int i, j, n;
	struct usb_interface_cache *intfc;
	unsigned char *buffer2;
	int size2;
	struct usb_descriptor_header *header;
	int len, retval;
	u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
	unsigned iad_num = 0;

	memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
	//做一些参数判断,desc.bDescriptorType = 2, desc.bLength = 9
	if (config->desc.bDescriptorType != USB_DT_CONFIG ||
		config->desc.bLength < USB_DT_CONFIG_SIZE) {
		dev_err(ddev, "invalid descriptor for config index %d: "
			"type = 0x%X, length = %d\n", cfgidx,
			config->desc.bDescriptorType, config->desc.bLength);
		return -EINVAL;
	}
	//保存当前配置的配置号
	cfgno = config->desc.bConfigurationValue;
	//usb_config_descriptor解析完了,跳过usb_config_descriptor去解析后面的数据
	buffer += config->desc.bLength;
	size -= config->desc.bLength;

	//获取usb_config_descriptor里面包含几个usb_interface_descriptor,最多可以有32个
	nintf = nintf_orig = config->desc.bNumInterfaces;
	if (nintf > USB_MAXINTERFACES) {
		dev_warn(ddev, "config %d has too many interfaces: %d, "
			"using maximum allowed: %d\n",
			cfgno, nintf, USB_MAXINTERFACES);
		nintf = USB_MAXINTERFACES;
	}

	/* Go through the descriptors, checking their length and counting the
	 * number of altsettings for each interface */
	n = 0;
	//统计一下这个配置里每个接口所拥有的设置数目
	for ((buffer2 = buffer, size2 = size);
		  size2 > 0;
		 (buffer2 += header->bLength, size2 -= header->bLength)) {

		if (size2 < sizeof(struct usb_descriptor_header)) {
			dev_warn(ddev, "config %d descriptor has %d excess "
				"byte%s, ignoring\n",
				cfgno, size2, plural(size2));
			break;
		}

		header = (struct usb_descriptor_header *) buffer2;
		if ((header->bLength > size2) || (header->bLength < 2)) {
			dev_warn(ddev, "config %d has an invalid descriptor "
				"of length %d, skipping remainder of the config\n",
				cfgno, header->bLength);
			break;
		}

		//某个接口拥有一个设置,是没有设置描述符
		if (header->bDescriptorType == USB_DT_INTERFACE) {
			struct usb_interface_descriptor *d;
			int inum;
			//header代表的就是usb_interface_descriptor
			d = (struct usb_interface_descriptor *) header;
			if (d->bLength < USB_DT_INTERFACE_SIZE) {
				dev_warn(ddev, "config %d has an invalid "
					"interface descriptor of length %d, "
					"skipping\n", cfgno, d->bLength);
				continue;
			}
			//usb_interface_descriptorde的索引值,不是表示个数
			inum = d->bInterfaceNumber;
			if (inum >= nintf_orig)
				dev_warn(ddev, "config %d has an invalid "
					"interface number: %d but max is %d\n",
					cfgno, inum, nintf_orig - 1);

			/* Have we already encountered this interface?
			 * Count its altsettings */
			//把索引值inum保存在inums数组里面
			for (i = 0; i < n; ++i) {
				if (inums[i] == inum)
					break;
			}
			if (i < n) {
				if (nalts[i] < 255)
					++nalts[i];
			} else if (n < USB_MAXINTERFACES) {
				//记录一个接口号
				inums[n] = inum;
				//记录的是每个接口拥有的设置数目
				nalts[n] = 1;
				++n;
			}

		} else if (header->bDescriptorType ==
				USB_DT_INTERFACE_ASSOCIATION) {
			if (iad_num == USB_MAXIADS) {
				dev_warn(ddev, "found more Interface "
						   "Association Descriptors "
						   "than allocated for in "
						   "configuration %d\n", cfgno);
			} else {
				config->intf_assoc[iad_num] =
					(struct usb_interface_assoc_descriptor
					*)header;
				iad_num++;
			}

		} else if (header->bDescriptorType == USB_DT_DEVICE ||
				header->bDescriptorType == USB_DT_CONFIG)
			dev_warn(ddev, "config %d contains an unexpected "
				"descriptor of type 0x%X, skipping\n",
				cfgno, header->bDescriptorType);

	}	/* for ((buffer2 = buffer, size2 = size); ...) */
	//在上面的循环中,过滤掉了错误的数据,得到实际上有效的长度size,desc.wTotalLength
	size = buffer2 - buffer;
	config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);

	//得到的usb_interface_descriptor的个数应该等于usb_config_descriptor.bNumInterfaces,不相等的话是有问题的
	if (n != nintf)
		dev_warn(ddev, "config %d has %d interface%s, different from "
			"the descriptor's value: %d\n",
			cfgno, n, plural(n), nintf_orig);
	//如果没有找到usb_interface_descriptor,也是有问题的
	else if (n == 0)
		dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
	
	config->desc.bNumInterfaces = nintf = n;

	/* Check for missing interface numbers */
	for (i = 0; i < nintf; ++i) {
		for (j = 0; j < nintf; ++j) {
			if (inums[j] == i)
				break;
		}
		if (j >= nintf)
			dev_warn(ddev, "config %d has no interface number "
				"%d\n", cfgno, i);
	}

	/* Allocate the usb_interface_caches and altsetting arrays */
	for (i = 0; i < nintf; ++i) {
		j = nalts[i];
		if (j > USB_MAXALTSETTING) {
			dev_warn(ddev, "too many alternate settings for "
				"config %d interface %d: %d, "
				"using maximum allowed: %d\n",
				cfgno, inums[i], j, USB_MAXALTSETTING);
			nalts[i] = j = USB_MAXALTSETTING;
		}
		//为每一个interface申请内存,内存大小为sizeof(*intfc) + n个usb_host_interface,
		//intfc.altsetting[0]是第一个usb_host_interface的地址
		len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
		config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
		if (!intfc)
			return -ENOMEM;
		kref_init(&intfc->ref);
	}

	/* FIXME: parse the BOS descriptor */

	/* Skip over any Class Specific or Vendor Specific descriptors;
	 * find the first interface descriptor */
	config->extra = buffer;
	//找到第一个usb_interface_descriptor出现的位置,上面的只是为了统计usb_interface_descriptor的个数
	i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
		USB_DT_INTERFACE, &n);
	config->extralen = i;
	if (n > 0)
		dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
			n, plural(n), "configuration");
	//buffer指针跳到第一个usb_interface_descriptor出现的位置
	buffer += i;
	size -= i;

	/* Parse all the interface/altsetting descriptors */
	//解析所有的 interface/altsetting
	while (size > 0) {
		retval = usb_parse_interface(ddev, cfgno, config,
			buffer, size, inums, nalts);
		if (retval < 0)
			return retval;

		buffer += retval;
		size -= retval;
	}

	/* Check for missing altsettings */
	for (i = 0; i < nintf; ++i) {
		intfc = config->intf_cache[i];
		for (j = 0; j < intfc->num_altsetting; ++j) {
			for (n = 0; n < intfc->num_altsetting; ++n) {
				if (intfc->altsetting[n].desc.
					bAlternateSetting == j)
					break;
			}
			if (n >= intfc->num_altsetting)
				dev_warn(ddev, "config %d interface %d has no "
					"altsetting %d\n", cfgno, inums[i], j);
		}
	}

	return 0;
}

解析接口描述符函数usb_parse_interface

static int usb_parse_interface(struct device *ddev, int cfgno,
    struct usb_host_config *config, unsigned char *buffer, int size,
    u8 inums[], u8 nalts[])
{
	unsigned char *buffer0 = buffer;
	struct usb_interface_descriptor *d;
	int inum, asnum;
	struct usb_interface_cache *intfc;
	struct usb_host_interface *alt;
	int i, n;
	int len, retval;
	int num_ep, num_ep_orig;

	d = (struct usb_interface_descriptor *) buffer;
	//buffer指针跳过usb_interface_descriptor的长度,usb_interface_descriptor的长度为9
	buffer += d->bLength;
	size -= d->bLength;

	if (d->bLength < USB_DT_INTERFACE_SIZE)
		goto skip_to_next_interface_descriptor;

	/* Which interface entry is this? */
	intfc = NULL;
	//有可能inum[0] = 1, inum[1] = 0
	inum = d->bInterfaceNumber;
	for (i = 0; i < config->desc.bNumInterfaces; ++i) {
		if (inums[i] == inum) {
			intfc = config->intf_cache[i];
			break;
		}
	}
	if (!intfc || intfc->num_altsetting >= nalts[i])
		goto skip_to_next_interface_descriptor;

	/* Check for duplicate altsetting entries */
	asnum = d->bAlternateSetting;
	//usb_interface_descriptor接口使用的是哪个可选设置
	for ((i = 0, alt = &intfc->altsetting[0]);
		  i < intfc->num_altsetting;
		 (++i, ++alt)) {
		//说明已经解析过了,就不用解析,跳到下一个
		if (alt->desc.bAlternateSetting == asnum) {
			dev_warn(ddev, "Duplicate descriptor for config %d "
				"interface %d altsetting %d, skipping\n",
				cfgno, inum, asnum);
			goto skip_to_next_interface_descriptor;
		}
	}
	//设置个数加1
	++intfc->num_altsetting;
	//把解析出来的usb_interface_descriptor拷贝到intfc->altsetting[i].desc里面去
	memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);

	/* Skip over any Class Specific or Vendor Specific descriptors;
	 * find the first endpoint or interface descriptor */
	alt->extra = buffer;
	//这里find_next_descriptor的dt1参数和dt2参数就不再一样了,因为如果一个接口只用到端点0,
	//它的接口描述符后边儿是不会跟有端点描述符的
	i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
		USB_DT_INTERFACE, &n);
	alt->extralen = i;
	if (n > 0)
		dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
			n, plural(n), "interface");
	buffer += i;
	size -= i;

	/* Allocate space for the right(?) number of endpoints */
	//获取这个设置的端点数目
	num_ep = num_ep_orig = alt->desc.bNumEndpoints;
	alt->desc.bNumEndpoints = 0;		/* Use as a counter */
	if (num_ep > USB_MAXENDPOINTS) {
		dev_warn(ddev, "too many endpoints for config %d interface %d "
			"altsetting %d: %d, using maximum allowed: %d\n",
			cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
		num_ep = USB_MAXENDPOINTS;
	}

	if (num_ep > 0) {
		/* Can't allocate 0 bytes */
		//申请内存,申请大小为num_ep个usb_host_endpoint
		len = sizeof(struct usb_host_endpoint) * num_ep;
		alt->endpoint = kzalloc(len, GFP_KERNEL);
		if (!alt->endpoint)
			return -ENOMEM;
	}

	/* Parse all the endpoint descriptors */
	n = 0;
	while (size > 0) {
		//判断find_next_descriptor找到的地址的描述符是不是接口描述符,
		//如果是直接退出while循环,否则解析完所有的usb_host_endpoint
		if (((struct usb_descriptor_header *) buffer)->bDescriptorType
			 == USB_DT_INTERFACE)
			break;
		//解析usb_host_endpoint
		retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
			num_ep, buffer, size);
		if (retval < 0)
			return retval;
		++n;
		//调整buffer的位置和size大小
		buffer += retval;
		size -= retval;
	}
	//判断解析出来的usb_host_endpoint的个数,肯定要是num_ep_orig个
	if (n != num_ep_orig)
		dev_warn(ddev, "config %d interface %d altsetting %d has %d "
			"endpoint descriptor%s, different from the interface "
			"descriptor's value: %d\n",
			cfgno, inum, asnum, n, plural(n), num_ep_orig);
	return buffer - buffer0;

skip_to_next_interface_descriptor:
	i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
		USB_DT_INTERFACE, NULL);
	return buffer - buffer0 + i;
}

端口描述符解析函数usb_parse_endpoint

static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
    int asnum, struct usb_host_interface *ifp, int num_ep,
    unsigned char *buffer, int size)
{
	unsigned char *buffer0 = buffer;
	struct usb_endpoint_descriptor *d;
	struct usb_host_endpoint *endpoint;
	int n, i, j, retval;

	d = (struct usb_endpoint_descriptor *) buffer;
	//跳过usb_endpoint_descriptor的大小
	buffer += d->bLength;
	size -= d->bLength;

	//usb_endpoint_descriptor的大小7 or 9,后面多了2个字节,是对音频扩展的
	if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE)
		n = USB_DT_ENDPOINT_AUDIO_SIZE;
	else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
		n = USB_DT_ENDPOINT_SIZE;
	else {
		dev_warn(ddev, "config %d interface %d altsetting %d has an "
			"invalid endpoint descriptor of length %d, skipping\n",
			cfgno, inum, asnum, d->bLength);
		goto skip_to_next_endpoint_or_interface_descriptor;
	}
	//得到端口地址
	i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
	if (i >= 16 || i == 0) {
		dev_warn(ddev, "config %d interface %d altsetting %d has an "
			"invalid endpoint with address 0x%X, skipping\n",
			cfgno, inum, asnum, d->bEndpointAddress);
		goto skip_to_next_endpoint_or_interface_descriptor;
	}

	/* Only store as many endpoints as we have room for */
	//ifp->desc.bNumEndpoints这个值在前面被赋值成0了
	if (ifp->desc.bNumEndpoints >= num_ep)
		goto skip_to_next_endpoint_or_interface_descriptor;
	//ifp->desc.bNumEndpoints这个值在前面被赋值成0了,把发现的usb_endpoint_descriptor一个一个赋值到endpoint->desc里面去
	endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
	++ifp->desc.bNumEndpoints;
	//把发现的usb_endpoint_descriptor一个一个赋值到endpoint->desc里面去
	memcpy(&endpoint->desc, d, n);
	INIT_LIST_HEAD(&endpoint->urb_list);

	/* Fix up bInterval values outside the legal range. Use 32 ms if no
	 * proper value can be guessed. */
	i = 0;		/* i = min, j = max, n = default */
	j = 255;
	//如果是中断传输模式
	if (usb_endpoint_xfer_int(d)) {
		i = 1;
		//判断速度
		switch (to_usb_device(ddev)->speed) {
		case USB_SPEED_SUPER:
		case USB_SPEED_HIGH:
			/* Many device manufacturers are using full-speed
			 * bInterval values in high-speed interrupt endpoint
			 * descriptors. Try to fix those and fall back to a
			 * 32 ms default value otherwise. */
			n = fls(d->bInterval*8);
			if (n == 0)
				n = 9;	/* 32 ms = 2^(9-1) uframes */
			j = 16;
			break;
		default:		/* USB_SPEED_FULL or _LOW */
			/* For low-speed, 10 ms is the official minimum.
			 * But some "overclocked" devices might want faster
			 * polling so we'll allow it. */
			n = 32;
			break;
		}					   //如果是等时传输
	} else if (usb_endpoint_xfer_isoc(d)) {
		i = 1;
		j = 16;
		switch (to_usb_device(ddev)->speed) {
		case USB_SPEED_HIGH:
			n = 9;		/* 32 ms = 2^(9-1) uframes */
			break;
		default:		/* USB_SPEED_FULL */
			n = 6;		/* 32 ms = 2^(6-1) frames */
			break;
		}
	}
	if (d->bInterval < i || d->bInterval > j) {
		dev_warn(ddev, "config %d interface %d altsetting %d "
			"endpoint 0x%X has an invalid bInterval %d, "
			"changing to %d\n",
			cfgno, inum, asnum,
			d->bEndpointAddress, d->bInterval, n);
		endpoint->desc.bInterval = n;
	}
	//下面是根据不同的U盘的读写速度和传输模式给endpoint->desc赋值
	
	/* Some buggy low-speed devices have Bulk endpoints, which is
	 * explicitly forbidden by the USB spec.  In an attempt to make
	 * them usable, we will try treating them as Interrupt endpoints.
	 */
	if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
			usb_endpoint_xfer_bulk(d)) {
		dev_warn(ddev, "config %d interface %d altsetting %d "
			"endpoint 0x%X is Bulk; changing to Interrupt\n",
			cfgno, inum, asnum, d->bEndpointAddress);
		endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
		endpoint->desc.bInterval = 1;
		if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
	}

	/*
	 * Some buggy high speed devices have bulk endpoints using
	 * maxpacket sizes other than 512.	High speed HCDs may not
	 * be able to handle that particular bug, so let's warn...
	 */
	if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
			&& usb_endpoint_xfer_bulk(d)) {
		unsigned maxp;

		maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
		if (maxp != 512)
			dev_warn(ddev, "config %d interface %d altsetting %d "
				"bulk endpoint 0x%X has invalid maxpacket %d\n",
				cfgno, inum, asnum, d->bEndpointAddress,
				maxp);
	}
	/* Allocate room for and parse any SS endpoint companion descriptors */
	if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) {
		endpoint->extra = buffer;
		i = find_next_descriptor_more(buffer, size, USB_DT_SS_ENDPOINT_COMP,
				USB_DT_ENDPOINT, USB_DT_INTERFACE, &n);
		endpoint->extralen = i;
		buffer += i;
		size -= i;

		/* Allocate space for the SS endpoint companion descriptor */
		endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
				GFP_KERNEL);
		if (!endpoint->ss_ep_comp)
			return -ENOMEM;

		/* Fill in some default values (may be overwritten later) */
		endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
		endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
		endpoint->ss_ep_comp->desc.bMaxBurst = 0;
		/*
		 * Leave bmAttributes as zero, which will mean no streams for
		 * bulk, and isoc won't support multiple bursts of packets.
		 * With bursts of only one packet, and a Mult of 1, the max
		 * amount of data moved per endpoint service interval is one
		 * packet.
		 */
		if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
				usb_endpoint_xfer_int(&endpoint->desc))
			endpoint->ss_ep_comp->desc.wBytesPerInterval =
				endpoint->desc.wMaxPacketSize;

		if (size > 0) {
			retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
					inum, asnum, endpoint, num_ep, buffer,
					size);
			if (retval >= 0) {
				buffer += retval;
				retval = buffer - buffer0;
			}
		} else {
			dev_warn(ddev, "config %d interface %d altsetting %d "
				"endpoint 0x%X has no "
				"SuperSpeed companion descriptor\n",
				cfgno, inum, asnum, d->bEndpointAddress);
			retval = buffer - buffer0;
		}
	} else {
		/* Skip over any Class Specific or Vendor Specific descriptors;
		 * find the next endpoint or interface descriptor */
		endpoint->extra = buffer;
		i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
				USB_DT_INTERFACE, &n);
		endpoint->extralen = i;
		retval = buffer - buffer0 + i;
	}
	if (n > 0)
		dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
			n, plural(n), "endpoint");
	return retval;

skip_to_next_endpoint_or_interface_descriptor:
	i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
		USB_DT_INTERFACE, NULL);
	return buffer - buffer0 + i;
}

所有解析出来的配置描述符信息保存在usb_device->usb_host_config[config_num].desc结构体里面,i是该配置的编号;
usb_device->usb_host_config[config_num].intf_cache[interface_num].altsetting[setting_num].desc保存每个接口描述符;
usb_device->usb_host_config[config_num].intf_cache[interface_num].altsetting[setting_num].endpoint[point_num].desc保存每个端口的描述符信息;

最后一步就是device_add添加root hub 设备。

文章参考:https://blog.csdn.net/fudan_abc/article/category/325189

你可能感兴趣的:(linux内核驱动,USB驱动,OHCI,Linux,root,hub)