启动主机控制器和根集线器之后,现在来注册根集线器
register_root_hub负责根集线器的注册
register_root_hub在/drivers/usb/core/hcd.c中
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; //设置设备的设备号为1 usb_dev->devnum = devnum; //uhci总线的设备计数器+1 usb_dev->bus->devnum_next = devnum + 1; //初始化设备位表 memset (&usb_dev->bus->devmap.devicemap, 0,sizeof usb_dev->bus->devmap.devicemap); //占用设备表的第1位 set_bit (devnum, usb_dev->bus->devmap.devicemap); //设置设备状态为USB_STATE_ADDRESS usb_set_device_state(usb_dev, USB_STATE_ADDRESS); mutex_lock(&usb_bus_list_lock); //设置端点0包的最大值 usb_dev->ep0.desc.wMaxPacketSize = __constant_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", usb_dev->dev.bus_id, 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",usb_dev->dev.bus_id, retval); } mutex_unlock(&usb_bus_list_lock); if (retval == 0) { spin_lock_irq (&hcd_root_hub_lock); //设置注册标识为1 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_get_device_descriptor负责取得设备的设备描述符,设备描述符的结构如下
struct usb_device_descriptor {
__u8 bLength; //描述符的长度
__u8 bDescriptorType; //描述符的类型
__le16 bcdUSB; //表示usb设备所遵循的usb规范
__u8 bDeviceClass; //表示usb设备所属的标准设备类
__u8 bDeviceSubClass; //表示usb设备所属的标准设备子类
__u8 bDeviceProtocol; //表示usb设备所使用的设备类协议
__u8 bMaxPacketSize0; //表示0号端点包的最大大小
__le16 idVendor; //表示usb设备的生厂商id
__le16 idProduct; //表示usb设备的产品id
__le16 bcdDevice; //表示usb设备的版本号
__u8 iManufacturer; //表示生产商字符串描述符的索引值
__u8 iProduct; //表示产品字符串描述符的索引值
__u8 iSerialNumber; //表示设备序列号字符串描述符的索引值
__u8 bNumConfigurations; //表示usb设备的配置数
} __attribute__ ((packed));
usb_get_device_descriptor在/drivers/usb/core/messgae.c中
int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) { struct usb_device_descriptor *desc; int ret; if (size > sizeof(*desc)) return -EINVAL; //分配设备描述符所需要的空间 desc = kmalloc(sizeof(*desc), GFP_NOIO); if (!desc) return -ENOMEM; //取得描述符,类型为设备 ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); if (ret >= 0) //拷贝设备描述符到usb_device中 memcpy(&dev->descriptor, desc, size); kfree(desc); return ret; }
|
usb_get_descripto的用途为取得描述符
usb_get_descriptor在/drivers/usb/core/messgae.c中
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) { int i; int result; //buf清0 memset(buf, 0, size); /* Make sure we parse really received data */ //重试3次 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 = -EPROTO; continue; } break; } return result; }
|
usb_control_msg的用途为发送控制消息
usb_control_msg在/drivers/usb/core/messgae.c中
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; //为控制请求结构分配空间 dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); if (!dr) return -ENOMEM; //组建8字节的控制请求字段 dr->bRequestType = requesttype; dr->bRequest = request; dr->wValue = cpu_to_le16p(&value); dr->wIndex = cpu_to_le16p(&index); dr->wLength = cpu_to_le16p(&size); /* dbg("usb_control_msg"); */ //发送控制消息 ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); kfree(dr); return ret; }
|
这8字节的数据眼熟么?~ 还记得在前面提到的setup事务中的数据包的内容么? 正是这8字节的数据,眼泪啊,到了这里,终于接触到传输了
usb_internal_control_msg的用途为组建一个urb结构并发送他,urb这个结构在usb设备插入前都不会讲解,因为在host自己对自己的访问中,urb只起到了一个花瓶的作用,走走过场,并没有真正发送出去
usb_internal_control_msg在/drivers/usb/core/messgae.c中
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结构 usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, len, usb_api_blocking_completion, NULL); //发送它 retv = usb_start_wait_urb(urb, timeout, &length); //检测错误标识 if (retv < 0) //返回错误标识 return retv; else //返回传输的数据长度 return length; }
|
这里需要注意的是usb_api_blocking_completion这个参数,他注册到urb的complete中,之后会再提起
usb_start_wait_urb的用途才是真正的发送并完成urb........真麻烦...........
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { 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; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; //等待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=%d/%d\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; //释放urb结构 usb_free_urb(urb); return retval; }
|
在这里先放下usb_submit_urb,先说说wait_for_completion_timeout,其实这等于一个异步传输,异步传输,也就是urb完成之后会报告我完成任务了,而不需要一直询问urb,你完成任务了嘛? 你完成任务了嘛?,呢用什么报告完成呢?就是前面的usb_api_blocking_completion,urb执行这个函数之后,线程才会继续执行下面的代码
好,现在回头看usb_submit_urb
usb_submit_urb在/drivers/usb/core/urb.c中
又臭又长........抱怨一下 Orz
int usb_submit_urb(struct urb *urb, gfp_t mem_flags) { int xfertype, max; struct usb_device *dev; struct usb_host_endpoint *ep; int is_out; //判断urb是否存在 //hcpriv私有数据是否存在 //完成函数是否存在 if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; //取得urb所关联的usb设备 dev = urb->dev; //检测usb设备是否存在并且状态低于默认 if ((!dev) || (dev->state < USB_STATE_DEFAULT)) return -ENODEV; /* For now, get the endpoint from the pipe. Eventually drivers * will be required to set urb->ep directly and we will eliminate * urb->pipe. */ //通过管道计算需要使用的usb设备端点号 ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)[usb_pipeendpoint(urb->pipe)]; if (!ep) return -ENOENT; //关联urb与端点 urb->ep = ep; //设置urb的状态 urb->status = -EINPROGRESS; //初始化实际传送的空间大小 urb->actual_length = 0; /* Lots of sanity checks, so HCDs can rely on clean data * and don't need to duplicate tests */ //取得端点的传输类型 xfertype = usb_endpoint_type(&ep->desc); //传输类型为控制信息 if (xfertype == USB_ENDPOINT_XFER_CONTROL) { //取得控制请求结构 struct usb_ctrlrequest *setup = (struct usb_ctrlrequest *) urb->setup_packet; //检测控制请求是否为空 if (!setup) return -ENOEXEC; //检测请求类型的要求是否为传入 is_out = !(setup->bRequestType & USB_DIR_IN) || !setup->wLength; } else { //检测端点的传输方向 is_out = usb_endpoint_dir_out(&ep->desc); } /* Cache the direction for later use */ urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) | (is_out ? URB_DIR_OUT : URB_DIR_IN); //端点的传输类型不为控制,且设备的状态小于设置则返回出错 if (xfertype != USB_ENDPOINT_XFER_CONTROL && dev->state < USB_STATE_CONFIGURED) return -ENODEV; //取得包的最大长度 max = le16_to_cpu(ep->desc.wMaxPacketSize); //包的长度小于0则返回出错 if (max <= 0) { dev_dbg(&dev->dev, "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", usb_endpoint_num(&ep->desc), is_out ? "out" : "in", __func__, max); return -EMSGSIZE; } /* periodic transfers limit size per frame/uframe, * but drivers only control those sizes for ISO. * while we're checking, initialize return status. */ //判断传输类型是否为等时 if (xfertype == USB_ENDPOINT_XFER_ISOC) { int n, len; /* "high bandwidth" mode, 1-3 packets/uframe? */ if (dev->speed == USB_SPEED_HIGH) { int mult = 1 + ((max >> 11) & 0x03); max &= 0x07ff; max *= mult; } if (urb->number_of_packets <= 0) return -EINVAL; for (n = 0; n < urb->number_of_packets; n++) { len = urb->iso_frame_desc[n].length; if (len < 0 || len > max) return -EMSGSIZE; urb->iso_frame_desc[n].status = -EXDEV; urb->iso_frame_desc[n].actual_length = 0; } } /* the I/O buffer must be mapped/unmapped, except when length=0 */ //检测需要传输的数据要求的大小,小于0则返回出错 if (urb->transfer_buffer_length < 0) return -EMSGSIZE; /* * Force periodic transfer intervals to be legal values that are * a power of two (so HCDs don't need to). * * FIXME want bus->{intr,iso}_sched_horizon values here. Each HC * supports different values... this uses EHCI/UHCI defaults (and * EHCI can use smaller non-default values). */ //判断传输类型 switch (xfertype) { //等时传输 case USB_ENDPOINT_XFER_ISOC: //中断传输 case USB_ENDPOINT_XFER_INT: /* too small? */ if (urb->interval <= 0) return -EINVAL; /* too big? */ //判断传输速度 switch (dev->speed) { //高速 case USB_SPEED_HIGH: /* units are microframes */ /* NOTE usb handles 2^15 */ if (urb->interval > (1024 * 8)) urb->interval = 1024 * 8; max = 1024 * 8; break; //全速 case USB_SPEED_FULL: /* units are frames/msec */ //低速 case USB_SPEED_LOW: if (xfertype == USB_ENDPOINT_XFER_INT) { if (urb->interval > 255) return -EINVAL; /* NOTE ohci only handles up to 32 */ max = 128; } else { if (urb->interval > 1024) urb->interval = 1024; /* NOTE usb and ohci handle up to 2^15 */ max = 1024; } break; default: return -EINVAL; } /* Round down to a power of 2, no more than max */ urb->interval = min(max, 1 << ilog2(urb->interval)); } //发送urb return usb_hcd_submit_urb(urb, mem_flags); }
|
走完这堆代码之后终于到了usb_hcd_submit_urb,一看还是submit....... 还没发送出去啊?倒~
usb_hcd_submit_urb在/drivers/usb/core/hcd.c中
int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) { int status; //取得host控制器驱动 struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); /* increment urb's reference count as part of giving it to the HCD * (which will control it). HCD guarantees that it either returns * an error or calls giveback(), but not both. */ usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); //usbmon_urb_submit(&hcd->self, urb);
/* NOTE requirements on root-hub callers (usbfs and the hub * driver, for now): URBs' urb->transfer_buffer must be * valid and usb_buffer_{sync,unmap}() not be needed, since * they could clobber root hub response data. Also, control * URBs must be submitted in process context with interrupts * enabled. */ //为urb建立DMA缓存 status = map_urb_for_dma(hcd, urb, mem_flags); //检测映射是否成功 if (unlikely(status)) { usbmon_urb_submit_error(&hcd->self, urb, status); goto error; } //判断接收设备是否为根集线器 if (is_root_hub(urb->dev)) status = rh_urb_enqueue(hcd, urb); else status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); //判断传输是否成功 if (unlikely(status)) { usbmon_urb_submit_error(&hcd->self, urb, status); unmap_urb_for_dma(hcd, urb); error: urb->hcpriv = NULL; INIT_LIST_HEAD(&urb->urb_list); atomic_dec(&urb->use_count); atomic_dec(&urb->dev->urbnum); if (urb->reject) wake_up(&usb_kill_urb_queue); usb_put_urb(urb); } //返回错误标识 return status; }
|
按fudan_abc的说法,带usbmon的都是usb监控相关的,既然和架构无关,我就无视这些函数好了 = 3=
我们的发送目标为根集线器,呢么调用的当然是rh_urb_enqueue了
rh_urb_enqueue在/drivers/usb/core/hcd.c中
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_call_control了
rh_call_control在/drivers/usb/core/hcd.c中
static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) { struct usb_ctrlrequest *cmd; u16 typeReq, wValue, wIndex, wLength; u8 *ubuf = urb->transfer_buffer; u8 tbuf [sizeof (struct usb_hub_descriptor)] __attribute__((aligned(4))); const u8 *bufp = tbuf; int len = 0; int status; int n; u8 patch_wakeup = 0; u8 patch_protocol = 0; might_sleep(); spin_lock_irq(&hcd_root_hub_lock); //添加URB进端点队列 status = usb_hcd_link_urb_to_ep(hcd, urb); spin_unlock_irq(&hcd_root_hub_lock); if (status) return status; //设置URB的私有信息为usb_hcd urb->hcpriv = hcd; /* Indicate it's queued */ //取得控制请求结构 cmd = (struct usb_ctrlrequest *) urb->setup_packet; typeReq = (cmd->bRequestType << 8) | cmd->bRequest; wValue = le16_to_cpu (cmd->wValue); wIndex = le16_to_cpu (cmd->wIndex); wLength = le16_to_cpu (cmd->wLength); if (wLength > urb->transfer_buffer_length) goto error; urb->actual_length = 0; //判断请求类型 switch (typeReq) { /* DEVICE REQUESTS */ /* The root hub's remote wakeup enable bit is implemented using * driver model wakeup flags. If this system supports wakeup * through USB, userspace may change the default "allow wakeup" * policy through sysfs or these calls. * * Most root hubs support wakeup from downstream devices, for * runtime power management (disabling USB clocks and reducing * VBUS power usage). However, not all of them do so; silicon, * board, and BIOS bugs here are not uncommon, so these can't * be treated quite like external hubs. * * Likewise, not all root hubs will pass wakeup events upstream, * to wake up the whole system. So don't assume root hub and * controller capabilities are identical. */ //请求设备信息| 标准类型| 接收为设备,信息为取得状态 case DeviceRequest | USB_REQ_GET_STATUS: tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev) << USB_DEVICE_REMOTE_WAKEUP) | (1 << USB_DEVICE_SELF_POWERED); tbuf [1] = 0; len = 2; break; //设置设备信息| 标准类型| 接收为设备,信息为清除特征 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (wValue == USB_DEVICE_REMOTE_WAKEUP) device_set_wakeup_enable(&hcd->self.root_hub->dev, 0); else goto error; break; //设置设备信息| 标准类型| 接收为设备,信息为设置特征 case DeviceOutRequest | USB_REQ_SET_FEATURE: if (device_can_wakeup(&hcd->self.root_hub->dev) && wValue == USB_DEVICE_REMOTE_WAKEUP) device_set_wakeup_enable(&hcd->self.root_hub->dev, 1); else goto error; break; //请求设备信息| 标准类型| 接收为设备,信息为取得配置 case DeviceRequest | USB_REQ_GET_CONFIGURATION: tbuf [0] = 1; len = 1; /* FALLTHROUGH */ //设置设备信息| 标准类型| 接收为设备,信息为设置配置 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: break; //请求设备信息| 标准类型| 接收为设备,信息为取得描述符 case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch (wValue & 0xff00) { //设备描述符 case USB_DT_DEVICE << 8: if (hcd->driver->flags & HCD_USB2) bufp = usb2_rh_dev_descriptor; else if (hcd->driver->flags & HCD_USB11) bufp = usb11_rh_dev_descriptor; else goto error; len = 18; if (hcd->has_tt) patch_protocol = 1; break; //设置描述符 case USB_DT_CONFIG << 8: if (hcd->driver->flags & HCD_USB2) { bufp = hs_rh_config_descriptor; len = sizeof hs_rh_config_descriptor; } else { bufp = fs_rh_config_descriptor; len = sizeof fs_rh_config_descriptor; } if (device_can_wakeup(&hcd->self.root_hub->dev)) patch_wakeup = 1; break; //字符描述符 case USB_DT_STRING << 8: n = rh_string (wValue & 0xff, hcd, ubuf, wLength); if (n < 0) goto error; urb->actual_length = n; break; default: goto error; } break; //请求设备信息| 标准类型| 接收为设备,信息为取得接口 case DeviceRequest | USB_REQ_GET_INTERFACE: tbuf [0] = 0; len = 1; /* FALLTHROUGH */ //设置设备信息| 标准类型| 接收为设备,信息为设置接口 case DeviceOutRequest | USB_REQ_SET_INTERFACE: break; //设置设备信息| 标准类型| 接收为设备,信息为设置地址 case DeviceOutRequest | USB_REQ_SET_ADDRESS: //wValue == urb->dev->devaddr dev_dbg (hcd->self.controller, "root hub device address %d\n",wValue); break; /* INTERFACE REQUESTS (no defined feature/status flags) */ /* ENDPOINT REQUESTS */ //请求端点信息| 标准类型| 接收为接口,信息为设置状态 case EndpointRequest | USB_REQ_GET_STATUS: // ENDPOINT_HALT flag tbuf [0] = 0; tbuf [1] = 0; len = 2; /* FALLTHROUGH */ //设置端点信息| 标准类型| 接收为接口,信息为清除特征 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: //设置端点信息| 标准类型| 接收为接口,信息为设置特征 case EndpointOutRequest | USB_REQ_SET_FEATURE: dev_dbg (hcd->self.controller, "no endpoint features yet\n"); break; /* CLASS REQUESTS (and errors) */ //默认类型 default: //非标准的请求 /* non-generic request */ switch (typeReq) { //取得集线器状态 case GetHubStatus: //取得端口状态 case GetPortStatus: len = 4; break; //取得集线器描述符 case GetHubDescriptor: len = sizeof (struct usb_hub_descriptor); break; } //运行host控制器驱动的hub_control函数 status = hcd->driver->hub_control (hcd,typeReq, wValue, wIndex,tbuf, wLength); break; error: /* "protocol stall" on error */ status = -EPIPE; } //检测错误描述符 if (status) { //设置需要复制的长度为0 len = 0; if (status != -EPIPE) { dev_dbg (hcd->self.controller, "CTRL: TypeReq=0x%x val=0x%x " "idx=0x%x len=%d ==> %d\n", typeReq, wValue, wIndex, wLength, status); } } //检测需要复制的大小 if (len) { //检测需要传输的数据大小,小于len则以要传输的大小为准 if (urb->transfer_buffer_length < len) len = urb->transfer_buffer_length; //设置实际传输的数据大小 urb->actual_length = len; // always USB_DIR_IN, toward host //复制大小为len的bufp信息到ubuf中 memcpy (ubuf, bufp, len); /* report whether RH hardware supports remote wakeup */ if (patch_wakeup &&len > offsetof (struct usb_config_descriptor,bmAttributes)) ((struct usb_config_descriptor *)ubuf)->bmAttributes |= USB_CONFIG_ATT_WAKEUP; /* report whether RH hardware has an integrated TT */ if (patch_protocol &&len > offsetof(struct usb_device_descriptor,bDeviceProtocol)) ((struct usb_device_descriptor *) ubuf)->bDeviceProtocol = 1; } /* any errors get returned through the urb completion */ spin_lock_irq(&hcd_root_hub_lock); //卸载urb与端点的连接 usb_hcd_unlink_urb_from_ep(hcd, urb); /* This peculiar use of spinlocks echoes what real HC drivers do. * Avoiding calls to local_irq_disable/enable makes the code * RT-friendly. */ spin_unlock(&hcd_root_hub_lock); //返回urb usb_hcd_giveback_urb(hcd, urb, status); spin_lock(&hcd_root_hub_lock); spin_unlock_irq(&hcd_root_hub_lock); return 0; }
|
我们的目标是取得设备描述符
呢么目标就是DeviceRequest | USB_REQ_GET_DESCRIPTOR中的USB_DT_DEVICE << 8了
uhci为1.1设备,呢么就是HCD_USB11了
千辛万苦,终于拿到了我们的设备描述符usb11_rh_dev_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; */
};
说明都在旁边,大家当锻炼一下英文吧 Orz
把usb11_rh_dev_descriptor复制到ubuf中,ubuf也就是urb->transfer_buffer,这样就把设备描述符复制到了urb中
到usb_hcd_giveback_urb,这个函数中有大玄机
usb_hcd_giveback_urb在/drivers/usb/core/hcd.c中
void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) { //卸载urb的私有数据 urb->hcpriv = NULL; //检测urb的连接状态 if (unlikely(urb->unlinked)) status = urb->unlinked; else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && urb->actual_length < urb->transfer_buffer_length && !status)) status = -EREMOTEIO; //卸载urb的dma缓存映射 unmap_urb_for_dma(hcd, urb); //usbmon_urb_complete(&hcd->self, urb, status); usb_unanchor_urb(urb); /* pass ownership to the completion handler */ //设置urb的状态 urb->status = status; //运行urb的完成函数 urb->complete (urb); atomic_dec (&urb->use_count); if (unlikely (urb->reject)) wake_up (&usb_kill_urb_queue); usb_put_urb (urb); }
|
urb->complete (urb);这句看到了么,前面在苦苦等待urb完成的线程终于可以前进了,因为这里调用的正是usb_api_blocking_completion
usb_get_device_descriptor执行完毕之后, usb11_rh_dev_descriptor就在usb_device. descriptor中了
接下来到usb_new_device
usb_new_device在/drivers/usb/core/hub.c中
int usb_new_device(struct usb_device *udev) { int err; //探测怪癖 usb_detect_quirks(udev); /* Determine quirks */ //取得设备设置 err = usb_configure_device(udev); /* detect & probe dev/intfs */ if (err < 0) goto fail; /* export the usbdev device-node for libusb */ //获取设备号 udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,(((udev->bus->busnum-1) * 128) + (udev->devnum-1))); /* Increment the parent's count of unsuspended children */ if (udev->parent) usb_autoresume_device(udev->parent); /* Register the device. The device driver is responsible * for adding the device files to sysfs and for configuring * the device. */ //注册设备到sysfs中 err = device_add(&udev->dev); if (err) { dev_err(&udev->dev, "can't device_add, error %d\n", err); goto fail; } /* put device-specific files into sysfs */ //建立USB设备的属性文件 usb_create_sysfs_dev_files(udev); /* Tell the world! */ //输出设备信息 announce_device(udev); return err; fail: usb_set_device_state(udev, USB_STATE_NOTATTACHED); return err; };
|
usb_detect_quirks的任务根据设备描述符中的数据检测是否为怪癖设备,某些设备要求的复位时间长一点啥之后的不符合usb规范的设置,这个函数就不详细介绍了
usb_configure_device的用途为取得信息描述符(配置描述符,接口描述符和端口描述符的联合体)
usb_configure_device在/drivers/usb/core/hub.c中
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_otg函数是otg内容,也就是On-The-Go,是为了让一些移动设备也能做host而出的规范,关于otg的内容我不做分析 = 3= 请大家略过