📄 message.c
字号:
dev_err (&dev->dev, "string descriptor 0 too short\n"); err = -EINVAL; goto errout; } else { dev->have_langid = -1; dev->string_langid = tbuf[2] | (tbuf[3]<< 8); /* always use the first langid listed */ dev_dbg (&dev->dev, "default language 0x%04x\n", dev->string_langid); } } err = usb_string_sub(dev, dev->string_langid, index, tbuf); if (err < 0) goto errout; size--; /* leave room for trailing NULL char in output buffer */ for (idx = 0, u = 2; u < err; u += 2) { if (idx >= size) break; if (tbuf[u+1]) /* high byte */ buf[idx++] = '?'; /* non ISO-8859-1 character */ else buf[idx++] = tbuf[u]; } buf[idx] = 0; err = idx; if (tbuf[1] != USB_DT_STRING) dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf); errout: kfree(tbuf); return err;}/** * usb_cache_string - read a string descriptor and cache it for later use * @udev: the device whose string descriptor is being read * @index: the descriptor index * * Returns a pointer to a kmalloc'ed buffer containing the descriptor string, * or NULL if the index is 0 or the string could not be read. */char *usb_cache_string(struct usb_device *udev, int index){ char *buf; char *smallbuf = NULL; int len; if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) { if ((len = usb_string(udev, index, buf, 256)) > 0) { if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL) return buf; memcpy(smallbuf, buf, len); } kfree(buf); } return smallbuf;}/* * 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. Note that several fields are * converted to the host CPU's byte order: the USB version (bcdUSB), and * vendors product and version fields (idVendor, idProduct, and bcdDevice). * That lets device drivers compare against non-byteswapped constants. * * 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 && dev->bus->op && dev->bus->op->disable) dev->bus->op->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). *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -