Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / usb / core / message.c
index fad1c22..4cc8d3e 100644 (file)
@@ -2,14 +2,6 @@
  * message.c - synchronous message handling
  */
 
-#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pci.h> /* for scatterlist macros */
 #include <linux/usb.h>
 #include <linux/module.h>
@@ -17,7 +9,10 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
 #include <asm/byteorder.h>
+#include <asm/scatterlist.h>
 
 #include "hcd.h"       /* for usbcore internals */
 #include "usb.h"
@@ -32,10 +27,6 @@ static void timeout_kill(unsigned long data)
 {
        struct urb      *urb = (struct urb *) data;
 
-       dev_warn(&urb->dev->dev, "%s timeout on ep%d%s\n",
-               usb_pipecontrol(urb->pipe) ? "control" : "bulk",
-               usb_pipeendpoint(urb->pipe),
-               usb_pipein(urb->pipe) ? "in" : "out");
        usb_unlink_urb(urb);
 }
 
@@ -50,14 +41,13 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
 
        init_completion(&done);         
        urb->context = &done;
-       urb->transfer_flags |= URB_ASYNC_UNLINK;
        urb->actual_length = 0;
        status = usb_submit_urb(urb, GFP_NOIO);
 
        if (status == 0) {
                if (timeout > 0) {
                        init_timer(&timer);
-                       timer.expires = jiffies + timeout;
+                       timer.expires = jiffies + msecs_to_jiffies(timeout);
                        timer.data = (unsigned long)urb;
                        timer.function = timeout_kill;
                        /* grr.  timeout _should_ include submit delays. */
@@ -66,8 +56,20 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
                wait_for_completion(&done);
                status = urb->status;
                /* note:  HCDs return ETIMEDOUT for other reasons too */
-               if (status == -ECONNRESET)
-                       status = -ETIMEDOUT;
+               if (status == -ECONNRESET) {
+                       dev_dbg(&urb->dev->dev,
+                               "%s timed out on ep%d%s len=%d/%d\n",
+                               current->comm,
+                               usb_pipeendpoint(urb->pipe),
+                               usb_pipein(urb->pipe) ? "in" : "out",
+                               urb->actual_length,
+                               urb->transfer_buffer_length
+                               );
+                       if (urb->actual_length > 0)
+                               status = 0;
+                       else
+                               status = -ETIMEDOUT;
+               }
                if (timeout > 0)
                        del_timer_sync(&timer);
        }
@@ -80,8 +82,10 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
 
 /*-------------------------------------------------------------------*/
 // 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)
+static 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;
@@ -91,8 +95,8 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
        if (!urb)
                return -ENOMEM;
   
-       usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
-                  usb_api_blocking_completion, 0);
+       usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
+                            len, usb_api_blocking_completion, NULL);
 
        retv = usb_start_wait_urb(urb, timeout, &length);
        if (retv < 0)
@@ -111,7 +115,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
  *     @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
+ *     @timeout: time in msecs to wait for the message to complete before
  *             timing out (if 0 the wait is forever)
  *     Context: !in_interrupt ()
  *
@@ -152,6 +156,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
 }
 
 
+/**
+ * usb_interrupt_msg - Builds an interrupt 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 msecs to wait for the message to complete before
+ *     timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple interrupt 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() If a thread in your
+ * driver uses this call, make sure your disconnect() method can wait for it to
+ * complete.  Since you don't have a handle on the URB used, you can't cancel
+ * the request.
+ */
+int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
+                     void *data, int len, int *actual_length, int timeout)
+{
+       return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout);
+}
+EXPORT_SYMBOL_GPL(usb_interrupt_msg);
+
 /**
  *     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
@@ -159,7 +194,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  *     @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
+ *     @timeout: time in msecs to wait for the message to complete before
  *             timing out (if 0 the wait is forever)
  *     Context: !in_interrupt ()
  *
@@ -176,23 +211,39 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  *      If a thread in your driver uses this call, make sure your disconnect()
  *      method can wait for it to complete.  Since you don't have a handle on
  *      the URB used, you can't cancel the request.
+ *
+ *     Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
+ *     ioctl, users are forced to abuse this routine by using it to submit
+ *     URBs for interrupt endpoints.  We will take the liberty of creating
+ *     an interrupt URB (with the default interval) if the target is an
+ *     interrupt endpoint.
  */
 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
                        void *data, int len, int *actual_length, int timeout)
 {
        struct urb *urb;
+       struct usb_host_endpoint *ep;
 
-       if (len < 0)
+       ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
+                       [usb_pipeendpoint(pipe)];
+       if (!ep || len < 0)
                return -EINVAL;
 
-       urb=usb_alloc_urb(0, GFP_KERNEL);
+       urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb)
                return -ENOMEM;
 
