aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-03-29 06:03:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:32 -0400
commit317149c655defedfaf432143b86a720cfc12a424 (patch)
treec9834f9813e14b595c93da5d7ceb718af39d1c5d
parent7f0ae3a8eeb7f231dc99cee7c871ba64e07ebefe (diff)
USB: Add a new quirk: USB_QUIRK_HONOR_BNUMINTERFACES
Add a new quirk USB_QUIRK_HONOR_BNUMINTERFACES, when this quirk is set and a device has more interface descriptors in a configuration then it claims to have in config->bNumInterfaces, ignore all additional interfaces. This is needed for devices which try to hide unused interfaces by only lowering config->bNumInterfaces, and which can't handle if you try to talk to the "hidden" interfaces. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/config.c16
-rw-r--r--drivers/usb/core/quirks.c4
-rw-r--r--include/linux/usb/quirks.h4
3 files changed, 22 insertions, 2 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 77e0dda3a2fb..16c1157be3fc 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -1,6 +1,7 @@
1#include <linux/usb.h> 1#include <linux/usb.h>
2#include <linux/usb/ch9.h> 2#include <linux/usb/ch9.h>
3#include <linux/usb/hcd.h> 3#include <linux/usb/hcd.h>
4#include <linux/usb/quirks.h>
4#include <linux/module.h> 5#include <linux/module.h>
5#include <linux/init.h> 6#include <linux/init.h>
6#include <linux/slab.h> 7#include <linux/slab.h>
@@ -479,9 +480,10 @@ skip_to_next_interface_descriptor:
479 return buffer - buffer0 + i; 480 return buffer - buffer0 + i;
480} 481}
481 482
482static int usb_parse_configuration(struct device *ddev, int cfgidx, 483static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
483 struct usb_host_config *config, unsigned char *buffer, int size) 484 struct usb_host_config *config, unsigned char *buffer, int size)
484{ 485{
486 struct device *ddev = &dev->dev;
485 unsigned char *buffer0 = buffer; 487 unsigned char *buffer0 = buffer;
486 int cfgno; 488 int cfgno;
487 int nintf, nintf_orig; 489 int nintf, nintf_orig;
@@ -550,6 +552,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
550 } 552 }
551 553
552 inum = d->bInterfaceNumber; 554 inum = d->bInterfaceNumber;
555
556 if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
557 n >= nintf_orig) {
558 dev_warn(ddev, "config %d has more interface "
559 "descriptors, than it declares in "
560 "bNumInterfaces, ignoring interface "
561 "number: %d\n", cfgno, inum);
562 continue;
563 }
564
553 if (inum >= nintf_orig) 565 if (inum >= nintf_orig)
554 dev_warn(ddev, "config %d has an invalid " 566 dev_warn(ddev, "config %d has an invalid "
555 "interface number: %d but max is %d\n", 567 "interface number: %d but max is %d\n",
@@ -801,7 +813,7 @@ int usb_get_configuration(struct usb_device *dev)
801 813
802 dev->rawdescriptors[cfgno] = bigbuffer; 814 dev->rawdescriptors[cfgno] = bigbuffer;
803 815
804 result = usb_parse_configuration(&dev->dev, cfgno, 816 result = usb_parse_configuration(dev, cfgno,
805 &dev->config[cfgno], bigbuffer, length); 817 &dev->config[cfgno], bigbuffer, length);
806 if (result < 0) { 818 if (result < 0) {
807 ++cfgno; 819 ++cfgno;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index f073c5cb4e7b..f22d03df8b17 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
71 /* SKYMEDI USB_DRIVE */ 71 /* SKYMEDI USB_DRIVE */
72 { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, 72 { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
73 73
74 /* BUILDWIN Photo Frame */
75 { USB_DEVICE(0x1908, 0x1315), .driver_info =
76 USB_QUIRK_HONOR_BNUMINTERFACES },
77
74 /* INTEL VALUE SSD */ 78 /* INTEL VALUE SSD */
75 { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, 79 { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
76 80
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 0a555dd131fc..16b7f3347545 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -22,4 +22,8 @@
22/*device will morph if reset, don't use reset for handling errors */ 22/*device will morph if reset, don't use reset for handling errors */
23#define USB_QUIRK_RESET_MORPHS 0x00000010 23#define USB_QUIRK_RESET_MORPHS 0x00000010
24 24
25/* device has more interface descriptions than the bNumInterfaces count,
26 and can't handle talking to these interfaces */
27#define USB_QUIRK_HONOR_BNUMINTERFACES 0x00000020
28
25#endif /* __LINUX_USB_QUIRKS_H */ 29#endif /* __LINUX_USB_QUIRKS_H */