This is against 2.3.39-pre6 (or later)

CHANGES:
- The camera detection is now more intelligent and efficient. This is an
attempt
  to eliminate the "Failed to read sensor ID" problem that many people
have.
- Added "i2c_detect_tries" module parameter.
- OV7610 reg COM_F default changed from 0x90 to 0xA2. Bit 2 must be 1
according
  to the 7620 spec, and I assume the same here.
- Added aperture parameter. Values are from 0 - 15 and are sensor
specific.
  Value is written to the upper nybble of 7610/20 reg COM_F.
- ov6710_configure() renamed to ov76xx_configure()
- moved OV511 reg defaults from aRegvalsNorm7610[] to aRegvalsNorm511[]
- moved OV76xx specific code from ov511_configure() to
ov76xx_configure()
- added version constant
- updated memory management functions
- proc filesystem support added
- minor changes in ov511_read()
- ov511_configure() now sets frame->depth and frame->segment; this fixed
read
- ov511_probe() modified to use custom ID table
- ov511.h: PDEBUG updated to print function name and line number
- ov511.h: Added proc fs vars to usb_ov511

-- 
Mark McClelland
[EMAIL PROTECTED]
diff -Naur linux-2.3.99-pre6-orig/Documentation/usb/ov511.txt 
linux/Documentation/usb/ov511.txt
--- linux-2.3.99-pre6-orig/Documentation/usb/ov511.txt  Thu Apr 13 23:23:28 2000
+++ linux/Documentation/usb/ov511.txt   Fri May  5 14:34:20 2000
@@ -6,8 +6,11 @@
 Homepage: http://alpha.dyndns.org/ov511
 
 NEW IN THIS VERSION:
- o Support for OV511+
- o Support for OV7620
+ o Improvements to sensor detection code
+ o Added "i2c_detect_tries" and "aperture" parameters
+ o proc filesystem status support
+ o read() fixed partially
+ o code cleanups and minor fixes
 
 INTRODUCTION:
 
@@ -151,11 +154,13 @@
  o Monochrome
  o Setting/getting of saturation, contrast and brightness (no hue yet; only
    works with OV7610, not the OV7620 or OV7620AE)
+ o proc status reporting
 
 EXPERIMENTAL FEATURES:
  o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
    corrupted frames.
  o Snapshot mode (only works with some read() based apps; see below for more)
+ o read() support
 
 TODO:
  o Fix the noise / grainy image problem.
@@ -180,6 +185,8 @@
  o Get rid of the memory management functions (put them in videodev.c??)
  o Setting of contrast and brightness not working with 7620
  o Driver/camera state save/restore for when USB supports suspend/resume
+ o Multiple cameras reportedly do not work simultaneously
+ o Problems with OHCI
 
 HOW TO CONTACT ME:
 
diff -Naur linux-2.3.99-pre6-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.3.99-pre6-orig/drivers/usb/ov511.c  Thu Apr 13 23:23:44 2000
+++ linux/drivers/usb/ov511.c   Fri May  5 14:34:33 2000
@@ -1,23 +1,20 @@
 /*
  * OmniVision OV511 Camera-to-USB Bridge Driver
- * Copyright (c) 1999/2000 Mark W. McClelland
+ *
+ * Copyright (c) 1999-2000 Mark W. McClelland
  * Many improvements by Bret Wallach
  * Color fixes by by Orion Sky Lawlor, [EMAIL PROTECTED], 2/26/2000
  * Snapshot code by Kevin Moore
  * OV7620 fixes by Charl P. Botha <[EMAIL PROTECTED]>
+ * Changes by Claudio Matsuoka, [EMAIL PROTECTED], 3/26/2000
  * 
- * Based on the Linux CPiA driver.
+ * Based on the Linux CPiA driver written by Peter Pregler,
+ * Scott J. Bertin and Johannes Erdfelt.
  * 
- * Released under GPL v.2 license.
- *
- * Version: 1.11
- *
  * Please see the file: linux/Documentation/usb/ov511.txt 
- * and the website at:  http://alpha.dyndns.org/ov511 
+ * and the website at:  http://alpha.dyndns.org/ov511
  * for more info.
- */
-
-/*
+ *
  * 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
@@ -33,23 +30,28 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+static const char version[] = "1.12";
+
 #define __NO_VERSION__
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/videodev.h>
-#include <linux/vmalloc.h>
-#include <linux/wrapper.h>
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/version.h>
 #include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/pagemap.h>
 #include <linux/usb.h>
 #include <asm/io.h>
+#include <asm/semaphore.h>
+#include <linux/wrapper.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
 
 #include "ov511.h"
 
@@ -59,11 +61,10 @@
 #define MAX_FRAME_SIZE (640 * 480 * 3)
 #define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
 
-// FIXME - Should find a better way to do this.
 #define DEFAULT_WIDTH 640
 #define DEFAULT_HEIGHT 480
 
-// PARAMETER VARIABLES:
+/* PARAMETER VARIABLES: */
 static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
 
 /* 0=no debug messages
@@ -85,24 +86,89 @@
 /* Sensor detection override (global for all attached cameras) */
 static int sensor = 0;
 
+/* Increase this if you are getting "Failed to read sensor ID..." */
+static int i2c_detect_tries = 5;
+
+/* For legal values, see the OV7610/7620 specs under register Common F,
+   upper nybble  (set to 0-F) */
+static int aperture = -1;
+
 MODULE_PARM(autoadjust, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(fix_rgb_offset, "i");
 MODULE_PARM(snapshot, "i");
 MODULE_PARM(sensor, "i");
+MODULE_PARM(i2c_detect_tries, "i");
+MODULE_PARM(aperture, "i");
 
 MODULE_AUTHOR("Mark McClelland (and others)");
 MODULE_DESCRIPTION("OV511 USB Camera Driver");
 
 char kernel_version[] = UTS_RELEASE;
 
-/*******************************/
-/* Memory management functions */
-/*******************************/
+static struct usb_driver ov511_driver;
 
-#define MDEBUG(x)      do { } while(0)         /* Debug memory management */
+/**********************************************************************
+ * List of known OV511-based cameras
+ **********************************************************************/
+
+static struct cam_list clist[] = {
+       {   0, "generic model (no ID)" },
+       {   3, "D-Link DSB-C300" },
+       {   4, "generic OV511/OV7610" },
+       {   5, "Puretek PT-6007" },
+       {  21, "Creative Labs WebCam 3" },
+       {  36, "Koala-Cam" },
+       {  38, "Lifeview USB Life TV" },        /* No support yet! */
+       { 100, "Lifeview RoboCam" },
+       { 102, "AverMedia InterCam Elite" },
+       { 112, "MediaForte MV300" },    /* or OV7110 evaluation kit */
+       {  -1, NULL }
+};
 
-static struct usb_driver ov511_driver;
+/**********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the OV511 driver -claudio
+ **********************************************************************/
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+
+static inline unsigned long uvirt_to_phys(unsigned long adr)
+{
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *ptep, pte;
+
+       pgd = pgd_offset(current->mm, adr);
+       if (pgd_none(*pgd))
+               return 0;
+       pmd = pmd_offset(pgd, adr);
+       if (pmd_none(*pmd))
+               return 0;
+       ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);
+       pte = *ptep;
+       if (pte_present(pte))
+               return virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));
+       return 0;
+}
+
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
+{
+       return uvirt_to_phys(VMALLOC_VMADDR(adr));
+}
+
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) */
 
 /* Given PGD from the address space's page table, return the kernel
  * virtual mapping of the physical memory mapped at ADR.
@@ -119,31 +185,11 @@
                        ptep = pte_offset(pmd, adr);
                        pte = *ptep;
                        if (pte_present(pte))
-                               ret = page_address(pte_page(pte)) | (adr & 
(PAGE_SIZE-1));
+                               ret = page_address(pte_page(pte)) |
+                                     (adr & (PAGE_SIZE-1));
                }
        }
-       MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
-       return ret;
-}
-
-static inline unsigned long uvirt_to_bus(unsigned long adr)
-{
-       unsigned long kva, ret;
 
-       kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
-       ret = virt_to_bus((void *)kva);
-       MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
-       return ret;
-}
-
-static inline unsigned long kvirt_to_bus(unsigned long adr)
-{
-       unsigned long va, kva, ret;
-
-       va = VMALLOC_VMADDR(adr);
-       kva = uvirt_to_kva(pgd_offset_k(va), va);
-       ret = virt_to_bus((void *)kva);
-       MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
        return ret;
 }
 
@@ -158,9 +204,10 @@
        va = VMALLOC_VMADDR(adr);
        kva = uvirt_to_kva(pgd_offset_k(va), va);
        ret = __pa(kva);
-       MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
        return ret;
 }
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) */
+
 
 static void *rvmalloc(unsigned long size)
 {
@@ -179,7 +226,11 @@
        adr = (unsigned long) mem;
        while (size > 0) {
                page = kvirt_to_pa(adr);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+               mem_map_reserve(MAP_NR(phys_to_virt(page)));
+#else
                mem_map_reserve(MAP_NR(__va(page)));
+#endif
                adr += PAGE_SIZE;
                if (size > PAGE_SIZE)
                        size -= PAGE_SIZE;
@@ -203,7 +254,11 @@
        adr=(unsigned long) mem;
        while (size > 0) {
                page = kvirt_to_pa(adr);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+               mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+#else
                mem_map_unreserve(MAP_NR(__va(page)));
+#endif
                adr += PAGE_SIZE;
                if (size > PAGE_SIZE)
                        size -= PAGE_SIZE;
@@ -213,9 +268,290 @@
        vfree(mem);
 }
 
+/**********************************************************************
+ * /proc interface
+ * Based on the CPiA driver version 0.7.4 -claudio
+ **********************************************************************/
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *ov511_proc_root = NULL;
+
+#define YES_NO(x) (x ? "yes" : "no")
+
+static int ov511_read_proc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+       char *out = page;
+       int i, len;
+       struct usb_ov511 *ov511 = data;
+
+       /* IMPORTANT: This output MUST be kept under PAGE_SIZE
+        *            or we need to get more sophisticated. */
+
+       out += sprintf (out, "custom_id       : %d\n", ov511->customid);
+       out += sprintf (out, "model           : %s\n", ov511->desc ?
+               clist[ov511->desc].description : "unknown");
+       out += sprintf (out, "streaming       : %s\n", YES_NO (ov511->streaming));
+       out += sprintf (out, "grabbing        : %s\n", YES_NO (ov511->grabbing));
+       out += sprintf (out, "compress        : %s\n", YES_NO (ov511->compress));
+       out += sprintf (out, "subcapture      : %s\n", YES_NO (ov511->sub_flag));
+       out += sprintf (out, "sub_size        : %d %d %d %d\n",
+               ov511->subx, ov511->suby, ov511->subw, ov511->subh);
+       out += sprintf (out, "num_frames      : %d\n", OV511_NUMFRAMES);
+       for (i = 0; i < OV511_NUMFRAMES; i++) {
+               out += sprintf (out, "frame           : %d\n", i);
+               out += sprintf (out, "  depth         : %d\n",
+                       ov511->frame[i].depth);
+               out += sprintf (out, "  size          : %d %d\n",
+                       ov511->frame[i].width, ov511->frame[i].height);
+               out += sprintf (out, "  hdr_size      : %d %d\n",
+                       ov511->frame[i].hdrwidth, ov511->frame[i].hdrheight);
+               out += sprintf (out, "  format        : %d\n",
+                       ov511->frame[i].format);
+               out += sprintf (out, "  segsize       : %d\n",
+                       ov511->frame[i].segsize);
+#if 0
+               out += sprintf (out, "  curline       : %d\n",
+                       ov511->frame[i].curline);
+               out += sprintf (out, "  segment       : %d\n",
+                       ov511->frame[i].segment);
+               out += sprintf (out, "  scanlength    : %ld\n",
+                       ov511->frame[i].scanlength);
+               out += sprintf (out, "  bytesread     : %ld\n",
+                       ov511->frame[i].bytes_read);
+#endif
+       }
+       out += sprintf (out, "snap_enabled    : %s\n", YES_NO (ov511->snap_enabled));
+       out += sprintf (out, "bridge          : %d\n", ov511->bridge);
+       out += sprintf (out, "sensor          : %d\n", ov511->sensor);
+       out += sprintf (out, "packet_size     : %d\n", ov511->packet_size);
+       
+       len = out - page;
+       len -= off;
+       if (len < count) {
+               *eof = 1;
+               if (len <= 0) return 0;
+       } else
+               len = count;
+
+       *start = page + off;
+       return len;
+}
+
+static int ov511_write_proc(struct file *file, const char *buffer,
+                           unsigned long count, void *data)
+{
+       int retval = -EINVAL;
+
+#if 0
+       /* struct cam_data *cam = data; */
+       struct usb_ov511 new_params;
+       int size = count;
+       int find_colon;
+       unsigned long val;
+       u32 command_flags = 0;
+       u8 new_mains;
+       
+       if (down_interruptible(&cam->param_lock))
+               return -ERESTARTSYS;
+       
+       /*
+        * Skip over leading whitespace
+        */
+       while (count && isspace(*buffer)) {
+               --count;
+               ++buffer;
+       }
+       
+       
+#define MATCH(x) \
+       ({ \
+               int _len = strlen(x), _ret, _colon_found; \
+               _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
+               if (_ret) { \
+                       buffer += _len; \
+                       count -= _len; \
+                       if (find_colon) { \
+                               _colon_found = 0; \
+                               while (count && (*buffer == ' ' || *buffer == '\t' || \
+                                      (!_colon_found && *buffer == ':'))) { \
+                                       if (*buffer == ':')  \
+                                               _colon_found = 1; \
+                                       --count; \
+                                       ++buffer; \
+                               } \
+                               if (!count || !_colon_found) \
+                                       retval = -EINVAL; \
+                               find_colon = 0; \
+                       } \
+               } \
+               _ret; \
+       })
+
+#define VALUE \
+       ({ \
+               char *_p; \
+               unsigned long int _ret; \
+               _ret = simple_strtoul(buffer, &_p, 0); \
+               if (_p == buffer) \
+                       retval = -EINVAL; \
+               else { \
+                       count -= _p - buffer; \
+                       buffer = _p; \
+               } \
+               _ret; \
+       })
+
+
+       retval = 0;
+       while (count && !retval) {
+               find_colon = 1;
+
+               if (MATCH("")) {
+                       if (!retval)
+                               val = VALUE;
+
+                       if (!retval) {
+                               if (val <= 0xff)
+                                       /* ... = val */ ;
+                               else
+                                       retval = -EINVAL;
+                       }
+               } else {
+                       DBG("No match found\n");
+                       retval = -EINVAL;
+               }
+
+               if (!retval) {
+                       while (count && isspace(*buffer) && *buffer != '\n') {
+                               --count;
+                               ++buffer;
+                       }
+                       if (count) {
+                               if (*buffer != '\n' && *buffer != ';')
+                                       retval = -EINVAL;
+                               else {
+                                       --count;
+                                       ++buffer;
+                               }
+                       }
+               }
+       }
+
+#undef MATCH   
+#undef FIRMWARE_VERSION
+#undef VALUE
+#undef FIND_VALUE
+#undef FIND_END
+       if (!retval) {
+               if (command_flags & COMMAND_SETCOLOURPARAMS) {
+                       /* Adjust cam->vp to reflect these changes */
+                       cam->vp.brightness =
+                               new_params.colourParams.brightness*65535/100;
+                       cam->vp.contrast =
+                               new_params.colourParams.contrast*65535/100;
+                       cam->vp.colour =
+                               new_params.colourParams.saturation*65535/100;
+               }
+               
+               memcpy(&cam->params, &new_params, sizeof(struct cam_params));
+               cam->mainsFreq = new_mains;
+               cam->cmd_queue |= command_flags;
+               retval = size;
+       } else
+               PDEBUG(3, "error: %d\n", retval);
+       
+       up(&cam->param_lock);
+#endif
+       
+       return retval;
+}
+
+static void create_proc_ov511_cam (struct usb_ov511 *ov511)
+{
+       char name[7];
+       struct proc_dir_entry *ent;
+       
+       PDEBUG (4, "***************");
+       if (!ov511_proc_root || !ov511)
+               return;
+
+       sprintf(name, "video%d", ov511->vdev.minor);
+       PDEBUG (4, "==== name: %s", name);
+       
+       ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_root);
+       if (!ent)
+               return;
+
+       ent->data = ov511;
+       ent->read_proc = ov511_read_proc;
+       ent->write_proc = ov511_write_proc;
+       ent->size = 3626;       /* FIXME */
+       ov511->proc_entry = ent;
+}
+
+static void destroy_proc_ov511_cam (struct usb_ov511 *ov511)
+{
+       char name[7];
+       
+       if (!ov511 || !ov511->proc_entry)
+               return;
+       
+       sprintf(name, "video%d", ov511->vdev.minor);
+       PDEBUG (4, "==== name: %s", name);
+#if 0
+       remove_proc_entry(name, ov511_proc_root);
+       ov511->proc_entry = NULL;
+#endif
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+/*
+ * This is called as the fill_inode function when an inode
+ * is going into (fill = 1) or out of service (fill = 0).
+ * We use it here to manage the module use counts.
+ */
+static void proc_ov511_modcount(struct inode *inode, int fill)
+{
+#ifdef MODULE
+       if (fill)
+               MOD_INC_USE_COUNT;
+       else
+               MOD_DEC_USE_COUNT;
+#endif
+}
+#endif
+
+static void proc_ov511_create(void)
+{
+       ov511_proc_root = create_proc_entry("ov511", S_IFDIR, 0);
+
+       if (ov511_proc_root) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+               ov511_proc_root->fill_inode = &proc_ov511_modcount;
+#else
+               ov511_proc_root->owner = THIS_MODULE;
+#endif
+       } else
+               printk("Unable to initialise /proc/ov511\n");   /***********/
+}
+
+static void proc_ov511_destroy(void)
+{
+       remove_proc_entry("ov511", 0);
+}
+#endif /* CONFIG_PROC_FS */
+
+
+/**********************************************************************
+ *
+ * Camera interface
+ *
+ **********************************************************************/
+
 static int ov511_reg_write(struct usb_device *dev,
-                           unsigned char reg,
-                           unsigned char value)
+                          unsigned char reg,
+                          unsigned char value)
 {
        int rc;
 
@@ -233,6 +569,7 @@
        return rc;
 }
 
+
 /* returns: negative is error, pos or zero is data */
 static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
 {
@@ -247,24 +584,25 @@
                                
        PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]);
        
-       if(rc < 0) {
+       if (rc < 0) {
                err("ov511_reg_read: error %d", rc);
                return rc;
-       }
-       else
+       } else {
                return buffer[0];       
+       }
 }
 
+
 static int ov511_i2c_write(struct usb_device *dev,
-                           unsigned char reg,
-                           unsigned char value)
+                          unsigned char reg,
+                          unsigned char value)
 {
        int rc, retries;
 
        PDEBUG(5, "i2c write: 0x%02X:0x%02X", reg, value);
 
        /* Three byte write cycle */
-       for(retries = OV511_I2C_RETRIES;;) {
+       for (retries = OV511_I2C_RETRIES; ; ) {
                /* Select camera register */
                rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
                if (rc < 0) goto error;
@@ -278,10 +616,10 @@
                if (rc < 0) goto error;
 
                do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
-               while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+               while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
                if (rc < 0) goto error;
 
-               if((rc&2) == 0) /* Ack? */
+               if ((rc&2) == 0) /* Ack? */
                        break;
 #if 0
                /* I2C abort */ 
@@ -301,13 +639,14 @@
        return rc;
 }
 
+
 /* returns: negative is error, pos or zero is data */
 static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
 {
        int rc, value, retries;
 
        /* Two byte write cycle */
-       for(retries = OV511_I2C_RETRIES;;) {
+       for (retries = OV511_I2C_RETRIES; ; ) {
                /* Select camera register */
                rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
                if (rc < 0) goto error;
@@ -317,10 +656,10 @@
                if (rc < 0) goto error;
 
                do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
-               while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+               while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
                if (rc < 0) goto error;
 
-               if((rc&2) == 0) /* Ack? */
+               if ((rc&2) == 0) /* Ack? */
                        break;
 
                /* I2C abort */ 
@@ -334,16 +673,16 @@
        }
 
        /* Two byte read cycle */
-       for(retries = OV511_I2C_RETRIES;;) {
+       for (retries = OV511_I2C_RETRIES; ; ) {
                /* Initiate 2-byte read cycle */
                rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
                if (rc < 0) goto error;
 
                do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
-               while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+               while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
                if (rc < 0) goto error;
 
-               if((rc&2) == 0) /* Ack? */
+               if ((rc&2) == 0) /* Ack? */
                        break;
 
                /* I2C abort */ 
@@ -363,7 +702,8 @@
                
        /* This is needed to make ov511_i2c_write() work */
        rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
-       if (rc < 0) goto error;
+       if (rc < 0)
+               goto error;
        
        return value;
 
@@ -372,12 +712,13 @@
        return rc;
 }
 
+
 static int ov511_write_regvals(struct usb_device *dev,
                               struct ov511_regvals * pRegvals)
 {
        int rc;
 
-       while(pRegvals->bus != OV511_DONE_BUS) {
+       while (pRegvals->bus != OV511_DONE_BUS) {
                if (pRegvals->bus == OV511_REG_BUS) {
                        if ((rc = ov511_reg_write(dev, pRegvals->reg,
                                                   pRegvals->val)) < 0)
@@ -400,6 +741,7 @@
        return rc;
 }
 
+
 #if 0
 static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
 {
@@ -411,12 +753,14 @@
        }
 }
 
+
 static void ov511_dump_i2c_regs( struct usb_device *dev)
 {
        PDEBUG(3, "I2C REGS");
        ov511_dump_i2c_range(dev, 0x00, 0x38);
 }
 
+
 static void ov511_dump_reg_range( struct usb_device *dev, int reg1, int regn)
 {
        int i;
@@ -427,6 +771,7 @@
        }
 }
 
+
 static void ov511_dump_regs( struct usb_device *dev)
 {
        PDEBUG(1, "CAMERA INTERFACE REGS");
@@ -451,6 +796,7 @@
 }
 #endif
 
+
 static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
        int rc;
@@ -465,6 +811,7 @@
        return rc;
 }
 
+
 /* Temporarily stops OV511 from functioning. Must do this before changing
  * registers while the camera is streaming */
 static inline int ov511_stop(struct usb_device *dev)
@@ -473,6 +820,7 @@
        return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
 }
 
+
 /* Restarts OV511 after ov511_stop() is called */
 static inline int ov511_restart(struct usb_device *dev)
 {
@@ -480,6 +828,7 @@
        return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
 }
 
+
 static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
 {
        int alt, mult;
@@ -487,7 +836,7 @@
        if (ov511_stop(ov511->dev) < 0)
                return -EIO;
 
-       mult = size / 32;
+       mult = size >> 5;
 
        if (ov511->bridge == BRG_OV511) {
                if (size == 0) alt = OV511_ALT_SIZE_0;
@@ -502,8 +851,7 @@
                        err("Set packet size: invalid size (%d)", size);
                        return -EINVAL;
                }
-       }
-       else if (ov511->bridge == BRG_OV511PLUS) {
+       } else if (ov511->bridge == BRG_OV511PLUS) {
                if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
                else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
                else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
@@ -516,16 +864,14 @@
                        err("Set packet size: invalid size (%d)", size);
                        return -EINVAL;
                }
-       }
-       else {
+       } else {
                err("Set packet size: Invalid bridge type");
                return -EINVAL;
        }
 
        PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
 
-       if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
-                            mult) < 0)
+       if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, mult) < 0)
                return -ENOMEM;
        
        if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