-       usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
-                   usb_api_blocking_completion, 0);
-
-       return usb_start_wait_urb(urb,timeout,actual_length);
+       if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_INT) {
+               pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+               usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL,
+                               ep->desc.bInterval);
+       } else
+               usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL);
+
+       return usb_start_wait_urb(urb, timeout, actual_length);
 }
 
 /*-------------------------------------------------------------------*/
@@ -203,11 +254,11 @@ static void sg_clean (struct usb_sg_request *io)
                while (io->entries--)
                        usb_free_urb (io->urbs [io->entries]);
                kfree (io->urbs);
-               io->urbs = 0;
+               io->urbs = NULL;
        }
-       if (io->dev->dev.dma_mask != 0)
+       if (io->dev->dev.dma_mask != NULL)
                usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
-       io->dev = 0;
+       io->dev = NULL;
 }
 
 static void sg_complete (struct urb *urb, struct pt_regs *regs)
@@ -239,28 +290,33 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
                // BUG ();
        }
 
-       if (urb->status && urb->status != -ECONNRESET) {
+       if (io->status == 0 && urb->status && urb->status != -ECONNRESET) {
                int             i, found, status;
 
                io->status = urb->status;
 
                /* the previous urbs, and this one, completed already.
                 * unlink pending urbs so they won't rx/tx bad data.
+                * careful: unlink can sometimes be synchronous...
                 */
+               spin_unlock (&io->lock);
                for (i = 0, found = 0; i < io->entries; i++) {
-                       if (!io->urbs [i])
+                       if (!io->urbs [i] || !io->urbs [i]->dev)
                                continue;
                        if (found) {
                                status = usb_unlink_urb (io->urbs [i]);
-                               if (status != -EINPROGRESS && status != -EBUSY)
+                               if (status != -EINPROGRESS
+                                               && status != -ENODEV
+                                               && status != -EBUSY)
                                        dev_err (&io->dev->dev,
                                                "%s, unlink --> %d\n",
                                                __FUNCTION__, status);
                        } else if (urb == io->urbs [i])
                                found = 1;
                }
+               spin_lock (&io->lock);
        }
-       urb->dev = 0;
+       urb->dev = NULL;
 
        /* on the last completion, signal usb_sg_wait() */
        io->bytes += urb->actual_length;
@@ -305,7 +361,7 @@ int usb_sg_init (
        struct scatterlist      *sg,
        int                     nents,
        size_t                  length,
-       int                     mem_flags
+       gfp_t                   mem_flags
 )
 {
        int                     i;
@@ -327,7 +383,7 @@ int usb_sg_init (
        /* not all host controllers use DMA (like the mainstream pci ones);
         * they can use PIO (sl811) or be software over another transport.
         */
-       dma = (dev->dev.dma_mask != 0);
+       dma = (dev->dev.dma_mask != NULL);
        if (dma)
                io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
        else
@@ -337,17 +393,16 @@ int usb_sg_init (
        if (io->entries <= 0)
                return io->entries;
 
-       io->count = 0;
+       io->count = io->entries;
        io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
        if (!io->urbs)
                goto nomem;
 
-       urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
-                       | URB_NO_INTERRUPT;
+       urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
        if (usb_pipein (pipe))
                urb_flags |= URB_SHORT_NOT_OK;
 
-       for (i = 0; i < io->entries; i++, io->count = i) {
+       for (i = 0; i < io->entries; i++) {
                unsigned                len;
 
                io->urbs [i] = usb_alloc_urb (0, mem_flags);
@@ -356,7 +411,7 @@ int usb_sg_init (
                        goto nomem;
                }
 
-               io->urbs [i]->dev = 0;
+               io->urbs [i]->dev = NULL;
                io->urbs [i]->pipe = pipe;
                io->urbs [i]->interval = period;
                io->urbs [i]->transfer_flags = urb_flags;
@@ -416,7 +471,7 @@ nomem:
  * (2) error, where io->status is a negative errno value.  The number
  *     of io->bytes transferred before the error is usually less
  *     than requested, and can be nonzero.
- * (3) cancelation, a type of error with status -ECONNRESET that
+ * (3) cancellation, a type of error with status -ECONNRESET that
  *     is initiated by usb_sg_cancel().
  *
  * When this function returns, all memory allocated through usb_sg_init() or
@@ -459,7 +514,7 @@ void usb_sg_wait (struct usb_sg_request *io)
                case -ENXIO:    // hc didn't queue this one
                case -EAGAIN:
                case -ENOMEM:
-                       io->urbs [i]->dev = 0;
+                       io->urbs[i]->dev = NULL;
                        retval = 0;
                        i--;
                        yield ();
@@ -477,24 +532,19 @@ void usb_sg_wait (struct usb_sg_request *io)
 
                        /* fail any uncompleted urbs */
                default:
-                       spin_lock_irq (&io->lock);
-                       io->count -= entries - i;
-                       if (io->status == -EINPROGRESS)
-                               io->status = retval;
-                       if (io->count == 0)
-                               complete (&io->complete);
-                       spin_unlock_irq (&io->lock);
-
-                       io->urbs [i]->dev = 0;
+                       io->urbs [i]->dev = NULL;
                        io->urbs [i]->status = retval;
                        dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
                                __FUNCTION__, retval);
                        usb_sg_cancel (io);
                }
                spin_lock_irq (&io->lock);
-               if (retval && io->status == -ECONNRESET)
+               if (retval && (io->status == 0 || io->status == -ECONNRESET))
                        io->status = retval;
        }
+       io->count -= entries - i;
+       if (io->count == 0)
+               complete (&io->complete);
        spin_unlock_irq (&io->lock);
 
        /* OK, yes, this could be packaged as non-blocking.
@@ -525,6 +575,7 @@ void usb_sg_cancel (struct usb_sg_request *io)
                int     i;
 
                io->status = -ECONNRESET;
+               spin_unlock (&io->lock);
                for (i = 0; i < io->entries; i++) {
                        int     retval;
 
@@ -535,6 +586,7 @@ void usb_sg_cancel (struct usb_sg_request *io)
                                dev_warn (&io->dev->dev, "%s, unlink --> %d\n",
                                        __FUNCTION__, retval);
                }
+               spin_lock (&io->lock);
        }
        spin_unlock_irqrestore (&io->lock, flags);
 }
@@ -552,8 +604,7 @@ void usb_sg_cancel (struct usb_sg_request *io)
  *
  * Gets a USB descriptor.  Convenience functions exist to simplify
  * getting some types of descriptors.  Use
- * usb_get_device_descriptor() for USB_DT_DEVICE (not exported),
- * and usb_get_string() or usb_string() for USB_DT_STRING.
+ * usb_get_string() or usb_string() for USB_DT_STRING.
  * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG)
  * are part of the device structure.
  * In addition to a number of USB-standard descriptors, some
@@ -566,22 +617,24 @@ void usb_sg_cancel (struct usb_sg_request *io)
  */
 int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
 {
-       int i = 5;
+       int i;
        int result;
        
        memset(buf,0,size);     // Make sure we parse really received data
 
-       while (i--) {
+       for (i = 0; i < 3; ++i) {
                /* retry on length 0 or stall; some devices are flakey */
-               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;
-
-               dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result);
-               result = -ENOMSG;
+               result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                               USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+                               (type << 8) + index, 0, buf, size,
+                               USB_CTRL_GET_TIMEOUT);
+               if (result == 0 || result == -EPIPE)
+                       continue;
+               if (result > 1 && ((u8 *)buf)[1] != type) {
+                       result = -EPROTO;
+                       continue;
+               }
+               break;
        }
        return result;
 }
@@ -608,16 +661,183 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
  * 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)
+static int usb_get_string(struct usb_device *dev, unsigned short langid,
+                         unsigned char index, void *buf, int size)
+{
+       int i;
+       int result;
+
+       for (i = 0; i < 3; ++i) {
+               /* retry on length 0 or stall; some devices are flakey */
+               result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+                       (USB_DT_STRING << 8) + index, langid, buf, size,
+                       USB_CTRL_GET_TIMEOUT);
+               if (!(result == 0 || result == -EPIPE))
+                       break;
+       }
+       return result;
+}
+
+static void usb_try_string_workarounds(unsigned char *buf, int *length)
+{
+       int newlength, oldlength = *length;
+
+       for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
+               if (!isprint(buf[newlength]) || buf[newlength + 1])
+                       break;
+
+       if (newlength > 2) {
+               buf[0] = newlength;
+               *length = newlength;
+       }
+}
+
+static int usb_string_sub(struct usb_device *dev, unsigned int langid,
+               unsigned int index, unsigned char *buf)
+{
+       int rc;
+
+       /* Try to read the string descriptor by asking for the maximum
+        * possible number of bytes */
+       rc = usb_get_string(dev, langid, index, buf, 255);
+
+       /* If that failed try to read the descriptor length, then
+        * ask for just that many bytes */
+       if (rc < 2) {
+               rc = usb_get_string(dev, langid, index, buf, 2);
+               if (rc == 2)
+                       rc = usb_get_string(dev, langid, index, buf, buf[0]);
+       }
+
+       if (rc >= 2) {
+               if (!buf[0] && !buf[1])
+                       usb_try_string_workarounds(buf, &rc);
+
+               /* There might be extra junk at the end of the descriptor */
+               if (buf[0] < rc)
+                       rc = buf[0];
+
+               rc = rc - (rc & 1); /* force a multiple of two */
+       }
+
+       if (rc < 2)
+               rc = (rc < 0 ? rc : -EINVAL);
+
+       return rc;
+}
+
+/**
+ * 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)
 {
-       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);
+       unsigned char *tbuf;
+       int err;
+       unsigned int u, idx;
+
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+       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_string_sub(dev, 0, 0, tbuf);
+               if (err < 0) {
+                       dev_err (&dev->dev,
+                               "string descriptor 0 read error: %d\n",
+                               err);
+                       goto errout;
+               } else if (err < 4) {
+                       dev_err (&dev->dev, "string descriptor 0 too short\n");
+                       err = -EINVAL;
+                       goto errout;
+               } else {
+                       dev->have_langid = -1;
+                       dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+                               /* always use the first langid listed */
+                       dev_dbg (&dev->dev, "default language 0x%04x\n",
+                               dev->string_langid);
+               }
+       }
+       
+       err = usb_string_sub(dev, dev->string_langid, index, tbuf);
+       if (err < 0)
+               goto errout;
+
+       size--;         /* leave room for trailing NULL char in output buffer */
+       for (idx = 0, u = 2; u < err; u += 2) {
+               if (idx >= size)
+                       break;
+               if (tbuf[u+1])                  /* high byte */
+                       buf[idx++] = '?';  /* non ISO-8859-1 character */
+               else
+                       buf[idx++] = tbuf[u];
+       }
+       buf[idx] = 0;
+       err = idx;
+
+       if (tbuf[1] != USB_DT_STRING)
+               dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf);
+
+ errout:
+       kfree(tbuf);
+       return err;
 }
 
 /**
- * usb_get_device_descriptor - (re)reads the device descriptor
+ * usb_cache_string - read a string descriptor and cache it for later use
+ * @udev: the device whose string descriptor is being read
+ * @index: the descriptor index
+ *
+ * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
+ * or NULL if the index is 0 or the string could not be read.
+ */
+char *usb_cache_string(struct usb_device *udev, int index)
+{
+       char *buf;
+       char *smallbuf = NULL;
+       int len;
+
+       if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
+               if ((len = usb_string(udev, index, buf, 256)) > 0) {
+                       if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+                               return buf;
+                       memcpy(smallbuf, buf, len);
+               }
+               kfree(buf);
+       }
+       return smallbuf;
+}
+
+/*
+ * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
  * @dev: the device whose device descriptor is being updated
  * @size: how much of the descriptor to read
  * Context: !in_interrupt ()
@@ -649,13 +869,8 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
                return -ENOMEM;
 
        ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
-       if (ret >= 0) {
-               le16_to_cpus(&desc->bcdUSB);
-               le16_to_cpus(&desc->idVendor);
-               le16_to_cpus(&desc->idProduct);
-               le16_to_cpus(&desc->bcdDevice);
+       if (ret >= 0) 
                memcpy(&dev->descriptor, desc, size);
-       }
        kfree(desc);
        return ret;
 }
@@ -684,9 +899,19 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
  */
 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);
+       int ret;
+       u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
+
+       if (!status)
+               return -ENOMEM;
+
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
+               sizeof(*status), USB_CTRL_GET_TIMEOUT);
+
+       *(u16 *)data = *status;
+       kfree(status);
+       return ret;
 }
 
 /**
@@ -727,7 +952,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
                USB_ENDPOINT_HALT, endp, NULL, 0,
-               HZ * USB_CTRL_SET_TIMEOUT);
+               USB_CTRL_SET_TIMEOUT);
 
        /* don't un-halt or force to DATA0 except on success */
        if (result < 0)
@@ -741,9 +966,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
         * the copy in usb-storage, for as long as we need two copies.
         */
 
-       /* toggle was reset by the clear, then ep was reactivated */
+       /* toggle was reset by the clear */
        usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-       usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
        return 0;
 }
@@ -757,25 +981,26 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
  * Deallocates hcd/hardware state for this endpoint ... and nukes all
  * pending urbs.
  *
- * If the HCD hasn't registered a disable() function, this marks the
- * endpoint as halted and sets its maxpacket size to 0 to prevent
- * further submissions.
+ * If the HCD hasn't registered a disable() function, this sets the
+ * endpoint's maxpacket size to 0 to prevent further submissions.
  */
 void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
 {
-       if (dev && dev->bus && dev->bus->op && dev->bus->op->disable)
-               dev->bus->op->disable(dev, epaddr);
-       else {
-               unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
-
-               if (usb_endpoint_out(epaddr)) {
-                       usb_endpoint_halt(dev, epnum, 1);
-                       dev->epmaxpacketout[epnum] = 0;
-               } else {
-                       usb_endpoint_halt(dev, epnum, 0);
-                       dev->epmaxpacketin[epnum] = 0;
-               }
+       unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+       struct usb_host_endpoint *ep;
+
+       if (!dev)
+               return;
+
+       if (usb_endpoint_out(epaddr)) {
+               ep = dev->ep_out[epnum];
+               dev->ep_out[epnum] = NULL;
+       } else {
+               ep = dev->ep_in[epnum];
+               dev->ep_in[epnum] = NULL;
        }
+       if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
+               dev->bus->op->disable(dev, ep);
 }
 
 /**
@@ -796,10 +1021,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
        }
 }
 
-static void release_interface(struct device *dev)
-{
-}
-
 /*
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
@@ -821,7 +1042,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                usb_disable_endpoint(dev, i + USB_DIR_IN);
        }
        dev->toggle[0] = dev->toggle[1] = 0;
-       dev->halted[0] = dev->halted[1] = 0;
 
        /* getting rid of interfaces will disconnect
         * any drivers bound to them (a key side effect)
@@ -830,15 +1050,26 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
                        struct usb_interface    *interface;
 
-                       /* remove this interface */
+                       /* remove this interface if it has been registered */
                        interface = dev->actconfig->interface[i];
+                       if (!device_is_registered(&interface->dev))
+                               continue;
                        dev_dbg (&dev->dev, "unregistering interface %s\n",
                                interface->dev.bus_id);
-                       device_unregister (&interface->dev);
+                       usb_remove_sysfs_intf_files(interface);
+                       device_del (&interface->dev);
+               }
+
+               /* Now that the interfaces are unbound, nobody should
+                * try to access them.
+                */
+               for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+                       put_device (&dev->actconfig->interface[i]->dev);
+                       dev->actconfig->interface[i] = NULL;
                }
-               dev->actconfig = 0;
+               dev->actconfig = NULL;
                if (dev->state == USB_STATE_CONFIGURED)
-                       dev->state = USB_STATE_ADDRESS;
+                       usb_set_device_state(dev, USB_STATE_ADDRESS);
        }
 }
 
@@ -846,30 +1077,27 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 /*
  * usb_enable_endpoint - Enable an endpoint for USB communications
  * @dev: the device whose interface is being enabled
- * @epd: pointer to the endpoint descriptor
+ * @ep: the endpoint
  *
- * Marks the endpoint as running, resets its toggle, and stores
- * its maxpacket value.  For control endpoints, both the input
- * and output sides are handled.
+ * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
+ * For control endpoints, both the input and output sides are handled.
  */
-void usb_enable_endpoint(struct usb_device *dev,
-               struct usb_endpoint_descriptor *epd)
+static void
+usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
 {
-       int maxsize = epd->wMaxPacketSize;
-       unsigned int epaddr = epd->bEndpointAddress;
+       unsigned int epaddr = ep->desc.bEndpointAddress;
        unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
-       int is_control = ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-                               USB_ENDPOINT_XFER_CONTROL);
+       int is_control;
 
+       is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                       == USB_ENDPOINT_XFER_CONTROL);
        if (usb_endpoint_out(epaddr) || is_control) {
-               usb_endpoint_running(dev, epnum, 1);
                usb_settoggle(dev, epnum, 1, 0);
-               dev->epmaxpacketout[epnum] = maxsize;
+               dev->ep_out[epnum] = ep;
        }
        if (!usb_endpoint_out(epaddr) || is_control) {
-               usb_endpoint_running(dev, epnum, 0);
                usb_settoggle(dev, epnum, 0, 0);
-               dev->epmaxpacketin[epnum] = maxsize;
+               dev->ep_in[epnum] = ep;
        }
 }
 
