Re: Using default LANGID = 0 causes a regression

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

 



On Thu, Jul 09, 2009 at 11:04:05AM -0400, Alan Stern wrote:
> Your "USB: allow malformed LANGID descriptors" patch (commit 
> b7af0bb26899bb47ae16fb41d2296111b0784a56) is causing a regression:
> 
> 	http://bugzilla.kernel.org/show_bug.cgi?id=13700
> 
> The usbmon log attached to comment #11 shows how the 5-2 device 
> doesn't work with this patch.  It rejects attempts to read string 0 
> (the language ID list) with a STALL, and it crashes when the kernel 
> attempts to read a string using language 0.

Ok, let me get this straight.

The device STALLS EP0 when asked for string descriptor 0, so it tells
it's not willing to hand out any string at all. Haven't checked with the
USB specs whether this is correct behaviour, but this is what it looks
like.

When an endpoint communication stalls, the return value is -EPIPE, and
in case of a malformed string descriptor we seem to be getting -ENODATA.

Handling those two case seperately should make both sides happy.

Could you test the patch below? It's only compile tested for now.

Thanks,
Daniel


diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 2bed83c..5deb286 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -840,20 +840,29 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 	/* 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) {
+
+		if (err == -ENODATA || err < 4) {
+			/* the string was reported, but is malformed.
+			 * default to english in this case */
+			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);
+		} else if (err < 0) {
+			/* in case of all other errors, don't set have_langid
+			 * so we won't retrieve any strings from the device */
 			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);
+			dev->have_langid = 1;
 			/* always use the first langid listed */
 			dev_dbg(&dev->dev, "default language 0x%04x\n",
 				dev->string_langid);
 		}
-
-		dev->have_langid = 1;
 	}
 
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
--
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