diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-06-25 06:32:01 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-06-25 06:32:01 -0400 |
| commit | da7878d75b8520c9ae00d27dfbbce546a7bfdfbb (patch) | |
| tree | 547fd497a80818a60ac36831377d5df97868173c /drivers/usb/misc | |
| parent | 0e50a4c6ab94ffe7e5515b86b5df9e5abc8c6b13 (diff) | |
| parent | 543cf4cb3fe6f6cae3651ba918b9c56200b257d0 (diff) | |
Merge branch 'linus' into x86/pebs
Diffstat (limited to 'drivers/usb/misc')
| -rw-r--r-- | drivers/usb/misc/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/usb/misc/isight_firmware.c | 140 | ||||
| -rw-r--r-- | drivers/usb/misc/phidgetkit.c | 6 | ||||
| -rw-r--r-- | drivers/usb/misc/phidgetmotorcontrol.c | 7 | ||||
| -rw-r--r-- | drivers/usb/misc/phidgetservo.c | 6 |
6 files changed, 162 insertions, 10 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a53db1d4e07a..001789c9a11a 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
| @@ -269,3 +269,15 @@ config USB_TEST | |||
| 269 | See <http://www.linux-usb.org/usbtest/> for more information, | 269 | See <http://www.linux-usb.org/usbtest/> for more information, |
| 270 | including sample test device firmware and "how to use it". | 270 | including sample test device firmware and "how to use it". |
| 271 | 271 | ||
| 272 | config USB_ISIGHTFW | ||
| 273 | tristate "iSight firmware loading support" | ||
| 274 | depends on USB | ||
| 275 | select FW_LOADER | ||
| 276 | help | ||
| 277 | This driver loads firmware for USB Apple iSight cameras, allowing | ||
| 278 | them to be driven by the USB video class driver available at | ||
| 279 | http://linux-uvc.berlios.de | ||
| 280 | |||
| 281 | The firmware for this driver must be extracted from the MacOS | ||
| 282 | driver beforehand. Tools for doing so are available at | ||
| 283 | 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 | |||
| 14 | obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o | 14 | obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o |
| 15 | obj-$(CONFIG_USB_IDMOUSE) += idmouse.o | 15 | obj-$(CONFIG_USB_IDMOUSE) += idmouse.o |
| 16 | obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o | 16 | obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o |
| 17 | obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o | ||
| 17 | obj-$(CONFIG_USB_LCD) += usblcd.o | 18 | obj-$(CONFIG_USB_LCD) += usblcd.o |
| 18 | obj-$(CONFIG_USB_LD) += ldusb.o | 19 | obj-$(CONFIG_USB_LD) += ldusb.o |
| 19 | obj-$(CONFIG_USB_LED) += usbled.o | 20 | 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..9f30aa1f8a5d --- /dev/null +++ b/drivers/usb/misc/isight_firmware.c | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | /* | ||
| 2 | * Driver for loading USB isight firmware | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Matthew Garrett <mjg@redhat.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * The USB isight cameras in recent Apples are roughly compatible with the USB | ||
| 11 | * video class specification, and can be driven by uvcvideo. However, they | ||
| 12 | * need firmware to be loaded beforehand. After firmware loading, the device | ||
| 13 | * detaches from the USB bus and reattaches with a new device ID. It can then | ||
| 14 | * be claimed by the uvc driver. | ||
| 15 | * | ||
| 16 | * The firmware is non-free and must be extracted by the user. Tools to do this | ||
| 17 | * are available at http://bersace03.free.fr/ift/ | ||
| 18 | * | ||
| 19 | * The isight firmware loading was reverse engineered by Johannes Berg | ||
| 20 | * <johannes@sipsolutions.de>, and this driver is based on code by Ronald | ||
| 21 | * Bultje <rbultje@ronald.bitfreak.net> | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/usb.h> | ||
| 25 | #include <linux/firmware.h> | ||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/module.h> | ||
| 28 | |||
| 29 | static struct usb_device_id id_table[] = { | ||
| 30 | {USB_DEVICE(0x05ac, 0x8300)}, | ||
| 31 | {}, | ||
| 32 | }; | ||
| 33 | |||
| 34 | MODULE_DEVICE_TABLE(usb, id_table); | ||
| 35 | |||
| 36 | static int isight_firmware_load(struct usb_interface *intf, | ||
| 37 | const struct usb_device_id *id) | ||
| 38 | { | ||
| 39 | struct usb_device *dev = interface_to_usbdev(intf); | ||
| 40 | int llen, len, req, ret = 0; | ||
| 41 | const struct firmware *firmware; | ||
| 42 | unsigned char *buf = kmalloc(50, GFP_KERNEL); | ||
| 43 | unsigned char data[4]; | ||
| 44 | u8 *ptr; | ||
| 45 | |||
| 46 | if (!buf) | ||
| 47 | return -ENOMEM; | ||
| 48 | |||
| 49 | if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { | ||
| 50 | printk(KERN_ERR "Unable to load isight firmware\n"); | ||
| 51 | return -ENODEV; | ||
| 52 | } | ||
| 53 | |||
| 54 | ptr = firmware->data; | ||
| 55 | |||
| 56 | if (usb_control_msg | ||
| 57 | (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, | ||
| 58 | 300) != 1) { | ||
| 59 | printk(KERN_ERR | ||
| 60 | "Failed to initialise isight firmware loader\n"); | ||
| 61 | ret = -ENODEV; | ||
| 62 | goto out; | ||
| 63 | } | ||
| 64 | |||
| 65 | while (ptr+4 <= firmware->data+firmware->size) { | ||
| 66 | memcpy(data, ptr, 4); | ||
| 67 | len = (data[0] << 8 | data[1]); | ||
| 68 | req = (data[2] << 8 | data[3]); | ||
| 69 | ptr += 4; | ||
| 70 | |||
| 71 | if (len == 0x8001) | ||
| 72 | break; /* success */ | ||
| 73 | else if (len == 0) | ||
| 74 | continue; | ||
| 75 | |||
| 76 | for (; len > 0; req += 50) { | ||
| 77 | llen = min(len, 50); | ||
| 78 | len -= llen; | ||
| 79 | if (ptr+llen > firmware->data+firmware->size) { | ||
| 80 | printk(KERN_ERR | ||
| 81 | "Malformed isight firmware"); | ||
| 82 | ret = -ENODEV; | ||
| 83 | goto out; | ||
| 84 | } | ||
| 85 | memcpy(buf, ptr, llen); | ||
| 86 | |||
| 87 | ptr += llen; | ||
| 88 | |||
| 89 | if (usb_control_msg | ||
| 90 | (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, req, 0, | ||
| 91 | buf, llen, 300) != llen) { | ||
| 92 | printk(KERN_ERR | ||
| 93 | "Failed to load isight firmware\n"); | ||
| 94 | kfree(buf); | ||
| 95 | ret = -ENODEV; | ||
| 96 | goto out; | ||
| 97 | } | ||
| 98 | |||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | if (usb_control_msg | ||
| 103 | (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, | ||
| 104 | 300) != 1) { | ||
| 105 | printk(KERN_ERR "isight firmware loading completion failed\n"); | ||
| 106 | ret = -ENODEV; | ||
| 107 | } | ||
| 108 | |||
| 109 | out: | ||
| 110 | kfree(buf); | ||
| 111 | release_firmware(firmware); | ||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | |||
| 115 | static void isight_firmware_disconnect(struct usb_interface *intf) | ||
| 116 | { | ||
| 117 | } | ||
| 118 | |||
| 119 | static struct usb_driver isight_firmware_driver = { | ||
| 120 | .name = "isight_firmware", | ||
| 121 | .probe = isight_firmware_load, | ||
| 122 | .disconnect = isight_firmware_disconnect, | ||
| 123 | .id_table = id_table, | ||
| 124 | }; | ||
| 125 | |||
| 126 | static int __init isight_firmware_init(void) | ||
| 127 | { | ||
| 128 | return usb_register(&isight_firmware_driver); | ||
| 129 | } | ||
| 130 | |||
| 131 | static void __exit isight_firmware_exit(void) | ||
| 132 | { | ||
| 133 | usb_deregister(&isight_firmware_driver); | ||
| 134 | } | ||
| 135 | |||
| 136 | module_init(isight_firmware_init); | ||
| 137 | module_exit(isight_firmware_exit); | ||
| 138 | |||
| 139 | MODULE_LICENSE("GPL"); | ||
| 140 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); | ||
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 | |||
| 595 | } while(value); | 595 | } while(value); |
| 596 | kit->dev_no = bit; | 596 | kit->dev_no = bit; |
| 597 | 597 | ||
| 598 | kit->dev = device_create(phidget_class, &kit->udev->dev, 0, | 598 | kit->dev = device_create_drvdata(phidget_class, &kit->udev->dev, |
| 599 | "interfacekit%d", kit->dev_no); | 599 | MKDEV(0, 0), kit, |
| 600 | "interfacekit%d", kit->dev_no); | ||
| 600 | if (IS_ERR(kit->dev)) { | 601 | if (IS_ERR(kit->dev)) { |
| 601 | rc = PTR_ERR(kit->dev); | 602 | rc = PTR_ERR(kit->dev); |
| 602 | kit->dev = NULL; | 603 | kit->dev = NULL; |
| 603 | goto out; | 604 | goto out; |
| 604 | } | 605 | } |
| 605 | dev_set_drvdata(kit->dev, kit); | ||
| 606 | 606 | ||
| 607 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 607 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
| 608 | rc = -EIO; | 608 | 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 | |||
| 365 | } while(value); | 365 | } while(value); |
| 366 | mc->dev_no = bit; | 366 | mc->dev_no = bit; |
| 367 | 367 | ||
| 368 | mc->dev = device_create(phidget_class, &mc->udev->dev, 0, | 368 | mc->dev = device_create_drvdata(phidget_class, &mc->udev->dev, |
| 369 | "motorcontrol%d", mc->dev_no); | 369 | MKDEV(0, 0), mc, |
| 370 | "motorcontrol%d", mc->dev_no); | ||
| 370 | if (IS_ERR(mc->dev)) { | 371 | if (IS_ERR(mc->dev)) { |
| 371 | rc = PTR_ERR(mc->dev); | 372 | rc = PTR_ERR(mc->dev); |
| 372 | mc->dev = NULL; | 373 | mc->dev = NULL; |
| 373 | goto out; | 374 | goto out; |
| 374 | } | 375 | } |
| 375 | 376 | ||
| 376 | dev_set_drvdata(mc->dev, mc); | ||
| 377 | |||
| 378 | if (usb_submit_urb(mc->irq, GFP_KERNEL)) { | 377 | if (usb_submit_urb(mc->irq, GFP_KERNEL)) { |
| 379 | rc = -EIO; | 378 | rc = -EIO; |
| 380 | goto out; | 379 | 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) | |||
| 275 | } while (value); | 275 | } while (value); |
| 276 | dev->dev_no = bit; | 276 | dev->dev_no = bit; |
| 277 | 277 | ||
| 278 | dev->dev = device_create(phidget_class, &dev->udev->dev, 0, | 278 | dev->dev = device_create_drvdata(phidget_class, &dev->udev->dev, |
| 279 | "servo%d", dev->dev_no); | 279 | MKDEV(0, 0), dev, |
| 280 | "servo%d", dev->dev_no); | ||
| 280 | if (IS_ERR(dev->dev)) { | 281 | if (IS_ERR(dev->dev)) { |
| 281 | rc = PTR_ERR(dev->dev); | 282 | rc = PTR_ERR(dev->dev); |
| 282 | dev->dev = NULL; | 283 | dev->dev = NULL; |
| 283 | goto out; | 284 | goto out; |
| 284 | } | 285 | } |
| 285 | dev_set_drvdata(dev->dev, dev); | ||
| 286 | 286 | ||
| 287 | servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; | 287 | servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; |
| 288 | 288 | ||
