diff -Naur linux-2.4.0-test9-pre6-orig/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- linux-2.4.0-test9-pre6-orig/Documentation/usb/ov511.txt	Sun Sep 24 01:19:27 2000
+++ linux/Documentation/usb/ov511.txt	Sun Sep 24 01:20:34 2000
@@ -6,11 +6,10 @@
 Homepage: http://alpha.dyndns.org/ov511
 
 NEW IN THIS VERSION:
- o Stability improvements
- o Support for hue control
- o 160x120 mostly working
- o OV6620 color problems fixed
- o More WebCam 3 detection improvements
+ o Experimental control file interface (disabled by default)
+ o Debug messages now are off by default
+ o Snapshot mode now works with mmap()
+ o Other trivial fixes
 
 INTRODUCTION:
 
@@ -205,13 +204,12 @@
         when your system is under heavy load.
  
 WORKING FEATURES:
- o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, 320x240, and
-   160x120
+ o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240
  o RGB24, YUV420, YUV422, YUYV, and YUV422P color
  o Monochrome
  o Setting/getting of saturation, contrast, brightness, and hue (only some of
    them work the OV7620 and OV7620AE)
- o proc status reporting
+ o /proc status reporting
 
 EXPERIMENTAL FEATURES:
  o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
@@ -219,6 +217,7 @@
  o Snapshot mode (only works with some read() based apps; see below for more)
  o OV6620 sensor support
  o GBR422 parsing
+ o 160x120
 
 TODO:
  o Fix the noise / grainy image problem.
@@ -227,18 +226,16 @@
    so we can't really work on that yet. Please kindly inform OmniVision that you
    would like them to release their specifications to the Linux community.
  o YUV422
- o Get snapshot mode working with mmap().
  o Fix fixFrameRGBoffset(). It is not stable yet with streaming video.
- o Get autoadjust disable working
  o V4L2 support (Probably not until it goes into the kernel)
- o Creative WebCam III has problems initializing its sensor. This should be
-   fixed now, but if you still have problems let me know.
  o Get rid of the memory management functions (put them in videodev.c??)
  o Setting of contrast and brightness not working with 7620/7620AE
  o Driver/camera state save/restore for when USB supports suspend/resume
  o Unstable on SMP systems
  o OV7620/OV6620 experience frame corruption with moving objects
  o OV6620 is too dark
+ o 176x144 support
+ o Driver sometimes hangs upon close() with OHCI
 
 HOW TO CONTACT ME:
 
diff -Naur linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.c	Sun Sep 24 01:19:51 2000
+++ linux/drivers/usb/ov511.c	Sun Sep 24 01:20:23 2000
@@ -30,7 +30,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.25";
+static const char version[] = "1.26";
 
 #define __NO_VERSION__
 
@@ -52,6 +52,7 @@
 #include "ov511.h"
 
 #undef OV511_GBR422		/* Experimental -- sets the 7610 to GBR422 */
+#undef OV511_CONTROL_API	/* Experimental -- IOCTL control API hack */
 
 #define OV511_I2C_RETRIES 3
 
@@ -74,7 +75,7 @@
  * 5=highly repetitive mesgs
  * NOTE: This should be changed to 0, 1, or 2 for production kernels
  */
-static int debug = 3;
+static int debug = 0;
 
 /* Fix vertical misalignment of red and blue at 640x480 */
 static int fix_rgb_offset = 0;
@@ -357,6 +358,7 @@
 		ov511->bridge == BRG_OV511PLUS ? "OV511+" :
 		"unknown");
 	out += sprintf (out, "sensor          : %s\n",
+		ov511->sensor == SEN_OV6620 ? "OV6620" :
 		ov511->sensor == SEN_OV7610 ? "OV7610" :
 		ov511->sensor == SEN_OV7620 ? "OV7620" :
 		ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
@@ -448,7 +450,6 @@
 }
 #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
 
-
 /**********************************************************************
  *
  * Camera interface
@@ -700,7 +701,7 @@
 {
 	int rc;
 	
-	PDEBUG(3, "Reset: type=0x%X", reset_type);
+	PDEBUG(4, "Reset: type=0x%X", reset_type);
 	rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
 	rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
 
@@ -829,14 +830,21 @@
 	} else if ((ov511->sensor == SEN_OV7620) 
 	         || (ov511->sensor == SEN_OV7620AE)) {
 #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)); 
+		int cur_sat, new_sat, tmp;
 
-		if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+		cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE);
+
+		tmp = (p->hue >> 8) - cur_sat;
+		new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp;
+
+	        PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp); 
+
+		if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0)
 			return -EIO;
+
+	        // DEBUG_CODE
+	        PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE)); 
+
 #endif
 	}
 
@@ -1662,6 +1670,11 @@
 			/* Frame start */
 			PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
 
+#if 0
+			/* Make sure no previous data carries over; necessary
+			 * for compression experimentation */
+			memset(frame->data, 0, MAX_DATA_SIZE);
+#endif
 			output_offset = 0;
 
 			/* Check to see if it's a snapshot frame */
@@ -2481,6 +2494,13 @@
 				goto redo;
 			}			
 		case FRAME_DONE:
+			if (ov511->snap_enabled && !ov511->frame[frame].snapshot) {
+				int ret;
+				if ((ret = ov511_new_frame(ov511, frame)) < 0)
+					return ret;
+				goto redo;
+			}
+
 			ov511->frame[frame].grabstate = FRAME_UNUSED;
 
 			/* Reset the hardware snapshot button */
@@ -2689,6 +2709,110 @@
 	initialize:	ov511_init_done,
 };
 
+#ifdef OV511_CONTROL_API
+/**********************************************************************
+ *
+ * Control File Interface
+ *
+ * NOTE: This API is definitely subject to change at this time. 
+ *
+ *  Q: Why are you using a device file instead of a proc file?
+ *  A: 1. /proc is for status reporting and not general I/O. 
+ *     2. The proc interface used here won't allow IOCTL.
+ *
+ *  Q: Why are you using IOCTL instead of read/write?
+ *  A: Passing data in ASCII is a pain (look at cpia's proc support)
+ *
+ *  Q: Why don't you use the normal video device's IOCTL function?
+ *  A: This would either require that the device be opened multiple
+ *     times, or that every video app implement ov511-control.
+ * 
+ * I admit this is a shitty hack. I should at elast add a new device
+ * type to V4L. Hopefully 2.5/V4L2 will obviate the need for this. - MM
+ *
+ **********************************************************************/
+
+static int ov511_control_open(struct video_device *dev, int flags)
+{
+	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+	int err = 0;
+
+	MOD_INC_USE_COUNT;
+	PDEBUG(4, "");
+	down(&ov511->lock);
+
+	err = -EBUSY;
+	if (ov511->user) 
+		goto out;
+
+	ov511->control_user++;
+
+out:
+	up(&ov511->lock);
+
+	if (err)
+		MOD_DEC_USE_COUNT;
+
+	return err;
+}
+
+static void ov511_control_close(struct video_device *dev)
+{
+	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+
+	PDEBUG(4, "");
+	
+	down(&ov511->lock);
+
+	ov511->control_user--;
+
+	up(&ov511->lock);
+
+	/* This is definitely broken (as well as the other close()) */
+	if (!ov511->dev) {
+		video_unregister_device(&ov511->vdev);
+		kfree(ov511);
+		ov511 = NULL;
+	}
+
+	MOD_DEC_USE_COUNT;
+}
+
+static int ov511_control_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+	struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
+
+	PDEBUG(4, "IOCtl: 0x%X", cmd);
+
+	if (!ov511->dev)
+		return -EIO;	
+
+	switch (cmd) {
+	/* The purpose of this is to let the control app make sure that it is
+	 * talking to an ov511 (using the name string). All V4L apps that use
+	 * extended IOCTLs should do that! */
+	case VIDIOCGCAP:
+	{
+		int err;
+		err = ov511_ioctl(vdev, cmd, arg);
+	}
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static struct video_device ov511_control_template = {
+	name:		"OV511 USB Camera (control)",
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_OV511,
+	open:		ov511_control_open,
+	close:		ov511_control_close,
+	ioctl:		ov511_control_ioctl,
+};
+#endif
+
 /****************************************************************************
  *
  * OV511/OV7610 configuration
@@ -3057,11 +3181,22 @@
 
 	init_waitqueue_head(&ov511->wq);
 
-	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) {
+	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) < 0) {
 		err("video_register_device failed");
 		return -EBUSY;
 	}
 
+#ifdef OV511_CONTROL_API
+	/* Create control device. Not a VTX; this is just an awful hack */
+	memcpy(&ov511->cdev, &ov511_control_template, 
+	 sizeof(ov511_control_template));
+	if (video_register_device(&ov511->cdev, VFL_TYPE_VTX) < 0) {
+		err("video_register_device failed for control device");
+		video_unregister_device(&ov511->vdev);
+		return -EBUSY;
+	}
+#endif
+
 	if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
 	if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
 
@@ -3131,6 +3266,9 @@
 	
 error:
 	video_unregister_device(&ov511->vdev);
+#ifdef OV511_CONTROL_API
+	video_unregister_device(&ov511->cdev);
+#endif
 	usb_driver_release_interface(&ov511_driver,
 		&dev->actconfig->interface[ov511->iface]);
 
@@ -3277,6 +3415,13 @@
 		video_unregister_device(&ov511->vdev);
 	else
 		PDEBUG(3, "Device open...deferring video_unregister_device");
+
+#ifdef OV511_CONTROL_API
+	if (!ov511->control_user)
+		video_unregister_device(&ov511->cdev);
+	else
+		PDEBUG(3, "Control device open...deferring video_unregister_device");
+#endif
 
 	for (n = 0; n < OV511_NUMFRAMES; n++)
 		ov511->frame[n].grabstate = FRAME_ERROR;
diff -Naur linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.h linux/drivers/usb/ov511.h
--- linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.h	Sun Sep 24 01:19:51 2000
+++ linux/drivers/usb/ov511.h	Sun Sep 24 01:20:27 2000
@@ -281,6 +281,7 @@
 
 struct usb_ov511 {
 	struct video_device vdev;
+	struct video_device cdev; 	/* Control device */
 
 	/* Device structure */
 	struct usb_device *dev;
@@ -301,6 +302,7 @@
 
 	struct semaphore lock;
 	int user;		/* user count for exclusive use */
+	int control_user;	/* user count for control device */
 
 	int streaming;		/* Are we streaming Isochronous? */
 	int grabbing;		/* Are we grabbing? */
@@ -339,7 +341,7 @@
 	struct proc_dir_entry *proc_entry;	/* /proc/ov511/videoX */
 	
 	/* Framebuffer/sbuf management */
-	int buf_state;
+	int buf_state;		/* Already 'atomic' by use of buf_lock */
 	struct semaphore buf_lock;
 	struct timer_list buf_timer;
 };
