USB驱动程序(一)————USB主机控制器驱动——OHCI分析

来源:互联网 发布:淘宝聘用店主 编辑:程序博客网 时间:2024/05/22 07:58

本文以 2440-ohci 驱动为例,简单分析 USB 主机控制器驱动 根 Hub 的注册过程,以及 USB设备的枚举过程,并不涉及USB协议,单纯分析驱动框架流程。无论是hub还是普通的usb设备,它们注册到 usb_bus_type 都会经历两次 Match ,因为第一次注册进来时,是将整个设备作为一个 device 注册,然后在通用的 devices 驱动程序 usb_generic_driver 的 generic_probe 函数中,将该设备的所有接口进行设置并将这些接口注册到 usb_bus_type 。如果是Hub设备的接口,则会调用 hub_probe,如果是其他设备则调用 xx_probe 函数。如果是 Hub 的话,usb主机会监测hub端口变化,如果有变化会分配一个usb_devices 注册到 usb_bus_type 重复前边的步骤。    

    首先,整个驱动框架的开始,是基于 platform 平台总线的。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. struct platform_device s3c_device_usb = {  
  2.     .name         = "s3c2410-ohci",  
  3.     .id       = -1,  
  4.     .num_resources    = ARRAY_SIZE(s3c_usb_resource),  
  5.     .resource     = s3c_usb_resource,  
  6.     .dev              = {  
  7.         .dma_mask = &s3c_device_usb_dmamask,  
  8.         .coherent_dma_mask = 0xffffffffUL  
  9.     }  
  10. };  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static struct platform_driver ohci_hcd_s3c2410_driver = {  
  2.     .probe      = ohci_hcd_s3c2410_drv_probe,  
  3.     .remove     = ohci_hcd_s3c2410_drv_remove,  
  4.     .shutdown   = usb_hcd_platform_shutdown,  
  5.     /*.suspend  = ohci_hcd_s3c2410_drv_suspend, */  
  6.     /*.resume   = ohci_hcd_s3c2410_drv_resume, */  
  7.     .driver     = {  
  8.         .owner  = THIS_MODULE,  
  9.         .name   = "s3c2410-ohci",  
  10.     },  
  11. };  
    platform 平台总线模型,这里定义了 platform_device 和 platform_driver ,后面将这俩注册到 platform_bus_type 时,就会根据它们的名字来匹配,显然,它们的名字都是 “s3c2410-ohci” ,匹配成功后,便会调用到 ohci_hcd_s3c2410_drv_probe 函数。在看 probe 函数之前,我们先看看设备侧提供的信息。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static struct resource s3c_usb_resource[] = {  
  2.     [0] = {  
  3.         .start = S3C_PA_USBHOST,  
  4.         .end   = S3C_PA_USBHOST + 0x100 - 1,  
  5.         .flags = IORESOURCE_MEM,  
  6.     },  
  7.     [1] = {  
  8.         .start = IRQ_USBH,  
  9.         .end   = IRQ_USBH,  
  10.         .flags = IORESOURCE_IRQ,  
  11.     }  
  12. };  
    resource 中指定了 2440 主机控制器的寄存器范围,以及中断。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_simtec_init(void)  
  2. {  
  3.     s3c_device_usb.dev.platform_data = &usb_simtec_info;  
  4. }  
  5.   
  6.   
  7. static struct s3c2410_hcd_info usb_simtec_info = {  
  8.     .port[0]    = {  
  9.         .flags  = S3C_HCDFLG_USED  
  10.     },  
  11.     .port[1]    = {  
  12.         .flags  = S3C_HCDFLG_USED  
  13.     },  
  14.   
  15.     .power_control  = usb_simtec_powercontrol,  
  16.     .enable_oc  = usb_simtec_enableoc,  
  17. };  
    这里,指定了一些额外的信息,保存在 dev.platform_data 中,后边我们再来看他们是干什么用的。下面来看 probe 函数。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)  
  2. {  
  3.     return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);  
  4. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,  
  2.                   struct platform_device *dev)  
  3. {  
  4.     struct usb_hcd *hcd = NULL;  
  5.     int retval;  
  6.       
  7.     /* 设置GPG4输出1 mini2440 jz2440好像均不需要 */  
  8.     s3c2410_usb_set_power(dev->dev.platform_data, 1, 1);  
  9.     s3c2410_usb_set_power(dev->dev.platform_data, 2, 1);  
  10.       
  11.     /* 创建usb_hcd 绑定 usb_driver等 */  
  12.     hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");  
  13.       
  14.     /* 主机控制寄存器 起始地址 结束地址 */  
  15.     hcd->rsrc_start = dev->resource[0].start;  
  16.     hcd->rsrc_len   = dev->resource[0].end - dev->resource[0].start + 1;  
  17.       
  18.     /* 申请IO空间 */  
  19.     if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {  
  20.         ...  
  21.     }  
  22.     /* 获得usb-host 时钟 */  
  23.     clk = clk_get(&dev->dev, "usb-host");  
  24.     /* 获得 usb-bus-host 时钟 */  
  25.     usb_clk = clk_get(&dev->dev, "usb-bus-host");  
  26.     /* 使能时钟 使能过流检查 */  
  27.     s3c2410_start_hc(dev, hcd);  
  28.     /* Ioremap */  
  29.     hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);  
  30.   
  31.     ohci_hcd_init(hcd_to_ohci(hcd));  
  32.   
  33.     retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);  
  34.   
  35.     return 0;  
  36.   
  37. }  
    前边第一个 probe 函数仅仅是一个中转,usb_hcd_s3c2410_probe 它才是真正的 probe 函数,主要工作就是分配一个 usb_hcd 结构、设置然后 usb_add_hcd 。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. struct usb_hcd {  
  2.   
  3.     /* 
  4.      * housekeeping 
  5.      */  
  6.     struct usb_bus      self;       /* hcd is-a bus */  
  7.     struct kref     kref;       /* reference counter */  
  8.   
  9.     const char      *product_desc;  /* product/vendor string */  
  10.     char            irq_descr[24];  /* driver + bus # */  
  11.   
  12.     struct timer_list   rh_timer;   /* drives root-hub polling */  
  13.     struct urb      *status_urb;    /* the current status urb */  
  14. #ifdef CONFIG_PM  
  15.     struct work_struct  wakeup_work;    /* for remote wakeup */  
  16. #endif  
  17.   
  18.     /* 
  19.      * hardware info/state 
  20.      */  
  21.     const struct hc_driver  *driver;    /* hw-specific hooks */  
  22.   
  23.     /* Flags that need to be manipulated atomically */  
  24.     unsigned long       flags;  
  25. #define HCD_FLAG_HW_ACCESSIBLE  0x00000001  
  26. #define HCD_FLAG_SAW_IRQ    0x00000002  
  27.   
  28.     unsigned        rh_registered:1;/* is root hub registered? */  
  29.   
  30.     /* The next flag is a stopgap, to be removed when all the HCDs 
  31.      * support the new root-hub polling mechanism. */  
  32.     unsigned        uses_new_polling:1;  
  33.     unsigned        poll_rh:1;  /* poll for rh status? */  
  34.     unsigned        poll_pending:1; /* status has changed? */  
  35.     unsigned        wireless:1; /* Wireless USB HCD */  
  36.     unsigned        authorized_default:1;  
  37.     unsigned        has_tt:1;   /* Integrated TT in root hub */  
  38.   
  39.     int         irq;        /* irq allocated */  
  40.     void __iomem        *regs;      /* device memory/io */  
  41.     u64         rsrc_start; /* memory/io resource start */  
  42.     u64         rsrc_len;   /* memory/io resource length */  
  43.     unsigned        power_budget;   /* in mA, 0 = no limit */  
  44.   
  45. #define HCD_BUFFER_POOLS    4  
  46.     struct dma_pool     *pool [HCD_BUFFER_POOLS];  
  47.   
  48.     int         state;  
  49. #   define  __ACTIVE        0x01  
  50. #   define  __SUSPEND       0x04  
  51. #   define  __TRANSIENT     0x80  
  52.   
  53. #   define  HC_STATE_HALT       0  
  54. #   define  HC_STATE_RUNNING    (__ACTIVE)  
  55. #   define  HC_STATE_QUIESCING  (__SUSPEND|__TRANSIENT|__ACTIVE)  
  56. #   define  HC_STATE_RESUMING   (__SUSPEND|__TRANSIENT)  
  57. #   define  HC_STATE_SUSPENDED  (__SUSPEND)  
  58.   
  59. #define HC_IS_RUNNING(state) ((state) & __ACTIVE)  
  60. #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)  
  61.   
  62.     /* more shared queuing code would be good; it should support 
  63.      * smarter scheduling, handle transaction translators, etc; 
  64.      * input size of periodic table to an interrupt scheduler. 
  65.      * (ohci 32, uhci 1024, ehci 256/512/1024). 
  66.      */  
  67.   
  68.     /* The HC driver's private data is stored at the end of 
  69.      * this structure. 
  70.      */  
  71.     unsigned long hcd_priv[0]  
  72.             __attribute__ ((aligned(sizeof(unsigned long))));  
  73. };  
    usb_hcd —— USB Host Controller Driver,同时,一个主机控制器驱动对应一条 usb_bus 。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. struct usb_bus {  
  2.     struct device *controller;  /* host/master side hardware */  
  3.     int busnum;         /* Bus number (in order of reg) */  
  4.     const char *bus_name;       /* stable id (PCI slot_name etc) */  
  5.     u8 uses_dma;            /* Does the host controller use DMA? */  
  6.     u8 otg_port;            /* 0, or number of OTG/HNP port */  
  7.     unsigned is_b_host:1;       /* true during some HNP roleswitches */  
  8.     unsigned b_hnp_enable:1;    /* OTG: did A-Host enable HNP? */  
  9.   
  10.     int devnum_next;        /* Next open device number in 
  11.                      * round-robin allocation */  
  12.   
  13.     struct usb_devmap devmap;   /* device address allocation map */  
  14.     struct usb_device *root_hub;    /* Root hub */  
  15.     struct list_head bus_list;  /* list of busses */  
  16.   
  17.     int bandwidth_allocated;    /* on this bus: how much of the time 
  18.                      * reserved for periodic (intr/iso) 
  19.                      * requests is used, on average? 
  20.                      * Units: microseconds/frame. 
  21.                      * Limits: Full/low speed reserve 90%, 
  22.                      * while high speed reserves 80%. 
  23.                      */  
  24.     int bandwidth_int_reqs;     /* number of Interrupt requests */  
  25.     int bandwidth_isoc_reqs;    /* number of Isoc. requests */  
  26.   
  27. #ifdef CONFIG_USB_DEVICEFS  
  28.     struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */  
  29. #endif  
  30.   
  31. #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)  
  32.     struct mon_bus *mon_bus;    /* non-null when associated */  
  33.     int monitored;          /* non-zero when monitored */  
  34. #endif  
  35. };  

    hcd的分配过程

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,  
  2.         struct device *dev, const char *bus_name)  
  3. {  
  4.     struct usb_hcd *hcd;  
  5.       
  6.     /* 分配一个 usb_hcd + driver->hcd_priv_size 空间 */  
  7.     hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);  
  8.       
  9.     /* dev->p->driver_data = hcd; */  
  10.     dev_set_drvdata(dev, hcd);  
  11.       
  12.     kref_init(&hcd->kref);  
  13.       
  14.     /* 初始化 usb_bus ,一个主机控制器对应一个 usb_bus */  
  15.     usb_bus_init(&hcd->self);  
  16.       
  17.     /* 设置 usb_bus */  
  18.     hcd->self.controller = dev;  
  19.     hcd->self.bus_name = bus_name;  
  20.     hcd->self.uses_dma = (dev->dma_mask != NULL);  
  21.       
  22.     /* 初始化 根Hub poll定时器 */  
  23.     init_timer(&hcd->rh_timer);  
  24.     hcd->rh_timer.function = rh_timer_func;  
  25.     hcd->rh_timer.data = (unsigned long) hcd;  
  26. #ifdef CONFIG_PM  
  27.     INIT_WORK(&hcd->wakeup_work, hcd_resume_work);  
  28. #endif  
  29.     /* 绑定 hc_driver */  
  30.     hcd->driver = driver;  
  31.     hcd->product_desc = (driver->product_desc) ? driver->product_desc :  
  32.             "USB Host Controller";  
  33.     return hcd;  
  34. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static void usb_bus_init (struct usb_bus *bus)  
  2. {  
  3.     memset (&bus->devmap, 0, sizeof(struct usb_devmap));  
  4.   
  5.     bus->devnum_next = 1;  
  6.   
  7.     bus->root_hub = NULL;  
  8.     bus->busnum = -1;  
  9.     bus->bandwidth_allocated = 0;  
  10.     bus->bandwidth_int_reqs  = 0;  
  11.     bus->bandwidth_isoc_reqs = 0;  
  12.   
  13.     INIT_LIST_HEAD (&bus->bus_list);  
  14. }  

整个Probe函数里干了那些事:

    1、创建一个 usb_hcd

    2、usb_bus_init ,初始化 usb_hcd 对应的 usb_bus ,bus->devmap 清零,根 Hub 指向 NULL等

    3、设置 usb_hcd.usb_bus 

      3.1 hcd.usb_bus.controller = s3c_device_usb.dev (最开始创建的平台device)

      3.2 hcd.usb_bus.name = “s3c24xx”

    4、设置 usb_hcd.rh_timer

    5、设置 usb_hcd.driver = ohci_s3c2410_hc_driver 

    6、根据 resource 资源,设置usb_hcd.rsrc_start、usb_hcd.rsrc_len

    7、使能时钟

    8、ioremap 、申请 io 空间

    9、usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED)

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  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.     /* 无线USB? */  
  7.     hcd->authorized_default = hcd->wireless? 0 : 1;  
  8.     set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);  
  9.   
  10.     /* hcd->pool[i] = dma_pool_create(name, hcd->self.controller,size, size, 0); */  
  11.     if ((retval = hcd_buffer_create(hcd)) != 0) {  
  12.         ...  
  13.     }  
  14.     /* 
  15.      * busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); 
  16.      * bus->busnum = busnum; 
  17.      * list_add (&bus->bus_list, &usb_bus_list); 
  18.      */  
  19.     if ((retval = usb_register_bus(&hcd->self)) < 0)  
  20.         goto err_register_bus;  
  21.     /* 根 Hub */  
  22.     if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {  
  23.         ...  
  24.     }  
  25.   
  26.     rhdev->speed = USB_SPEED_FULL;  
  27.   
  28.     hcd->self.root_hub = rhdev;  
  29.       
  30.     /* dev->power.can_wakeup = dev->power.should_wakeup = 1 */  
  31.     device_init_wakeup(&rhdev->dev, 1);  
  32.   
  33.     if (hcd->driver->irq) {  
  34.   
  35.         snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",  
  36.                 hcd->driver->description, hcd->self.busnum);  
  37.                   
  38.         if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,  
  39.                 hcd->irq_descr, hcd)) != 0) {  
  40.             ...  
  41.         }  
  42.         hcd->irq = irqnum;         
  43.     }  
  44.       
  45.     hcd->driver->start(hcd));  
  46.   
  47.   
  48.     /* starting here, usbcore will pay attention to this root hub */  
  49.     rhdev->bus_mA = min(500u, hcd->power_budget);  
  50.     if ((retval = register_root_hub(hcd)) != 0)  
  51.         goto err_register_root_hub;  
  52.   
  53.     retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);  
  54.   
  55.     if (hcd->uses_new_polling && hcd->poll_rh)  
  56.         usb_hcd_poll_rh_status(hcd);  
  57.     return retval;  
  58.   
  59. }  

usb_hcd_add 干了哪些事:

    1、hcd_buffer_create(hcd) 

    2、usb_register_bus(&hcd->self) ,将 usb_hcd.usb_bus 注册到全局链表 usb_bus_list

    3、为根 hub 分配一个 usb_device 结构(内核中,所有的真实的usb设备(Hub,鼠标...)都用usb_device结构来描述)

    4、注册根 Hub 的 usb_device 结构到 usb_bus_type

    弄了半天,神神秘秘的USB主机控制器也只不过是分配了一个 usb_hcd 结构体,为它的 根hub 分配了一个usb_device 结构体,注册到 usb_bus_type 罢了,后边是 根Hub 的注册和设备枚举过程了。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  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 = container_of(bus, struct usb_hcd, self);  
  6.     unsigned root_hub = 0;  
  7.     /* 分配一个 usb_device  */  
  8.     dev = kzalloc(sizeof(*dev), GFP_KERNEL);  
  9.   
  10.     device_initialize(&dev->dev);  
  11.     /* usb_bus_type */  
  12.     dev->dev.bus = &usb_bus_type;  
  13.     /* 属性文件 */  
  14.     dev->dev.type = &usb_device_type;  
  15.     dev->dev.groups = usb_device_groups;  
  16.     dev->dev.dma_mask = bus->controller->dma_mask;  
  17.     set_dev_node(&dev->dev, dev_to_node(bus->controller));  
  18.     dev->state = USB_STATE_ATTACHED;  
  19.     atomic_set(&dev->urbnum, 0);  
  20.   
  21.     INIT_LIST_HEAD(&dev->ep0.urb_list);  
  22.     dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;  
  23.     dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;  
  24.     /* ep0 maxpacket comes later, from device descriptor */  
  25.     usb_enable_endpoint(dev, &dev->ep0, false);  
  26.     dev->can_submit = 1;  
  27.   
  28.     /* 如果是根Hub */  
  29.     if (unlikely(!parent)) {  
  30.         ...  
  31.     } else {  
  32.         ...  
  33.     }  
  34.   
  35. <span style="white-space:pre">    </span>...  
  36.     }  
  37.     return dev;  
  38. }  
注意一下几点:

    1、dev->dev.bus = &usb_bus_type 这里出现了一条“总线模型”中的总线,注意和 usb_bus 完全没关系。相当于hub 、鼠标等 usb 设备是注册到 usb_bus_type 的,前面我们说的控制器的驱动是注册到 platform_bus_type 的。

    2、dev->dev.type = &usb_device_type ;后边Match函数中会用到

    3、dev->state = USB_STATE_ATTACHED; 根Hub是和控制器连在一起的,必然已经连接上了

      ATTACHED :表示设备已经连接到 hub 接口上了。

      Powered      :表示加电状态

      Default         :表示默认状态,在powered状态之后,设备必须受到一个复位信号并成功复位后,才能使用默认地址回应主机发过来的设备描述符的请求。

      Address        :表示主机分配了一个唯一的地址给设备。

      Configured   :表示设备已经被主机配置过了,此时,主机可以使用设备提供的所有功能。

      Supended    :表示挂起状态,设备在指定的时间内没有传输,就要进入挂起状态。
    4、dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT ,我们说一个 usb 设备有多个配置,每个配置又有多个接口,每个接口有多个 端点。但是端点 0 比较特殊,它是整个 usb 设备共享的,因此它的表述符直接在 usb_device中。

    5、dev->bus = bus ,根 Hub 连接到 控制器总线。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  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.       
  8.     /* 设备地址 */  
  9.     usb_dev->devnum = devnum;  
  10.     usb_dev->bus->devnum_next = devnum + 1;  
  11.     memset (&usb_dev->bus->devmap.devicemap, 0,  
  12.             sizeof usb_dev->bus->devmap.devicemap);  
  13.     set_bit (devnum, usb_dev->bus->devmap.devicemap);  
  14.     usb_set_device_state(usb_dev, USB_STATE_ADDRESS);  
  15.   
  16.     mutex_lock(&usb_bus_list_lock);  
  17.   
  18.     usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);  
  19.       
  20.     /* 获得设备描述符 */  
  21.     retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);  
  22.   
  23.     /* 进一步设置,然后 add_device */  
  24.     retval = usb_new_device (usb_dev);  
  25.   
  26.     return retval;  
  27. }  
    1、usb_dev->devnum = 1 ;根 Hub 的地址为1 ,usb_dev->bus->devmap.devicemap ,表示哪些设备地址被占用了,以及这个 hub 一共支持多少设备。

    2、usb_set_device_state(usb_dev, USB_STATE_ADDRESS); 变更状态

    3、usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); 获得设备描述符,保存在usb_dev.descriptor 中。

    4、usb_new_device 进一步设置(获得配置、端点描述符等),将 usb_device 注册到 usb_bus_type 。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)  
  2. {  
  3.     struct usb_device_descriptor *desc;  
  4.     int ret;  
  5.   
  6.     if (size > sizeof(*desc))  
  7.         return -EINVAL;  
  8.     desc = kmalloc(sizeof(*desc), GFP_NOIO);  
  9.     if (!desc)  
  10.         return -ENOMEM;  
  11.   
  12.     ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);  
  13.     if (ret >= 0)  
  14.         memcpy(&dev->descriptor, desc, size);  
  15.     kfree(desc);  
  16.     return ret;  
  17. }  

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_get_descriptor(struct usb_device *dev, unsigned char type,  
  2.                unsigned char index, void *buf, int size)  
  3. {  
  4.     int i;  
  5.     int result;  
  6.   
  7.     memset(buf, 0, size);   /* Make sure we parse really received data */  
  8.   
  9.     for (i = 0; i < 3; ++i) {  
  10.         /* retry on length 0 or error; some devices are flakey */  
  11.         result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),  
  12.                 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,  
  13.                 (type << 8) + index, 0, buf, size,  
  14.                 USB_CTRL_GET_TIMEOUT);  
  15.         if (result <= 0 && result != -ETIMEDOUT)  
  16.             continue;  
  17.         if (result > 1 && ((u8 *)buf)[1] != type) {  
  18.             result = -ENODATA;  
  19.             continue;  
  20.         }  
  21.         break;  
  22.     }  
  23.     return result;  
  24. }  
    注意,这里是将整个根Hub作为一个 device 注册到 usb_bus_type ,后边还会将Hub的接口注册进去
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_new_device(struct usb_device *udev)  
  2. {  
  3.     int err;  
  4.   
  5.     /* Increment the parent's count of unsuspended children */  
  6.     if (udev->parent)  
  7.         usb_autoresume_device(udev->parent);  
  8.   
  9.     usb_detect_quirks(udev);        /* Determine quirks */  
  10.     err = usb_configure_device(udev);   /* detect & probe dev/intfs */  
  11.   
  12.     /* export the usbdev device-node for libusb */  
  13.     udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,  
  14.             (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));  
  15.   
  16.     /* Tell the world! */  
  17.     announce_device(udev);  
  18.   
  19.     /* Register the device.  The device driver is responsible 
  20.      * for configuring the device and invoking the add-device 
  21.      * notifier chain (used by usbfs and possibly others). 
  22.      */  
  23.     err = device_add(&udev->dev);  
  24.   
  25.     (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);  
  26.     return err;  
  27.   
  28. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int usb_configure_device(struct usb_device *udev)  
  2. {  
  3.     usb_get_configuration(udev);  
  4. }  

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_get_configuration(struct usb_device *dev)  
  2. {  
  3.     struct device *ddev = &dev->dev;  
  4.     int ncfg = dev->descriptor.bNumConfigurations;  
  5.     int result = 0;  
  6.     unsigned int cfgno, length;  
  7.     unsigned char *buffer;  
  8.     unsigned char *bigbuffer;  
  9.     struct usb_config_descriptor *desc;  
  10.   
  11.     cfgno = 0;  
  12.   
  13.     if (ncfg > USB_MAXCONFIG) {  
  14.         dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;  
  15.     }  
  16.   
  17.     length = ncfg * sizeof(struct usb_host_config);  
  18.     dev->config = kzalloc(length, GFP_KERNEL);  
  19.   
  20.     length = ncfg * sizeof(char *);  
  21.     dev->rawdescriptors = kzalloc(length, GFP_KERNEL);  
  22.   
  23.     buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);  
  24.   
  25.     desc = (struct usb_config_descriptor *)buffer;  
  26.   
  27.     result = 0;  
  28.     for (; cfgno < ncfg; cfgno++) {  
  29.         /* We grab just the first descriptor so we know how long the whole configuration is */  
  30.         result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, USB_DT_CONFIG_SIZE);  
  31.   
  32.         length = max((int) le16_to_cpu(desc->wTotalLength), USB_DT_CONFIG_SIZE);  
  33.   
  34.         /* Now that we know the length, get the whole thing */  
  35.         bigbuffer = kmalloc(length, GFP_KERNEL);  
  36.   
  37.         result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);  
  38.           
  39.         dev->rawdescriptors[cfgno] = bigbuffer;  
  40.         /* 解析配置描述符 */  
  41.         result = usb_parse_configuration(&dev->dev, cfgno, &dev->config[cfgno], bigbuffer, length);  
  42.     }  
  43.     result = 0;  
  44.   
  45.     return result;  
  46. }  

    也就是说,在将 usb_device 注册到 usb_bus_type 时,它所有的描述符信息都已经获取到了。

    整个控制器驱动一路走下来,最后 注册了一个根 Hub 的 usb_device 到 usb_bus_type 。有必要看一下usb_bus_type ,它的 match 函数,将注册进来的 device 和 接口分开处理。第一次注册的我们说是 device ,那么看看对应的 driver 是啥。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. struct bus_type usb_bus_type = {  
  2.     .name =     "usb",  
  3.     .match =    usb_device_match,  
  4.     .uevent =   usb_uevent,  
  5. };  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int usb_device_match(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     /* return dev->type == &usb_device_type; */  
  4.     if (is_usb_device(dev)) {  
  5.   
  6.         /* return container_of(drv, struct usbdrv_wrap, driver)->for_devices; */  
  7.         if (!is_usb_device_driver(drv))  
  8.             return 0;  
  9.   
  10.         /* TODO: Add real matching code */  
  11.         return 1;  
  12.   
  13.     } else if (is_usb_interface(dev)) {  
  14.         ....  
  15.     }  
  16.   
  17.     return 0;  
  18. }  

    如果设备的 dev->type == &usb_device_type ,且 driver.for_devices == 1 ,直接匹配成功。匹配成功之后便会调用driver侧的 probe 函数了。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. struct usb_device_driver usb_generic_driver = {  
  2.     .name = "usb",  
  3.     .probe = generic_probe,  
  4.     .disconnect = generic_disconnect,  
  5. #ifdef  CONFIG_PM  
  6.     .suspend = generic_suspend,  
  7.     .resume = generic_resume,  
  8. #endif  
  9.     .supports_autosuspend = 1,  
  10. };  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int generic_probe(struct usb_device *udev)  
  2. {  
  3.     int err, c;  
  4.   
  5.     c = usb_choose_configuration(udev);  
  6.   
  7.     err = usb_set_configuration(udev, c);  
  8.   
  9.     /* USB device state == configured ... usable */  
  10.     usb_notify_add_device(udev);  
  11.   
  12.     return 0;  
  13. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_set_configuration(struct usb_device *dev, int configuration)  
  2. {  
  3.     int i, ret;  
  4.     struct usb_host_config *cp = NULL;  
  5.     struct usb_interface **new_interfaces = NULL;  
  6.     int n, nintf;  
  7.   
  8.     if (dev->authorized == 0 || configuration == -1)  
  9.         configuration = 0;  
  10.     else {  
  11.         for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {  
  12.             if (dev->config[i].desc.bConfigurationValue ==  
  13.                     configuration) {  
  14.                 cp = &dev->config[i];  
  15.                 break;  
  16.             }  
  17.         }  
  18.     }  
  19.   
  20.     n = nintf = 0;  
  21.     if (cp) {  
  22.         /* new_interfaces 是个指针数组,首先为它分配空间 */  
  23.         nintf = cp->desc.bNumInterfaces;  
  24.         new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), GFP_KERNEL);  
  25.         /* 为它指向的接口分配空间 */  
  26.         for (; n < nintf; ++n) {  
  27.             new_interfaces[n] = kzalloc(sizeof(struct usb_interface), GFP_KERNEL);  
  28.         }  
  29.   
  30.         i = dev->bus_mA - cp->desc.bMaxPower * 2;  
  31.     }  
  32.   
  33.     /* Wake up the device so we can send it the Set-Config request */  
  34.     ret = usb_autoresume_device(dev);  
  35.   
  36.     if (cp)  
  37.         ret = usb_hcd_check_bandwidth(dev, cp, NULL);  
  38.     else  
  39.         ret = usb_hcd_check_bandwidth(dev, NULL, NULL);  
  40.   
  41.     /* if it's already configured, clear out old state first. 
  42.      * getting rid of old interfaces means unbinding their drivers. 
  43.      */  
  44.     if (dev->state != USB_STATE_ADDRESS)  
  45.         usb_disable_device(dev, 1); /* Skip ep0 */  
  46.   
  47.     /* Get rid of pending async Set-Config requests for this device */  
  48.     cancel_async_set_config(dev);  
  49.       
  50.     /* 设置配置 */  
  51.     ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  
  52.                   USB_REQ_SET_CONFIGURATION, 0, configuration, 0,  
  53.                   NULL, 0, USB_CTRL_SET_TIMEOUT);  
  54.   
  55.     dev->actconfig = cp;  
  56.       
  57.     /* 变更状态 */  
  58.     usb_set_device_state(dev, USB_STATE_CONFIGURED);  
  59.       
  60.     /* 设置这个配置的所有接口 */  
  61.     for (i = 0; i < nintf; ++i) {  
  62.         struct usb_interface_cache *intfc;  
  63.         struct usb_interface *intf;  
  64.         struct usb_host_interface *alt;  
  65.   
  66.         cp->interface[i] = intf = new_interfaces[i];  
  67.         intfc = cp->intf_cache[i];  
  68.         intf->altsetting = intfc->altsetting;  
  69.         intf->num_altsetting = intfc->num_altsetting;  
  70.         intf->intf_assoc = find_iad(dev, cp, i);  
  71.         kref_get(&intfc->ref);  
  72.   
  73.         alt = usb_altnum_to_altsetting(intf, 0);  
  74.   
  75.         if (!alt)  
  76.             alt = &intf->altsetting[0];  
  77.   
  78.         intf->cur_altsetting = alt;  
  79.         usb_enable_interface(dev, intf, true);  
  80.         intf->dev.parent = &dev->dev;  
  81.         intf->dev.driver = NULL;  
  82.         intf->dev.bus = &usb_bus_type;  
  83.           
  84.         /* 注意这个,match时会区分 device 和 接口 */  
  85.         intf->dev.type = &usb_if_device_type;  
  86.         intf->dev.groups = usb_interface_groups;  
  87.         intf->dev.dma_mask = dev->dev.dma_mask;  
  88.         INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);  
  89.         device_initialize(&intf->dev);  
  90.         mark_quiesced(intf);  
  91.         dev_set_name(&intf->dev, "%d-%s:%d.%d",  
  92.             dev->bus->busnum, dev->devpath,  
  93.             configuration, alt->desc.bInterfaceNumber);  
  94.     }  
  95.     kfree(new_interfaces);  
  96.   
  97.     if (cp->string == NULL &&  
  98.             !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))  
  99.         cp->string = usb_cache_string(dev, cp->desc.iConfiguration);  
  100.   
  101.     for (i = 0; i < nintf; ++i) {  
  102.         struct usb_interface *intf = cp->interface[i];  
  103.           
  104.         /* 注册到 usb_bus_type */  
  105.         ret = device_add(&intf->dev);  
  106.         create_intf_ep_devs(intf);  
  107.     }  
  108.   
  109.     usb_autosuspend_device(dev);  
  110.     return 0;  
  111. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int usb_device_match(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     /* devices and interfaces are handled separately */  
  4.     if (is_usb_device(dev)) {  
  5. <span style="white-space:pre">    </span>...  
  6.     } else if (is_usb_interface(dev)) {  
  7.         struct usb_interface *intf;  
  8.         struct usb_driver *usb_drv;  
  9.         const struct usb_device_id *id;  
  10.   
  11.         /* device drivers never match interfaces */  
  12.         if (is_usb_device_driver(drv))  
  13.             return 0;  
  14.   
  15.         intf = to_usb_interface(dev);  
  16.         usb_drv = to_usb_driver(drv);  
  17.   
  18.         id = usb_match_id(intf, usb_drv->id_table);  
  19.         if (id)  
  20.             return 1;  
  21.   
  22.         id = usb_match_dynamic_id(intf, usb_drv);  
  23.         if (id)  
  24.             return 1;  
  25.     }  
  26.   
  27.     return 0;  
  28. }  
    第一次注册进来的是 devies,在通用的driver 的 probe 函数,将该设备的所有接口信息都读取出来并设置再注册到 usb_bus_type 中,也就是说在match函数中,会走下边这个分支,根据 dirver 的 id_table 来匹配,根 Hub 的接口自然是与 hub_driver 进行匹配。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static struct usb_driver hub_driver = {  
  2.     .name =     "hub",  
  3.     .probe =    hub_probe,  
  4.     .disconnect =   hub_disconnect,  
  5.     .suspend =  hub_suspend,  
  6.     .resume =   hub_resume,  
  7.     .reset_resume = hub_reset_resume,  
  8.     .pre_reset =    hub_pre_reset,  
  9.     .post_reset =   hub_post_reset,  
  10.     .ioctl =    hub_ioctl,  
  11.     .id_table = hub_id_table,  
  12.     .supports_autosuspend = 1,  
  13. };  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_hub_init(void)  
  2. {  
  3.     if (usb_register(&hub_driver) < 0) {  
  4.         ...  
  5.     }  
  6.     /* 创建内核线程,子进程将从 hub_thread 开始,名字叫 khubd  */  
  7.     khubd_task = kthread_run(hub_thread, NULL, "khubd");  
  8. }  
    分析过设备模型的都知道,匹配成功后调用的是usb_driver.driver.probe函数,然而这里并没有,而且usb_bus_type中也没有 probe 函数,那么有可能是在driver的注册过程中动了哪些手脚。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static inline int usb_register(struct usb_driver *driver)  
  2. {  
  3.     return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);  
  4. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_register_driver(struct usb_driver *new_driver, struct module *owner,  
  2.             const char *mod_name)  
  3. {  
  4.     int retval = 0;  
  5.   
  6.     if (usb_disabled())  
  7.         return -ENODEV;  
  8.   
  9.     new_driver->drvwrap.for_devices = 0;  
  10.     new_driver->drvwrap.driver.name = (char *) new_driver->name;  
  11.     new_driver->drvwrap.driver.bus = &usb_bus_type;  
  12.     new_driver->drvwrap.driver.probe = usb_probe_interface;  
  13.     new_driver->drvwrap.driver.remove = usb_unbind_interface;  
  14.     new_driver->drvwrap.driver.owner = owner;  
  15.     new_driver->drvwrap.driver.mod_name = mod_name;  
  16.     spin_lock_init(&new_driver->dynids.lock);  
  17.     INIT_LIST_HEAD(&new_driver->dynids.list);  
  18.   
  19.     retval = driver_register(&new_driver->drvwrap.driver);  
  20.   
  21.     if (!retval) {  
  22.         pr_info("%s: registered new interface driver %s\n",  
  23.             usbcore_name, new_driver->name);  
  24.         usbfs_update_special();  
  25.         usb_create_newid_file(new_driver);  
  26.     } else {  
  27.         printk(KERN_ERR "%s: error %d registering interface "  
  28.             "   driver %s\n",  
  29.             usbcore_name, retval, new_driver->name);  
  30.     }  
  31.   
  32.     return retval;  
  33. }  
    这里注册到 usb_bus_type 的是 usb_driver.drvwrap.driver ,那么匹配成功后调用的自然是 usb_probe_interface
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int usb_probe_interface(struct device *dev)  
  2. {  
  3.     struct usb_driver *driver = to_usb_driver(dev->driver);  
  4.     struct usb_interface *intf = to_usb_interface(dev);  
  5.     struct usb_device *udev = interface_to_usbdev(intf);  
  6.     const struct usb_device_id *id;  
  7.     int error = -ENODEV;  
  8.   
  9.     dev_dbg(dev, "%s\n", __func__);  
  10.   
  11.     intf->needs_binding = 0;  
  12.   
  13.     id = usb_match_id(intf, driver->id_table);  
  14.     if (!id)  
  15.         id = usb_match_dynamic_id(intf, driver);  
  16.     if (id) {  
  17.         dev_dbg(dev, "%s - got id\n", __func__);  
  18.   
  19.         error = usb_autoresume_device(udev);  
  20.         mark_active(intf);  
  21.         intf->condition = USB_INTERFACE_BINDING;  
  22.   
  23.         atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);  
  24.   
  25.         if (intf->needs_altsetting0) {  
  26.             error = usb_set_interface(udev, intf->altsetting[0].  
  27.                     desc.bInterfaceNumber, 0);  
  28.   
  29.             intf->needs_altsetting0 = 0;  
  30.         }  
  31. <span style="white-space:pre">        </span>/* 看这里 */  
  32.         error = driver->probe(intf, id);  
  33.   
  34.         intf->condition = USB_INTERFACE_BOUND;  
  35.         usb_autosuspend_device(udev);  
  36.     }  
  37.   
  38.     return error;  
  39. }  
    获取到 usb_device 的接口 usb_interface 以及 usb_device_id ,然后 driver->probe(intf, id) 调用到 usb_driver.probe 函数。传递进来的参数非常重要~,尤其是第一个 ---接口。再看 probe 函数之前,还有一点需要先看一下。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int usb_hub_init(void)  
  2. {  
  3.     if (usb_register(&hub_driver) < 0) {  
  4.         ...  
  5.     }  
  6.     /* 创建内核线程,子进程将从 hub_thread 开始,名字叫 khubd  */  
  7.     khubd_task = kthread_run(hub_thread, NULL, "khubd");  
  8. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int hub_thread(void *__unused)  
  2. {  
  3.     /* khubd needs to be freezable to avoid intefering with USB-PERSIST 
  4.      * port handover.  Otherwise it might see that a full-speed device 
  5.      * was gone before the EHCI controller had handed its port over to 
  6.      * the companion full-speed controller. 
  7.      */  
  8.     set_freezable();  
  9.   
  10.     do {  
  11.         hub_events();  
  12.         /* wait_event_interruptible(khubd_wait, ... */  
  13.         wait_event_freezable(khubd_wait,  
  14.                 !list_empty(&hub_event_list) ||  
  15.                 kthread_should_stop());  
  16.     } while (!kthread_should_stop() || !list_empty(&hub_event_list));  
  17.   
  18.     pr_debug("%s: khubd exiting\n", usbcore_name);  
  19.     return 0;  
  20. }  
    这个内核线程里干两件事,第一,hub_events(),第二休眠,等待唤醒。
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)  
  2. {  
  3.     struct usb_host_interface *desc;  
  4.     struct usb_endpoint_descriptor *endpoint;  
  5.     struct usb_device *hdev;  
  6.     struct usb_hub *hub;  
  7.   
  8.     desc = intf->cur_altsetting;  
  9.     hdev = interface_to_usbdev(intf);  
  10.   
  11.     /* Hub 的子类就是0,即desc->desc 这个interface 描述符里边的bInterfaceSubClass就应该是0 */  
  12.     if ((desc->desc.bInterfaceSubClass != 0) &&  
  13.         (desc->desc.bInterfaceSubClass != 1)) {  
  14.         ...  
  15.     }  
  16.   
  17.     /* spec 规定了Hub 只有一个端点(除去端点0)也就是中断端点 */  
  18.     if (desc->desc.bNumEndpoints != 1)  
  19.         goto descriptor_error;  
  20.   
  21.     endpoint = &desc->endpoint[0].desc;  
  22.   
  23.     /* 判断这个端点是否是中断端点 */  
  24.     if (!usb_endpoint_is_int_in(endpoint))  
  25.         goto descriptor_error;  
  26.     /* 分配一个usb_hub */  
  27.     hub = kzalloc(sizeof(*hub), GFP_KERNEL);  
  28.   
  29.     kref_init(&hub->kref);  
  30.     INIT_LIST_HEAD(&hub->event_list);  
  31.       
  32.     hub->intfdev = &intf->dev;    //hub  device  
  33.     hub->hdev = hdev;    //hub usb_device  
  34.       
  35.     INIT_DELAYED_WORK(&hub->leds, led_work);  
  36.     INIT_DELAYED_WORK(&hub->init_work, NULL);  
  37.     usb_get_intf(intf);  
  38.       
  39.     /* intf->dev = hub */  
  40.     usb_set_intfdata (intf, hub);  
  41.       
  42.     intf->needs_remote_wakeup = 1;  
  43.   
  44.     if (hdev->speed == USB_SPEED_HIGH)  
  45.         highspeed_hubs++;  
  46.   
  47.     if (hub_configure(hub, endpoint) >= 0)  
  48.         return 0;  
  49.   
  50. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint)  
  2. {  
  3.     struct usb_hcd *hcd;  
  4.     struct usb_device *hdev = hub->hdev;  
  5.     struct device *hub_dev = hub->intfdev;  
  6.     u16 hubstatus, hubchange;  
  7.     u16 wHubCharacteristics;  
  8.     unsigned int pipe;  
  9.     int maxp, ret;  
  10.     char *message = "out of memory";  
  11.       
  12.     /* 内存分配 */  
  13.     hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL,  
  14.             &hub->buffer_dma);  
  15.     hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);  
  16.     mutex_init(&hub->status_mutex);  
  17.     hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);  
  18.   
  19.     /* 获得 hub 描述符 */  
  20.     ret = get_hub_descriptor(hdev, hub->descriptor,  
  21.             sizeof(*hub->descriptor));  
  22.   
  23.     }  
  24.     /* hub 支持的最大下行端口 */  
  25.     hdev->maxchild = hub->descriptor->bNbrPorts;  
  26.   
  27.     hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL);  
  28.   
  29.     wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);  
  30.   
  31.     if (wHubCharacteristics & HUB_CHAR_COMPOUND) {  
  32.         /* 复合设备 */  
  33.     } else  
  34.         dev_dbg(hub_dev, "standalone hub\n");  
  35.   
  36.     switch (wHubCharacteristics & HUB_CHAR_LPSM) {  
  37.         /* 电源切换方式 */  
  38.     }  
  39.   
  40.     switch (wHubCharacteristics & HUB_CHAR_OCPM) {  
  41.         /* 过流保护模式 */  
  42.     }  
  43.   
  44.     spin_lock_init (&hub->tt.lock);  
  45.     INIT_LIST_HEAD (&hub->tt.clear_list);  
  46.     INIT_WORK(&hub->tt.clear_work, hub_tt_work);  
  47.       
  48.     switch (hdev->descriptor.bDeviceProtocol) {  
  49.         /* 低速全速设备掠过 */  
  50.     }  
  51.   
  52.     /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */  
  53.     switch (wHubCharacteristics & HUB_CHAR_TTTT) {  
  54.         /* 指定 hub->tt.think_time = 666 * n; n根据设备速度不同而不同*/  
  55.     }  
  56.   
  57.     /* 是否支持 hub 上的指示灯 */  
  58.     if (wHubCharacteristics & HUB_CHAR_PORTIND) {  
  59.         hub->has_indicators = 1;  
  60.         dev_dbg(hub_dev, "Port indicators are supported\n");  
  61.     }  
  62.     /* 请求设备状态 */  
  63.     ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);  
  64.   
  65.     le16_to_cpus(&hubstatus);  
  66.       
  67.     /* hub 的端口电流 */  
  68.     if (hdev == hdev->bus->root_hub) {    //根Hub  
  69.         ...  
  70.     }  
  71.   
  72.   
  73.     /* Update the HCD's internal representation of this hub before khubd 
  74.      * starts getting port status changes for devices under the hub. 
  75.      */  
  76.     hcd = bus_to_hcd(hdev->bus);  
  77.     if (hcd->driver->update_hub_device) {  
  78.         ret = hcd->driver->update_hub_device(hcd, hdev,  
  79.                 &hub->tt, GFP_KERNEL);  
  80.   
  81.     }  
  82.   
  83.     ret = hub_hub_status(hub, &hubstatus, &hubchange);  
  84.       
  85.     /* 获得主机和 Hub 端点的管道 */  
  86.     pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);  
  87.     maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));  
  88.   
  89.     if (maxp > sizeof(*hub->buffer))  
  90.         maxp = sizeof(*hub->buffer);  
  91.       
  92.     /* 分配一个urb */  
  93.     hub->urb = usb_alloc_urb(0, GFP_KERNEL);  
  94.     /* 填充Urb */  
  95.     usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,  
  96.         hub, endpoint->bInterval);  
  97.     hub->urb->transfer_dma = hub->buffer_dma;  
  98.     hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;  
  99.   
  100.     /* maybe cycle the hub leds */  
  101.     if (hub->has_indicators && blinkenlights)  
  102.         hub->indicator [0] = INDICATOR_CYCLE;  
  103.       
  104.     //tatus = usb_submit_urb(hub->urb, GFP_NOIO);  
  105.     //kick_khubd(hub) -> wake_up(&khubd_wait);  
  106.     hub_activate(hub, HUB_INIT);  
  107.     return 0;  
  108.   
  109. }  

    填充一个 urb ,检测 hub 端口状态,如果有状态发生改变,则会调用 hub_irq 

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static void hub_irq(struct urb *urb)  
  2. {  
  3.     struct usb_hub *hub = urb->context;  
  4.     int status = urb->status;  
  5.     unsigned i;  
  6.     unsigned long bits;  
  7.   
  8.     switch (status) {  
  9.     ....  
  10.   
  11.     /* let khubd handle things */  
  12.     case 0:         /* we got data:  port status changed */  
  13.         bits = 0;  
  14.         for (i = 0; i < urb->actual_length; ++i)  
  15.             bits |= ((unsigned long) ((*hub->buffer)[i]))  
  16.                     << (i*8);  
  17.         hub->event_bits[0] = bits;  
  18.         break;  
  19.     }  
  20.   
  21.     hub->nerrors = 0;  
  22.   
  23.     /* Something happened, let khubd figure it out */  
  24.     kick_khubd(hub);  
  25.   
  26. resubmit:  
  27.     if (hub->quiescing)  
  28.         return;  
  29.   
  30.     if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0  
  31.             && status != -ENODEV && status != -EPERM)  
  32.         dev_err (hub->intfdev, "resubmit --> %d\n", status);  
  33. }  

    如果哪一位端口发生了变化,标记在 Hub->event_bits[0]中,然后唤醒线程,hub_event 被调用。再次提交 urb

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static void hub_events(void)  
  2. {  
  3.     struct list_head *tmp;  
  4.     struct usb_device *hdev;  
  5.     struct usb_interface *intf;  
  6.     struct usb_hub *hub;  
  7.     struct device *hub_dev;  
  8.     u16 hubstatus;  
  9.     u16 hubchange;  
  10.     u16 portstatus;  
  11.     u16 portchange;  
  12.     int i, ret;  
  13.     int connect_change;  
  14.   
  15.     while (1) {  
  16.   
  17.         /* Grab the first entry at the beginning of the list */  
  18.         spin_lock_irq(&hub_event_lock);  
  19.   
  20.         tmp = hub_event_list.next;  
  21.         list_del_init(tmp);  
  22.   
  23.         hub = list_entry(tmp, struct usb_hub, event_list);  
  24.         kref_get(&hub->kref);  
  25.         spin_unlock_irq(&hub_event_lock);  
  26.   
  27.         hdev = hub->hdev;  
  28.         hub_dev = hub->intfdev;  
  29.         intf = to_usb_interface(hub_dev);  
  30.   
  31.         /* Lock the device, then check to see if we were 
  32.          * disconnected while waiting for the lock to succeed. */  
  33.         usb_lock_device(hdev);  
  34.   
  35.         /* Autoresume */  
  36.         ret = usb_autopm_get_interface(intf);  
  37.   
  38.         /* deal with port status changes */  
  39.         for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {  
  40.             if (test_bit(i, hub->busy_bits))  
  41.                 continue;  
  42.               
  43.             connect_change = test_bit(i, hub->change_bits);  
  44.             /* 第i位为0返回0 否则返回1,如果端口发生变化,返回1 */  
  45.             if (!test_and_clear_bit(i, hub->event_bits) &&  
  46.                     !connect_change)  
  47.                 continue;  
  48.             /* 程序运行到这,说明第i个端口发生了变化 */  
  49.             ret = hub_port_status(hub, i, &portstatus, &portchange);  
  50.   
  51.             if (portchange & USB_PORT_STAT_C_CONNECTION) {  
  52.                 clear_port_feature(hdev, i, USB_PORT_FEAT_C_CONNECTION);  
  53.                 connect_change = 1;  
  54.             }  
  55.   
  56.             if (portchange & USB_PORT_STAT_C_ENABLE) {  
  57.                 ...  
  58.             }  
  59.   
  60.             if (portchange & USB_PORT_STAT_C_SUSPEND) {  
  61.                 ...  
  62.             }  
  63.               
  64.             if (portchange & USB_PORT_STAT_C_OVERCURRENT) {  
  65.                 ...  
  66.             }  
  67.   
  68.             if (portchange & USB_PORT_STAT_C_RESET) {  
  69.                 ...  
  70.             }  
  71.   
  72.             if (connect_change)  
  73.                 hub_port_connect_change(hub, i, portstatus, portchange);  
  74.         } /* end for i */  
  75.         ...  
  76. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static void hub_port_connect_change(struct usb_hub *hub, int port1,  
  2.                     u16 portstatus, u16 portchange)  
  3. {  
  4.     struct usb_device *hdev = hub->hdev;  
  5.     struct device *hub_dev = hub->intfdev;  
  6.     struct usb_hcd *hcd = bus_to_hcd(hdev->bus);  
  7.     unsigned wHubCharacteristics =  
  8.             le16_to_cpu(hub->descriptor->wHubCharacteristics);  
  9.     struct usb_device *udev;  
  10.     int status, i;  
  11.   
  12.     for (i = 0; i < SET_CONFIG_TRIES; i++) {  
  13.           
  14.         /* 分配一个 usb_device */  
  15.         udev = usb_alloc_dev(hdev, hdev->bus, port1);  
  16.           
  17.         /* 设置它的状态为 加电的 */  
  18.         usb_set_device_state(udev, USB_STATE_POWERED);  
  19.         udev->bus_mA = hub->mA_per_port;  
  20.         udev->level = hdev->level + 1;  
  21.         udev->wusb = hub_is_wusb(hub);  
  22.         udev->speed = USB_SPEED_UNKNOWN;  
  23.           
  24.         /* 分配一个地址 devnum = find_next_zero_bit(bus->devmap.devicemap, 128, bus->devnum_next); */  
  25.         choose_address(udev);  
  26.           
  27.         /* 复位 获取描述符 */  
  28.         status = hub_port_init(hub, udev, port1, i);  
  29.   
  30.         status = 0;  
  31.   
  32.         /* Run it through the hoops (find a driver, etc) */  
  33.         if (!status) {  
  34.             status = usb_new_device(udev);  
  35.         }  
  36.   
  37.         status = hub_power_remaining(hub);  
  38.   
  39.         return;  
  40. }  
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  
  2.         int retry_counter)  
  3. {  
  4.     static DEFINE_MUTEX(usb_address0_mutex);  
  5.   
  6.     struct usb_device   *hdev = hub->hdev;  
  7.     struct usb_hcd      *hcd = bus_to_hcd(hdev->bus);  
  8.     int         i, j, retval;  
  9.     unsigned        delay = HUB_SHORT_RESET_TIME;  
  10.     enum usb_device_speed   oldspeed = udev->speed;  
  11.     char            *speed, *type;  
  12.     int         devnum = udev->devnum;  
  13.   
  14.     mutex_lock(&usb_address0_mutex);  
  15.       
  16.     retval = hub_port_reset(hub, port1, udev, delay);  
  17.           
  18.     oldspeed = udev->speed;  
  19.       
  20.     /* 根据传输速度设置端点0的最大包大小 */  
  21.     switch (udev->speed) {  
  22.     case USB_SPEED_SUPER:  
  23.     case USB_SPEED_VARIABLE:    /* fixed at 512 */  
  24.         udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);  
  25.         break;  
  26.     case USB_SPEED_HIGH:        /* fixed at 64 */  
  27.         udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);  
  28.         break;  
  29.     case USB_SPEED_FULL:        /* 8, 16, 32, or 64 */  
  30.         udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);  
  31.         break;  
  32.     case USB_SPEED_LOW:     /* fixed at 8 */  
  33.         udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);  
  34.         break;  
  35.     default:  
  36.         goto fail;  
  37.     }  
  38.    
  39.     type = "";  
  40.     switch (udev->speed) {  
  41.     case USB_SPEED_LOW: speed = "low";  break;  
  42.     case USB_SPEED_FULL:    speed = "full"break;  
  43.     case USB_SPEED_HIGH:    speed = "high"break;  
  44.     case USB_SPEED_SUPER:  
  45.                 speed = "super";  
  46.                 break;  
  47.     case USB_SPEED_VARIABLE:  
  48.                 speed = "variable";  
  49.                 type = "Wireless ";  
  50.                 break;  
  51.     default:        speed = "?";    break;  
  52.     }  
  53.   
  54.     for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {  
  55.   
  56.         if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {  
  57.             ...  
  58.         }  
  59.   
  60.         if (udev->wusb == 0) {  
  61.             for (j = 0; j < SET_ADDRESS_TRIES; ++j) {  
  62.                   
  63.                 /* 将分配的地址告诉设备 ,并设置设备状态为 USB_STATE_ADDRESS */  
  64.                 retval = hub_set_address(udev, devnum);  
  65.   
  66.                 msleep(200);  
  67.             }  
  68.   
  69.             if (udev->speed == USB_SPEED_SUPER) {  
  70.                 devnum = udev->devnum;  
  71.             }  
  72.   
  73.             msleep(10);  
  74.             if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))  
  75.                 break;  
  76.         }  
  77.         /* 不知道一次能获取多少,但至少能获取8 */  
  78.         retval = usb_get_device_descriptor(udev, 8);  
  79.         if (retval < 8) {  
  80.             ...  
  81.         } else {  
  82.             retval = 0;  
  83.             break;  
  84.         }  
  85.     }  
  86.   
  87.     if (udev->descriptor.bMaxPacketSize0 == 0xff ||  
  88.             udev->speed == USB_SPEED_SUPER)  
  89.         i = 512;  
  90.     else  
  91.         i = udev->descriptor.bMaxPacketSize0;  
  92.     if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {  
  93.   
  94.         udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);  
  95.         usb_ep0_reinit(udev);  
  96.     }  
  97.     /* 重新获取全部描述符 */  
  98.     retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);  
  99.   
  100.     retval = 0;  
  101.   
  102.     mutex_unlock(&usb_address0_mutex);  
  103.     return retval;  
  104. }  

    在 Hub_event 中,会调用 对于状态变化的端口调用 hub_port_status 来检测Hub端口的具体状态,然后调用 hub_port_connect_change 

    hub_port_connect_change
        udev = usb_alloc_dev(hdev, hdev->bus, port1);
            dev->dev.bus = &usb_bus_type;
        choose_address(udev); // 给新设备分配编号(地址)
        hub_port_init   // usb 1-1: new full speed USB device using s3c2410-ohci and address 3
            hub_set_address  // 把编号(地址)告诉USB设备
            usb_get_device_descriptor(udev, 8); // 获取设备描述符
            retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
            usb_new_device(udev)   
                err = usb_get_configuration(udev); // 把所有的描述符都读出来,并解析
                usb_parse_configuration
                device_add  // 把device放入usb_bus_type的dev链表, 
                    // 从usb_bus_type的driver链表里取出usb_driver,
                    // 把usb_interface和usb_driver的id_table比较
                    // 如果能匹配,调用usb_driver的probe

    显然,从 usb_alloc_dev 开始,重复了如同根 Hub 作为一个 device 注册进内核时的流程。如此循环下去,就能枚举注册所有的 usb 设备。


阅读全文
0 0
原创粉丝点击