@@ -880,14 +1108,14 @@ void usb_enable_endpoint(struct usb_device *dev,
  *
  * Enables all the endpoints for the interface's current altsetting.
  */
-void usb_enable_interface(struct usb_device *dev,
-               struct usb_interface *intf)
+static void usb_enable_interface(struct usb_device *dev,
+                                struct usb_interface *intf)
 {
        struct usb_host_interface *alt = intf->cur_altsetting;
        int i;
 
        for (i = 0; i < alt->desc.bNumEndpoints; ++i)
-               usb_enable_endpoint(dev, &alt->endpoint[i].desc);
+               usb_enable_endpoint(dev, &alt->endpoint[i]);
 }
 
 /**
@@ -930,6 +1158,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
        int ret;
        int manual = 0;
 
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+
        iface = usb_ifnum_to_if(dev, interface);
        if (!iface) {
                dev_dbg(&dev->dev, "selecting invalid interface %d\n",
@@ -945,7 +1176,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
-                                  alternate, interface, NULL, 0, HZ * 5);
+                                  alternate, interface, NULL, 0, 5000);
 
        /* 9.4.10 says devices don't need this and are free to STALL the
         * request if the interface only has one alternate setting.
@@ -965,6 +1196,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         */
 
        /* prevent submissions using previous endpoint settings */
+       if (device_is_registered(&iface->dev))
+               usb_remove_sysfs_intf_files(iface);
        usb_disable_interface(dev, iface);
 
        iface->cur_altsetting = alt;
@@ -1000,6 +1233,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         * (Likewise, EP0 never "halts" on well designed devices.)
         */
        usb_enable_interface(dev, iface);
+       if (device_is_registered(&iface->dev))
+               usb_create_sysfs_intf_files(iface);
 
        return 0;
 }
@@ -1017,9 +1252,13 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  *
  * Because this affects multiple interfaces, avoid using this with composite
  * (multi-interface) devices.  Instead, the driver for each interface may
- * use usb_set_interface() on the interfaces it claims.  Resetting the whole
+ * use usb_set_interface() on the interfaces it claims.  Be careful though;
+ * some devices don't support the SET_INTERFACE request, and others won't
+ * reset all the interface state (notably data toggles).  Resetting the whole
  * configuration would affect other drivers' interfaces.
  *
+ * The caller must own the device lock.
+ *
  * Returns zero on success, else a negative error code.
  */
 int usb_reset_configuration(struct usb_device *dev)
@@ -1027,9 +1266,12 @@ int usb_reset_configuration(struct usb_device *dev)
        int                     i, retval;
        struct usb_host_config  *config;
 
-       /* caller must own dev->serialize (config won't change)
-        * and the usb bus readlock (so driver bindings are stable);
-        * so calls during probe() are fine
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+
+       /* caller must have locked the device and must own
+        * the usb bus readlock (so driver bindings are stable);
+        * calls during probe() are fine
         */
 
        for (i = 1; i < 16; ++i) {
@@ -1041,20 +1283,19 @@ int usb_reset_configuration(struct usb_device *dev)
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        USB_REQ_SET_CONFIGURATION, 0,
                        config->desc.bConfigurationValue, 0,
-                       NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-       if (retval < 0) {
-               dev->state = USB_STATE_ADDRESS;
+                       NULL, 0, USB_CTRL_SET_TIMEOUT);
+       if (retval < 0)
                return retval;
-       }
 
        dev->toggle[0] = dev->toggle[1] = 0;
-       dev->halted[0] = dev->halted[1] = 0;
 
        /* re-init hc/hcd interface/endpoint state */
        for (i = 0; i < config->desc.bNumInterfaces; i++) {
                struct usb_interface *intf = config->interface[i];
                struct usb_host_interface *alt;
 
+               if (device_is_registered(&intf->dev))
+                       usb_remove_sysfs_intf_files(intf);
                alt = usb_altnum_to_altsetting(intf, 0);
 
                /* No altsetting 0?  We'll assume the first altsetting.
@@ -1067,15 +1308,27 @@ int usb_reset_configuration(struct usb_device *dev)
 
                intf->cur_altsetting = alt;
                usb_enable_interface(dev, intf);
+               if (device_is_registered(&intf->dev))
+                       usb_create_sysfs_intf_files(intf);
        }
        return 0;
 }
 
+static void release_interface(struct device *dev)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct usb_interface_cache *intfc =
+                       altsetting_to_usb_interface_cache(intf->altsetting);
+
+       kref_put(&intfc->ref, usb_release_interface_cache);
+       kfree(intf);
+}
+
 /*
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
  * @configuration: the configuration being chosen.
- * Context: !in_interrupt(), caller holds dev->serialize
+ * Context: !in_interrupt(), caller owns the device lock
  *
  * This is used to enable non-default device modes.  Not all devices
  * use this kind of configurability; many devices only have one
@@ -1096,11 +1349,11 @@ int usb_reset_configuration(struct usb_device *dev)
  * usb_set_interface().
  *
  * This call is synchronous. The calling context must be able to sleep,
- * and must not hold the driver model lock for USB; usb device driver
- * probe() methods may not use this routine.
+ * must own the device lock, and must not hold the driver model's USB
+ * bus rwsem; usb device driver probe() methods cannot use this routine.
  *
  * Returns zero on success, or else the status code returned by the
- * underlying call that failed.  On succesful completion, each interface
+ * underlying call that failed.  On successful completion, each interface
  * in the original device configuration has been destroyed, and each one
  * in the new configuration has been probed by all relevant usb device
  * drivers currently known to the kernel.
@@ -1109,19 +1362,17 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
 {
        int i, ret;
        struct usb_host_config *cp = NULL;
-       
-       /* dev->serialize guards all config changes */
+       struct usb_interface **new_interfaces = NULL;
+       int n, nintf;
 
-       for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
+       for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
                if (dev->config[i].desc.bConfigurationValue == configuration) {
                        cp = &dev->config[i];
                        break;
                }
        }
