diff -urN -X /home/spse/dontdiff linux-2.5.12-clean/drivers/usb/media/ibmcam.c linux-2.5.12/drivers/usb/media/ibmcam.c
--- linux-2.5.12-clean/drivers/usb/media/ibmcam.c	Wed May  1 01:08:50 2002
+++ linux-2.5.12/drivers/usb/media/ibmcam.c	Wed May  1 02:49:32 2002
@@ -3899,6 +3899,17 @@
 	return uvd;
 }
 
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
+	{ }  /* Terminating entry */
+};
+
 /*
  * ibmcam_init()
  *
@@ -3926,7 +3937,8 @@
 		sizeof(ibmcam_t),
 		"ibmcam",
 		&cbTbl,
-		THIS_MODULE);
+		THIS_MODULE,
+		id_table);
 }
 
 static void __exit ibmcam_cleanup(void)
@@ -3934,15 +3946,6 @@
 	usbvideo_Deregister(&cams);
 }
 
-static __devinitdata struct usb_device_id id_table[] = {
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
-	{ }  /* Terminating entry */
-};
 MODULE_DEVICE_TABLE(usb, id_table);
 
 module_init(ibmcam_init);
diff -urN -X /home/spse/dontdiff linux-2.5.12-clean/drivers/usb/media/konicawc.c linux-2.5.12/drivers/usb/media/konicawc.c
--- linux-2.5.12-clean/drivers/usb/media/konicawc.c	Wed May  1 01:08:44 2002
+++ linux-2.5.12/drivers/usb/media/konicawc.c	Wed May  1 02:49:44 2002
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * konicawc.c - konica webcam driver
  *
  * Author: Simon Evans <spse@secret.org.uk>
@@ -26,9 +24,11 @@
 #define MAX_SHARPNESS	108
 #define MAX_WHITEBAL	372
 #define MAX_SPEED	6
+#define MAX_FRAME_SIZE	2
+
 #define MAX_CAMERAS	1
 
-#define DRIVER_VERSION	"v1.1"
+#define DRIVER_VERSION	"v1.2"
 #define DRIVER_DESC	"Konica Webcam driver"
 
 enum ctrl_req {
@@ -61,16 +61,16 @@
 static int sharpness =	MAX_SHARPNESS/2;
 static int whitebal =	3*(MAX_WHITEBAL/4);
 
-static int speed_to_interface[] = { 1, 0, 3, 2, 4, 5, 6 };
+static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
 
 /* These FPS speeds are from the windows config box. They are
  * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
  * real fps.
  */
 
-static int speed_to_fps[3][7] = { { 24, 40, 48, 60, 72, 80, 100 },
-				  { 18, 30, 36, 45, 54, 60, 75  },
-				  { 6,  10, 12, 15, 18, 20, 25  } };
+static int spd_to_fps[3][7] = { { 24, 40, 48, 60, 72, 80, 100 },
+				{ 18, 30, 36, 45, 54, 60, 75  },
+				{ 6,  10, 12, 15, 18, 21, 25  } };
 
 
 static int camera_sizes[][2] = { { 160, 136 },
@@ -85,7 +85,7 @@
 	u8 saturation;		/* as above */
 	u8 sharpness;		/* as above */
 	u8 white_bal;		/* 0 - 33, x11 for real value */
-	u8 speed;		/* Stored as 0 - 6, used as index in speed_to_* (above) */
+	u8 speed;		/* Stored as 0 - 6, used as index in spd_to_* (above) */
 	u8 size;		/* Frame Size */
 	int height;
 	int width;
@@ -93,6 +93,11 @@
 	u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];
 	struct urb *last_data_urb;
 	int lastframe;
+	int cur_frame_size;	/* number of bytes in current frame size */
+	int maxline;		/* number of lines per frame */
+	int yplanesz;		/* Number of bytes in the Y plane */
+	unsigned int skip_frame:1;
+	unsigned int buttonsts:1;
 };
 
 
