Hi,

The following is the patch applied to Debian package in order to make
linux-uvc work on both iSight and Logitech stuff. It needs re-working
since it uses a global, but this is a start.

regards,
        junichi
-- 
[EMAIL PROTECTED],netfort.gr.jp}   Debian Project
#! /bin/sh /usr/share/dpatch/dpatch-run
## 01_macbook_support.dpatch by Junichi Uekawa <[EMAIL PROTECTED]>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Mactel Linux iSight support by rbultje, rediffed against trunk

@DPATCH@
diff -urNad trunk~/Makefile trunk/Makefile
--- trunk~/Makefile     2006-07-22 21:59:17.000000000 +0900
+++ trunk/Makefile      2006-07-23 08:39:33.000000000 +0900
@@ -1,7 +1,7 @@
 KERNEL_VERSION := `uname -r`
 KERNEL_DIR     := /lib/modules/$(KERNEL_VERSION)/build
 INSTALL_MOD_DIR        := usb/media
-
+DRIVER_VERSION := `grep DRIVER_VERSION uvcvideo.c | grep define | grep -v 
DRIVER_VERSION_NUMBER | cut -d"\"" -f2`
 PWD            := $(shell pwd)
 
 obj-m          := uvcvideo.o
@@ -9,7 +9,7 @@
 %.o : %.c
        gcc $(TEST_CFLAGS) -c -o $@ $<
 
-all: uvcvideo
+all: uvcvideo extract
 
 uvcvideo:
        @echo "Building USB Video Class driver..."
@@ -24,3 +24,12 @@
        -rm -f *.o *.ko .*.cmd .*.flags *.mod.c Modules.symvers
        -rm -rf .tmp_versions
 
