usb主控器注册

来源:互联网 发布:企业收支软件 编辑:程序博客网 时间:2024/04/29 03:21

第一步usb主控器设备的分配

usb_create_hcd

[cpp] view plaincopy
  1. struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,struct device *dev, const char *bus_name)  
  2. {  
  3.     struct usb_hcd *hcd;  
  4.     hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); //分配usb_hcd和私有数据内存  
  5.     if (!hcd) {  
  6.         dev_dbg (dev, "hcd alloc failed\n");  
  7.         return NULL;  
  8.     }  
  9.     dev_set_drvdata(dev, hcd);  //dev->p->driver_data=hcd  
  10.     kref_init(&hcd->kref);   //参考计数+1  
  11.     usb_bus_init(&hcd->self);    //初始化usb总线  
  12.     hcd->self.controller = dev;  //设置总线控制器设备  
  13.     hcd->self.bus_name = bus_name;   //设置总线名  
  14.     hcd->self.uses_dma = (dev->dma_mask != NULL); //设置DMA标志  
  15.     init_timer(&hcd->rh_timer);      //初始化定时器  
  16.     hcd->rh_timer.function = rh_timer_func;  //定时器回调函数  
  17.     hcd->rh_timer.data = (unsigned long) hcd;    //回调函数参数  
  18. #ifdef CONFIG_USB_SUSPEND  
  19.     INIT_WORK(&hcd->wakeup_work, hcd_resume_work);   //唤醒执行hcd_resume_work函数  
  20. #endif  
  21.     mutex_init(&hcd->bandwidth_mutex);  
  22.     hcd->driver = driver;    //设置主控器驱动  
  23.     hcd->product_desc = (driver->product_desc) ? driver->product_desc :"USB Host Controller";  //设置厂商字串  
  24.     if (hcd->driver->recover_hcd) //若主控器驱动存在recover_hcd方法  
  25.         INIT_WORK(&hcd->ehci_omap_work, hcd->driver->recover_hcd); //则调用其方法  
  26.     return hcd;  
  27. }  

这里定时器的回调函数

[cpp] view plaincopy
  1. static void rh_timer_func (unsigned long _hcd)  
  2. {  
  3.     usb_hcd_poll_rh_status((struct usb_hcd *) _hcd);    //调用hcd轮询检测状态的函数  
  4. }  

第二步usb主控器设备添加

usb_add_hcd

[cpp] view plaincopy
  1. int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags)  
  2. {  
  3.     int retval;  
  4.     struct usb_device *rhdev;   //usb设备(root hub)  
  5.     dev_info(hcd->self.controller, "%s\n", hcd->product_desc);    //设置usb主控器设备设备文件名称  
  6.     hcd->authorized_default = hcd->wireless? 0 : 1;   //检测无线受权信息  
  7.     set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);    //置位usb主控器标志    (全功耗)  
  8.     if ((retval = hcd_buffer_create(hcd)) != 0) {   //分配usb主控器设备DMA缓冲池  
  9.         dev_dbg(hcd->self.controller, "pool alloc failed\n");  
  10.         return retval;  
  11.     }  
  12.     if ((retval = usb_register_bus(&hcd->self)) < 0)  //usb注册总线  
  13.         goto err_register_bus;  
  14.     if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {  //分配usb设备(根hub)  
  15.         dev_err(hcd->self.controller, "unable to allocate root hub\n");  
  16.         retval = -ENOMEM;  
  17.         goto err_allocate_root_hub;  
  18.     }  
  19.     hcd->self.root_hub = rhdev;  
  20.     switch (hcd->driver->flags & HCD_MASK) {  //设置usb设备速度类型  
  21.     case HCD_USB11:  
  22.         rhdev->speed = USB_SPEED_FULL;   //全速  
  23.         break;  
  24.     case HCD_USB2:  
  25.         rhdev->speed = USB_SPEED_HIGH;   //高速  
  26.         break;  
  27.     case HCD_USB3:  
  28.         rhdev->speed = USB_SPEED_SUPER;  //超速  
  29.         break;  
  30.     default:  
  31.         goto err_set_rh_speed;  
  32.     }  
  33.     device_init_wakeup(&rhdev->dev, 1);  
  34.     if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {  //若usb主控器驱动存在重置方法则调用  
  35.         dev_err(hcd->self.controller, "can't setup\n");  
  36.         goto err_hcd_driver_setup;  
  37.     }  
  38.     hcd->rh_pollable = 1;//设置为可轮循  
  39.     if (device_can_wakeup(hcd->self.controller)&& device_can_wakeup(&hcd->self.root_hub->dev)) //检测唤醒功能  
  40.         dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");  
  41.     if (hcd->driver->irq) {   //可中断  
  42.         if (irqflags & IRQF_SHARED) //不能支持共享中断  
  43.             irqflags &= ~IRQF_DISABLED;  
  44.         snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",hcd->driver->description, hcd->self.busnum);  
  45.         if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,hcd->irq_descr, hcd)) != 0) {   //申请中断  
  46.             dev_err(hcd->self.controller,"request interrupt %d failed\n", irqnum);  
  47.             goto err_request_irq;  
  48.         }  
  49.         hcd->irq = irqnum;   //设置中断号  
  50.         dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,(hcd->driver->flags & HCD_MEMORY) ?  
  51.                     "io mem" : "io base",(unsigned long long)hcd->rsrc_start);  
  52.     } else {            //不可中断  
  53.         hcd->irq = -1;  
  54.         if (hcd->rsrc_start) //存在内存资源起始地址  
  55.             dev_info(hcd->self.controller, "%s 0x%08llx\n",(hcd->driver->flags & HCD_MEMORY) ?  
  56.                 "io mem" : "io base",(unsigned long long)hcd->rsrc_start);  
  57.     }  
  58.     if ((retval = hcd->driver->start(hcd)) < 0) {  //调用主机驱动的start方法  
  59.         dev_err(hcd->self.controller, "startup error %d\n", retval);  
  60.         goto err_hcd_driver_start;  
  61.     }  
  62.     rhdev->bus_mA = min(500u, hcd->power_budget); //设置总线电流限值  
  63.     if ((retval = register_root_hub(hcd)) != 0) //注册根hub  
  64.         goto err_register_root_hub;  
  65.     retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);  //创建root hub属性文件  
  66.     if (retval < 0) {  
  67.         printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",retval);  
  68.         goto error_create_attr_group;  
  69.     }  
  70.     if (hcd->uses_new_polling && HCD_POLL_RH(hcd))   //若使用新的轮询方式且flags为HCD_FLAG_POLL_RH  
  71.         usb_hcd_poll_rh_status(hcd);    //则轮询监控root hub状态  
  72.     return retval;  
  73. error_create_attr_group:  
  74.     if (HC_IS_RUNNING(hcd->state))  
  75.         hcd->state = HC_STATE_QUIESCING;  
  76.     spin_lock_irq(&hcd_root_hub_lock);  
  77.     hcd->rh_registered = 0;  
  78.     spin_unlock_irq(&hcd_root_hub_lock);  
  79. #ifdef CONFIG_USB_SUSPEND  
  80.     cancel_work_sync(&hcd->wakeup_work);  
  81. #endif  
  82.     mutex_lock(&usb_bus_list_lock);  
  83.     usb_disconnect(&rhdev);  
  84.     mutex_unlock(&usb_bus_list_lock);  
  85. err_register_root_hub:  
  86.     hcd->rh_pollable = 0;  
  87.     clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);  
  88.     del_timer_sync(&hcd->rh_timer);  
  89.     hcd->driver->stop(hcd);  
  90.     hcd->state = HC_STATE_HALT;  
  91.     clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);  
  92.     del_timer_sync(&hcd->rh_timer);  
  93. err_hcd_driver_start:  
  94.     if (hcd->irq >= 0)  
  95.         free_irq(irqnum, hcd);  
  96. err_request_irq:  
  97. err_hcd_driver_setup:  
  98. err_set_rh_speed:  
  99.     usb_put_dev(hcd->self.root_hub);  
  100. err_allocate_root_hub:  
  101.     usb_deregister_bus(&hcd->self);  
  102. err_register_bus:  
  103.     hcd_buffer_destroy(hcd);  
  104.     return retval;  
  105. }   

