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

📄 usb.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	intf = to_usb_interface(dev);	usb_drv = to_usb_driver(drv);		id = usb_match_id (intf, usb_drv->id_table);	if (id)		return 1;	return 0;}#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. * * We're called either from khubd (the typical case) or from root hub * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the * device (and this configuration!) are still present. */static int usb_hotplug (struct device *dev, char **envp, int num_envp,			char *buffer, int buffer_size){	struct usb_interface *intf;	struct usb_device *usb_dev;	int i = 0;	int length = 0;	if (!dev)		return -ENODEV;	/* driver is often null here; dev_dbg() would oops */	pr_debug ("usb %s: hotplug\n", dev->bus_id);	/* Must check driver_data here, as on remove driver is always NULL */	if ((dev->driver == &usb_generic_driver) || 	    (dev->driver_data == &usb_generic_driver_data))		return 0;	intf = to_usb_interface(dev);	usb_dev = interface_to_usbdev (intf);		if (usb_dev->devnum < 0) {		pr_debug ("usb %s: already deleted?\n", dev->bus_id);		return -ENODEV;	}	if (!usb_dev->bus) {		pr_debug ("usb %s: bus removed?\n", dev->bus_id);		return -ENODEV;	}#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	 */	if (add_hotplug_env_var(envp, num_envp, &i,				buffer, buffer_size, &length,				"DEVICE=/proc/bus/usb/%03d/%03d",				usb_dev->bus->busnum, usb_dev->devnum))		return -ENOMEM;#endif	/* per-device configurations are common */	if (add_hotplug_env_var(envp, num_envp, &i,				buffer, buffer_size, &length,				"PRODUCT=%x/%x/%x",				le16_to_cpu(usb_dev->descriptor.idVendor),				le16_to_cpu(usb_dev->descriptor.idProduct),				le16_to_cpu(usb_dev->descriptor.bcdDevice)))		return -ENOMEM;	/* class-based driver binding models */	if (add_hotplug_env_var(envp, num_envp, &i,				buffer, buffer_size, &length,				"TYPE=%d/%d/%d",				usb_dev->descriptor.bDeviceClass,				usb_dev->descriptor.bDeviceSubClass,				usb_dev->descriptor.bDeviceProtocol))		return -ENOMEM;	if (usb_dev->descriptor.bDeviceClass == 0) {		struct usb_host_interface *alt = intf->cur_altsetting;		/* 2.4 only exposed interface zero.  in 2.5, hotplug		 * agents are called for all interfaces, and can use		 * $DEVPATH/bInterfaceNumber if necessary.		 */		if (add_hotplug_env_var(envp, num_envp, &i,					buffer, buffer_size, &length,					"INTERFACE=%d/%d/%d",					alt->desc.bInterfaceClass,					alt->desc.bInterfaceSubClass,					alt->desc.bInterfaceProtocol))			return -ENOMEM;	}	envp[i] = NULL;	return 0;}#elsestatic int usb_hotplug (struct device *dev, char **envp,			int num_envp, char *buffer, int buffer_size){	return -ENODEV;}#endif	/* CONFIG_HOTPLUG *//** * usb_release_dev - free a usb device structure when all users of it are finished. * @dev: device that's been disconnected * * Will be called only by the device core when all users of this usb device are * done. */static void usb_release_dev(struct device *dev){	struct usb_device *udev;	udev = to_usb_device(dev);	usb_destroy_configuration(udev);	usb_bus_put(udev->bus);	kfree (udev);}/** * usb_alloc_dev - usb device constructor (usbcore-internal) * @parent: hub to which device is connected; null to allocate a root hub * @bus: bus used to access the device * @port1: one-based index of port; ignored for root hubs * Context: !in_interrupt () * * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. * * This call may not be used in a non-sleeping context. */struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1){	struct usb_device *dev;	dev = kmalloc(sizeof(*dev), GFP_KERNEL);	if (!dev)		return NULL;	memset(dev, 0, sizeof(*dev));	bus = usb_bus_get(bus);	if (!bus) {		kfree(dev);		return NULL;	}	device_initialize(&dev->dev);	dev->dev.bus = &usb_bus_type;	dev->dev.dma_mask = bus->controller->dma_mask;	dev->dev.driver_data = &usb_generic_driver_data;	dev->dev.driver = &usb_generic_driver;	dev->dev.release = usb_release_dev;	dev->state = USB_STATE_ATTACHED;	INIT_LIST_HEAD(&dev->ep0.urb_list);	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;	/* ep0 maxpacket comes later, from device descriptor */	dev->ep_in[0] = dev->ep_out[0] = &dev->ep0;	/* Save readable and stable topology id, distinguishing devices	 * by location for diagnostics, tools, driver model, etc.  The	 * string is a path along hub ports, from the root.  Each device's	 * dev->devpath will be stable until USB is re-cabled, and hubs	 * are often labeled with these port numbers.  The bus_id isn't	 * as stable:  bus->busnum changes easily from modprobe order,	 * cardbus or pci hotplugging, and so on.	 */	if (unlikely (!parent)) {		dev->devpath [0] = '0';		dev->dev.parent = bus->controller;		sprintf (&dev->dev.bus_id[0], "usb%d", bus->busnum);	} else {		/* match any labeling on the hubs; it's one-based */		if (parent->devpath [0] == '0')			snprintf (dev->devpath, sizeof dev->devpath,				"%d", port1);		else			snprintf (dev->devpath, sizeof dev->devpath,				"%s.%d", parent->devpath, port1);		dev->dev.parent = &parent->dev;		sprintf (&dev->dev.bus_id[0], "%d-%s",			bus->busnum, dev->devpath);		/* hub driver sets up TT records */	}	dev->bus = bus;	dev->parent = parent;	INIT_LIST_HEAD(&dev->filelist);	init_MUTEX(&dev->serialize);	return dev;}/** * usb_get_dev - increments the reference count of the usb device structure * @dev: the device being referenced * * Each live reference to a device should be refcounted. * * Drivers for USB interfaces should normally record such references in * their probe() methods, when they bind to an interface, and release * them by calling usb_put_dev(), in their disconnect() methods. * * A pointer to the device with the incremented reference counter is returned. */struct usb_device *usb_get_dev(struct usb_device *dev){	if (dev)		get_device(&dev->dev);	return dev;}/** * usb_put_dev - release a use of the usb device structure * @dev: device that's been disconnected * * Must be called when a user of a device is finished with it.  When the last * user of the device calls this function, the memory of the device is freed. */void usb_put_dev(struct usb_device *dev){	if (dev)		put_device(&dev->dev);}/** * usb_get_intf - increments the reference count of the usb interface structure * @intf: the interface being referenced * * Each live reference to a interface must be refcounted. * * Drivers for USB interfaces should normally record such references in * their probe() methods, when they bind to an interface, and release * them by calling usb_put_intf(), in their disconnect() methods. * * A pointer to the interface with the incremented reference counter is * returned. */struct usb_interface *usb_get_intf(struct usb_interface *intf){	if (intf)		get_device(&intf->dev);	return intf;}/** * usb_put_intf - release a use of the usb interface structure * @intf: interface that's been decremented * * Must be called when a user of an interface is finished with it.  When the * last user of the interface calls this function, the memory of the interface * is freed. */void usb_put_intf(struct usb_interface *intf){	if (intf)		put_device(&intf->dev);}/*			USB device locking * * Although locking USB devices should be straightforward, it is * complicated by the way the driver-model core works.  When a new USB * driver is registered or unregistered, the core will automatically * probe or disconnect all matching interfaces on all USB devices while * holding the USB subsystem writelock.  There's no good way for us to * tell which devices will be used or to lock them beforehand; our only * option is to effectively lock all the USB devices. * * We do that by using a private rw-semaphore, usb_all_devices_rwsem. * When locking an individual device you must first acquire the rwsem's * readlock.  When a driver is registered or unregistered the writelock * must be held.  These actions are encapsulated in the subroutines * below, so all a driver needs to do is call usb_lock_device() and * usb_unlock_device(). * * Complications arise when several devices are to be locked at the same * time.  Only hub-aware drivers that are part of usbcore ever have to * do this; nobody else needs to worry about it.  The problem is that * usb_lock_device() must not be called to lock a second device since it * would acquire the rwsem's readlock reentrantly, leading to deadlock if * another thread was waiting for the writelock.  The solution is simple: * *	When locking more than one device, call usb_lock_device() *	to lock the first one.  Lock the others by calling *	down(&udev->serialize) directly. * *	When unlocking multiple devices, use up(&udev->serialize) *	to unlock all but the last one.  Unlock the last one by *	calling usb_unlock_device(). * *	When locking both a device and its parent, always lock the *	the parent first. *//** * usb_lock_device - acquire the lock for a usb device structure * @udev: device that's being locked * * Use this routine when you don't hold any other device locks; * to acquire nested inner locks call down(&udev->serialize) directly. * This is necessary for proper interaction with usb_lock_all_devices(). */void usb_lock_device(struct usb_device *udev){	down_read(&usb_all_devices_rwsem);	down(&udev->serialize);}/** * usb_trylock_device - attempt to acquire the lock for a usb device structure * @udev: device that's being locked * * Don't use this routine if you already hold a device lock; * use down_trylock(&udev->serialize) instead. * This is necessary for proper interaction with usb_lock_all_devices(). * * Returns 1 if successful, 0 if contention. */int usb_trylock_device(struct usb_device *udev){	if (!down_read_trylock(&usb_all_devices_rwsem))		return 0;	if (down_trylock(&udev->serialize)) {		up_read(&usb_all_devices_rwsem);		return 0;	}	return 1;}/** * usb_lock_device_for_reset - cautiously acquire the lock for a *	usb device structure * @udev: device that's being locked * @iface: interface bound to the driver making the request (optional) * * Attempts to acquire the device lock, but fails if the device is * NOTATTACHED or SUSPENDED, or if iface is specified and the interface * is neither BINDING nor BOUND.  Rather than sleeping to wait for the * lock, the routine polls repeatedly.  This is to prevent deadlock with * disconnect; in some drivers (such as usb-storage) the disconnect() * callback will block waiting for a device reset to complete. * * Returns a negative error code for failure, otherwise 1 or 0 to indicate * that the device will or will not have to be unlocked.  (0 can be * returned when an interface is given and is BINDING, because in that * case the driver already owns the device lock.) */int usb_lock_device_for_reset(struct usb_device *udev,		struct usb_interface *iface){	if (udev->state == USB_STATE_NOTATTACHED)		return -ENODEV;	if (udev->state == USB_STATE_SUSPENDED)		return -EHOSTUNREACH;	if (iface) {		switch (iface->condition) {		  case USB_INTERFACE_BINDING:			return 0;		  case USB_INTERFACE_BOUND:			break;		  default:			return -EINTR;		}	}	while (!usb_trylock_device(udev)) {		msleep(15);		if (udev->state == USB_STATE_NOTATTACHED)			return -ENODEV;		if (udev->state == USB_STATE_SUSPENDED)			return -EHOSTUNREACH;		if (iface && iface->condition != USB_INTERFACE_BOUND)			return -EINTR;	}	return 1;}/** * usb_unlock_device - release the lock for a usb device structure * @udev: device that's being unlocked * * Use this routine when releasing the only device lock you hold; * to release inner nested locks call up(&udev->serialize) directly. * This is necessary for proper interaction with usb_lock_all_devices(). */void usb_unlock_device(struct usb_device *udev){	up(&udev->serialize);	up_read(&usb_all_devices_rwsem);}/** * usb_lock_all_devices - acquire the lock for all usb device structures * * This is necessary when registering a new driver or probing a bus, * since the driver-model core may try to use any usb_device. */void usb_lock_all_devices(void){	down_write(&usb_all_devices_rwsem);}/** * usb_unlock_all_devices - release the lock for all usb device structures */void usb_unlock_all_devices(void){	up_write(&usb_all_devices_rwsem);}static struct usb_device *match_device(struct usb_device *dev,				       u16 vendor_id, u16 product_id){	struct usb_device *ret_dev = NULL;	int child;	dev_dbg(&dev->dev, "check for vendor %04x, product %04x ...\n",	    le16_to_cpu(dev->descriptor.idVendor),	    le16_to_cpu(dev->descriptor.idProduct));	/* see if this device matches */	if ((vendor_id == le16_to_cpu(dev->descriptor.idVendor)) &&	    (product_id == le16_to_cpu(dev->descriptor.idProduct))) {		dev_dbg (&dev->dev, "matched this device!\n");		ret_dev = usb_get_dev(dev);		goto exit;	}	/* look through all of the children of this device */	for (child = 0; child < dev->maxchild; ++child) {		if (dev->children[child]) {			down(&dev->children[child]->serialize);			ret_dev = match_device(dev->children[child],					       vendor_id, product_id);			up(&dev->children[child]->serialize);			if (ret_dev)				goto exit;		}	}exit:	return ret_dev;}/** * usb_find_device - find a specific usb device in the system * @vendor_id: the vendor id of the device to find * @product_id: the product id of the device to find * * Returns a pointer to a struct usb_device if such a specified usb * device is present in the system currently.  The usage count of the * device will be incremented if a device is found.  Make sure to call * usb_put_dev() when the caller is finished with the device. * * If a device with the specified vendor and product id is not found, * NULL is returned. */struct usb_device *usb_find_device(u16 vendor_id, u16 product_id){	struct list_head *buslist;	struct usb_bus *bus;	struct usb_device *dev = NULL;		down(&usb_bus_list_lock);	for (buslist = usb_bus_list.next;	     buslist != &usb_bus_list; 	     buslist = buslist->next) {		bus = container_of(buslist, struct usb_bus, bus_list);		if (!bus->root_hub)			continue;		usb_lock_device(bus->root_hub);		dev = match_device(bus->root_hub, vendor_id, product_id);		usb_unlock_device(bus->root_hub);		if (dev)			goto exit;	}exit:	up(&usb_bus_list_lock);	return dev;}/** * usb_get_current_frame_number - return current bus frame number * @dev: the device whose bus is being queried * * Returns the current frame number for the USB host controller

⌨️ 快捷键说明

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