当前位置:   article > 正文

usb主机控制器ehci_usb ehci "dma

usb ehci "dma

1. 主机控制器流程图


device_add()上图和下图的连接!



关于hub_probe()内部的具体实现,详见:点击打开链接


2. echi设备注册

  1. static struct platform_device *nuc970_public_dev[] __initdata = {
  2. &&nuc970_device_ehci,
  3. };
  1. static u64 nuc970_device_usb_ehci_dmamask = 0xffffffffUL;
  2. static struct platform_device nuc970_device_ehci = {
  3. .name = "nuc970-ehci", //平台设备名,用来与设备驱动匹配的
  4. .id = -1,
  5. .num_resources = ARRAY_SIZE(nuc970_ehci_resource),
  6. .resource = nuc970_ehci_resource,
  7. .dev = {
  8. .dma_mask = &nuc970_device_usb_ehci_dmamask,
  9. .coherent_dma_mask = 0xffffffffUL
  10. }
  11. };
  1. static struct resource nuc970_ehci_resource[] = {
  2. [0] = { //寄存器地址
  3. .start = NUC970_PA_EHCI,
  4. .end = NUC970_PA_EHCI + NUC970_SZ_EHCI - 1,
  5. .flags = IORESOURCE_MEM,
  6. },
  7. [1] = { //中断
  8. .start = IRQ_EHCI,
  9. .end = IRQ_EHCI,
  10. .flags = IORESOURCE_IRQ,
  11. }
  12. };

ehci设备注册:

platform_add_devices(nuc970_public_dev, ARRAY_SIZE(nuc970_public_dev));

3. echi平台驱动注册

  1. static int __init ehci_nuc970_init(void)
  2. {
  3. return platform_driver_register(&ehci_hcd_nuc970_driver); //echi平台设备驱动注册
  4. }
  5. static void __exit ehci_nuc970_cleanup(void)
  6. {
  7. platform_driver_unregister(&ehci_hcd_nuc970_driver); //echi平台设备驱动注销
  8. }
  1. static struct platform_driver ehci_hcd_nuc970_driver = { //平台设备驱动
  2. .probe = ehci_nuc970_probe,
  3. .remove = ehci_nuc970_remove,
  4. .driver = {
  5. .name = "nuc970-ehci", //平台设备驱动名称,用来与2.中的平台设备匹配
  6. .owner= THIS_MODULE,
  7. },
  8. };

当platform_device平台设备和platform_driver平台驱动注册到platform总线上时,通过设备名和设备驱动名“nuc970-echi”相匹配,最终调用ehci_nuc970_probe()探测函数,接下来我们将重点分析该函数。

4. ehci_nuc970_probe()

  1. static int ehci_nuc970_probe(struct platform_device *pdev)
  2. {
  3. //printk("ehci_nuc970_probe()\n");
  4. if (usb_disabled())
  5. return -ENODEV;
  6. return usb_nuc970_probe(&ehci_nuc970_hc_driver, pdev); //见下
  7. }

usb_nuc970_probe()的函数参数为平台设备和ehci主机控制器驱动ehci_nuc970_hc_driver,对应结构体如下:

  1. static const struct hc_driver ehci_nuc970_hc_driver = {
  2. .description = hcd_name, //hcd主机控制器名称“ehci-platform”
  3. .product_desc = "Nuvoton NUC970 EHCI Host Controller", //产品描述
  4. .hcd_priv_size = sizeof(struct ehci_hcd), //echi主机控制器大小
  5. /*
  6. * generic hardware linkage
  7. */
  8. .irq = ehci_irq, //echi硬件中断
  9. .flags = HCD_USB2|HCD_MEMORY, //usb2.0 | hcd使用内存(其它就是I/O)
  10. /*
  11. * basic lifecycle operations
  12. */
  13. .reset = ehci_init, //复位主机控制器
  14. .start = ehci_run, //启动主机控制器
  15. .stop = ehci_stop, //停止主机控制器
  16. /*
  17. * managing i/o requests and associated device resources
  18. */
  19. .urb_enqueue = ehci_urb_enqueue, //urq请求队列
  20. .urb_dequeue = ehci_urb_dequeue, //urb释放队列
  21. .endpoint_disable = ehci_endpoint_disable, //端点禁止
  22. /*
  23. * scheduling support
  24. */
  25. .get_frame_number = ehci_get_frame,
  26. /*
  27. * root hub support
  28. */
  29. .hub_status_data = ehci_hub_status_data, //获取hub状态
  30. .hub_control = ehci_hub_control, //hub控制操作
  31. #ifdef CONFIG_PM
  32. .bus_suspend = ehci_bus_suspend,
  33. .bus_resume = ehci_bus_resume,
  34. #endif
  35. };

usb_nuc970_probe()函数:

return usb_nuc970_probe(&ehci_nuc970_hc_driver, pdev);
  1. static int usb_nuc970_probe(const struct hc_driver *driver,
  2. struct platform_device *pdev)
  3. {
  4. struct usb_hcd *hcd;
  5. struct ehci_hcd *ehci;
  6. u32 physical_map_ehci;
  7. struct pinctrl *p;
  8. int retval;
  9. if (IS_ERR(clk_get(NULL, "usbh_hclk"))) {
  10. printk("clk_get error!!\n");
  11. return -1;
  12. }
  13. /* multi-function pin select */
  14. #if defined (CONFIG_NUC970_USBH_PWR_PE)
  15. /* set over-current active low */
  16. __raw_writel(__raw_readl(NUC970_VA_OHCI+0x204) | 0x8, NUC970_VA_OHCI+0x204);
  17. /* initial USBH_PPWR0 & USBH_PPWR1 pin -> PE.14 & PE.15 */
  18. p = devm_pinctrl_get_select(&pdev->dev, "usbh-ppwr-pe");
  19. if (IS_ERR(p))
  20. {
  21. dev_err(&pdev->dev, "unable to reserve pin\n");
  22. retval = PTR_ERR(p);
  23. }
  24. #elif defined (CONFIG_NUC970_USBH_PWR_PF)
  25. /* set over-current active low */
  26. __raw_writel(__raw_readl(NUC970_VA_OHCI+0x204) | 0x8, NUC970_VA_OHCI+0x204);
  27. /* initial USBH_PPWR pin -> PF.10 */
  28. p = devm_pinctrl_get_select(&pdev->dev, "usbh-ppwr-pf");
  29. if (IS_ERR(p))
  30. {
  31. dev_err(&pdev->dev, "unable to reserve pin\n");
  32. retval = PTR_ERR(p);
  33. }
  34. #elif defined (CONFIG_NUC970_USBH_OC_ONLY)
  35. /* set over-current active low */
  36. __raw_writel(__raw_readl(NUC970_VA_OHCI+0x204) | 0x8, NUC970_VA_OHCI+0x204);
  37. p = devm_pinctrl_get_select(&pdev->dev, "usbh-ppwr-oc");
  38. if (IS_ERR(p))
  39. {
  40. dev_err(&pdev->dev, "unable to reserve pin\n");
  41. retval = PTR_ERR(p);
  42. }
  43. #else // CONFIG_NUC970_USBH_NONE
  44. /* set over-current active high */
  45. __raw_writel(__raw_readl(NUC970_VA_OHCI+0x204) &~0x8, NUC970_VA_OHCI+0x204);
  46. #endif
  47. /* Enable USB Host clock */
  48. clk_prepare(clk_get(NULL, "usb_eclk"));
  49. clk_enable(clk_get(NULL, "usb_eclk"));
  50. clk_prepare(clk_get(NULL, "usbh_hclk"));
  51. clk_enable(clk_get(NULL, "usbh_hclk"));
  52. if (pdev->resource[1].flags != IORESOURCE_IRQ) { //判定是否是中断
  53. pr_debug("resource[1] is not IORESOURCE_IRQ");
  54. retval = -ENOMEM;
  55. }
  56. hcd = usb_create_hcd(driver, &pdev->dev, "nuc970-ehci"); //创建一个usb hcd主机控制器(struct usb_hcd)
  57. if (!hcd) {
  58. retval = -ENOMEM;
  59. goto err1;
  60. }
  61. //赋值ehci寄存器地址
  62. hcd->rsrc_start = pdev->resource[0].start;
  63. hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
  64. //申请内存
  65. if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
  66. pr_debug("ehci probe request_mem_region failed");
  67. retval = -EBUSY;
  68. goto err2;
  69. }
  70. //映射内存
  71. hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
  72. if (hcd->regs == NULL) {
  73. pr_debug("ehci error mapping memory\n");
  74. retval = -EFAULT;
  75. goto err3;
  76. }
  77. ehci = hcd_to_ehci(hcd);
  78. ehci->caps = hcd->regs;
  79. ehci->regs = hcd->regs + 0x20;
  80. /* enable PHY 0/1 */
  81. physical_map_ehci = (u32)ehci->caps;
  82. __raw_writel(0x160, physical_map_ehci+0xC4);
  83. __raw_writel(0x520, physical_map_ehci+0xC8);
  84. /* cache this readonly data; minimize chip reads */
  85. ehci->hcs_params = readl(&ehci->caps->hcs_params); //echi结构体参数寄存器
  86. ehci->sbrn = 0x20;
  87. retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); //增加主机控制器
  88. if (retval != 0)
  89. goto err4;
  90. return retval;
  91. err4:
  92. iounmap(hcd->regs);
  93. err3:
  94. release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  95. err2:
  96. usb_put_hcd(hcd);
  97. err1:
  98. return retval;
  99. }

