summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-02-20 16:33:08 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-02-27 14:40:50 -0800
commit67f5a4ba9741fcef3f4db3509ad03565d9e33af2 (patch)
treebf27a10cfe13a95144e04cd50136a8f55e3b2a3c
parent54b9ed35aea88b05d711884a3c2dc21bba047bd8 (diff)
downloadlinux-3.10-67f5a4ba9741fcef3f4db3509ad03565d9e33af2.tar.gz
linux-3.10-67f5a4ba9741fcef3f4db3509ad03565d9e33af2.tar.bz2
linux-3.10-67f5a4ba9741fcef3f4db3509ad03565d9e33af2.zip
USB: usb_get_string should check the descriptor type
This patch (as1218) fixes a problem with a radio-control joystick used in the "walkera 4#3" helicopter. This device responds to the initial Get-String-Descriptor request for string 0 (which is really the list of supported languages) by sending its config descriptor! The usb_get_string() routine needs to check whether it got the right type of descriptor. Oddly enough, this sort of check is already present in usb_get_descriptor(). The patch changes the error code from -EPROTO to -ENODATA, because -EPROTO shows up in so many other contexts to indicate a hardware failure rather than a firmware error. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Tested-by: Guillermo Jarabo <williamjap@gmail.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ===================================================================
-rw-r--r--drivers/usb/core/message.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 31fb204f44c..49e7f56e0d7 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
if (result <= 0 && result != -ETIMEDOUT)
continue;
if (result > 1 && ((u8 *)buf)[1] != type) {
- result = -EPROTO;
+ result = -ENODATA;
continue;
}
break;
@@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(USB_DT_STRING << 8) + index, langid, buf, size,
USB_CTRL_GET_TIMEOUT);
- if (!(result == 0 || result == -EPIPE))
- break;
+ if (result == 0 || result == -EPIPE)
+ continue;
+ if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
+ result = -ENODATA;
+ continue;
+ }
+ break;
}
return result;
}