@@ -132,20 +137,25 @@
 	konicawc_set_value(uvd, cam->sharpness, SetSharpness);
 	dbg("setting size %d", cam->size);
 	switch(cam->size) {
-	case 0:
+	case SIZE_160X136:
 		konicawc_set_misc(uvd, 0x2, 0xa, 0x08);
 		break;
 
-	case 1:
+	case SIZE_176X144:
 		konicawc_set_misc(uvd, 0x2, 4, 0x08);
 		break;
 
-	case 2:
+	case SIZE_320X240:
 		konicawc_set_misc(uvd, 0x2, 5, 0x08);
 		break;
 	}
 	konicawc_set_misc(uvd, 0x2, 1, 0x0b);
 	cam->lastframe = -1;
+	cam->skip_frame = 0;
+	cam->buttonsts = 0;
+	cam->cur_frame_size = (cam->height * cam->width * 3) / 2;
+	cam->maxline = cam->cur_frame_size / 384;
+	cam->yplanesz = cam->height * cam->width;
 	return 0;
 }
 
@@ -154,6 +164,7 @@
 {
 	struct konicawc *cam = (struct konicawc *)uvd->user_data;
 
+	konicawc_set_misc(uvd, 0x2, 0, 0x0b);
 	dbg("new brightness: %d", uvd->vpic.brightness);
 	uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness;
 	if(cam->brightness != uvd->vpic.brightness / 11) {
@@ -171,6 +182,7 @@
 		    cam->contrast * 11);
 		konicawc_set_value(uvd, cam->contrast, SetContrast);
 	}
+	konicawc_set_misc(uvd, 0x2, 1, 0x0b);
 }
 
 
@@ -180,10 +192,10 @@
 	int i, totlen = 0;
 	unsigned char *status = stsurb->transfer_buffer;
 	int keep = 0, discard = 0, bad = 0;
-	static int buttonsts = 0;
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
 
 	for (i = 0; i < dataurb->number_of_packets; i++) {
-		int button = buttonsts;
+		int button = cam->buttonsts;
 		unsigned char sts;
 		int n = dataurb->iso_frame_desc[i].actual_length;
 		int st = dataurb->iso_frame_desc[i].status;
@@ -210,8 +222,8 @@
 
 		/* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
 		 * otherwise:
-		 * bit 0 0:drop packet (padding data)
-		 *	 1 keep packet
+		 * bit 0 0: keep packet
+		 *	 1: drop packet (padding data)
 		 *
 		 * bit 4 0 button not clicked
 		 *       1 button clicked
@@ -226,9 +238,9 @@
 		/* work out the button status, but dont do
 		   anything with it for now */
 		   
-		if(button != buttonsts) {
+		if(button != cam->buttonsts) {
 			dbg("button: %sclicked", button ? "" : "un");
-			buttonsts = button;
+			cam->buttonsts = button;
 		}
 
 		if(sts == 0x01) { /* drop frame */
@@ -243,15 +255,28 @@
 		}
 
 		keep++;
-		if(*(status+i) & 0x80) { /* frame start */
+		if(sts & 0x80) { /* frame start */
 			unsigned char marker[] = { 0, 0xff, 0, 0x00 };
+
+			/* Do we have enough space for this frame? */
+			if((uvd->dp.length - RingQueue_GetLength(&uvd->dp)) < cam->cur_frame_size + 4) {
+				dbg("Dropping frame");
+				cam->skip_frame = 1;
+				continue;
+			} else {
+				cam->skip_frame = 0;
+			}
+			   
 			if(debug > 1)
 				dbg("Adding Marker packet = %d, frame = %2.2x",
 				    i, *(status+i));
-			marker[3] = *(status+i) - 0x80;
+			marker[3] = sts - 0x80;
 			RingQueue_Enqueue(&uvd->dp, marker, 4);			
 			totlen += 4;
 		}
+		if(cam->skip_frame)
+			continue;
+
 		totlen += n;	/* Little local accounting */
 		if(debug > 5)
 			dbg("Adding packet %d, bytes = %d", i, n);
@@ -276,6 +301,17 @@
 	if (!CAMERA_IS_OPERATIONAL(uvd))
 		return;
 
+	if(urb->status) {
+		if(urb->status == -EOVERFLOW) {
+			dbg("isoc_irq: got babble");
+		} else if(urb->status == -ENOENT || urb->status == -EINPROGRESS) {
+			dbg("isoc_irq: URB unlinked");
+		} else {
+			dbg("isoc_irq: status %d", urb->status);
+		}
+		return;
+	}
+
 	if (urb->actual_length > 32) {
 		cam->last_data_urb = urb;
 		return;
@@ -324,7 +360,12 @@
 	struct usb_device *dev = uvd->dev;
 	int i, errFlag;
 	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+	int pktsz;
+	struct usb_interface_descriptor *interface;
 
+	interface = &dev->actconfig->interface[uvd->iface].altsetting[spd_to_iface[cam->speed]];
+	pktsz = interface->endpoint[1].wMaxPacketSize;
+	dbg("pktsz = %d", pktsz);
 	if (!CAMERA_IS_OPERATIONAL(uvd)) {
 		err("Camera is not operational");
 		return -EFAULT;
@@ -350,10 +391,10 @@
 		urb->transfer_buffer = uvd->sbuf[i].data;
 		urb->complete = konicawc_isoc_irq;
 		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
-		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
+		urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
+		for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
 			urb->iso_frame_desc[j].offset = k;
-			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
+			urb->iso_frame_desc[j].length = pktsz;
 		}
 
 		urb = cam->sts_urb[i];
@@ -439,14 +480,12 @@
 
 static void konicawc_process_isoc(uvd_t *uvd, usbvideo_frame_t *frame)
 {	
-	int n;
-	int maxline, yplanesz;
 	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	assert(uvd != NULL);
+	int maxline = cam->maxline;
+	int yplanesz = cam->yplanesz;
+
 	assert(frame != NULL);
 
-	maxline = (cam->height * cam->width * 3) / (2 * 384);
-	yplanesz = cam->height * cam->width;
 	if(debug > 5)
 		dbg("maxline = %d yplanesz = %d", maxline, yplanesz);
 	
@@ -472,9 +511,10 @@
 						fdrops = curframe - cam->lastframe;
 					}
 					fdrops--;
-					if(fdrops)
-						info("Dropped %d frames (%d -> %d)", fdrops,
+					if(fdrops) {
+						dbg("Dropped %d frames (%d -> %d)", fdrops,
 						     cam->lastframe, curframe);
+					}
 				}
 				cam->lastframe = curframe;
 				frame->curline = 0;
@@ -496,7 +536,7 @@
 	 * This needs to be written out as a Y plane, a U plane and a V plane.
 	 */
 		
-	while ( frame->curline < maxline && (n = RingQueue_GetLength(&uvd->dp)) >= 384) {
+	while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) {
 		/* Y */
 		RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
 		/* U */
@@ -519,12 +559,61 @@
 }
 
 
-static int konicawc_calculate_fps(uvd_t *uvd)
+static int konicawc_set_video_mode(uvd_t *uvd, int x, int y, int fps)
 {
-	struct konicawc *t = uvd->user_data;
-	dbg("fps = %d", speed_to_fps[t->size][t->speed]/3);
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+	int newsize, newspeed;
+
+	if(x > 0 && y > 0) {
+		dbg("trying to find size %d,%d", x, y);
+		for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
+			if((camera_sizes[newsize][0] == x) && (camera_sizes[newsize][1] == y))
+				break;
+		}
+	} else {
+		newsize = cam->size;
+	}
+
+	if(newsize > MAX_FRAME_SIZE) {
+		dbg("couldnt find size %d,%d", x, y);
+		return -EINVAL;
+	}
 
-	return speed_to_fps[t->size][t->speed]/3;
+	if(fps > 0) {
+		dbg("trying to set fps to %d", fps);
+		for(newspeed = 0; newspeed <= MAX_SPEED; newspeed++) {
+			if(fps == spd_to_fps[newsize][newspeed]/3)
+				break;
+		}
+	} else {
+		newspeed = cam->speed;
+	}
+
+	if(newspeed > MAX_SPEED)
+		return -EINVAL;
+
+	dbg("setting size to %d speed to %d", newsize, newspeed);
+	if((newsize == cam->size) && (newspeed == cam->speed)) {
+		/* Nothing to do */
+		return 0;
+	}
+
+	konicawc_stop_data(uvd);
+	konicawc_set_misc(uvd, 0x2, 0, 0x0b);
+	uvd->ifaceAltActive = spd_to_iface[newspeed];
+	dbg("new interface = %d", uvd->ifaceAltActive);
+	cam->size = newsize;
+	cam->speed = newspeed;
+	konicawc_set_misc(uvd, 0x2, 1, 0x0b);
+	konicawc_start_data(uvd);
+	return 0;
+}
+
+
+static int konicawc_calculate_fps(uvd_t *uvd)
+{
+	struct konicawc *cam = uvd->user_data;
+	return spd_to_fps[cam->size][cam->speed]/3;
 }
 
 
@@ -548,6 +637,9 @@
 	cam->sharpness = sharpness / 11;
 	cam->white_bal = whitebal / 11;
 
+	cam->maxline = (cam->height * cam->width * 3) / (2 * 384);
+	cam->yplanesz = cam->height * cam->width;
+
 	uvd->vpic.colour = 108;
 	uvd->vpic.hue = 108;
 	uvd->vpic.brightness = brightness;
@@ -582,7 +674,6 @@
 	if(konicawc_set_misc(uvd, 0x2, 0, 0xd))
 		dbg("2,0,d failed");
 	dbg("setting initial values");
-
 }
 
 
@@ -605,10 +696,8 @@
 
 	/* Validate found interface: must have one ISO endpoint */
 	nas = dev->actconfig->interface[ifnum].num_altsetting;
-	if (debug > 0)
-		info("Number of alternate settings=%d.", nas);
-	if (nas < 8) {
-		err("Too few alternate settings for this camera!");
+	if (nas != 8) {
+		err("Incorrect number of alternate settings (%d) for this camera!", nas);
 		return NULL;
 	}
 	/* Validate all alternate settings */
@@ -647,22 +736,20 @@
 				return NULL;
 			}
 		} else {
-			if (i == speed_to_interface[speed]) {
+			if (i == spd_to_iface[speed]) {
 				/* This one is the requested one */
 				actInterface = i;
-				maxPS = endpoint->wMaxPacketSize;
-				if (debug > 0) {
-					info("Selecting requested active setting=%d. maxPS=%d.",
-					     i, maxPS);
-				}
 			}
 		}
+		if(endpoint->wMaxPacketSize > maxPS)
+			maxPS = endpoint->wMaxPacketSize;
 	}
 	if(actInterface == -1) {
 		err("Cant find required endpoint");
 		return NULL;
 	}
 
+	dbg("Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS);
 
 	/* Code below may sleep, need to lock module while we are here */
 	MOD_INC_USE_COUNT;
@@ -757,6 +844,7 @@
 	cbTbl.setupOnOpen = konicawc_setup_on_open;
 	cbTbl.processData = konicawc_process_isoc;
 	cbTbl.getFPS = konicawc_calculate_fps;
+	cbTbl.setVideoMode = konicawc_set_video_mode;
 	cbTbl.startDataPump = konicawc_start_data;
 	cbTbl.stopDataPump = konicawc_stop_data;
 	cbTbl.adjustPicture = konicawc_adjust_picture;
@@ -767,7 +855,8 @@
 		sizeof(struct konicawc),
 		"konicawc",
 		&cbTbl,
-		THIS_MODULE);
+		THIS_MODULE,
+		id_table);
 }
 
 