-       if ((!cp && configuration != 0)) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if ((!cp && configuration != 0))
+               return -EINVAL;
 
        /* The USB spec says configuration 0 means unconfigured.
         * But if a device includes a configuration numbered 0,
@@ -1130,6 +1381,43 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        if (cp && configuration == 0)
                dev_warn(&dev->dev, "config 0 descriptor??\n");
 
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+
+       /* Allocate memory for new interfaces before doing anything else,
+        * so that if we run out then nothing will have changed. */
+       n = nintf = 0;
+       if (cp) {
+               nintf = cp->desc.bNumInterfaces;
+               new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
+                               GFP_KERNEL);
+               if (!new_interfaces) {
+                       dev_err(&dev->dev, "Out of memory");
+                       return -ENOMEM;
+               }
+
+               for (; n < nintf; ++n) {
+                       new_interfaces[n] = kzalloc(
+                                       sizeof(struct usb_interface),
+                                       GFP_KERNEL);
+                       if (!new_interfaces[n]) {
+                               dev_err(&dev->dev, "Out of memory");
+                               ret = -ENOMEM;
+free_interfaces:
+                               while (--n >= 0)
+                                       kfree(new_interfaces[n]);
+                               kfree(new_interfaces);
+                               return ret;
+                       }
+               }
+
+               i = dev->bus_mA - cp->desc.bMaxPower * 2;
+               if (i < 0)
+                       dev_warn(&dev->dev, "new config #%d exceeds power "
+                                       "limit by %dmA\n",
+                                       configuration, -i);
+       }
+
        /* if it's already configured, clear out old state first.
         * getting rid of old interfaces means unbinding their drivers.
         */
@@ -1138,170 +1426,86 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
 
        if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-                       NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
-               goto out;
+                       NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
 
-       dev->actconfig = cp;
-       if (!cp)
-               dev->state = USB_STATE_ADDRESS;
-       else {
-               dev->state = USB_STATE_CONFIGURED;
-
-               /* re-initialize hc/hcd/usbcore interface/endpoint state.
-                * this triggers binding of drivers to interfaces; and
-                * maybe probe() calls will choose different altsettings.
+               /* All the old state is gone, so what else can we do?
+                * The device is probably useless now anyway.
                 */
-               for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
-                       struct usb_interface *intf = cp->interface[i];
-                       struct usb_host_interface *alt;
-
-                       alt = usb_altnum_to_altsetting(intf, 0);
-
-                       /* No altsetting 0?  We'll assume the first altsetting.
-                        * We could use a GetInterface call, but if a device is
-                        * so non-compliant that it doesn't have altsetting 0
-                        * then I wouldn't trust its reply anyway.
-                        */
-                       if (!alt)
-                               alt = &intf->altsetting[0];
-
-                       intf->cur_altsetting = alt;
-                       usb_enable_interface(dev, intf);
-                       intf->dev.parent = &dev->dev;
-                       intf->dev.driver = NULL;
-                       intf->dev.bus = &usb_bus_type;
-                       intf->dev.dma_mask = dev->dev.dma_mask;
-                       intf->dev.release = release_interface;
-                       device_initialize (&intf->dev);
-                       sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
-                                dev->bus->busnum, dev->devpath,
-                                configuration,
-                                alt->desc.bInterfaceNumber);
-               }
-
-               /* Now that all interfaces are setup, probe() calls
-                * may claim() any interface that's not yet bound.
-                * Many class drivers need that: CDC, audio, video, etc.
-                */
-               for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
-                       struct usb_interface *intf = cp->interface[i];
-                       struct usb_interface_descriptor *desc;
-
-                       desc = &intf->altsetting [0].desc;
-                       dev_dbg (&dev->dev,
-                               "adding %s (config #%d, interface %d)\n",
-                               intf->dev.bus_id, configuration,
-                               desc->bInterfaceNumber);
-                       ret = device_add (&intf->dev);
-                       if (ret != 0) {
-                               dev_err(&dev->dev,
-                                       "device_add(%s) --> %d\n",
-                                       intf->dev.bus_id,
-                                       ret);
-                               continue;
-                       }
-                       usb_create_driverfs_intf_files (intf);
-               }
+               cp = NULL;
        }
 
