lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080520190628.GA14580@srcf.ucam.org>
Date:	Tue, 20 May 2008 20:06:28 +0100
From:	Matthew Garrett <mjg59@...f.ucam.org>
To:	linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org
Cc:	gregkh@...e.de, bersace03@...oste.net, johannes@...solutions.de
Subject: [PATCH] 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 <mjg@...hat.com>

---

I think this is a cleaner solution than adding support for the firmware 
loading directly to the uvcvideo driver, and doing it as a driver rather 
than a set of userspace callouts simplifies the suspend/resume case. The 
required firmware is, sadly, non-free and undistributable.

diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a53db1d..0629e7a 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -269,3 +269,14 @@ config USB_TEST
 	  See <http://www.linux-usb.org/usbtest/> 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 b68e6b7..aba091c 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 0000000..c76da4a
--- /dev/null
+++ b/drivers/usb/misc/isight_firmware.c
@@ -0,0 +1,131 @@
+/*
+ * Driver for loading USB isight firmware
+ *
+ * Copyright (C) 2008 Matthew Garrett <mjg@...hat.com>
+ *
+ * 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
+ * <johannes@...solutions.de>, and this driver is based on code by Ronald
+ * Bultje <rbultje@...ald.bitfreak.net>
+ */
+
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+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 <mjg@...hat.com>");

-- 
Matthew Garrett | mjg59@...f.ucam.org
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