root hub中断例程

[cpp] view plaincopy
  1. irqreturn_t usb_hcd_irq (int irq, void *__hcd)  
  2. {  
  3.     struct usb_hcd  *hcd = __hcd;  
  4.     unsigned long   flags;  
  5.     irqreturn_t rc;  
  6.     local_irq_save(flags);  
  7.     if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {  
  8.         rc = IRQ_NONE;  
  9.     } else if (hcd->driver->irq(hcd) == IRQ_NONE) {   //调用主控器驱动的中断处理例程  
  10.         rc = IRQ_NONE;  
  11.     } else {  
  12.         set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);  //设置usb主控器标志HCD_FLAG_SAW_IRQ  
  13.   
  14.         if (unlikely(hcd->state == HC_STATE_HALT))   //root hub处于停止状态  
  15.             usb_hc_died(hcd);  
  16.         rc = IRQ_HANDLED;  
  17.     }  
  18.     local_irq_restore(flags);  
  19.     return rc;  
  20. }  

注册根hub register_root_hub

[cpp] view plaincopy
  1. static int register_root_hub(struct usb_hcd *hcd)  
  2. {  
  3.     struct device *parent_dev = hcd->self.controller;  
  4.     struct usb_device *usb_dev = hcd->self.root_hub;  
  5.     const int devnum = 1;  
  6.     int retval;  
  7.     usb_dev->devnum = devnum;    //地址  
  8.     usb_dev->bus->devnum_next = devnum + 1;  
  9.     memset (&usb_dev->bus->devmap.devicemap, 0,sizeof usb_dev->bus->devmap.devicemap);  //初始化总线usb设备号表  
  10.     set_bit (devnum, usb_dev->bus->devmap.devicemap); //设置usb设备地址表第1位  
  11.     usb_set_device_state(usb_dev, USB_STATE_ADDRESS);   //设置设备为寻址态  
  12.     mutex_lock(&usb_bus_list_lock);  
  13.     usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);  
  14.     retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);    //获取设备描述符  
  15.     if (retval != sizeof usb_dev->descriptor) {  
  16.         mutex_unlock(&usb_bus_list_lock);  
  17.         dev_dbg (parent_dev, "can't read %s device descriptor %d\n",dev_name(&usb_dev->dev), retval);  
  18.         return (retval < 0) ? retval : -EMSGSIZE;  
  19.     }  
  20.     retval = usb_new_device (usb_dev);  //添加新的usb设备(root hub)-->枚举  
  21.     if (retval) {  
  22.         dev_err (parent_dev, "can't register root hub for %s, %d\n",dev_name(&usb_dev->dev), retval);  
  23.     }  
  24.     mutex_unlock(&usb_bus_list_lock);  
  25.     if (retval == 0) {  
  26.         spin_lock_irq (&hcd_root_hub_lock);  
  27.         hcd->rh_registered = 1;  //设置hub已注册标志  
  28.         spin_unlock_irq (&hcd_root_hub_lock);  
  29.         if (hcd->state == HC_STATE_HALT) //若root hub处于停止状态  
  30.             usb_hc_died (hcd);  
  31.     }  
  32.     return retval;  
  33. }  

调用usb_new_device添加新设备

[cpp] view plaincopy
  1. int usb_new_device(struct usb_device *udev)  
  2. {  
  3.     int err;  
  4.     if (udev->parent) {  
  5.         device_init_wakeup(&udev->dev, 0);  
  6.     }  
  7.     pm_runtime_set_active(&udev->dev);  
  8.     pm_runtime_enable(&udev->dev);  
  9.     err = usb_enumerate_device(udev);   //读取usb设备描述符      
  10.         if (err < 0)  
  11.         goto fail;  
  12.     dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",udev->devnum, udev->bus->busnum,(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));  
  13.     udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));    //分配设备号  
  14.     announce_device(udev);  //打印设备miOAHUDU  
  15.     device_enable_async_suspend(&udev->dev);  
  16.     err = device_add(&udev->dev);    //设备添加  
  17.     if (err) {  
  18.         dev_err(&udev->dev, "can't device_add, error %d\n", err);  
  19.         goto fail;  
  20.     }  
  21.     (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);  //创建端点设备  
  22.     return err;  
  23. fail:  
  24.     usb_set_device_state(udev, USB_STATE_NOTATTACHED);  
  25.     pm_runtime_disable(&udev->dev);  
  26.     pm_runtime_set_suspended(&udev->dev);  
  27.     return err;  
  28. }   

有些主控器支持uses_new_polling方法则会调用usb_hcd_poll_rh_status函数

[cpp] view plaincopy
  1. void usb_hcd_poll_rh_status(struct usb_hcd *hcd)  
  2. {  
  3.     struct urb  *urb;  
  4.     int     length;  
  5.     unsigned long   flags;  
  6.     char    buffer[6];  
  7.     if (unlikely(!hcd->rh_pollable)) //若不支持轮询  
  8.         return;  
  9.     if (!hcd->uses_new_polling && !hcd->status_urb)   //若没有urb要处理  
  10.         return;  
  11.     length = hcd->driver->hub_status_data(hcd, buffer);   //调用usb主控器驱动的hub_status_data方法  
  12.     if (length > 0) {  
  13.         spin_lock_irqsave(&hcd_root_hub_lock, flags);  
  14.         urb = hcd->status_urb;   //获取待处理的urb  
  15.         if (urb) {  
  16.             clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);   //清除标志位  
  17.             hcd->status_urb = NULL;  //清除待处理urb  
  18.             urb->actual_length = length; //指定处理的urb长度  
  19.             memcpy(urb->transfer_buffer, buffer, length);  
  20.   
  21.             usb_hcd_unlink_urb_from_ep(hcd, urb);//urb与设备端点解绑  
  22.             spin_unlock(&hcd_root_hub_lock);  
  23.             usb_hcd_giveback_urb(hcd, urb, 0);  //处理urb,并返回给usb设备  
  24.             spin_lock(&hcd_root_hub_lock);  
  25.         } else {  
  26.             length = 0;  
  27.             set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);  
  28.         }  
  29.         spin_unlock_irqrestore(&hcd_root_hub_lock, flags);  
  30.     }  
  31.     if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :(length == 0 && hcd->status_urb != NULL))  
  32.         mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));   //修改定时值,激活定时器  
  33. }  

usb_hcd_giveback_urb  //处理urb

[cpp] view plaincopy
  1. void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)  
  2. {  
  3.     urb->hcpriv = NULL;  
  4.     if (unlikely(urb->unlinked))  
  5.         status = urb->unlinked;  
  6.     else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&  
  7.         urb->actual_length < urb->transfer_buffer_length &&!status))  
  8.         status = -EREMOTEIO;  
  9.     unmap_urb_for_dma(hcd, urb);  
  10.     usbmon_urb_complete(&hcd->self, urb, status);  
  11.     usb_unanchor_urb(urb);  
  12.     urb->status = status;  
  13.     urb->complete (urb);     //urb 回调函数  
  14.     atomic_dec (&urb->use_count);  
  15.     if (unlikely(atomic_read(&urb->reject)))  
  16.         wake_up (&usb_kill_urb_queue);  
  17.     usb_put_urb (urb);  
  18. }  
原创粉丝点击