diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/Kconfig | 22 | ||||
-rw-r--r-- | drivers/usb/core/config.c | 42 |
2 files changed, 54 insertions, 10 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index f493fb1eaa27..346fc030c929 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -40,21 +40,25 @@ config USB_DEVICEFS config USB_DEVICE_CLASS bool "USB device class-devices (DEPRECATED)" depends on USB - default n + default y ---help--- Userspace access to USB devices is granted by device-nodes exported directly from the usbdev in sysfs. Old versions of the driver core and udev needed additional class devices to export device nodes. These additional devices are difficult to handle in userspace, if - information about USB interfaces must be available. One device contains - the device node, the other device contains the interface data. Both - devices are at the same level in sysfs (siblings) and one can't access - the other. The device node created directly by the usbdev is the parent - device of the interface and therefore easily accessible from the interface - event. - - This option provides backward compatibility if needed. + information about USB interfaces must be available. One device + contains the device node, the other device contains the interface + data. Both devices are at the same level in sysfs (siblings) and one + can't access the other. The device node created directly by the + usb device is the parent device of the interface and therefore + easily accessible from the interface event. + + This option provides backward compatibility for libusb device + nodes (lsusb) when usbfs is not used, and the following udev rule + doesn't exist: + SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \ + NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644" config USB_DYNAMIC_MINORS bool "Dynamic USB minor allocation (EXPERIMENTAL)" diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 2d4fd530e5e4..dd3482328ad2 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -1,4 +1,5 @@ #include <linux/usb.h> +#include <linux/usb/ch9.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -49,7 +50,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; struct usb_host_endpoint *endpoint; - int n, i; + int n, i, j; d = (struct usb_endpoint_descriptor *) buffer; buffer += d->bLength; @@ -84,6 +85,45 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, memcpy(&endpoint->desc, d, n); INIT_LIST_HEAD(&endpoint->urb_list); + /* If the bInterval value is outside the legal range, + * set it to a default value: 32 ms */ + i = 0; /* i = min, j = max, n = default */ + j = 255; + if (usb_endpoint_xfer_int(d)) { + i = 1; + switch (to_usb_device(ddev)->speed) { + case USB_SPEED_HIGH: + n = 9; /* 32 ms = 2^(9-1) uframes */ + j = 16; + break; + default: /* USB_SPEED_FULL or _LOW */ + /* For low-speed, 10 ms is the official minimum. + * But some "overclocked" devices might want faster + * polling so we'll allow it. */ + n = 32; + break; + } + } else if (usb_endpoint_xfer_isoc(d)) { + i = 1; + j = 16; + switch (to_usb_device(ddev)->speed) { + case USB_SPEED_HIGH: + n = 9; /* 32 ms = 2^(9-1) uframes */ + break; + default: /* USB_SPEED_FULL */ + n = 6; /* 32 ms = 2^(6-1) frames */ + break; + } + } + if (d->bInterval < i || d->bInterval > j) { + dev_warn(ddev, "config %d interface %d altsetting %d " + "endpoint 0x%X has an invalid bInterval %d, " + "changing to %d\n", + cfgno, inum, asnum, + d->bEndpointAddress, d->bInterval, n); + endpoint->desc.bInterval = n; + } + /* Skip over any Class Specific or Vendor Specific descriptors; * find the next endpoint or interface descriptor */ endpoint->extra = buffer; |