Hello,
Attached you will find a patch that adds iSight support to uvcvideo
and applies to HEAD (revision 140). This patch has existed for some
time now. Initially it was very instrusive to the uvcvideo code, but
this has been fixed.
Please, lets get this reviewed and merged with uvcvideo. It's very
time consuming for me to keep it in sync with uvcvideo head. openSUSE
patches uvcvideo with this patch, Gentoo too, possibly others. It
would make our life much easier if we could get this upstream.
This patch enables the isight camera found in all apple macs fully,
including suspend and resume support.
iSight is an uvc device, but not fully. I am not an expert but it
seems to use a custom packet format on top of the uvc, has different
guid, has partially broken video descriptors and requires firmware.
This patch deals with those in the most intrusive way I could.
Inside the uvcvideo code it will only change the decoding queue if the
device is recognized as an isight device. In addition it will call
uvc_load_firmware during the uvc initialization.
Outside in the self-contained isight.c|h it will handle the firmware
loading, patching the usb descriptors and the decoding.
I would like to express my gratitude to Martin Szulecki who worked
with me on getting the patch in sync with latest uvcvideo and testing
it for the past two days.
Regards,
--
Ivan N. Zlatev
Web: http://www.i-nZ.net
"It's all some kind of whacked out conspiracy."
Index: uvc_video.c
===================================================================
--- uvc_video.c (revision 140)
+++ uvc_video.c (working copy)
@@ -26,6 +26,7 @@
#endif
#include "uvcvideo.h"
+#include "isight.h"
/* ------------------------------------------------------------------------
* UVC Controls
@@ -551,6 +552,15 @@
}
}
+static void uvc_video_decode(struct urb *urb, struct uvc_video_queue *queue,
+ struct uvc_buffer *buf)
+{
+ if (urb->number_of_packets)
+ uvc_video_complete_isoc(urb, queue, buf);
+ else
+ uvc_video_complete_bulk(urb, queue, buf);
+}
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
static void uvc_video_complete(struct urb *urb, struct pt_regs *regs)
#else
@@ -585,10 +595,7 @@
buf = list_entry(queue->irqqueue.next, struct uvc_buffer, queue);
spin_unlock_irqrestore(&queue->irqlock, flags);
- if (urb->number_of_packets)
- uvc_video_complete_isoc(urb, queue, buf);
- else
- uvc_video_complete_bulk(urb, queue, buf);
+ queue->decode(urb, queue, buf);
if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
@@ -944,6 +951,14 @@
video->streaming->cur_frame = frame;
atomic_set(&video->active, 1);
+ /* Select the video decoder based. This might be better handled
+ * elsewhere, based on the format GUID instead of the device ID.
+ */
+ if (is_isight (video->dev->udev) == 0)
+ video->queue.decode = isight_video_decode;
+ else
+ video->queue.decode = uvc_video_decode;
+
return 0;
}
Index: isight.c
===================================================================
--- isight.c (revision 0)
+++ isight.c (revision 0)
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2006-2007 Ivan N. Zlatev <[EMAIL PROTECTED]>
+ *
+ * Based on extract.c by Ronald S. Bultje <[EMAIL PROTECTED]>
+ * Firmware loading specifics by Johannes Berg <[EMAIL PROTECTED]>
+ * at http://johannes.sipsolutions.net/MacBook/iSight
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA
+ */
+
+#include <linux/usb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crypto.h>
+#include <linux/firmware.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include "isight.h"
+#include "uvcvideo.h"
+
+#define isight_printk(msg...) \
+ printk(KERN_DEBUG "uvcvideo: iSight: " msg)
+
+#define TIMEOUT 300
+#define UVC_STREAM_EOF (1 << 1)
+#define N_ELEMENT(array) (sizeof (array) / sizeof ((array)[0]))
+
+static const struct {
+ unsigned char sha1sum[20];
+ long offset;
+} offsets[] = {
+ { { 0x86, 0x43, 0x0c, 0x04, 0xf9, 0xb6, 0x7c, 0x5c,
+ 0x3d, 0x84, 0x40, 0x91, 0x38, 0xa7, 0x67, 0x98,
+ 0x27, 0x02, 0x5e, 0xc2 }, 5172 /* 0x1434 */ },
+ { { 0xa1, 0x4c, 0x15, 0x9b, 0x17, 0x6d, 0x27, 0xa6,
+ 0xe9, 0x8d, 0xcb, 0x5d, 0xea, 0x5d, 0x78, 0xb8,
+ 0x1e, 0x15, 0xad, 0x41 }, 9176 /* 0x23D8 */ },
+ { { 0xc6, 0xc9, 0x4d, 0xd7, 0x7b, 0x86, 0x4f, 0x8b,
+ 0x2d, 0x31, 0xab, 0xf3, 0xcb, 0x2d, 0xe4, 0xc9,
+ 0xd1, 0x39, 0xe1, 0xbf }, 0x1434 },
+ { { 0x01, 0xe2, 0x91, 0xd5, 0x29, 0xe7, 0xc1, 0x8d,
+ 0xee, 0xa2, 0xeb, 0xa2, 0x52, 0xd1, 0x81, 0x14,
+ 0xe0, 0x96, 0x27, 0x6e }, 0x2060 },
+};
+
+
+
+/* A record looks like:
+ __be16 data_length;
+ __be16 value;
+ __u8 data[data_length];
+ */
+
+static int isight_upload_firmware (struct usb_device *dev,
+ unsigned char *data, size_t size, long offset)
+{
+ int position = 0, success = 0;
+ int record_size, record_val, chunk_size;
+ unsigned char *chunk_ptr;
+ unsigned char *data_k;
+
+ if (offset > size) {
+ return -1;
+ }
+
+ data_k = kmalloc (size, GFP_KERNEL);
+ if (data_k == NULL) {
+ isight_printk ("Unable to kalloc memory. \n");
+ return -1;
+ }
+ memcpy (data_k, data, size);
+ data = data_k;
+
+ data += offset;
+
+ if (usb_control_msg (dev, usb_rcvctrlpipe (dev, 0), 0xA0, 0x40, 0xe600, 0,
+ "\1", 1, TIMEOUT) < 0) {
+ isight_printk ("firmware loading init failed\n");
+ success = -1;
+ goto end;
+ }
+
+ while (1) {
+ if (position > size) {
+ goto end;
+ }
+
+ record_size = (data[position + 0] << 8) | data[position + 1];
+ record_val = (data[position + 2] << 8) | data[position + 3];
+
+ position += 4;
+
+ if (record_size == 0x8001) { /* success */
+ goto end;
+ }
+ else if (record_size == 0) {
+ continue;
+ }
+ else if (record_size < 0 || record_size >= 1024 ||
+ position + record_size > size) {
+ isight_printk ("invalid firmware record_size: %X \n", record_size);
+ success = -1;
+ goto end;
+ }
+
+ /* Upload to usb bus in 50 bytes chunks,
+ where the last can be less than 50
+ */
+
+ chunk_ptr = &data[position];
+ position += record_size;
+
+ while (record_size > 0) {
+ chunk_size = record_size > 50 ? 50 : record_size;
+ record_size -= chunk_size;
+ if (usb_control_msg (dev, usb_sndctrlpipe (dev, 0), 0xA0, 0x40,
+ record_val, 0, chunk_ptr, chunk_size,
+ TIMEOUT) != chunk_size) {
+ isight_printk ("firmware upload failed.\n");
+ success = -1;
+ goto end;
+ }
+ chunk_ptr += chunk_size;
+ record_val += 50;
+ }
+ }
+
+end:
+ if (usb_control_msg (dev, usb_sndctrlpipe (dev, 0), 0xA0, 0x40, 0xe600, 0,
+ "\0", 1, TIMEOUT) < 0) {
+ isight_printk ("firmware loading finish-up failed.\n");
+ success = -1;
+ }
+
+ kfree (data_k);
+ return success;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static void isight_sha1 (char *result, unsigned char *data, int size)
+{
+ struct crypto_tfm *tfm;
+ struct scatterlist sg[1];
+
+ if (result == NULL)
+ return;
+ memset (result, 0x00, 20);
+ sg_set_buf (sg, data, size);
+ tfm = crypto_alloc_tfm ("sha1", 0);
+
+ if (tfm != NULL) {
+ crypto_digest_init (tfm);
+ crypto_digest_update (tfm, sg, 1);
+ crypto_digest_final (tfm, result);
+ crypto_free_tfm (tfm);
+ }
+}
+#else
+static void isight_sha1 (char *result, unsigned char *data, int size)
+{
+ struct hash_desc desc;
+ struct scatterlist sg[1];
+
+ if (result == NULL)
+ return;
+ memset (result, 0x00, 20);
+ sg_set_buf (sg, data, size);
+
+ desc.tfm = crypto_alloc_hash ("sha1", 0, CRYPTO_ALG_ASYNC);
+ desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ if (desc.tfm != NULL) {
+ crypto_hash_init (&desc);
+ crypto_hash_update (&desc, sg, size);
+ crypto_hash_final (&desc, result);
+ crypto_free_hash (desc.tfm);
+ }
+}
+#endif
+
+/* returns the offset where the firmware blob starts, else -1 */
+static long isight_extract_firmware_offset (unsigned char *data, size_t size)
+{
+ char sha1sum[20];
+ int i, offset;
+
+ if (data == NULL ||size <= 0) {
+ return -1;
+ }
+
+ isight_sha1 (sha1sum, data, size);
+
+ offset = -1;
+ for (i=0; i < N_ELEMENT (offsets); i++) {
+ if (memcmp (offsets[i].sha1sum, sha1sum, 20) == 0) {
+ offset = offsets[i].offset;
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static void isight_patch_usb_descriptor (struct usb_device *dev)
+{
+ struct usb_interface *intf = NULL;
+ struct usb_host_interface *setting = NULL;
+
+ isight_printk ("Patching broken iSight USB interface descriptors\n");
+
+ intf = usb_ifnum_to_if (dev, 0);
+ if (intf != NULL) {
+ setting = &intf->altsetting[0];
+ setting->desc.bInterfaceClass = USB_CLASS_VIDEO;
+ setting->desc.bInterfaceSubClass = SC_VIDEOCONTROL;
+ setting->desc.bInterfaceProtocol = PC_PROTOCOL_UNDEFINED;
+ }
+
+ intf = usb_ifnum_to_if (dev, 1);
+ if (intf != NULL) {
+ setting = &intf->altsetting[0];
+ setting->desc.bInterfaceClass = USB_CLASS_VIDEO;
+ setting->desc.bInterfaceSubClass = SC_VIDEOSTREAMING;
+ setting->desc.bInterfaceProtocol = PC_PROTOCOL_UNDEFINED;
+ setting = &intf->altsetting[1];
+ setting->desc.bInterfaceClass = USB_CLASS_VIDEO;
+ setting->desc.bInterfaceSubClass = SC_VIDEOSTREAMING;
+ setting->desc.bInterfaceProtocol = PC_PROTOCOL_UNDEFINED;
+ }
+}
+
+int isight_load_firmware (struct usb_device *dev)
+{
+ long offset;
+ size_t size;
+ int success = -1;
+ const struct firmware *fw;
+ unsigned char *data_k = NULL;
+
+
+ if (dev->descriptor.idVendor == 0x05ac &&
+ dev->descriptor.idProduct == 0x8300 &&
+ dev->descriptor.bDeviceClass == 0xff &&
+ dev->descriptor.bDeviceSubClass == 0xff &&
+ dev->descriptor.bDeviceProtocol == 0xff) {
+
+ /* request firmware using the firmware_class kernel interface */
+ if (request_firmware (&fw, "AppleUSBVideoSupport", &dev->dev) != 0 ) {
+ isight_printk ("firmware file AppleUSBVideoSupport not found.\n");
+ return -1;
+ }
+
+ /* copy to kernel memory - required*/
+ data_k = kmalloc (fw->size, GFP_KERNEL);
+ if (data_k == NULL) {
+ isight_printk ("can't kalloc memory.");
+ return -1;
+ }
+ memcpy (data_k, fw->data, fw->size);
+ size = fw->size;
+ release_firmware (fw);
+
+ offset = isight_extract_firmware_offset (data_k, size);
+ if (offset == -1) {
+ isight_printk ("invalid firmware file\n");
+ }
+ else {
+ if (isight_upload_firmware (dev, data_k, size, offset) == 0) {
+ isight_printk ("firmware successfully loaded.\n");
+ success = 0;
+ }
+ }
+ kfree (data_k);
+ }
+ else if (dev->descriptor.idVendor == 0x05ac &&
+ dev->descriptor.idProduct == 0x8501) {
+ isight_printk ("firmware already loaded.\n");
+ success = 0;
+ }
+
+ if (success == 0)
+ isight_patch_usb_descriptor (dev);
+
+ return success;
+}
+
+/* Built-in iSight webcams are completely broken. They implement most
+ * of UVC 1.0, but the Apple engineers decided to use a completely
+ * different packet format, although the video data is in YUV. Were
+ * they on crack or just lazy ? As the hardware is 8051-based, it
+ * might be interesting to write an open-source firmware.
+ *
+ * Instead of sending a header at the beginning of each isochronous
+ * transfer payload, the webcam sends a single header per image (on
+ * its own in a packet), followed by packets containing data only.
+ *
+ * Offset Size (bytes) Description
+ * ------------------------------------------------------------------
+ * 0x00 1 Header length
+ * 0x01 1 Flags (UVC-compliant)
+ * 0x02 4 Always equal to '11223344'
+ * 0x06 8 Always equal to 'deadbeefdeadface'
+ * 0x0e 16 Unknown
+ *
+ * The header can be prefixed by an optional, unknown-purpose byte.
+ */
+
+static int isight_decode (struct uvc_video_queue *queue, struct uvc_buffer *buf,
+ const __u8 *data, unsigned int len)
+{
+ static const __u8 hdr[] = {
+ 0x11, 0x22, 0x33, 0x44, 0xde, 0xad, 0xbe, 0xef,
+ 0xde, 0xad, 0xfa, 0xce
+ };
+
+ unsigned int maxlen, nbytes;
+ __u8 *mem;
+ int is_header = 0;
+
+ if (buf == NULL)
+ return 0;
+
+ if ((len >= 14 && memcmp (&data[2], hdr, 12) == 0) ||
+ (len >= 15 && memcmp (&data[3], hdr, 12) == 0)) {
+ uvc_trace(UVC_TRACE_FRAME, "iSight header found\n");
+ is_header = 1;
+ }
+
+ /* Synchronize to the input stream by waiting for a header packet. */
+ if (buf->state != UVC_BUF_STATE_ACTIVE) {
+ if (!is_header) {
+ uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of "
+ "sync).\n");
+ return 0;
+ }
+
+ buf->state = UVC_BUF_STATE_ACTIVE;
+ }
+
+ /* Mark the buffer as done if we're at the beginning of a new frame.
+ *
+ * Empty buffers (bytesused == 0) don't trigger end of frame detection
+ * as it doesn't make sense to return an empty buffer.
+ */
+ if (is_header && buf->buf.bytesused != 0) {
+ buf->state = UVC_BUF_STATE_DONE;
+ return -EAGAIN;
+ }
+
+ /* Copy the video data to the buffer. Skip header packets, as they
+ * contain no data.
+ */
+ if (!is_header) {
+ maxlen = buf->buf.length - buf->buf.bytesused;
+ mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ nbytes = min(len, maxlen);
+ memcpy(mem, data, nbytes);
+ buf->buf.bytesused += nbytes;
+
+ /* Drop the current frame if the buffer size was exceeded. */
+ if (len > maxlen || buf->buf.bytesused == buf->buf.length) {
+ uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
+ buf->state = UVC_BUF_STATE_DONE;
+ }
+ }
+
+ return 0;
+}
+
+void isight_video_decode (struct urb *urb, struct uvc_video_queue *queue,
+ struct uvc_buffer *buf)
+{
+ int ret, i;
+
+ for (i = 0; i < urb->number_of_packets; ++i) {
+ if (urb->iso_frame_desc[i].status < 0) {
+ uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
+ "lost (%d).\n", urb->iso_frame_desc[i].status);
+ /* Breaks 640x480
+ continue;
+ */
+ }
+
+ /* Decode the payload packet.
+ * uvc_video_decode is entered twice when a frame transition
+ * has been detected because the end of frame can only be
+ * reliably detected when the first packet of the new frame
+ * is processed. The first pass detects the transition and
+ * closes the previous frame's buffer, the second pass
+ * processes the data of the first payload of the new frame.
+ */
+ do {
+ ret = isight_decode(queue, buf,
+ urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+ urb->iso_frame_desc[i].actual_length);
+
+ if (buf == NULL)
+ break;
+
+ if (buf->state == UVC_BUF_STATE_DONE ||
+ buf->state == UVC_BUF_STATE_ERROR)
+ buf = uvc_queue_next_buffer(queue, buf);
+ } while (ret == -EAGAIN);
+ }
+}
+
+int is_isight (struct usb_device *dev)
+{
+ if (dev->descriptor.idVendor == 0x05ac &&
+ (dev->descriptor.idProduct == 0x8300) &&
+ dev->descriptor.bDeviceClass == 0xff &&
+ dev->descriptor.bDeviceSubClass == 0xff &&
+ dev->descriptor.bDeviceProtocol == 0xff) {
+ return 0;
+ }
+ else if (dev->descriptor.idVendor == 0x05ac &&
+ dev->descriptor.idProduct == 0x8501) {
+ return 0;
+ }
+ return -1;
+}
Property changes on: isight.c
___________________________________________________________________
Name: svn:eol-style
+ native
Index: uvc_driver.c
===================================================================
--- uvc_driver.c (revision 140)
+++ uvc_driver.c (working copy)
@@ -43,6 +43,7 @@
#endif
#include "uvcvideo.h"
+#include "isight.h"
#define DRIVER_AUTHOR "Laurent Pinchart <[EMAIL PROTECTED]>"
#define DRIVER_DESC "USB Video Class driver"
@@ -54,11 +55,16 @@
static struct uvc_format_desc uvc_fmts[] = {
{
- .name = "YUV 4:2:2 (YUYV)",
- .guid = UVC_GUID_FORMAT_YUY2,
+ .name = "YUV 4:2:2 (YUYV)",
+ .guid = UVC_GUID_FORMAT_YUY2,
.fcc = V4L2_PIX_FMT_YUYV,
},
{
+ .name = "YUV 4:2:2 (YUYV MACOSX)",
+ .guid = UVC_GUID_FORMAT_YUY2_MACOSX,
+ .fcc = V4L2_PIX_FMT_UYVY,
+ },
+ {
.name = "YUV 4:2:0 (NV12)",
.guid = UVC_GUID_FORMAT_NV12,
.fcc = V4L2_PIX_FMT_NV12,
@@ -1503,6 +1509,16 @@
kfree(dev);
}
+static int uvc_load_firmware (struct usb_device *dev)
+{
+ int success = 0;
+
+ if (is_isight (dev) == 0) {
+ success = isight_load_firmware (dev);
+ }
+ return success;
+}
+
static int uvc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1522,6 +1538,9 @@
if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
return -ENOMEM;
+ if (uvc_load_firmware (udev) < 0)
+ return -ENODEV;
+
INIT_LIST_HEAD(&dev->entities);
INIT_LIST_HEAD(&dev->streaming);
kref_init(&dev->kref);
@@ -1626,8 +1645,10 @@
uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
intf->cur_altsetting->desc.bInterfaceNumber);
- if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL)
+ if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
+ uvc_load_firmware (interface_to_usbdev(intf));
return uvc_ctrl_resume_device(dev);
+ }
if (dev->video.streaming->intf != intf) {
uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB "
@@ -1648,6 +1669,20 @@
* though they are compliant.
*/
static struct usb_device_id uvc_ids[] = {
+ /* Apple Built-In iSight - with firmware loaded */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x05ac,
+ .idProduct = 0x8501,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Apple Built-In iSight - no firmware loaded */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x05ac,
+ .idProduct = 0x8300,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Microsoft Lifecam NX-6000 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
Index: uvcvideo.h
===================================================================
--- uvcvideo.h (revision 140)
+++ uvcvideo.h (working copy)
@@ -279,6 +279,8 @@
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
#define UVC_GUID_FORMAT_YUY2 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2_MACOSX {'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \
+ 0x00, 0x80, 0x71, 0x9b, 0x38, 0x00, 0xaa, 0x00}
#define UVC_GUID_FORMAT_NV12 { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
#define UVC_GUID_FORMAT_YV12 { 'Y', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \
@@ -576,6 +578,9 @@
struct list_head mainqueue;
struct list_head irqqueue;
+
+ void (*decode)(struct urb *urb, struct uvc_video_queue *queue,
+ struct uvc_buffer *buf);
};
struct uvc_video_device {
Index: Makefile
===================================================================
--- Makefile (revision 140)
+++ Makefile (working copy)
@@ -5,7 +5,7 @@
PWD := $(shell pwd)
obj-m := uvcvideo.o
-uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o
+uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o isight.o
all: uvcvideo
Index: isight.h
===================================================================
--- isight.h (revision 0)
+++ isight.h (revision 0)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006-2007 Ivan N. Zlatev <[EMAIL PROTECTED]>
+ *
+ * Based on extract.c by Ronald S. Bultje <[EMAIL PROTECTED]>
+ * Firmware loading specifics by Johannes Berg <[EMAIL PROTECTED]>
+ * at http://johannes.sipsolutions.net/MacBook/iSight
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA
+ */
+
+#ifndef _ISIGHT_H_
+#define _ISIGHT_H_
+
+#include <linux/usb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crypto.h>
+#include <linux/firmware.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+
+#include "uvcvideo.h"
+
+int is_isight (struct usb_device *dev);
+int isight_load_firmware (struct usb_device *dev);
+void isight_video_decode (struct urb *urb, struct uvc_video_queue *queue,
+ struct uvc_buffer *buf);
+#endif
+
Property changes on: isight.h
___________________________________________________________________
Name: svn:eol-style
+ native
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel