2085 lines · 59.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * drivers/usb/core/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 * * Released under the GPLv2 only. * * 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,			 const struct usb_device_id *id_table,			 struct device_driver *driver,			 const char *buf, size_t count){	struct usb_dynid *dynid;	u32 idVendor = 0;	u32 idProduct = 0;	unsigned int bInterfaceClass = 0;	u32 refVendor, refProduct;	int fields = 0;	int retval = 0; 	fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct,			&bInterfaceClass, &refVendor, &refProduct);	if (fields < 2)		return -EINVAL; 	dynid = kzalloc_obj(*dynid);	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 > 2 && bInterfaceClass) {		if (bInterfaceClass > 255) {			retval = -EINVAL;			goto fail;		} 		dynid->id.bInterfaceClass = (u8)bInterfaceClass;		dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;	} 	if (fields > 4) {		const struct usb_device_id *id = id_table; 		if (!id) {			retval = -ENODEV;			goto fail;		} 		for (; id->match_flags; id++)			if (id->idVendor == refVendor && id->idProduct == refProduct)				break; 		if (id->match_flags) {			dynid->id.driver_info = id->driver_info;		} else {			retval = -ENODEV;			goto fail;		}	} 	mutex_lock(&usb_dynids_lock);	list_add_tail(&dynid->node, &dynids->list);	mutex_unlock(&usb_dynids_lock); 	retval = driver_attach(driver); 	if (retval)		return retval;	return count; fail:	kfree(dynid);	return retval;}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; 	guard(mutex)(&usb_dynids_lock);	list_for_each_entry(dynid, &dynids->list, node)		if (dynid->id.bInterfaceClass != 0)			count += sysfs_emit_at(buf, count, "%04x %04x %02x\n",					   dynid->id.idVendor, dynid->id.idProduct,					   dynid->id.bInterfaceClass);		else			count += sysfs_emit_at(buf, 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, usb_drv->id_table, 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; 	guard(mutex)(&usb_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;		}	}	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->driver,					   &driver_attr_new_id);		if (error == 0) {			error = driver_create_file(&usb_drv->driver,					&driver_attr_remove_id);			if (error)				driver_remove_file(&usb_drv->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->driver,				&driver_attr_remove_id);		driver_remove_file(&usb_drv->driver,				   &driver_attr_new_id);	}} static void usb_free_dynids(struct usb_driver *usb_drv){	struct usb_dynid *dynid, *n; 	guard(mutex)(&usb_dynids_lock);	list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {		list_del(&dynid->node);		kfree(dynid);	}} static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,							const struct usb_driver *drv,							struct usb_device_id *id_copy){	struct usb_dynid *dynid; 	guard(mutex)(&usb_dynids_lock);	list_for_each_entry(dynid, &drv->dynids.list, node) {		if (usb_match_one_id(intf, &dynid->id)) {			*id_copy = dynid->id;			return id_copy;		}	}	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)		return error; 	if (udriver->generic_subclass)		error = usb_generic_driver_probe(udev);	if (error)		return error; 	/* Probe the USB device with the driver in hand, but only	 * defer to a generic driver in case the current USB	 * device driver has an id_table or a match function; i.e.,	 * when the device driver was explicitly matched against	 * a device.	 *	 * If the device driver does not have either of these,	 * then we assume that it can bind to any device and is	 * not truly a more specialized/non-generic driver, so a	 * return value of -ENODEV should not force the device	 * to be handled by the generic USB driver, as there	 * can still be another, more specialized, device driver.	 *	 * This accommodates the usbip driver.	 *	 * TODO: What if, in the future, there are multiple	 * specialized USB device drivers for a particular device?	 * In such cases, there is a need to try all matching	 * specialised device drivers prior to setting the	 * use_generic_driver bit.	 */	if (udriver->probe)		error = udriver->probe(udev);	else if (!udriver->generic_subclass)		error = -EINVAL;	if (error == -ENODEV && udriver != &usb_generic_driver &&	    (udriver->id_table || udriver->match)) {		udev->use_generic_driver = 1;		return -EPROBE_DEFER;	}	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); 	if (udriver->disconnect)		udriver->disconnect(udev);	if (udriver->generic_subclass)		usb_generic_driver_disconnect(udev);	if (!udriver->supports_autosuspend)		usb_autosuspend_device(udev);	return 0;} /* 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;	struct usb_device_id id_copy;	int error = -ENODEV;	int lpm_disable_error = -ENODEV; 	dev_dbg(dev, "%s\n", __func__); 	intf->needs_binding = 0; 	if (usb_device_is_owned(udev))		return error; 	if (udev->authorized == 0) {		dev_info(&intf->dev, "Device is not authorized for usage\n");		return error;	} else if (intf->authorized == 0) {		dev_info(&intf->dev, "Interface %d is not authorized for usage\n",				intf->altsetting->desc.bInterfaceNumber);		return error;	} 	id = usb_match_dynamic_id(intf, driver, &id_copy);	if (!id)		id = usb_match_id(intf, driver->id_table);	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.	 */	if (driver->disable_hub_initiated_lpm) {		lpm_disable_error = usb_unlocked_disable_lpm(udev);		if (lpm_disable_error) {			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; 	/* 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_host_endpoint *ep, **eps = NULL;	struct usb_device *udev;	int i, j, error, r;	int lpm_disable_error = -ENODEV; 	intf->condition = USB_INTERFACE_UNBINDING; 	/* Autoresume for set_interface call below */	udev = interface_to_usbdev(intf);	error = usb_autoresume_device(udev); 	/* If hub-initiated LPM policy may change, 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.	 */	if (driver->disable_hub_initiated_lpm)		lpm_disable_error = usb_unlocked_disable_lpm(udev); 	/*	 * Terminate all URBs for this interface unless the driver	 * supports "soft" unbinding and the device is still present.	 */	if (!driver->soft_unbind || udev->state == USB_STATE_NOTATTACHED)		usb_disable_interface(udev, intf, false); 	driver->disconnect(intf); 	/* Free streams */	for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {		ep = &intf->cur_altsetting->endpoint[i];		if (ep->streams == 0)			continue;		if (j == 0) {			eps = kmalloc_array(USB_MAXENDPOINTS, sizeof(void *),				      GFP_KERNEL);			if (!eps)				break;		}		eps[j++] = ep;	}	if (j) {		usb_free_streams(intf, eps, j, GFP_KERNEL);		kfree(eps);	} 	/* 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);

Lines 1–500 of 2085.