From 5fc89390f74ac42165db477793fb30f6a200e79c Mon Sep 17 00:00:00 2001 From: Xiaofan Chen Date: Tue, 13 May 2008 21:52:00 +0800 Subject: USB: remove PICDEM FS USB demo (04d8:000c) device from ldusb Microchip has changed the PICDEM FS USB demo device (0x04d8:000c) to use bulk transfer and not interrupt transfer. So I've updated the libusb based program here (Post #31). http://forum.microchip.com/tm.aspx?m=106426&mpage=2 So I believe that the in-kernel ldusb driver will no longer work with the demo firmware. It should be removed. Signed-off-by: Xiaofan Chen Cc: Michael Hund Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ldusb.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 7aafd53fbcab..189a9db03509 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -63,9 +63,6 @@ #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 #define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 -#define USB_VENDOR_ID_MICROCHIP 0x04d8 -#define USB_DEVICE_ID_PICDEM 0x000c - #ifdef CONFIG_USB_DYNAMIC_MINORS #define USB_LD_MINOR_BASE 0 #else @@ -92,7 +89,6 @@ static struct usb_device_id ld_usb_table [] = { { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, - { USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICDEM) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, { } /* Terminating entry */ }; -- cgit v1.2.3 From 6def755320a214ae149ad6bc69eb8c1d7887e678 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 12 May 2008 20:17:25 +0200 Subject: usbtest: comment on why this code "expects" negative and positive errnos On Mon, May 12, 2008 at 01:02:22AM -0700, David Brownell wrote: > On Sunday 11 May 2008, Marcin Slusarz wrote: > > > > test_ctrl_queue expects (?) positive and negative errnos. > > what is going on here? > > The sign is just a way to flag something: > > /* some faults are allowed, not required */ > > The negative ones are required. Positive codes are optional, > in the sense that, depending on how the peripheral happens > to be implemented, they won't necessarily be triggered. > > For example, the test to fetch a device qualifier desriptor > must succeed if the device is running at high speed. So that > test is marked as negative. But when it's full speed, it > could legitimately fail; marked as positive. And so on for > other tests. > > Look at how the codes are *interpreted* to see it work. Lets document it. Based on comment from David Brownell . Signed-off-by: Marcin Slusarz Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 742be3c35947..054dedd28127 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -856,6 +856,11 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) struct urb *u; struct usb_ctrlrequest req; struct subcase *reqp; + + /* sign of this variable means: + * -: tested code must return this (negative) error code + * +: tested code may return this (negative too) error code + */ int expected = 0; /* requests here are mostly expected to succeed on any -- cgit v1.2.3 From bfd3a5a96c1dd432303fdf2283e770419f6aecb3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 May 2008 17:55:12 -0700 Subject: USB: Phidget: fix race in device_create There is a race from when a device is created with device_create() and then the drvdata is set with a call to dev_set_drvdata() in which a sysfs file could be open, yet the drvdata will be NULL, causing all sorts of bad things to happen. This patch fixes the problem by using the new function, device_create_drvdata(). It fixes all 3 phidget drivers, which all have the same problem. Cc: Kay Sievers Cc: Sean Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetkit.c | 6 +++--- drivers/usb/misc/phidgetmotorcontrol.c | 7 +++---- drivers/usb/misc/phidgetservo.c | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 24230c638b8e..4cfa25b0f44e 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -595,14 +595,14 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic } while(value); kit->dev_no = bit; - kit->dev = device_create(phidget_class, &kit->udev->dev, 0, - "interfacekit%d", kit->dev_no); + kit->dev = device_create_drvdata(phidget_class, &kit->udev->dev, + MKDEV(0, 0), kit, + "interfacekit%d", kit->dev_no); if (IS_ERR(kit->dev)) { rc = PTR_ERR(kit->dev); kit->dev = NULL; goto out; } - dev_set_drvdata(kit->dev, kit); if (usb_submit_urb(kit->irq, GFP_KERNEL)) { rc = -EIO; diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index f0113c17cc5a..9b4696f21b22 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -365,16 +365,15 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic } while(value); mc->dev_no = bit; - mc->dev = device_create(phidget_class, &mc->udev->dev, 0, - "motorcontrol%d", mc->dev_no); + mc->dev = device_create_drvdata(phidget_class, &mc->udev->dev, + MKDEV(0, 0), mc, + "motorcontrol%d", mc->dev_no); if (IS_ERR(mc->dev)) { rc = PTR_ERR(mc->dev); mc->dev = NULL; goto out; } - dev_set_drvdata(mc->dev, mc); - if (usb_submit_urb(mc->irq, GFP_KERNEL)) { rc = -EIO; goto out; diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index 7d590c09434a..1ca7ddb41d4d 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c @@ -275,14 +275,14 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id) } while (value); dev->dev_no = bit; - dev->dev = device_create(phidget_class, &dev->udev->dev, 0, - "servo%d", dev->dev_no); + dev->dev = device_create_drvdata(phidget_class, &dev->udev->dev, + MKDEV(0, 0), dev, + "servo%d", dev->dev_no); if (IS_ERR(dev->dev)) { rc = PTR_ERR(dev->dev); dev->dev = NULL; goto out; } - dev_set_drvdata(dev->dev, dev); servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; -- cgit v1.2.3 From 62d104d0deeabd4148e49eba729d963e740e205f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 20 May 2008 20:06:28 +0100 Subject: USB: Firmware loader driver for USB Apple iSight camera Uninitialised Apple iSight drivers present with a distinctive USB ID. Once firmware has been uploaded, they disconnect and reconnect with a new ID. At this point they can be driven by the uvcvideo driver. As this is unique to the Apple cameras and not functionality shared by any other UVC devices, it makes sense to provide the firmware loading functionality in a separate driver. This driver will read an isight.fw file extracted from the Apple driver using the tools at http://bersace03.free.fr/ift/ and upload it to the camera. It will also handle the case where the device loses its firmware during hibernation and must have it reloaded. Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 11 ++++ drivers/usb/misc/Makefile | 1 + drivers/usb/misc/isight_firmware.c | 131 +++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 drivers/usb/misc/isight_firmware.c (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a53db1d4e07a..eb6c06979f3b 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -269,3 +269,14 @@ config USB_TEST See for more information, including sample test device firmware and "how to use it". +config USB_ISIGHTFW + tristate "iSight firmware loading support" + depends on USB + help + This driver loads firmware for USB Apple iSight cameras, allowing + them to be driven by the USB video class driver available at + http://linux-uvc.berlios.de + + The firmware for this driver must be extracted from the MacOS + driver beforehand. Tools for doing so are available at + http://bersace03.free.fr diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index b68e6b774f1a..aba091cb5ec0 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_EMI62) += emi62.o obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o obj-$(CONFIG_USB_IDMOUSE) += idmouse.o obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o +obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LED) += usbled.o diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c new file mode 100644 index 000000000000..390e04885536 --- /dev/null +++ b/drivers/usb/misc/isight_firmware.c @@ -0,0 +1,131 @@ +/* + * Driver for loading USB isight firmware + * + * Copyright (C) 2008 Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 2. + * + * The USB isight cameras in recent Apples are roughly compatible with the USB + * video class specification, and can be driven by uvcvideo. However, they + * need firmware to be loaded beforehand. After firmware loading, the device + * detaches from the USB bus and reattaches with a new device ID. It can then + * be claimed by the uvc driver. + * + * The firmware is non-free and must be extracted by the user. Tools to do this + * are available at http://bersace03.free.fr/ift/ + * + * The isight firmware loading was reverse engineered by Johannes Berg + * , and this driver is based on code by Ronald + * Bultje + */ + +#include +#include +#include +#include + +static struct usb_device_id id_table[] = { + {USB_DEVICE(0x05ac, 0x8300)}, + {}, +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static int isight_firmware_load(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + int llen, len, req, ret = 0; + const struct firmware *firmware; + unsigned char *buf; + unsigned char data[4]; + char *ptr; + + if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { + printk(KERN_ERR "Unable to load isight firmware\n"); + return -ENODEV; + } + + ptr = firmware->data; + + if (usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, + 300) != 1) { + printk(KERN_ERR + "Failed to initialise isight firmware loader\n"); + ret = -ENODEV; + goto out; + } + + while (1) { + memcpy(data, ptr, 4); + len = (data[0] << 8 | data[1]); + req = (data[2] << 8 | data[3]); + ptr += 4; + + if (len == 0x8001) + break; /* success */ + else if (len == 0) + continue; + + for (; len > 0; req += 50) { + llen = len > 50 ? 50 : len; + len -= llen; + + buf = kmalloc(llen, GFP_KERNEL); + memcpy(buf, ptr, llen); + + ptr += llen; + + if (usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, req, 0, + buf, llen, 300) != llen) { + printk(KERN_ERR + "Failed to load isight firmware\n"); + kfree(buf); + ret = -ENODEV; + 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: + release_firmware(firmware); + return ret; +} + +static void isight_firmware_disconnect(struct usb_interface *intf) +{ +} + +static struct usb_driver isight_firmware_driver = { + .name = "isight_firmware", + .probe = isight_firmware_load, + .disconnect = isight_firmware_disconnect, + .id_table = id_table, +}; + +static int __init isight_firmware_init(void) +{ + return usb_register(&isight_firmware_driver); +} + +static void __exit isight_firmware_exit(void) +{ + usb_deregister(&isight_firmware_driver); +} + +module_init(isight_firmware_init); +module_exit(isight_firmware_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Matthew Garrett "); -- cgit v1.2.3 From 6460a261b5893e769a314c246faec31bbc4aad9c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 2 Jun 2008 21:21:03 +0200 Subject: USB: fix build bug in USB_ISIGHTFW USB: fix build bug in USB_ISIGHTFW -tip tree testing found this build bug: drivers/built-in.o: In function `isight_firmware_load': isight_firmware.c:(.text+0x1ade08): undefined reference to `request_firmware' isight_firmware.c:(.text+0x1adf9c): undefined reference to `release_firmware' select FW_LOADER in USB_ISIGHTFW. From: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index eb6c06979f3b..001789c9a11a 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 -- cgit v1.2.3 From 62b5884875fcd4babf6c0c377046f226abbfe491 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 6 Jun 2008 12:35:15 -0700 Subject: isight_firmware: Avoid crash on loading invalid firmware Different tools generate slightly different formats of the isight firmware. Ensure that the firmware buffer is not overrun, while still ensuring that the correct amount of data is written if trailing data is present. Signed-off-by: Matthew Garrett Report-by: Justin Mattock Tested-by: Justin Mattock Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/isight_firmware.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index 390e04885536..9f30aa1f8a5d 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; } -- cgit v1.2.3