summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-05-31 04:25:49 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-05-31 04:25:49 -0700
commitc2a84d00f6dbb6c8edcc2bc0a92d5e4329773f33 (patch)
tree3f286f1ce745c95273bdaa179ca2da4a34f64b13
parent6188af0c4286035029c80147c066a91151b35a0b (diff)
parent27f4974232b20d4f0192bce7a159c7d95161b68e (diff)
Merge bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--Documentation/DocBook/Makefile3
-rw-r--r--Documentation/DocBook/kernel-api.tmpl3
-rw-r--r--drivers/usb/core/Makefile5
-rw-r--r--drivers/usb/core/config.c494
-rw-r--r--drivers/usb/core/message.c661
-rw-r--r--drivers/usb/core/urb.c236
-rw-r--r--drivers/usb/core/usb.c1359
-rw-r--r--drivers/usb/host/ehci-q.c2
-rw-r--r--drivers/usb/image/scanner.c23
-rw-r--r--drivers/usb/image/scanner.h10
10 files changed, 1427 insertions, 1369 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 1bcd43c7f08c..442924cf6d22 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -113,6 +113,9 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
$(TOPDIR)/drivers/net/wan/syncppp.c \
$(TOPDIR)/drivers/net/wan/z85230.c \
$(TOPDIR)/drivers/usb/core/hcd.c \
+ $(TOPDIR)/drivers/usb/core/urb.c \
+ $(TOPDIR)/drivers/usb/core/message.c \
+ $(TOPDIR)/drivers/usb/core/config.c \
$(TOPDIR)/drivers/usb/core/usb.c \
$(TOPDIR)/drivers/video/fbmem.c \
$(TOPDIR)/drivers/video/fbcmap.c \
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 2e783c8b00ed..52094d07bc19 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -282,6 +282,9 @@
</sect1>
<sect1><title>USB Core APIs</title>
+!Edrivers/usb/core/urb.c
+!Edrivers/usb/core/config.c
+!Edrivers/usb/core/message.c
!Edrivers/usb/core/usb.c
</sect1>
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 3b5293b9bba9..1648f8598b08 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -2,9 +2,10 @@
# Makefile for USB Core files and filesystem
#
-export-objs := usb.o hcd.o
+export-objs := usb.o hcd.o urb.o message.o config.o
-usbcore-objs := usb.o usb-debug.o hub.o hcd.o
+usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
+ config.o
ifeq ($(CONFIG_USB_DEVICEFS),y)
usbcore-objs += devio.o inode.o drivers.o devices.o
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
new file mode 100644
index 000000000000..2598edc8d9c1
--- /dev/null
+++ b/drivers/usb/core/config.c
@@ -0,0 +1,494 @@
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
+{
+ struct usb_descriptor_header *header;
+ unsigned char *begin;
+ int parsed = 0, len, numskipped;
+
+ header = (struct usb_descriptor_header *)buffer;
+
+ /* Everything should be fine being passed into here, but we sanity */
+ /* check JIC */
+ if (header->bLength > size) {
+ err("ran out of descriptors parsing");
+ return -1;
+ }
+
+ if (header->bDescriptorType != USB_DT_ENDPOINT) {
+ warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
+ endpoint->bDescriptorType, USB_DT_ENDPOINT);
+ return parsed;
+ }
+
+ if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
+ memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
+ else
+ memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
+
+ le16_to_cpus(&endpoint->wMaxPacketSize);
+
+ buffer += header->bLength;
+ size -= header->bLength;
+ parsed += header->bLength;
+
+ /* Skip over the rest of the Class Specific or Vendor Specific */
+ /* descriptors */
+ begin = buffer;
+ numskipped = 0;
+ while (size >= sizeof(struct usb_descriptor_header)) {
+ header = (struct usb_descriptor_header *)buffer;
+
+ if (header->bLength < 2) {
+ err("invalid descriptor length of %d", header->bLength);
+ return -1;
+ }
+
+ /* If we find another "proper" descriptor then we're done */
+ if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
+ (header->bDescriptorType == USB_DT_INTERFACE) ||
+ (header->bDescriptorType == USB_DT_CONFIG) ||
+ (header->bDescriptorType == USB_DT_DEVICE))
+ break;
+
+ dbg("skipping descriptor 0x%X",
+ header->bDescriptorType);
+ numskipped++;
+
+ buffer += header->bLength;
+ size -= header->bLength;
+ parsed += header->bLength;
+ }
+ if (numskipped)
+ dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
+
+ /* Copy any unknown descriptors into a storage area for drivers */
+ /* to later parse */
+ len = (int)(buffer - begin);
+ if (!len) {
+ endpoint->extra = NULL;
+ endpoint->extralen = 0;
+ return parsed;
+ }
+
+ endpoint->extra = kmalloc(len, GFP_KERNEL);
+
+ if (!endpoint->extra) {
+ err("couldn't allocate memory for endpoint extra descriptors");
+ endpoint->extralen = 0;
+ return parsed;
+ }
+
+ memcpy(endpoint->extra, begin, len);
+ endpoint->extralen = len;
+
+ return parsed;
+}
+
+static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
+{
+ int i, len, numskipped, retval, parsed = 0;
+ struct usb_descriptor_header *header;
+ struct usb_interface_descriptor *ifp;
+ unsigned char *begin;
+
+ interface->act_altsetting = 0;
+ interface->num_altsetting = 0;
+ interface->max_altsetting = USB_ALTSETTINGALLOC;
+
+ interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
+
+ if (!interface->altsetting) {
+ err("couldn't kmalloc interface->altsetting");
+ return -1;
+ }
+
+ while (size > 0) {
+ if (interface->num_altsetting >= interface->max_altsetting) {
+ void *ptr;
+ int oldmas;
+
+ oldmas = interface->max_altsetting;
+ interface->max_altsetting += USB_ALTSETTINGALLOC;
+ if (interface->max_altsetting > USB_MAXALTSETTING) {
+ warn("too many alternate settings (max %d)",
+ USB_MAXALTSETTING);
+ return -1;
+ }
+
+ ptr = interface->altsetting;
+ interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
+ if (!interface->altsetting) {
+ err("couldn't kmalloc interface->altsetting");
+ interface->altsetting = ptr;
+ return -1;
+ }
+ memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas);
+
+ kfree(ptr);
+ }
+
+ ifp = interface->altsetting + interface->num_altsetting;
+ ifp->endpoint = NULL;
+ ifp->extra = NULL;
+ ifp->extralen = 0;
+ interface->num_altsetting++;
+
+ memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
+
+ /* Skip over the interface */
+ buffer += ifp->bLength;
+ parsed += ifp->bLength;
+ size -= ifp->bLength;
+
+ begin = buffer;
+ numskipped = 0;
+
+ /* Skip over any interface, class or vendor descriptors */
+ while (size >= sizeof(struct usb_descriptor_header)) {
+ header = (struct usb_descriptor_header *)buffer;
+
+ if (header->bLength < 2) {
+ err("invalid descriptor length of %d", header->bLength);
+ return -1;
+ }
+
+ /* If we find another "proper" descriptor then we're done */
+ if ((header->bDescriptorType == USB_DT_INTERFACE) ||
+ (header->bDescriptorType == USB_DT_ENDPOINT) ||
+ (header->bDescriptorType == USB_DT_CONFIG) ||
+ (header->bDescriptorType == USB_DT_DEVICE))
+ break;
+
+ numskipped++;
+
+ buffer += header->bLength;
+ parsed += header->bLength;
+ size -= header->bLength;
+ }
+
+ if (numskipped)
+ dbg("skipped %d class/vendor specific interface descriptors", numskipped);
+
+ /* Copy any unknown descriptors into a storage area for */
+ /* drivers to later parse */
+ len = (int)(buffer - begin);
+ if (len) {
+ ifp->extra = kmalloc(len, GFP_KERNEL);
+
+ if (!ifp->extra) {
+ err("couldn't allocate memory for interface extra descriptors");
+ ifp->extralen = 0;
+ return -1;
+ }
+ memcpy(ifp->extra, begin, len);
+ ifp->extralen = len;
+ }
+
+ /* Did we hit an unexpected descriptor? */
+ header = (struct usb_descriptor_header *)buffer;
+ if ((size >= sizeof(struct usb_descriptor_header)) &&
+ ((header->bDescriptorType == USB_DT_CONFIG) ||
+ (header->bDescriptorType == USB_DT_DEVICE)))
+ return parsed;
+
+ if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
+ warn("too many endpoints");
+ return -1;
+ }
+
+ ifp->endpoint = (struct usb_endpoint_descriptor *)
+ kmalloc(ifp->bNumEndpoints *
+ sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
+ if (!ifp->endpoint) {
+ err("out of memory");
+ return -1;
+ }
+
+ memset(ifp->endpoint, 0, ifp->bNumEndpoints *
+ sizeof(struct usb_endpoint_descriptor));
+
+ for (i = 0; i < ifp->bNumEndpoints; i++) {
+ header = (struct usb_descriptor_header *)buffer;
+
+ if (header->bLength > size) {
+ err("ran out of descriptors parsing");
+ return -1;
+ }
+
+ retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
+ if (retval < 0)
+ return retval;
+
+ buffer += retval;
+ parsed += retval;
+ size -= retval;
+ }
+
+ /* We check to see if it's an alternate to this one */
+ ifp = (struct usb_interface_descriptor *)buffer;
+ if (size < USB_DT_INTERFACE_SIZE ||
+ ifp->bDescriptorType != USB_DT_INTERFACE ||
+ !ifp->bAlternateSetting)
+ return parsed;
+ }
+
+ return parsed;
+}
+
+int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
+{
+ int i, retval, size;
+ struct usb_descriptor_header *header;
+
+ memcpy(config, buffer, USB_DT_CONFIG_SIZE);
+ le16_to_cpus(&config->wTotalLength);
+ size = config->wTotalLength;
+
+ if (config->bNumInterfaces > USB_MAXINTERFACES) {
+ warn("too many interfaces");
+ return -1;
+ }
+
+ config->interface = (struct usb_interface *)
+ kmalloc(config->bNumInterfaces *
+ sizeof(struct usb_interface), GFP_KERNEL);
+ dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces);
+ if (!config->interface) {
+ err("out of memory");
+ return -1;
+ }
+
+ memset(config->interface, 0,
+ config->bNumInterfaces * sizeof(struct usb_interface));
+
+ buffer += config->bLength;
+ size -= config->bLength;
+
+ config->extra = NULL;
+ config->extralen = 0;
+
+ for (i = 0; i < config->bNumInterfaces; i++) {
+ int numskipped, len;
+ char *begin;
+
+ /* Skip over the rest of the Class Specific or Vendor */
+ /* Specific descriptors */
+ begin = buffer;
+ numskipped = 0;
+ while (size >= sizeof(struct usb_descriptor_header)) {
+ header = (struct usb_descriptor_header *)buffer;
+
+ if ((header->bLength > size) || (header->bLength < 2)) {
+ err("invalid descriptor length of %d", header->bLength);
+ return -1;
+ }
+
+ /* If we find another "proper" descriptor then we're done */
+ if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
+ (header->bDescriptorType == USB_DT_INTERFACE) ||
+ (header->bDescriptorType == USB_DT_CONFIG) ||
+ (header->bDescriptorType == USB_DT_DEVICE))
+ break;
+
+ dbg("skipping descriptor 0x%X", header->bDescriptorType);
+ numskipped++;
+
+ buffer += header->bLength;
+ size -= header->bLength;
+ }
+ if (numskipped)
+ dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
+
+ /* Copy any unknown descriptors into a storage area for */
+ /* drivers to later parse */
+ len = (int)(buffer - begin);
+ if (len) {
+ if (config->extralen) {
+ warn("extra config descriptor");
+ } else {
+ config->extra = kmalloc(len, GFP_KERNEL);
+ if (!config->extra) {
+ err("couldn't allocate memory for config extra descriptors");
+ config->extralen = 0;
+ return -1;
+ }
+
+ memcpy(config->extra, begin, len);
+ config->extralen = len;
+ }
+ }
+
+ retval = usb_parse_interface(config->interface + i, buffer, size);
+ if (retval < 0)
+ return retval;
+
+ buffer += retval;
+ size -= retval;
+ }
+
+ return size;
+}
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally on disconnect/destroy path
+void usb_destroy_configuration(struct usb_device *dev)
+{
+ int c, i, j, k;
+
+ if (!dev->config)
+ return;
+
+ if (dev->rawdescriptors) {
+ for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
+ kfree(dev->rawdescriptors[i]);
+
+ kfree(dev->rawdescriptors);
+ }
+
+ for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
+ struct usb_config_descriptor *cf = &dev->config[c];
+
+ if (!cf->interface)
+ break;
+
+ for (i = 0; i < cf->bNumInterfaces; i++) {
+ struct usb_interface *ifp =
+ &cf->interface[i];
+
+ if (!ifp->altsetting)
+ break;
+
+ for (j = 0; j < ifp->num_altsetting; j++) {
+ struct usb_interface_descriptor *as =
+ &ifp->altsetting[j];
+
+ if(as->extra) {
+ kfree(as->extra);
+ }
+
+ if (!as->endpoint)
+ break;
+
+ for(k = 0; k < as->bNumEndpoints; k++) {
+ if(as->endpoint[k].extra) {
+ kfree(as->endpoint[k].extra);
+ }
+ }
+ kfree(as->endpoint);
+ }
+
+ kfree(ifp->altsetting);
+ }
+ kfree(cf->interface);
+ }
+ kfree(dev->config);
+}
+
+
+// hub-only!! ... and only in reset path, or usb_new_device()
+// (used by real hubs and virtual root hubs)
+int usb_get_configuration(struct usb_device *dev)
+{
+ int result;
+ unsigned int cfgno, length;
+ unsigned char *buffer;
+ unsigned char *bigbuffer;
+ struct usb_config_descriptor *desc;
+
+ if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
+ warn("too many configurations");
+ return -EINVAL;
+ }
+
+ if (dev->descriptor.bNumConfigurations < 1) {
+ warn("not enough configurations");
+ return -EINVAL;
+ }
+
+ dev->config = (struct usb_config_descriptor *)
+ kmalloc(dev->descriptor.bNumConfigurations *
+ sizeof(struct usb_config_descriptor), GFP_KERNEL);
+ if (!dev->config) {
+ err("out of memory");
+ return -ENOMEM;
+ }
+ memset(dev->config, 0, dev->descriptor.bNumConfigurations *
+ sizeof(struct usb_config_descriptor));
+
+ dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
+ dev->descriptor.bNumConfigurations, GFP_KERNEL);
+ if (!dev->rawdescriptors) {
+ err("out of memory");
+ return -ENOMEM;
+ }
+
+ buffer = kmalloc(8, GFP_KERNEL);
+ if (!buffer) {
+ err("unable to allocate memory for configuration descriptors");
+ return -ENOMEM;
+ }
+ desc = (struct usb_config_descriptor *)buffer;
+
+ for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
+ /* We grab the first 8 bytes so we know how long the whole */
+ /* configuration is */
+ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
+ if (result < 8) {
+ if (result < 0)
+ err("unable to get descriptor");
+ else {
+ err("config descriptor too short (expected %i, got %i)", 8, result);
+ result = -EINVAL;
+ }
+ goto err;
+ }
+
+ /* Get the full buffer */
+ length = le16_to_cpu(desc->wTotalLength);
+
+ bigbuffer = kmalloc(length, GFP_KERNEL);
+ if (!bigbuffer) {
+ err("unable to allocate memory for configuration descriptors");
+ result = -ENOMEM;
+ goto err;
+ }
+
+ /* Now that we know the length, get the whole thing */
+ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
+ if (result < 0) {
+ err("couldn't get all of config descriptors");
+ kfree(bigbuffer);
+ goto err;
+ }
+
+ if (result < length) {
+ err("config descriptor too short (expected %i, got %i)", length, result);
+ result = -EINVAL;
+ kfree(bigbuffer);
+ goto err;
+ }
+
+ dev->rawdescriptors[cfgno] = bigbuffer;
+
+ result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
+ if (result > 0)
+ dbg("descriptor data left");
+ else if (result < 0) {
+ result = -EINVAL;
+ goto err;
+ }
+ }
+
+ kfree(buffer);
+ return 0;
+err:
+ kfree(buffer);
+ dev->descriptor.bNumConfigurations = cfgno;
+ return result;
+}
+
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
new file mode 100644
index 000000000000..33f9ed3ca50f
--- /dev/null
+++ b/drivers/usb/core/message.c
@@ -0,0 +1,661 @@
+/*
+ * message.c - synchronous message handling
+ */
+
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/byteorder.h>
+
+struct usb_api_data {
+ wait_queue_head_t wqh;
+ int done;
+};
+
+static void usb_api_blocking_completion(struct urb *urb)
+{
+ struct usb_api_data *awd = (struct usb_api_data *)urb->context;
+
+ awd->done = 1;
+ wmb();
+ wake_up(&awd->wqh);
+}
+
+// Starts urb and waits for completion or timeout
+static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct usb_api_data awd;
+ int status;
+
+ init_waitqueue_head(&awd.wqh);
+ awd.done = 0;
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&awd.wqh, &wait);
+
+ urb->context = &awd;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status) {
+ // something went wrong
+ usb_free_urb(urb);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&awd.wqh, &wait);
+ return status;
+ }
+
+ while (timeout && !awd.done)
+ {
+ timeout = schedule_timeout(timeout);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ rmb();
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&awd.wqh, &wait);
+
+ if (!timeout && !awd.done) {
+ if (urb->status != -EINPROGRESS) { /* No callback?!! */
+ printk(KERN_ERR "usb: raced timeout, "
+ "pipe 0x%x status %d time left %d\n",
+ urb->pipe, urb->status, timeout);
+ status = urb->status;
+ } else {
+ printk("usb_control/bulk_msg: timeout\n");
+ usb_unlink_urb(urb); // remove urb safely
+ status = -ETIMEDOUT;
+ }
+ } else
+ status = urb->status;
+
+ if (actual_length)
+ *actual_length = urb->actual_length;
+
+ usb_free_urb(urb);
+ return status;
+}
+
+/*-------------------------------------------------------------------*/
+// returns status (negative) or length (positive)
+int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
+ struct usb_ctrlrequest *cmd, void *data, int len, int timeout)
+{
+ struct urb *urb;
+ int retv;
+ int length;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
+ usb_api_blocking_completion, 0);
+
+ retv = usb_start_wait_urb(urb, timeout, &length);
+ if (retv < 0)
+ return retv;
+ else
+ return length;
+}
+
+/**
+ * usb_control_msg - Builds a control urb, sends it off and waits for completion
+ * @dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @request: USB message request value
+ * @requesttype: USB message request type value
+ * @value: USB message value
+ * @index: USB message index value
+ * @data: pointer to the data to send
+ * @size: length in bytes of the data to send
+ * @timeout: time in jiffies to wait for the message to complete before
+ * timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple control message to a specified endpoint
+ * and waits for the message to complete, or timeout.
+ *
+ * If successful, it returns the number of bytes transferred, otherwise a negative error number.
+ *
+ * Don't use this function from within an interrupt context, like a
+ * bottom half handler. If you need an asynchronous message, or need to send
+ * a message from within interrupt context, use usb_submit_urb()
+ */
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
+ __u16 value, __u16 index, void *data, __u16 size, int timeout)
+{
+ struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ int ret;
+
+ if (!dr)
+ return -ENOMEM;
+
+ dr->bRequestType= requesttype;
+ dr->bRequest = request;
+ dr->wValue = cpu_to_le16p(&value);
+ dr->wIndex = cpu_to_le16p(&index);
+ dr->wLength = cpu_to_le16p(&size);
+
+ //dbg("usb_control_msg");
+
+ ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
+
+ kfree(dr);
+
+ return ret;
+}
+
+
+/**
+ * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @data: pointer to the data to send
+ * @len: length in bytes of the data to send
+ * @actual_length: pointer to a location to put the actual length transferred in bytes
+ * @timeout: time in jiffies to wait for the message to complete before
+ * timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple bulk message to a specified endpoint
+ * and waits for the message to complete, or timeout.
+ *
+ * If successful, it returns 0, otherwise a negative error number.
+ * The number of actual bytes transferred will be stored in the
+ * actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a
+ * bottom half handler. If you need an asynchronous message, or need to
+ * send a message from within interrupt context, use usb_submit_urb()
+ */
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+ void *data, int len, int *actual_length, int timeout)
+{
+ struct urb *urb;
+
+ if (len < 0)
+ return -EINVAL;
+
+ urb=usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ FILL_BULK_URB(urb, usb_dev, pipe, data, len,
+ usb_api_blocking_completion, 0);
+
+ return usb_start_wait_urb(urb,timeout,actual_length);
+}
+
+/**
+ * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
+ * @dev: the device whose descriptor is being retrieved
+ * @type: the descriptor type (USB_DT_*)
+ * @index: the number of the descriptor
+ * @buf: where to put the descriptor
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Gets a USB descriptor. Convenience functions exist to simplify
+ * getting some types of descriptors. Use
+ * usb_get_device_descriptor() for USB_DT_DEVICE,
+ * and usb_get_string() or usb_string() for USB_DT_STRING.
+ * Configuration descriptors (USB_DT_CONFIG) are part of the device
+ * structure, at least for the current configuration.
+ * In addition to a number of USB-standard descriptors, some
+ * devices also use class-specific or vendor-specific descriptors.
+ *
+ * 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_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
+{
+ int i = 5;
+ int result;
+
+ memset(buf,0,size); // Make sure we parse really received data
+
+ while (i--) {
+ /* retries if the returned length was 0; flakey device */
+ if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (type << 8) + index, 0, buf, size,
+ HZ * USB_CTRL_GET_TIMEOUT)) > 0
+ || result == -EPIPE)
+ break;
+ }
+ return result;
+}
+
+/**
+ * usb_get_string - gets a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @langid: code for language chosen (from string descriptor zero)
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
+ * in little-endian byte order).
+ * The usb_string() function will often be a convenient way to turn
+ * these strings into kernel-printable form.
+ *
+ * Strings may be referenced in device, configuration, interface, or other
+ * descriptors, and could also be used in vendor-specific ways.
+ *
+ * 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_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (USB_DT_STRING << 8) + index, langid, buf, size,
+ HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+/**
+ * usb_get_device_descriptor - (re)reads the device descriptor
+ * @dev: the device whose device descriptor is being updated
+ * 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.
+ *
+ * There's normally no need to use this call, although some devices
+ * will change their descriptors after events like updating firmware.
+ *
+ * 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)
+{
+ int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
+ sizeof(dev->descriptor));
+ if (ret >= 0) {
+ le16_to_cpus(&dev->descriptor.bcdUSB);
+ le16_to_cpus(&dev->descriptor.idVendor);
+ le16_to_cpus(&dev->descriptor.idProduct);
+ le16_to_cpus(&dev->descriptor.bcdDevice);
+ }
+ 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)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
+ HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for config/altsetting reconfig.
+void usb_set_maxpacket(struct usb_device *dev)
+{
+ int i, b;
+
+ for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
+ struct usb_interface *ifp = dev->actconfig->interface + i;
+ struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;
+ struct usb_endpoint_descriptor *ep = as->endpoint;
+ int e;
+
+ for (e=0; e<as->bNumEndpoints; e++) {
+ b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */
+ dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+ dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+ }
+ else if (usb_endpoint_out(ep[e].bEndpointAddress)) {
+ if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
+ dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+ }
+ else {
+ if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
+ dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+ }
+ }
+ }
+}
+
+/**
+ * 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 queued for such an endpoint should normally be unlinked before
+ * clearing the halt condition.
+ *
+ * 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;
+ __u16 status;
+ unsigned char *buffer;
+ int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
+
+/*
+ if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
+ return 0;
+*/
+
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
+ HZ * USB_CTRL_SET_TIMEOUT);
+
+ /* don't clear if failed */
+ if (result < 0)
+ return result;
+
+ buffer = kmalloc(sizeof(status), GFP_KERNEL);
+ if (!buffer) {
+ err("unable to allocate memory for configuration descriptors");
+ return -ENOMEM;
+ }
+
+ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
+ // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
+ buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
+
+ memcpy(&status, buffer, sizeof(status));
+ kfree(buffer);
+
+ if (result < 0)
+ return result;
+
+ if (le16_to_cpu(status) & 1)
+ return -EPIPE; /* still halted */
+
+ usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
+ /* toggle is reset on clear */
+
+ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+
+ return 0;
+}
+
+/**
+ * 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.
+ *
+ * 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 about 4KBytes per
+ * microframe, and isochronous endpoints may never be part of a an
+ * interface's default setting. To access such bandwidth, alternate
+ * interface setting 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
+ * 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.
+ *
+ * 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_interface_descriptor *iface_as;
+ int i, ret;
+
+ iface = usb_ifnum_to_if(dev, interface);
+ if (!iface) {
+ warn("selecting invalid interface %d", interface);
+ return -EINVAL;
+ }
+
+ /* 9.4.10 says devices don't need this, if the interface
+ only has one alternate setting */
+ if (iface->num_altsetting == 1) {
+ dbg("ignoring set_interface for dev %d, iface %d, alt %d",
+ dev->devnum, interface, alternate);
+ return 0;
+ }
+
+ if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
+ interface, NULL, 0, HZ * 5)) < 0)
+ return ret;
+
+ iface->act_altsetting = alternate;
+
+ /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
+ *
+ * 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.
+ */
+
+ iface_as = &iface->altsetting[alternate];
+ for (i = 0; i < iface_as->bNumEndpoints; i++) {
+ u8 ep = iface_as->endpoint[i].bEndpointAddress;
+
+ usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
+ }
+
+ /* usb_set_maxpacket() sets the maxpacket size for all EP in all
+ * interfaces but it shouldn't do any harm here: we have changed
+ * the AS for the requested interface only, hence for unaffected
+ * interfaces it's just re-application of still-valid values.
+ */
+ usb_set_maxpacket(dev);
+ return 0;
+}
+
+/**
+ * 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 ()
+ *
+ * This is used to enable non-default device modes. Not all devices
+ * support this kind of configurability. By default, configuration
+ * zero is selected after enumeration; many devices only have a single
+ * configuration.
+ *
+ * USB devices may support one or more configurations, which affect
+ * 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 will be in some
+ * non-default device configuration. Other device modes may also be
+ * reflected as configuration options, such as whether two ISDN
+ * channels are presented as independent 64Kb/s interfaces or as one
+ * bonded 128Kb/s interface.
+ *
+ * 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, 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_set_configuration(struct usb_device *dev, int configuration)
+{
+ int i, ret;
+ struct usb_config_descriptor *cp = NULL;
+
+ for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
+ if (dev->config[i].bConfigurationValue == configuration) {
+ cp = &dev->config[i];
+ break;
+ }
+ }
+ if (!cp) {
+ warn("selecting invalid configuration %d", configuration);
+ return -EINVAL;
+ }
+
+ 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)
+ return ret;
+
+ dev->actconfig = cp;
+ dev->toggle[0] = 0;
+ dev->toggle[1] = 0;
+ usb_set_maxpacket(dev);
+
+ return 0;
+}
+
+
+/**
+ * usb_string - returns ISO 8859-1 version of a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * This converts the UTF-16LE encoded strings returned by devices, from
+ * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
+ * that are more usable in most kernel contexts. Note that all characters
+ * in the chosen descriptor that can't be encoded using ISO-8859-1
+ * are converted to the question mark ("?") character, and this function
+ * chooses strings in the first language supported by the device.
+ *
+ * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
+ * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
+ * and is appropriate for use many uses of English and several other
+ * Western European languages. (But it doesn't include the "Euro" symbol.)
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns length of the string (>= 0) or usb_control_msg status (< 0).
+ */
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+{
+ unsigned char *tbuf;
+ int err;
+ unsigned int u, idx;
+
+ if (size <= 0 || !buf || !index)
+ return -EINVAL;
+ buf[0] = 0;
+ tbuf = kmalloc(256, GFP_KERNEL);
+ if (!tbuf)
+ return -ENOMEM;
+
+ /* get langid for strings if it's not yet known */
+ if (!dev->have_langid) {
+ err = usb_get_string(dev, 0, 0, tbuf, 4);
+ if (err < 0) {
+ err("error getting string descriptor 0 (error=%d)", err);
+ goto errout;
+ } else if (tbuf[0] < 4) {
+ err("string descriptor 0 too short");
+ err = -EINVAL;
+ goto errout;
+ } else {
+ dev->have_langid = -1;
+ dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+ /* always use the first langid listed */
+ dbg("USB device number %d default language ID 0x%x",
+ dev->devnum, dev->string_langid);
+ }
+ }
+
+ /*
+ * Just ask for a maximum length string and then take the length
+ * that was returned.
+ */
+ err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
+ 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;
+
+ errout:
+ kfree(tbuf);
+ return err;
+}
+
+// synchronous request completion model
+EXPORT_SYMBOL(usb_control_msg);
+EXPORT_SYMBOL(usb_bulk_msg);
+// synchronous control message convenience routines
+EXPORT_SYMBOL(usb_get_descriptor);
+EXPORT_SYMBOL(usb_get_device_descriptor);
+EXPORT_SYMBOL(usb_get_status);
+EXPORT_SYMBOL(usb_get_string);
+EXPORT_SYMBOL(usb_string);
+EXPORT_SYMBOL(usb_clear_halt);
+EXPORT_SYMBOL(usb_set_configuration);
+EXPORT_SYMBOL(usb_set_interface);
+
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
new file mode 100644
index 000000000000..6cb11b083890
--- /dev/null
+++ b/drivers/usb/core/urb.c
@@ -0,0 +1,236 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+#include <linux/usb.h>
+#include "hcd.h"
+
+/**
+ * usb_alloc_urb - creates a new urb for a USB driver to use
+ * @iso_packets: number of iso packets for this urb
+ * @mem_flags: the type of memory to allocate, see kmalloc() for a list of
+ * valid options for this.
+ *
+ * Creates an urb for the USB driver to use, initializes a few internal
+ * structures, incrementes the usage counter, and returns a pointer to it.
+ *
+ * If no memory is available, NULL is returned.
+ *
+ * If the driver want to use this urb for interrupt, control, or bulk
+ * endpoints, pass '0' as the number of iso packets.
+ *
+ * The driver must call usb_free_urb() when it is finished with the urb.
+ */
+struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
+{
+ struct urb *urb;
+
+ urb = (struct urb *)kmalloc(sizeof(struct urb) +
+ iso_packets * sizeof(struct usb_iso_packet_descriptor),
+ mem_flags);
+ if (!urb) {
+ err("alloc_urb: kmalloc failed");
+ return NULL;
+ }
+
+ memset(urb, 0, sizeof(*urb));
+ urb->count = (atomic_t)ATOMIC_INIT(1);
+ spin_lock_init(&urb->lock);
+
+ return urb;
+}
+
+/**
+ * usb_free_urb - frees the memory used by a urb when all users of it are finished
+ * @urb: pointer to the urb to free
+ *
+ * Must be called when a user of a urb is finished with it. When the last user
+ * of the urb calls this function, the memory of the urb is freed.
+ *
+ * Note: The transfer buffer associated with the urb is not freed, that must be
+ * done elsewhere.
+ */
+void usb_free_urb(struct urb *urb)
+{
+ if (urb)
+ if (atomic_dec_and_test(&urb->count))
+ kfree(urb);
+}
+
+/**
+ * usb_get_urb - increments the reference count of the urb
+ * @urb: pointer to the urb to modify
+ *
+ * This must be called whenever a urb is transfered from a device driver to a
+ * host controller driver. This allows proper reference counting to happen
+ * for urbs.
+ *
+ * A pointer to the urb with the incremented reference counter is returned.
+ */
+struct urb * usb_get_urb(struct urb *urb)
+{
+ if (urb) {
+ atomic_inc(&urb->count);
+ return urb;
+ } else
+ return NULL;
+}
+
+
+/*-------------------------------------------------------------------*/
+
+/**
+ * usb_submit_urb - asynchronously issue a transfer request for an endpoint
+ * @urb: pointer to the urb describing the request
+ * @mem_flags: the type of memory to allocate, see kmalloc() for a list
+ * of valid options for this.
+ *
+ * This submits a transfer request, and transfers control of the URB
+ * describing that request to the USB subsystem. Request completion will
+ * indicated later, asynchronously, by calling the completion handler.
+ * This call may be issued in interrupt context.
+ *
+ * The caller must have correctly initialized the URB before submitting
+ * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
+ * available to ensure that most fields are correctly initialized, for
+ * the particular kind of transfer, although they will not initialize
+ * any transfer flags.
+ *
+ * Successful submissions return 0; otherwise this routine returns a
+ * negative error number. If the submission is successful, the complete
+ * fuction of the urb will be called when the USB host driver is
+ * finished with the urb (either a successful transmission, or some
+ * error case.)
+ *
+ * Unreserved Bandwidth Transfers:
+ *
+ * Bulk or control requests complete only once. When the completion
+ * function is called, control of the URB is returned to the device
+ * driver which issued the request. The completion handler may then
+ * immediately free or reuse that URB.
+ *
+ * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set
+ * in the URB. This can be used to maximize bandwidth utilization by
+ * letting the USB controller start work on the next URB without any
+ * delay to report completion (scheduling and processing an interrupt)
+ * and then submit that next request.
+ *
+ * For control endpoints, the synchronous usb_control_msg() call is
+ * often used (in non-interrupt context) instead of this call.
+ *
+ * Reserved Bandwidth Transfers:
+ *
+ * Periodic URBs (interrupt or isochronous) are completed repeatedly,
+ * until the original request is aborted. When the completion callback
+ * indicates the URB has been unlinked (with a special status code),
+ * control of that URB returns to the device driver. Otherwise, the
+ * completion handler does not control the URB, and should not change
+ * any of its fields.
+ *
+ * Note that isochronous URBs should be submitted in a "ring" data
+ * structure (using urb->next) to ensure that they are resubmitted
+ * appropriately.
+ *
+ * If the USB subsystem can't reserve sufficient bandwidth to perform
+ * the periodic request, and bandwidth reservation is being done for
+ * this controller, submitting such a periodic request will fail.
+ *
+ * Memory Flags:
+ *
+ * General rules for how to decide which mem_flags to use:
+ *
+ * Basically the rules are the same as for kmalloc. There are four
+ * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
+ * GFP_ATOMIC.
+ *
+ * GFP_NOFS is not ever used, as it has not been implemented yet.
+ *
+ * There are three situations you must use GFP_ATOMIC.
+ * a) you are inside a completion handler, an interrupt, bottom half,
+ * tasklet or timer.
+ * b) you are holding a spinlock or rwlock (does not apply to
+ * semaphores)
+ * c) current->state != TASK_RUNNING, this is the case only after
+ * you've changed it.
+ *
+ * GFP_NOIO is used in the block io path and error handling of storage
+ * devices.
+ *
+ * All other situations use GFP_KERNEL.
+ *
+ * Specfic rules for how to decide which mem_flags to use:
+ *
+ * - start_xmit, timeout, and receive methods of network drivers must
+ * use GFP_ATOMIC (spinlock)
+ * - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
+ * - If you use a kernel thread with a network driver you must use
+ * GFP_NOIO, unless b) or c) apply
+ * - After you have done a down() you use GFP_KERNEL, unless b) or c)
+ * apply or your are in a storage driver's block io path
+ * - probe and disconnect use GFP_KERNEL unless b) or c) apply
+ * - Changing firmware on a running storage or net device uses
+ * GFP_NOIO, unless b) or c) apply
+ *
+ */
+int usb_submit_urb(struct urb *urb, int mem_flags)
+{
+
+ if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) {
+ if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) <= 0) {
+ err("%s: pipe %x has invalid size (<= 0)", __FUNCTION__, urb->pipe);
+ return -EMSGSIZE;
+ }
+ return urb->dev->bus->op->submit_urb(urb, mem_flags);
+ }
+ return -ENODEV;
+}
+
+/*-------------------------------------------------------------------*/
+
+/**
+ * usb_unlink_urb - abort/cancel a transfer request for an endpoint
+ * @urb: pointer to urb describing a previously submitted request
+ *
+ * This routine cancels an in-progress request. The requests's
+ * completion handler will be called with a status code indicating
+ * that the request has been canceled, and that control of the URB
+ * has been returned to that device driver. This is the only way
+ * to stop an interrupt transfer, so long as the device is connected.
+ *
+ * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this
+ * request is synchronous. Success is indicated by returning zero,
+ * at which time the urb will have been unlinked,
+ * and the completion function will see status -ENOENT. Failure is
+ * indicated by any other return value. This mode may not be used
+ * when unlinking an urb from an interrupt context, such as a bottom
+ * half or a completion handler,
+ *
+ * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this
+ * request is asynchronous. Success is indicated by returning -EINPROGRESS,
+ * at which time the urb will normally not have been unlinked,
+ * and the completion function will see status -ECONNRESET. Failure is
+ * indicated by any other return value.
+ */
+int usb_unlink_urb(struct urb *urb)
+{
+ if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
+ return urb->dev->bus->op->unlink_urb(urb);
+ else
+ return -ENODEV;
+}
+
+// asynchronous request completion model
+EXPORT_SYMBOL(usb_alloc_urb);
+EXPORT_SYMBOL(usb_free_urb);
+EXPORT_SYMBOL(usb_get_urb);
+EXPORT_SYMBOL(usb_submit_urb);
+EXPORT_SYMBOL(usb_unlink_urb);
+
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e0cf2c28fb92..4842fbf06737 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -33,7 +33,6 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
-#include <asm/byteorder.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
@@ -1014,401 +1013,6 @@ void usb_free_dev(struct usb_device *dev)
}
}
-/**
- * usb_alloc_urb - creates a new urb for a USB driver to use
- * @iso_packets: number of iso packets for this urb
- * @mem_flags: the type of memory to allocate, see kmalloc() for a list of
- * valid options for this.
- *
- * Creates an urb for the USB driver to use, initializes a few internal
- * structures, incrementes the usage counter, and returns a pointer to it.
- *
- * If no memory is available, NULL is returned.
- *
- * If the driver want to use this urb for interrupt, control, or bulk
- * endpoints, pass '0' as the number of iso packets.
- *
- * The driver must call usb_free_urb() when it is finished with the urb.
- */
-struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
-{
- struct urb *urb;
-
- urb = (struct urb *)kmalloc(sizeof(struct urb) +
- iso_packets * sizeof(struct usb_iso_packet_descriptor),
- mem_flags);
- if (!urb) {
- err("alloc_urb: kmalloc failed");
- return NULL;
- }
-
- memset(urb, 0, sizeof(*urb));
- urb->count = (atomic_t)ATOMIC_INIT(1);
- spin_lock_init(&urb->lock);
-
- return urb;
-}
-
-/**
- * usb_free_urb - frees the memory used by a urb when all users of it are finished
- * @urb: pointer to the urb to free
- *
- * Must be called when a user of a urb is finished with it. When the last user
- * of the urb calls this function, the memory of the urb is freed.
- *
- * Note: The transfer buffer associated with the urb is not freed, that must be
- * done elsewhere.
- */
-void usb_free_urb(struct urb *urb)
-{
- if (urb)
- if (atomic_dec_and_test(&urb->count))
- kfree(urb);
-}
-
-/**
- * usb_get_urb - increments the reference count of the urb
- * @urb: pointer to the urb to modify
- *
- * This must be called whenever a urb is transfered from a device driver to a
- * host controller driver. This allows proper reference counting to happen
- * for urbs.
- *
- * A pointer to the urb with the incremented reference counter is returned.
- */
-struct urb * usb_get_urb(struct urb *urb)
-{
- if (urb) {
- atomic_inc(&urb->count);
- return urb;
- } else
- return NULL;
-}
-
-
-/*-------------------------------------------------------------------*/
-
-/**
- * usb_submit_urb - asynchronously issue a transfer request for an endpoint
- * @urb: pointer to the urb describing the request
- * @mem_flags: the type of memory to allocate, see kmalloc() for a list
- * of valid options for this.
- *
- * This submits a transfer request, and transfers control of the URB
- * describing that request to the USB subsystem. Request completion will
- * indicated later, asynchronously, by calling the completion handler.
- * This call may be issued in interrupt context.
- *
- * The caller must have correctly initialized the URB before submitting
- * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
- * available to ensure that most fields are correctly initialized, for
- * the particular kind of transfer, although they will not initialize
- * any transfer flags.
- *
- * Successful submissions return 0; otherwise this routine returns a
- * negative error number. If the submission is successful, the complete
- * fuction of the urb will be called when the USB host driver is
- * finished with the urb (either a successful transmission, or some
- * error case.)
- *
- * Unreserved Bandwidth Transfers:
- *
- * Bulk or control requests complete only once. When the completion
- * function is called, control of the URB is returned to the device
- * driver which issued the request. The completion handler may then
- * immediately free or reuse that URB.
- *
- * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set
- * in the URB. This can be used to maximize bandwidth utilization by
- * letting the USB controller start work on the next URB without any
- * delay to report completion (scheduling and processing an interrupt)
- * and then submit that next request.
- *
- * For control endpoints, the synchronous usb_control_msg() call is
- * often used (in non-interrupt context) instead of this call.
- *
- * Reserved Bandwidth Transfers:
- *
- * Periodic URBs (interrupt or isochronous) are completed repeatedly,
- * until the original request is aborted. When the completion callback
- * indicates the URB has been unlinked (with a special status code),
- * control of that URB returns to the device driver. Otherwise, the
- * completion handler does not control the URB, and should not change
- * any of its fields.
- *
- * Note that isochronous URBs should be submitted in a "ring" data
- * structure (using urb->next) to ensure that they are resubmitted
- * appropriately.
- *
- * If the USB subsystem can't reserve sufficient bandwidth to perform
- * the periodic request, and bandwidth reservation is being done for
- * this controller, submitting such a periodic request will fail.
- *
- * Memory Flags:
- *
- * General rules for how to decide which mem_flags to use:
- *
- * Basically the rules are the same as for kmalloc. There are four
- * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
- * GFP_ATOMIC.
- *
- * GFP_NOFS is not ever used, as it has not been implemented yet.
- *
- * There are three situations you must use GFP_ATOMIC.
- * a) you are inside a completion handler, an interrupt, bottom half,
- * tasklet or timer.
- * b) you are holding a spinlock or rwlock (does not apply to
- * semaphores)
- * c) current->state != TASK_RUNNING, this is the case only after
- * you've changed it.
- *
- * GFP_NOIO is used in the block io path and error handling of storage
- * devices.
- *
- * All other situations use GFP_KERNEL.
- *
- * Specfic rules for how to decide which mem_flags to use:
- *
- * - start_xmit, timeout, and receive methods of network drivers must
- * use GFP_ATOMIC (spinlock)
- * - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
- * - If you use a kernel thread with a network driver you must use
- * GFP_NOIO, unless b) or c) apply
- * - After you have done a down() you use GFP_KERNEL, unless b) or c)
- * apply or your are in a storage driver's block io path
- * - probe and disconnect use GFP_KERNEL unless b) or c) apply
- * - Changing firmware on a running storage or net device uses
- * GFP_NOIO, unless b) or c) apply
- *
- */
-int usb_submit_urb(struct urb *urb, int mem_flags)
-{
-
- if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) {
- if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) <= 0) {
- err("%s: pipe %x has invalid size (<= 0)", __FUNCTION__, urb->pipe);
- return -EMSGSIZE;
- }
- return urb->dev->bus->op->submit_urb(urb, mem_flags);
- }
- return -ENODEV;
-}
-
-/*-------------------------------------------------------------------*/
-
-/**
- * usb_unlink_urb - abort/cancel a transfer request for an endpoint
- * @urb: pointer to urb describing a previously submitted request
- *
- * This routine cancels an in-progress request. The requests's
- * completion handler will be called with a status code indicating
- * that the request has been canceled, and that control of the URB
- * has been returned to that device driver. This is the only way
- * to stop an interrupt transfer, so long as the device is connected.
- *
- * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this
- * request is synchronous. Success is indicated by returning zero,
- * at which time the urb will have been unlinked,
- * and the completion function will see status -ENOENT. Failure is
- * indicated by any other return value. This mode may not be used
- * when unlinking an urb from an interrupt context, such as a bottom
- * half or a completion handler,
- *
- * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this
- * request is asynchronous. Success is indicated by returning -EINPROGRESS,
- * at which time the urb will normally not have been unlinked,
- * and the completion function will see status -ECONNRESET. Failure is
- * indicated by any other return value.
- */
-int usb_unlink_urb(struct urb *urb)
-{
- if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
- return urb->dev->bus->op->unlink_urb(urb);
- else
- return -ENODEV;
-}
-/*-------------------------------------------------------------------*
- * SYNCHRONOUS CALLS *
- *-------------------------------------------------------------------*/
-
-struct usb_api_data {
- wait_queue_head_t wqh;
- int done;
-};
-
-static void usb_api_blocking_completion(struct urb *urb)
-{
- struct usb_api_data *awd = (struct usb_api_data *)urb->context;
-
- awd->done = 1;
- wmb();
- wake_up(&awd->wqh);
-}
-
-// Starts urb and waits for completion or timeout
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct usb_api_data awd;
- int status;
-
- init_waitqueue_head(&awd.wqh);
- awd.done = 0;
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&awd.wqh, &wait);
-
- urb->context = &awd;
- status = usb_submit_urb(urb, GFP_KERNEL);
- if (status) {
- // something went wrong
- usb_free_urb(urb);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&awd.wqh, &wait);
- return status;
- }
-
- while (timeout && !awd.done)
- {
- timeout = schedule_timeout(timeout);
- set_current_state(TASK_UNINTERRUPTIBLE);
- rmb();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&awd.wqh, &wait);
-
- if (!timeout && !awd.done) {
- if (urb->status != -EINPROGRESS) { /* No callback?!! */
- printk(KERN_ERR "usb: raced timeout, "
- "pipe 0x%x status %d time left %d\n",
- urb->pipe, urb->status, timeout);
- status = urb->status;
- } else {
- printk("usb_control/bulk_msg: timeout\n");
- usb_unlink_urb(urb); // remove urb safely
- status = -ETIMEDOUT;
- }
- } else
- status = urb->status;
-
- if (actual_length)
- *actual_length = urb->actual_length;
-
- usb_free_urb(urb);
- return status;
-}
-
-/*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
- struct usb_ctrlrequest *cmd, void *data, int len, int timeout)
-{
- struct urb *urb;
- int retv;
- int length;
-
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
- usb_api_blocking_completion, 0);
-
- retv = usb_start_wait_urb(urb, timeout, &length);
- if (retv < 0)
- return retv;
- else
- return length;
-}
-
-/**
- * usb_control_msg - Builds a control urb, sends it off and waits for completion
- * @dev: pointer to the usb device to send the message to
- * @pipe: endpoint "pipe" to send the message to
- * @request: USB message request value
- * @requesttype: USB message request type value
- * @value: USB message value
- * @index: USB message index value
- * @data: pointer to the data to send
- * @size: length in bytes of the data to send
- * @timeout: time in jiffies to wait for the message to complete before
- * timing out (if 0 the wait is forever)
- * Context: !in_interrupt ()
- *
- * This function sends a simple control message to a specified endpoint
- * and waits for the message to complete, or timeout.
- *
- * If successful, it returns the number of bytes transferred, otherwise a negative error number.
- *
- * Don't use this function from within an interrupt context, like a
- * bottom half handler. If you need an asynchronous message, or need to send
- * a message from within interrupt context, use usb_submit_urb()
- */
-int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
- __u16 value, __u16 index, void *data, __u16 size, int timeout)
-{
- struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
- int ret;
-
- if (!dr)
- return -ENOMEM;
-
- dr->bRequestType= requesttype;
- dr->bRequest = request;
- dr->wValue = cpu_to_le16p(&value);
- dr->wIndex = cpu_to_le16p(&index);
- dr->wLength = cpu_to_le16p(&size);
-
- //dbg("usb_control_msg");
-
- ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
-
- kfree(dr);
-
- return ret;
-}
-
-
-/**
- * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
- * @usb_dev: pointer to the usb device to send the message to
- * @pipe: endpoint "pipe" to send the message to
- * @data: pointer to the data to send
- * @len: length in bytes of the data to send
- * @actual_length: pointer to a location to put the actual length transferred in bytes
- * @timeout: time in jiffies to wait for the message to complete before
- * timing out (if 0 the wait is forever)
- * Context: !in_interrupt ()
- *
- * This function sends a simple bulk message to a specified endpoint
- * and waits for the message to complete, or timeout.
- *
- * If successful, it returns 0, otherwise a negative error number.
- * The number of actual bytes transferred will be stored in the
- * actual_length paramater.
- *
- * Don't use this function from within an interrupt context, like a
- * bottom half handler. If you need an asynchronous message, or need to
- * send a message from within interrupt context, use usb_submit_urb()
- */
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
- void *data, int len, int *actual_length, int timeout)
-{
- struct urb *urb;
-
- if (len < 0)
- return -EINVAL;
-
- urb=usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- FILL_BULK_URB(urb, usb_dev, pipe, data, len,
- usb_api_blocking_completion, 0);
-
- return usb_start_wait_urb(urb,timeout,actual_length);
-}
/**
* usb_get_current_frame_number - return current bus frame number
@@ -1430,390 +1034,6 @@ int usb_get_current_frame_number(struct usb_device *dev)
/*-------------------------------------------------------------------*/
-static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
-{
- struct usb_descriptor_header *header;
- unsigned char *begin;
- int parsed = 0, len, numskipped;
-
- header = (struct usb_descriptor_header *)buffer;
-
- /* Everything should be fine being passed into here, but we sanity */
- /* check JIC */
- if (header->bLength > size) {
- err("ran out of descriptors parsing");
- return -1;
- }
-
- if (header->bDescriptorType != USB_DT_ENDPOINT) {
- warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
- endpoint->bDescriptorType, USB_DT_ENDPOINT);
- return parsed;
- }
-
- if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
- memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
- else
- memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
-
- le16_to_cpus(&endpoint->wMaxPacketSize);
-
- buffer += header->bLength;
- size -= header->bLength;
- parsed += header->bLength;
-
- /* Skip over the rest of the Class Specific or Vendor Specific */
- /* descriptors */
- begin = buffer;
- numskipped = 0;
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *)buffer;
-
- if (header->bLength < 2) {
- err("invalid descriptor length of %d", header->bLength);
- return -1;
- }
-
- /* If we find another "proper" descriptor then we're done */
- if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
- (header->bDescriptorType == USB_DT_INTERFACE) ||
- (header->bDescriptorType == USB_DT_CONFIG) ||
- (header->bDescriptorType == USB_DT_DEVICE))
- break;
-
- dbg("skipping descriptor 0x%X",
- header->bDescriptorType);
- numskipped++;
-
- buffer += header->bLength;
- size -= header->bLength;
- parsed += header->bLength;
- }
- if (numskipped)
- dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
-
- /* Copy any unknown descriptors into a storage area for drivers */
- /* to later parse */
- len = (int)(buffer - begin);
- if (!len) {
- endpoint->extra = NULL;
- endpoint->extralen = 0;
- return parsed;
- }
-
- endpoint->extra = kmalloc(len, GFP_KERNEL);
-
- if (!endpoint->extra) {
- err("couldn't allocate memory for endpoint extra descriptors");
- endpoint->extralen = 0;
- return parsed;
- }
-
- memcpy(endpoint->extra, begin, len);
- endpoint->extralen = len;
-
- return parsed;
-}
-
-static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
-{
- int i, len, numskipped, retval, parsed = 0;
- struct usb_descriptor_header *header;
- struct usb_interface_descriptor *ifp;
- unsigned char *begin;
-
- interface->act_altsetting = 0;
- interface->num_altsetting = 0;
- interface->max_altsetting = USB_ALTSETTINGALLOC;
-
- interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
-
- if (!interface->altsetting) {
- err("couldn't kmalloc interface->altsetting");
- return -1;
- }
-
- while (size > 0) {
- if (interface->num_altsetting >= interface->max_altsetting) {
- void *ptr;
- int oldmas;
-
- oldmas = interface->max_altsetting;
- interface->max_altsetting += USB_ALTSETTINGALLOC;
- if (interface->max_altsetting > USB_MAXALTSETTING) {
- warn("too many alternate settings (max %d)",
- USB_MAXALTSETTING);
- return -1;
- }
-
- ptr = interface->altsetting;
- interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
- if (!interface->altsetting) {
- err("couldn't kmalloc interface->altsetting");
- interface->altsetting = ptr;
- return -1;
- }
- memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas);
-
- kfree(ptr);
- }
-
- ifp = interface->altsetting + interface->num_altsetting;
- ifp->endpoint = NULL;
- ifp->extra = NULL;
- ifp->extralen = 0;
- interface->num_altsetting++;
-
- memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
-
- /* Skip over the interface */
- buffer += ifp->bLength;
- parsed += ifp->bLength;
- size -= ifp->bLength;
-
- begin = buffer;
- numskipped = 0;
-
- /* Skip over any interface, class or vendor descriptors */
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *)buffer;
-
- if (header->bLength < 2) {
- err("invalid descriptor length of %d", header->bLength);
- return -1;
- }
-
- /* If we find another "proper" descriptor then we're done */
- if ((header->bDescriptorType == USB_DT_INTERFACE) ||
- (header->bDescriptorType == USB_DT_ENDPOINT) ||
- (header->bDescriptorType == USB_DT_CONFIG) ||
- (header->bDescriptorType == USB_DT_DEVICE))
- break;
-
- numskipped++;
-
- buffer += header->bLength;
- parsed += header->bLength;
- size -= header->bLength;
- }
-
- if (numskipped)
- dbg("skipped %d class/vendor specific interface descriptors", numskipped);
-
- /* Copy any unknown descriptors into a storage area for */
- /* drivers to later parse */
- len = (int)(buffer - begin);
- if (len) {
- ifp->extra = kmalloc(len, GFP_KERNEL);
-
- if (!ifp->extra) {
- err("couldn't allocate memory for interface extra descriptors");
- ifp->extralen = 0;
- return -1;
- }
- memcpy(ifp->extra, begin, len);
- ifp->extralen = len;
- }
-
- /* Did we hit an unexpected descriptor? */
- header = (struct usb_descriptor_header *)buffer;
- if ((size >= sizeof(struct usb_descriptor_header)) &&
- ((header->bDescriptorType == USB_DT_CONFIG) ||
- (header->bDescriptorType == USB_DT_DEVICE)))
- return parsed;
-
- if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
- warn("too many endpoints");
- return -1;
- }
-
- ifp->endpoint = (struct usb_endpoint_descriptor *)
- kmalloc(ifp->bNumEndpoints *
- sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
- if (!ifp->endpoint) {
- err("out of memory");
- return -1;
- }
-
- memset(ifp->endpoint, 0, ifp->bNumEndpoints *
- sizeof(struct usb_endpoint_descriptor));
-
- for (i = 0; i < ifp->bNumEndpoints; i++) {
- header = (struct usb_descriptor_header *)buffer;
-
- if (header->bLength > size) {
- err("ran out of descriptors parsing");
- return -1;
- }
-
- retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
- if (retval < 0)
- return retval;
-
- buffer += retval;
- parsed += retval;
- size -= retval;
- }
-
- /* We check to see if it's an alternate to this one */
- ifp = (struct usb_interface_descriptor *)buffer;
- if (size < USB_DT_INTERFACE_SIZE ||
- ifp->bDescriptorType != USB_DT_INTERFACE ||
- !ifp->bAlternateSetting)
- return parsed;
- }
-
- return parsed;
-}
-
-int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
-{
- int i, retval, size;
- struct usb_descriptor_header *header;
-
- memcpy(config, buffer, USB_DT_CONFIG_SIZE);
- le16_to_cpus(&config->wTotalLength);
- size = config->wTotalLength;
-
- if (config->bNumInterfaces > USB_MAXINTERFACES) {
- warn("too many interfaces");
- return -1;
- }
-
- config->interface = (struct usb_interface *)
- kmalloc(config->bNumInterfaces *
- sizeof(struct usb_interface), GFP_KERNEL);
- dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces);
- if (!config->interface) {
- err("out of memory");
- return -1;
- }
-
- memset(config->interface, 0,
- config->bNumInterfaces * sizeof(struct usb_interface));
-
- buffer += config->bLength;
- size -= config->bLength;
-
- config->extra = NULL;
- config->extralen = 0;
-
- for (i = 0; i < config->bNumInterfaces; i++) {
- int numskipped, len;
- char *begin;
-
- /* Skip over the rest of the Class Specific or Vendor */
- /* Specific descriptors */
- begin = buffer;
- numskipped = 0;
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *)buffer;
-
- if ((header->bLength > size) || (header->bLength < 2)) {
- err("invalid descriptor length of %d", header->bLength);
- return -1;
- }
-
- /* If we find another "proper" descriptor then we're done */
- if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
- (header->bDescriptorType == USB_DT_INTERFACE) ||
- (header->bDescriptorType == USB_DT_CONFIG) ||
- (header->bDescriptorType == USB_DT_DEVICE))
- break;
-
- dbg("skipping descriptor 0x%X", header->bDescriptorType);
- numskipped++;
-
- buffer += header->bLength;
- size -= header->bLength;
- }
- if (numskipped)
- dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
-
- /* Copy any unknown descriptors into a storage area for */
- /* drivers to later parse */
- len = (int)(buffer - begin);
- if (len) {
- if (config->extralen) {
- warn("extra config descriptor");
- } else {
- config->extra = kmalloc(len, GFP_KERNEL);
- if (!config->extra) {
- err("couldn't allocate memory for config extra descriptors");
- config->extralen = 0;
- return -1;
- }
-
- memcpy(config->extra, begin, len);
- config->extralen = len;
- }
- }
-
- retval = usb_parse_interface(config->interface + i, buffer, size);
- if (retval < 0)
- return retval;
-
- buffer += retval;
- size -= retval;
- }
-
- return size;
-}
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally on disconnect/destroy path
-void usb_destroy_configuration(struct usb_device *dev)
-{
- int c, i, j, k;
-
- if (!dev->config)
- return;
-
- if (dev->rawdescriptors) {
- for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
- kfree(dev->rawdescriptors[i]);
-
- kfree(dev->rawdescriptors);
- }
-
- for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
- struct usb_config_descriptor *cf = &dev->config[c];
-
- if (!cf->interface)
- break;
-
- for (i = 0; i < cf->bNumInterfaces; i++) {
- struct usb_interface *ifp =
- &cf->interface[i];
-
- if (!ifp->altsetting)
- break;
-
- for (j = 0; j < ifp->num_altsetting; j++) {
- struct usb_interface_descriptor *as =
- &ifp->altsetting[j];
-
- if(as->extra) {
- kfree(as->extra);
- }
-
- if (!as->endpoint)
- break;
-
- for(k = 0; k < as->bNumEndpoints; k++) {
- if(as->endpoint[k].extra) {
- kfree(as->endpoint[k].extra);
- }
- }
- kfree(as->endpoint);
- }
-
- kfree(ifp->altsetting);
- }
- kfree(cf->interface);
- }
- kfree(dev->config);
-}
/* for returning string descriptors in UTF-16LE */
static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
@@ -2013,565 +1233,6 @@ int usb_set_address(struct usb_device *dev)
0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
}
-/**
- * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
- * @dev: the device whose descriptor is being retrieved
- * @type: the descriptor type (USB_DT_*)
- * @index: the number of the descriptor
- * @buf: where to put the descriptor
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Gets a USB descriptor. Convenience functions exist to simplify
- * getting some types of descriptors. Use
- * usb_get_device_descriptor() for USB_DT_DEVICE,
- * and usb_get_string() or usb_string() for USB_DT_STRING.
- * Configuration descriptors (USB_DT_CONFIG) are part of the device
- * structure, at least for the current configuration.
- * In addition to a number of USB-standard descriptors, some
- * devices also use class-specific or vendor-specific descriptors.
- *
- * 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_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
-{
- int i = 5;
- int result;
-
- memset(buf,0,size); // Make sure we parse really received data
-
- while (i--) {
- /* retries if the returned length was 0; flakey device */
- if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (type << 8) + index, 0, buf, size,
- HZ * USB_CTRL_GET_TIMEOUT)) > 0
- || result == -EPIPE)
- break;
- }
- return result;
-}
-
-/**
- * usb_get_string - gets a string descriptor
- * @dev: the device whose string descriptor is being retrieved
- * @langid: code for language chosen (from string descriptor zero)
- * @index: the number of the descriptor
- * @buf: where to put the string
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
- * in little-endian byte order).
- * The usb_string() function will often be a convenient way to turn
- * these strings into kernel-printable form.
- *
- * Strings may be referenced in device, configuration, interface, or other
- * descriptors, and could also be used in vendor-specific ways.
- *
- * 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_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (USB_DT_STRING << 8) + index, langid, buf, size,
- HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-/**
- * usb_get_device_descriptor - (re)reads the device descriptor
- * @dev: the device whose device descriptor is being updated
- * 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.
- *
- * There's normally no need to use this call, although some devices
- * will change their descriptors after events like updating firmware.
- *
- * 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)
-{
- int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
- sizeof(dev->descriptor));
- if (ret >= 0) {
- le16_to_cpus(&dev->descriptor.bcdUSB);
- le16_to_cpus(&dev->descriptor.idVendor);
- le16_to_cpus(&dev->descriptor.idProduct);
- le16_to_cpus(&dev->descriptor.bcdDevice);
- }
- 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)
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
- HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally, for config/altsetting reconfig.
-void usb_set_maxpacket(struct usb_device *dev)
-{
- int i, b;
-
- for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
- struct usb_interface *ifp = dev->actconfig->interface + i;
- struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;
- struct usb_endpoint_descriptor *ep = as->endpoint;
- int e;
-
- for (e=0; e<as->bNumEndpoints; e++) {
- b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */
- dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
- dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
- }
- else if (usb_endpoint_out(ep[e].bEndpointAddress)) {
- if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
- dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
- }
- else {
- if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
- dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
- }
- }
- }
-}
-
-/**
- * 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 queued for such an endpoint should normally be unlinked before
- * clearing the halt condition.
- *
- * 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;
- __u16 status;
- unsigned char *buffer;
- int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
-
-/*
- if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
- return 0;
-*/
-
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
- HZ * USB_CTRL_SET_TIMEOUT);
-
- /* don't clear if failed */
- if (result < 0)
- return result;
-
- buffer = kmalloc(sizeof(status), GFP_KERNEL);
- if (!buffer) {
- err("unable to allocate memory for configuration descriptors");
- return -ENOMEM;
- }
-
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
- // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
- buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
-
- memcpy(&status, buffer, sizeof(status));
- kfree(buffer);
-
- if (result < 0)
- return result;
-
- if (le16_to_cpu(status) & 1)
- return -EPIPE; /* still halted */
-
- usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
-
- /* toggle is reset on clear */
-
- usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-
- return 0;
-}
-
-/**
- * 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.
- *
- * 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 about 4KBytes per
- * microframe, and isochronous endpoints may never be part of a an
- * interface's default setting. To access such bandwidth, alternate
- * interface setting 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
- * 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.
- *
- * 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_interface_descriptor *iface_as;
- int i, ret;
-
- iface = usb_ifnum_to_if(dev, interface);
- if (!iface) {
- warn("selecting invalid interface %d", interface);
- return -EINVAL;
- }
-
- /* 9.4.10 says devices don't need this, if the interface
- only has one alternate setting */
- if (iface->num_altsetting == 1) {
- dbg("ignoring set_interface for dev %d, iface %d, alt %d",
- dev->devnum, interface, alternate);
- return 0;
- }
-
- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
- interface, NULL, 0, HZ * 5)) < 0)
- return ret;
-
- iface->act_altsetting = alternate;
-
- /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
- *
- * 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.
- */
-
- iface_as = &iface->altsetting[alternate];
- for (i = 0; i < iface_as->bNumEndpoints; i++) {
- u8 ep = iface_as->endpoint[i].bEndpointAddress;
-
- usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
- }
-
- /* usb_set_maxpacket() sets the maxpacket size for all EP in all
- * interfaces but it shouldn't do any harm here: we have changed
- * the AS for the requested interface only, hence for unaffected
- * interfaces it's just re-application of still-valid values.
- */
- usb_set_maxpacket(dev);
- return 0;
-}
-
-/**
- * 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 ()
- *
- * This is used to enable non-default device modes. Not all devices
- * support this kind of configurability. By default, configuration
- * zero is selected after enumeration; many devices only have a single
- * configuration.
- *
- * USB devices may support one or more configurations, which affect
- * 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 will be in some
- * non-default device configuration. Other device modes may also be
- * reflected as configuration options, such as whether two ISDN
- * channels are presented as independent 64Kb/s interfaces or as one
- * bonded 128Kb/s interface.
- *
- * 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, 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_set_configuration(struct usb_device *dev, int configuration)
-{
- int i, ret;
- struct usb_config_descriptor *cp = NULL;
-
- for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
- if (dev->config[i].bConfigurationValue == configuration) {
- cp = &dev->config[i];
- break;
- }
- }
- if (!cp) {
- warn("selecting invalid configuration %d", configuration);
- return -EINVAL;
- }
-
- 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)
- return ret;
-
- dev->actconfig = cp;
- dev->toggle[0] = 0;
- dev->toggle[1] = 0;
- usb_set_maxpacket(dev);
-
- return 0;
-}
-
-// hub-only!! ... and only in reset path, or usb_new_device()
-// (used by real hubs and virtual root hubs)
-int usb_get_configuration(struct usb_device *dev)
-{
- int result;
- unsigned int cfgno, length;
- unsigned char *buffer;
- unsigned char *bigbuffer;
- struct usb_config_descriptor *desc;
-
- if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
- warn("too many configurations");
- return -EINVAL;
- }
-
- if (dev->descriptor.bNumConfigurations < 1) {
- warn("not enough configurations");
- return -EINVAL;
- }
-
- dev->config = (struct usb_config_descriptor *)
- kmalloc(dev->descriptor.bNumConfigurations *
- sizeof(struct usb_config_descriptor), GFP_KERNEL);
- if (!dev->config) {
- err("out of memory");
- return -ENOMEM;
- }
- memset(dev->config, 0, dev->descriptor.bNumConfigurations *
- sizeof(struct usb_config_descriptor));
-
- dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
- dev->descriptor.bNumConfigurations, GFP_KERNEL);
- if (!dev->rawdescriptors) {
- err("out of memory");
- return -ENOMEM;
- }
-
- buffer = kmalloc(8, GFP_KERNEL);
- if (!buffer) {
- err("unable to allocate memory for configuration descriptors");
- return -ENOMEM;
- }
- desc = (struct usb_config_descriptor *)buffer;
-
- for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
- /* We grab the first 8 bytes so we know how long the whole */
- /* configuration is */
- result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
- if (result < 8) {
- if (result < 0)
- err("unable to get descriptor");
- else {
- err("config descriptor too short (expected %i, got %i)", 8, result);
- result = -EINVAL;
- }
- goto err;
- }
-
- /* Get the full buffer */
- length = le16_to_cpu(desc->wTotalLength);
-
- bigbuffer = kmalloc(length, GFP_KERNEL);
- if (!bigbuffer) {
- err("unable to allocate memory for configuration descriptors");
- result = -ENOMEM;
- goto err;
- }
-
- /* Now that we know the length, get the whole thing */
- result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
- if (result < 0) {
- err("couldn't get all of config descriptors");
- kfree(bigbuffer);
- goto err;
- }
-
- if (result < length) {
- err("config descriptor too short (expected %i, got %i)", length, result);
- result = -EINVAL;
- kfree(bigbuffer);
- goto err;
- }
-
- dev->rawdescriptors[cfgno] = bigbuffer;
-
- result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
- if (result > 0)
- dbg("descriptor data left");
- else if (result < 0) {
- result = -EINVAL;
- goto err;
- }
- }
-
- kfree(buffer);
- return 0;
-err:
- kfree(buffer);
- dev->descriptor.bNumConfigurations = cfgno;
- return result;
-}
-
-/**
- * usb_string - returns ISO 8859-1 version of a string descriptor
- * @dev: the device whose string descriptor is being retrieved
- * @index: the number of the descriptor
- * @buf: where to put the string
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * This converts the UTF-16LE encoded strings returned by devices, from
- * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
- * that are more usable in most kernel contexts. Note that all characters
- * in the chosen descriptor that can't be encoded using ISO-8859-1
- * are converted to the question mark ("?") character, and this function
- * chooses strings in the first language supported by the device.
- *
- * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
- * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
- * and is appropriate for use many uses of English and several other
- * Western European languages. (But it doesn't include the "Euro" symbol.)
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns length of the string (>= 0) or usb_control_msg status (< 0).
- */
-int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
-{
- unsigned char *tbuf;
- int err;
- unsigned int u, idx;
-
- if (size <= 0 || !buf || !index)
- return -EINVAL;
- buf[0] = 0;
- tbuf = kmalloc(256, GFP_KERNEL);
- if (!tbuf)
- return -ENOMEM;
-
- /* get langid for strings if it's not yet known */
- if (!dev->have_langid) {
- err = usb_get_string(dev, 0, 0, tbuf, 4);
- if (err < 0) {
- err("error getting string descriptor 0 (error=%d)", err);
- goto errout;
- } else if (tbuf[0] < 4) {
- err("string descriptor 0 too short");
- err = -EINVAL;
- goto errout;
- } else {
- dev->have_langid = -1;
- dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
- /* always use the first langid listed */
- dbg("USB device number %d default language ID 0x%x",
- dev->devnum, dev->string_langid);
- }
- }
-
- /*
- * Just ask for a maximum length string and then take the length
- * that was returned.
- */
- err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
- 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;
-
- errout:
- kfree(tbuf);
- return err;
-}
/*
* By the time we get here, the device has gotten a new device ID
@@ -2828,25 +1489,5 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_get_current_frame_number);
-// asynchronous request completion model
-EXPORT_SYMBOL(usb_alloc_urb);
-EXPORT_SYMBOL(usb_free_urb);
-EXPORT_SYMBOL(usb_get_urb);
-EXPORT_SYMBOL(usb_submit_urb);
-EXPORT_SYMBOL(usb_unlink_urb);
-
-// synchronous request completion model
-EXPORT_SYMBOL(usb_control_msg);
-EXPORT_SYMBOL(usb_bulk_msg);
-// synchronous control message convenience routines
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_device_descriptor);
-EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_get_string);
-EXPORT_SYMBOL(usb_string);
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_set_configuration);
-EXPORT_SYMBOL(usb_set_interface);
-
EXPORT_SYMBOL(usb_devfs_handle);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index ca32e98d90eb..f8725f64ac85 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -144,11 +144,13 @@ static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
usb_pipeendpoint (pipe),
usb_pipeout (pipe));
if (urb->dev->tt && !usb_pipeint (pipe)) {
+#ifdef DEBUG
struct usb_device *tt = urb->dev->tt->hub;
dbg ("clear tt %s-%s p%d buffer, a%d ep%d",
tt->bus->bus_name, tt->devpath,
urb->dev->ttport, urb->dev->devnum,
usb_pipeendpoint (pipe));
+#endif /* DEBUG */
usb_hub_tt_clear_buffer (urb->dev, pipe);
}
}
diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
index 3f43ef71ec67..54e181fdb695 100644
--- a/drivers/usb/image/scanner.c
+++ b/drivers/usb/image/scanner.c
@@ -1,13 +1,13 @@
/* -*- linux-c -*- */
/*
- * Driver for USB Scanners (linux-2.4.12)
+ * Driver for USB Scanners (linux-2.4.18)
*
- * Copyright (C) 1999, 2000, 2001 David E. Nelson
+ * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
*
* Portions may be copyright Brad Keryan and Michael Gee.
*
- * David E. Nelson (dnelson@jump.net)
+ * Brian Beattie <beattie@beattie-home.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -302,11 +302,24 @@
*
* 05/21/02 Currently maintained by Brian Beattie <beattie@beattie-home.net>
*
+ * 0.4.8 5/30/2002
+ * - Added Mustek BearPaw 2400 TA. Thanks to Sergey
+ * Vlasov <vsu@mivlgu.murom.ru>.
+ * - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's. These use
+ * the Grandtech GT-6801 chip. Thanks to Henning
+ * Meier-Geinitz <henning@meier-geinitz.de>.
+ * - Increased Epson timeout to 60 secs as requested from
+ * Karl Heinz Kremer <khk@khk.net>.
+ * - Changed maintainership from David E. Nelson to Brian
+ * Beattie <beattie@beattie-home.net>.
+ *
* TODO
+ * - Remove the 2/3 endpoint limitation
* - Performance
* - Select/poll methods
* - More testing
* - Proper registry/assignment for LM9830 ioctl's
+ * - More general usage ioctl's
*
*
* Thanks to:
@@ -322,6 +335,8 @@
* - All the folks who chimed in with reports and suggestions.
* - All the developers that are working on USB SANE backends or other
* applications to use USB scanners.
+ * - Thanks to Greg KH <greg@kroah.com> for setting up Brian Beattie
+ * to be the new USB Scanner maintainer.
*
* Performance:
*
@@ -1035,7 +1050,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
case 0x04b8: /* Seiko/Epson */
- scn->rd_nak_timeout = HZ * 40;
+ scn->rd_nak_timeout = HZ * 60;
break;
case 0x055f: /* Mustek */
case 0x0400: /* Another Mustek */
diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
index f48387e9b3a9..0fa9036358dc 100644
--- a/drivers/usb/image/scanner.h
+++ b/drivers/usb/image/scanner.h
@@ -1,9 +1,9 @@
/*
- * Driver for USB Scanners (linux-2.4.12)
+ * Driver for USB Scanners (linux-2.4.18)
*
- * Copyright (C) 1999, 2000, 2001 David E. Nelson
+ * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
*
- * David E. Nelson (dnelson@jump.net)
+ * Brian Beattie <beattie@beattie-home.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -51,7 +51,7 @@
static __s32 vendor=-1, product=-1, read_timeout=0;
-MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
+MODULE_AUTHOR("Brian Beattie, beattie@beattie-home.net");
MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);
MODULE_LICENSE("GPL");
@@ -144,6 +144,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
+ { USB_DEVICE(0x055f, 0x0218) }, /* BearPaw 2400 TA */
+ { USB_DEVICE(0x05d8, 0x4002) }, /* 1200 CU and 1200 UB Plus */
/* Plustek */
{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
{ USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */