当usb设备插入接口,电压变化会通知到usb主控器,
触发主控器中断,如果主控器不支持中断,那么会使用rh_timer方法,轮询接口
其结果都是调用usb_hcd_poll_rh_status
- void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
- {
- struct urb *urb;
- int length;
- unsigned long flags;
- char buffer[6]; /* Any root hubs with > 31 ports? */
- if (unlikely(!hcd->rh_pollable))
- return;
- if (!hcd->uses_new_polling && !hcd->status_urb)
- return;
- length = hcd->driver->hub_status_data(hcd, buffer); //获取urb数据长度
- if (length > 0) {
- /* try to complete the status urb */
- spin_lock_irqsave(&hcd_root_hub_lock, flags);
- urb = hcd->status_urb; //获取要处理的urb
- if (urb) {
- clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); //清除urb主控器poll标志
- hcd->status_urb = NULL; //清空待处理urb
- urb->actual_length = length; //获取urb数据长度
- memcpy(urb->transfer_buffer, buffer, length); //复制urb缓冲区
- usb_hcd_unlink_urb_from_ep(hcd, urb); //从主控器的端点上解绑urb
- spin_unlock(&hcd_root_hub_lock);
- usb_hcd_giveback_urb(hcd, urb, 0); //处理urb并回传urb给设备
- spin_lock(&hcd_root_hub_lock);
- } else {
- length = 0;
- set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
- }
- spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
- }
- if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
- (length == 0 && hcd->status_urb != NULL))
- mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
- }
usb_hcd_giveback_urb函数
- void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
- {
- urb->hcpriv = NULL;
- 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;
- unmap_urb_for_dma(hcd, urb);
- usbmon_urb_complete(&hcd->self, urb, status);
- usb_unanchor_urb(urb);
- /* pass ownership to the completion handler */
- urb->status = status;
- urb->complete (urb); //执行urb回调函数,就是hub_irq
- atomic_dec (&urb->use_count);
- if (unlikely(atomic_read(&urb->reject)))
- wake_up (&usb_kill_urb_queue);
- usb_put_urb (urb);
- }
hub_irq函数
- static void hub_irq(struct urb *urb)
- {
- struct usb_hub *hub = urb->context;
- int status = urb->status;
- unsigned i;
- unsigned long bits;
- switch (status) {
- case -ENOENT:
- case -ECONNRESET:
- case -ESHUTDOWN:
- return;
- default: //错误
- dev_dbg (hub->intfdev, "transfer --> %d\n", status);
- if ((++hub->nerrors < 10) || hub->error)
- goto resubmit;
- hub->error = status;
- case 0: //端口状态有变化
- bits = 0;
- for (i = 0; i < urb->actual_length; ++i)
- bits |= ((unsigned long) ((*hub->buffer)[i]))<< (i*8);
- hub->event_bits[0] = bits; //填充hub->event_bit数组
- break;
- }
- hub->nerrors = 0;
- kick_khubd(hub); //调用kick_khubd函数
- resubmit:
- if (hub->quiescing)
- return;
- if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0&& status != -ENODEV && status != -EPERM)
- dev_err (hub->intfdev, "resubmit --> %d\n", status);
- }
kick_khubd函数
- static void kick_khubd(struct usb_hub *hub)
- {
- unsigned long flags;
- spin_lock_irqsave(&hub_event_lock, flags);
- if (!hub->disconnected && list_empty(&hub->event_list)) {
- list_add_tail(&hub->event_list, &hub_event_list);
- usb_autopm_get_interface_no_resume(to_usb_interface(hub->intfdev));
- wake_up(&khubd_wait); //唤醒khubd_wait相关的等待队列
- }
- spin_unlock_irqrestore(&hub_event_lock, flags);
- }
这里会触发hub_events函数,原因如下
- do {
- hub_events();
- wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop());
- } while (!kthread_should_stop() || !list_empty(&hub_event_list));
hub_events函数
- static void hub_events(void)
- {
- struct list_head *tmp;
- struct usb_device *hdev;
- struct usb_interface *intf;
- struct usb_hub *hub;
- struct device *hub_dev;
- u16 hubstatus;
- u16 hubchange;
- u16 portstatus;
- u16 portchange;
- int i, ret;
- int connect_change;
- //hcd usb主控器的状态由usb主控器的中断例程根据具体硬件状态去设置
- while (1) {
- spin_lock_irq(&hub_event_lock);
- //这次执行假设usb主控器已经注册
- if (list_empty(&hub_event_list)) { //usb事件链表不为为空
- spin_unlock_irq(&hub_event_lock);
- break;
- }
- tmp = hub_event_list.next; //拿出hub_event链表项
- list_del_init(tmp); //从hub_event_list删除其
- hub = list_entry(tmp, struct usb_hub, event_list); //根据链表项获取usb_hub
- kref_get(&hub->kref); //引用计数
- spin_unlock_irq(&hub_event_lock);
- hdev = hub->hdev; //获取hub usb设备
- hub_dev = hub->intfdev; //获取hub 设备文件
- intf = to_usb_interface(hub_dev); //获取hub usb接口
- usb_lock_device(hdev);
- if (unlikely(hub->disconnected))
- goto loop_disconnected;
- if (hdev->state == USB_STATE_NOTATTACHED) { //判断是否为USB_STATE_NOTATTACHED状态
- hub->error = -ENODEV;
- hub_quiesce(hub, HUB_DISCONNECT);
- goto loop;
- }
- ret = usb_autopm_get_interface(intf);
- if (ret) {
- dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
- goto loop;
- }
- if (hub->quiescing)
- goto loop_autopm;
- if (hub->error) {
- dev_dbg (hub_dev, "resetting for error %d\n",hub->error);
- ret = usb_reset_device(hdev);
- if (ret) {
- dev_dbg (hub_dev,"error resetting hub: %d\n", ret);
- goto loop_autopm;
- }
- hub->nerrors = 0;
- hub->error = 0;
- }
- for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
- if (test_bit(i, hub->busy_bits))
- continue;
- connect_change = test_bit(i, hub->change_bits); //判断是否hub口状态变化
- if (!test_and_clear_bit(i, hub->event_bits) &&!connect_change)
- continue;
- ret = hub_port_status(hub, i,&portstatus, &portchange);
- if (ret < 0)
- continue;
- if (portchange & USB_PORT_STAT_C_CONNECTION) { //hub口连接上设备
- clear_port_feature(hdev, i,USB_PORT_FEAT_C_CONNECTION);
- connect_change = 1;
- }
- if (portchange & USB_PORT_STAT_C_ENABLE) { //hub口的设备使能
- if (!connect_change)
- dev_dbg (hub_dev,"port %d enable change,status %08x\n",i, portstatus);
- clear_port_feature(hdev, i,USB_PORT_FEAT_C_ENABLE);
- if (!(portstatus & USB_PORT_STAT_ENABLE)&& !connect_change&& hdev->children[i-1]) {
- dev_err (hub_dev,"port %i disabled by hub (EMI?),re-enabling...\n",i);
- connect_change = 1;
- }
- }
- if (portchange & USB_PORT_STAT_C_SUSPEND) { //hub口的设备挂起
- struct usb_device *udev;
- clear_port_feature(hdev, i,USB_PORT_FEAT_C_SUSPEND);
- udev = hdev->children[i-1];
- if (udev) {
- msleep(10);
- usb_lock_device(udev);
- ret = usb_remote_wakeup(hdev->children[i-1]);
- usb_unlock_device(udev);
- if (ret < 0)
- connect_change = 1;
- } else {
- ret = -ENODEV;
- hub_port_disable(hub, i, 1);
- }
- dev_dbg (hub_dev,"resume on port %d, status %d\n",i, ret);
- }
- if (portchange & USB_PORT_STAT_C_OVERCURRENT) { //hub口设备过流
- dev_err (hub_dev,"over-current change on port %d\n",i);
- clear_port_feature(hdev, i,USB_PORT_FEAT_C_OVER_CURRENT);
- hub_power_on(hub, true);
- }
- if (portchange & USB_PORT_STAT_C_RESET) { //hub口设备重置
- dev_dbg (hub_dev,"reset change on port %d\n",i);
- clear_port_feature(hdev, i,USB_PORT_FEAT_C_RESET);
- }
- if (connect_change) //hub口有变化(设备插入肯定有变化)
- hub_port_connect_change(hub, i,portstatus, portchange); //hub口变化处理
- }
- if (test_and_clear_bit(0, hub->event_bits) == 0)
- ;
- else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
- dev_err (hub_dev, "get_hub_status failed\n");
- else {
- if (hubchange & HUB_CHANGE_LOCAL_POWER) {
- dev_dbg (hub_dev, "power change\n");
- clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
- if (hubstatus & HUB_STATUS_LOCAL_POWER)
- hub->limited_power = 1;
- else
- hub->limited_power = 0;
- }
- if (hubchange & HUB_CHANGE_OVERCURRENT) {
- dev_dbg (hub_dev, "overcurrent change\n");
- msleep(500);
- clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
- hub_power_on(hub, true);
- }
- }
- loop_autopm:
- usb_autopm_put_interface_no_suspend(intf);
- loop:
- usb_autopm_put_interface(intf);
- loop_disconnected:
- usb_unlock_device(hdev);
- kref_put(&hub->kref, hub_release);
- }
- }
hub口状态变化处理函数
- static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange)
- {
- struct usb_device *hdev = hub->hdev;
- struct device *hub_dev = hub->intfdev;
- struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
- unsigned wHubCharacteristics =le16_to_cpu(hub->descriptor->wHubCharacteristics);
- struct usb_device *udev;
- int status, i;
- dev_dbg (hub_dev,"port %d, status %04x, change %04x, %s\n",port1, portstatus, portchange, portspeed (portstatus));
- if (hub->has_indicators) {
- set_port_led(hub, port1, HUB_LED_AUTO);
- hub->indicator[port1-1] = INDICATOR_AUTO;
- }
- #ifdef CONFIG_USB_OTG
- if (hdev->bus->is_b_host)
- portchange &= ~(USB_PORT_STAT_C_CONNECTION |USB_PORT_STAT_C_ENABLE);
- #endif
- udev = hdev->children[port1-1]; //获取usb_device
- if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&udev->state != USB_STATE_NOTATTACHED) {
- usb_lock_device(udev);
- if (portstatus & USB_PORT_STAT_ENABLE) {
- status = 0;
- #ifdef CONFIG_USB_SUSPEND
- } else if (udev->state == USB_STATE_SUSPENDED &&udev->persist_enabled) {
- status = usb_remote_wakeup(udev);
- #endif
- } else {
- status = -ENODEV;
- }
- usb_unlock_device(udev);
- if (status == 0) {
- clear_bit(port1, hub->change_bits);
- return;
- }
- }
- if (udev)
- usb_disconnect(&hdev->children[port1-1]);
- clear_bit(port1, hub->change_bits); //清除标志位
- if (!(portstatus & USB_PORT_STAT_CONNECTION) ||(portchange & USB_PORT_STAT_C_CONNECTION))
- clear_bit(port1, hub->removed_bits);
- if (portchange & (USB_PORT_STAT_C_CONNECTION |USB_PORT_STAT_C_ENABLE)) {
- status = hub_port_debounce(hub, port1);
- if (status < 0) {
- if (printk_ratelimit())
- dev_err(hub_dev, "connect-debounce failed,port %d disabled\n", port1);
- portstatus &= ~USB_PORT_STAT_CONNECTION;
- } else {
- portstatus = status;
- }
- }
- if (!(portstatus & USB_PORT_STAT_CONNECTION) ||test_bit(port1, hub->removed_bits)) {
- if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2&& !(portstatus & USB_PORT_STAT_POWER))
- set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
- if (portstatus & USB_PORT_STAT_ENABLE)
- goto done;
- return;
- }
- for (i = 0; i < SET_CONFIG_TRIES; i++) { //配置usb设备
- udev = usb_alloc_dev(hdev, hdev->bus, port1); //分配usb_device
- if (!udev) {
- dev_err (hub_dev,"couldn't allocate port %d usb_device\n",port1);
- goto done;
- }
- usb_set_device_state(udev, USB_STATE_POWERED); //设置usb设备为得电态
- udev->bus_mA = hub->mA_per_port; //指定其电流限额
- udev->level = hdev->level + 1; //层数为所属的hub的层数+1
- udev->wusb = hub_is_wusb(hub);
- if (!(hcd->driver->flags & HCD_USB3)) //usb设备速度
- udev->speed = USB_SPEED_UNKNOWN;
- else if ((hdev->parent == NULL) &&(portstatus & USB_PORT_STAT_SUPER_SPEED))
- udev->speed = USB_SPEED_SUPER;
- else
- udev->speed = USB_SPEED_UNKNOWN;
- choose_address(udev); //选择一个usb设备地址
- if (udev->devnum <= 0) {
- status = -ENOTCONN; /* Don't retry */
- goto loop;
- }
- status = hub_port_init(hub, udev, port1, i); //初始化hub端口,枚举
- if (status < 0)
- goto loop;
- usb_detect_quirks(udev);
- if (udev->quirks & USB_QUIRK_DELAY_INIT)
- msleep(1000);
- if (udev->descriptor.bDeviceClass == USB_CLASS_HUB&& udev->bus_mA <= 100) { //若插进来的也是hub
- u16 devstat;
- status = usb_get_status(udev, USB_RECIP_DEVICE, 0,&devstat);
- if (status < 2) {
- dev_dbg(&udev->dev, "get status %d ?\n", status);
- goto loop_disable;
- }
- le16_to_cpus(&devstat);
- if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
- dev_err(&udev->dev,"can't connect bus-powered hub to this port\n");
- if (hub->has_indicators) {
- hub->indicator[port1-1] =INDICATOR_AMBER_BLINK;
- schedule_delayed_work (&hub->leds, 0);
- }
- status = -ENOTCONN;
- goto loop_disable;
- }
- }
- if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200&& udev->speed == USB_SPEED_FULL&& highspeed_hubs != 0)
- check_highspeed (hub, udev, port1);
- status = 0;
- spin_lock_irq(&device_state_lock);
- if (hdev->state == USB_STATE_NOTATTACHED)
- status = -ENOTCONN;
- else
- hdev->children[port1-1] = udev; //设置hub usb设备的子设备
- spin_unlock_irq(&device_state_lock);
- if (!status) {
- status = usb_new_device(udev); //usb添加新设备
- if (status) {
- spin_lock_irq(&device_state_lock);
- hdev->children[port1-1] = NULL;
- spin_unlock_irq(&device_state_lock);
- }
- }
- if (status)
- goto loop_disable;
- status = hub_power_remaining(hub);
- if (status)
- dev_dbg(hub_dev, "%dmA power budget left\n", status);
- return;
- loop_disable:
- hub_port_disable(hub, port1, 1);
- loop:
- usb_ep0_reinit(udev);
- release_address(udev);
- hub_free_dev(udev);
- usb_put_dev(udev);
- if ((status == -ENOTCONN) || (status == -ENOTSUPP))
- break;
- }
- if (hub->hdev->parent ||!hcd->driver->port_handed_over ||!(hcd->driver->port_handed_over)(hcd, port1))
- dev_err(hub_dev, "unable to enumerate USB device on port %d\n",port1);
- done:
- hub_port_disable(hub, port1, 1);
- if (hcd->driver->relinquish_port && !hub->hdev->parent)
- hcd->driver->relinquish_port(hcd, port1);
- }
hub端口初始化
- static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,int retry_counter)
- {
- static DEFINE_MUTEX(usb_address0_mutex);
- struct usb_device *hdev = hub->hdev;
- struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
- int i, j, retval;
- unsigned delay = HUB_SHORT_RESET_TIME;
- enum usb_device_speed oldspeed = udev->speed;
- char *speed, *type;
- int devnum = udev->devnum;
- if (!hdev->parent) {
- delay = HUB_ROOT_RESET_TIME;
- if (port1 == hdev->bus->otg_port)
- hdev->bus->b_hnp_enable = 0;
- }
- if (oldspeed == USB_SPEED_LOW)
- delay = HUB_LONG_RESET_TIME;
- mutex_lock(&usb_address0_mutex);
- if (!udev->config && oldspeed == USB_SPEED_SUPER) {
- usb_set_device_state(udev, USB_STATE_DEFAULT);
- } else {
- retval = hub_port_reset(hub, port1, udev, delay);
- if (retval < 0)
- goto fail;
- }
- retval = -ENODEV;
- if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) {
- dev_dbg(&udev->dev, "device reset changed speed!\n");
- goto fail;
- }
- oldspeed = udev->speed;
- switch (udev->speed) {
- case USB_SPEED_SUPER:
- case USB_SPEED_WIRELESS:
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
- break;
- case USB_SPEED_HIGH:
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- break;
- case USB_SPEED_FULL:
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- break;
- case USB_SPEED_LOW:
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
- break;
- default:
- goto fail;
- }
- type = "";
- switch (udev->speed) {
- case USB_SPEED_LOW: speed = "low"; break;
- case USB_SPEED_FULL: speed = "full"; break;
- case USB_SPEED_HIGH: speed = "high"; break;
- case USB_SPEED_SUPER: speed = "super"; break;
- case USB_SPEED_WIRELESS: speed = "variable"; type = "Wireless "; break;
- default: speed = "?"; break;
- }
- if (udev->speed != USB_SPEED_SUPER)
- dev_info(&udev->dev,"%s %s speed %sUSB device using %s and address %d\n",
- (udev->config) ? "reset" : "new", speed, type,udev->bus->controller->driver->name, devnum);
- if (hdev->tt) {
- udev->tt = hdev->tt;
- udev->ttport = hdev->ttport;
- } else if (udev->speed != USB_SPEED_HIGH&& hdev->speed == USB_SPEED_HIGH) {
- udev->tt = &hub->tt;
- udev->ttport = port1;
- }
- for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
- if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
- struct usb_device_descriptor *buf;
- int r = 0;
- #define GET_DESCRIPTOR_BUFSIZE 64
- buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
- if (!buf) {
- retval = -ENOMEM;
- continue;
- }
- for (j = 0; j < 3; ++j) {
- buf->bMaxPacketSize0 = 0;
- r = usb_control_msg(udev, usb_rcvaddr0pipe(),USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- USB_DT_DEVICE << 8, 0,buf, GET_DESCRIPTOR_BUFSIZE,initial_descriptor_timeout);
- //获取描述符
- switch (buf->bMaxPacketSize0) {
- case 8: case 16: case 32: case 64: case 255:
- if (buf->bDescriptorType == USB_DT_DEVICE) {
- r = 0;
- break;
- }
- default:
- if (r == 0)
- r = -EPROTO;
- break;
- }
- if (r == 0)
- break;
- }
- udev->descriptor.bMaxPacketSize0 = buf->bMaxPacketSize0;
- kfree(buf);
- retval = hub_port_reset(hub, port1, udev, delay);
- if (retval < 0)
- goto fail;
- if (oldspeed != udev->speed) {
- dev_dbg(&udev->dev,"device reset changed speed!\n");
- retval = -ENODEV;
- goto fail;
- }
- if (r) {
- dev_err(&udev->dev,"device descriptor read/64, error %d\n",r);
- retval = -EMSGSIZE;
- continue;
- }
- #undef GET_DESCRIPTOR_BUFSIZE
- }
- if (udev->wusb == 0) {
- for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
- retval = hub_set_address(udev, devnum); //hub设置usb地址并告诉usb设备
- if (retval >= 0)
- break;
- msleep(200);
- }
- if (retval < 0) {
- dev_err(&udev->dev,"device not accepting address %d, error %d\n",devnum, retval);
- goto fail;
- }
- if (udev->speed == USB_SPEED_SUPER) {
- devnum = udev->devnum;
- dev_info(&udev->dev,"%s SuperSpeed USB device using %s and address %d\n",
- (udev->config) ? "reset" : "new",udev->bus->controller->driver->name, devnum);
- }
- msleep(10);
- if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
- break;
- }
- retval = usb_get_device_descriptor(udev, 8); //获取设备描述符先读8字节
- if (retval < 8) {
- dev_err(&udev->dev,"device descriptor read/8, error %d\n",retval);
- if (retval >= 0)
- retval = -EMSGSIZE;
- } else {
- retval = 0;
- break;
- }
- }
- if (retval)
- goto fail;
- if (udev->descriptor.bMaxPacketSize0 == 0xff ||
- udev->speed == USB_SPEED_SUPER)
- i = 512;
- else
- i = udev->descriptor.bMaxPacketSize0;
- if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
- if (udev->speed == USB_SPEED_LOW ||!(i == 8 || i == 16 || i == 32 || i == 64)) {
- dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
- retval = -EMSGSIZE;
- goto fail;
- }
- if (udev->speed == USB_SPEED_FULL)
- dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
- else
- dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
- usb_ep0_reinit(udev);
- }
- retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); //再次获取设备描述符
- if (retval < (signed)sizeof(udev->descriptor)) {
- dev_err(&udev->dev, "device descriptor read/all, error %d\n",
- retval);
- if (retval >= 0)
- retval = -ENOMSG;
- goto fail;
- }
- retval = 0;
- if (hcd->driver->update_device)
- hcd->driver->update_device(hcd, udev);
- fail:
- if (retval) {
- hub_port_disable(hub, port1, 0);
- update_address(udev, devnum); /* for disconnect processing */
- }
- mutex_unlock(&usb_address0_mutex);
- return retval;
- }
usb_new_device
- int usb_new_device(struct usb_device *udev)
- {
- int err;
- if (udev->parent) {
- device_init_wakeup(&udev->dev, 0);
- }
- pm_runtime_set_active(&udev->dev);
- pm_runtime_enable(&udev->dev);
- err = usb_enumerate_device(udev); //读取usb设备的描述符信息
- 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)));
- udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,(((udev->bus->busnum-1) * 128) + (udev->devnum-1))); //分配设备号
- announce_device(udev); //打印usb设备厂商啊啥的信息
- device_enable_async_suspend(&udev->dev);
- err = device_add(&udev->dev); //添加设备(至此usb枚举完了)-->usb设备与驱动的匹配
- 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);
- pm_runtime_disable(&udev->dev);
- pm_runtime_set_suspended(&udev->dev);
- return err;
- }
usb_enumerate_device
- static int usb_enumerate_device(struct usb_device *udev)
- {
- int err;
- if (udev->config == NULL) {
- err = usb_get_configuration(udev); //usb获取配置描述符
- 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 {
- udev->product = usb_cache_string(udev, udev->descriptor.iProduct); //设置产品id
- udev->manufacturer = usb_cache_string(udev,udev->descriptor.iManufacturer); //设置厂商id
- udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); //设置产品序列号
- }
- err = usb_enumerate_device_otg(udev);
- fail:
- return err;
- }
device_add函数会出发总线的通知链发送通知,最终会调用总线的match方法
usb设备和驱动一旦match,则会调用驱动的drvwrap.driver.probe方法
若是设备则调用usb_probe_device
若是接口则调用usb_probe_interface
这里我们调用的是usb接口的,也就是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 error;
- if (udev->authorized == 0) {
- dev_err(&intf->dev, "Device is not authorized for usage\n");
- return error;
- }
- id = usb_match_id(intf, driver->id_table); //静态id匹配
- if (!id)
- id = usb_match_dynamic_id(intf, driver); //动态id匹配
- 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;
- pm_runtime_set_active(dev);
- pm_suspend_ignore_children(dev, false);
- if (driver->supports_autosuspend)
- pm_runtime_enable(dev);
- 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驱动的probe方法
- if (error)
- goto err;
- intf->condition = USB_INTERFACE_BOUND;
- usb_autosuspend_device(udev);
- return error;
- err:
- intf->needs_remote_wakeup = 0;
- intf->condition = USB_INTERFACE_UNBOUND;
- usb_cancel_queued_reset(intf);
- if (driver->supports_autosuspend)
- pm_runtime_disable(dev);
- pm_runtime_set_suspended(dev);
- usb_autosuspend_device(udev);
- return error;
- }
一般在usb设备驱动的probe方法中会调用usb_alloc_urb分配urb
用
usb_fill_int_urb
usb_fill_bulk_urb
usb_fill_control_urb
填充urb
然后用usb_submit_urb提交urb
- 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;
- if (!urb || urb->hcpriv || !urb->complete)
- return -EINVAL;
- dev = urb->dev;
- if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
- return -ENODEV;
- ep = usb_pipe_endpoint(dev, urb->pipe); //获取端点
- if (!ep)
- return -ENOENT;
- urb->ep = ep; //设置端点
- urb->status = -EINPROGRESS;
- urb->actual_length = 0;
- xfertype = usb_endpoint_type(&ep->desc);
- if (xfertype == USB_ENDPOINT_XFER_CONTROL) { //控制传输
- struct usb_ctrlrequest *setup =(struct usb_ctrlrequest *) urb->setup_packet; //设置setup包
- if (!setup)
- return -ENOEXEC;
- is_out = !(setup->bRequestType & USB_DIR_IN) ||!setup->wLength;
- } else {
- is_out = usb_endpoint_dir_out(&ep->desc);
- }
- urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
- URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |URB_DMA_SG_COMBINED);
- urb->transfer_flags |= (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);
- 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;
- }
- if (xfertype == USB_ENDPOINT_XFER_ISOC) { //同步传输
- int n, len;
- 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;
- }
- }
- if (urb->transfer_buffer_length > INT_MAX)
- return -EMSGSIZE;
- switch (xfertype) { //传输类型
- case USB_ENDPOINT_XFER_ISOC: //同步传输
- case USB_ENDPOINT_XFER_INT: //中断传输
- switch (dev->speed) {
- case USB_SPEED_WIRELESS: //无线?
- if (urb->interval < 6)
- return -EINVAL;
- break;
- default:
- if (urb->interval <= 0)
- return -EINVAL;
- break;
- }
- switch (dev->speed) {
- case USB_SPEED_SUPER: //超速设备
- if (urb->interval > (1 << 15))
- return -EINVAL;
- max = 1 << 15;
- break;
- case USB_SPEED_WIRELESS: //无线?
- if (urb->interval > 16)
- return -EINVAL;
- break;
- case USB_SPEED_HIGH: //高速设备
- if (urb->interval > (1024 * 8))
- urb->interval = 1024 * 8;
- max = 1024 * 8;
- break;
- case USB_SPEED_FULL: //全速
- case USB_SPEED_LOW: //低速
- if (xfertype == USB_ENDPOINT_XFER_INT) {
- if (urb->interval > 255)
- return -EINVAL;
- max = 128;
- } else {
- if (urb->interval > 1024)
- urb->interval = 1024;
- max = 1024;
- }
- break;
- default:
- return -EINVAL;
- }
- if (dev->speed != USB_SPEED_WIRELESS) {
- urb->interval = min(max, 1 << ilog2(urb->interval));
- }
- }
- return usb_hcd_submit_urb(urb, mem_flags);
- }
调用主控器usb_hcd_submit_urb
- int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
- {
- int status;
- struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
- usb_get_urb(urb);
- atomic_inc(&urb->use_count);
- atomic_inc(&urb->dev->urbnum);
- usbmon_urb_submit(&hcd->self, urb);
- if (is_root_hub(urb->dev)) { //这次不是根hub
- status = rh_urb_enqueue(hcd, urb);
- } else {
- status = map_urb_for_dma(hcd, urb, mem_flags);
- if (likely(status == 0)) {
- status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); //调用主控器的urb_enqueue方法
- if (unlikely(status))
- unmap_urb_for_dma(hcd, urb);
- }
- }
- if (unlikely(status)) {
- usbmon_urb_submit_error(&hcd->self, urb, status);
- urb->hcpriv = NULL;
- INIT_LIST_HEAD(&urb->urb_list);
- atomic_dec(&urb->use_count);
- atomic_dec(&urb->dev->urbnum);
- if (atomic_read(&urb->reject))
- wake_up(&usb_kill_urb_queue);
- usb_put_urb(urb);
- }
- return status;
- }