Commit 317149c6 authored by Hans de Goede's avatar Hans de Goede Committed by Greg Kroah-Hartman

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: default avatarHans de Goede <hdegoede@redhat.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 7f0ae3a8
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/hcd.h> #include <linux/usb/hcd.h>
#include <linux/usb/quirks.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -479,9 +480,10 @@ static int usb_parse_interface(struct device *ddev, int cfgno, ...@@ -479,9 +480,10 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
return buffer - buffer0 + i; return buffer - buffer0 + i;
} }
static int usb_parse_configuration(struct device *ddev, int cfgidx, static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
struct usb_host_config *config, unsigned char *buffer, int size) struct usb_host_config *config, unsigned char *buffer, int size)
{ {
struct device *ddev = &dev->dev;
unsigned char *buffer0 = buffer; unsigned char *buffer0 = buffer;
int cfgno; int cfgno;
int nintf, nintf_orig; int nintf, nintf_orig;
...@@ -550,6 +552,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx, ...@@ -550,6 +552,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
} }
inum = d->bInterfaceNumber; inum = d->bInterfaceNumber;
if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
n >= nintf_orig) {
dev_warn(ddev, "config %d has more interface "
"descriptors, than it declares in "
"bNumInterfaces, ignoring interface "
"number: %d\n", cfgno, inum);
continue;
}
if (inum >= nintf_orig) if (inum >= nintf_orig)
dev_warn(ddev, "config %d has an invalid " dev_warn(ddev, "config %d has an invalid "
"interface number: %d but max is %d\n", "interface number: %d but max is %d\n",
...@@ -801,7 +813,7 @@ int usb_get_configuration(struct usb_device *dev) ...@@ -801,7 +813,7 @@ int usb_get_configuration(struct usb_device *dev)
dev->rawdescriptors[cfgno] = bigbuffer; dev->rawdescriptors[cfgno] = bigbuffer;
result = usb_parse_configuration(&dev->dev, cfgno, result = usb_parse_configuration(dev, cfgno,
&dev->config[cfgno], bigbuffer, length); &dev->config[cfgno], bigbuffer, length);
if (result < 0) { if (result < 0) {
++cfgno; ++cfgno;
......
...@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* SKYMEDI USB_DRIVE */ /* SKYMEDI USB_DRIVE */
{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
/* BUILDWIN Photo Frame */
{ USB_DEVICE(0x1908, 0x1315), .driver_info =
USB_QUIRK_HONOR_BNUMINTERFACES },
/* INTEL VALUE SSD */ /* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
......
...@@ -22,4 +22,8 @@ ...@@ -22,4 +22,8 @@
/*device will morph if reset, don't use reset for handling errors */ /*device will morph if reset, don't use reset for handling errors */
#define USB_QUIRK_RESET_MORPHS 0x00000010 #define USB_QUIRK_RESET_MORPHS 0x00000010
/* device has more interface descriptions than the bNumInterfaces count,
and can't handle talking to these interfaces */
#define USB_QUIRK_HONOR_BNUMINTERFACES 0x00000020
#endif /* __LINUX_USB_QUIRKS_H */ #endif /* __LINUX_USB_QUIRKS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment