赞
踩
关键词:linux、驱动、usb、usb host controller、usb主机控制器
在rk3128 的 TRM 文件《Rockchip RK312X TRM V1.0 Part2 20160630.pdf》中,USB主机控制器 USB HOST CONTROLLER 通过 UTMI 接口与 USB HOST PHY 连接,USB HOST PHY 通过 USB 线与其它设备连接,USB 的 PHY 与以太网的 PHY 类似,用于数字信号和电气信号的转换。
USB 主机控制器使用函数 usb_create_hcd() 和 usb_add_hcd() 创建并注册,在函数usb_add_hcd() 中会调用函数phy_get() 获取 USB PHY驱动中注册的 struct phy *phy,并调用 USB PHY 驱动的初始化函数struct phy *phy->ops->init :
- err = usb_add_hcd(hcd, irq, IRQF_SHARED)->
- struct phy *phy = phy_get(hcd->self.controller, "usb");
- index = of_property_match_string(dev->of_node, "phy-names", string);
- struct phy *phy = _of_phy_get(dev->of_node, index)-> //获取 usb phy 驱动中注册的 struct phy
- ret = of_parse_phandle_with_args(np, "phys", "#phy-cells", index, &args);
- struct phy_provider *phy_provider = of_phy_provider_lookup(args.np)->
- list_for_each_entry(phy_provider, &phy_provider_list, list)
- {
- /*
- 在 usb phy 驱动中会将注册的 struct phy *phy 添加到链表 phy_provider_list 中
- rockchip_usb2phy_probe()->
- provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate)->
- __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
- struct phy_provider *phy_provider = __of_phy_provider_register(dev, owner, of_xlate)->
- struct phy_provider *phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
- phy_provider->dev = dev;
- phy_provider->owner = owner;
- phy_provider->of_xlate = of_xlate;
- list_add_tail(&phy_provider->list, &phy_provider_list);
- */
- if (phy_provider->dev->of_node == node)
- return phy_provider;
- for_each_child_of_node(phy_provider->dev->of_node, child)
- if (child == node)
- return phy_provider;
- }
- // 以 rk3128 为例, phy_provider->of_xlate = of_phy_simple_xlate
- phy = phy_provider->of_xlate(phy_provider->dev, &args);
- struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args *args)->
- class_dev_iter_init(&iter, phy_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter)))
- {
- phy = to_phy(dev);
- class_dev_iter_exit(&iter);
- return phy;
- }
- return phy;
- hcd->phy = phy; // USB 主机控制器 struct usb_hcd *hcd 与 USB PHY 驱动 struct phy *phy 结合在一起
- retval = phy_init(phy)->
- ret = phy->ops->init(phy);//以rk3128为例: struct phy_ops rockchip_usb2phy_ops.init = rockchip_usb2phy_init
- static int rockchip_usb2phy_init(struct phy *phy)->
- if (rport->port_id == USB2PHY_PORT_OTG && rport->bvalid_irq > 0)
- {
- ret = rockchip_usb2phy_enable_vbus_irq(rphy, rport, true);
- ret = rockchip_usb2phy_enable_id_irq(rphy, rport, true);
- schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
- }
- else if (rport->port_id == USB2PHY_PORT_HOST)
- {
- ret = rockchip_usb2phy_enable_line_irq(rphy, rport, true);
- schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
- }
-
USB主机控制器驱动struct usb_hcd 的主要成员变量如下:
- struct usb_hcd {
- const char *product_desc; /* product/vendor string */
- int speed;
- char irq_descr[24]; /* driver + bus # */
- struct timer_list rh_timer; /* drives root-hub polling */
- struct urb *status_urb; /* the current status urb */
- const struct hc_driver *driver; /* hw-specific hooks */
-
- /*
- * OTG and some Host controllers need software interaction with phys;
- * other external phys should be software-transparent
- */
- struct usb_phy *usb_phy;
- struct phy *phy; // 与USB主机控制器连接的 USB PHY
- unsigned long flags;
- /* Flags that get set only during HCD registration or removal. */
- unsigned rh_registered:1;/* is root hub registered? */
- unsigned rh_pollable:1; /* may we poll the root hub? */
- unsigned int irq; /* irq allocated */
- void __iomem *regs; /* device memory/io */
- };
以rk3128为例,内核版本号为 linux-4.4,ehci 驱动 struct platform_driver ehci_platform_driver 与如下的EHCI USB 主机控制器的设备树匹配:
- usb_host_ehci: usb@101c0000 {
- compatible = "generic-ehci";
- reg = <0x101c0000 0x20000>;
- interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru HCLK_HOST2>, <&u2phy>;
- clock-names = "usbhost", "utmi";
- phys = <&u2phy_host>;
- phy-names = "usb";
- status = "okay";
- };
在内核启动过程中会根据设备树 usb_host_ehci 注册平台设备/sys/devices/platform/101c0000.usb :
- root@mxlos:/sys/devices/platform/101c0000.usb# ll
- total 0
- drwxr-xr-x 5 root root 0 Jan 1 00:53 ./
- drwxr-xr-x 78 root root 0 Jan 1 00:53 ../
- -rw-r--r-- 1 root root 4096 Jan 1 00:55 companion
- lrwxrwxrwx 1 root root 0 Jan 1 00:55 driver -> ../../../bus/platform/drivers/ehci-platform/
- -rw-r--r-- 1 root root 4096 Jan 1 00:55 driver_override
- -r--r--r-- 1 root root 4096 Jan 1 00:55 modalias
- lrwxrwxrwx 1 root root 0 Jan 1 00:55 of_node -> ../../../firmware/devicetree/base/usb@101c0000/
- -r--r--r-- 1 root root 4096 Jan 1 00:55 pools
- drwxr-xr-x 2 root root 0 Jan 1 00:55 power/
- lrwxrwxrwx 1 root root 0 Jan 1 00:53 subsystem -> ../../../bus/platform/
- -rw-r--r-- 1 root root 4096 Jan 1 00:53 uevent
- -rw-r--r-- 1 root root 4096 Jan 1 00:55 uframe_periodic_max
- drwxr-xr-x 6 root root 0 Jan 1 00:53 usb2/
- drwxr-xr-x 3 root root 0 Jan 1 00:53 usbmon/
-
- root@mxlos:/sys/devices/platform/101c0000.usb#
- root@mxlos:/sys/devices/platform/101c0000.usb# cat modalias
- of:NusbT<NULL>Cgeneric-ehci
- root@mxlos:/sys/devices/platform/101c0000.usb# cat uevent
- DRIVER=ehci-platform
- OF_NAME=usb
- OF_FULLNAME=/usb@101c0000
- OF_COMPATIBLE_0=generic-ehci
- OF_COMPATIBLE_N=1
- MODALIAS=of:NusbT<NULL>Cgeneric-ehci
-
- root@mxlos:/sys/devices/platform/101c0000.usb# cat companion
ehci 驱动 struct platform_driver ehci_platform_driver 的相关定义如下:
- static struct platform_driver ehci_platform_driver = {
- .id_table = ehci_platform_table,
- .probe = ehci_platform_probe,
- .remove = ehci_platform_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ehci-platform",
- .pm = &ehci_platform_pm_ops,
- .of_match_table = vt8500_ehci_ids,
- .acpi_match_table = ACPI_PTR(ehci_acpi_match),
- }
- };
- static const struct platform_device_id ehci_platform_table[] = {
- { "ehci-platform", 0 },
- { }
- };
- static const struct of_device_id vt8500_ehci_ids[] = {
- { .compatible = "via,vt8500-ehci", },
- { .compatible = "wm,prizm-ehci", },
- { .compatible = "generic-ehci", },
- { .compatible = "cavium,octeon-6335-ehci", },
- {}
- };
参见内核源码文件 linux-rk3128\drivers\usb\host\ehci-platform.c:
- module_init(ehci_platform_init);
- static int __init ehci_platform_init(void)
- {
- /*
- [ 2.788385] phy phy-20008000.syscon:usb2-phy@17c.0: charger = USB_FLOATING_CHARGER
- [ 2.797461] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
- [ 2.804138] ehci-platform: EHCI generic platform driver
-
-
- #define DRIVER_DESC "EHCI generic platform driver"
- */
- pr_info("%s: " DRIVER_DESC "\n", hcd_name); //实际打印:ehci-platform: EHCI generic platform driver
- ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides)->
- *drv = ehci_hc_driver; // Copy the generic table to drv and then apply the overrides
- /*
- static const struct hc_driver ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
- // generic hardware linkage
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
- //basic lifecycle operations
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
- //managing i/o requests and associated device resources
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
- // scheduling support
- .get_frame_number = ehci_get_frame,
- // root hub support
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
- // device support
- .free_dev = ehci_remove_device,
- };
- */
- return platform_driver_register(&ehci_platform_driver)-> //对应目录 /sys/bus/platform/drivers/ehci-platform
- /*
- root@mxlos:/sys/bus/platform/drivers/ehci-platform# pwd
- /sys/bus/platform/drivers/ehci-platform
- root@mxlos:/sys/bus/platform/drivers/ehci-platform# ls
- 101c0000.usb bind uevent unbind
-
-
- static struct platform_driver ehci_platform_driver = {
- .id_table = ehci_platform_table,
- .probe = ehci_platform_probe,
- .remove = ehci_platform_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ehci-platform",
- .pm = &ehci_platform_pm_ops,
- .of_match_table = vt8500_ehci_ids,
- .acpi_match_table = ACPI_PTR(ehci_acpi_match),
- }
- };
- static const struct platform_device_id ehci_platform_table[] = {
- { "ehci-platform", 0 },
- { }
- };
- static const struct of_device_id vt8500_ehci_ids[] = {
- { .compatible = "via,vt8500-ehci", },
- { .compatible = "wm,prizm-ehci", },
- { .compatible = "generic-ehci", },
- { .compatible = "cavium,octeon-6335-ehci", },
- {}
- };
- */
- __platform_driver_register(drv, THIS_MODULE)->
- drv->driver.owner = owner;
- drv->driver.bus = &platform_bus_type; //对应目录 /sys/bus/platform
- drv->driver.probe = platform_drv_probe;
- drv->driver.remove = platform_drv_remove;
- drv->driver.shutdown = platform_drv_shutdown;
- return driver_register(&drv->driver)->
- other = driver_find(drv->name, drv->bus);
- ret = bus_add_driver(drv)->
- kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,"%s", drv->name);
- error = driver_attach(drv)-> //驱动与设备匹配,这个过程会调用驱动的 probe = platform_drv_probe
- return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)->
- klist_iter_init_node(&bus->p->klist_devices, &i, (start ? &start->p->knode_bus : NULL));
- fn(dev, data)=__driver_attach;
- static int __driver_attach(struct device *dev, void *data)->
- if (!driver_match_device(drv, dev))->
- //struct bus_type platform_bus_type.match= platform_match
- return drv->bus->match ? drv->bus->match(dev, drv) : 1;
- static int platform_match(struct device *dev, struct device_driver *drv)->
- // Attempt an OF style match first :尝试匹配设备树
- if (of_driver_match_device(dev, drv))
- return 1;
- /* Then try to match against the id table */
- if (pdrv->id_table)
- return platform_match_id(pdrv->id_table, pdev) != NULL;
- // fall-back to driver name match :尝试匹配设备名与驱动名
- return (strcmp(pdev->name, drv->name) == 0);
- {
- return 0;
- }
- if (!dev->driver)
- driver_probe_device(drv, dev);
- module_add_driver(drv->owner, drv);
- driver_create_file(drv, &driver_attr_uevent);
- ret = driver_add_groups(drv, drv->groups);
- kobject_uevent(&drv->p->kobj, KOBJ_ADD);
- }
-
-
-
- 最终调用ehci 驱动 struct platform_driver ehci_platform_driver 的 probe 函数:
- static int ehci_platform_probe(struct platform_device *dev)
- err = dma_coerce_mask_and_coherent(&dev->dev,pdata->dma_mask_64 ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32));
- irq = platform_get_irq(dev, 0);
- struct usb_hcd *hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,dev_name(&dev->dev))->
- return usb_create_shared_hcd(driver, dev, bus_name, NULL)-> //创建结构体 struct usb_hcd *hcd
- struct usb_hcd *hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
- usb_bus_init(&hcd->self)->
- bus->devnum_next = 1;
- bus->root_hub = NULL;
- bus->busnum = -1;
- bus->bandwidth_allocated = 0;
- bus->bandwidth_int_reqs = 0;
- bus->bandwidth_isoc_reqs = 0;
- hcd->self.controller = dev;
- hcd->self.bus_name = bus_name;
- hcd->self.uses_dma = (dev->dma_mask != NULL);
- init_timer(&hcd->rh_timer);
- hcd->rh_timer.function = rh_timer_func; //usb_hcd_poll_rh_status((struct usb_hcd *) _hcd);
- hcd->rh_timer.data = (unsigned long) hcd;
- INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
- hcd->driver = driver = struct hc_driver ehci_hc_driver;
- /*
- static const struct hc_driver ehci_hc_driver = {
- .description = hcd_name, //static const char hcd_name [] = "ehci_hcd";
- .product_desc = "EHCI Host Controller",
- .irq = ehci_irq,
- //basic lifecycle operations
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
- //managing i/o requests and associated device resources
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
- // scheduling support
- .get_frame_number = ehci_get_frame,
- // root hub support
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
- // device support
- .free_dev = ehci_remove_device,
- };
- */
- hcd->speed = driver->flags & HCD_MASK;
- hcd->product_desc = (driver->product_desc) ? driver->product_desc : "USB Host Controller";
- platform_set_drvdata(dev, hcd);
- dev->dev.platform_data = pdata;
- priv = hcd_to_ehci_priv(hcd);
- ehci = hcd_to_ehci(hcd);
- //获取 USB 的 phys
- priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,"phys", "#phy-cells");
- /*
- usb_host_ehci: usb@101c0000 {
- compatible = "generic-ehci";
- phys = <&u2phy_host>;
- };
- u2phy_host: host-port {
- #phy-cells = <0>;
- interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "linestate";
- status = "okay";
- };
- */
- priv->num_phys = 0;
- priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
- pm_runtime_set_active(&dev->dev);
- pm_runtime_enable(&dev->dev);
- pm_runtime_get_sync(&dev->dev);
- res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
- hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
- hcd->rsrc_start = res_mem->start;
- hcd->rsrc_len = resource_size(res_mem);
- err = usb_add_hcd(hcd, irq, IRQF_SHARED)->
- struct phy *phy = phy_get(hcd->self.controller, "usb");
- index = of_property_match_string(dev->of_node, "phy-names", string);
- struct phy *phy = _of_phy_get(dev->of_node, index)-> //获取 usb phy 驱动中注册的 struct phy
- ret = of_parse_phandle_with_args(np, "phys", "#phy-cells", index, &args);
- struct phy_provider *phy_provider = of_phy_provider_lookup(args.np)->
- list_for_each_entry(phy_provider, &phy_provider_list, list)
- {
- /*
- 在 usb phy 驱动中会将注册的 struct phy *phy 添加到链表 phy_provider_list 中
- rockchip_usb2phy_probe()->
- provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate)->
- __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
- struct phy_provider *phy_provider = __of_phy_provider_register(dev, owner, of_xlate)->
- struct phy_provider *phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
- phy_provider->dev = dev;
- phy_provider->owner = owner;
- phy_provider->of_xlate = of_xlate;
- list_add_tail(&phy_provider->list, &phy_provider_list);
- */
- if (phy_provider->dev->of_node == node)
- return phy_provider;
- for_each_child_of_node(phy_provider->dev->of_node, child)
- if (child == node)
- return phy_provider;
- }
- // 以 rk3128 为例, phy_provider->of_xlate = of_phy_simple_xlate
- phy = phy_provider->of_xlate(phy_provider->dev, &args);
- struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args *args)->
- class_dev_iter_init(&iter, phy_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter)))
- {
- phy = to_phy(dev);
- class_dev_iter_exit(&iter);
- return phy;
- }
- return phy;
- retval = phy_init(phy)->
- ret = phy->ops->init(phy);//以rk3128为例: struct phy_ops rockchip_usb2phy_ops.init = rockchip_usb2phy_init
- static int rockchip_usb2phy_init(struct phy *phy)->
- if (rport->port_id == USB2PHY_PORT_OTG && rport->bvalid_irq > 0)
- {
- ret = rockchip_usb2phy_enable_vbus_irq(rphy, rport, true);
- ret = rockchip_usb2phy_enable_id_irq(rphy, rport, true);
- schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
- }
- else if (rport->port_id == USB2PHY_PORT_HOST)
- {
- ret = rockchip_usb2phy_enable_line_irq(rphy, rport, true);
- schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
- }
- retval = phy_power_on(phy);
- dev_info(hcd->self.controller, "%s\n", hcd->product_desc); //实际打印:ehci-platform 101c0000.usb: EHCI Host Controller
- retval = hcd_buffer_create(hcd)->
- snprintf(name, sizeof(name), "buffer-%d", size);
- hcd->pool[i] = dma_pool_create(name, hcd->self.controller, size, size, 0);
- retval = usb_register_bus(&hcd->self)-> //registers the USB host controller with the usb core
- busnum = find_next_zero_bit(busmap, USB_MAXBUS, 1);
- bus->busnum = busnum;
- // Add it to the local list of buses
- list_add (&bus->bus_list, &usb_bus_list);
- usb_notify_add_bus(bus)->
- blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
- //对于 rk3128 来说,实际打印:ehci-platform 101c0000.usb: new USB bus registered, assigned bus number 2
- dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
- struct usb_device *rhdev = usb_alloc_dev(NULL, &hcd->self, 0)->
- struct usb_hcd *usb_hcd = bus_to_hcd(bus);
- struct usb_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- device_initialize(&dev->dev);
- dev->dev.bus = &usb_bus_type;
- dev->dev.type = &usb_device_type;
- dev->dev.groups = usb_device_groups;
- dev->dev.dma_mask = bus->controller->dma_mask;
- set_dev_node(&dev->dev, dev_to_node(bus->controller));
- dev->state = USB_STATE_ATTACHED;
- dev->lpm_disable_count = 1;
- atomic_set(&dev->urbnum, 0);
- INIT_LIST_HEAD(&dev->ep0.urb_list);
- dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
- dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
- /* ep0 maxpacket comes later, from device descriptor */
- usb_enable_endpoint(dev, &dev->ep0, false);
- dev->can_submit = 1;
- /* Save readable and stable topology id, distinguishing devices
- * by location for diagnostics, tools, driver model, etc. The
- * string is a path along hub ports, from the root. Each device's
- * dev->devpath will be stable until USB is re-cabled, and hubs
- * are often labeled with these port numbers. The name isn't
- * as stable: bus->busnum changes easily from modprobe order,
- * cardbus or pci hotplugging, and so on.
- */
- if (unlikely(!parent))
- {
- dev->devpath[0] = '0';
- dev->route = 0;
- dev->dev.parent = bus->controller;
- dev_set_name(&dev->dev, "usb%d", bus->busnum);
- root_hub = 1;
- }
- else
- {
- /* match any labeling on the hubs; it's one-based */
- if (parent->devpath[0] == '0')
- {
- snprintf(dev->devpath, sizeof dev->devpath,"%d", port1);
- /* Root ports are not counted in route string */
- dev->route = 0;
- }
- else
- {
- snprintf(dev->devpath, sizeof dev->devpath, "%s.%d", parent->devpath, port1);
- /* Route string assumes hubs have less than 16 ports */
- if (port1 < 15)
- dev->route = parent->route +(port1 << ((parent->level - 1)*4));
- else
- dev->route = parent->route +(15 << ((parent->level - 1)*4));
- }
- dev->dev.parent = &parent->dev;
- dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
- /* hub driver sets up TT records */
- }
- dev->portnum = port1;
- dev->bus = bus;
- dev->parent = parent;
- INIT_LIST_HEAD(&dev->filelist);
- if (root_hub) /* Root hub always ok [and always wired] */
- dev->authorized = 1;
- else
- {
- dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd);
- dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
- }
- hcd->self.root_hub = rhdev; //设置主机控制器的根集线器
- switch (hcd->speed)
- {
- case HCD_USB11:
- rhdev->speed = USB_SPEED_FULL;
- break;
- case HCD_USB2:
- rhdev->speed = USB_SPEED_HIGH;
- break;
- case HCD_USB25:
- rhdev->speed = USB_SPEED_WIRELESS;
- break;
- case HCD_USB3:
- case HCD_USB31:
- rhdev->speed = USB_SPEED_SUPER;
- break;
- default:
- retval = -EINVAL;
- goto err_set_rh_speed;
- }
- retval = hcd->driver->reset(hcd) = struct hc_driver ehci_hc_driver.reset =ehci_setup
- int ehci_setup(struct usb_hcd *hcd)->
- ehci_init(hcd)->
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- ehci->hrtimer.function = ehci_hrtimer_func;
- ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
- hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
- ehci_mem_init(ehci, GFP_KERNEL)->
- /* QTDs for control/bulk/intr transfers */
- ehci->qtd_pool = dma_pool_create ("ehci_qtd",
- ehci_to_hcd(ehci)->self.controller,
- sizeof (struct ehci_qtd),
- 32 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- /* QHs for control/bulk/intr transfers */
- ehci->qh_pool = dma_pool_create ("ehci_qh",
- ehci_to_hcd(ehci)->self.controller,
- sizeof(struct ehci_qh_hw),
- 32 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- ehci->async = ehci_qh_alloc (ehci, flags)->
- struct ehci_qh *qh = kzalloc(sizeof *qh, GFP_ATOMIC);
- qh->hw = (struct ehci_qh_hw *)dma_pool_alloc(ehci->qh_pool, flags, &dma);
- qh->dummy = ehci_qtd_alloc (ehci, flags);
- struct ehci_qtd *qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
- /* ITD for high speed ISO transfers */
- ehci->itd_pool = dma_pool_create ("ehci_itd",
- ehci_to_hcd(ehci)->self.controller,
- sizeof (struct ehci_itd),
- 32 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- /* SITD for full/low speed split ISO transfers */
- ehci->sitd_pool = dma_pool_create ("ehci_sitd",
- ehci_to_hcd(ehci)->self.controller,
- sizeof (struct ehci_sitd),
- 32 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- /* Hardware periodic table */
- ehci->periodic = (__le32 *)
- dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
- ehci->periodic_size * sizeof(__le32),
- &ehci->periodic_dma, flags);
- ehci_halt(ehci);
- ehci_reset(ehci);
- hcd->rh_pollable = 1;
- init_giveback_urb_bh(&hcd->high_prio_bh);
- init_giveback_urb_bh(&hcd->low_prio_bh);
- /* enable irqs just before we start the controller,
- * if the BIOS provides legacy PCI irqs.
- */
- if (usb_hcd_is_primary_hcd(hcd) && irqnum)
- {
- usb_hcd_request_irqs(hcd, irqnum, irqflags)->
- if (hcd->driver->irq) //struct hc_driver ehci_hc_driver.irq = ehci_irq
- {
- snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
- hcd->driver->description, hcd->self.busnum); //中断名为 :ehci_hcd:usb2
- request_irq(irqnum, &usb_hcd_irq, irqflags, hcd->irq_descr, hcd);
- irqreturn_t usb_hcd_irq (int irq, void *__hcd)->
- hcd->driver->irq(hcd) = struct hc_driver ehci_hc_driver.irq = ehci_irq(hdc)->
- /*
- EHCI 的 interrupt 在 HCD 中被分为了 6 种类型,如下宏定义:
- // these STS_* flags are also intr_enable bits (USBINTR)
- #define STS_IAA (1<<5) //Interrupted on async advance 当要从asynchronous schedule传输队列中移除一个QH时
- #define STS_FATAL (1<<4) /* such as some PCI access errors */
- #define STS_FLR (1<<3) /* frame list rolled over */
- #define STS_PCD (1<<2) /* port change detect:root hub上某个端口上有设备插入或拔出所产生的中断,
- 需要进一步的读取root hub上各port对应的register判断是插入还是拔出。 */
- #define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
- #define STS_INT (1<<0) /* "normal" completion (short, ...) 正确完成一次数据传输后所发出的中断*/
- */
- spin_lock_irqsave(&ehci->lock, flags);
- status = ehci_readl(ehci, &ehci->regs->status);
- #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
- masked_status = status & (INTR_MASK | STS_FLR);
- ehci_writel(ehci, masked_status, &ehci->regs->status);/* clear (just) interrupts:清除中断标志位。 */
- /* remote wakeup [4.3.1] */
- if (status & STS_PCD) //port change detect:root hub上某个端口上有设备插入或拔出所产生的中断
- {
- unsigned i = HCS_N_PORTS (ehci->hcs_params);
- u32 ppcd = ~0;
- /* kick root hub later */
- pcd_status = status;
- /* resume root hub? */
- if (ehci->rh_state == EHCI_RH_SUSPENDED)
- usb_hcd_resume_root_hub(hcd);
- /* get per-port change detect bits */
- if (ehci->has_ppcd)
- ppcd = status >> 16;
- while (i--) {
- int pstatus;
- ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
- usb_hcd_start_port_resume(&hcd->self, i);
- mod_timer(&hcd->rh_timer, ehci->reset_done[i])->
- expires = apply_slack(timer, expires);
- return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
- }
- }
- ehci_work (ehci)->
- ehci->scanning = true;
- if (ehci->intr_count > 0)
- {
- scan_intr(ehci)->
- qh_completions(ehci, qh)->
- list_entry (entry, struct ehci_qtd, qtd_list);
- ehci_urb_done(ehci, last->urb, last_status)->
- //ehci-platform 101c0000.usb: ehci_urb_done 1
- //urb ee71e780 ep1in status 0 len 1/1
- ehci_dbg (ehci,
- "%s %s urb %p ep%d%s status %d len %d/%d\n",
- __func__, urb->dev->devpath, urb,
- usb_pipeendpoint (urb->pipe),
- usb_pipein (urb->pipe) ? "in" : "out",
- status,
- urb->actual_length, urb->transfer_buffer_length);
- usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status)->
- __usb_hcd_giveback_urb(urb)->
- urb->complete(urb);//urb->complete =hub_irq
- }
- turn_on_io_watchdog(ehci);
- if (pcd_status)
- usb_hcd_poll_rh_status(hcd)->
- length = hcd->driver->hub_status_data(hcd, buffer) = ehci_hub_status_data(hcd, buffer);
- //get per-port change detect bits:获取每个端口变化检测位
- ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16;
- struct urb *urb = hcd->status_urb;
- urb->actual_length = length;
- memcpy(urb->transfer_buffer, buffer, length);
- usb_hcd_unlink_urb_from_ep(hcd, urb);
- usb_hcd_giveback_urb(hcd, urb, 0)-》
- if (!hcd_giveback_urb_in_bh(hcd) && !is_root_hub(urb->dev))
- {
- __usb_hcd_giveback_urb(urb)->
- usbmon_urb_complete(&hcd->self, urb, status);
- usb_anchor_suspend_wakeups(anchor);
- usb_unanchor_urb(urb);
- urb->complete(urb);
- usb_anchor_resume_wakeups(anchor);
- return;
- }
- list_add_tail(&urb->urb_list, &bh->head);
- mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
- /*
- root@mxlos:~# cat /proc/interrupts
- CPU0 CPU1 CPU2 CPU3
- 39: 5 0 0 0 GIC 42 Level 10180000.usb, 10180000.usb, dwc2_hsotg:usb1
- 40: 492059 0 0 0 GIC 43 Level ehci_hcd:usb2
- 41: 0 0 0 0 GIC 64 Level ohci_hcd:usb3
- */
- hcd->irq = irqnum;
- dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
- (hcd->driver->flags & HCD_MEMORY) ?
- "io mem" : "io base",(unsigned long long)hcd->rsrc_start);
- //实际打印:ehci-platform 101c0000.usb: irq 40, io mem 0x101c0000
- }
- }
- hcd->state = HC_STATE_RUNNING;
- retval = hcd->driver->start(hcd) = struct hc_driver ehci_hc_driver.start = ehci_run
- static int ehci_run(struct usb_hcd *hcd)->
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- hcd->uses_new_polling = 1;
- ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
- ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
- temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
- ehci_info (ehci, "USB %x.%x started, EHCI %x.%02x%s\n",
- ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
- temp >> 8, temp & 0xff, ignore_oc ? ", overcurrent ignored" : "");
- //对于 rk3128 来说实际打印:ehci-platform 101c0000.usb: USB 2.0 started, EHCI 1.00
- create_debug_files(ehci);
- create_sysfs_files(ehci)->
- struct device *controller = ehci_to_hcd(ehci)->self.controller;
- //对于rk3128对应文件 /sys/devices/platform/101c0000.usb/uframe_periodic_max
- i = device_create_file(controller, &dev_attr_uframe_periodic_max);
- retval = register_root_hub(hcd)-> //注册根集线器 root hub
-
- struct usb_device *usb_dev = hcd->self.root_hub;
- struct usb_device *usb_dev->devnum = devnum;
- usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
- usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE)-> //获取根集线器描述符
- struct usb_device_descriptor *desc = kmalloc(sizeof(*desc), GFP_NOIO);
- usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size)->
- for (i = 0; i < 3; ++i) //尝试读取3次
- {
- /* retry on length 0 or error; some devices are flakey */
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (type << 8) + index, 0, buf, size,
- USB_CTRL_GET_TIMEOUT);
- }
- memcpy(&dev->descriptor, desc, size);
- usb_new_device (usb_dev)->
- usb_enumerate_device(udev)-> /* Read descriptors */
- dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",
- udev->devnum, udev->bus->busnum,
- (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
- /* export the usbdev device-node for libusb */
- //#define USB_DEVICE_MAJOR 189
- udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
- announce_device(udev)-> /* Tell the world! 告诉全世界我诞生了 */
- /*
- 对于 USB2.0 的 root hub 实际打印:1d6b 和 0002 代表 USB2.0 root hub
- usb usb2: New USB device found, idVendor=1d6b, idProduct=0002
- usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
- usb usb2: Product: EHCI Host Controller
- usb usb2: Manufacturer: Linux 4.4.194 ehci_hcd
- usb usb2: SerialNumber: 101c0000.usb
- */
- dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",
- le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
- dev_info(&udev->dev,
- "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
- udev->descriptor.iManufacturer,
- udev->descriptor.iProduct,
- udev->descriptor.iSerialNumber);
- show_string(udev, "Product", udev->product);
- show_string(udev, "Manufacturer", udev->manufacturer);
- show_string(udev, "SerialNumber", udev->serial);
- device_enable_async_suspend(&udev->dev);
- device_add(&udev->dev)->
- dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
- // 对于 USB2.0 的 root hub 实际打印:device: 'usb2': device_add
- pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
- error = bus_add_device(dev)->
- struct bus_type *bus = bus_get(dev->bus);
- //对于 USB2.0 的 root hub 实际打印: bus: 'usb': add device usb2
- pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
- error = sysfs_create_link(&dev->kobj, &dev->bus->p->subsys.kobj, "subsystem");
- klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
- blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);
- kobject_uevent(&dev->kobj, KOBJ_ADD);
- bus_probe_device(dev)->device_initial_probe(dev)->__device_attach(dev, true)->
- bus_for_each_drv(dev->bus, NULL, &data, _device_attach_driver)->
- while ((drv = next_driver(&i)) && !error)
- {
- error = fn(drv, data)=_device_attach_driver;
- static int __device_attach_driver(struct device_driver *drv, void *_data)->
- if (!driver_match_device(drv, dev))->
- return drv->bus->match ? drv->bus->match(dev, drv) : 1;
- struct bus_type usb_bus_type.match = usb_device_match,
- // usb_device_match 有匹配的驱动时返回值为 1
- static int usb_device_match(struct device *dev, struct device_driver *drv)
- {
- /* devices and interfaces are handled separately */
- if (is_usb_device(dev)) //return dev->type == &usb_device_type;
- {
- /* interface drivers never match devices */
- if (!is_usb_device_driver(drv))
- return 0;
- /* TODO: Add real matching code */
- return 1;
- }
- else if (is_usb_interface(dev))
- {
- struct usb_interface *intf;
- struct usb_driver *usb_drv;
- const struct usb_device_id *id;
- /* device drivers never match interfaces */
- if (is_usb_device_driver(drv))
- return 0;
- intf = to_usb_interface(dev);
- usb_drv = to_usb_driver(drv);
- id = usb_match_id(intf, usb_drv->id_table);
- if (id)
- return 1;
- id = usb_match_dynamic_id(intf, usb_drv);
- if (id)
- return 1;
- }
- return 0;
- }
- {
- return 0;
- }
- return driver_probe_device(drv, dev)->
- //对USB2.0 的 root hub 实际打印: bus: 'usb': driver_probe_device: matched device usb2 with driver usb
- pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
- drv->bus->name, __func__, dev_name(dev), drv->name);
- really_probe(dev, drv)->
- //USB2.0 的 root hub 打印:bus: 'usb': driver_probe_device: matched device usb2 with driver usb
- pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
- drv->bus->name, __func__, drv->name, dev_name(dev));
- dev->driver = drv;
- // 所有USB子设备struct usb_device和USB接口设备struct usb_interface
- //都挂在USB总线上struct struct bus_type usb_bus_type
- if (dev->bus->probe) //struct struct bus_type usb_bus_type.probe = NULL
- {
- /*
- struct bus_type usb_bus_type = {
- .name = "usb",
- .match = usb_device_match,
- .uevent = usb_uevent,
- .need_parent_lock = true,
- };
- */
- ret = dev->bus->probe(dev);
- }
- else if (drv->probe)
- {//对 usb hub 驱动 struct usb_driver hub_driver hub.drvwrap.driver.probe = usb_probe_interface
- drv->probe(dev)=usb_probe_interface;
- static int usb_probe_interface(struct device *dev)->
- struct usb_device_id *id = usb_match_dynamic_id(intf, driver);
- if (!id)
- {
- id = usb_match_id(intf, driver->id_table)->
- for (; id->idVendor || id->idProduct || id->bDeviceClass ||
- id->bInterfaceClass || id->driver_info; id++) {
- if (usb_match_one_id(interface, id))->
- intf = interface->cur_altsetting;
- dev = interface_to_usbdev(interface);
- if (!usb_match_device(dev, id))
- return 0;
- return usb_match_one_id_intf(dev, intf, id);
- {
- return id;
- }
- }
- }
- dev_dbg(dev, "%s - got id\n", __func__);
- //对于 usb hub 驱动 struct usb_driver hub_driver.probe = hub_probe
- driver->probe(intf, id);
- int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)->
- dev_info(&intf->dev, "USB hub found\n");/* We found a hub */
- struct usb_hub *hub = kzalloc(sizeof(*hub), GFP_KERNEL);
- hub->intfdev = &intf->dev;
- hub->hdev = hdev;
- INIT_DELAYED_WORK(&hub->leds, led_work);
- INIT_DELAYED_WORK(&hub->init_work, NULL);
- INIT_WORK(&hub->events, hub_event); //用于处理hub的事件
- usb_get_intf(intf);
- usb_get_dev(hdev);
- usb_set_intfdata(intf, hub);
- intf->needs_remote_wakeup = 1;
- hub_configure(hub, endpoint)->// //设置hub的端点0
- hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
- hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
- hub->descriptor = kzalloc(sizeof(*hub->descriptor), ..);
- //Request the entire hub descriptor.
- get_hub_descriptor(hdev, hub->descriptor);
- maxchild = hub->descriptor->bNbrPorts;
- // USB2.0 的 root hub 打印: hub 2-0:1.0: 1 port detected
- //对于 GL852G 打印: hub 2-1:1.0: 4 ports detected
- dev_info(hub_dev, "%d port%s detected\n",
- maxchild, (maxchild == 1) ? "" : "s");
- hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), ..);
- wHubCharacteristics =
- le16_to_cpu(hub->descriptor->wHubCharacteristics);
- // USB2.0 的 root hub打印:hub 2-0:1.0: standalone hub
- dev_dbg(hub_dev, "standalone hub\n");
- //对于 GL852G 打印:hub 2-1:1.0: compound device;
- //port removable status: FFFF
- dev_dbg(hub_dev, "compound device;
- port removable status: %s\n", portstr);
- switch (wHubCharacteristics & HUB_CHAR_LPSM)
- {
- case HUB_CHAR_COMMON_LPSM:
- dev_dbg(hub_dev,"ganged power switching\n");
- break;
- case HUB_CHAR_INDV_PORT_LPSM:
- // USB2.0 的 root hub打印:
- //hub 2-0:1.0: individual port power switching
- dev_dbg(hub_dev, "individual port power switching\n");
- break;
- case HUB_CHAR_NO_LPSM:
- case HUB_CHAR_LPSM:
- dev_dbg(hub_dev, "no power switching (usb 1.0)\n");
- break;
- }
- switch (wHubCharacteristics & HUB_CHAR_OCPM) {
- case HUB_CHAR_INDV_PORT_OCPM:
- //USB2.0 的 root hub 打印:
- //hub 2-0:1.0: individual port over-current protection
- dev_dbg(hub_dev,
- "individual port over-current protection\n");
- break;
- case HUB_CHAR_NO_OCPM:
- case HUB_CHAR_OCPM:
- dev_dbg(hub_dev, "no over-current protection\n");
- break;
- }
- INIT_LIST_HEAD(&hub->tt.clear_list);
- INIT_WORK(&hub->tt.clear_work, hub_tt_work);
- // USB2.0 的 root hub打印:
- //hub 2-0:1.0: power on to power good time: 20ms
- dev_dbg(hub_dev, "power on to power good time: %dms\n",
- hub->descriptor->bPwrOn2PwrGood * 2);
- usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
- hcd = bus_to_hcd(hdev->bus);
- hub_hub_status(hub, &hubstatus, &hubchange);
- //USB2.0 root hub :hub 2-0:1.0: local power source is good
- dev_dbg(hub_dev, "local power source is %s\n",
- (hubstatus & HUB_STATUS_LOCAL_POWER)
- ? "lost (inactive)" : "good");
- hub->urb = usb_alloc_urb(0, GFP_KERNEL);
- /*
- USB设备需要热插拔,因此在hub_probe函数中调用hub_configure函数来配置hub,在这个函数中主要是利用函数usb_alloc_urb函数来分配一个urb,利用usb_fill_int_urb来初始化这个urb结构,包括hub的中断服务程序hub_irq的,查询的周期等。
- 每当有设备连接到USB接口时,USB总线在查询hub状态信息的时候会触发hub的中断服务程序hub_irq, 在该函数中置位event_bits,运行工作队列。进入hub_event函数,该函数用来处理端口变化的事件。然后通过一个for循环来检测每个端口的状态信息。利用usb_port_status获取端口信息,如果发生变化就调用hub_port_connect_change函数来配置端口等。
- */
- usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp,
- hub_irq, hub, endpoint->bInterval);
- for (i = 0; i < maxchild; i++)
- {
- usb_hub_create_port_device(hub, i + 1)->
- port_dev=kzalloc(sizeof(*port_dev), GFP_KERNEL);
- port_dev->req= kzalloc(sizeof(*(port_dev->req)), .);
- hub->ports[port1 - 1] = port_dev;
- port_dev->portnum = port1;
- set_bit(port1, hub->power_bits);
- port_dev->dev.parent = hub->intfdev;
- port_dev->dev.groups = port_dev_group;
- port_dev->dev.type = &usb_port_device_type;
- port_dev->dev.driver = &usb_port_driver;
- // USB2.0 的 root hub 上的
- //第一个USB子设备名为 : usb2-port1
- dev_set_name(&port_dev->dev,
- "%s-port%d",
- dev_name(&hub->hdev->dev), port1);
- device_register(&port_dev->dev)->
- device_initialize(dev);
- return device_add(dev);
- }
- hub_activate(hub, HUB_INIT)->
- //上电后延时,使hub稳定
- delay = hub_power_on_good_delay(hub);
- hub_power_on(hub, false)->
- //对于 USB2.0 的 root hub 实际打印:
- //hub 2-0:1.0: enabling power on all ports
- dev_dbg(hub->intfdev,
- "enabling power on all ports\n");
- INIT_DELAYED_WORK(&hub->init_work,
- hub_init_func2);
- queue_delayed_work(system_power_efficient_wq,
- &hub->init_work,
- msecs_to_jiffies(delay));
- init3:
- //提交urb,等执行完成就会回调hub_irq
- usb_submit_urb(hub->urb, GFP_NOIO);
- /* Scan all ports that need attention */
- kick_hub_wq(hub)->
- intf = to_usb_interface(hub->intfdev);
- //把hub_event加入工作队列,开始运行
- queue_work(hub_wq, &hub->events);
- intf->condition = USB_INTERFACE_BOUND;
- }
- else if (drv->probe) //匹配USB子设备 struct usb_device
- {
- // struct usb_device_driver usb_generic_driver.probe = generic_probe,
- // usb_register_device_driver()->
- // new_udriver->drvwrap.driver.probe = usb_probe_device;
- ret = drv->probe(dev);
- static int generic_probe(struct usb_device *udev)->
- usb_choose_configuration(udev)->
- num_configs = udev->descriptor.bNumConfigurations;
- usb_get_max_power(udev, c);
- i = best->desc.bConfigurationValue;
- //对于 USB2.0 的 root hub 实际打印:
- // usb usb2: configuration #1 chosen from 1 choice
- dev_dbg(&udev->dev, "configuration #%d chosen from %d
- choice%s\n", i, num_configs,
- plural(num_configs));
- usb_set_configuration(udev, c)->
- int nintf = cp->desc.bNumInterfaces;
- struct usb_interface **new_interfaces =
- kmalloc(nintf * sizeof(*new_interfaces),
- i = dev->bus_mA - usb_get_max_power(dev, cp);
- usb_autoresume_device(dev);
- usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
- struct usb_host_interface *alt = usb_altnum_to_altsetting(intf, 0);
- struct usb_interface *intf->cur_altsetting = alt;
- usb_enable_interface(dev, intf, true);
- intf->dev.parent = &dev->dev;
- intf->dev.driver = NULL;
- intf->dev.bus = &usb_bus_type;
- intf->dev.type = &usb_if_device_type; //USB 子设备
- intf->dev.groups = usb_interface_groups;
- intf->dev.dma_mask = dev->dev.dma_mask;
- INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); /*
- __usb_queue_reset_device(struct work_struct *ws)-> usb_reset_device(udev)->
- usb_reset_and_verify_device(udev)->
- usb_ep0_reinit(udev);
- descriptors_changed()->
- usb_string(udev,..)->
- usb_get_langid(dev, tbuf)->
- //对GL852G hub 芯片实际打印:usb 2-1: default language 0x0409
- dev_dbg(&dev->dev, "default language 0x%04x\n",
- dev->string_langid); */
- intf->minor = -1;
- device_initialize(&intf->dev);
- pm_runtime_no_callbacks(&intf->dev);
- dev_set_name(&intf->dev, "%d-%s:%d.%d",
- dev->bus->busnum, dev->devpath,
- configuration, alt->desc.bInterfaceNumber);
- usb_get_dev(dev);
- usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration,
- 0,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
- usb_set_device_state(dev, USB_STATE_CONFIGURED);
- for (i = 0; i < nintf; ++i)
- {
- struct usb_interface *intf = cp->interface[i];
- /*
- 对于 USB2.0 的 root hub 实际打印: usb usb2: adding 2-0:1.0 (config #1, interface 0)
- root@mxlos:/sys/bus/usb/drivers/usb/usb2# cd 2-0\:1.0/
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# ls
- authorized bInterfaceClass bInterfaceProtocol bNumEndpoints
- ep_81 power supports_autosuspend usb2-port1
- bAlternateSetting bInterfaceNumber bInterfaceSubClass driver
- modalias subsystem uevent
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# pwd
- /sys/bus/usb/drivers/usb/usb2/2-0:1.0
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# cat modalias
- usb:v1D6Bp0002d0404dc09dsc00dp00ic09isc00ip00in00
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# cat bInterfaceNumber
- 00
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# cat bAlternateSetting
- 0
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# cat uevent
- DEVTYPE=usb_interface
- DRIVER=hub
- PRODUCT=1d6b/2/404
- TYPE=9/0/0
- INTERFACE=9/0/0 MODALIAS=usb:v1D6Bp0002d0404dc09dsc00dp00ic09isc00ip00in00
- root@mxlos:/sys/bus/usb/drivers/usb/usb2/2-0:1.0# cat bInterfaceClass
- 09
- */ dev_dbg(&dev->dev,
- "adding %s (config #%d, interface %d)\n",
- dev_name(&intf->dev), configuration,
- intf->cur_altsetting->desc.bInterfaceNumber);
- device_enable_async_suspend(&intf->dev);
- ret = device_add(&intf->dev)->
- dev_set_name(dev, "%s%u", dev->bus->dev_name,
- dev->id);
- //对于USB2.0 的 root hub 的 interface 0 实际打印:
- // device: '2-0:1.0': device_add
- pr_debug("device: '%s': %s\n",
- dev_name(dev), __func__);
- kobject_uevent(&dev->kobj, KOBJ_ADD);
- bus_probe_device(dev);
- create_intf_ep_devs(intf);
- }
- usb_notify_add_device(udev)->
- blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
- }
- driver_bound(dev);
- //对于 USB2.0 的 root hub 实际打印: bus: 'usb': really_probe: bound device usb2 to driver usb
- pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
- drv->bus->name, __func__, dev_name(dev), drv->name);
- }
- /* Create link files between child device and usb port device. */
- if (udev->parent) {
- struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
- int port1 = udev->portnum;
- struct usb_port *port_dev = hub->ports[port1 - 1];
- err = sysfs_create_link(&udev->dev.kobj, &port_dev->dev.kobj, "port");
- err = sysfs_create_link(&port_dev->dev.kobj,&udev->dev.kobj, "device");
- }
- usb_create_ep_devs(&udev->dev, &udev->ep0, udev)->
- struct ep_device *ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
- ep_dev->desc = &endpoint->desc;
- ep_dev->udev = udev;
- ep_dev->dev.groups = ep_dev_groups;
- ep_dev->dev.type = &usb_ep_device_type;
- ep_dev->dev.parent = parent;
- //对于 USB2.0 的 root hub 对应 :/sys/bus/usb/drivers/usb/usb2/ep_00
- dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
- device_register(&ep_dev->dev);
- endpoint->ep_dev = ep_dev;
- hcd->rh_registered = 1;
- retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
- usb_hcd_poll_rh_status(hcd);
- device_wakeup_enable(hcd->self.controller);
- platform_set_drvdata(dev, hcd);
在注册 USB 主机控制器 host controller 的函数usb_add_hcd() 中会调用函数register_root_hub() 注册主机控制器下的 root hub,并最终调用 generic_probe() 遍历 root hub 下挂载的USB设备:
- usb_add_hcd(hcd, irq, IRQF_SHARED)->
- hcd->self.root_hub = rhdev; //设置主机控制器的根集线器
- struct usb_device *rhdev = usb_alloc_dev(NULL, &hcd->self, 0)->
- dev->dev.bus = &usb_bus_type;
- dev->dev.type = &usb_device_type;
- register_root_hub(hcd)->
- usb_new_device (usb_dev)->
- announce_device(udev);
- usb_enumerate_device(udev)
- device_add(&udev->dev)->
- bus_probe_device(dev)->device_initial_probe(dev)->__device_attach(dev, true)->
- bus_for_each_drv(dev->bus, NULL, &data, _device_attach_driver)->
- static int __device_attach_driver(struct device_driver *drv, void *_data)->
- static int usb_device_match(struct device *dev, struct device_driver *drv)
- /* devices and interfaces are handled separately */
- if (is_usb_device(dev)) //return dev->type == &usb_device_type;
- {
- /* interface drivers never match devices */
- /*
- 在函数usb_hub_init() 中注册 struct usb_driver hub_driver 时设置for_devices = 0:
- usb_register(&hub_driver)->
- usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)->
- new_driver->drvwrap.for_devices = 0;
- usb_init() 中注册 struct usb_device_driver usb_generic_driver 时设置for_devices = 1:
- usb_register_device_driver(&usb_generic_driver, THIS_MODULE)->
- new_udriver->drvwrap.for_devices = 1;
- */
- if (!is_usb_device_driver(drv))->
- return container_of(drv, struct usbdrv_wrap, driver)->for_devices;
- {
- return 0;
- }
- return 1;
- }
- return driver_probe_device(drv, dev)-> //匹配到 root hub 的驱动为 struct usb_device_driver usb_generic_driver
- really_probe(dev, drv)-> //struct usb_device_driver usb_generic_driver.probe = generic_probe
- generic_probe(struct usb_device *udev)->
- usb_choose_configuration(udev);
- usb_set_configuration(udev, c);
在内核源文件 linux-4.4\drivers\usb\core\driver.c 的函数usb_match_one_id_intf() 根据 usb interface class 来匹配USB 设备的驱动:
- int usb_match_one_id_intf(struct usb_device *dev,
- struct usb_host_interface *intf,
- const struct usb_device_id *id)
- {
- /* The interface class, subclass, protocol and number should never be
- * checked for a match if the device class is Vendor Specific,
- * unless the match record specifies the Vendor ID. */
- if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
- !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
- (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
- USB_DEVICE_ID_MATCH_INT_SUBCLASS |
- USB_DEVICE_ID_MATCH_INT_PROTOCOL |
- USB_DEVICE_ID_MATCH_INT_NUMBER)))
- return 0;
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
- (id->bInterfaceClass != intf->desc.bInterfaceClass))
- return 0;
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
- (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
- return 0;
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
- (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
- return 0;
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&
- (id->bInterfaceNumber != intf->desc.bInterfaceNumber))
- return 0;
- return 1;
- }
在文件 linux-4.4\include\uapi\linux\usb\ch9.h 定义的 usb interface class codes :
/*
* Device and/or Interface Class codes
* as found in bDeviceClass or bInterfaceClass
* and defined by www.usb.org documents
*/
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1 #音频设备
#define USB_CLASS_COMM 2 #调制解调器,网卡,ISDN连接
#define USB_CLASS_HID 3 #人机交互设备,,如鼠标,键盘
#define USB_CLASS_PHYSICAL 5 # 物理设备
#define USB_CLASS_STILL_IMAGE 6 #静止图像捕捉设备
#define USB_CLASS_PRINTER 7 #打印机
#define USB_CLASS_MASS_STORAGE 8 #大容量存储器
#define USB_CLASS_HUB 9 #集线器
#define USB_CLASS_CDC_DATA 0x0a #
#define USB_CLASS_CSCID 0x0b /* chip+ smart card :智能卡*/
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
#define USB_CLASS_VIDEO 0x0e // 视频设备,如网络摄像头
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_SUBCLASS_VENDOR_SPEC 0xff
在USB 官网Defined Class Codes | USB-IF 规定了 usb interface class :
复制网址 Defined Class Codes | USB-IF 的内容如下:
Base Class | Descriptor Usage | Description |
00h | Device | |
01h | Interface | |
02h | Both | |
03h | Interface | |
05h | Interface | |
06h | Interface | |
07h | Interface | |
08h | Interface | |
09h | Device | |
0Ah | Interface | |
0Bh | Interface | |
0Dh | Interface | |
0Eh | Interface | |
0Fh | Interface | |
10h | Interface | |
11h | Device | |
12h | Interface | |
13h | Interface | |
14h | Interface | |
3Ch | Interface | |
DCh | Both | |
E0h | Interface | |
EFh | Both | |
FEh | Interface | |
FFh | Both |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。