message.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 1,673 行 · 第 1/4 页

C
1,673
字号
 * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) * @dev: the device whose device descriptor is being updated * @size: how much of the descriptor to read * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, * which dedicates space for this purpose. * * Not exported, only for use by the core.  If drivers really want to read * the device descriptor directly, they can call usb_get_descriptor() with * type = USB_DT_DEVICE and index = 0. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */int usb_get_device_descriptor(struct usb_device *dev, unsigned int size){	struct usb_device_descriptor *desc;	int ret;	if (size > sizeof(*desc))		return -EINVAL;	desc = kmalloc(sizeof(*desc), GFP_NOIO);	if (!desc)		return -ENOMEM;	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);	if (ret >= 0) 		memcpy(&dev->descriptor, desc, size);	kfree(desc);	return ret;}/** * usb_get_status - issues a GET_STATUS call * @dev: the device whose status is being checked * @type: USB_RECIP_*; for device, interface, or endpoint * @target: zero (for device), else interface or endpoint number * @data: pointer to two bytes of bitmap data * Context: !in_interrupt () * * Returns device, interface, or endpoint status.  Normally only of * interest to see if the device is self powered, or has enabled the * remote wakeup facility; or whether a bulk or interrupt endpoint * is halted ("stalled"). * * Bits in these status bitmaps are set using the SET_FEATURE request, * and cleared using the CLEAR_FEATURE request.  The usb_clear_halt() * function should be used to clear halt ("stall") status. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */int usb_get_status(struct usb_device *dev, int type, int target, void *data){	int ret;	u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);	if (!status)		return -ENOMEM;	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,		sizeof(*status), USB_CTRL_GET_TIMEOUT);	*(u16 *)data = *status;	kfree(status);	return ret;}/** * usb_clear_halt - tells device to clear endpoint halt/stall condition * @dev: device whose endpoint is halted * @pipe: endpoint "pipe" being cleared * Context: !in_interrupt () * * This is used to clear halt conditions for bulk and interrupt endpoints, * as reported by URB completion status.  Endpoints that are halted are * sometimes referred to as being "stalled".  Such endpoints are unable * to transmit or receive data until the halt status is cleared.  Any URBs * queued for such an endpoint should normally be unlinked by the driver * before clearing the halt condition, as described in sections 5.7.5 * and 5.8.5 of the USB 2.0 spec. * * Note that control and isochronous endpoints don't halt, although control * endpoints report "protocol stall" (for unsupported requests) using the * same status code used to report a true stall. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */int usb_clear_halt(struct usb_device *dev, int pipe){	int result;	int endp = usb_pipeendpoint(pipe);		if (usb_pipein (pipe))		endp |= USB_DIR_IN;	/* we don't care if it wasn't halted first. in fact some devices	 * (like some ibmcam model 1 units) seem to expect hosts to make	 * this request for iso endpoints, which can't halt!	 */	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,		USB_ENDPOINT_HALT, endp, NULL, 0,		USB_CTRL_SET_TIMEOUT);	/* don't un-halt or force to DATA0 except on success */	if (result < 0)		return result;	/* NOTE:  seems like Microsoft and Apple don't bother verifying	 * the clear "took", so some devices could lock up if you check...	 * such as the Hagiwara FlashGate DUAL.  So we won't bother.	 *	 * NOTE:  make sure the logic here doesn't diverge much from	 * the copy in usb-storage, for as long as we need two copies.	 */	/* toggle was reset by the clear */	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);	return 0;}/** * usb_disable_endpoint -- Disable an endpoint by address * @dev: the device whose endpoint is being disabled * @epaddr: the endpoint's address.  Endpoint number for output, *	endpoint number + USB_DIR_IN for input * * Deallocates hcd/hardware state for this endpoint ... and nukes all * pending urbs. * * If the HCD hasn't registered a disable() function, this sets the * endpoint's maxpacket size to 0 to prevent further submissions. */void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr){	unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;	struct usb_host_endpoint *ep;	if (!dev)		return;	if (usb_endpoint_out(epaddr)) {		ep = dev->ep_out[epnum];		dev->ep_out[epnum] = NULL;	} else {		ep = dev->ep_in[epnum];		dev->ep_in[epnum] = NULL;	}	if (ep && dev->bus)		usb_hcd_endpoint_disable(dev, ep);}/** * usb_disable_interface -- Disable all endpoints for an interface * @dev: the device whose interface is being disabled * @intf: pointer to the interface descriptor * * Disables all the endpoints for the interface's current altsetting. */void usb_disable_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_disable_endpoint(dev,				alt->endpoint[i].desc.bEndpointAddress);	}}/* * usb_disable_device - Disable all the endpoints for a USB device * @dev: the device whose endpoints are being disabled * @skip_ep0: 0 to disable endpoint 0, 1 to skip it. * * Disables all the device's endpoints, potentially including endpoint 0. * Deallocates hcd/hardware state for the endpoints (nuking all or most * pending urbs) and usbcore state for the interfaces, so that usbcore * must usb_set_configuration() before any interfaces could be used. */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 if it has been registered */			interface = dev->actconfig->interface[i];			if (!device_is_registered(&interface->dev))				continue;			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. */static 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, 5000);	/* 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 */	if (device_is_registered(&iface->dev))		usb_remove_sysfs_intf_files(iface);	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);	if (device_is_registered(&iface->dev))		usb_create_sysfs_intf_files(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.  Be careful though; * some devices don't support the SET_INTERFACE request, and others won't * reset all the interface state (notably data toggles).  Resetting the whole * configuration would affect other drivers' interfaces. * * The caller must own the device lock. *

⌨️ 快捷键说明

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