diff -urN -X /home/spse/dontdiff linux-2.5.12-clean/drivers/usb/media/ultracam.c linux-2.5.12/drivers/usb/media/ultracam.c
--- linux-2.5.12-clean/drivers/usb/media/ultracam.c	Wed May  1 01:08:48 2002
+++ linux-2.5.12/drivers/usb/media/ultracam.c	Wed May  1 02:49:32 2002
@@ -659,6 +659,12 @@
 	return uvd;
 }
 
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
+	{ }  /* Terminating entry */
+};
+
 /*
  * ultracam_init()
  *
@@ -682,7 +688,8 @@
 		sizeof(ultracam_t),
 		"ultracam",
 		&cbTbl,
-		THIS_MODULE);
+		THIS_MODULE,
+		id_table);
 }
 
 static void __exit ultracam_cleanup(void)
@@ -690,16 +697,7 @@
 	usbvideo_Deregister(&cams);
 }
 
-#if defined(usb_device_id_ver)
-
-static __devinitdata struct usb_device_id id_table[] = {
-	{ USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
-	{ }  /* Terminating entry */
-};
 MODULE_DEVICE_TABLE(usb, id_table);
-
-
-#endif /* defined(usb_device_id_ver) */
 MODULE_LICENSE("GPL");
 
 module_init(ultracam_init);
