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

📄 usb.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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-2001 (kernel hotplug, usb_device_id, 	more docs, etc) * (C) Copyright Yggdrasil Computing, Inc. 2000 *     (usb_device_id matching changes by Adam J. Richter) * * 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>#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/devfs_fs_kernel.h>#include <linux/spinlock.h>#include <asm/byteorder.h>#ifdef CONFIG_USB_DEBUG	#define DEBUG#else	#undef DEBUG#endif#include <linux/usb.h>#include "hcd.h"extern int  usb_hub_init(void);extern void usb_hub_cleanup(void);/* * Prototypes for the device driver probing/loading functions */static void usb_find_drivers(struct usb_device *);static int  usb_find_interface_driver(struct usb_device *, unsigned int);static void usb_check_support(struct usb_device *);/* * We have a per-interface "registered driver" list. */LIST_HEAD(usb_driver_list);devfs_handle_t usb_devfs_handle;	/* /dev/usb dir. */static struct usb_driver *usb_minors[256];/** *	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. */int usb_register(struct usb_driver *new_driver){	int i;	if (new_driver->fops != NULL) {		for (i = new_driver->minor; i < new_driver->minor + new_driver->num_minors; ++i) {			if (usb_minors[i]) {				err("error registering %s driver", new_driver->name);				return -EINVAL;			}		}		for (i = new_driver->minor; i < new_driver->minor + new_driver->num_minors; ++i)			usb_minors[i] = new_driver;	}	info("registered new driver %s", new_driver->name);	init_MUTEX(&new_driver->serialize);	/* Add it to the list of known drivers */	list_add_tail(&new_driver->driver_list, &usb_driver_list);	usb_scan_devices();	usbfs_update_special();	return 0;}/** *	usb_scan_devices - scans all unclaimed USB interfaces *	Context: !in_interrupt () * *	Goes through all unclaimed USB interfaces, and offers them to all *	registered USB drivers through the 'probe' function. *	This will automatically be called after usb_register is called. *	It is called by some of the subsystems layered over USB *	after one of their subdrivers are registered. */void usb_scan_devices(void){	struct list_head *tmp;	down (&usb_bus_list_lock);	tmp = usb_bus_list.next;	while (tmp != &usb_bus_list) {		struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);		tmp = tmp->next;		usb_check_support(bus->root_hub);	}	up (&usb_bus_list_lock);}/* * This function is part of a depth-first search down the device tree, * removing any instances of a device driver. */static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev){	int i;	if (!dev) {		err("null device being purged!!!");		return;	}	for (i=0; i<USB_MAXCHILDREN; i++)		if (dev->children[i])			usb_drivers_purge(driver, dev->children[i]);	if (!dev->actconfig)		return;				for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {		struct usb_interface *interface = &dev->actconfig->interface[i];				if (interface->driver == driver) {			if (driver->owner)				__MOD_INC_USE_COUNT(driver->owner);			down(&driver->serialize);			driver->disconnect(dev, interface->private_data);			up(&driver->serialize);			if (driver->owner)				__MOD_DEC_USE_COUNT(driver->owner);			/* if driver->disconnect didn't release the interface */			if (interface->driver)				usb_driver_release_interface(driver, interface);			/*			 * This will go through the list looking for another			 * driver that can handle the device			 */			usb_find_interface_driver(dev, i);		}	}}/** *	usb_deregister - unregister a USB driver *	@driver: USB operations of the driver to unregister *	Context: !in_interrupt () * *	Unlinks the specified driver from the internal USB driver list. */void usb_deregister(struct usb_driver *driver){	struct list_head *tmp;	int i;	info("deregistering driver %s", driver->name);	if (driver->fops != NULL)		for (i = driver->minor; i < driver->minor + driver->num_minors; ++i)			usb_minors[i] = NULL;	/*	 * first we remove the driver, to be sure it doesn't get used by	 * another thread while we are stepping through removing entries	 */	list_del(&driver->driver_list);	down (&usb_bus_list_lock);	tmp = usb_bus_list.next;	while (tmp != &usb_bus_list) {		struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);		tmp = tmp->next;		usb_drivers_purge(driver, bus->root_hub);	}	up (&usb_bus_list_lock);	usbfs_update_special();}/** * usb_ifnum_to_ifpos - convert the interface number to the interface position * @dev: the device to use * @ifnum: the interface number (bInterfaceNumber); not interface position * * This is used to convert the interface _number_ (as in * interface.bInterfaceNumber) to the interface _position_ (as in * dev->actconfig->interface + position).  Note that the number is the same as * the position for all interfaces _except_ devices with interfaces not * sequentially numbered (e.g., 0, 2, 3, etc). */int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum){	int i;	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)		if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)			return i;	return -EINVAL;}/** * 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. */struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum){	int i;	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)		if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)			return &dev->actconfig->interface[i];	return NULL;}/** * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number * @dev: the device whose current configuration is considered * @epnum: the desired endpoint * * This walks the device descriptor for the currently active configuration, * and returns a pointer to the endpoint with that particular endpoint * number, or null. * * Note that interface descriptors are not required to assign endpont * numbers sequentially, so that it would be incorrect to assume that * the first endpoint in that descriptor corresponds to interface zero. * This routine helps device drivers avoid such mistakes. */struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum){	int i, j, k;	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)		for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++)			for (k = 0; k < dev->actconfig->interface[i].altsetting[j].bNumEndpoints; k++)				if (epnum == dev->actconfig->interface[i].altsetting[j].endpoint[k].bEndpointAddress)					return &dev->actconfig->interface[i].altsetting[j].endpoint[k];	return NULL;}/* * This function is for doing a depth-first search for devices which * have support, for dynamic loading of driver modules. */static void usb_check_support(struct usb_device *dev){	int i;	if (!dev) {		err("null device being checked!!!");		return;	}	for (i=0; i<USB_MAXCHILDREN; i++)		if (dev->children[i])			usb_check_support(dev->children[i]);	if (!dev->actconfig)		return;	/* now we check this device */	if (dev->devnum > 0)		for (i = 0; i < dev->actconfig->bNumInterfaces; i++)			usb_find_interface_driver(dev, i);}/** * 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 * @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.  Any driver that does use this must * first be sure that no other driver has claimed the interface, by * checking with usb_interface_claimed(). */void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv){	if (!iface || !driver)		return;	// FIXME change API to report an error in this case	if (iface->driver)	    err ("%s driver booted %s off interface %p",	    	driver->name, iface->driver->name, iface);	else	    dbg("%s driver claimed interface %p", driver->name, iface);	iface->driver = driver;	iface->private_data = priv;} /* usb_driver_claim_interface() *//** * usb_interface_claimed - returns true iff an interface is claimed * @iface: the interface being checked * * This should be used by drivers to check other interfaces to see if * they are available or not.  If another driver has claimed the interface, * they may not claim it.  Otherwise it's OK to claim it using * usb_driver_claim_interface(). * * Returns true (nonzero) iff the interface is claimed, else false (zero). */int usb_interface_claimed(struct usb_interface *iface){	if (!iface)		return 0;	return (iface->driver != NULL);} /* usb_interface_claimed() *//** * 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 should be used by drivers to release their claimed interfaces. * It is normally called in their disconnect() methods, and only for * drivers that bound to more than one interface in their probe(). * * When the USB subsystem disconnect()s a driver from some interface, * it automatically invokes this method for that interface.  That * means that even drivers that used usb_driver_claim_interface() * usually won't need to call this. */void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface){	/* this should never happen, don't release something that's not ours */	if (!iface || iface->driver != driver)		return;	iface->driver = NULL;	iface->private_data = NULL;}/** * usb_match_id - find first usb_device_id matching device or interface * @dev: the device whose descriptors are considered when matching * @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;

⌨️ 快捷键说明

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