ChangeSet 1.1743.3.13, 2004/05/25 11:37:59-07:00, stern@rowland.harvard.edu

[PATCH] USB: Initially read 9 bytes of config descriptor

This patch reads the full 9 bytes of a configuration descriptor during
enumeration rather than just the first 8 bytes.  That's how Windows does
it, and today I ran across a device that doesn't work properly when asked
to send only 8 bytes worth.  I doubt very much this will cause any
problems with currently-working devices; since the descriptor itself is 9
bytes long and since the devices are most likely to expect a 9-byte
request, anything that can handle an 8-byte request should have no
difficulty.  (Also, some debugging messages have been slightly improved.)

Incidentally, USB traces taken from Windows 2000 and Windows XP show that
when those operating systems retrieve a string descriptor during
enumeration, they do so by requesting a 255-byte transfer.  They do not
first ask just for the initial 2 bytes (which contain the actual length)
and then ask for the actual length, which is what we do.  Interestingly,
back in 2.4 we _did_ do things the same as Windows.


 drivers/usb/core/config.c |   17 +++++++++--------
 1 files changed, 9 insertions(+), 8 deletions(-)


diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c	Fri May 28 14:40:51 2004
+++ b/drivers/usb/core/config.c	Fri May 28 14:40:51 2004
@@ -465,23 +465,24 @@
 		goto err2;
 	memset(dev->rawdescriptors, 0, length);
 
-	buffer = kmalloc(8, GFP_KERNEL);
+	buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
 	if (!buffer)
 		goto err2;
 	desc = (struct usb_config_descriptor *)buffer;
 
 	for (cfgno = 0; cfgno < ncfg; cfgno++) {
-		/* We grab the first 8 bytes so we know how long the whole */
-		/* configuration is */
+		/* We grab just the first descriptor so we know how long
+		 * the whole configuration is */
 		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
-		    buffer, 8);
+		    buffer, USB_DT_CONFIG_SIZE);
 		if (result < 0) {
 			dev_err(ddev, "unable to read config index %d "
-			    "descriptor\n", cfgno);
+			    "descriptor/%s\n", cfgno, "start");
 			goto err;
-		} else if (result < 8) {
+		} else if (result < 4) {
 			dev_err(ddev, "config index %d descriptor too short "
-			    "(expected %i, got %i)\n", cfgno, 8, result);
+			    "(expected %i, got %i)\n", cfgno,
+			    USB_DT_CONFIG_SIZE, result);
 			result = -EINVAL;
 			goto err;
 		}
@@ -498,7 +499,7 @@
 		    bigbuffer, length);
 		if (result < 0) {
 			dev_err(ddev, "unable to read config index %d "
-			    "descriptor\n", cfgno);
+			    "descriptor/%s\n", cfgno, "all");
 			kfree(bigbuffer);
 			goto err;
 		}