+extract: extract.c
+       gcc -g `pkg-config --cflags --libs libusb` -o extract extract.c
+
+dist:
+       rm -fr linux-uvc-${DRIVER_VERSION}
+       mkdir linux-uvc-${DRIVER_VERSION}
+       cp uvcvideo.[ch] Makefile extract.c linux-uvc-${DRIVER_VERSION}/
+       tar -zcf linux-uvc-${DRIVER_VERSION}.tar.gz linux-uvc-${DRIVER_VERSION}
+       rm -fr linux-uvc-${DRIVER_VERSION}
diff -urNad trunk~/extract.c trunk/extract.c
--- trunk~/extract.c    1970-01-01 09:00:00.000000000 +0900
+++ trunk/extract.c     2006-07-23 08:39:33.000000000 +0900
@@ -0,0 +1,202 @@
+/*
+ * Apple iSight (the one built in the screen of Macbooks) firmware loader
+ * Copyright (C) 2006 Ronald S. Bultje <[EMAIL PROTECTED]>
+ *
+ * Special thanks to Johannes Berg <[EMAIL PROTECTED]> for helping
+ * to find out how to load the firmware; see his website on
+ * http://johannes.sipsolutions.net/MacBook/iSight for details.
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <usb.h>
+#define TIMEOUT 300
+
+static int
+read_fw (struct usb_dev_handle *dev, char *filename)
+{
+       long long int pos;
+       int fd, rd, len, req, llen, res, ret = -1;
+       unsigned char data[4], rdata[1024], *ptr;
+
+       if ((fd = open (filename, O_RDONLY)) == -1) {
+               perror ("Opening file");
+               return -1;
+       } else if (lseek (fd, 5172, SEEK_SET) != 5172) {
+               perror ("Seeking");
+               close (fd);
+               return -1;
+       }
+
+       if ((res = usb_control_msg (dev, 0x40, 0xA0, 0xe600, 0,
+                                   "\1", 1, TIMEOUT)) != 1) {
+               perror ("Firmware load init failed");
+               close (fd);
+               return -1;
+       }
+       while (1) {
+               if ((len = read (fd, data, 4)) != 4) {
+                       if (len == 0) {
+                               fprintf (stderr,
+                                        "Unexpected eos - corrupt driver?\n");
+                               goto end;
+                       } else {
+                               perror("Reading firmware header chunk failed");
+                               goto end;
+                       }
+               }
+               len = (data[0] << 8) | data[1];
+               req = (data[2] << 8) | data[3];
+               if (len == 0x8001)
+                       break; /* success */
+               else if (len == 0)
+                       continue;
+               else if (len < 0 || len >= 1024) {
+                       fprintf (stderr,
+                                "Invalid firmware length %d, load aborted\n",
+                                len);
+                       goto end;
+               } else if (read (fd, rdata, len) != len) {
+                       perror ("Error reading firmware data");
+                       goto end;
+               }
+
+               /* upload to usb bus */
+               for (ptr = rdata; len > 0; req += 50, ptr += 50) {
+                       llen = len > 50 ? 50 : len;
+                       len -= llen;
+
+                       if ((res = usb_control_msg (dev, 0x40, 0xA0, req, 0,
+                                                   (char *) ptr, llen,
+                                                   TIMEOUT)) != llen) {
+                               fprintf (stderr,
+                                        "firmware load req=0x%x failed: %s\n",
+                                        req, strerror (errno));
+                               goto end;
+                       }
+               }
+       }
+
+       ret = 0;
+end:
+       if ((res = usb_control_msg (dev, 0x40, 0xA0, 0xe600, 0,
+                                   "\0", 1, TIMEOUT)) != 1) {
+               perror ("Firmware finish-up failed");
+               ret = -1;
+       }
+
+       close (fd);
+
+       return ret;
+}
+
+static int
+probe_dev (struct usb_device *dev, char *fw_filename)
+{
+       int n, total = 0;
+
+       if (dev->descriptor.idVendor == 0x05ac &&
+           dev->descriptor.idProduct == 0x8300 &&
+           dev->descriptor.bDeviceClass == 0xff &&
+           dev->descriptor.bDeviceSubClass == 0xff &&
+           dev->descriptor.bDeviceProtocol == 0xff) {
+               usb_dev_handle *h;
+
+               /* load firmware */
+               if (!(h = usb_open (dev))) {
+                       perror ("Opening iSight");
+                       return;
+               }
+               printf ("Loading firmware for iSight...\n");
+               if (read_fw (h, fw_filename) == 0) {
+                       printf ("done\n");
+                       total++;
+               }
+               usb_close (h);
+       } else if (dev->descriptor.idVendor == 0x05ac &&
+                  dev->descriptor.idProduct == 0x8501) {
+               printf ("Apple iSight with firmware already loaded found\n");
+               total++;
+       }
+
+       for (n = 0; n < dev->num_children; n++)
+               total += probe_dev (dev->children[n], fw_filename);
+
+       return total;
+}
+
+int
+main (int argc, char *argv[])
+{
+       int n, m, found = 0;
+       char command[1024];
+       struct usb_bus *bus;
+       struct usb_device *dev;
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: %s <firmware file>\n", argv[0]);
+               fprintf(stderr, "Firmware can usually be found on your Mac "
+                       "partition in /System/Library/Extensions/"
+                       "IOUSBFamily.kext/Contents/PlugIns/"
+                       "AppleUSBVideoSupport.kext/Contents/MacOS/"
+                       "AppleUSBVideoSupport\n");
+               return -1;
+       }
+       
+       /* check sha1sum on firmware, to prevent loading crap into the
+        * iSight and thus possibly damaging it. */
+       snprintf (command, sizeof (command) - 1,
+                 "test \"x`sha1sum %s`\" == \"x%s  %s\" &> /dev/null",
+                 argv[1], "86430c04f9b67c5c3d84409138a7679827025ec2",
+                 argv[1]);
+       if (system (command) != 0) {
+               fprintf (stderr, "Sha1sum check on firmware file failed\n");
+               return -1;
+       }
+
+       /* init usb */
+       usb_init ();
+       if (usb_find_busses () == 0) {
+               fprintf (stderr, "No USB busses found\n");
+               return -1;
+       } else if (usb_find_devices () == 0) {
+               fprintf (stderr, "No USB devices found\n");
+               return -1;
+       }
+
+       /* find iSight */
+       for (bus = usb_busses; bus != NULL; bus = bus->next) {
+               if (bus->devices != NULL) {
+                       for (dev = bus->devices; dev != NULL;
+                            dev = dev->next) {
+                               found += probe_dev (dev, argv[1]);
+                       }
+               }
+       }
+       if (found == 0) {
+               fprintf (stderr, "No Apple iSight found!\n");
+               return -1;
+       }
+
+       return 0;
+}
diff -urNad trunk~/uvcvideo.c trunk/uvcvideo.c
--- trunk~/uvcvideo.c   2006-07-22 21:59:17.000000000 +0900
+++ trunk/uvcvideo.c    2006-07-23 08:39:33.000000000 +0900
@@ -53,7 +53,7 @@
 
 #define DRIVER_AUTHOR          "Laurent Pinchart <[EMAIL PROTECTED]>"
 #define DRIVER_DESC            "USB Video Class driver"