diff -urN -X /home/spse/dontdiff linux-2.5.12-clean/drivers/usb/media/usbvideo.c linux-2.5.12/drivers/usb/media/usbvideo.c
--- linux-2.5.12-clean/drivers/usb/media/usbvideo.c	Wed May  1 01:08:58 2002
+++ linux-2.5.12/drivers/usb/media/usbvideo.c	Wed May  1 02:49:44 2002
@@ -749,7 +749,8 @@
 	const int num_extra,
 	const char *driverName,
 	const usbvideo_cb_t *cbTbl,
-	struct module *md )
+	struct module *md,
+	struct usb_device_id id_table[])
 {
 	static const char proc[] = "usbvideo_register";
 	usbvideo_t *cams;
@@ -839,6 +840,7 @@
 	cams->usbdrv.name = cams->drvName;
 	cams->usbdrv.probe = cams->cb.probe;
 	cams->usbdrv.disconnect = cams->cb.disconnect;
+	cams->usbdrv.id_table = id_table;
 
 #if USES_PROC_FS
 	if (cams->uses_procfs) {
@@ -1192,7 +1194,7 @@
 	if (!CAMERA_IS_OPERATIONAL(uvd))
 		return -EFAULT;
 
-	if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+	if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 		return -EINVAL;
 
 	pos = (unsigned long) uvd->fbuf;
@@ -1441,7 +1443,8 @@
 		case VIDIOCSWIN:
 		{
 			struct video_window *vw = arg;
-
+			int fps;
+			/*
 			if (vw->flags)
 				return -EINVAL;
 			if (vw->clipcount)
@@ -1450,7 +1453,17 @@
 				return -EINVAL;
 			if (vw->height != VIDEOSIZE_Y(uvd->canvas))
 				return -EINVAL;
-
+			*/
+			fps = vw->flags;
+			if(VALID_CALLBACK(uvd, setVideoMode)) {
+				int err;
+				err = GET_CALLBACK(uvd, setVideoMode)(uvd, vw->width, vw->height, fps);
+				if(!err) {
+					return 0;
+				} else {
+					return -EINVAL;
+				}
+			}
 			return 0;
 		}
 		case VIDIOCGWIN:
@@ -1459,8 +1472,8 @@
 
 			vw->x = 0;
 			vw->y = 0;
-			vw->width = VIDEOSIZE_X(uvd->canvas);
-			vw->height = VIDEOSIZE_Y(uvd->canvas);
+			vw->width = VIDEOSIZE_X(uvd->videosize);
+			vw->height = VIDEOSIZE_Y(uvd->videosize);
 			vw->chromakey = 0;
 			if (VALID_CALLBACK(uvd, getFPS))
 				vw->flags = GET_CALLBACK(uvd, getFPS)(uvd);
@@ -1471,12 +1484,14 @@
 		case VIDIOCGMBUF:
 		{
 			struct video_mbuf *vm = arg;
+			int i;
 
 			memset(vm, 0, sizeof(*vm));
-			vm->size = uvd->max_frame_size * 2;
-			vm->frames = 2;
-			vm->offsets[0] = 0;
-			vm->offsets[1] = uvd->max_frame_size;
+			vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES;
+			vm->frames = USBVIDEO_NUMFRAMES;
+			for(i = 0; i < USBVIDEO_NUMFRAMES; i++) 
+			  vm->offsets[i] = i * uvd->max_frame_size;
+
 			return 0;
 		}
 		case VIDIOCMCAPTURE:
@@ -1518,8 +1533,8 @@
 				}
 				return -EINVAL;
 			}
-			if ((vm->frame != 0) && (vm->frame != 1)) {
-				err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm->frame);
+			if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) {
+				err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1);
 				return -EINVAL;
 			}
 			if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) {
@@ -1618,7 +1633,7 @@
 	static const char proc[] = "usbvideo_v4l_read";
 	uvd_t *uvd = file->private_data;
 	int noblock = file->f_flags & O_NONBLOCK;
-	int frmx = -1;
+	int frmx = -1, i;
 	usbvideo_frame_t *frame;
 
 	if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
@@ -1630,14 +1645,13 @@
 	down(&uvd->lock);	
 
 	/* See if a frame is completed, then use it. */
-	if ((uvd->frame[0].frameState == FrameState_Done) ||
-	    (uvd->frame[0].frameState == FrameState_Done_Hold) ||
-	    (uvd->frame[0].frameState == FrameState_Error)) {
-		frmx = 0;
-	} else if ((uvd->frame[1].frameState >= FrameState_Done) ||
-		   (uvd->frame[1].frameState == FrameState_Done_Hold) ||
-		   (uvd->frame[1].frameState >= FrameState_Done)) {
-		frmx = 1;
+	for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
+		if ((uvd->frame[i].frameState == FrameState_Done) ||
+		    (uvd->frame[i].frameState == FrameState_Done_Hold) ||
+		    (uvd->frame[i].frameState == FrameState_Error)) {
+			frmx = i;
+			break;
+		}
 	}
 
 	/* FIXME: If we don't start a frame here then who ever does? */
@@ -1652,10 +1666,12 @@
 	 * We will need to wait until it becomes cooked, of course.
 	 */
 	if (frmx == -1) {
-		if (uvd->frame[0].frameState == FrameState_Grabbing)
-			frmx = 0;
-		else if (uvd->frame[1].frameState == FrameState_Grabbing)
-			frmx = 1;
+		for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
+			if (uvd->frame[i].frameState == FrameState_Grabbing) {
+				frmx = i;
+				break;
+			}
+		}
 	}
 
 	/*
@@ -1753,7 +1769,7 @@
 
 		/* Mark it as available to be used again. */
 		uvd->frame[frmx].frameState = FrameState_Unused;
-		if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) {
+		if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
 			err("%s: usbvideo_NewFrame failed.", proc);
 		}
 	}
@@ -1990,7 +2006,7 @@
 		uvd->settingsAdjusted = 1;
 	}
 
-	n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
+	n = (framenum + 1) % USBVIDEO_NUMFRAMES;
 	if (uvd->frame[n].frameState == FrameState_Ready)
 		framenum = n;
 
@@ -2022,7 +2038,8 @@
 	 */
 	if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
 		/* This copies previous frame into this one to mask losses */
-		memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size);
+		int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
+		memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size);
 	} else {
 		if (uvd->flags & FLAGS_CLEAN_FRAMES) {
 			/* This provides a "clean" frame but slows things down */
diff -urN -X /home/spse/dontdiff linux-2.5.12-clean/drivers/usb/media/usbvideo.h linux-2.5.12/drivers/usb/media/usbvideo.h
--- linux-2.5.12-clean/drivers/usb/media/usbvideo.h	Wed May  1 02:54:52 2002
+++ linux-2.5.12/drivers/usb/media/usbvideo.h	Wed May  1 02:49:44 2002
@@ -271,6 +271,7 @@
 	int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data);
 	int (*startDataPump)(uvd_t *uvd);
 	void (*stopDataPump)(uvd_t *uvd);
+	int (*setVideoMode)(uvd_t *, int, int, int);
 } usbvideo_cb_t;
 
 struct s_usbvideo_t {
@@ -327,7 +328,8 @@
 	const int num_extra,
 	const char *driverName,
 	const usbvideo_cb_t *cbTable,
-	struct module *md);
+	struct module *md,
+	struct usb_device_id id_table[]);
 uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams);
 int usbvideo_RegisterVideoDevice(uvd_t *uvd);
 void usbvideo_Deregister(usbvideo_t **uvt);