-out:
-       return ret;
-}
+       dev->actconfig = cp;
+       if (!cp) {
+               usb_set_device_state(dev, USB_STATE_ADDRESS);
+               goto free_interfaces;
+       }
+       usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
-/**
- * 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, len;
-       unsigned int u, idx;
+       /* Initialize the new interface structures and the
+        * hc/hcd/usbcore interface/endpoint state.
+        */
+       for (i = 0; i < nintf; ++i) {
+               struct usb_interface_cache *intfc;
+               struct usb_interface *intf;
+               struct usb_host_interface *alt;
 
-       if (size <= 0 || !buf || !index)
-               return -EINVAL;
-       buf[0] = 0;
-       tbuf = kmalloc(256, GFP_KERNEL);
-       if (!tbuf)
-               return -ENOMEM;
+               cp->interface[i] = intf = new_interfaces[i];
+               intfc = cp->intf_cache[i];
+               intf->altsetting = intfc->altsetting;
+               intf->num_altsetting = intfc->num_altsetting;
+               kref_get(&intfc->ref);
 
-       /* get langid for strings if it's not yet known */
-       if (!dev->have_langid) {
-               err = usb_get_descriptor(dev, USB_DT_STRING, 0, tbuf, 4);
-               if (err < 0) {
-                       dev_err (&dev->dev,
-                               "string descriptor 0 read error: %d\n",
-                               err);
-                       goto errout;
-               } else if (err < 4 || tbuf[0] < 4) {
-                       dev_err (&dev->dev, "string descriptor 0 too short\n");
-                       err = -EINVAL;
-                       goto errout;
-               } else {
-                       dev->have_langid = -1;
-                       dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
-                               /* always use the first langid listed */
-                       dev_dbg (&dev->dev, "default language 0x%04x\n",
-                               dev->string_langid);
-               }
-       }
+               alt = usb_altnum_to_altsetting(intf, 0);
 
-       /*
-        * ask for the length of the string 
-        */
+               /* No altsetting 0?  We'll assume the first altsetting.
+                * We could use a GetInterface call, but if a device is
+                * so non-compliant that it doesn't have altsetting 0
+                * then I wouldn't trust its reply anyway.
+                */
+               if (!alt)
+                       alt = &intf->altsetting[0];
 
-       err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
-       if (err == -EPIPE) {
-               dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2);
-               err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
-       }
-       if(err<2)
-               goto errout;
-       len=tbuf[0];    
-       
-       err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
-       if (err == -EPIPE) {
-               dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len);
-               err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
+               intf->cur_altsetting = alt;
+               usb_enable_interface(dev, intf);
+               intf->dev.parent = &dev->dev;
+               intf->dev.driver = NULL;
+               intf->dev.bus = &usb_bus_type;
+               intf->dev.dma_mask = dev->dev.dma_mask;
+               intf->dev.release = release_interface;
+               device_initialize (&intf->dev);
+               mark_quiesced(intf);
+               sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
+                        dev->bus->busnum, dev->devpath,
+                        configuration, alt->desc.bInterfaceNumber);
        }
-       if (err < 0)
-               goto errout;
+       kfree(new_interfaces);
 
-       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];
+       if (cp->string == NULL)
+               cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
+
+       /* Now that all the interfaces are set up, register them
+        * to trigger binding of drivers to interfaces.  probe()
+        * routines may install different altsettings and may
+        * claim() any interfaces not yet bound.  Many class drivers
+        * need that: CDC, audio, video, etc.
+        */
+       for (i = 0; i < nintf; ++i) {
+               struct usb_interface *intf = cp->interface[i];
+
+               dev_dbg (&dev->dev,
+                       "adding %s (config #%d, interface %d)\n",
+                       intf->dev.bus_id, configuration,
+                       intf->cur_altsetting->desc.bInterfaceNumber);
+               ret = device_add (&intf->dev);
+               if (ret != 0) {
+                       dev_err(&dev->dev, "device_add(%s) --> %d\n",
+                               intf->dev.bus_id, ret);
+                       continue;
+               }
+               usb_create_sysfs_intf_files (intf);
        }
-       buf[idx] = 0;
-       err = idx;
 
- errout:
-       kfree(tbuf);
-       return err;
+       return 0;
 }
 
 // synchronous request completion model
@@ -1315,7 +1519,6 @@ EXPORT_SYMBOL(usb_sg_wait);
 // synchronous control message convenience routines
 EXPORT_SYMBOL(usb_get_descriptor);
 EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_get_string);
 EXPORT_SYMBOL(usb_string);
 
 // synchronous calls that also maintain usbcore state