linux USB驱动分析(三)USB host controller驱动分析

关键词: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 

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);

 USB2.0 root hub根集线器

在注册 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);

 usb interface class

在内核源文件 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

Use class information in the Interface Descriptors

01h

Interface

Audio

02h

Both

Communications and CDC Control

03h

Interface

HID (Human Interface Device)

05h

Interface

Physical

06h

Interface

Image

07h

Interface

Printer

08h

Interface

Mass Storage

09h

Device

Hub

0Ah

Interface

CDC-Data

0Bh

Interface

Smart Card

0Dh

Interface

Content Security

0Eh

Interface

Video

0Fh

Interface

Personal Healthcare

10h

Interface

Audio/Video Devices

11h

Device

Billboard Device Class

12h

Interface

USB Type-C Bridge Class

13h

Interface

USB Bulk Display Protocol Device Class

14h

Interface

MCTP over USB Protocol Endpoint Device Class

3Ch

Interface

I3C Device Class

DCh

Both

Diagnostic Device

E0h

Interface

Wireless Controller

EFh

Both

Miscellaneous

FEh

Interface

Application Specific

FFh

Both

Vendor Specific

 

 

 

  • 30
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的Linux USB驱动程序示例代码,实现了对USB设备的读写操作: ```c #include <linux/module.h> #include <linux/usb.h> #include <linux/slab.h> #include <linux/uaccess.h> #define USB_VENDOR_ID 0xXXXX // 请替换为实际的USB设备的Vendor ID #define USB_PRODUCT_ID 0xXXXX // 请替换为实际的USB设备的Product ID static struct usb_device_id my_usb_table[] = { { USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) }, { } }; MODULE_DEVICE_TABLE(usb, my_usb_table); static int my_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(interface); struct usb_endpoint_descriptor *ep_desc; struct usb_host_interface *iface_desc; unsigned char *buffer; int retval = -ENOMEM; int i; printk(KERN_INFO "My USB device (%04X:%04X) plugged in\n", id->idVendor, id->idProduct); printk(KERN_INFO "Number of endpoints: %d\n", interface->cur_altsetting->desc.bNumEndpoints); iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { ep_desc = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(ep_desc)) { printk(KERN_INFO "Bulk IN endpoint found\n"); } if (usb_endpoint_is_bulk_out(ep_desc)) { printk(KERN_INFO "Bulk OUT endpoint found\n"); } } buffer = kmalloc(64, GFP_KERNEL); if (!buffer) { printk(KERN_ERR "Failed to allocate memory for buffer\n"); return -ENOMEM; } retval = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x81), buffer, 64, NULL, 5000); if (retval < 0) { printk(KERN_ERR "Failed to read data from USB device (%d)\n", retval); goto error; } printk(KERN_INFO "Data read from USB device: "); for (i = 0; i < 64; i++) { printk("%02X ", buffer[i]); } printk("\n"); retval = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 0x01), "Hello World!", strlen("Hello World!") + 1, NULL, 5000); if (retval < 0) { printk(KERN_ERR "Failed to write data to USB device (%d)\n", retval); goto error; } kfree(buffer); return 0; error: kfree(buffer); return retval; } static void my_usb_disconnect(struct usb_interface *interface) { printk(KERN_INFO "My USB device removed\n"); } static struct usb_driver my_usb_driver = { .name = "my_usb_driver", .id_table = my_usb_table, .probe = my_usb_probe, .disconnect = my_usb_disconnect, }; static int __init my_usb_init(void) { int retval; retval = usb_register(&my_usb_driver); if (retval < 0) { printk(KERN_ERR "Failed to register USB driver (%d)\n", retval); return retval; } printk(KERN_INFO "My USB driver module loaded\n"); return 0; } static void __exit my_usb_exit(void) { usb_deregister(&my_usb_driver); printk(KERN_INFO "My USB driver module unloaded\n"); } module_init(my_usb_init); module_exit(my_usb_exit); MODULE_LICENSE("GPL"); ``` 这段代码实现了一个名为my_usb_driver的USB驱动程序,用于与指定的USB设备通信。在probe函数中,我们获取了设备的Endpoint信息,并使用usb_bulk_msg函数进行了读写操作。在disconnect函数中,我们简单地输出了设备的移除信息。 需要注意的是,此代码中的USB_VENDOR_ID和USB_PRODUCT_ID需要替换为实际的USB设备的Vendor ID和Product ID。这些信息可以通过使用lsusb命令来获取。另外,在编译此代码时,需要链接USB库。可以使用以下命令进行编译: ```shell make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` 其中,$(uname -r)用于获取当前Linux内核的版本号。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值