Linux usb【2】- hub 驱动介绍

本文简单介绍一下usb hub驱动如何工作。

通过前面文章我们知道,usb控制器驱动注册时会注册一个root_hub对应的usb_interface设备,它对于的驱动就在drivers/usb/core/hub.c里面, 当hub设备被注册时,会匹配到这个驱动,开始执行hub_probe。我们还是不会关注太多细节,主要关注hub是如何发现并创建一个设备的。

hub_probe里主要就是分配了一个usb_hub结构,并且注册了一个events工作队列和一个rq_urb_retry定时器,events工作队列主要用来处理hub的一些插拔事件,rq_urb_retry用来向hub发送hub->urb失败后通过定时器回调重新发送。然后调用hub_configure。

1777  static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
1778  {
1779  	struct usb_host_interface *desc;
1780  	struct usb_device *hdev;
1781  	struct usb_hub *hub;
1782  
1783  	desc = intf->cur_altsetting;
1784  	hdev = interface_to_usbdev(intf);
1785  
1786  	/*
1787  	 * Set default autosuspend delay as 0 to speedup bus suspend,
1788  	 * based on the below considerations:
1789  	 *
1790  	 * - Unlike other drivers, the hub driver does not rely on the
1791  	 *   autosuspend delay to provide enough time to handle a wakeup
1792  	 *   event, and the submitted status URB is just to check future
1793  	 *   change on hub downstream ports, so it is safe to do it.
1794  	 *
1795  	 * - The patch might cause one or more auto supend/resume for
1796  	 *   below very rare devices when they are plugged into hub
1797  	 *   first time:
1798  	 *
1799  	 *   	devices having trouble initializing, and disconnect
1800  	 *   	themselves from the bus and then reconnect a second
1801  	 *   	or so later
1802  	 *
1803  	 *   	devices just for downloading firmware, and disconnects
1804  	 *   	themselves after completing it
1805  	 *
1806  	 *   For these quite rare devices, their drivers may change the
1807  	 *   autosuspend delay of their parent hub in the probe() to one
1808  	 *   appropriate value to avoid the subtle problem if someone
1809  	 *   does care it.
1810  	 *
1811  	 * - The patch may cause one or more auto suspend/resume on
1812  	 *   hub during running 'lsusb', but it is probably too
1813  	 *   infrequent to worry about.
1814  	 *
1815  	 * - Change autosuspend delay of hub can avoid unnecessary auto
1816  	 *   suspend timer for hub, also may decrease power consumption
1817  	 *   of USB bus.
1818  	 *
1819  	 * - If user has indicated to prevent autosuspend by passing
1820  	 *   usbcore.autosuspend = -1 then keep autosuspend disabled.
1821  	 */
1822  #ifdef CONFIG_PM
1823  	if (hdev->dev.power.autosuspend_delay >= 0)
1824  		pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
1825  #endif
1826  
1827  	/*
1828  	 * Hubs have proper suspend/resume support, except for root hubs
1829  	 * where the controller driver doesn't have bus_suspend and
1830  	 * bus_resume methods.
1831  	 */
1832  	if (hdev->parent) {		/* normal device */
1833  		usb_enable_autosuspend(hdev);
1834  	} else {			/* root hub */
1835  		const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver;
1836  
1837  		if (drv->bus_suspend && drv->bus_resume)
1838  			usb_enable_autosuspend(hdev);
1839  	}
1840  
1841  	if (hdev->level == MAX_TOPO_LEVEL) {
1842  		dev_err(&intf->dev,
1843  			"Unsupported bus topology: hub nested too deep\n");
1844  		return -E2BIG;
1845  	}
1846  
1847  #ifdef	CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB
1848  	if (hdev->parent) {
1849  		dev_warn(&intf->dev, "ignoring external hub\n");
1850  		return -ENODEV;
1851  	}
1852  #endif
1853  
1854  	if (!hub_descriptor_is_sane(desc)) {
1855  		dev_err(&intf->dev, "bad descriptor, ignoring hub\n");
1856  		return -EIO;
1857  	}
1858  
1859  	/* We found a hub */
1860  	dev_info(&intf->dev, "USB hub found\n");
1861  
1862  	hub = kzalloc(sizeof(*hub), GFP_KERNEL);
1863  	if (!hub)
1864  		return -ENOMEM;
1865  
1866  	kref_init(&hub->kref);
1867  	hub->intfdev = &intf->dev;
1868  	hub->hdev = hdev;
1869  	INIT_DELAYED_WORK(&hub->leds, led_work);
1870  	INIT_DELAYED_WORK(&hub->init_work, NULL);
1871  	INIT_WORK(&hub->events, hub_event);
1872  	spin_lock_init(&hub->irq_urb_lock);
1873  	timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0);
1874  	usb_get_intf(intf);
1875  	usb_get_dev(hdev);
1876  
1877  	usb_set_intfdata(intf, hub);
1878  	intf->needs_remote_wakeup = 1;
1879  	pm_suspend_ignore_children(&intf->dev, true);
1880  
1881  	if (hdev->speed == USB_SPEED_HIGH)
1882  		highspeed_hubs++;
1883  
1884  	if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
1885  		hub->quirk_check_port_auto_suspend = 1;
1886  
1887  	if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) {
1888  		hub->quirk_disable_autosuspend = 1;
1889  		usb_autopm_get_interface_no_resume(intf);
1890  	}
1891  
1892  	if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
1893  		return 0;
1894  
1895  	hub_disconnect(intf);
1896  	return -ENODEV;
1897  }
1898  
1899  static int
1900  hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
1901  {
1902  	struct usb_device *hdev = interface_to_usbdev(intf);
1903  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
1904  
1905  	/* assert ifno == 0 (part of hub spec) */
1906  	switch (code) {
1907  	case USBDEVFS_HUB_PORTINFO: {
1908  		struct usbdevfs_hub_portinfo *info = user_data;
1909  		int i;
1910  
1911  		spin_lock_irq(&device_state_lock);
1912  		if (hdev->devnum <= 0)
1913  			info->nports = 0;
1914  		else {
1915  			info->nports = hdev->maxchild;
1916  			for (i = 0; i < info->nports; i++) {
1917  				if (hub->ports[i]->child == NULL)
1918  					info->port[i] = 0;
1919  				else
1920  					info->port[i] =
1921  						hub->ports[i]->child->devnum;
1922  			}
1923  		}
1924  		spin_unlock_irq(&device_state_lock);
1925  
1926  		return info->nports + 1;
1927  		}
1928  
1929  	default:
1930  		return -ENOSYS;
1931  	}
1932  }