这个函数内部主要时完成一些资源的分配和初始化,我们只关注usb hcd主机控制器的创建和增加,对应的接口函数如下:

  1. hcd = usb_create_hcd(driver, &pdev->dev, "nuc970-ehci"); //创建一个usb hcd主机控制器(struct usb_hcd)
  2. retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); //增加主机控制器

这里我们将逐个分析。

5. usb主机控制器创建

  1. struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
  2. struct device *dev, const char *bus_name)
  3. {
  4. return usb_create_shared_hcd(driver, dev, bus_name, NULL); //创建一个共享的USB hcd控制器
  5. }
  6. EXPORT_SYMBOL_GPL(usb_create_hcd);
  1. struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
  2. struct device *dev, const char *bus_name,
  3. struct usb_hcd *primary_hcd)
  4. {
  5. struct usb_hcd *hcd;
  6. hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); //分配一个usb hcd主机控制器
  7. if (!hcd) {
  8. dev_dbg (dev, "hcd alloc failed\n");
  9. return NULL;
  10. }
  11. //分配"带宽"互斥锁,干啥用的,忘了!!!
  12. if (primary_hcd == NULL) { //=NULL,为真
  13. hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
  14. GFP_KERNEL);
  15. if (!hcd->bandwidth_mutex) {
  16. kfree(hcd);
  17. dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
  18. return NULL;
  19. }
  20. mutex_init(hcd->bandwidth_mutex);
  21. dev_set_drvdata(dev, hcd); //将usb hcd绑定为设备的私有数据
  22. } else {
  23. hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;
  24. hcd->primary_hcd = primary_hcd;
  25. primary_hcd->primary_hcd = primary_hcd;
  26. hcd->shared_hcd = primary_hcd;
  27. primary_hcd->shared_hcd = hcd;
  28. }
  29. kref_init(&hcd->kref);
  30. usb_bus_init(&hcd->self); //usb-hcd 作为一个总线初始化
  31. hcd->self.controller = dev; //绑定设备,对应platform_device
  32. hcd->self.bus_name = bus_name; //usb-hcd总线名称“nuc970-ehci”
  33. hcd->self.uses_dma = (dev->dma_mask != NULL); //主机控制器是否使用DMA,通过platfrom_device知道dev->dma_mask=0xffff
  34. init_timer(&hcd->rh_timer); //初始化一个root-hub定时器
  35. hcd->rh_timer.function = rh_timer_func; //绑定定时器超时的回调函数
  36. hcd->rh_timer.data = (unsigned long) hcd; //回调函数的参数为usb-hcd主机控制器
  37. #ifdef CONFIG_PM_RUNTIME
  38. INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
  39. #endif
  40. hcd->driver = driver; //usb-hcd主机控制器绑定主机控制器驱动driver
  41. hcd->speed = driver->flags & HCD_MASK; //获取主机控制器速率
  42. hcd->product_desc = (driver->product_desc) ? driver->product_desc : //初始化主机控制器的产品描述符
  43. "USB Host Controller";
  44. return hcd;
  45. }

该函数内部主要分配了一个usb-hcd主机控制器,初始化主机控制器root-hub的一个定时器回调函数,最后将主机控制器驱动hcd_driver绑定到usb-hcd主机控制器上,这里要区分他们的关系:

a> struct usb_hcd usb主机控制器

b> struct hc_driver 主机控制器驱动

c> struct usb_bus self 总线

d> struct usb_device *rhdev 设备

6. usb主机控制器添加

retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); //增加主机控制器
  1. int usb_add_hcd(struct usb_hcd *hcd,
  2. unsigned int irqnum, unsigned long irqflags)
  3. {
  4. int retval;
  5. struct usb_device *rhdev;
  6. dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
  7. /* Keep old behaviour if authorized_default is not in [0, 1]. */
  8. /*authorized_default
  9. 的三种设备状态
  10. -1 表示认证无线之外的所有设备
  11. 0 表示不认证任何设备
  12. 1 表示认证所有设备
  13. */
  14. if (authorized_default < 0 || authorized_default > 1)
  15. hcd->authorized_default = hcd->wireless? 0 : 1;
  16. else
  17. hcd->authorized_default = authorized_default;
  18. set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); //设置usb-hcd的状态标识为“上电”
  19. /* HC is in reset state, but accessible. Now do the one-time init,
  20. * bottom up so that hcds can customize the root hubs before khubd
  21. * starts talking to them. (Note, bus id is assigned early too.)
  22. */
  23. if ((retval = hcd_buffer_create(hcd)) != 0) { //创建一个DMA缓冲池
  24. dev_dbg(hcd->self.controller, "pool alloc failed\n");
  25. return retval;
  26. }
  27. if ((retval = usb_register_bus(&hcd->self)) < 0) //注册一个usb-bus
  28. goto err_register_bus;
  29. if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { //分配一个usb设备,作为root_hub
  30. dev_err(hcd->self.controller, "unable to allocate root hub\n");
  31. retval = -ENOMEM;
  32. goto err_allocate_root_hub;
  33. }
  34. hcd->self.root_hub = rhdev;
  35. switch (hcd->speed) {
  36. case HCD_USB11:
  37. rhdev->speed = USB_SPEED_FULL;
  38. break;
  39. case HCD_USB2:
  40. rhdev->speed = USB_SPEED_HIGH;
  41. break;
  42. case HCD_USB3:
  43. rhdev->speed = USB_SPEED_SUPER;
  44. break;
  45. default:
  46. retval = -EINVAL;
  47. goto err_set_rh_speed;
  48. }
  49. /* wakeup flag init defaults to "everything works" for root hubs,
  50. * but drivers can override it in reset() if needed, along with
  51. * recording the overall controller's system wakeup capability.
  52. */
  53. device_set_wakeup_capable(&rhdev->dev, 1);
  54. /* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
  55. * registered. But since the controller can die at any time,
  56. * let's initialize the flag before touching the hardware.
  57. */
  58. set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
  59. /* "reset" is misnamed; its role is now one-time init. the controller
  60. * should already have been reset (and boot firmware kicked off etc).
  61. */
  62. if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
  63. dev_err(hcd->self.controller, "can't setup\n");
  64. goto err_hcd_driver_setup;
  65. }
  66. hcd->rh_pollable = 1;
  67. /* NOTE: root hub and controller capabilities may not be the same */
  68. if (device_can_wakeup(hcd->self.controller)
  69. && device_can_wakeup(&hcd->self.root_hub->dev))
  70. dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
  71. /* enable irqs just before we start the controller,
  72. * if the BIOS provides legacy PCI irqs.
  73. */
  74. if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
  75. retval = usb_hcd_request_irqs(hcd, irqnum, irqflags); //申请中断
  76. if (retval)
  77. goto err_request_irq;
  78. }
  79. hcd->state = HC_STATE_RUNNING;
  80. retval = hcd->driver->start(hcd); //.start = ehci_run
  81. if (retval < 0) {
  82. dev_err(hcd->self.controller, "startup error %d\n", retval);
  83. goto err_hcd_driver_start;
  84. }
  85. /* starting here, usbcore will pay attention to this root hub */
  86. if ((retval = register_root_hub(hcd)) != 0)
  87. goto err_register_root_hub;
  88. retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
  89. if (retval < 0) {
  90. printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
  91. retval);
  92. goto error_create_attr_group;
  93. }
  94. if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
  95. usb_hcd_poll_rh_status(hcd);
  96. /*
  97. * Host controllers don't generate their own wakeup requests;
  98. * they only forward requests from the root hub. Therefore
  99. * controllers should always be enabled for remote wakeup.
  100. */
  101. device_wakeup_enable(hcd->self.controller);
  102. return retval;
  103. error_create_attr_group:
  104. clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
  105. if (HC_IS_RUNNING(hcd->state))
  106. hcd->state = HC_STATE_QUIESCING;
  107. spin_lock_irq(&hcd_root_hub_lock);
  108. hcd->rh_registered = 0;
  109. spin_unlock_irq(&hcd_root_hub_lock);
  110. #ifdef CONFIG_PM_RUNTIME
  111. cancel_work_sync(&hcd->wakeup_work);
  112. #endif
  113. mutex_lock(&usb_bus_list_lock);
  114. usb_disconnect(&rhdev); /* Sets rhdev to NULL */
  115. mutex_unlock(&usb_bus_list_lock);
  116. err_register_root_hub:
  117. hcd->rh_pollable = 0;
  118. clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
  119. del_timer_sync(&hcd->rh_timer);
  120. hcd->driver->stop(hcd);
  121. hcd->state = HC_STATE_HALT;
  122. clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
  123. del_timer_sync(&hcd->rh_timer);
  124. err_hcd_driver_start:
  125. if (usb_hcd_is_primary_hcd(hcd) && hcd->irq > 0)
  126. free_irq(irqnum, hcd);
  127. err_request_irq:
  128. err_hcd_driver_setup:
  129. err_set_rh_speed:
  130. usb_put_dev(hcd->self.root_hub);
  131. err_allocate_root_hub:
  132. usb_deregister_bus(&hcd->self);
  133. err_register_bus:
  134. hcd_buffer_destroy(hcd);
  135. return retval;
  136. }
  137. EXPORT_SYMBOL_GPL(usb_add_hcd);

usb-hcd主机控制器添加,主要完成以下几点:

1> hcd_buffer_create(hcd) 创建一个hcd DMA池;

2> usb_register_bus(&hcd->self) 注册一个usb总线;

3> usb_alloc_dev(NULL, &hcd->self, 0) 分配一个usb-device设备;

4> usb_hcd_request_irqs(hcd, irqnum, irqflags)申请一个hcd中断定时器;

5> register_root_hub(hcd)注册一个root-hub。

这里将逐个分析:

5.1 hcd_buffer_create()

创建DMA池:

hcd_buffer_create()--> dma_pool_create()-->device_create_file(dev, &dev_attr_pools)

static DEVICE_ATTR(pools, S_IRUGO, show_pools, NULL);
  1. static ssize_t
  2. show_pools(struct device *dev, struct device_attribute *attr, char *buf)
  3. {
  4. unsigned temp;
  5. unsigned size;
  6. char *next;
  7. struct dma_page *page;
  8. struct dma_pool *pool;
  9. next = buf;
  10. size = PAGE_SIZE;
  11. temp = scnprintf(next, size, "poolinfo - 0.1\n");
  12. size -= temp;
  13. next += temp;
  14. mutex_lock(&pools_lock);
  15. list_for_each_entry(pool, &dev->dma_pools, pools) {
  16. unsigned pages = 0;
  17. unsigned blocks = 0;
  18. spin_lock_irq(&pool->lock);
  19. list_for_each_entry(page, &pool->page_list, page_list) {
  20. pages++;
  21. blocks += page->in_use;
  22. }
  23. spin_unlock_irq(&pool->lock);
  24. /* per-pool info, no real statistics yet */
  25. temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n",
  26. pool->name, blocks,
  27. pages * (pool->allocation / pool->size),
  28. pool->size, pages);
  29. size -= temp;
  30. next += temp;
  31. }
  32. mutex_unlock(&pools_lock);
  33. return PAGE_SIZE - size;
  34. }

在终端上执行: cat pools命令调用上面的show_pools(),打印如下信息:

  1. [root@szclou /sys/devices/platform/nuc970-ehci]#cat pools
  2. poolinfo - 0.1
  3. ehci_sitd 0 0 96 0
  4. ehci_itd 0 0 160 0
  5. ehci_qh 1 42 96 1
  6. ehci_qtd 1 42 96 1
  7. buffer-2048 0 0 2048 0
  8. buffer-512 0 0 512 0
  9. buffer-128 0 0 128 0
  10. buffer-32 0 0 32 0

至此,属性文件的操作就是用来显示这些信息的,再看一个usb-root信息

dev->dev.groups = usb_device_groups;

其中dev->dev.groups类型为

const struct attribute_group **groups
  1. const struct attribute_group *usb_device_groups[] = {
  2. &dev_attr_grp, //属性组信息
  3. &dev_string_attr_grp, //属性字符串组
  4. NULL
  5. };
  1. static struct attribute_group dev_attr_grp = {
  2. .attrs = dev_attrs,
  3. };
  1. static struct attribute *dev_attrs[] = {
  2. /* current configuration's attributes */
  3. &dev_attr_configuration.attr,
  4. &dev_attr_bNumInterfaces.attr,
  5. &dev_attr_bConfigurationValue.attr,
  6. &dev_attr_bmAttributes.attr,
  7. &dev_attr_bMaxPower.attr,
  8. /* device attributes */
  9. &dev_attr_urbnum.attr,
  10. &dev_attr_idVendor.attr,
  11. &dev_attr_idProduct.attr,
  12. &dev_attr_bcdDevice.attr,
  13. &dev_attr_bDeviceClass.attr,
  14. &dev_attr_bDeviceSubClass.attr,
  15. &dev_attr_bDeviceProtocol.attr,
  16. &dev_attr_bNumConfigurations.attr,
  17. &dev_attr_bMaxPacketSize0.attr,
  18. &dev_attr_speed.attr,
  19. &dev_attr_busnum.attr,
  20. &dev_attr_devnum.attr,
  21. &dev_attr_devpath.attr,
  22. &dev_attr_version.attr,
  23. &dev_attr_maxchild.attr,
  24. &dev_attr_quirks.attr,
  25. &dev_attr_avoid_reset_quirk.attr,
  26. &dev_attr_authorized.attr,
  27. &dev_attr_remove.attr,
  28. &dev_attr_removable.attr,
  29. &dev_attr_ltm_capable.attr,
  30. NULL,
  31. };

  1. static struct attribute_group dev_string_attr_grp = {
  2. .attrs = dev_string_attrs,
  3. .is_visible = dev_string_attrs_are_visible,
  4. };
  1. static struct attribute *dev_string_attrs[] = {
  2. &dev_attr_manufacturer.attr,
  3. &dev_attr_product.attr,
  4. &dev_attr_serial.attr,
  5. NULL
  6. };

*dev_string_attrs[] 和 *dev_attrs[]对应系统目录结构信息为:

  1. [root@szclou /sys/devices/platform/nuc970-ehci/usb1]#ls
  2. 1-0:1.0 bmAttributes maxchild
  3. authorized busnum product
  4. authorized_default configuration quirks
  5. avoid_reset_quirk descriptors removable
  6. bConfigurationValue dev remove
  7. bDeviceClass devnum serial
  8. bDeviceProtocol devpath speed
  9. bDeviceSubClass driver subsystem
  10. bMaxPacketSize0 ep_00 uevent
  11. bMaxPower idProduct urbnum
  12. bNumConfigurations idVendor version
  13. bNumInterfaces ltm_capable
  14. bcdDevice manufacturer

