summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/message.c63
1 files changed, 45 insertions, 18 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 2bed83caacb1..9720e699f472 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
return rc;
}
+static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
+{
+ int err;
+
+ if (dev->have_langid)
+ return 0;
+
+ if (dev->string_langid < 0)
+ return -EPIPE;
+
+ err = usb_string_sub(dev, 0, 0, tbuf);
+
+ /* If the string was reported but is malformed, default to english
+ * (0x0409) */
+ if (err == -ENODATA || (err > 0 && err < 4)) {
+ dev->string_langid = 0x0409;
+ dev->have_langid = 1;
+ dev_err(&dev->dev,
+ "string descriptor 0 malformed (err = %d), "
+ "defaulting to 0x%04x\n",
+ err, dev->string_langid);
+ return 0;
+ }
+
+ /* In case of all other errors, we assume the device is not able to
+ * deal with strings at all. Set string_langid to -1 in order to
+ * prevent any string to be retrieved from the device */
+ if (err < 0) {
+ dev_err(&dev->dev, "string descriptor 0 read error: %d\n",
+ err);
+ dev->string_langid = -1;
+ return -EPIPE;
+ }
+
+ /* always use the first langid listed */
+ dev->string_langid = tbuf[2] | (tbuf[3] << 8);
+ dev->have_langid = 1;
+ dev_dbg(&dev->dev, "default language 0x%04x\n",
+ dev->string_langid);
+ return 0;
+}
+
/**
* usb_string - returns UTF-8 version of a string descriptor
* @dev: the device whose string descriptor is being retrieved
@@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
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);
- } else if (err < 4) {
- dev_err(&dev->dev, "string descriptor 0 too short\n");
- } else {
- 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);
- }
-
- dev->have_langid = 1;
- }
+ err = usb_get_langid(dev, tbuf);
+ if (err < 0)
+ goto errout;
err = usb_string_sub(dev, dev->string_langid, index, tbuf);
if (err < 0)