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

📄 message.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
void usb_disable_device(struct usb_device *dev, int skip_ep0){	int i;	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,			skip_ep0 ? "non-ep0" : "all");	for (i = skip_ep0; i < 16; ++i) {		usb_disable_endpoint(dev, i);		usb_disable_endpoint(dev, i + USB_DIR_IN);	}	dev->toggle[0] = dev->toggle[1] = 0;	/* getting rid of interfaces will disconnect	 * any drivers bound to them (a key side effect)	 */	if (dev->actconfig) {		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {			struct usb_interface	*interface;			/* remove this interface */			interface = dev->actconfig->interface[i];			dev_dbg (&dev->dev, "unregistering interface %s\n",				interface->dev.bus_id);			usb_remove_sysfs_intf_files(interface);			device_del (&interface->dev);		}		/* Now that the interfaces are unbound, nobody should		 * try to access them.		 */		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {			put_device (&dev->actconfig->interface[i]->dev);			dev->actconfig->interface[i] = NULL;		}		dev->actconfig = NULL;		if (dev->state == USB_STATE_CONFIGURED)			usb_set_device_state(dev, USB_STATE_ADDRESS);	}}/* * usb_enable_endpoint - Enable an endpoint for USB communications * @dev: the device whose interface is being enabled * @ep: the endpoint * * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers. * For control endpoints, both the input and output sides are handled. */static voidusb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep){	unsigned int epaddr = ep->desc.bEndpointAddress;	unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;	int is_control;	is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)			== USB_ENDPOINT_XFER_CONTROL);	if (usb_endpoint_out(epaddr) || is_control) {		usb_settoggle(dev, epnum, 1, 0);		dev->ep_out[epnum] = ep;	}	if (!usb_endpoint_out(epaddr) || is_control) {		usb_settoggle(dev, epnum, 0, 0);		dev->ep_in[epnum] = ep;	}}/* * usb_enable_interface - Enable all the endpoints for an interface * @dev: the device whose interface is being enabled * @intf: pointer to the interface descriptor * * Enables all the endpoints for the interface's current altsetting. */void usb_enable_interface(struct usb_device *dev,		struct usb_interface *intf){	struct usb_host_interface *alt = intf->cur_altsetting;	int i;	for (i = 0; i < alt->desc.bNumEndpoints; ++i)		usb_enable_endpoint(dev, &alt->endpoint[i]);}/** * usb_set_interface - Makes a particular alternate setting be current * @dev: the device whose interface is being updated * @interface: the interface being updated * @alternate: the setting being chosen. * Context: !in_interrupt () * * This is used to enable data transfers on interfaces that may not * be enabled by default.  Not all devices support such configurability. * Only the driver bound to an interface may change its setting. * * Within any given configuration, each interface may have several * alternative settings.  These are often used to control levels of * bandwidth consumption.  For example, the default setting for a high * speed interrupt endpoint may not send more than 64 bytes per microframe, * while interrupt transfers of up to 3KBytes per microframe are legal. * Also, isochronous endpoints may never be part of an * interface's default setting.  To access such bandwidth, alternate * interface settings must be made current. * * Note that in the Linux USB subsystem, bandwidth associated with * an endpoint in a given alternate setting is not reserved until an URB * is submitted that needs that bandwidth.  Some other operating systems * allocate bandwidth early, when a configuration is chosen. * * This call is synchronous, and may not be used in an interrupt context. * Also, drivers must not change altsettings while urbs are scheduled for * endpoints in that interface; all such urbs must first be completed * (perhaps forced by unlinking). * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */int usb_set_interface(struct usb_device *dev, int interface, int alternate){	struct usb_interface *iface;	struct usb_host_interface *alt;	int ret;	int manual = 0;	if (dev->state == USB_STATE_SUSPENDED)		return -EHOSTUNREACH;	iface = usb_ifnum_to_if(dev, interface);	if (!iface) {		dev_dbg(&dev->dev, "selecting invalid interface %d\n",			interface);		return -EINVAL;	}	alt = usb_altnum_to_altsetting(iface, alternate);	if (!alt) {		warn("selecting invalid altsetting %d", alternate);		return -EINVAL;	}	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),				   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,				   alternate, interface, NULL, 0, HZ * 5);	/* 9.4.10 says devices don't need this and are free to STALL the	 * request if the interface only has one alternate setting.	 */	if (ret == -EPIPE && iface->num_altsetting == 1) {		dev_dbg(&dev->dev,			"manual set_interface for iface %d, alt %d\n",			interface, alternate);		manual = 1;	} else if (ret < 0)		return ret;	/* FIXME drivers shouldn't need to replicate/bugfix the logic here	 * when they implement async or easily-killable versions of this or	 * other "should-be-internal" functions (like clear_halt).	 * should hcd+usbcore postprocess control requests?	 */	/* prevent submissions using previous endpoint settings */	usb_disable_interface(dev, iface);	iface->cur_altsetting = alt;	/* If the interface only has one altsetting and the device didn't	 * accept the request, we attempt to carry out the equivalent action	 * by manually clearing the HALT feature for each endpoint in the	 * new altsetting.	 */	if (manual) {		int i;		for (i = 0; i < alt->desc.bNumEndpoints; i++) {			unsigned int epaddr =				alt->endpoint[i].desc.bEndpointAddress;			unsigned int pipe =	__create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)	| (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);			usb_clear_halt(dev, pipe);		}	}	/* 9.1.1.5: reset toggles for all endpoints in the new altsetting	 *	 * Note:	 * Despite EP0 is always present in all interfaces/AS, the list of	 * endpoints from the descriptor does not contain EP0. Due to its	 * omnipresence one might expect EP0 being considered "affected" by	 * any SetInterface request and hence assume toggles need to be reset.	 * However, EP0 toggles are re-synced for every individual transfer	 * during the SETUP stage - hence EP0 toggles are "don't care" here.	 * (Likewise, EP0 never "halts" on well designed devices.)	 */	usb_enable_interface(dev, iface);	return 0;}/** * usb_reset_configuration - lightweight device reset * @dev: the device whose configuration is being reset * * This issues a standard SET_CONFIGURATION request to the device using * the current configuration.  The effect is to reset most USB-related * state in the device, including interface altsettings (reset to zero), * endpoint halts (cleared), and data toggle (only for bulk and interrupt * endpoints).  Other usbcore state is unchanged, including bindings of * usb device drivers to interfaces. * * Because this affects multiple interfaces, avoid using this with composite * (multi-interface) devices.  Instead, the driver for each interface may * use usb_set_interface() on the interfaces it claims.  Resetting the whole * configuration would affect other drivers' interfaces. * * The caller must own the device lock. * * Returns zero on success, else a negative error code. */int usb_reset_configuration(struct usb_device *dev){	int			i, retval;	struct usb_host_config	*config;	if (dev->state == USB_STATE_SUSPENDED)		return -EHOSTUNREACH;	/* caller must have locked the device and must own	 * the usb bus readlock (so driver bindings are stable);	 * calls during probe() are fine	 */	for (i = 1; i < 16; ++i) {		usb_disable_endpoint(dev, i);		usb_disable_endpoint(dev, i + USB_DIR_IN);	}	config = dev->actconfig;	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),			USB_REQ_SET_CONFIGURATION, 0,			config->desc.bConfigurationValue, 0,			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);	if (retval < 0) {		usb_set_device_state(dev, USB_STATE_ADDRESS);		return retval;	}	dev->toggle[0] = dev->toggle[1] = 0;	/* re-init hc/hcd interface/endpoint state */	for (i = 0; i < config->desc.bNumInterfaces; i++) {		struct usb_interface *intf = config->interface[i];		struct usb_host_interface *alt;		alt = usb_altnum_to_altsetting(intf, 0);		/* No altsetting 0?  We'll assume the first altsetting.		 * We could use a GetInterface call, but if a device is		 * so non-compliant that it doesn't have altsetting 0		 * then I wouldn't trust its reply anyway.		 */		if (!alt)			alt = &intf->altsetting[0];		intf->cur_altsetting = alt;		usb_enable_interface(dev, intf);	}	return 0;}static void release_interface(struct device *dev){	struct usb_interface *intf = to_usb_interface(dev);	struct usb_interface_cache *intfc =			altsetting_to_usb_interface_cache(intf->altsetting);	kref_put(&intfc->ref, usb_release_interface_cache);	kfree(intf);}/* * usb_set_configuration - Makes a particular device setting be current * @dev: the device whose configuration is being updated * @configuration: the configuration being chosen. * Context: !in_interrupt(), caller owns the device lock * * This is used to enable non-default device modes.  Not all devices * use this kind of configurability; many devices only have one * configuration. * * USB device configurations may affect Linux interoperability, * power consumption and the functionality available.  For example, * the default configuration is limited to using 100mA of bus power, * so that when certain device functionality requires more power, * and the device is bus powered, that functionality should be in some * non-default device configuration.  Other device modes may also be * reflected as configuration options, such as whether two ISDN * channels are available independently; and choosing between open * standard device protocols (like CDC) or proprietary ones. * * Note that USB has an additional level of device configurability, * associated with interfaces.  That configurability is accessed using * usb_set_interface(). * * This call is synchronous. The calling context must be able to sleep, * must own the device lock, and must not hold the driver model's USB * bus rwsem; usb device driver probe() methods cannot use this routine. * * Returns zero on success, or else the status code returned by the * underlying call that failed.  On succesful completion, each interface * in the original device configuration has been destroyed, and each one * in the new configuration has been probed by all relevant usb device * drivers currently known to the kernel. */int usb_set_configuration(struct usb_device *dev, int configuration){	int i, ret;	struct usb_host_config *cp = NULL;	struct usb_interface **new_interfaces = NULL;	int n, nintf;	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {		if (dev->config[i].desc.bConfigurationValue == configuration) {			cp = &dev->config[i];			break;		}	}	if ((!cp && configuration != 0))		return -EINVAL;	/* The USB spec says configuration 0 means unconfigured.	 * But if a device includes a configuration numbered 0,	 * we will accept it as a correctly configured state.	 */	if (cp && configuration == 0)		dev_warn(&dev->dev, "config 0 descriptor??\n");	if (dev->state == USB_STATE_SUSPENDED)		return -EHOSTUNREACH;	/* Allocate memory for new interfaces before doing anything else,	 * so that if we run out then nothing will have changed. */	n = nintf = 0;	if (cp) {		nintf = cp->desc.bNumInterfaces;		new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),				GFP_KERNEL);		if (!new_interfaces) {			dev_err(&dev->dev, "Out of memory");			return -ENOMEM;		}		for (; n < nintf; ++n) {			new_interfaces[n] = kmalloc(					sizeof(struct usb_interface),					GFP_KERNEL);			if (!new_interfaces[n]) {				dev_err(&dev->dev, "Out of memory");				ret = -ENOMEM;free_interfaces:				while (--n >= 0)					kfree(new_interfaces[n]);				kfree(new_interfaces);				return ret;			}		}	}	/* if it's already configured, clear out old state first.	 * getting rid of old interfaces means unbinding their drivers.	 */	if (dev->state != USB_STATE_ADDRESS)		usb_disable_device (dev, 1);	// Skip ep0	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)		goto free_interfaces;	dev->actconfig = cp;	if (!cp)		usb_set_device_state(dev, USB_STATE_ADDRESS);	else {		usb_set_device_state(dev, USB_STATE_CONFIGURED);		/* Initialize the new interface structures and the		 * hc/hcd/usbcore interface/endpoint state.		 */		for (i = 0; i < nintf; ++i) {			struct usb_interface_cache *intfc;			struct usb_interface *intf;			struct usb_host_interface *alt;			cp->interface[i] = intf = new_interfaces[i];			memset(intf, 0, sizeof(*intf));			intfc = cp->intf_cache[i];			intf->altsetting = intfc->altsetting;			intf->num_altsetting = intfc->num_altsetting;			kref_get(&intfc->ref);			alt = usb_altnum_to_altsetting(intf, 0);			/* No altsetting 0?  We'll assume the first altsetting.			 * We could use a GetInterface call, but if a device is			 * so non-compliant that it doesn't have altsetting 0			 * then I wouldn't trust its reply anyway.			 */			if (!alt)				alt = &intf->altsetting[0];			intf->cur_altsetting = alt;			usb_enable_interface(dev, intf);			intf->dev.parent = &dev->dev;			intf->dev.driver = NULL;			intf->dev.bus = &usb_bus_type;			intf->dev.dma_mask = dev->dev.dma_mask;			intf->dev.release = release_interface;			device_initialize (&intf->dev);			sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",				 dev->bus->busnum, dev->devpath,				 configuration,				 alt->desc.bInterfaceNumber);		}		kfree(new_interfaces);		/* Now that all the interfaces are set up, register them		 * to trigger binding of drivers to interfaces.  probe()		 * routines may install different altsettings and may		 * claim() any interfaces not yet bound.  Many class drivers		 * need that: CDC, audio, video, etc.		 */		for (i = 0; i < nintf; ++i) {			struct usb_interface *intf = cp->interface[i];			struct usb_interface_descriptor *desc;			desc = &intf->altsetting [0].desc;			dev_dbg (&dev->dev,				"adding %s (config #%d, interface %d)\n",				intf->dev.bus_id, configuration,				desc->bInterfaceNumber);			ret = device_add (&intf->dev);			if (ret != 0) {				dev_err(&dev->dev,					"device_add(%s) --> %d\n",					intf->dev.bus_id,					ret);				continue;			}			usb_create_sysfs_intf_files (intf);		}	}	return ret;}// synchronous request completion modelEXPORT_SYMBOL(usb_control_msg);EXPORT_SYMBOL(usb_bulk_msg);EXPORT_SYMBOL(usb_sg_init);EXPORT_SYMBOL(usb_sg_cancel);EXPORT_SYMBOL(usb_sg_wait);// synchronous control message convenience routinesEXPORT_SYMBOL(usb_get_descriptor);EXPORT_SYMBOL(usb_get_status);EXPORT_SYMBOL(usb_get_string);EXPORT_SYMBOL(usb_string);// synchronous calls that also maintain usbcore stateEXPORT_SYMBOL(usb_clear_halt);EXPORT_SYMBOL(usb_reset_configuration);EXPORT_SYMBOL(usb_set_interface);

⌨️ 快捷键说明

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