@@ -545,8 +891,9 @@
        return 0;
 }
 
-static inline int ov7610_set_picture(struct usb_ov511 *ov511,
-                                     struct video_picture *p)
+
+static inline int
+ov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
 {
        int ret;
        struct usb_device *dev = ov511->dev;
@@ -556,10 +903,10 @@
        if (ov511_stop(dev) < 0)
                return -EIO;
 
-       if((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
+       if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
                return -EIO;
 #if 0
-       if(ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
+       if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
                return -EIO;
 #endif
        if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE)
@@ -572,17 +919,18 @@
 
                if(ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
                        return -EIO;
-       }               
-       else if ((ov511->sensor == SEN_OV7620) 
+       } else if ((ov511->sensor == SEN_OV7620) 
                 || (ov511->sensor == SEN_OV7620AE)) {
-//             cur_con = ov511_i2c_read(dev, OV7610_REG_CNT);
-//             cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT);
-//             // DEBUG_CODE
-//             PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT),
-//                                        ov511_i2c_read(dev, OV7610_REG_BRT)); 
-//
-//             if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
-//                     return -EIO;
+#if 0
+               cur_con = ov511_i2c_read(dev, OV7610_REG_CNT);
+               cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT);
+               // DEBUG_CODE
+               PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT),
+                ov511_i2c_read(dev, OV7610_REG_BRT)); 
+
+               if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+                       return -EIO;
+#endif
        }
 
        if (ov511_restart(dev) < 0)
@@ -591,8 +939,9 @@
        return 0;
 }
 
-static inline int ov7610_get_picture(struct usb_ov511 *ov511,
-                                     struct video_picture *p)
+
+static inline int
+ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
 {
        int ret;
        struct usb_device *dev = ov511->dev;
@@ -613,7 +962,11 @@
 
        p->hue = 0x8000;
        p->whiteness = 105 << 8;
+#if 0
        p->depth = 3;  /* Don't know if this is right */
+#else
+       p->depth = 24;
+#endif
        p->palette = VIDEO_PALETTE_RGB24;
 
        if (ov511_restart(dev) < 0)
@@ -622,15 +975,17 @@
        return 0;
 }
 
-static int ov511_mode_init_regs(struct usb_ov511 *ov511,
-                               int width, int height, int mode, int sub_flag)
+
+static int
+ov511_mode_init_regs(struct usb_ov511 *ov511,
+                    int width, int height, int mode, int sub_flag)
 {
        int rc = 0;
        struct usb_device *dev = ov511->dev;
-        int hwsbase = 0;
-        int hwebase = 0;
+       int hwsbase = 0;
+       int hwebase = 0;
 
-       PDEBUG(3, "ov511_mode_init_regs(ov511, w:%d, h:%d, mode:%d, sub:%d)",
+       PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
               width, height, mode, sub_flag);
 
        if (ov511_stop(ov511->dev) < 0)
@@ -644,34 +999,39 @@
                        ov511_i2c_write(dev, 0x0e, 0x44);
                }
                ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);
+
                /* For snapshot */
                ov511_reg_write(dev, 0x1e, 0x00);
                ov511_reg_write(dev, 0x1f, 0x01);
        } else {
                ov511_reg_write(dev, 0x16, 0x01);
-               if (ov511->sensor == SEN_OV7610
+               if (ov511->sensor == SEN_OV7610
                    || ov511->sensor == SEN_OV7620AE) {
-                  /* not valid on the OV7620 */
-                  ov511_i2c_write(dev, 0x0e, 0x04);
+                       /* not valid on the OV7620 */
+                       ov511_i2c_write(dev, 0x0e, 0x04);
                }
                ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);
+
                /* For snapshot */
                ov511_reg_write(dev, 0x1e, 0x01);
                ov511_reg_write(dev, 0x1f, 0x03);
        }
 
        /* The different sensor ICs handle setting up of window differently */
-        switch (ov511->sensor) {
-        case SEN_OV7610:
-        case SEN_OV7620AE:
-          hwsbase = 0x38;
-          hwebase = 0x3a; break;
-        case SEN_OV7620:
-          hwsbase = 0x2c;
-          hwebase = 0x2d; break;
-        default:
-          hwsbase = 0;
-          hwebase = 0; break;
+       switch (ov511->sensor) {
+       case SEN_OV7610:
+       case SEN_OV7620AE:
+               hwsbase = 0x38;
+               hwebase = 0x3a;
+               break;
+       case SEN_OV7620:
+               hwsbase = 0x2c;
+               hwebase = 0x2d;
+               break;
+       default:
+               hwsbase = 0;
+               hwebase = 0;
+               break;
        }
 
        if (width == 640 && height == 480) {
@@ -680,12 +1040,12 @@
                        ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>2));
                        /* horizontal window end */
                        ov511_i2c_write(dev, 0x18,
-                                       hwebase+((ov511->subx+ov511->subw)>>2));
+                               hwebase+((ov511->subx+ov511->subw)>>2));
                        /* vertical window start */
-                       ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1));
+                       ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1));
                        /* vertical window end */
-                   ov511_i2c_write(dev, 0x1a,
-                                       0x5+((ov511->suby+ov511->subh)>>1));
+                       ov511_i2c_write(dev, 0x1a,
+                               0x5+((ov511->suby+ov511->subh)>>1));
                        ov511_reg_write(dev, 0x12, (ov511->subw>>3)-1);
                        ov511_reg_write(dev, 0x13, (ov511->subh>>3)-1);
                        /* clock rate control */
@@ -762,255 +1122,267 @@
        return rc;
 }
 
-       
-/*************************************************************
-
-Turn a YUV4:2:0 block into an RGB block
-
-Video4Linux seems to use the blue, green, red channel
-order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
 
-Color space conversion coefficients taken from the excellent
-http://www.inforamp.net/~poynton/ColorFAQ.html
-In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
-Y values are given for all 4 pixels, but the U (Pb)
-and V (Pr) are assumed constant over the 2x2 block.
+/**********************************************************************
+ *
+ * Color correction functions
+ *
+ **********************************************************************/
 
-To avoid floating point arithmetic, the color conversion
-coefficients are scaled into 16.16 fixed-point integers.
+/*
+ * Turn a YUV4:2:0 block into an RGB block
+ *
+ * Video4Linux seems to use the blue, green, red channel
+ * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
+ *
+ * Color space conversion coefficients taken from the excellent
+ * http://www.inforamp.net/~poynton/ColorFAQ.html
+ * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
+ * Y values are given for all 4 pixels, but the U (Pb)
+ * and V (Pr) are assumed constant over the 2x2 block.
+ *
+ * To avoid floating point arithmetic, the color conversion
+ * coefficients are scaled into 16.16 fixed-point integers.
+ */
 
-*************************************************************/
-// LIMIT: convert a 16.16 fixed-point value to a byte, with clipping.
+/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
-static inline void ov511_move_420_block(
-                       int yTL, int yTR, int yBL, int yBR,
-                                       int u, int v, 
-                                       int rowPixels, unsigned char * rgb)
-{
-       const double brightness=1.0;//0->black; 1->full scale
-       const double saturation=1.0;//0->greyscale; 1->full color
-       const double fixScale=brightness*256*256;
-       const int rvScale=(int)(1.402*saturation*fixScale);
-       const int guScale=(int)(-0.344136*saturation*fixScale);
-       const int gvScale=(int)(-0.714136*saturation*fixScale);
-       const int buScale=(int)(1.772*saturation*fixScale);
-       const int yScale=(int)(fixScale);       
-
-       int r    =               rvScale * v;
-       int g    = guScale * u + gvScale * v;
-       int b    = buScale * u;
+
+static inline void
+ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
+       int rowPixels, unsigned char * rgb)
+{
+       const double brightness = 1.0; // 0->black; 1->full scale
+       const double saturation = 1.0; // 0->greyscale; 1->full color
+       const double fixScale = brightness * 256 * 256;
+       const int rvScale = (int)(1.402 * saturation * fixScale);
+       const int guScale = (int)(-0.344136 * saturation * fixScale);
+       const int gvScale = (int)(-0.714136 * saturation * fixScale);
+       const int buScale = (int)(1.772 * saturation * fixScale);
+       const int yScale = (int)(fixScale);     
+
+       int r = rvScale * v;
+       int g = guScale * u + gvScale * v;
+       int b = buScale * u;
        yTL *= yScale; yTR *= yScale;
        yBL *= yScale; yBR *= yScale;
 
        //Write out top two pixels
-       rgb[0]=LIMIT(b+yTL); rgb[1]=LIMIT(g+yTL); rgb[2]=LIMIT(r+yTL);
-       rgb[3]=LIMIT(b+yTR); rgb[4]=LIMIT(g+yTR); rgb[5]=LIMIT(r+yTR);
-       rgb+=3*rowPixels;//Skip down to next line to write out bottom two pixels
-       rgb[0]=LIMIT(b+yBL); rgb[1]=LIMIT(g+yBL); rgb[2]=LIMIT(r+yBL);
-       rgb[3]=LIMIT(b+yBR); rgb[4]=LIMIT(g+yBR); rgb[5]=LIMIT(r+yBR);
-}
-
+       rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
+       rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);
 
-/***************************************************************
-
-For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.  The
-first 64 bytes of each segment are U, the next 64 are V.  The U and
-V are arranged as follows:
-
-  0  1 ...  7
-  8  9 ... 15
-       ...   
- 56 57 ... 63
-
-U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
-
-The next 256 bytes are full resolution Y data and represent 4 
-squares of 8x8 pixels as follows:
-
-  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
-  8  9 ... 15    72  73 ...  79        200 201 ... 207
-       ...              ...                    ...
- 56 57 ... 63   120 121     127        248 249 ... 255
+       //Skip down to next line to write out bottom two pixels
+       rgb += 3 * rowPixels;
+       rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
+       rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
+}
 
-Note that the U and V data in one segment represents a 16 x 16 pixel
-area, but the Y data represents a 32 x 8 pixel area.
 
-If OV511_DUMPPIX is defined, _parse_data just dumps the
-incoming segments, verbatim, in order, into the frame.
-When used with vidcat -f ppm -s 640x480 this puts the data
-on the standard output and can be analyzed with the parseppm.c
-utility I wrote.  That's a much faster way for figuring out how
-this data is scrambled.
+/*
+ * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.
+ * The first 64 bytes of each segment are U, the next 64 are V.  The U and
+ * V are arranged as follows:
+ *
+ *      0  1 ...  7
+ *      8  9 ... 15
+ *           ...   
+ *     56 57 ... 63
+ *
+ * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
+ *
+ * The next 256 bytes are full resolution Y data and represent 4 squares
+ * of 8x8 pixels as follows:
+ *
+ *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+ *      8  9 ... 15    72  73 ...  79        200 201 ... 207
+ *           ...              ...                    ...
+ *     56 57 ... 63   120 121     127        248 249 ... 255
+ *
+ * Note that the U and V data in one segment represents a 16 x 16 pixel
+ * area, but the Y data represents a 32 x 8 pixel area.
+ *
+ * If OV511_DUMPPIX is defined, _parse_data just dumps the incoming segments,
+ * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
+ * this puts the data on the standard output and can be analyzed with the
+ * parseppm.c utility I wrote.  That's a much faster way for figuring out how
+ * this data is scrambled.
+ */
 
-****************************************************************/ 
 #define HDIV 8
 #define WDIV (256/HDIV)
 
+#undef OV511_DUMPPIX
 
-static void ov511_parse_data_rgb24(unsigned char * pIn0,
-                                  unsigned char * pOut0,
-                                  int iOutY,
-                                  int iOutUV,
-                                  int iHalf,
-                                  int iWidth)
-                                                   
+static void
+ov511_parse_data_rgb24(unsigned char * pIn0, unsigned char * pOut0,
+                      int iOutY, int iOutUV, int iHalf, int iWidth)                   
+             
 {
 #ifndef OV511_DUMPPIX
-    int k, l, m;
-    unsigned char * pIn;
-    unsigned char * pOut, * pOut1;
-
-    /* Just copy the Y's if in the first stripe */
-    if (!iHalf) {
-       pIn = pIn0 + 128;
-       pOut = pOut0 + iOutY;
-       for(k=0; k<4; k++) {
-           pOut1 = pOut;
-           for(l=0; l<8; l++) {
-             for(m=0; m<8; m++) {
-               *pOut1 = *pIn++;
-               pOut1 += 3;
-             }
-             pOut1 += (iWidth - 8) * 3;
-           }
-           pOut += 8 * 3;
-       }
-    }
-
-    /* Use the first half of VUs to calculate value */
-    pIn = pIn0;
-    pOut = pOut0 + iOutUV;
-    for(l=0; l<4; l++) {
-       for(m=0; m<8; m++) {
-           int y00 = *(pOut);
-           int y01 = *(pOut+3);
-           int y10 = *(pOut+iWidth*3);
-           int y11 = *(pOut+iWidth*3+3);
-           int v   = *(pIn+64) - 128;
-           int u   = *pIn++ - 128;
-           ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut);
-           pOut += 6;
-       }
-       pOut += (iWidth*2 - 16) * 3;
-    }
-
-    /* Just copy the other UV rows */
-    for(l=0; l<4; l++) {
-       for(m=0; m<8; m++) {
-         *pOut++ = *(pIn + 64);
-         *pOut = *pIn++;
-         pOut += 5;
-       }
-       pOut += (iWidth*2 - 16) * 3;
-    }
-
-    /* Calculate values if it's the second half */
-    if (iHalf) {
-       pIn = pIn0 + 128;
-       pOut = pOut0 + iOutY;
-       for(k=0; k<4; k++) {
-           pOut1 = pOut;
-           for(l=0; l<4; l++) {
-             for(m=0; m<4; m++) {
-               int y10 = *(pIn+8);
-               int y00 = *pIn++;
-               int y11 = *(pIn+8);
-               int y01 = *pIn++;
-               int v   = *pOut1 - 128;
-               int u   = *(pOut1+1) - 128;
-               ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut1);
-               pOut1 += 6;
-             }
-             pOut1 += (iWidth*2 - 8) * 3;
-             pIn += 8;
-           }
-           pOut += 8 * 3;
+       int k, l, m;
+       unsigned char * pIn;
+       unsigned char * pOut, * pOut1;
+
+       /* Just copy the Y's if in the first stripe */
+       if (!iHalf) {
+               pIn = pIn0 + 128;
+               pOut = pOut0 + iOutY;
+               for (k = 0; k < 4; k++) {
+                       pOut1 = pOut;
+                       for (l = 0; l < 8; l++) {
+                               for (m = 0; m < 8; m++) {
+                                       *pOut1 = *pIn++;
+                                       pOut1 += 3;
+                               }
+                               pOut1 += (iWidth - 8) * 3;
+                       }
+                       pOut += 8 * 3;
+               }
+       }
+
+       /* Use the first half of VUs to calculate value */
+       pIn = pIn0;
+       pOut = pOut0 + iOutUV;
+       for (l = 0; l < 4; l++) {
+               for (m=0; m<8; m++) {
+                       int y00 = *(pOut);
+                       int y01 = *(pOut+3);
+                       int y10 = *(pOut+iWidth*3);
+                       int y11 = *(pOut+iWidth*3+3);
+                       int v   = *(pIn+64) - 128;
+                       int u   = *pIn++ - 128;
+                       ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,
+                               pOut);
+                       pOut += 6;
+               }
+               pOut += (iWidth*2 - 16) * 3;
+       }
+
+       /* Just copy the other UV rows */
+       for (l = 0; l < 4; l++) {
+               for (m = 0; m < 8; m++) {
+                       *pOut++ = *(pIn + 64);
+                       *pOut = *pIn++;
+                       pOut += 5;
+               }
+               pOut += (iWidth*2 - 16) * 3;
+       }
+
+       /* Calculate values if it's the second half */
+       if (iHalf) {
+               pIn = pIn0 + 128;
+               pOut = pOut0 + iOutY;
+               for (k = 0; k < 4; k++) {
+                       pOut1 = pOut;
+                       for (l=0; l<4; l++) {
+                               for (m=0; m<4; m++) {
+                                       int y10 = *(pIn+8);
+                                       int y00 = *pIn++;
+                                       int y11 = *(pIn+8);
+                                       int y01 = *pIn++;
+                                       int v   = *pOut1 - 128;
+                                       int u   = *(pOut1+1) - 128;
+                                       ov511_move_420_block(y00, y01, y10,
+                                               y11, u, v, iWidth, pOut1);
+                                       pOut1 += 6;
+                               }
+                               pOut1 += (iWidth*2 - 8) * 3;
+                               pIn += 8;
+                       }
+                       pOut += 8 * 3;
+               }
        }
-    }
 
 #else
        /* Just dump pix data straight out for debug */
-       int i;
-       pOut0 += iSegmentY * 384;
-       for(i=0; i<384; i++) {
-         *pOut0++ = *pIn0++;
+       int i, j;
+
+       pOut0 += iOutY;
+       for (i = 0; i < HDIV; i++) {
+               for (j = 0; j < WDIV; j++) {
+                       *pOut0++ = *pIn0++;
+                       *pOut0++ = *pIn0++;
+                       *pOut0++ = *pIn0++;
+               }
+               pOut0 += (iWidth - WDIV) * 3;
        }
 #endif
 }
 
-/***************************************************************
 
-For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
-The segments represent 4 squares of 8x8 pixels as
-follows:
-
-  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
-  8  9 ... 15    72  73 ...  79        200 201 ... 207
-       ...              ...                    ...
- 56 57 ... 63   120 121     127        248 249 ... 255
-
-****************************************************************/ 
-static void ov511_parse_data_grey(unsigned char * pIn0,
-                                 unsigned char * pOut0,
-                                 int iOutY,
-                                 int iWidth)
-                           
-{
-    int k, l, m;
-    unsigned char * pIn;
-    unsigned char * pOut, * pOut1;
+/*
+ * For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
+ * The segments represent 4 squares of 8x8 pixels as follows:
+ *
+ *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+ *      8  9 ... 15    72  73 ...  79        200 201 ... 207
+ *           ...              ...                    ...
+ *     56 57 ... 63   120 121     127        248 249 ... 255
+ *
+ */ 
+static void
+ov511_parse_data_grey(unsigned char * pIn0, unsigned char * pOut0,
+                     int iOutY, int iWidth)                
+{
+       int k, l, m;
+       unsigned char *pIn;
+       unsigned char *pOut, *pOut1;
 
-    pIn = pIn0;
-    pOut = pOut0 + iOutY;
-    for(k=0; k<4; k++) {
-      pOut1 = pOut;
-      for(l=0; l<8; l++) {
-       for(m=0; m<8; m++) {
-         *pOut1++ = *pIn++;
+       pIn = pIn0;
+       pOut = pOut0 + iOutY;
+       for (k = 0; k < 4; k++) {
+               pOut1 = pOut;
+               for (l = 0; l < 8; l++) {
+                       for (m = 0; m < 8; m++) {
+                               *pOut1++ = *pIn++;
+                       }
+                       pOut1 += iWidth - 8;
+               }
+               pOut += 8;
        }
-       pOut1 += iWidth - 8;
-      }
-      pOut += 8;
-    }
 }
 
 
-/**************************************************************
+/*
  * fixFrameRGBoffset--
  * My camera seems to return the red channel about 1 pixel
  * low, and the blue channel about 1 pixel high. After YUV->RGB
  * conversion, we can correct this easily. OSL 2/24/2000.
- *************************************************************/
+ */
 static void fixFrameRGBoffset(struct ov511_frame *frame)
 {
-  int x, y;
-  int rowBytes = frame->width*3, w = frame->width;
-  unsigned char *rgb = frame->data;
-  const int shift = 1;   //Distance to shift pixels by, vertically
-
-  if (frame->width < 400) 
-          return;     //Don't bother with little images
-
-  //Shift red channel up
-  for (y = shift; y < frame->height; y++)
-  {
-    int lp = (y-shift)*rowBytes;     //Previous line offset
-    int lc = y*rowBytes;             //Current line offset
-    for (x = 0; x < w; x++)
-      rgb[lp+x*3+2] = rgb[lc+x*3+2]; //Shift red up
-  }
-
-  //Shift blue channel down
-  for (y=frame->height-shift-1; y >= 0; y--)
-  {
-    int ln = (y+shift)*rowBytes;   //Next line offset
-    int lc = y*rowBytes;           //Current line offset
-    for (x = 0; x < w; x++)
-      rgb[ln+x*3+0] = rgb[lc+x*3+0]; //Shift blue down
-  }
+       int x, y;
+       int rowBytes = frame->width*3, w = frame->width;
+       unsigned char *rgb = frame->data;
+       const int shift = 1;  /* Distance to shift pixels by, vertically */
+
+       /* Don't bother with little images */
+       if (frame->width < 400) 
+               return;
+
+       /* Shift red channel up */
+       for (y = shift; y < frame->height; y++) {
+               int lp = (y-shift)*rowBytes;     /* Previous line offset */
+               int lc = y*rowBytes;             /* Current line offset */
+               for (x = 0; x < w; x++)
+                       rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
+       }
+
+       /* Shift blue channel down */
+       for (y = frame->height-shift-1; y >= 0; y--) {
+               int ln = (y + shift) * rowBytes;  /* Next line offset */
+               int lc = y * rowBytes;            /* Current line offset */
+               for (x = 0; x < w; x++)
+                       rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
+       }
 }
 
 
+/**********************************************************************
+ *
+ * OV511 data transfer, IRQ handler
+ *
+ **********************************************************************/
+
 static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
 {
        unsigned char *cdata;
@@ -1175,6 +1547,7 @@
        return totlen;
 }
 
+
 static void ov511_isoc_irq(struct urb *urb)
 {
        int len;
@@ -1187,28 +1560,32 @@
        if (!ov511->streaming) {
                PDEBUG(2, "hmmm... not streaming, but got interrupt");
                return;
+       } else {
+               PDEBUG(5, "streaming. got interrupt");
        }
        
        sbuf = &ov511->sbuf[ov511->cursbuf];
 
        /* Copy the data received into our scratch buffer */
-       if (ov511->curframe >= 0)
-         len = ov511_move_data(ov511, urb);
-       else if (waitqueue_active(&ov511->wq))
-         wake_up_interruptible(&ov511->wq);
-       
+       if (ov511->curframe >= 0) {
+               len = ov511_move_data(ov511, urb);
+       } else if (waitqueue_active(&ov511->wq)) {
+               wake_up_interruptible(&ov511->wq);
+       }
+
        /* Move to the next sbuf */
        ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
 
        return;
 }
 
+
 static int ov511_init_isoc(struct usb_ov511 *ov511)
 {
        urb_t *urb;
        int fx, err;
 
-       PDEBUG(4, "ov511_init_isoc");
+       PDEBUG(3, "*** Initializing capture ***");
 
        ov511->compress = 0;
        ov511->curframe = -1;
@@ -1235,11 +1612,11 @@
        urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
        urb->transfer_flags = USB_ISO_ASAP;
        urb->transfer_buffer = ov511->sbuf[0].data;
-       urb->complete = ov511_isoc_irq;
-       urb->number_of_packets = FRAMES_PER_DESC;
-       urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
-       for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-               urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
+       urb->complete = ov511_isoc_irq;
+       urb->number_of_packets = FRAMES_PER_DESC;
+       urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
+       for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+               urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
                urb->iso_frame_desc[fx].length = ov511->packet_size;
        }
 
@@ -1254,11 +1631,11 @@
        urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
        urb->transfer_flags = USB_ISO_ASAP;
        urb->transfer_buffer = ov511->sbuf[1].data;
-       urb->complete = ov511_isoc_irq;
-       urb->number_of_packets = FRAMES_PER_DESC;
-       urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
-       for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-               urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
+       urb->complete = ov511_isoc_irq;
+       urb->number_of_packets = FRAMES_PER_DESC;
+       urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
+       for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+               urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
                urb->iso_frame_desc[fx].length = ov511->packet_size;
        }
 
@@ -1280,10 +1657,11 @@
 
 static void ov511_stop_isoc(struct usb_ov511 *ov511)
 {
-       PDEBUG(4, "ov511_stop_isoc");
        if (!ov511->streaming || !ov511->dev)
                return;
 
+       PDEBUG (3, "*** Stopping capture ***");
+
        ov511_set_packet_size(ov511, 0);
 
        ov511->streaming = 0;
@@ -1303,18 +1681,19 @@
        }
 }
 
+
 static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
 {
        struct ov511_frame *frame;
        int width, height;
 
-       PDEBUG(4, "ov511_new_frame");
-
+       PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,
+               framenum);
        if (!ov511->dev)
                return -1;
 
        /* If we're not grabbing a frame right now and the other frame is */
-       /*  ready to be grabbed into, then use it instead */
+       /* ready to be grabbed into, then use it instead */
        if (ov511->curframe == -1) {
                if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % 
OV511_NUMFRAMES].grabstate == FRAME_READY)
                        framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
@@ -1325,6 +1704,9 @@
        width = frame->width;
        height = frame->height;
 
+       PDEBUG (4, "framenum = %d, width = %d, height = %d", framenum, width,
+               height);
+
        frame->grabstate = FRAME_GRABBING;
        frame->scanstate = STATE_SCANNING;
        frame->scanlength = 0;          /* accumulated in ov511_parse_data() */
@@ -1335,11 +1717,17 @@
        /* Make sure it's not too big */
        if (width > DEFAULT_WIDTH)
                width = DEFAULT_WIDTH;
+#if 0
        width = (width / 8) * 8;        /* Multiple of 8 */
+#endif
+       width &= ~7L;
 
        if (height > DEFAULT_HEIGHT)
                height = DEFAULT_HEIGHT;
+#if 0
        height = (height / 4) * 4;      /* Multiple of 4 */
+#endif
+       width &= ~3L;
 
 //     /* We want a fresh frame every 30 we get */
 //     ov511->compress = (ov511->compress + 1) % 30;
@@ -1348,7 +1736,12 @@
 }
 
 
-/* Video 4 Linux API */
+/****************************************************************************
+ *
+ * V4L API
+ *
+ ***************************************************************************/
+
 static int ov511_open(struct video_device *dev, int flags)
 {
        int err = -EBUSY;
@@ -1409,9 +1802,9 @@
 out_unlock:
        up(&ov511->lock);
        return err;
-
 }
 
+
 static void ov511_close(struct video_device *dev)
 {
        struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
@@ -1438,16 +1831,23 @@
        }
 }
 
+
 static int ov511_init_done(struct video_device *dev)
 {
+#ifdef CONFIG_PROC_FS
+       create_proc_ov511_cam((struct usb_ov511 *)dev);
+#endif
+
        return 0;
 }
 
+
 static long ov511_write(struct video_device *dev, const char *buf, unsigned long 
count, int noblock)
 {
        return -EINVAL;
 }
 
+
 static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 {
        struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
@@ -1756,13 +2156,15 @@
        return 0;
 }
 
+
 static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int 
noblock)
 {
        struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+       int i;
        int frmx = -1;
        volatile struct ov511_frame *frame;
 
-       PDEBUG(4, "ov511_read: %ld bytes, noblock=%d", count, noblock);
+       PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
 
        if (!dev || !buf)
                return -EFAULT;
@@ -1776,6 +2178,7 @@
        else if (ov511->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
                frmx = 1;
 
+       /* If nonblocking we return immediately */
        if (noblock && (frmx == -1))
                return -EAGAIN;
 
@@ -1794,19 +2197,26 @@
 
        frame = &ov511->frame[frmx];
 
+       /* FIXME */
+       frame->segsize = frame->format == VIDEO_PALETTE_RGB24 ? 384 : 256;
+       frame->depth = frame->format == VIDEO_PALETTE_RGB24 ? 24 : 8;
+
 restart:
        if (!ov511->dev)
                return -EIO;
 
+       /* Wait while we're grabbing the image */
+       PDEBUG(4, "Waiting image grabbing");
        while (frame->grabstate == FRAME_GRABBING) {
                interruptible_sleep_on(&ov511->frame[frmx].wq);
                if (signal_pending(current))
                        return -EINTR;
        }
+       PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
 
        if (frame->grabstate == FRAME_ERROR) {
                frame->bytes_read = 0;
-               err("ov511_read: errored frame %d", ov511->curframe);
+               err("** ick! ** Errored frame %d", ov511->curframe);
                if (ov511_new_frame(ov511, frmx))
                        err("ov511_read: ov511_new_frame error");
                goto restart;
@@ -1814,14 +2224,21 @@
 
 
        /* Repeat until we get a snapshot frame */
+       if (!ov511->snap_enabled) {
+               PDEBUG (4, "snap disabled");
+       } else {
+               PDEBUG (4, "Waiting snapshot frame");
+       }
        if (ov511->snap_enabled && !frame->snapshot) {
                frame->bytes_read = 0;
                if (ov511_new_frame(ov511, frmx))
-                       err("ov511_read: ov511_new_frame error");
+                       err("ov511_new_frame error");
                goto restart;
        }
 
        /* Clear the snapshot */
+       if (ov511->snap_enabled)
+               PDEBUG (4, "Clear snapshot");
        if (ov511->snap_enabled && frame->snapshot) {
                frame->snapshot = 0;
                ov511_reg_write(ov511->dev, 0x52, 0x01);
@@ -1829,20 +2246,24 @@
                ov511_reg_write(ov511->dev, 0x52, 0x01);
        }
 
-       PDEBUG(4, "ov511_read: frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
+       PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
                frame->bytes_read, frame->scanlength);
 
        /* copy bytes to user space; we allow for partials reads */
 //     if ((count + frame->bytes_read) > frame->scanlength)
 //             count = frame->scanlength - frame->bytes_read;
+
        /* FIXME - count hardwired to be one frame... */
-       count = frame->width * frame->height * frame->depth;
+       count = frame->width * frame->height * (frame->depth >> 3);
 
-       if (copy_to_user(buf, frame->data + frame->bytes_read, count))
+       PDEBUG(4, "Copy to user space: %ld bytes", count);
+       if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
+               PDEBUG(4, "Copy failed! %d bytes not copied", i);
                return -EFAULT;
+       }
 
        frame->bytes_read += count;
-       PDEBUG(4, "ov511_read: {copy} count used=%ld, new bytes_read=%ld",
+       PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
                count, frame->bytes_read);
 
        if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
@@ -1851,13 +2272,17 @@
                /* Mark it as available to be used again. */
                ov511->frame[frmx].grabstate = FRAME_UNUSED;
                if (ov511_new_frame(ov511, frmx ? 0 : 1))
-                       err("ov511_read: ov511_new_frame returned error");
+                       err("ov511_new_frame returned error");
        }
 
+       PDEBUG(4, "read finished, returning %ld (sweet)", count);
+
        return count;
 }
 
-static int ov511_mmap(struct video_device *dev, const char *adr, unsigned long size)
+
+static int ov511_mmap(struct video_device *dev, const char *adr,
+       unsigned long size)
 {
        struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
        unsigned long start = (unsigned long)adr;
@@ -1888,6 +2313,7 @@
        return 0;
 }
 
+
 static struct video_device ov511_template = {
        name:           "OV511 USB Camera",
        type:           VID_TYPE_CAPTURE,
@@ -1901,12 +2327,81 @@
        initialize:     ov511_init_done,
 };
 
-static int ov7610_configure(struct usb_ov511 *ov511)
+
+/****************************************************************************
+ *
+ * OV511/OV7610 configuration
+ *
+ ***************************************************************************/
+
+static int ov76xx_configure(struct usb_ov511 *ov511)
 {
        struct usb_device *dev = ov511->dev;
-       int tries;
+       int i, success;
        int rc;
 
+       static struct ov511_regvals aRegvalsNorm7610[] =
+       {{OV511_I2C_BUS, 0x10, 0xff},
+        {OV511_I2C_BUS, 0x16, 0x06},
+        {OV511_I2C_BUS, 0x28, 0x24},
+        {OV511_I2C_BUS, 0x2b, 0xac},
+        {OV511_I2C_BUS, 0x05, 0x00},
+        {OV511_I2C_BUS, 0x06, 0x00},
+        {OV511_I2C_BUS, 0x12, 0x00},
+        {OV511_I2C_BUS, 0x38, 0x81},
+        {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
+        {OV511_I2C_BUS, 0x05, 0x00},
+        {OV511_I2C_BUS, 0x0f, 0x05},
+        {OV511_I2C_BUS, 0x15, 0x01},
+        {OV511_I2C_BUS, 0x20, 0x1c},
+        {OV511_I2C_BUS, 0x23, 0x2a},
+        {OV511_I2C_BUS, 0x24, 0x10},
+        {OV511_I2C_BUS, 0x25, 0x8a},
+        {OV511_I2C_BUS, 0x27, 0xc2},
+        {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
+        {OV511_I2C_BUS, 0x2a, 0x04},
+        {OV511_I2C_BUS, 0x2c, 0xfe},
+        {OV511_I2C_BUS, 0x30, 0x71},
+        {OV511_I2C_BUS, 0x31, 0x60},
+        {OV511_I2C_BUS, 0x32, 0x26},
+        {OV511_I2C_BUS, 0x33, 0x20},
+        {OV511_I2C_BUS, 0x34, 0x48},
+        {OV511_I2C_BUS, 0x12, 0x24},
+        {OV511_I2C_BUS, 0x11, 0x01},
+        {OV511_I2C_BUS, 0x0c, 0x24},
+        {OV511_I2C_BUS, 0x0d, 0x24},
+        {OV511_DONE_BUS, 0x0, 0x00},
+       };
+
+       static struct ov511_regvals aRegvalsNorm7620[] =
+       {{OV511_I2C_BUS, 0x10, 0xff},
+        {OV511_I2C_BUS, 0x16, 0x06},
+        {OV511_I2C_BUS, 0x28, 0x24},
+        {OV511_I2C_BUS, 0x2b, 0xac},
+        {OV511_I2C_BUS, 0x12, 0x00},
+        {OV511_I2C_BUS, 0x28, 0x24},
+        {OV511_I2C_BUS, 0x05, 0x00},
+        {OV511_I2C_BUS, 0x0f, 0x05},
+        {OV511_I2C_BUS, 0x15, 0x01},
+        {OV511_I2C_BUS, 0x23, 0x00},
+        {OV511_I2C_BUS, 0x24, 0x10},
+        {OV511_I2C_BUS, 0x25, 0x8a},
+        {OV511_I2C_BUS, 0x27, 0xe2},
+        {OV511_I2C_BUS, 0x29, 0x03},
+        {OV511_I2C_BUS, 0x2a, 0x00},
+        {OV511_I2C_BUS, 0x2c, 0xfe},
+        {OV511_I2C_BUS, 0x30, 0x71},
+        {OV511_I2C_BUS, 0x31, 0x60},
+        {OV511_I2C_BUS, 0x32, 0x26},
+        {OV511_I2C_BUS, 0x33, 0x20},
+        {OV511_I2C_BUS, 0x34, 0x48},
+        {OV511_I2C_BUS, 0x12, 0x24},
+        {OV511_I2C_BUS, 0x11, 0x01},
+        {OV511_I2C_BUS, 0x0c, 0x24},
+        {OV511_I2C_BUS, 0x0d, 0x24},
+        {OV511_DONE_BUS, 0x0, 0x00},
+       };
+
        if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
                                OV7610_I2C_WRITE_ID) < 0)
                return -1;
@@ -1918,64 +2413,90 @@
        if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
                return -1;
        
-       /* Reset the 7610 and wait a bit for it to initialize */ 
+       /* Reset the 76xx */ 
        if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
-       schedule_timeout (1 + 150 * HZ / 1000);
 
-       /* Dummy read to sync I2C */
-       if(ov511_i2c_read(dev, 0x00) < 0)
-               return -1;
- 
-       tries = 5;
-       while((tries > 0) &&
-             ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) != 0x7F) ||
-              (ov511_i2c_read(dev, OV7610_REG_ID_LOW) != 0xA2))) {
-               --tries;
+       for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
+               if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
+                   (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2))
+                       success = 1;
+
+               /* Dummy read to sync I2C */
+               if (ov511_i2c_read(dev, 0x00) < 0) return -1;
+               /* Wait for it to initialize */ 
+               schedule_timeout (1 + 150 * HZ / 1000);
        }
-       
-       if (tries == 1) {
-               err("Failed to read sensor ID. You might not have an OV7610/20,");
+
+       if (success) {
+               PDEBUG(1, "I2C synced in %d attempt(s)", i);
+       } else {
+               err("Failed to read sensor ID. You might not have an OV76xx,");
                err("or it may be not responding. Report this to");
                err("[EMAIL PROTECTED]");
                return -1;
        }
 
+       /* Detect sensor if user didn't use override param */
        if (sensor == 0) {
                rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
 
                if (rc < 0) {
                        err("Error detecting sensor type");
                        return -1;
-               }
-               else if((rc & 3) == 3) {
+               } else if((rc & 3) == 3) {
                        printk("ov511: Sensor is an OV7610\n");
                        ov511->sensor = SEN_OV7610;
-               }
-               else if((rc & 3) == 1) {
+               } else if((rc & 3) == 1) {
                        printk("ov511: Sensor is an OV7620AE\n");
                        ov511->sensor = SEN_OV7620AE;
-               }
-               else if((rc & 3) == 0) {
+               } else if((rc & 3) == 0) {
                        printk("ov511: Sensor is an OV7620\n");
                        ov511->sensor = SEN_OV7620;
-               }
-               else {
+               } else {
                        err("Unknown image sensor version: %d", rc & 3);
                        return -1;
                }
-       }
-       else {  /* sensor != 0; user overrode detection */
+       } else {        /* sensor != 0; user overrode detection */
                ov511->sensor = sensor;
                printk("ov511: Sensor set to type %d\n", ov511->sensor);
        }
 
+       if (ov511->sensor == SEN_OV7620) {
+               if (ov511_write_regvals(dev, aRegvalsNorm7620))
+                       return -1;
+       } else {
+               if (ov511_write_regvals(dev, aRegvalsNorm7610))
+                       return -1;
+       }
+
+       if (aperture < 0) {          /* go with the default */
+               if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
+       } else if (aperture <= 0xf) {  /* user overrode default */
+               if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
+                       return -1;
+       } else {
+               err("Invalid setting for aperture; legal value: 0 - 15");
+               return -1;
+       }
+
+       if (autoadjust) {
+               if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
+               if (ov511_i2c_write(dev, 0x2d, 
+                    ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
+       } else {
+               if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
+               if (ov511_i2c_write(dev, 0x2d, 
+                    ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
+               ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
+       }
+
        return 0;
 }
 
+
 static int ov511_configure(struct usb_ov511 *ov511)
 {
        struct usb_device *dev = ov511->dev;
-       int rc;
 
        static struct ov511_regvals aRegvalsInit[] =
        {{OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x7f},
@@ -1988,7 +2509,7 @@
         {OV511_DONE_BUS, 0x0, 0x00},
        };
 
-       static struct ov511_regvals aRegvalsNorm7610[] =
+       static struct ov511_regvals aRegvalsNorm511[] =
        {{OV511_REG_BUS, 0x20, 0x01},
         {OV511_REG_BUS, 0x52, 0x02},
         {OV511_REG_BUS, 0x52, 0x00},
@@ -2003,85 +2524,6 @@
         {OV511_REG_BUS, 0x77, 0x01},
         {OV511_REG_BUS, 0x78, 0x06},
         {OV511_REG_BUS, 0x79, 0x03},
-
-        {OV511_I2C_BUS, 0x10, 0xff},
-        {OV511_I2C_BUS, 0x16, 0x06},
-        {OV511_I2C_BUS, 0x28, 0x24},
-        {OV511_I2C_BUS, 0x2b, 0xac},
-        {OV511_I2C_BUS, 0x05, 0x00},
-        {OV511_I2C_BUS, 0x06, 0x00},
-
-        {OV511_I2C_BUS, 0x12, 0x00},
-        {OV511_I2C_BUS, 0x38, 0x81},
-        {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
-        {OV511_I2C_BUS, 0x05, 0x00},
-        {OV511_I2C_BUS, 0x0f, 0x05},
-        {OV511_I2C_BUS, 0x15, 0x01},
-        {OV511_I2C_BUS, 0x20, 0x1c},
-        {OV511_I2C_BUS, 0x23, 0x2a},
-        {OV511_I2C_BUS, 0x24, 0x10},
-        {OV511_I2C_BUS, 0x25, 0x8a},
-        {OV511_I2C_BUS, 0x26, 0x90},
-        {OV511_I2C_BUS, 0x27, 0xc2},
-        {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
-        {OV511_I2C_BUS, 0x2a, 0x04},
-        {OV511_I2C_BUS, 0x2c, 0xfe},
-        {OV511_I2C_BUS, 0x30, 0x71},
-        {OV511_I2C_BUS, 0x31, 0x60},
-        {OV511_I2C_BUS, 0x32, 0x26},
-        {OV511_I2C_BUS, 0x33, 0x20},
-        {OV511_I2C_BUS, 0x34, 0x48},
-        {OV511_I2C_BUS, 0x12, 0x24},
-        {OV511_I2C_BUS, 0x11, 0x01},
-        {OV511_I2C_BUS, 0x0c, 0x24},
-        {OV511_I2C_BUS, 0x0d, 0x24},
-        {OV511_DONE_BUS, 0x0, 0x00},
-       };
-
-       static struct ov511_regvals aRegvalsNorm7620[] =
-       {{OV511_REG_BUS, 0x20, 0x01},
-        {OV511_REG_BUS, 0x52, 0x02},
-        {OV511_REG_BUS, 0x52, 0x00},
-        {OV511_REG_BUS, 0x31, 0x1f},
-        {OV511_REG_BUS, 0x70, 0x3f},
-        {OV511_REG_BUS, 0x71, 0x3f},
-        {OV511_REG_BUS, 0x72, 0x01},
-        {OV511_REG_BUS, 0x73, 0x01},
-        {OV511_REG_BUS, 0x74, 0x01},
-        {OV511_REG_BUS, 0x75, 0x01},
-        {OV511_REG_BUS, 0x76, 0x01},
-        {OV511_REG_BUS, 0x77, 0x01},
-        {OV511_REG_BUS, 0x78, 0x06},
-        {OV511_REG_BUS, 0x79, 0x03},
-
-        {OV511_I2C_BUS, 0x10, 0xff},
-        {OV511_I2C_BUS, 0x16, 0x06},
-        {OV511_I2C_BUS, 0x28, 0x24},
-        {OV511_I2C_BUS, 0x2b, 0xac},
-
-        {OV511_I2C_BUS, 0x12, 0x00},
-
-        {OV511_I2C_BUS, 0x28, 0x24},
-        {OV511_I2C_BUS, 0x05, 0x00},
-        {OV511_I2C_BUS, 0x0f, 0x05},
-        {OV511_I2C_BUS, 0x15, 0x01},
-        {OV511_I2C_BUS, 0x23, 0x00},
-        {OV511_I2C_BUS, 0x24, 0x10},
-        {OV511_I2C_BUS, 0x25, 0x8a},
-        {OV511_I2C_BUS, 0x26, 0xa2},
-        {OV511_I2C_BUS, 0x27, 0xe2},
-        {OV511_I2C_BUS, 0x29, 0x03},
-        {OV511_I2C_BUS, 0x2a, 0x00},
-        {OV511_I2C_BUS, 0x2c, 0xfe},
-        {OV511_I2C_BUS, 0x30, 0x71},
-        {OV511_I2C_BUS, 0x31, 0x60},
-        {OV511_I2C_BUS, 0x32, 0x26},
-        {OV511_I2C_BUS, 0x33, 0x20},
-        {OV511_I2C_BUS, 0x34, 0x48},
-        {OV511_I2C_BUS, 0x12, 0x24},
-        {OV511_I2C_BUS, 0x11, 0x01},
-        {OV511_I2C_BUS, 0x0c, 0x24},
-        {OV511_I2C_BUS, 0x0d, 0x24},
         {OV511_DONE_BUS, 0x0, 0x00},
        };
 
@@ -2096,54 +2538,36 @@
                return -EBUSY;
        }
 
-       if ((rc = ov511_write_regvals(dev, aRegvalsInit)))
-               return rc;
-
-       if(ov7610_configure(ov511) < 0) {
-               err("failed to configure OV7610");
-               goto error;     
-       }
+       if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
+       if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
 
        ov511_set_packet_size(ov511, 0);
 
-       /* Disable compression */
-       if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0)
-               goto error;
-
        ov511->snap_enabled = snapshot; 
 
        /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
         * (using read() instead). */
        ov511->frame[0].width = DEFAULT_WIDTH;
        ov511->frame[0].height = DEFAULT_HEIGHT;
+       ov511->frame[0].depth = 24;             /**************/
        ov511->frame[0].bytes_read = 0;
+       ov511->frame[0].segment = 0;
        ov511->frame[1].width = DEFAULT_WIDTH;
        ov511->frame[1].height = DEFAULT_HEIGHT;
+       ov511->frame[1].depth = 24;
        ov511->frame[1].bytes_read = 0;
+       ov511->frame[1].segment = 0;
 
        /* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
 
-       if (ov511->sensor == SEN_OV7620) {
-               if (ov511_write_regvals(dev, aRegvalsNorm7620)) goto error;
-       }
-       else {
-               if (ov511_write_regvals(dev, aRegvalsNorm7610)) goto error;
+       if(ov76xx_configure(ov511) < 0) {
+               err("failed to configure OV76xx");
+               goto error;     
        }
 
        if (ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                                      VIDEO_PALETTE_RGB24, 0) < 0) goto error;
-
-       if (autoadjust) {
-               if (ov511_i2c_write(dev, 0x13, 0x01) < 0) goto error;
-               if (ov511_i2c_write(dev, 0x2d, 
-                    ov511->sensor==SEN_OV7620?0x91:0x93) < 0) goto error;
-       }
-       else {
-               if (ov511_i2c_write(dev, 0x13, 0x00) < 0) goto error;
-               if (ov511_i2c_write(dev, 0x2d, 
-                    ov511->sensor==SEN_OV7620?0x81:0x83) < 0) goto error;
-               ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
-       }
+                                VIDEO_PALETTE_RGB24, 0) < 0)
+               goto error;
 
        return 0;
        
@@ -2158,11 +2582,18 @@
        return -EBUSY;  
 }
 
+
+/****************************************************************************
+ *
+ *  USB routines
+ *
+ ***************************************************************************/
+
 static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_interface_descriptor *interface;
        struct usb_ov511 *ov511;
-       int rc;
+       int i;
 
        PDEBUG(1, "probing for device...");
 
@@ -2191,79 +2622,58 @@
        }
 
        memset(ov511, 0, sizeof(*ov511));
-       
+
        ov511->dev = dev;
        ov511->iface = interface->bInterfaceNumber;
 
-       if (dev->descriptor.idProduct == 0x0511) {
+       switch (dev->descriptor.idProduct) {
+       case 0x0511:
                info("USB OV511 camera found");
                ov511->bridge = BRG_OV511;
-       }
-       else if (dev->descriptor.idProduct == 0xA511) {
+               break;
+       case 0xA511:
                info("USB OV511+ camera found");
                ov511->bridge = BRG_OV511PLUS;
+               break;
        }
 
-       rc = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
-       if (rc < 0) {
+       ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
+       if (ov511->customid < 0) {
                err("Unable to read camera bridge registers");
                goto error;
        }
-       
-       switch(ov511->customid = rc) {
-       case 0: /* This also means that no custom ID was set */
-               printk("ov511: Camera is a generic model (no ID)\n");
-               break;
-       case 3:
-               printk("ov511: Camera is a D-Link DSB-C300\n");
-               break;
-       case 4:
-               printk("ov511: Camera is a generic OV511/OV7610\n");
-               break;
-       case 5:
-               printk("ov511: Camera is a Puretek PT-6007\n");
-               break;
-       case 21:
-               printk("ov511: Camera is a Creative Labs WebCam 3\n");
-               break;
-       case 36:
-               printk("ov511: Camera is a Koala-Cam\n");
-               break;
-       case 38:
-               printk("ov511: Camera is a Lifeview USB Life TV\n");
-               printk("ov511: This device is not supported, exiting...\n");
-               goto error;
-               break;
-       case 100:
-               printk("ov511: Camera is a Lifeview RoboCam\n");
-               break;
-       case 102:
-               printk("ov511: Camera is a AverMedia InterCam Elite\n");
-               break;
-       case 112: /* The OmniVision OV7110 evaluation kit uses this too */
-               printk("ov511: Camera is a MediaForte MV300\n");
-               break;
-       default:
-               err("Specific camera type (%d) not recognized", rc);
+
+       ov511->desc = -1;
+       PDEBUG (4, "CustomID = %d", ov511->customid);
+       for (i = 0; clist[i].id >= 0; i++) {
+               if (ov511->customid == clist[i].id) {
+                       printk ("Camera: %s\n", clist[i].description);
+                       ov511->desc = i;
+                       break;
+               }
+       }
+
+       /* Lifeview USB Life TV not supported */
+       if (clist[i].id == 38) {
+               err("This device is not supported yet.");
+               return NULL;
+       }
+
+       if (clist[i].id == -1) {
+               err("Camera type (%d) not recognized", ov511->customid);
                err("Please contact [EMAIL PROTECTED] to request");
                err("support for your camera.");
        }
 
-//     if (ov511->bridge == BRG_OV511PLUS) {
-//             err("Sorry, the OV511+ chip is not supported yet");
-//             goto error;
-//     }
-
        if (!ov511_configure(ov511)) {
-               ov511->user=0;
+               ov511->user = 0;
                init_MUTEX(&ov511->lock);       /* to 1 == available */
                return ov511;
-       }
-       else {
+       } else {
                err("Failed to configure camera");
                goto error;
        }
-       
+
        return ov511;
 
 error:
@@ -2272,12 +2682,12 @@
                ov511 = NULL;
        }
 
-       return NULL;    
+       return NULL;
 }
 
+
 static void ov511_disconnect(struct usb_device *dev, void *ptr)
 {
-
        struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
 
 //     video_unregister_device(&ov511->vdev);
@@ -2318,6 +2728,11 @@
                ov511->sbuf[0].urb = NULL;
        }
 
+#ifdef CONFIG_PROC_FS
+        PDEBUG(3, "destroying /proc/ov511/video%d", ov511->vdev.minor);
+        destroy_proc_ov511_cam(ov511);
+#endif
+
        /* Free the memory */
        if (!ov511->user) {
                kfree(ov511);
@@ -2332,18 +2747,35 @@
        { NULL, NULL }
 };
 
+
+/****************************************************************************
+ *
+ *  Module routines
+ *
+ ***************************************************************************/
+
 static int __init usb_ov511_init(void)
 {
+#ifdef CONFIG_PROC_FS
+       PDEBUG(3, "creating /proc/ov511");
+        proc_ov511_create();
+#endif
+
        if (usb_register(&ov511_driver) < 0)
                return -1;
 
-       info("ov511 driver registered");
+       info("ov511 driver version %s registered", version);
 
        return 0;
 }
 
 static void __exit usb_ov511_exit(void)
 {
+#ifdef CONFIG_PROC_FS
+       PDEBUG(3, "destroying /proc/ov511");
+        proc_ov511_destroy();
+#endif 
+
        usb_deregister(&ov511_driver);
        info("ov511 driver deregistered");
 }
diff -Naur linux-2.3.99-pre6-orig/drivers/usb/ov511.h linux/drivers/usb/ov511.h
--- linux-2.3.99-pre6-orig/drivers/usb/ov511.h  Thu Apr 13 23:23:45 2000
+++ linux/drivers/usb/ov511.h   Fri May  5 14:34:29 2000
@@ -1,34 +1,38 @@
 #ifndef __LINUX_OV511_H
 #define __LINUX_OV511_H
 
+#include <asm/uaccess.h>
+#include <linux/videodev.h>
+#include <linux/smp_lock.h>
+
 #define OV511_DEBUG    /* Turn on debug messages */
 
 #ifdef OV511_DEBUG
 #  define PDEBUG(level, fmt, args...) \
-if (debug >= level) printk("ov511: " fmt "\n" , ## args)
+if (debug >= level) printk("ov511: [" __PRETTY_FUNCTION__ ":%d] " fmt "\n", __LINE__ 
+, ## args)
 #else
 #  define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
 
 /* Camera interface register numbers */
-#define OV511_REG_CAMERA_DELAY_MODE                    0x10
-#define OV511_REG_CAMERA_EDGE_MODE                     0x11
+#define OV511_REG_CAMERA_DELAY_MODE            0x10
+#define OV511_REG_CAMERA_EDGE_MODE             0x11
 #define OV511_REG_CAMERA_CLAMPED_PIXEL_NUM     0x12
 #define OV511_REG_CAMERA_CLAMPED_LINE_NUM      0x13
 #define OV511_REG_CAMERA_PIXEL_DIVISOR         0x14
 #define OV511_REG_CAMERA_LINE_DIVISOR          0x15
 #define OV511_REG_CAMERA_DATA_INPUT_SELECT     0x16
 #define OV511_REG_CAMERA_RESERVED_LINE_MODE    0x17
-#define OV511_REG_CAMERA_BITMASK                       0x18
+#define OV511_REG_CAMERA_BITMASK               0x18
 
 /* Snapshot mode camera interface register numbers */
 #define OV511_REG_SNAP_CAPTURED_FRAME          0x19
 #define OV511_REG_SNAP_CLAMPED_PIXEL_NUM       0x1A
 #define OV511_REG_SNAP_CLAMPED_LINE_NUM                0x1B
 #define OV511_REG_SNAP_PIXEL_DIVISOR           0x1C
-#define OV511_REG_SNAP_LINE_DIVISOR                    0x1D
+#define OV511_REG_SNAP_LINE_DIVISOR            0x1D
 #define OV511_REG_SNAP_DATA_INPUT_SELECT       0x1E
-#define OV511_REG_SNAP_BITMASK                         0x1F
+#define OV511_REG_SNAP_BITMASK                 0x1F
 
 /* DRAM register numbers */
 #define OV511_REG_DRAM_ENABLE_FLOW_CONTROL     0x20
@@ -37,21 +41,21 @@
 #define OV511_REG_DRAM_REFRESH_COUNTER         0x23
 
 /* ISO FIFO register numbers */
-#define OV511_REG_FIFO_PACKET_SIZE                     0x30
-#define OV511_REG_FIFO_BITMASK                         0x31
+#define OV511_REG_FIFO_PACKET_SIZE             0x30
+#define OV511_REG_FIFO_BITMASK                 0x31
 
 /* PIO register numbers */
-#define OV511_REG_PIO_BITMASK                          0x38
-#define OV511_REG_PIO_DATA_PORT                                0x39
-#define OV511_REG_PIO_BIST                                     0x3E
+#define OV511_REG_PIO_BITMASK                  0x38
+#define OV511_REG_PIO_DATA_PORT                        0x39
+#define OV511_REG_PIO_BIST                     0x3E
 
 /* I2C register numbers */
-#define OV511_REG_I2C_CONTROL                          0x40
+#define OV511_REG_I2C_CONTROL                  0x40
 #define OV511_REG_I2C_SLAVE_ID_WRITE           0x41
 #define OV511_REG_I2C_SUB_ADDRESS_3_BYTE       0x42
 #define OV511_REG_I2C_SUB_ADDRESS_2_BYTE       0x43
-#define OV511_REG_I2C_SLAVE_ID_READ                    0x44
-#define OV511_REG_I2C_DATA_PORT                                0x45
+#define OV511_REG_I2C_SLAVE_ID_READ            0x44
+#define OV511_REG_I2C_DATA_PORT                        0x45
 #define OV511_REG_I2C_CLOCK_PRESCALER          0x46
 #define OV511_REG_I2C_TIME_OUT_COUNTER         0x47
 
@@ -60,39 +64,39 @@
 #define OV511_REG_I2C_SNAP_DATA_PORT           0x49
 
 /* System control register numbers */
-#define OV511_REG_SYSTEM_RESET                         0x50
-#define        OV511_RESET_UDC                         0x01
-#define        OV511_RESET_I2C                         0x02
-#define        OV511_RESET_FIFO                        0x04
-#define        OV511_RESET_OMNICE                      0x08
+#define OV511_REG_SYSTEM_RESET                 0x50
+#define        OV511_RESET_UDC                 0x01
+#define        OV511_RESET_I2C                 0x02
+#define        OV511_RESET_FIFO                0x04
+#define        OV511_RESET_OMNICE              0x08
 #define        OV511_RESET_DRAM_INTF           0x10
 #define        OV511_RESET_CAMERA_INTF         0x20
-#define                OV511_RESET_OV511                       0x40
-#define                OV511_RESET_NOREGS                      0x3F    /* All but 
OV511 & regs */
-#define        OV511_RESET_ALL                         0x7F
+#define        OV511_RESET_OV511               0x40
+#define        OV511_RESET_NOREGS              0x3F /* All but OV511 & regs */
+#define        OV511_RESET_ALL                 0x7F
 #define OV511_REG_SYSTEM_CLOCK_DIVISOR         0x51
-#define OV511_REG_SYSTEM_SNAPSHOT                      0x52
+#define OV511_REG_SYSTEM_SNAPSHOT              0x52
 #define OV511_REG_SYSTEM_INIT                  0x53
-#define OV511_REG_SYSTEM_PWR_CLK               0x54    /* OV511+ only */
-#define OV511_REG_SYSTEM_LED_CTL               0x55    /* OV511+ only */
+#define OV511_REG_SYSTEM_PWR_CLK               0x54    /* OV511+ only */
+#define OV511_REG_SYSTEM_LED_CTL               0x55    /* OV511+ only */
 #define OV511_REG_SYSTEM_USER_DEFINED          0x5E
-#define OV511_REG_SYSTEM_CUSTOM_ID                     0x5F
+#define OV511_REG_SYSTEM_CUSTOM_ID             0x5F
 
 /* OmniCE register numbers */
-#define OV511_OMNICE_PREDICTION_HORIZ_Y        0x70
+#define OV511_OMNICE_PREDICTION_HORIZ_Y                0x70
 #define OV511_OMNICE_PREDICTION_HORIZ_UV       0x71
 #define OV511_OMNICE_PREDICTION_VERT_Y         0x72
-#define OV511_OMNICE_PREDICTION_VERT_UV        0x73
+#define OV511_OMNICE_PREDICTION_VERT_UV                0x73
 #define OV511_OMNICE_QUANTIZATION_HORIZ_Y      0x74
 #define OV511_OMNICE_QUANTIZATION_HORIZ_UV     0x75
 #define OV511_OMNICE_QUANTIZATION_VERT_Y       0x76
 #define OV511_OMNICE_QUANTIZATION_VERT_UV      0x77
-#define OV511_OMNICE_ENABLE                                    0x78
-#define OV511_OMNICE_LUT_ENABLE                                0x79            
-#define OV511_OMNICE_Y_LUT_BEGIN                       0x80
-#define OV511_OMNICE_Y_LUT_END                         0x9F
-#define OV511_OMNICE_UV_LUT_BEGIN                      0xA0
-#define OV511_OMNICE_UV_LUT_END                                0xBF
+#define OV511_OMNICE_ENABLE                    0x78
+#define OV511_OMNICE_LUT_ENABLE                        0x79            
+#define OV511_OMNICE_Y_LUT_BEGIN               0x80
+#define OV511_OMNICE_Y_LUT_END                 0x9F
+#define OV511_OMNICE_UV_LUT_BEGIN              0xA0
+#define OV511_OMNICE_UV_LUT_END                        0xBF
 
 /* Alternate numbers for various max packet sizes (OV511 only) */
 #define OV511_ALT_SIZE_992     0
@@ -114,7 +118,7 @@
 #define OV511PLUS_ALT_SIZE_769 6
 #define OV511PLUS_ALT_SIZE_961 7
 
-/* ov7610 registers */
+/* OV7610 registers */
 #define OV7610_REG_GAIN          0x00
 #define OV7610_REG_BLUE          0x01
 #define OV7610_REG_RED           0x02
@@ -163,12 +167,12 @@
 
 #define SCRATCH_BUF_SIZE 384
 
-#define FRAMES_PER_DESC                10  /* FIXME - What should this be? */
+#define FRAMES_PER_DESC                10      /* FIXME - What should this be? */
 #define FRAME_SIZE_PER_DESC    993     /* FIXME - Deprecated */
-#define MAX_FRAME_SIZE_PER_DESC        993  /* For statically allocated stuff */
+#define MAX_FRAME_SIZE_PER_DESC        993     /* For statically allocated stuff */
 
 // FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)?
-#define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */
+#define OV511_ENDPOINT_ADDRESS 0x81    /* Address of isoc endpoint */
 
 // CAMERA SPECIFIC
 // FIXME - these can vary between specific models
@@ -213,7 +217,7 @@
        FRAME_UNUSED,           /* Unused (no MCAPTURE) */
        FRAME_READY,            /* Ready to start grabbing */
        FRAME_GRABBING,         /* In the process of being grabbed into */
-       FRAME_DONE,                     /* Finished grabbing, but not been synced yet 
*/
+       FRAME_DONE,             /* Finished grabbing, but not been synced yet */
        FRAME_ERROR,            /* Something bad happened while processing */
 };
 
@@ -238,7 +242,7 @@
        int hdrheight;          /* Height */
 
        int sub_flag;           /* Sub-capture mode for this frame? */
-       int format;                     /* Format for this frame */
+       int format;             /* Format for this frame */
        int segsize;            /* How big is each segment from the camera? */
 
        volatile int grabstate; /* State of grabbing */
@@ -253,7 +257,7 @@
 
        wait_queue_head_t wq;   /* Processes waiting */
 
-       int snapshot;                   /* True if frame was a snapshot */
+       int snapshot;           /* True if frame was a snapshot */
 };
 
 #define OV511_NUMFRAMES        2
@@ -261,23 +265,28 @@
 
 struct usb_ov511 {
        struct video_device vdev;
-       
+
        /* Device structure */
        struct usb_device *dev;
 
+#if 0
        unsigned char customid; /* Type of camera */
+#else
+       int customid;
+       int desc;
+#endif
 
        unsigned char iface;
-       
+
        struct semaphore lock;
-       int user;                       /* user count for exclusive use */
+       int user;               /* user count for exclusive use */
 
        int streaming;          /* Are we streaming Isochronous? */
        int grabbing;           /* Are we grabbing? */
 
        int compress;           /* Should the next frame be compressed? */
 
-       char *fbuf;                     /* Videodev buffer area */
+       char *fbuf;             /* Videodev buffer area */
 
        int sub_flag;           /* Pix Array subcapture on flag */
        int subx;               /* Pix Array subcapture x offset */
@@ -297,12 +306,22 @@
 
        wait_queue_head_t wq;   /* Processes waiting */
 
-       int snap_enabled;   /* Snapshot mode enabled */
+       int snap_enabled;       /* Snapshot mode enabled */
        
-       int bridge;         /* Type of bridge (OV511 or OV511+) */
-       int sensor;         /* Type of image sensor chip */
+       int bridge;             /* Type of bridge (OV511 or OV511+) */
+       int sensor;             /* Type of image sensor chip */
+
+       int packet_size;        /* Frame size per isoc desc */
+
+                               /* proc interface */
+       struct semaphore param_lock;    /* params lock for this camera */
+       struct proc_dir_entry *proc_entry;      /* /proc/ov511/videoX */
+};
+
 
-       int packet_size;    /* Frame size per isoc desc */
+struct cam_list {
+       int id;
+       char *description;
 };
 
 #endif

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to