Re: Using default LANGID = 0 causes a regression

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jul 10, 2009 at 11:36:20AM +0300, jouni wrote:
> On Friday 10 July 2009 11:16:08 Daniel Mack wrote:
> > On Fri, Jul 10, 2009 at 11:04:13AM +0300, jouni wrote:
> > > I just tested this patch and it works for me.
> >
> > Thanks for testing! Could you provide the dmesg output?

Ok thanks. Below is the patch with a changelog.

Thanks everyone :)

Daniel


commit 87803165ad7727fbb1576294bff2d9d1e9b95827
Author: Daniel Mack <daniel@xxxxxxxx>
Date:   Fri Jul 10 10:53:07 2009 +0200

    USB: fix LANGID=0 regression
    
    commit b7af0bb ("USB: allow malformed LANGID descriptors") broke support
    for devices without string descriptor support.
    
    Reporting string descriptors is optional to USB devices, and a device
    lets us know it can't deal with strings by responding to the LANGID
    request with a STALL token.
    
    The kernel handled that correctly before b7af0bb came in, but failed
    hard if the LANGID was reported but broken. More than that, if a device
    was not able to provide string descriptors, the LANGID was retrieved
    over and over again at each string read request.
    
    This patch changes the behaviour so that
    
     a) the LANGID is only queried once
     b) devices which can't handle string requests are not asked again
     c) devices with malformed LANGID values have a sane fallback to 0x0409
    
    Signed-off-by: Daniel Mack <daniel@xxxxxxxx>

diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 2bed83c..9720e69 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)
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux