⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * drivers/usb/usb.c * * (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 * generic USB things that the real drivers can use.. * * Think of this as a "USB library" rather than anything else. * It should be considered a slave, with no callbacks. Callbacks * are evil. */#include <linux/config.h>#ifdef CONFIG_USB_DEBUG	#define DEBUG#else	#undef DEBUG#endif#include <linux/module.h>#include <linux/string.h>#include <linux/bitops.h>#include <linux/slab.h>#include <linux/interrupt.h>  /* for in_interrupt() */#include <linux/kmod.h>#include <linux/init.h>#include <linux/spinlock.h>#include <linux/errno.h>#include <linux/smp_lock.h>#include <linux/rwsem.h>#include <linux/usb.h>#include <asm/io.h>#include <asm/scatterlist.h>#include <linux/mm.h>#include <linux/dma-mapping.h>#include "hcd.h"#include "usb.h"extern int  usb_hub_init(void);extern void usb_hub_cleanup(void);extern int usb_major_init(void);extern void usb_major_cleanup(void);extern int usb_host_init(void);extern void usb_host_cleanup(void);const char *usbcore_name = "usbcore";int nousb;		/* Disable USB when built into kernel image */			/* Not honored on modular build */static DECLARE_RWSEM(usb_all_devices_rwsem);static int generic_probe (struct device *dev){	return 0;}static int generic_remove (struct device *dev){	return 0;}static struct device_driver usb_generic_driver = {	.owner = THIS_MODULE,	.name =	"usb",	.bus = &usb_bus_type,	.probe = generic_probe,	.remove = generic_remove,};static int usb_generic_driver_data;/* called from driver core with usb_bus_type.subsys writelock */int usb_probe_interface(struct device *dev){	struct usb_interface * intf = to_usb_interface(dev);	struct usb_driver * driver = to_usb_driver(dev->driver);	const struct usb_device_id *id;	int error = -ENODEV;	dev_dbg(dev, "%s\n", __FUNCTION__);	if (!driver->probe)		return error;	/* FIXME we'd much prefer to just resume it ... */	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)		return -EHOSTUNREACH;	id = usb_match_id (intf, driver->id_table);	if (id) {		dev_dbg (dev, "%s - got id\n", __FUNCTION__);		intf->condition = USB_INTERFACE_BINDING;		error = driver->probe (intf, id);		intf->condition = error ? USB_INTERFACE_UNBOUND :				USB_INTERFACE_BOUND;	}	return error;}/* called from driver core with usb_bus_type.subsys writelock */int usb_unbind_interface(struct device *dev){	struct usb_interface *intf = to_usb_interface(dev);	struct usb_driver *driver = to_usb_driver(intf->dev.driver);	intf->condition = USB_INTERFACE_UNBINDING;	/* release all urbs for this interface */	usb_disable_interface(interface_to_usbdev(intf), intf);	if (driver && driver->disconnect)		driver->disconnect(intf);	/* reset other interface state */	usb_set_interface(interface_to_usbdev(intf),			intf->altsetting[0].desc.bInterfaceNumber,			0);	usb_set_intfdata(intf, NULL);	intf->condition = USB_INTERFACE_UNBOUND;	return 0;}/** * usb_register - register a USB driver * @new_driver: USB operations for the driver * * Registers a USB driver with the USB core.  The list of unattached * interfaces will be rescanned whenever a new driver is added, allowing * the new driver to attach to any recognized devices. * Returns a negative error code on failure and 0 on success. *  * NOTE: if you want your driver to use the USB major number, you must call * usb_register_dev() to enable that functionality.  This function no longer * takes care of that. */int usb_register(struct usb_driver *new_driver){	int retval = 0;	if (nousb)		return -ENODEV;	new_driver->driver.name = (char *)new_driver->name;	new_driver->driver.bus = &usb_bus_type;	new_driver->driver.probe = usb_probe_interface;	new_driver->driver.remove = usb_unbind_interface;	new_driver->driver.owner = new_driver->owner;	usb_lock_all_devices();	retval = driver_register(&new_driver->driver);	usb_unlock_all_devices();	if (!retval) {		pr_info("%s: registered new driver %s\n",			usbcore_name, new_driver->name);		usbfs_update_special();	} else {		printk(KERN_ERR "%s: error %d registering driver %s\n",			usbcore_name, retval, new_driver->name);	}	return retval;}/** * usb_deregister - unregister a USB driver * @driver: USB operations of the driver to unregister * Context: must be able to sleep * * Unlinks the specified driver from the internal USB driver list. *  * NOTE: If you called usb_register_dev(), you still need to call * usb_deregister_dev() to clean up your driver's allocated minor numbers, * this * call will no longer do it for you. */void usb_deregister(struct usb_driver *driver){	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);	usb_lock_all_devices();	driver_unregister (&driver->driver);	usb_unlock_all_devices();	usbfs_update_special();}/** * usb_ifnum_to_if - get the interface object with a given interface number * @dev: the device whose current configuration is considered * @ifnum: the desired interface * * This walks the device descriptor for the currently active configuration * and returns a pointer to the interface with that particular interface * number, or null. * * Note that configuration descriptors are not required to assign interface * numbers sequentially, so that it would be incorrect to assume that * the first interface in that descriptor corresponds to interface zero. * This routine helps device drivers avoid such mistakes. * However, you should make sure that you do the right thing with any * alternate settings available for this interfaces. * * Don't call this function unless you are bound to one of the interfaces * on this device or you have locked the device! */struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum){	struct usb_host_config *config = dev->actconfig;	int i;	if (!config)		return NULL;	for (i = 0; i < config->desc.bNumInterfaces; i++)		if (config->interface[i]->altsetting[0]				.desc.bInterfaceNumber == ifnum)			return config->interface[i];	return NULL;}/** * usb_altnum_to_altsetting - get the altsetting structure with a given *	alternate setting number. * @intf: the interface containing the altsetting in question * @altnum: the desired alternate setting number * * This searches the altsetting array of the specified interface for * an entry with the correct bAlternateSetting value and returns a pointer * to that entry, or null. * * Note that altsettings need not be stored sequentially by number, so * it would be incorrect to assume that the first altsetting entry in * the array corresponds to altsetting zero.  This routine helps device * drivers avoid such mistakes. * * Don't call this function unless you are bound to the intf interface * or you have locked the device! */struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,		unsigned int altnum){	int i;	for (i = 0; i < intf->num_altsetting; i++) {		if (intf->altsetting[i].desc.bAlternateSetting == altnum)			return &intf->altsetting[i];	}	return NULL;}/** * 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 and the driver model's usb_bus_type.subsys * writelock.  So driver probe() entries don't need extra locking, * but other call contexts may need to explicitly claim those locks. */int usb_driver_claim_interface(struct usb_driver *driver,				struct usb_interface *iface, void* priv){	struct device *dev = &iface->dev;	if (dev->driver)		return -EBUSY;	dev->driver = &driver->driver;	usb_set_intfdata(iface, priv);	iface->condition = USB_INTERFACE_BOUND;	/* if interface was already added, bind now; else let	 * the future device_add() bind it, bypassing probe()	 */	if (!list_empty (&dev->bus_list))		device_bind_driver(dev);	return 0;}/** * usb_driver_release_interface - unbind a driver from an interface * @driver: the driver to be unbound * @iface: the interface from which it will be unbound * * This can be used by drivers to release an interface without waiting * for their disconnect() methods to be called.  In typical cases this * also causes the driver disconnect() method to be called. * * This call is synchronous, and may not be used in an interrupt context. * Callers must own the device lock and the driver model's usb_bus_type.subsys * writelock.  So driver disconnect() entries don't need extra locking, * but other call contexts may need to explicitly claim those locks. */void usb_driver_release_interface(struct usb_driver *driver,					struct usb_interface *iface){	struct device *dev = &iface->dev;	/* this should never happen, don't release something that's not ours */	if (!dev->driver || dev->driver != &driver->driver)		return;	/* don't disconnect from disconnect(), or before dev_add() */	if (!list_empty (&dev->driver_list) && !list_empty (&dev->bus_list))		device_release_driver(dev);	dev->driver = NULL;	usb_set_intfdata(iface, NULL);	iface->condition = USB_INTERFACE_UNBOUND;}/** * usb_match_id - find first usb_device_id matching device or interface * @interface: the interface of interest * @id: array of usb_device_id structures, terminated by zero entry * * usb_match_id searches an array of usb_device_id's and returns * the first one matching the device or interface, or null. * This is used when binding (or rebinding) a driver to an interface. * Most USB device drivers will use this indirectly, through the usb core, * but some layered driver frameworks use it directly. * These device tables are exported with MODULE_DEVICE_TABLE, through * modutils and "modules.usbmap", to support the driver loading * functionality of USB hotplugging. * * What Matches: * * The "match_flags" element in a usb_device_id controls which * members are used.  If the corresponding bit is set, the * value in the device_id must match its corresponding member * in the device or interface descriptor, or else the device_id * does not match. * * "driver_info" is normally used only by device drivers, * but you can create a wildcard "matches anything" usb_device_id * as a driver's "modules.usbmap" entry if you provide an id with * only a nonzero "driver_info" field.  If you do this, the USB device * driver's probe() routine should use additional intelligence to * decide whether to bind to the specified interface. *  * What Makes Good usb_device_id Tables: * * The match algorithm is very simple, so that intelligence in * driver selection must come from smart driver id records. * Unless you have good reasons to use another selection policy, * provide match elements only in related groups, and order match * specifiers from specific to general.  Use the macros provided * for that purpose if you can. * * The most specific match specifiers use device descriptor * data.  These are commonly used with product-specific matches; * the USB_DEVICE macro lets you provide vendor and product IDs, * and you can also match against ranges of product revisions. * These are widely used for devices with application or vendor * specific bDeviceClass values. * * Matches based on device class/subclass/protocol specifications * are slightly more general; use the USB_DEVICE_INFO macro, or * its siblings.  These are used with single-function devices * where bDeviceClass doesn't specify that each interface has * its own class.  * * Matches based on interface class/subclass/protocol are the * most general; they let drivers bind to any interface on a * multiple-function device.  Use the USB_INTERFACE_INFO * macro, or its siblings, to match class-per-interface style  * devices (as recorded in bDeviceClass). *   * Within those groups, remember that not all combinations are * meaningful.  For example, don't give a product version range * without vendor and product IDs; or specify a protocol without * its associated class and subclass. */   const struct usb_device_id *usb_match_id(struct usb_interface *interface, const struct usb_device_id *id){	struct usb_host_interface *intf;	struct usb_device *dev;	/* proc_connectinfo in devio.c may call us with id == NULL. */	if (id == NULL)		return NULL;	intf = interface->cur_altsetting;	dev = interface_to_usbdev(interface);	/* It is important to check that id->driver_info is nonzero,	   since an entry that is all zeroes except for a nonzero	   id->driver_info is the way to create an entry that	   indicates that the driver want to examine every	   device and interface. */	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||	       id->driver_info; id++) {		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&		    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&		    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))			continue;		/* No need to test id->bcdDevice_lo != 0, since 0 is never		   greater than any unsigned number. */		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&		    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&		    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&		    (id->bDeviceClass != dev->descriptor.bDeviceClass))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&		    (id->bInterfaceClass != intf->desc.bInterfaceClass))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&		    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&		    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))			continue;		return id;	}	return NULL;}/** * usb_find_interface - find usb_interface pointer for driver and device * @drv: the driver whose current configuration is considered * @minor: the minor number of the desired device * * This walks the driver device list and returns a pointer to the interface  * with the matching minor.  Note, this only works for devices that share the * USB major number. */struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor){	struct list_head *entry;	struct device *dev;	struct usb_interface *intf;	list_for_each(entry, &drv->driver.devices) {		dev = container_of(entry, struct device, driver_list);		/* can't look at usb devices, only interfaces */		if (dev->driver == &usb_generic_driver)			continue;		intf = to_usb_interface(dev);		if (intf->minor == -1)			continue;		if (intf->minor == minor)			return intf;	}	/* no device found that matches */	return NULL;	}static int usb_device_match (struct device *dev, struct device_driver *drv){	struct usb_interface *intf;	struct usb_driver *usb_drv;	const struct usb_device_id *id;	/* check for generic driver, which we don't match any device with */	if (drv == &usb_generic_driver)		return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -