This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / usb / core / message.c
index e0eacc2..18a5da4 100644 (file)
@@ -91,8 +91,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, NULL);
+       usb_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)
@@ -190,7 +190,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
                return -ENOMEM;
 
        usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
-                         usb_api_blocking_completion, NULL);
+                   usb_api_blocking_completion, 0);
 
        return usb_start_wait_urb(urb,timeout,actual_length);
 }
@@ -203,11 +203,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 = NULL;
+               io->urbs = 0;
        }
        if (io->dev->dev.dma_mask != 0)
                usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
-       io->dev = NULL;
+       io->dev = 0;
 }
 
 static void sg_complete (struct urb *urb, struct pt_regs *regs)
@@ -260,7 +260,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
                                found = 1;
                }
        }
-       urb->dev = NULL;
+       urb->dev = 0;
 
        /* on the last completion, signal usb_sg_wait() */
        io->bytes += urb->actual_length;
@@ -356,7 +356,7 @@ int usb_sg_init (
                        goto nomem;
                }
 
-               io->urbs [i]->dev = NULL;
+               io->urbs [i]->dev = 0;
                io->urbs [i]->pipe = pipe;
                io->urbs [i]->interval = period;
                io->urbs [i]->transfer_flags = urb_flags;
@@ -459,7 +459,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 = NULL;
+                       io->urbs [i]->dev = 0;
                        retval = 0;
                        i--;
                        yield ();
@@ -485,7 +485,7 @@ void usb_sg_wait (struct usb_sg_request *io)
                                complete (&io->complete);
                        spin_unlock_irq (&io->lock);
 
-                       io->urbs[i]->dev = NULL;
+                       io->urbs [i]->dev = 0;
                        io->urbs [i]->status = retval;
                        dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
                                __FUNCTION__, retval);
@@ -605,128 +605,12 @@ 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)
+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,
-                       HZ * USB_CTRL_GET_TIMEOUT);
-               if (!(result == 0 || result == -EPIPE))
-                       break;
-       }
-       return result;
-}
-
-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 < 0) {
-               rc = usb_get_string(dev, langid, index, buf, 2);
-               if (rc == 2)
-                       rc = usb_get_string(dev, langid, index, buf, buf[0]);
-       }
-
-       if (rc >= 0) {
-               /* There might be extra junk at the end of the descriptor */
-               if (buf[0] < rc)
-                       rc = buf[0];
-               if (rc < 2)
-                       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)
-{
-       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_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;
-
- errout:
-       kfree(tbuf);
-       return err;
+       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);
 }
 
 /**
@@ -954,7 +838,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                        put_device (&dev->actconfig->interface[i]->dev);
                        dev->actconfig->interface[i] = NULL;
                }
-               dev->actconfig = NULL;
+               dev->actconfig = 0;
                if (dev->state == USB_STATE_CONFIGURED)
                        usb_set_device_state(dev, USB_STATE_ADDRESS);
        }
@@ -1373,6 +1257,102 @@ free_interfaces:
        return ret;
 }
 
+/**
+ * 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;
+
+       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_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);
+               }
+       }
+
+       /*
+        * ask for the length of the string 
+        */
+
+       err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
+       if (err == -EPIPE || err == 0) {
+               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 || err == 0) {
+               dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len);
+               err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
+       }
+       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);