-#define DRIVER_VERSION         "0.1.0"
+#define DRIVER_VERSION         "0.1.0-b"
 #define DRIVER_VERSION_NUMBER  KERNEL_VERSION(0, 1, 0)
 
 #define UVC_CTRL_TIMEOUT       300
@@ -77,6 +77,8 @@
                                 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 #define UVC_GUID_FORMAT_YUY2   {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 
0x00, \
                                 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2A  {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 
0x00, \
+                                0x00, 0x80, 0x71, 0x9b, 0x38, 0x00, 0xaa, 0x00}
 #define UVC_GUID_FORMAT_NV12   {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 
0x00, \
                                 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 
@@ -568,8 +570,8 @@
                .fcc            = V4L2_PIX_FMT_YUYV,
        },
        {
-               .guid           = UVC_GUID_FORMAT_YUY2,
-               .fcc            = V4L2_PIX_FMT_YUYV,
+               .guid           = UVC_GUID_FORMAT_YUY2A,
+               .fcc            = V4L2_PIX_FMT_UYVY,
        },
        {
                .guid           = UVC_GUID_FORMAT_NV12,
@@ -1275,24 +1277,38 @@
                struct uvc_buffer *buf, const __u8 *data, unsigned int len)
 {
        unsigned int maxlen, nbytes;
-       void *mem;
-       __u8 fid;
+       __u8 *mem;
+       __u8 fid = queue->last_fid;
+       int hlen = 0, flags = 0, is_header = 0;
+       static const __u8 hdr[] = { 0x11, 0x22, 0x33, 0x44,
+                                   0xde, 0xad, 0xbe, 0xef,
+                                   0xde, 0xad, 0xfa, 0xce };
 
        /* Sanity checks:
         * - packet must be at least 2 bytes long
         * - bHeaderLength value must be at least 2 bytes (see above)
         * - bHeaderLength value can't be larger than the packet size.
         */
-       if (len < 2 || data[0] < 2 || data[0] > len)
-               return -EINVAL;
+       if ((len >= 14 && memcmp (&data[3], hdr, 12) == 0) ||
+           (len >= 13 && memcmp (&data[2], hdr, 12) == 0)) {
+               uvc_trace(UVC_TRACE_FRAME, "Detecting new header");
+               hlen = (data[3] == 0x11) ? data[1] : data[0];
+               if (hlen > len - 1 || hlen < 2)
+                       return -EINVAL;
+               flags = (data[3] == 0x11) ? data[2] : data[1];
+               is_header = 1;
+       }
 
        /* Skip payloads marked with the error bit ("error frames"). */
-       if (data[1] & UVC_STREAM_ERR) {
+       if (hlen != 0 && flags & UVC_STREAM_ERR) {
                uvc_trace(UVC_TRACE_FRAME, "Dropping packet (error bit 
set).\n");
-               return 0;
+
+               //return 0;
        }
 
-       fid = data[1] & UVC_STREAM_FID;
+       if (hlen != 0) {
+               fid = flags & UVC_STREAM_FID;
+       }
 
        /* Store the packet FID bit and return immediately when the buffer is
         * NULL.
@@ -1338,28 +1354,33 @@
                                "toggled).\n");
                buf->state = UVC_BUF_STATE_DONE;
                return -EAGAIN;
+       } else if (is_header && buf->buf.bytesused > 0) {
+               buf->state = UVC_BUF_STATE_DONE;
+               return -EAGAIN;
        }
 
        queue->last_fid = fid;
 
        /* Copy the video data to the buffer. */
-       len -= data[0];
+       len -= hlen;
        maxlen = buf->buf.length - buf->buf.bytesused;
-       mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
-       nbytes = min(len, maxlen);
-       memcpy(mem, data + data[0], nbytes);
-       buf->buf.bytesused += nbytes;
+       if (!is_header) { /* we skip headers, they do not contain data */
+               mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+               nbytes = min(len - hlen, maxlen);
+               memmove(mem, data + hlen, nbytes);
+               buf->buf.bytesused += nbytes;
+       }
 
        /* Drop the current frame if the buffer size was exceeded. */
-       if (len > maxlen) {
+       if (len - hlen > maxlen || buf->buf.bytesused == buf->buf.length) {
                uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
                buf->state = UVC_BUF_STATE_DONE;
        }
 
        /* Mark the buffer as done if the EOF marker is set. */
-       if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) {
+       if (hlen != 0 && (flags & UVC_STREAM_EOF && buf->buf.bytesused != 0)) {
                uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
-               if (data[0] == len)
+               if (hlen != 0 && hlen == len)
                        printk("EOF in empty packet.\n");
                buf->state = UVC_BUF_STATE_DONE;
        }
@@ -1597,7 +1618,7 @@
 
        if (ret != size) {
                uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u "
-                       "(unit %u) : %d.\n", query, cs, unit, ret);
+                       "(unit %u) : %d (exp: %u).\n", query, cs, unit, ret, 
size);
                return -EIO;
        }
 
@@ -1887,8 +1908,10 @@
 
        /* Get the minimum and maximum values for compression settings. */
        if ((ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN)) < 0 ||
-           (ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX)) < 0)
+           (ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX)) < 0) {
+               ret = 0;
                goto done;
+       }
 
        probe->wCompQuality = probe_max.wCompQuality;
 
@@ -1946,7 +1969,7 @@
                return ret;
 
        /* Retrieve the default format and commit it. */
-       if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0)
+       if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
                return ret;
        if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0)
                return ret;
@@ -2218,6 +2241,11 @@
        if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0)
                return ret;
 
+       if (probe.dwMaxVideoFrameSize == 0)
+               probe.dwMaxVideoFrameSize =
+                       video->streaming->format[probe.bFormatIndex - 1].
+                               frame[probe.bFrameIndex - 
1].dwMaxVideoFrameBufferSize;
+
        memcpy(&video->streaming->ctrl, &probe, sizeof probe);
        video->streaming->cur_format = format;
        video->streaming->cur_frame = frame;
@@ -3590,6 +3618,13 @@
 
        if (!found) {
                uvc_printk(KERN_INFO, "No valid video chain found.\n");
+               if (dev->udev->descriptor.idVendor == 0x05ac &&
+                   dev->udev->descriptor.idProduct == 0x8300) {
+                       uvc_printk (KERN_ERR, "Possible an Apple iSight "
+                                   "without firmware loaded; please read "
+                                   "the documentation, load the firmware "
+                                   "and re-load the driver.");
+               }
                return -1;
        }
 
@@ -3841,6 +3876,19 @@
          .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0 },
+       /* Apple iSight (built-in in Macintels) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE,
+         .idVendor             = 0x05ac,
+         .idProduct            = 0x8501 },
+       /* same, but without firmware loaded (will give useful warning)
+        * when the firmware is not loaded in the pre-instal step). */
+       { .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 },
        /* Generic USB Video Class */
        { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
        {}



#! /bin/sh /usr/share/dpatch/dpatch-run
## 07_with_isight.dpatch Nobuhiro Iwamatsu <[EMAIL PROTECTED]>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Workaround to get iSight and normal UVC devices function.

@DPATCH@
diff -urN trunk~/uvcvideo.c trunk/uvcvideo.c
--- trunk~/uvcvideo.c   2006-09-10 23:09:20.000000000 +0900
+++ trunk/uvcvideo.c    2006-09-10 23:17:08.000000000 +0900
@@ -288,6 +288,11 @@
        UVC_BUF_STATE_ERROR      = 4,
 };
 
+enum uvc_dev_type{
+       UVC_DEV_ISIGHT          = 0 ,   /* Apple iSight */
+       UVC_DEV_QCAM_FUSION     = 1 ,   /* Qcam Fusion  */
+};
+
 struct uvc_buffer {
        unsigned int size;
        unsigned long vma_use_count;
@@ -379,6 +384,7 @@
 
 static void uvc_delete(struct kref *kref);
 
+static int dev_type ;/* device type */
 /* ------------------------------------------------------------------------
  * Control, formats, ...
  */
@@ -1289,14 +1295,23 @@
         * - bHeaderLength value must be at least 2 bytes (see above)
         * - bHeaderLength value can't be larger than the packet size.
         */
-       if ((len >= 14 && memcmp (&data[3], hdr, 12) == 0) ||
-           (len >= 13 && memcmp (&data[2], hdr, 12) == 0)) {
-               uvc_trace(UVC_TRACE_FRAME, "Detecting new header");
-               hlen = (data[3] == 0x11) ? data[1] : data[0];
-               if (hlen > len - 1 || hlen < 2)
+       if( dev_type != UVC_DEV_ISIGHT ){
+               if (len < 2 || data[0] < 2 || data[0] > len){
                        return -EINVAL;
-               flags = (data[3] == 0x11) ? data[2] : data[1];
-               is_header = 1;
+               }
+
+               hlen  = data[0];
+               flags = data[1];
+       }else{
+               if ((len >= 14 && memcmp (&data[3], hdr, 12) == 0) ||
+               (len >= 13 && memcmp (&data[2], hdr, 12) == 0)) {
+                       uvc_trace(UVC_TRACE_FRAME, "Detecting new header");
+                       hlen = (data[3] == 0x11) ? data[1] : data[0];
+                       if (hlen > len - 1 || hlen < 2)
+                               return -EINVAL;
+                       flags = (data[3] == 0x11) ? data[2] : data[1];
+                       is_header = 1;
+               }
        }
 
        /* Skip payloads marked with the error bit ("error frames"). */
@@ -1364,7 +1379,14 @@
        /* Copy the video data to the buffer. */
        len -= hlen;
        maxlen = buf->buf.length - buf->buf.bytesused;
-       if (!is_header) { /* we skip headers, they do not contain data */
+
+       if(dev_type != UVC_DEV_ISIGHT){
+               mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+               nbytes = min(len, maxlen);
+               memcpy(mem, data + hlen, nbytes);
+               buf->buf.bytesused += nbytes;
+       }else if((dev_type == UVC_DEV_ISIGHT)&& (!is_header)) {
+               /* we skip headers, they do not contain data */
                mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
                nbytes = min(len - hlen, maxlen);
                memmove(mem, data + hlen, nbytes);
@@ -1372,11 +1394,19 @@
        }
 
        /* Drop the current frame if the buffer size was exceeded. */
-       if (len - hlen > maxlen || buf->buf.bytesused == buf->buf.length) {
-               uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
-               buf->state = UVC_BUF_STATE_DONE;
+       if ( dev_type != UVC_DEV_ISIGHT ){
+               if (len > maxlen) {
+                       uvc_trace(UVC_TRACE_FRAME, "Frame complete 
(overflow).\n");
+                       buf->state = UVC_BUF_STATE_DONE;
+               }
+       }else{
+               if (len - hlen > maxlen || buf->buf.bytesused == 
buf->buf.length) {
+                       uvc_trace(UVC_TRACE_FRAME, "Frame complete 
(overflow).\n");
+                       buf->state = UVC_BUF_STATE_DONE;
+               }
        }
 
+
        /* Mark the buffer as done if the EOF marker is set. */
        if (hlen != 0 && (flags & UVC_STREAM_EOF && buf->buf.bytesused != 0)) {
                uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
@@ -3628,8 +3658,15 @@
                        }
                }
 
-               if (found)
+               if (found){
+                       if (dev->udev->descriptor.idVendor == 0x05ac &&
+                               dev->udev->descriptor.idProduct == 0x8300) {
+                               dev_type = UVC_DEV_ISIGHT ;
+                       }else{
+                               dev_type = UVC_DEV_QCAM_FUSION ;
+                       }
                        break;
+               }
        }
 
        if (!found) {


_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel

Reply via email to