5.2 usb_register_bus()

  1. static int usb_register_bus(struct usb_bus *bus)
  2. {
  3. int result = -E2BIG;
  4. int busnum;
  5. mutex_lock(&usb_bus_list_lock);
  6. busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
  7. if (busnum >= USB_MAXBUS) {
  8. printk (KERN_ERR "%s: too many buses\n", usbcore_name);
  9. goto error_find_busnum;
  10. }
  11. set_bit (busnum, busmap.busmap);
  12. bus->busnum = busnum;
  13. /* Add it to the local list of buses */
  14. list_add (&bus->bus_list, &usb_bus_list); //将当前usb总线添加到usb_bus_list链表中
  15. mutex_unlock(&usb_bus_list_lock);
  16. usb_notify_add_bus(bus);
  17. dev_info (bus->controller, "new USB bus registered, assigned bus "
  18. "number %d\n", bus->busnum);
  19. return 0;
  20. error_find_busnum:
  21. mutex_unlock(&usb_bus_list_lock);
  22. return result;
  23. }

5.3 usb_alloc_dev()

  1. if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { //分配一个usb设备,作为root_hub
  2. dev_err(hcd->self.controller, "unable to allocate root hub\n");
  3. retval = -ENOMEM;
  4. goto err_allocate_root_hub;
  5. }
  6. hcd->self.root_hub = rhdev; //如果上面usb设备分配成功,将作为hcd主机控制器的根设备
  1. struct usb_device *usb_alloc_dev(struct usb_device *parent,
  2. struct usb_bus *bus, unsigned port1)
  3. {
  4. struct usb_device *dev;
  5. struct usb_hcd *usb_hcd = bus_to_hcd(bus);
  6. unsigned root_hub = 0;
  7. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  8. if (!dev)
  9. return NULL;
  10. if (!usb_get_hcd(usb_hcd)) {
  11. kfree(dev);
  12. return NULL;
  13. }
  14. /* Root hubs aren't true devices, so don't allocate HCD resources */
  15. if (usb_hcd->driver->alloc_dev && parent &&
  16. !usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
  17. usb_put_hcd(bus_to_hcd(bus));
  18. kfree(dev);
  19. return NULL;
  20. }
  21. device_initialize(&dev->dev);
  22. dev->dev.bus = &usb_bus_type; //绑定设备的总线为“usb”
  23. dev->dev.type = &usb_device_type; //设备的类型
  24. dev->dev.groups = usb_device_groups; //对sysfs文件系统的属性文件操作,上面有对usb_device_groups分析
  25. dev->dev.dma_mask = bus->controller->dma_mask;
  26. set_dev_node(&dev->dev, dev_to_node(bus->controller));
  27. dev->state = USB_STATE_ATTACHED; //设置usb状态为绑定
  28. dev->lpm_disable_count = 1;
  29. atomic_set(&dev->urbnum, 0);
  30. INIT_LIST_HEAD(&dev->ep0.urb_list);
  31. dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; //设置断点长度
  32. dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; //设置端点描述符
  33. /* ep0 maxpacket comes later, from device descriptor */
  34. usb_enable_endpoint(dev, &dev->ep0, false);
  35. dev->can_submit = 1;
  36. /* Save readable and stable topology id, distinguishing devices
  37. * by location for diagnostics, tools, driver model, etc. The
  38. * string is a path along hub ports, from the root. Each device's
  39. * dev->devpath will be stable until USB is re-cabled, and hubs
  40. * are often labeled with these port numbers. The name isn't
  41. * as stable: bus->busnum changes easily from modprobe order,
  42. * cardbus or pci hotplugging, and so on.
  43. */
  44. if (unlikely(!parent)) {
  45. dev->devpath[0] = '0';
  46. dev->route = 0;
  47. dev->dev.parent = bus->controller;
  48. dev_set_name(&dev->dev, "usb%d", bus->busnum);
  49. root_hub = 1;
  50. } else {
  51. /* match any labeling on the hubs; it's one-based */
  52. if (parent->devpath[0] == '0') {
  53. snprintf(dev->devpath, sizeof dev->devpath,
  54. "%d", port1);
  55. /* Root ports are not counted in route string */
  56. dev->route = 0;
  57. } else {
  58. snprintf(dev->devpath, sizeof dev->devpath,
  59. "%s.%d", parent->devpath, port1);
  60. /* Route string assumes hubs have less than 16 ports */
  61. if (port1 < 15)
  62. dev->route = parent->route +
  63. (port1 << ((parent->level - 1)*4));
  64. else
  65. dev->route = parent->route +
  66. (15 << ((parent->level - 1)*4));
  67. }
  68. dev->dev.parent = &parent->dev;
  69. dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
  70. /* hub driver sets up TT records */
  71. }
  72. dev->portnum = port1;
  73. dev->bus = bus;
  74. dev->parent = parent;
  75. INIT_LIST_HEAD(&dev->filelist);
  76. #ifdef CONFIG_PM
  77. pm_runtime_set_autosuspend_delay(&dev->dev,
  78. usb_autosuspend_delay * 1000);
  79. dev->connect_time = jiffies;
  80. dev->active_duration = -jiffies;
  81. #endif
  82. if (root_hub) /* Root hub always ok [and always wired] */
  83. dev->authorized = 1;
  84. else {
  85. dev->authorized = usb_hcd->authorized_default;
  86. dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
  87. }
  88. return dev;
  89. }

5.4 usb_hcd_request_irqs()

在分析中断之前,先看下中断的处理流程图



  1. if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
  2. retval = usb_hcd_request_irqs(hcd, irqnum, irqflags); //申请中断
  3. if (retval)
  4. goto err_request_irq;
  5. }
  1. static int usb_hcd_request_irqs(struct usb_hcd *hcd,
  2. unsigned int irqnum, unsigned long irqflags)
  3. {
  4. int retval;
  5. if (hcd->driver->irq) {
  6. /* IRQF_DISABLED doesn't work as advertised when used together
  7. * with IRQF_SHARED. As usb_hcd_irq() will always disable
  8. * interrupts we can remove it here.
  9. */
  10. if (irqflags & IRQF_SHARED)
  11. irqflags &= ~IRQF_DISABLED;
  12. snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
  13. hcd->driver->description, hcd->self.busnum);
  14. retval = request_irq(irqnum, &usb_hcd_irq, irqflags, //usb_hcd_irq()函数内部将调用hcd->driver->irq(hcd)
  15. hcd->irq_descr, hcd);
  16. if (retval != 0) {
  17. dev_err(hcd->self.controller,
  18. "request interrupt %d failed\n",
  19. irqnum);
  20. return retval;
  21. }
  22. hcd->irq = irqnum;
  23. dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
  24. (hcd->driver->flags & HCD_MEMORY) ?
  25. "io mem" : "io base",
  26. (unsigned long long)hcd->rsrc_start);
  27. } else {
  28. hcd->irq = 0;
  29. if (hcd->rsrc_start)
  30. dev_info(hcd->self.controller, "%s 0x%08llx\n",
  31. (hcd->driver->flags & HCD_MEMORY) ?
  32. "io mem" : "io base",
  33. (unsigned long long)hcd->rsrc_start);
  34. }
  35. return 0;
  36. }

5.5 register_root_hub()

  1. if ((retval = register_root_hub(hcd)) != 0)
  2. goto err_register_root_hub;
  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,
  10. sizeof usb_dev->bus->devmap.devicemap);
  11. set_bit (devnum, usb_dev->bus->devmap.devicemap); //设备编号屏蔽字
  12. usb_set_device_state(usb_dev, USB_STATE_ADDRESS); //设置usb设备状态,当前为USB_STATE_ADDRESS
  13. mutex_lock(&usb_bus_list_lock);
  14. usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); //给端点0描述符分配64个字节长度空间
  15. retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); //获取设备描述符,包括配置,接口,端点
  16. if (retval != sizeof usb_dev->descriptor) {
  17. mutex_unlock(&usb_bus_list_lock);
  18. dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
  19. dev_name(&usb_dev->dev), retval);
  20. return (retval < 0) ? retval : -EMSGSIZE;
  21. }
  22. if (usb_dev->speed == USB_SPEED_SUPER) { //usb3.0,暂时不分析
  23. retval = usb_get_bos_descriptor(usb_dev);
  24. if (retval < 0) {
  25. mutex_unlock(&usb_bus_list_lock);
  26. dev_dbg(parent_dev, "can't read %s bos descriptor %d\n",
  27. dev_name(&usb_dev->dev), retval);
  28. return retval;
  29. }
  30. }
  31. retval = usb_new_device (usb_dev); //新建一个usb设备
  32. if (retval) {
  33. dev_err (parent_dev, "can't register root hub for %s, %d\n",
  34. dev_name(&usb_dev->dev), retval);
  35. } else {
  36. spin_lock_irq (&hcd_root_hub_lock);
  37. hcd->rh_registered = 1;
  38. spin_unlock_irq (&hcd_root_hub_lock);
  39. /* Did the HC die before the root hub was registered? */
  40. if (HCD_DEAD(hcd))
  41. usb_hc_died (hcd); /* This time clean up */
  42. }
  43. mutex_unlock(&usb_bus_list_lock);
  44. return retval;
  45. }

该函数主要完成的工作时给usb设备分配一个编号(范围1~127),获取设备描述符usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE),这里使用了一个技巧,因为不知道设备描述符里面有多少个配置,配置里有多少个接口,所以这里直接读取USB_DT_DEVICE_SIZE个字节,而这个字节的长度恰好对应设备描述符的结构体成员长度,如下:

  1. /* USB_DT_DEVICE: Device descriptor */
  2. struct usb_device_descriptor {
  3. __u8 bLength;//设备描述符的字节数大小,为0x12
  4. __u8 bDescriptorType;//描述符类型编号,为0x01
  5. __le16 bcdUSB;//USB版本号
  6. __u8 bDeviceClass;//USB分配的设备类代码,0x01~0xfe为标准设备类,0xff为厂商自定义类型
  7. //0x00不是在设备描述符中定义的,如HID
  8. __u8 bDeviceSubClass;//usb分配的子类代码,同上,值由USB规定和分配的
  9. __u8 bDeviceProtocol;//USB分配的设备协议代码,同上
  10. __u8 bMaxPacketSize0;//端点0的最大包的大小
  11. __le16 idVendor;//厂商编号
  12. __le16 idProduct;//产品编号
  13. __le16 bcdDevice;//设备出厂编号
  14. __u8 iManufacturer;//描述厂商字符串的索引
  15. __u8 iProduct;//描述产品字符串的索引
  16. __u8 iSerialNumber;//描述设备序列号字符串的索引
  17. __u8 bNumConfigurations;//可能的配置数量
  18. } __attribute__ ((packed));

再后续时创建了一个新的usb设备,下面将详细分析。

5.6 usb_new_device

先贴出流程图

retval = usb_new_device (usb_dev); //新建一个usb设备
  1. int usb_new_device(struct usb_device *udev)
  2. {
  3. int err;
  4. if (udev->parent) {
  5. /* Initialize non-root-hub device wakeup to disabled;
  6. * device (un)configuration controls wakeup capable
  7. * sysfs power/wakeup controls wakeup enabled/disabled
  8. */
  9. device_init_wakeup(&udev->dev, 0);
  10. }
  11. /* Tell the runtime-PM framework the device is active */
  12. pm_runtime_set_active(&udev->dev);
  13. pm_runtime_get_noresume(&udev->dev);
  14. pm_runtime_use_autosuspend(&udev->dev);
  15. pm_runtime_enable(&udev->dev);
  16. /* By default, forbid autosuspend for all devices. It will be
  17. * allowed for hubs during binding.
  18. */
  19. usb_disable_autosuspend(udev);
  20. //枚举设备
  21. err = usb_enumerate_device(udev); /* Read descriptors */
  22. if (err < 0)
  23. goto fail;
  24. dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",
  25. udev->devnum, udev->bus->busnum,
  26. (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
  27. /* export the usbdev device-node for libusb */
  28. udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
  29. (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
  30. /* Tell the world! */
  31. announce_device(udev);
  32. if (udev->serial)
  33. add_device_randomness(udev->serial, strlen(udev->serial));
  34. if (udev->product)
  35. add_device_randomness(udev->product, strlen(udev->product));
  36. if (udev->manufacturer)
  37. add_device_randomness(udev->manufacturer,
  38. strlen(udev->manufacturer));
  39. device_enable_async_suspend(&udev->dev);
  40. /*
  41. * check whether the hub marks this port as non-removable. Do it
  42. * now so that platform-specific data can override it in
  43. * device_add()
  44. */
  45. if (udev->parent)
  46. set_usb_port_removable(udev);
  47. /* Register the device. The device driver is responsible
  48. * for configuring the device and invoking the add-device
  49. * notifier chain (used by usbfs and possibly others).
  50. */
  51. err = device_add(&udev->dev);
  52. if (err) {
  53. dev_err(&udev->dev, "can't device_add, error %d\n", err);
  54. goto fail;
  55. }
  56. /* Create link files between child device and usb port device. */
  57. if (udev->parent) {
  58. struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
  59. struct usb_port *port_dev = hub->ports[udev->portnum - 1];
  60. err = sysfs_create_link(&udev->dev.kobj,
  61. &port_dev->dev.kobj, "port");
  62. if (err)
  63. goto fail;
  64. err = sysfs_create_link(&port_dev->dev.kobj,
  65. &udev->dev.kobj, "device");
  66. if (err) {
  67. sysfs_remove_link(&udev->dev.kobj, "port");
  68. goto fail;
  69. }
  70. pm_runtime_get_sync(&port_dev->dev);
  71. }
  72. (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
  73. usb_mark_last_busy(udev);
  74. pm_runtime_put_sync_autosuspend(&udev->dev);
  75. return err;
  76. fail:
  77. usb_set_device_state(udev, USB_STATE_NOTATTACHED);
  78. pm_runtime_disable(&udev->dev);
  79. pm_runtime_set_suspended(&udev->dev);
  80. return err;
  81. }

这里主要分析设备枚举,是这里最核心的一个地方!!!

  1. //枚举设备
  2. err = usb_enumerate_device(udev); /* Read descriptors */
  1. static int usb_enumerate_device(struct usb_device *udev)
  2. {
  3. int err;
  4. if (udev->config == NULL) {
  5. err = usb_get_configuration(udev); //获取配置信息
  6. if (err < 0) {
  7. if (err != -ENODEV)
  8. dev_err(&udev->dev, "can't read configurations, error %d\n",
  9. err);
  10. return err;
  11. }
  12. }
  13. /* read the standard strings and cache them if present */
  14. udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
  15. udev->manufacturer = usb_cache_string(udev,
  16. udev->descriptor.iManufacturer);
  17. udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
  18. err = usb_enumerate_device_otg(udev);
  19. if (err < 0)
  20. return err;
  21. usb_detect_interface_quirks(udev);
  22. return 0;
  23. }

5.6.1 获取配置信息

  1. if (udev->config == NULL) {
  2. err = usb_get_configuration(udev);
  3. if (err < 0) {
  4. if (err != -ENODEV)
  5. dev_err(&udev->dev, "can't read configurations, error %d\n",
  6. err);
  7. return err;
  8. }
  9. }
  1. int usb_get_configuration(struct usb_device *dev)
  2. {
  3. struct device *ddev = &dev->dev;
  4. int ncfg = dev->descriptor.bNumConfigurations; //usb配置个数
  5. int result = 0;
  6. unsigned int cfgno, length;
  7. unsigned char *bigbuffer;
  8. struct usb_config_descriptor *desc;
  9. cfgno = 0;
  10. result = -ENOMEM;
  11. if (ncfg > USB_MAXCONFIG) {
  12. dev_warn(ddev, "too many configurations: %d, "
  13. "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
  14. dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
  15. }
  16. if (ncfg < 1) {
  17. dev_err(ddev, "no configurations\n");
  18. return -EINVAL;
  19. }
  20. length = ncfg * sizeof(struct usb_host_config);
  21. dev->config = kzalloc(length, GFP_KERNEL); //分配一个设备下的ncfg个config配置结构体
  22. if (!dev->config)
  23. goto err2;
  24. length = ncfg * sizeof(char *);
  25. dev->rawdescriptors = kzalloc(length, GFP_KERNEL); //分配ncfg个char指针
  26. if (!dev->rawdescriptors)
  27. goto err2;
  28. desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
  29. if (!desc)
  30. goto err2;
  31. result = 0;
  32. for (; cfgno < ncfg; cfgno++) {
  33. /* We grab just the first descriptor so we know how long
  34. * the whole configuration is */
  35. result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
  36. desc, USB_DT_CONFIG_SIZE); //由于无法知道配置的长度,这里使用一个小技巧,先读取配置USB_DT_CONFIG_SIZE个字节,从该长度内部可以获取配置下的接口长度,所以这里会读取两次,这是第一次!!!
  37. if (result < 0) {
  38. dev_err(ddev, "unable to read config index %d "
  39. "descriptor/%s: %d\n", cfgno, "start", result);
  40. if (result != -EPIPE)
  41. goto err;
  42. dev_err(ddev, "chopping to %d config(s)\n", cfgno);
  43. dev->descriptor.bNumConfigurations = cfgno;
  44. break;
  45. } else if (result < 4) {
  46. dev_err(ddev, "config index %d descriptor too short "
  47. "(expected %i, got %i)\n", cfgno,
  48. USB_DT_CONFIG_SIZE, result);
  49. result = -EINVAL;
  50. goto err;
  51. }
  52. length = max((int) le16_to_cpu(desc->wTotalLength), //获取当前配置的的总长度
  53. USB_DT_CONFIG_SIZE);
  54. /* Now that we know the length, get the whole thing */
  55. bigbuffer = kmalloc(length, GFP_KERNEL);
  56. if (!bigbuffer) {
  57. result = -ENOMEM;
  58. goto err;
  59. }
  60. //获取配置的所有长度信息,这里是第二次读取!!!
  61. result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
  62. bigbuffer, length);
  63. if (result < 0) {
  64. dev_err(ddev, "unable to read config index %d "
  65. "descriptor/%s\n", cfgno, "all");
  66. kfree(bigbuffer);
  67. goto err;
  68. }
  69. if (result < length) {
  70. dev_warn(ddev, "config index %d descriptor too short "
  71. "(expected %i, got %i)\n", cfgno, length, result);
  72. length = result;
  73. }
  74. dev->rawdescriptors[cfgno] = bigbuffer; //每一个指针指向一个配置
  75. //解析配置信息
  76. result = usb_parse_configuration(dev, cfgno,
  77. &dev->config[cfgno], bigbuffer, length);
  78. if (result < 0) {
  79. ++cfgno;
  80. goto err;
  81. }
  82. }
  83. result = 0;
  84. err:
  85. kfree(desc);
  86. dev->descriptor.bNumConfigurations = cfgno;
  87. err2:
  88. if (result == -ENOMEM)
  89. dev_err(ddev, "out of memory\n");
  90. return result;
  91. }

5.6.2 解析配置信息

  1. //解析配置信息
  2. result = usb_parse_configuration(dev, cfgno,
  3. &dev->config[cfgno], bigbuffer, length);
  1. static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
  2. struct usb_host_config *config, unsigned char *buffer, int size)
  3. {
  4. struct device *ddev = &dev->dev;
  5. unsigned char *buffer0 = buffer;
  6. int cfgno;
  7. int nintf, nintf_orig;
  8. int i, j, n;
  9. struct usb_interface_cache *intfc;
  10. unsigned char *buffer2;
  11. int size2;
  12. struct usb_descriptor_header *header;
  13. int len, retval;
  14. u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
  15. unsigned iad_num = 0;
  16. memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); //拷贝当前配置信息到config->desc
  17. if (config->desc.bDescriptorType != USB_DT_CONFIG ||
  18. config->desc.bLength < USB_DT_CONFIG_SIZE ||
  19. config->desc.bLength > size) {
  20. dev_err(ddev, "invalid descriptor for config index %d: "
  21. "type = 0x%X, length = %d\n", cfgidx,
  22. config->desc.bDescriptorType, config->desc.bLength);
  23. return -EINVAL;
  24. }
  25. cfgno = config->desc.bConfigurationValue; //当前配置编号值
  26. //这里偏移buffer的目的是啥???不过下面又开始计算配置下的接口了!!!
  27. //上面是以前的疑问,现在明白了,buffer += config->desc.bLength 表示跳过配置的内容,直接跳转到接口
  28. buffer += config->desc.bLength; //偏移到接口
  29. size -= config->desc.bLength; //减去配置的长度
  30. nintf = nintf_orig = config->desc.bNumInterfaces; //接口个数
  31. if (nintf > USB_MAXINTERFACES) {
  32. dev_warn(ddev, "config %d has too many interfaces: %d, "
  33. "using maximum allowed: %d\n",
  34. cfgno, nintf, USB_MAXINTERFACES);
  35. nintf = USB_MAXINTERFACES;
  36. }
  37. /* Go through the descriptors, checking their length and counting the
  38. * number of altsettings for each interface */
  39. n = 0;
  40. for ((buffer2 = buffer, size2 = size); //遍历接口
  41. size2 > 0;
  42. (buffer2 += header->bLength, size2 -= header->bLength)) {
  43. if (size2 < sizeof(struct usb_descriptor_header)) {
  44. dev_warn(ddev, "config %d descriptor has %d excess "
  45. "byte%s, ignoring\n",
  46. cfgno, size2, plural(size2));
  47. break;
  48. }
  49. header = (struct usb_descriptor_header *) buffer2; //这里先获取描述符接口的长度和描述符的类型(这里类型为接口)两个字段
  50. if ((header->bLength > size2) || (header->bLength < 2)) {
  51. dev_warn(ddev, "config %d has an invalid descriptor "
  52. "of length %d, skipping remainder of the config\n",
  53. cfgno, header->bLength);
  54. break;
  55. }
  56. if (header->bDescriptorType == USB_DT_INTERFACE) { //是接口
  57. struct usb_interface_descriptor *d;
  58. int inum;
  59. d = (struct usb_interface_descriptor *) header; //上面通过两个字段确定了为接口,这里直接转换为接口描述符 struct usb_interface_descriptor
  60. if (d->bLength < USB_DT_INTERFACE_SIZE) {
  61. dev_warn(ddev, "config %d has an invalid "
  62. "interface descriptor of length %d, "
  63. "skipping\n", cfgno, d->bLength);
  64. continue;
  65. }
  66. inum = d->bInterfaceNumber; //获取接口的编号
  67. if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
  68. n >= nintf_orig) {
  69. dev_warn(ddev, "config %d has more interface "
  70. "descriptors, than it declares in "
  71. "bNumInterfaces, ignoring interface "
  72. "number: %d\n", cfgno, inum);
  73. continue;
  74. }
  75. if (inum >= nintf_orig) //当前接口编号是否大于总得接口个数
  76. dev_warn(ddev, "config %d has an invalid "
  77. "interface number: %d but max is %d\n",
  78. cfgno, inum, nintf_orig - 1);
  79. /* Have we already encountered this interface?
  80. * Count its altsettings */
  81. for (i = 0; i < n; ++i) {
  82. if (inums[i] == inum) //确定之前是否已经统计了该接口
  83. break;
  84. }
  85. if (i < n) { //
  86. if (nalts[i] < 255)
  87. ++nalts[i]; //对当前接口编号相同的进行统计(初始化为1,在else if语句中)
  88. } else if (n < USB_MAXINTERFACES) {
  89. inums[n] = inum; //记录当前接口的编号到inums数组中
  90. nalts[n] = 1; //初始化当前接口值为1
  91. ++n;
  92. }
  93. } else if (header->bDescriptorType ==
  94. USB_DT_INTERFACE_ASSOCIATION) {
  95. if (iad_num == USB_MAXIADS) {
  96. dev_warn(ddev, "found more Interface "
  97. "Association Descriptors "
  98. "than allocated for in "
  99. "configuration %d\n", cfgno);
  100. } else {
  101. config->intf_assoc[iad_num] =
  102. (struct usb_interface_assoc_descriptor
  103. *)header;
  104. iad_num++;
  105. }
  106. } else if (header->bDescriptorType == USB_DT_DEVICE ||
  107. header->bDescriptorType == USB_DT_CONFIG)
  108. dev_warn(ddev, "config %d contains an unexpected "
  109. "descriptor of type 0x%X, skipping\n",
  110. cfgno, header->bDescriptorType);
  111. } /* for ((buffer2 = buffer, size2 = size); ...) */
  112. size = buffer2 - buffer; //size=一个配置中所有接口描述符的长度
  113. config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0); //config->desc.wTotalLength = 一个配置和接口描述符的总长度
  114. if (n != nintf)
  115. dev_warn(ddev, "config %d has %d interface%s, different from "
  116. "the descriptor's value: %d\n",
  117. cfgno, n, plural(n), nintf_orig);
  118. else if (n == 0)
  119. dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
  120. config->desc.bNumInterfaces = nintf = n;
  121. /* Check for missing interface numbers */
  122. for (i = 0; i < nintf; ++i) { //由于inums数组中存储的是随机接口编号,所以这里通过从小到大的顺序检测是否正常,否则输出调试警告
  123. for (j = 0; j < nintf; ++j) {
  124. if (inums[j] == i)
  125. break;
  126. }
  127. if (j >= nintf)
  128. dev_warn(ddev, "config %d has no interface number "
  129. "%d\n", cfgno, i);
  130. }
  131. /* Allocate the usb_interface_caches and altsetting arrays */
  132. for (i = 0; i < nintf; ++i) { //遍历接口
  133. j = nalts[i];
  134. if (j > USB_MAXALTSETTING) {
  135. dev_warn(ddev, "too many alternate settings for "
  136. "config %d interface %d: %d, "
  137. "using maximum allowed: %d\n",
  138. cfgno, inums[i], j, USB_MAXALTSETTING);
  139. nalts[i] = j = USB_MAXALTSETTING;
  140. }
  141. //sizeof(*intfc): 接口缓存的长度
  142. //sizeof(struct usb_host_interface) * j: 表示一个主机控制的长度*接口个数
  143. len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
  144. //表示一个接口的缓存(包括接口轮流, 因为存在多个相同的接口编号)
  145. config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
  146. if (!intfc)
  147. return -ENOMEM;
  148. kref_init(&intfc->ref);
  149. }
  150. /* FIXME: parse the BOS descriptor */
  151. /* Skip over any Class Specific or Vendor Specific descriptors;
  152. * find the first interface descriptor */
  153. config->extra = buffer; //处理设备中要求的接口个数,之外的接口数据
  154. i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
  155. USB_DT_INTERFACE, &n);
  156. config->extralen = i;
  157. if (n > 0)
  158. dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
  159. n, plural(n), "configuration");
  160. buffer += i;
  161. size -= i;
  162. /* Parse all the interface/altsetting descriptors */
  163. while (size > 0) {
  164. //解析接口数据
  165. retval = usb_parse_interface(ddev, cfgno, config,
  166. buffer, size, inums, nalts);
  167. if (retval < 0)
  168. return retval;
  169. buffer += retval;
  170. size -= retval;
  171. }
  172. /* Check for missing altsettings */
  173. for (i = 0; i < nintf; ++i) {
  174. intfc = config->intf_cache[i];
  175. for (j = 0; j < intfc->num_altsetting; ++j) {
  176. for (n = 0; n < intfc->num_altsetting; ++n) {
  177. if (intfc->altsetting[n].desc.
  178. bAlternateSetting == j)
  179. break;
  180. }
  181. if (n >= intfc->num_altsetting)
  182. dev_warn(ddev, "config %d interface %d has no "
  183. "altsetting %d\n", cfgno, inums[i], j);
  184. }
  185. }
  186. return 0;
  187. }

5.6.3 解析接口信息

  1. while (size > 0) {
  2. //解析接口数据
  3. retval = usb_parse_interface(ddev, cfgno, config,
  4. buffer, size, inums, nalts);
  5. if (retval < 0)
  6. return retval;
  7. buffer += retval;
  8. size -= retval;
  9. }
  1. static int usb_parse_interface(struct device *ddev, int cfgno,
  2. struct usb_host_config *config, unsigned char *buffer, int size,
  3. u8 inums[], u8 nalts[])
  4. {
  5. unsigned char *buffer0 = buffer;
  6. struct usb_interface_descriptor *d;
  7. int inum, asnum;
  8. struct usb_interface_cache *intfc;
  9. struct usb_host_interface *alt;
  10. int i, n;
  11. int len, retval;
  12. int num_ep, num_ep_orig;
  13. d = (struct usb_interface_descriptor *) buffer; //获取接口描述符信息
  14. buffer += d->bLength;
  15. size -= d->bLength;
  16. if (d->bLength < USB_DT_INTERFACE_SIZE)
  17. goto skip_to_next_interface_descriptor;
  18. /* Which interface entry is this? */
  19. intfc = NULL;
  20. inum = d->bInterfaceNumber; //接口编号
  21. for (i = 0; i < config->desc.bNumInterfaces; ++i) { //根据设备中获取的接口总数,遍历接口,匹配与当前inum接口编号相等的
  22. if (inums[i] == inum) {
  23. intfc = config->intf_cache[i]; //获取接口缓存信息
  24. break;
  25. }
  26. }
  27. if (!intfc || intfc->num_altsetting >= nalts[i])
  28. goto skip_to_next_interface_descriptor;
  29. /* Check for duplicate altsetting entries */
  30. asnum = d->bAlternateSetting;
  31. for ((i = 0, alt = &intfc->altsetting[0]);
  32. i < intfc->num_altsetting;
  33. (++i, ++alt)) {
  34. if (alt->desc.bAlternateSetting == asnum) {
  35. dev_warn(ddev, "Duplicate descriptor for config %d "
  36. "interface %d altsetting %d, skipping\n",
  37. cfgno, inum, asnum);
  38. goto skip_to_next_interface_descriptor;
  39. }
  40. }
  41. ++intfc->num_altsetting;
  42. memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE); //拷贝一个接口描述符
  43. /* Skip over any Class Specific or Vendor Specific descriptors;
  44. * find the first endpoint or interface descriptor */
  45. alt->extra = buffer;
  46. i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  47. USB_DT_INTERFACE, &n);
  48. alt->extralen = i;
  49. if (n > 0)
  50. dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
  51. n, plural(n), "interface");
  52. buffer += i;
  53. size -= i;
  54. /* Allocate space for the right(?) number of endpoints */
  55. num_ep = num_ep_orig = alt->desc.bNumEndpoints; //获取接口的端点个数
  56. alt->desc.bNumEndpoints = 0; /* Use as a counter */
  57. if (num_ep > USB_MAXENDPOINTS) {
  58. dev_warn(ddev, "too many endpoints for config %d interface %d "
  59. "altsetting %d: %d, using maximum allowed: %d\n",
  60. cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
  61. num_ep = USB_MAXENDPOINTS;
  62. }
  63. if (num_ep > 0) {
  64. /* Can't allocate 0 bytes */
  65. len = sizeof(struct usb_host_endpoint) * num_ep; //分配端点个数的空间
  66. alt->endpoint = kzalloc(len, GFP_KERNEL);
  67. if (!alt->endpoint)
  68. return -ENOMEM;
  69. }
  70. /* Parse all the endpoint descriptors */
  71. n = 0;
  72. while (size > 0) {
  73. if (((struct usb_descriptor_header *) buffer)->bDescriptorType
  74. == USB_DT_INTERFACE)
  75. break;
  76. //解析端点
  77. retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
  78. num_ep, buffer, size);
  79. if (retval < 0)
  80. return retval;
  81. ++n;
  82. buffer += retval;
  83. size -= retval;
  84. }
  85. if (n != num_ep_orig)
  86. dev_warn(ddev, "config %d interface %d altsetting %d has %d "
  87. "endpoint descriptor%s, different from the interface "
  88. "descriptor's value: %d\n",
  89. cfgno, inum, asnum, n, plural(n), num_ep_orig);
  90. return buffer - buffer0;
  91. skip_to_next_interface_descriptor:
  92. i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
  93. USB_DT_INTERFACE, NULL);
  94. return buffer - buffer0 + i;
  95. }

5.6.4 解析端点

  1. //解析端点
  2. retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
  3. num_ep, buffer, size);
  1. static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
  2. int asnum, struct usb_host_interface *ifp, int num_ep,
  3. unsigned char *buffer, int size)
  4. {
  5. unsigned char *buffer0 = buffer;
  6. struct usb_endpoint_descriptor *d;
  7. struct usb_host_endpoint *endpoint;
  8. int n, i, j, retval;
  9. d = (struct usb_endpoint_descriptor *) buffer; //获取端点描述符
  10. buffer += d->bLength;
  11. size -= d->bLength;
  12. if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE)
  13. n = USB_DT_ENDPOINT_AUDIO_SIZE;
  14. else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
  15. n = USB_DT_ENDPOINT_SIZE;
  16. else {
  17. dev_warn(ddev, "config %d interface %d altsetting %d has an "
  18. "invalid endpoint descriptor of length %d, skipping\n",
  19. cfgno, inum, asnum, d->bLength);
  20. goto skip_to_next_endpoint_or_interface_descriptor;
  21. }
  22. i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
  23. if (i >= 16 || i == 0) {
  24. dev_warn(ddev, "config %d interface %d altsetting %d has an "
  25. "invalid endpoint with address 0x%X, skipping\n",
  26. cfgno, inum, asnum, d->bEndpointAddress);
  27. goto skip_to_next_endpoint_or_interface_descriptor;
  28. }
  29. /* Only store as many endpoints as we have room for */
  30. if (ifp->desc.bNumEndpoints >= num_ep)
  31. goto skip_to_next_endpoint_or_interface_descriptor;
  32. endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
  33. ++ifp->desc.bNumEndpoints;
  34. memcpy(&endpoint->desc, d, n);
  35. INIT_LIST_HEAD(&endpoint->urb_list);
  36. /* Fix up bInterval values outside the legal range. Use 32 ms if no
  37. * proper value can be guessed. */
  38. //根据不同速率的usb,计算时间
  39. i = 0; /* i = min, j = max, n = default */
  40. j = 255;
  41. if (usb_endpoint_xfer_int(d)) {
  42. i = 1;
  43. switch (to_usb_device(ddev)->speed) {
  44. case USB_SPEED_SUPER:
  45. case USB_SPEED_HIGH:
  46. /* Many device manufacturers are using full-speed
  47. * bInterval values in high-speed interrupt endpoint
  48. * descriptors. Try to fix those and fall back to a
  49. * 32 ms default value otherwise. */
  50. n = fls(d->bInterval*8);
  51. if (n == 0)
  52. n = 9; /* 32 ms = 2^(9-1) uframes */
  53. j = 16;
  54. break;
  55. default: /* USB_SPEED_FULL or _LOW */
  56. /* For low-speed, 10 ms is the official minimum.
  57. * But some "overclocked" devices might want faster
  58. * polling so we'll allow it. */
  59. n = 32;
  60. break;
  61. }
  62. } else if (usb_endpoint_xfer_isoc(d)) {
  63. i = 1;
  64. j = 16;
  65. switch (to_usb_device(ddev)->speed) {
  66. case USB_SPEED_HIGH:
  67. n = 9; /* 32 ms = 2^(9-1) uframes */
  68. break;
  69. default: /* USB_SPEED_FULL */
  70. n = 6; /* 32 ms = 2^(6-1) frames */
  71. break;
  72. }
  73. }
  74. if (d->bInterval < i || d->bInterval > j) {
  75. dev_warn(ddev, "config %d interface %d altsetting %d "
  76. "endpoint 0x%X has an invalid bInterval %d, "
  77. "changing to %d\n",
  78. cfgno, inum, asnum,
  79. d->bEndpointAddress, d->bInterval, n);
  80. endpoint->desc.bInterval = n;
  81. }
  82. /* Some buggy low-speed devices have Bulk endpoints, which is
  83. * explicitly forbidden by the USB spec. In an attempt to make
  84. * them usable, we will try treating them as Interrupt endpoints.
  85. */
  86. if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
  87. usb_endpoint_xfer_bulk(d)) {
  88. dev_warn(ddev, "config %d interface %d altsetting %d "
  89. "endpoint 0x%X is Bulk; changing to Interrupt\n",
  90. cfgno, inum, asnum, d->bEndpointAddress);
  91. endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
  92. endpoint->desc.bInterval = 1;
  93. if (usb_endpoint_maxp(&endpoint->desc) > 8)
  94. endpoint->desc.wMaxPacketSize = cpu_to_le16(8); //低速设备端点字节为8个
  95. }
  96. /*
  97. * Some buggy high speed devices have bulk endpoints using
  98. * maxpacket sizes larger than 64 under full-speed mode.
  99. * Full speed HCDs may not
  100. * be able to handle that particular bug, so let's modify
  101. * the maxpacket size to make it work.
  102. */
  103. if (to_usb_device(ddev)->speed == USB_SPEED_FULL
  104. && usb_endpoint_xfer_bulk(d)) {
  105. if (usb_endpoint_maxp(&endpoint->desc) > 64)
  106. endpoint->desc.wMaxPacketSize = cpu_to_le16(64); //全速设备端点字节为64个
  107. }
  108. /*
  109. * Some buggy high speed devices have bulk endpoints using
  110. * maxpacket sizes other than 512. High speed HCDs may not
  111. * be able to handle that particular bug, so let's warn...
  112. */
  113. if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
  114. && usb_endpoint_xfer_bulk(d)) {
  115. unsigned maxp;
  116. maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff; //高速设备端点字节数。。。
  117. if (maxp != 512)
  118. dev_warn(ddev, "config %d interface %d altsetting %d "
  119. "bulk endpoint 0x%X has invalid maxpacket %d\n",
  120. cfgno, inum, asnum, d->bEndpointAddress,
  121. maxp);
  122. }
  123. /* Parse a possible SuperSpeed endpoint companion descriptor */
  124. if (to_usb_device(ddev)->speed == USB_SPEED_SUPER)
  125. usb_parse_ss_endpoint_companion(ddev, cfgno,
  126. inum, asnum, endpoint, buffer, size);
  127. /* Skip over any Class Specific or Vendor Specific descriptors;
  128. * find the next endpoint or interface descriptor */
  129. endpoint->extra = buffer;
  130. i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  131. USB_DT_INTERFACE, &n);
  132. endpoint->extralen = i;
  133. retval = buffer - buffer0 + i;
  134. if (n > 0)
  135. dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
  136. n, plural(n), "endpoint");
  137. return retval;
  138. skip_to_next_endpoint_or_interface_descriptor:
  139. i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  140. USB_DT_INTERFACE, NULL);
  141. return buffer - buffer0 + i;
  142. }

端点部分主要工作是,根据不同速率的usb,传输不同的字节数,以及主机查询端点的间隔时间。至此分析完了枚举一个usb主机控制器的过程:设备-->N个配置-->N个接口-->N个端点,最后通过如下函数输出控制器的功能信息

6. 输出主机控制器信息

	announce_device(udev);
  1. static void announce_device(struct usb_device *udev)
  2. {
  3. dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",
  4. le16_to_cpu(udev->descriptor.idVendor),
  5. le16_to_cpu(udev->descriptor.idProduct));
  6. dev_info(&udev->dev,
  7. "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
  8. udev->descriptor.iManufacturer,
  9. udev->descriptor.iProduct,
  10. udev->descriptor.iSerialNumber);
  11. show_string(udev, "Product", udev->product);
  12. show_string(udev, "Manufacturer", udev->manufacturer);
  13. show_string(udev, "SerialNumber", udev->serial);
  14. }

系统启动时输出上述信息:

  1. usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
  2. usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
  3. usb usb1: Product: Nuvoton NUC970 EHCI Host Controller
  4. usb usb1: Manufacturer: Linux 3.10.32 ehci_hcd
  5. usb usb1: SerialNumber: nuc970-ehci

7. 总结

      本文开始通过platform总线完成ehci设备和驱动的匹配调用探测函数ehci_nuc970_probe(),在该函数内部完成主机控制器的寄存器资源分配,然后注册一个hcd主机控制器(包括是否使用DMA池),然后增加主机控制器到usb总线上,然后注册一个根hub,期间包括最重要的部分,即设备枚举,在枚举的过程,先获取设备,通过设备获取接口,因接口长度未定,所以分两次读取接口信息,即第一次读取固定长度的接口信息,第二次根据第一次的描述符信息里的长度再读取整个接口信息,最后根据接口信息解析端点,最后将该主机控制器的根hub注册到usb总线上。





















本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号