1811 lines · 52.7 KB · C
RawDownload
/* * drivers/usb/driver.c - most of the driver model stuff for usb * * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de> * * based on drivers/usb/usb.c which had the following copyrights: *	(C) Copyright Linus Torvalds 1999 *	(C) Copyright Johannes Erdfelt 1999-2001 *	(C) Copyright Andreas Gal 1999 *	(C) Copyright Gregory P. Smith 1999 *	(C) Copyright Deti Fliegl 1999 (new USB architecture) *	(C) Copyright Randy Dunlap 2000 *	(C) Copyright David Brownell 2000-2004 *	(C) Copyright Yggdrasil Computing, Inc. 2000 *		(usb_device_id matching changes by Adam J. Richter) *	(C) Copyright Greg Kroah-Hartman 2002-2003 * * NOTE! This is not actually a driver at all, rather this is * just a collection of helper routines that implement the * matching, probing, releasing, suspending and resuming for * real drivers. * */ #include <linux/device.h>#include <linux/slab.h>#include <linux/export.h>#include <linux/usb.h>#include <linux/usb/quirks.h>#include <linux/usb/hcd.h> #include "usb.h"  /* * Adds a new dynamic USBdevice ID to this driver, * and cause the driver to probe for all devices again. */ssize_t usb_store_new_id(struct usb_dynids *dynids,			 struct device_driver *driver,			 const char *buf, size_t count){	struct usb_dynid *dynid;	u32 idVendor = 0;	u32 idProduct = 0;	unsigned int bInterfaceClass = 0;	int fields = 0;	int retval = 0; 	fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct,					&bInterfaceClass);	if (fields < 2)		return -EINVAL; 	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);	if (!dynid)		return -ENOMEM; 	INIT_LIST_HEAD(&dynid->node);	dynid->id.idVendor = idVendor;	dynid->id.idProduct = idProduct;	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;	if (fields == 3) {		dynid->id.bInterfaceClass = (u8)bInterfaceClass;		dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;	} 	spin_lock(&dynids->lock);	list_add_tail(&dynid->node, &dynids->list);	spin_unlock(&dynids->lock); 	retval = driver_attach(driver); 	if (retval)		return retval;	return count;}EXPORT_SYMBOL_GPL(usb_store_new_id); ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf){	struct usb_dynid *dynid;	size_t count = 0; 	list_for_each_entry(dynid, &dynids->list, node)		if (dynid->id.bInterfaceClass != 0)			count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x %02x\n",					   dynid->id.idVendor, dynid->id.idProduct,					   dynid->id.bInterfaceClass);		else			count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x\n",					   dynid->id.idVendor, dynid->id.idProduct);	return count;}EXPORT_SYMBOL_GPL(usb_show_dynids); static ssize_t new_id_show(struct device_driver *driver, char *buf){	struct usb_driver *usb_drv = to_usb_driver(driver); 	return usb_show_dynids(&usb_drv->dynids, buf);} static ssize_t new_id_store(struct device_driver *driver,			    const char *buf, size_t count){	struct usb_driver *usb_drv = to_usb_driver(driver); 	return usb_store_new_id(&usb_drv->dynids, driver, buf, count);}static DRIVER_ATTR_RW(new_id); /* * Remove a USB device ID from this driver */static ssize_t remove_id_store(struct device_driver *driver, const char *buf,			       size_t count){	struct usb_dynid *dynid, *n;	struct usb_driver *usb_driver = to_usb_driver(driver);	u32 idVendor;	u32 idProduct;	int fields; 	fields = sscanf(buf, "%x %x", &idVendor, &idProduct);	if (fields < 2)		return -EINVAL; 	spin_lock(&usb_driver->dynids.lock);	list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {		struct usb_device_id *id = &dynid->id;		if ((id->idVendor == idVendor) &&		    (id->idProduct == idProduct)) {			list_del(&dynid->node);			kfree(dynid);			break;		}	}	spin_unlock(&usb_driver->dynids.lock);	return count;} static ssize_t remove_id_show(struct device_driver *driver, char *buf){	return new_id_show(driver, buf);}static DRIVER_ATTR_RW(remove_id); static int usb_create_newid_files(struct usb_driver *usb_drv){	int error = 0; 	if (usb_drv->no_dynamic_id)		goto exit; 	if (usb_drv->probe != NULL) {		error = driver_create_file(&usb_drv->drvwrap.driver,					   &driver_attr_new_id);		if (error == 0) {			error = driver_create_file(&usb_drv->drvwrap.driver,					&driver_attr_remove_id);			if (error)				driver_remove_file(&usb_drv->drvwrap.driver,						&driver_attr_new_id);		}	}exit:	return error;} static void usb_remove_newid_files(struct usb_driver *usb_drv){	if (usb_drv->no_dynamic_id)		return; 	if (usb_drv->probe != NULL) {		driver_remove_file(&usb_drv->drvwrap.driver,				&driver_attr_remove_id);		driver_remove_file(&usb_drv->drvwrap.driver,				   &driver_attr_new_id);	}} static void usb_free_dynids(struct usb_driver *usb_drv){	struct usb_dynid *dynid, *n; 	spin_lock(&usb_drv->dynids.lock);	list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {		list_del(&dynid->node);		kfree(dynid);	}	spin_unlock(&usb_drv->dynids.lock);} static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,							struct usb_driver *drv){	struct usb_dynid *dynid; 	spin_lock(&drv->dynids.lock);	list_for_each_entry(dynid, &drv->dynids.list, node) {		if (usb_match_one_id(intf, &dynid->id)) {			spin_unlock(&drv->dynids.lock);			return &dynid->id;		}	}	spin_unlock(&drv->dynids.lock);	return NULL;}  /* called from driver core with dev locked */static int usb_probe_device(struct device *dev){	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);	struct usb_device *udev = to_usb_device(dev);	int error = 0; 	dev_dbg(dev, "%s\n", __func__); 	/* TODO: Add real matching code */ 	/* The device should always appear to be in use	 * unless the driver supports autosuspend.	 */	if (!udriver->supports_autosuspend)		error = usb_autoresume_device(udev); 	if (!error)		error = udriver->probe(udev);	return error;} /* called from driver core with dev locked */static int usb_unbind_device(struct device *dev){	struct usb_device *udev = to_usb_device(dev);	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); 	udriver->disconnect(udev);	if (!udriver->supports_autosuspend)		usb_autosuspend_device(udev);	return 0;} /* * Cancel any pending scheduled resets * * [see usb_queue_reset_device()] * * Called after unconfiguring / when releasing interfaces. See * comments in __usb_queue_reset_device() regarding * udev->reset_running. */static void usb_cancel_queued_reset(struct usb_interface *iface){	if (iface->reset_running == 0)		cancel_work_sync(&iface->reset_ws);} /* called from driver core with dev locked */static int usb_probe_interface(struct device *dev){	struct usb_driver *driver = to_usb_driver(dev->driver);	struct usb_interface *intf = to_usb_interface(dev);	struct usb_device *udev = interface_to_usbdev(intf);	const struct usb_device_id *id;	int error = -ENODEV;	int lpm_disable_error; 	dev_dbg(dev, "%s\n", __func__); 	intf->needs_binding = 0; 	if (usb_device_is_owned(udev))		return error; 	if (udev->authorized == 0) {		dev_err(&intf->dev, "Device is not authorized for usage\n");		return error;	} 	id = usb_match_id(intf, driver->id_table);	if (!id)		id = usb_match_dynamic_id(intf, driver);	if (!id)		return error; 	dev_dbg(dev, "%s - got id\n", __func__); 	error = usb_autoresume_device(udev);	if (error)		return error; 	intf->condition = USB_INTERFACE_BINDING; 	/* Probed interfaces are initially active.  They are	 * runtime-PM-enabled only if the driver has autosuspend support.	 * They are sensitive to their children's power states.	 */	pm_runtime_set_active(dev);	pm_suspend_ignore_children(dev, false);	if (driver->supports_autosuspend)		pm_runtime_enable(dev); 	/* If the new driver doesn't allow hub-initiated LPM, and we can't	 * disable hub-initiated LPM, then fail the probe.	 *	 * Otherwise, leaving LPM enabled should be harmless, because the	 * endpoint intervals should remain the same, and the U1/U2 timeouts	 * should remain the same.	 *	 * If we need to install alt setting 0 before probe, or another alt	 * setting during probe, that should also be fine.  usb_set_interface()	 * will attempt to disable LPM, and fail if it can't disable it.	 */	lpm_disable_error = usb_unlocked_disable_lpm(udev);	if (lpm_disable_error && driver->disable_hub_initiated_lpm) {		dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",				__func__, driver->name);		error = lpm_disable_error;		goto err;	} 	/* Carry out a deferred switch to altsetting 0 */	if (intf->needs_altsetting0) {		error = usb_set_interface(udev, intf->altsetting[0].				desc.bInterfaceNumber, 0);		if (error < 0)			goto err;		intf->needs_altsetting0 = 0;	} 	error = driver->probe(intf, id);	if (error)		goto err; 	intf->condition = USB_INTERFACE_BOUND; 	/* If the LPM disable succeeded, balance the ref counts. */	if (!lpm_disable_error)		usb_unlocked_enable_lpm(udev); 	usb_autosuspend_device(udev);	return error;  err:	usb_set_intfdata(intf, NULL);	intf->needs_remote_wakeup = 0;	intf->condition = USB_INTERFACE_UNBOUND;	usb_cancel_queued_reset(intf); 	/* If the LPM disable succeeded, balance the ref counts. */	if (!lpm_disable_error)		usb_unlocked_enable_lpm(udev); 	/* Unbound interfaces are always runtime-PM-disabled and -suspended */	if (driver->supports_autosuspend)		pm_runtime_disable(dev);	pm_runtime_set_suspended(dev); 	usb_autosuspend_device(udev);	return error;} /* called from driver core with dev locked */static int usb_unbind_interface(struct device *dev){	struct usb_driver *driver = to_usb_driver(dev->driver);	struct usb_interface *intf = to_usb_interface(dev);	struct usb_device *udev;	int error, r, lpm_disable_error; 	intf->condition = USB_INTERFACE_UNBINDING; 	/* Autoresume for set_interface call below */	udev = interface_to_usbdev(intf);	error = usb_autoresume_device(udev); 	/* Hub-initiated LPM policy may change, so attempt to disable LPM until	 * the driver is unbound.  If LPM isn't disabled, that's fine because it	 * wouldn't be enabled unless all the bound interfaces supported	 * hub-initiated LPM.	 */	lpm_disable_error = usb_unlocked_disable_lpm(udev); 	/* Terminate all URBs for this interface unless the driver	 * supports "soft" unbinding.	 */	if (!driver->soft_unbind)		usb_disable_interface(udev, intf, false); 	driver->disconnect(intf);	usb_cancel_queued_reset(intf); 	/* Reset other interface state.	 * We cannot do a Set-Interface if the device is suspended or	 * if it is prepared for a system sleep (since installing a new	 * altsetting means creating new endpoint device entries).	 * When either of these happens, defer the Set-Interface.	 */	if (intf->cur_altsetting->desc.bAlternateSetting == 0) {		/* Already in altsetting 0 so skip Set-Interface.		 * Just re-enable it without affecting the endpoint toggles.		 */		usb_enable_interface(udev, intf, false);	} else if (!error && !intf->dev.power.is_prepared) {		r = usb_set_interface(udev, intf->altsetting[0].				desc.bInterfaceNumber, 0);		if (r < 0)			intf->needs_altsetting0 = 1;	} else {		intf->needs_altsetting0 = 1;	}	usb_set_intfdata(intf, NULL); 	intf->condition = USB_INTERFACE_UNBOUND;	intf->needs_remote_wakeup = 0; 	/* Attempt to re-enable USB3 LPM, if the disable succeeded. */	if (!lpm_disable_error)		usb_unlocked_enable_lpm(udev); 	/* Unbound interfaces are always runtime-PM-disabled and -suspended */	if (driver->supports_autosuspend)		pm_runtime_disable(dev);	pm_runtime_set_suspended(dev); 	/* Undo any residual pm_autopm_get_interface_* calls */	for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r)		usb_autopm_put_interface_no_suspend(intf);	atomic_set(&intf->pm_usage_cnt, 0); 	if (!error)		usb_autosuspend_device(udev); 	return 0;} /** * usb_driver_claim_interface - bind a driver to an interface * @driver: the driver to be bound * @iface: the interface to which it will be bound; must be in the *	usb device's active configuration * @priv: driver data associated with that interface * * This is used by usb device drivers that need to claim more than one * interface on a device when probing (audio and acm are current examples). * No device driver should directly modify internal usb_interface or * usb_device structure members. * * Few drivers should need to use this routine, since the most natural * way to bind to an interface is to return the private data from * the driver's probe() method. * * Callers must own the device lock, so driver probe() entries don't need * extra locking, but other call contexts may need to explicitly claim that * lock. * * Return: 0 on success. */int usb_driver_claim_interface(struct usb_driver *driver,				struct usb_interface *iface, void *priv){	struct device *dev = &iface->dev;	struct usb_device *udev;	int retval = 0;	int lpm_disable_error; 	if (dev->driver)		return -EBUSY; 	udev = interface_to_usbdev(iface); 	dev->driver = &driver->drvwrap.driver;	usb_set_intfdata(iface, priv);	iface->needs_binding = 0; 	iface->condition = USB_INTERFACE_BOUND; 	/* Disable LPM until this driver is bound. */	lpm_disable_error = usb_unlocked_disable_lpm(udev);	if (lpm_disable_error && driver->disable_hub_initiated_lpm) {		dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",				__func__, driver->name);		return -ENOMEM;	} 	/* Claimed interfaces are initially inactive (suspended) and	 * runtime-PM-enabled, but only if the driver has autosuspend	 * support.  Otherwise they are marked active, to prevent the	 * device from being autosuspended, but left disabled.  In either	 * case they are sensitive to their children's power states.	 */	pm_suspend_ignore_children(dev, false);	if (driver->supports_autosuspend)		pm_runtime_enable(dev);	else		pm_runtime_set_active(dev);

Lines 1–500 of 1811.