diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 46 | ||||
-rw-r--r-- | drivers/usb/core/quirks.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 8 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-hcd.c | 8 | ||||
-rw-r--r-- | drivers/usb/misc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/misc/isight_firmware.c | 23 |
6 files changed, 72 insertions, 17 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8eb4da332f5..94789be54ca 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub) #ifdef CONFIG_PM +/* Try to identify which devices need USB-PERSIST handling */ +static int persistent_device(struct usb_device *udev) +{ + int i; + int retval; + struct usb_host_config *actconfig; + + /* Explicitly not marked persistent? */ + if (!udev->persist_enabled) + return 0; + + /* No active config? */ + actconfig = udev->actconfig; + if (!actconfig) + return 0; + + /* FIXME! We should check whether it's open here or not! */ + + /* + * Check that all the interface drivers have a + * 'reset_resume' entrypoint + */ + retval = 0; + for (i = 0; i < actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf; + struct usb_driver *driver; + + intf = actconfig->interface[i]; + if (!intf->dev.driver) + continue; + driver = to_usb_driver(intf->dev.driver); + if (!driver->reset_resume) + return 0; + /* + * We have at least one driver, and that one + * has a reset_resume method. + */ + retval = 1; + } + return retval; +} + static void hub_restart(struct usb_hub *hub, int type) { struct usb_device *hdev = hub->hdev; @@ -689,8 +731,8 @@ static void hub_restart(struct usb_hub *hub, int type) * turn off the various status changes to prevent * khubd from disconnecting it later. */ - if (udev->persist_enabled && status == 0 && - !(portstatus & USB_PORT_STAT_ENABLE)) { + if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) && + persistent_device(udev)) { if (portchange & USB_PORT_STAT_C_ENABLE) clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 3da1ab4b389..c070b34b669 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -47,6 +47,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Edirol SD-20 */ { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, + /* appletouch */ + { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Avision AV600U */ { USB_DEVICE(0x0638, 0x0a13), .driver_info = USB_QUIRK_STRING_FETCH_255 }, diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1ef6df395e0..228797e54f9 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -300,8 +300,8 @@ config USB_R8A66597_HCD module will be called r8a66597-hcd. config SUPERH_ON_CHIP_R8A66597 - boolean "Enable SuperH on-chip USB like the R8A66597" - depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366 + boolean "Enable SuperH on-chip R8A66597 USB" + depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723) help - Renesas SuperH processor has USB like the R8A66597. - This driver supported processor is SH7366. + This driver enables support for the on-chip R8A66597 in the + SH7366 and SH7723 processors. diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9cec873826..65aa5ecf569 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2207,14 +2207,14 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, goto err_put; } - ret = usb_add_hcd(hcd, irq, irqflags); - if (ret) - goto err_unmap; - hcd->irq = irq; hcd->rsrc_start = res_start; hcd->rsrc_len = res_len; + ret = usb_add_hcd(hcd, irq, irqflags); + if (ret) + goto err_unmap; + return hcd; err_unmap: diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index eb6c06979f3..001789c9a11 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -272,6 +272,7 @@ config USB_TEST config USB_ISIGHTFW tristate "iSight firmware loading support" depends on USB + select FW_LOADER help This driver loads firmware for USB Apple iSight cameras, allowing them to be driven by the USB video class driver available at diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index 390e0488553..9f30aa1f8a5 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -39,9 +39,12 @@ static int isight_firmware_load(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); int llen, len, req, ret = 0; const struct firmware *firmware; - unsigned char *buf; + unsigned char *buf = kmalloc(50, GFP_KERNEL); unsigned char data[4]; - char *ptr; + u8 *ptr; + + if (!buf) + return -ENOMEM; if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { printk(KERN_ERR "Unable to load isight firmware\n"); @@ -59,7 +62,7 @@ static int isight_firmware_load(struct usb_interface *intf, goto out; } - while (1) { + while (ptr+4 <= firmware->data+firmware->size) { memcpy(data, ptr, 4); len = (data[0] << 8 | data[1]); req = (data[2] << 8 | data[3]); @@ -71,10 +74,14 @@ static int isight_firmware_load(struct usb_interface *intf, continue; for (; len > 0; req += 50) { - llen = len > 50 ? 50 : len; + llen = min(len, 50); len -= llen; - - buf = kmalloc(llen, GFP_KERNEL); + if (ptr+llen > firmware->data+firmware->size) { + printk(KERN_ERR + "Malformed isight firmware"); + ret = -ENODEV; + goto out; + } memcpy(buf, ptr, llen); ptr += llen; @@ -89,16 +96,18 @@ static int isight_firmware_load(struct usb_interface *intf, goto out; } - kfree(buf); } } + if (usb_control_msg (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, 300) != 1) { printk(KERN_ERR "isight firmware loading completion failed\n"); ret = -ENODEV; } + out: + kfree(buf); release_firmware(firmware); return ret; } |