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

📄 usb.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
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);}/* * This is intended to be used by usb device drivers that need to * claim more than one interface on a device at once when probing * (audio and acm are good examples).  No device driver should have * to mess with the internal usb_interface or usb_device structure * members. */void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv){	if (!iface || !driver)		return;	dbg("%s driver claimed interface %p", driver->name, iface);	iface->driver = driver;	iface->private_data = priv;} /* usb_driver_claim_interface() *//* * This should be used by drivers to check other interfaces to see if * they are available or not. */int usb_interface_claimed(struct usb_interface *iface){	if (!iface)		return 0;	return (iface->driver != NULL);} /* usb_interface_claimed() *//* * This should be used by drivers to release their claimed interfaces */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; * 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_device *dev, struct usb_interface *interface,	     const struct usb_device_id *id){	struct usb_interface_descriptor	*intf = 0;	/* proc_connectinfo in devio.c may call us with id == NULL. */	if (id == NULL)		return NULL;	/* 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 != dev->descriptor.idVendor)			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&		    id->idProduct != 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 > dev->descriptor.bcdDevice))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&		    (id->bcdDevice_hi < 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;		intf = &interface->altsetting [interface->act_altsetting];		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&		    (id->bInterfaceClass != intf->bInterfaceClass))			continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&		    (id->bInterfaceSubClass != intf->bInterfaceSubClass))		    continue;		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&		    (id->bInterfaceProtocol != intf->bInterfaceProtocol))		    continue;		return id;	}	return NULL;}/* * This entrypoint gets called for each new device. * * We now walk the list of registered USB drivers, * looking for one that will accept this interface. * * "New Style" drivers use a table describing the devices and interfaces * they handle.  Those tables are available to user mode tools deciding * whether to load driver modules for a new device. * * The probe return value is changed to be a private pointer.  This way * the drivers don't have to dig around in our structures to set the * private pointer if they only need one interface.  * * Returns: 0 if a driver accepted the interface, -1 otherwise */static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum){	struct list_head *tmp;	struct usb_interface *interface;	void *private;	const struct usb_device_id *id;	struct usb_driver *driver;	int i;		if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {		err("bad find_interface_driver params");		return -1;	}	down(&dev->serialize);	interface = dev->actconfig->interface + ifnum;	if (usb_interface_claimed(interface))		goto out_err;	private = NULL;	for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {		driver = list_entry(tmp, struct usb_driver, driver_list);		tmp = tmp->next;		id = driver->id_table;		/* new style driver? */		if (id) {			for (i = 0; i < interface->num_altsetting; i++) {			  	interface->act_altsetting = i;				id = usb_match_id(dev, interface, id);				if (id) {					down(&driver->serialize);					private = driver->probe(dev,ifnum,id);					up(&driver->serialize);					if (private != NULL)						break;				}			}			/* if driver not bound, leave defaults unchanged */			if (private == NULL)				interface->act_altsetting = 0;		} else { /* "old style" driver */			down(&driver->serialize);			private = driver->probe(dev, ifnum, NULL);			up(&driver->serialize);		}		/* probe() may have changed the config on us */		interface = dev->actconfig->interface + ifnum;		if (private) {			usb_driver_claim_interface(driver, interface, private);			up(&dev->serialize);			return 0;		}	}out_err:	up(&dev->serialize);	return -1;}#ifdef	CONFIG_HOTPLUG/* * USB hotplugging invokes what /proc/sys/kernel/hotplug says * (normally /sbin/hotplug) when USB devices get added or removed. * * This invokes a user mode policy agent, typically helping to load driver * or other modules, configure the device, and more.  Drivers can provide * a MODULE_DEVICE_TABLE to help with module loading subtasks. * * Some synchronization is important: removes can't start processing * before the add-device processing completes, and vice versa.  That keeps * a stack of USB-related identifiers stable while they're in use.  If we * know that agents won't complete after they return (such as by forking * a process that completes later), it's enough to just waitpid() for the * agent -- as is currently done. * * The reason: we know we're called either from khubd (the typical case) * or from root hub initialization (init, kapmd, modprobe, etc).  In both * cases, we know no other thread can recycle our address, since we must * already have been serialized enough to prevent that. */static void call_policy (char *verb, struct usb_device *dev){	char *argv [3], **envp, *buf, *scratch;	int i = 0, value;	if (!hotplug_path [0])		return;	if (in_interrupt ()) {		dbg ("In_interrupt");		return;	}	if (!current->fs->root) {		/* statically linked USB is initted rather early */		dbg ("call_policy %s, num %d -- no FS yet", verb, dev->devnum);		return;	}	if (dev->devnum < 0) {		dbg ("device already deleted ??");		return;	}	if (!(envp = (char **) kmalloc (20 * sizeof (char *), GFP_KERNEL))) {		dbg ("enomem");		return;	}	if (!(buf = kmalloc (256, GFP_KERNEL))) {		kfree (envp);		dbg ("enomem2");		return;	}	/* only one standardized param to hotplug command: type */	argv [0] = hotplug_path;	argv [1] = "usb";	argv [2] = 0;	/* minimal command environment */	envp [i++] = "HOME=/";	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";#ifdef	DEBUG	/* hint that policy agent should enter no-stdout debug mode */	envp [i++] = "DEBUG=kernel";#endif	/* extensible set of named bus-specific parameters,	 * supporting multiple driver selection algorithms.	 */	scratch = buf;	/* action:  add, remove */	envp [i++] = scratch;	scratch += sprintf (scratch, "ACTION=%s", verb) + 1;#ifdef	CONFIG_USB_DEVICEFS	/* If this is available, userspace programs can directly read	 * all the device descriptors we don't tell them about.  Or	 * even act as usermode drivers.	 *	 * FIXME reduce hardwired intelligence here	 */	envp [i++] = "DEVFS=/proc/bus/usb";	envp [i++] = scratch;	scratch += sprintf (scratch, "DEVICE=/proc/bus/usb/%03d/%03d",		dev->bus->busnum, dev->devnum) + 1;#endif	/* per-device configuration hacks are common */	envp [i++] = scratch;	scratch += sprintf (scratch, "PRODUCT=%x/%x/%x",		dev->descriptor.idVendor,		dev->descriptor.idProduct,		dev->descriptor.bcdDevice) + 1;	/* class-based driver binding models */	envp [i++] = scratch;	scratch += sprintf (scratch, "TYPE=%d/%d/%d",			    dev->descriptor.bDeviceClass,			    dev->descriptor.bDeviceSubClass,			    dev->descriptor.bDeviceProtocol) + 1;	if (dev->descriptor.bDeviceClass == 0) {		int alt = dev->actconfig->interface [0].act_altsetting;		/* a simple/common case: one config, one interface, one driver		 * with current altsetting being a reasonable setting.		 * everything needs a smart agent and usbdevfs; or can rely on		 * device-specific binding policies.		 */		envp [i++] = scratch;		scratch += sprintf (scratch, "INTERFACE=%d/%d/%d",			dev->actconfig->interface [0].altsetting [alt].bInterfaceClass,			dev->actconfig->interface [0].altsetting [alt].bInterfaceSubClass,			dev->actconfig->interface [0].altsetting [alt].bInterfaceProtocol)			+ 1;		/* INTERFACE-0, INTERFACE-1, ... ? */	}	envp [i++] = 0;	/* assert: (scratch - buf) < sizeof buf */	/* NOTE: user mode daemons can call the agents too */	dbg ("kusbd: %s %s %d", argv [0], verb, dev->devnum);	value = call_usermodehelper (argv [0], argv, envp);	kfree (buf);	kfree (envp);	if (value != 0)		dbg ("kusbd policy returned 0x%x", value);}#elsestatic inline voidcall_policy (char *verb, struct usb_device *dev){ } #endif	/* CONFIG_HOTPLUG *//* * This entrypoint gets called for each new device. * * All interfaces are scanned for matching drivers. */static void usb_find_drivers(struct usb_device *dev){	unsigned ifnum;	unsigned rejected = 0;	unsigned claimed = 0;	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {		/* if this interface hasn't already been claimed */		if (!usb_interface_claimed(dev->actconfig->interface + ifnum)) {			if (usb_find_interface_driver(dev, ifnum))				rejected++;			else				claimed++;		}	} 	if (rejected)		dbg("unhandled interfaces on device");	if (!claimed) {		warn("USB device %d (vend/prod 0x%x/0x%x) is not claimed by any active driver.",			dev->devnum,			dev->descriptor.idVendor,			dev->descriptor.idProduct);#ifdef DEBUG		usb_show_device(dev);#endif	}}/* * Only HC's should call usb_alloc_dev and usb_free_dev directly * Anybody may use usb_inc_dev_use or usb_dec_dev_use */struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus){	struct usb_device *dev;	dev = kmalloc(sizeof(*dev), GFP_KERNEL);	if (!dev)		return NULL;	memset(dev, 0, sizeof(*dev));	usb_bus_get(bus);	dev->bus = bus;	dev->parent = parent;	atomic_set(&dev->refcnt, 1);

⌨️ 快捷键说明

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