diff -Naur linux-2.4.0-test4-orig/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- linux-2.4.0-test4-orig/Documentation/usb/ov511.txt	Fri Jul 14 03:54:08 2000
+++ linux/Documentation/usb/ov511.txt	Fri Jul 14 04:06:46 2000
@@ -176,6 +176,26 @@
         programs that expect RGB data (e.g. gqcam) to work with this driver. If
         your colors look VERY wrong, you may want to change this.
 
+  NAME: buf_timeout
+  TYPE: integer
+  DEFAULT: 5 (seconds)
+  DESC: Number of seconds before unused frame buffers are deallocated.
+        Previously, memory was allocated upon open() and deallocated upon
+        close(). Deallocation now occurs only if the driver is closed and this
+        timeout is reached. If you are capturing frames less frequently than
+        the default timeout, increase this. This will not make any difference
+        with programs that capture multiple frames during an open/close cycle.
+
+  NAME: cams
+  TYPE: integer (1-4 for OV511, 1-31 for OV511+)
+  DEFAULT: 1
+  DESC: Number of cameras allowed to stream simultaneously on a single bus.
+        Values higher than 1 reduce the data rate of each camera, allowing two
+        or more to be used at once. If you have a complicated setup involving
+        both OV511 and OV511+ cameras, trial-and-error may be necessary for
+        finding the opt
+
+  
 WORKING FEATURES:
  o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240
  o YUV420 and YUV422P color
@@ -210,7 +230,6 @@
  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 Unstable on SMP systems
 
 HOW TO CONTACT ME:
diff -Naur linux-2.4.0-test4-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.4.0-test4-orig/drivers/usb/ov511.c	Fri Jul 14 03:54:14 2000
+++ linux/drivers/usb/ov511.c	Fri Jul 14 04:06:31 2000
@@ -30,7 +30,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.19";
+static const char version[] = "1.20";
 
 #define __NO_VERSION__
 
@@ -101,6 +101,12 @@
 /* Number of seconds before inactive buffers are deallocated */
 static int buf_timeout = 5;
 
+/* Number of cameras to stream from simultaneously */
+static int cams = 1;
+
+/* Prevent apps from timing out if frame is not done in time */
+static int retry_sync = 0;
+
 MODULE_PARM(autoadjust, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(fix_rgb_offset, "i");
@@ -110,6 +116,8 @@
 MODULE_PARM(aperture, "i");
 MODULE_PARM(force_rgb, "i");
 MODULE_PARM(buf_timeout, "i");
+MODULE_PARM(cams, "i");
+MODULE_PARM(retry_sync, "i");
 
 MODULE_AUTHOR("Mark McClelland <mmcclelland@delphi.com> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
 MODULE_DESCRIPTION("OV511 USB Camera Driver");
@@ -1676,7 +1684,7 @@
 static int ov511_init_isoc(struct usb_ov511 *ov511)
 {
 	urb_t *urb;
-	int fx, err, n;
+	int fx, err, n, size;
 
 	PDEBUG(3, "*** Initializing capture ***");
 
@@ -1686,11 +1694,29 @@
 	ov511->scratchlen = 0;
 
 	if (ov511->bridge == BRG_OV511)
-		ov511_set_packet_size(ov511, 993);
+		if (cams == 1)			 size = 993;
+		else if (cams == 2)		 size = 513;
+		else if (cams == 3 || cams == 4) size = 257;
+		else {
+			err("\"cams\" parameter too high!");
+			return -1;
+		}
 	else if (ov511->bridge == BRG_OV511PLUS)
-		ov511_set_packet_size(ov511, 961);
-	else
+		if (cams == 1)                      size = 961;
+		else if (cams == 2)                 size = 513;
+		else if (cams == 3 || cams == 4) size = 257;
+		else if (cams >= 5 && cams <= 8)    size = 129;
+		else if (cams >= 9 && cams <= 31)   size = 33;
+		else {
+			err("\"cams\" parameter too high!");
+			return -1;
+		}
+	else {
 		err("invalid bridge type");
+		return -1;
+	}
+
+	ov511_set_packet_size(ov511, size);
 
 	for (n = 0; n < OV511_NUMSBUF; n++) {
 		urb = usb_alloc_urb(FRAMES_PER_DESC);
@@ -2085,11 +2111,15 @@
 		if (copy_from_user(&p, arg, sizeof(p)))
 			return -EFAULT;
 
+		if (p.palette != VIDEO_PALETTE_GREY &&
+		    p.palette != VIDEO_PALETTE_RGB24 &&
+		    p.palette != VIDEO_PALETTE_YUV422 &&
+		    p.palette != VIDEO_PALETTE_YUV422P)
+			return -EINVAL;
+			
 		if (ov7610_set_picture(ov511, &p))
 			return -EIO;
 
-		/* FIXME: check validity */
-
 		PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
 		for (i = 0; i < OV511_NUMFRAMES; i++) {
 			ov511->frame[i].depth = p.depth;
@@ -2294,8 +2324,23 @@
 				init_waitqueue_head(&ov511->frame[frame].wq);
 #endif
 				interruptible_sleep_on(&ov511->frame[frame].wq);
-				if (signal_pending(current))
-					return -EINTR;
+				if (signal_pending(current)) {
+					if (retry_sync) {
+						PDEBUG(3, "***retry sync***");
+
+						/* Polling apps will destroy frames with that! */
+						ov511_new_frame(ov511, frame);
+						ov511->curframe = -1;
+
+						/* This will request another frame. */
+						if (waitqueue_active(&ov511->frame[frame].wq))
+							wake_up_interruptible(&ov511->frame[frame].wq);
+
+						return 0;
+ 					} else {
+						return -EINTR;
+					}
+				}
 			} while (ov511->frame[frame].grabstate == FRAME_GRABBING);
 
 			if (ov511->frame[frame].grabstate == FRAME_ERROR) {
