第一步usb主控器设备的分配
usb_create_hcd
struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,struct device *dev, const char *bus_name) { struct usb_hcd *hcd; hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); //分配usb_hcd和私有数据内存 if (!hcd) { dev_dbg (dev, "hcd alloc failed\n"); return NULL; } dev_set_drvdata(dev, hcd); //dev->p->driver_data=hcd kref_init(&hcd->kref); //参考计数+1 usb_bus_init(&hcd->self); //初始化usb总线 hcd->self.controller = dev; //设置总线控制器设备 hcd->self.bus_name = bus_name; //设置总线名 hcd->self.uses_dma = (dev->dma_mask != NULL); //设置DMA标志 init_timer(&hcd->rh_timer); //初始化定时器 hcd->rh_timer.function = rh_timer_func; //定时器回调函数 hcd->rh_timer.data = (unsigned long) hcd; //回调函数参数 #ifdef CONFIG_USB_SUSPEND INIT_WORK(&hcd->wakeup_work, hcd_resume_work); //唤醒执行hcd_resume_work函数 #endif mutex_init(&hcd->bandwidth_mutex); hcd->driver = driver; //设置主控器驱动 hcd->product_desc = (driver->product_desc) ? driver->product_desc :"USB Host Controller"; //设置厂商字串 if (hcd->driver->recover_hcd) //若主控器驱动存在recover_hcd方法 INIT_WORK(&hcd->ehci_omap_work, hcd->driver->recover_hcd); //则调用其方法 return hcd; }
这里定时器的回调函数
static void rh_timer_func (unsigned long _hcd) { usb_hcd_poll_rh_status((struct usb_hcd *) _hcd); //调用hcd轮询检测状态的函数 }
第二步usb主控器设备添加
usb_add_hcd
int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags) { int retval; struct usb_device *rhdev; //usb设备(root hub) dev_info(hcd->self.controller, "%s\n", hcd->product_desc); //设置usb主控器设备设备文件名称 hcd->authorized_default = hcd->wireless? 0 : 1; //检测无线受权信息 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); //置位usb主控器标志 (全功耗) if ((retval = hcd_buffer_create(hcd)) != 0) { //分配usb主控器设备DMA缓冲池 dev_dbg(hcd->self.controller, "pool alloc failed\n"); return retval; } if ((retval = usb_register_bus(&hcd->self)) < 0) //usb注册总线 goto err_register_bus; if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { //分配usb设备(根hub) dev_err(hcd->self.controller, "unable to allocate root hub\n"); retval = -ENOMEM; goto err_allocate_root_hub; } hcd->self.root_hub = rhdev; switch (hcd->driver->flags & HCD_MASK) { //设置usb设备速度类型 case HCD_USB11: rhdev->speed = USB_SPEED_FULL; //全速 break; case HCD_USB2: rhdev->speed = USB_SPEED_HIGH; //高速 break; case HCD_USB3: rhdev->speed = USB_SPEED_SUPER; //超速 break; default: goto err_set_rh_speed; } device_init_wakeup(&rhdev->dev, 1); if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { //若usb主控器驱动存在重置方法则调用 dev_err(hcd->self.controller, "can't setup\n"); goto err_hcd_driver_setup; } hcd->rh_pollable = 1;//设置为可轮循 if (device_can_wakeup(hcd->self.controller)&& device_can_wakeup(&hcd->self.root_hub->dev)) //检测唤醒功能 dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); if (hcd->driver->irq) { //可中断 if (irqflags & IRQF_SHARED) //不能支持共享中断 irqflags &= ~IRQF_DISABLED; snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",hcd->driver->description, hcd->self.busnum); if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,hcd->irq_descr, hcd)) != 0) { //申请中断 dev_err(hcd->self.controller,"request interrupt %d failed\n", irqnum); goto err_request_irq; } hcd->irq = irqnum; //设置中断号 dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,(hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base",(unsigned long long)hcd->rsrc_start); } else { //不可中断 hcd->irq = -1; if (hcd->rsrc_start) //存在内存资源起始地址 dev_info(hcd->self.controller, "%s 0x%08llx\n",(hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base",(unsigned long long)hcd->rsrc_start); } if ((retval = hcd->driver->start(hcd)) < 0) { //调用主机驱动的start方法 dev_err(hcd->self.controller, "startup error %d\n", retval); goto err_hcd_driver_start; } rhdev->bus_mA = min(500u, hcd->power_budget); //设置总线电流限值 if ((retval = register_root_hub(hcd)) != 0) //注册根hub goto err_register_root_hub; retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group); //创建root hub属性文件 if (retval < 0) { printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",retval); goto error_create_attr_group; } if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) //若使用新的轮询方式且flags为HCD_FLAG_POLL_RH usb_hcd_poll_rh_status(hcd); //则轮询监控root hub状态 return retval; error_create_attr_group: if (HC_IS_RUNNING(hcd->state)) hcd->state = HC_STATE_QUIESCING; spin_lock_irq(&hcd_root_hub_lock); hcd->rh_registered = 0; spin_unlock_irq(&hcd_root_hub_lock); #ifdef CONFIG_USB_SUSPEND cancel_work_sync(&hcd->wakeup_work); #endif mutex_lock(&usb_bus_list_lock); usb_disconnect(&rhdev); mutex_unlock(&usb_bus_list_lock); err_register_root_hub: hcd->rh_pollable = 0; clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); hcd->driver->stop(hcd); hcd->state = HC_STATE_HALT; clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); err_hcd_driver_start: if (hcd->irq >= 0) free_irq(irqnum, hcd); err_request_irq: err_hcd_driver_setup: err_set_rh_speed: usb_put_dev(hcd->self.root_hub); err_allocate_root_hub: usb_deregister_bus(&hcd->self); err_register_bus: hcd_buffer_destroy(hcd); return retval; }
root hub中断例程
irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; unsigned long flags; irqreturn_t rc; local_irq_save(flags); if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) { rc = IRQ_NONE; } else if (hcd->driver->irq(hcd) == IRQ_NONE) { //调用主控器驱动的中断处理例程 rc = IRQ_NONE; } else { set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); //设置usb主控器标志HCD_FLAG_SAW_IRQ if (unlikely(hcd->state == HC_STATE_HALT)) //root hub处于停止状态 usb_hc_died(hcd); rc = IRQ_HANDLED; } local_irq_restore(flags); return rc; }
注册根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); //初始化总线usb设备号表 set_bit (devnum, usb_dev->bus->devmap.devicemap); //设置usb设备地址表第1位 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); //添加新的usb设备(root hub)-->枚举 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; //设置hub已注册标志 spin_unlock_irq (&hcd_root_hub_lock); if (hcd->state == HC_STATE_HALT) //若root hub处于停止状态 usb_hc_died (hcd); } 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); //打印设备miOAHUDU device_enable_async_suspend(&udev->dev); 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); pm_runtime_disable(&udev->dev); pm_runtime_set_suspended(&udev->dev); return err; }
有些主控器支持uses_new_polling方法则会调用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]; if (unlikely(!hcd->rh_pollable)) //若不支持轮询 return; if (!hcd->uses_new_polling && !hcd->status_urb) //若没有urb要处理 return; length = hcd->driver->hub_status_data(hcd, buffer); //调用usb主控器驱动的hub_status_data方法 if (length > 0) { spin_lock_irqsave(&hcd_root_hub_lock, flags); urb = hcd->status_urb; //获取待处理的urb if (urb) { clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); //清除标志位 hcd->status_urb = NULL; //清除待处理urb urb->actual_length = length; //指定处理的urb长度 memcpy(urb->transfer_buffer, buffer, length); usb_hcd_unlink_urb_from_ep(hcd, urb);//urb与设备端点解绑 spin_unlock(&hcd_root_hub_lock); usb_hcd_giveback_urb(hcd, urb, 0); //处理urb,并返回给usb设备 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 //处理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); urb->status = status; urb->complete (urb); //urb 回调函数 atomic_dec (&urb->use_count); if (unlikely(atomic_read(&urb->reject))) wake_up (&usb_kill_urb_queue); usb_put_urb (urb); }
<--- usb子系统初始化