hub_configure中会读取全部的hub描述符信息,用来初始化usb_hub,并且会填充hub->urb,这个urb就是用来轮询hub状态的urb,它的回调函数就是hub_irq。然后调用hub_activate。

1373  static int hub_configure(struct usb_hub *hub,
1374  	struct usb_endpoint_descriptor *endpoint)
1375  {
1376  	struct usb_hcd *hcd;
1377  	struct usb_device *hdev = hub->hdev;
1378  	struct device *hub_dev = hub->intfdev;
1379  	u16 hubstatus, hubchange;
1380  	u16 wHubCharacteristics;
1381  	unsigned int pipe;
1382  	int maxp, ret, i;
1383  	char *message = "out of memory";
1384  	unsigned unit_load;
1385  	unsigned full_load;
1386  	unsigned maxchild;
1387  
1388  	hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
1389  	if (!hub->buffer) {
1390  		ret = -ENOMEM;
1391  		goto fail;
1392  	}
1393  
1394  	hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
1395  	if (!hub->status) {
1396  		ret = -ENOMEM;
1397  		goto fail;
1398  	}
1399  	mutex_init(&hub->status_mutex);
1400  
1401  	hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
1402  	if (!hub->descriptor) {
1403  		ret = -ENOMEM;
1404  		goto fail;
1405  	}
1406  
1407  	/* Request the entire hub descriptor.
1408  	 * hub->descriptor can handle USB_MAXCHILDREN ports,
1409  	 * but a (non-SS) hub can/will return fewer bytes here.
1410  	 */
1411  	ret = get_hub_descriptor(hdev, hub->descriptor);
1412  	if (ret < 0) {
1413  		message = "can't read hub descriptor";
1414  		goto fail;
1415  	}
1416  
1417  	maxchild = USB_MAXCHILDREN;
1418  	if (hub_is_superspeed(hdev))
1419  		maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS);
1420  
1421  	if (hub->descriptor->bNbrPorts > maxchild) {
1422  		message = "hub has too many ports!";
1423  		ret = -ENODEV;
1424  		goto fail;
1425  	} else if 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值