mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 01:51:53 +00:00
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>
This commit is contained in:
parent
7f0ae3a8ee
commit
317149c655
@ -1,6 +1,7 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/usb/quirks.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
@ -479,9 +480,10 @@ skip_to_next_interface_descriptor:
|
||||
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 device *ddev = &dev->dev;
|
||||
unsigned char *buffer0 = buffer;
|
||||
int cfgno;
|
||||
int nintf, nintf_orig;
|
||||
@ -550,6 +552,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
|
||||
}
|
||||
|
||||
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)
|
||||
dev_warn(ddev, "config %d has an invalid "
|
||||
"interface number: %d but max is %d\n",
|
||||
@ -801,7 +813,7 @@ int usb_get_configuration(struct usb_device *dev)
|
||||
|
||||
dev->rawdescriptors[cfgno] = bigbuffer;
|
||||
|
||||
result = usb_parse_configuration(&dev->dev, cfgno,
|
||||
result = usb_parse_configuration(dev, cfgno,
|
||||
&dev->config[cfgno], bigbuffer, length);
|
||||
if (result < 0) {
|
||||
++cfgno;
|
||||
|
@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
/* SKYMEDI USB_DRIVE */
|
||||
{ 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 */
|
||||
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
|
@ -22,4 +22,8 @@
|
||||
/*device will morph if reset, don't use reset for handling errors */
|
||||
#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 */
|
||||
|
Loading…
Reference in New Issue
Block a user