V4L/DVB (4927): Enhancements on usbvision driver

Enhance the buffer management of this driver + some corrections
- linux list.h usage for buffer management
- VIDIOC_ENUMSTD/VIDIOC_G_STD/VIDIOC_S_STD simplification (use of
v4l2_video_std_construct)
- create_sysfs : remove of warnings for video_device_create_file return code
- make the driver compatible with 2.6.19 kernel version (remove
slave_send and slave_recv in usbvision-i2c, change ctrlUrb_complete
function prototype)
- deactivated v4l2_read because this code was not the priority but
working on it :)

Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index f225701..06e8e67 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -437,6 +437,25 @@
 	{ 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
 };
 
+/* supported tv norms */
+static struct usbvision_tvnorm tvnorms[] = {
+	{
+		.name = "PAL",
+		.id = V4L2_STD_PAL,
+	}, {
+		.name = "NTSC",
+		.id = V4L2_STD_NTSC,
+	}, {
+		 .name = "SECAM",
+		 .id = V4L2_STD_SECAM,
+	}, {
+		.name = "PAL-M",
+		.id = V4L2_STD_PAL_M,
+	}
+};
+
+#define TVNORMS ARRAY_SIZE(tvnorms)
+
 
 /*
  * The value of 'scratch_buf_size' affects quality of the picture
@@ -451,7 +470,7 @@
 // Function prototypes
 static int usbvision_restart_isoc(struct usb_usbvision *usbvision);
 static int usbvision_begin_streaming(struct usb_usbvision *usbvision);
-static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel, int norm);
+static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel);
 static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, short len);
 static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, short len);
 static int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
@@ -463,6 +482,8 @@
 static void usbvision_release(struct usb_usbvision *usbvision);
 static int usbvision_set_input(struct usb_usbvision *usbvision);
 static int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
+static void usbvision_empty_framequeues(struct usb_usbvision *dev);
+static int usbvision_stream_interrupt(struct usb_usbvision *dev);
 static void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, void *arg);
 
 
@@ -609,7 +630,7 @@
 {
 	struct video_device *vdev = to_video_device(class_dev);
 	struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-	return sprintf(buf, "%s\n", YES_NO(usbvision->streaming));
+	return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0));
 }
 static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
 
@@ -639,17 +660,18 @@
 
 static void usbvision_create_sysfs(struct video_device *vdev)
 {
+	int res;
 	if (vdev) {
-		video_device_create_file(vdev, &class_device_attr_version);
-		video_device_create_file(vdev, &class_device_attr_model);
-		video_device_create_file(vdev, &class_device_attr_hue);
-		video_device_create_file(vdev, &class_device_attr_contrast);
-		video_device_create_file(vdev, &class_device_attr_brightness);
-		video_device_create_file(vdev, &class_device_attr_saturation);
-		video_device_create_file(vdev, &class_device_attr_streaming);
-		video_device_create_file(vdev, &class_device_attr_overlay);
-		video_device_create_file(vdev, &class_device_attr_compression);
-		video_device_create_file(vdev, &class_device_attr_bridge);
+		res=video_device_create_file(vdev, &class_device_attr_version);
+		res=video_device_create_file(vdev, &class_device_attr_model);
+		res=video_device_create_file(vdev, &class_device_attr_hue);
+		res=video_device_create_file(vdev, &class_device_attr_contrast);
+		res=video_device_create_file(vdev, &class_device_attr_brightness);
+		res=video_device_create_file(vdev, &class_device_attr_saturation);
+		res=video_device_create_file(vdev, &class_device_attr_streaming);
+		res=video_device_create_file(vdev, &class_device_attr_overlay);
+		res=video_device_create_file(vdev, &class_device_attr_compression);
+		res=video_device_create_file(vdev, &class_device_attr_bridge);
 	}
 }
 
@@ -1209,15 +1231,13 @@
 		printk(KERN_ERR "%s: usbvision == NULL\n", proc);
 		return;
 	}
-	if ((usbvision->curFrameNum < 0)
-	    || (usbvision->curFrameNum >= USBVISION_NUMFRAMES)) {
-		printk(KERN_ERR "%s: usbvision->curFrameNum=%d.\n", proc,
-		       usbvision->curFrameNum);
+	if (usbvision->curFrame == NULL) {
+		printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc);
 		return;
 	}
 
 	/* Grab the current frame */
-	frame = &usbvision->frame[usbvision->curFrameNum];
+	frame = usbvision->curFrame;
 
 	/* Optionally start at the beginning */
 	if (fullframe) {
@@ -1290,7 +1310,7 @@
 		frame = &usbvision->overlay_frame;
 	}
 	else {
-		frame = &usbvision->frame[usbvision->curFrameNum];
+		frame = usbvision->curFrame;
 	}
 
 	while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) {
@@ -1325,7 +1345,6 @@
 		frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width;
 		frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height;
 		frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3;
-		usbvision->curFrame = frame;
 	}
 	else { // no header found
 		PDEBUG(DBG_HEADER, "skipping scratch data, no header");
@@ -1380,7 +1399,7 @@
 			usbvision->vid_buf.fmt.bytesperline;
 	}
 	else {
-		frame  = &usbvision->frame[usbvision->curFrameNum];
+		frame  = usbvision->curFrame;
 		f = frame->data + (frame->v4l2_linesize * frame->curline);
 	}
 
@@ -1612,7 +1631,7 @@
 			usbvision->vid_buf.fmt.bytesperline;
 	}
 	else {
-		frame  = &usbvision->frame[usbvision->curFrameNum];
+		frame  = usbvision->curFrame;
 		imageSize = frame->frmwidth * frame->frmheight;
 		if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
 		     (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) )
@@ -1833,7 +1852,7 @@
 		f_odd  = f_even + usbvision->vid_buf.fmt.bytesperline * usbvision->stretch_height;
 	}
 	else {
-		frame  = &usbvision->frame[usbvision->curFrameNum];
+		frame  = usbvision->curFrame;
 		f_even = frame->data + (frame->v4l2_linesize * frame->curline);
 		f_odd  = f_even + frame->v4l2_linesize * usbvision->stretch_height;
 	}
@@ -2088,17 +2107,17 @@
 	struct usbvision_frame *frame;
 	enum ParseState newstate;
 	long copylen = 0;
+	unsigned long lock_flags;
 
 	if (usbvision->overlay) {
 		frame = &usbvision->overlay_frame;
 	}
 	else {
-		frame = &usbvision->frame[usbvision->curFrameNum];
+		frame = usbvision->curFrame;
 	}
 
 	PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision));
 
-
 	while (1) {
 
 		newstate = ParseState_Out;
@@ -2141,7 +2160,10 @@
 			copylen = 0;
 		}
 		else {
-			usbvision->curFrameNum = -1;
+			spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+			list_move_tail(&(frame->frame), &usbvision->outqueue);
+			usbvision->curFrame = NULL;
+			spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
 		}
 		usbvision->frame_num++;
 
@@ -2150,10 +2172,14 @@
 			usbvision_osd_stats(usbvision, frame);
 
 		/* This will cause the process to request another frame. */
-		if (waitqueue_active(&frame->wq)) {
-			wake_up_interruptible(&frame->wq);
+		if (waitqueue_active(&usbvision->wait_frame)) {
+			PDEBUG(DBG_PARSE, "Wake up !");
+			wake_up_interruptible(&usbvision->wait_frame);
 		}
 	}
+	else
+		frame->grabstate = FrameState_Grabbing;
+
 
 	/* Update the frame's uncompressed length. */
 	frame->scanlength += copylen;
@@ -2164,7 +2190,7 @@
  * Make all of the blocks of data contiguous
  */
 static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
-				       struct urb *urb)
+					  struct urb *urb)
 {
 	unsigned char *packet_data;
 	int i, totlen = 0;
@@ -2246,51 +2272,70 @@
 
 static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)
 {
- int errCode = 0;
- int len;
- struct usb_usbvision *usbvision = urb->context;
- int i;
- unsigned long startTime = jiffies;
+	int errCode = 0;
+	int len;
+	struct usb_usbvision *usbvision = urb->context;
+	int i;
+	unsigned long startTime = jiffies;
+	struct usbvision_frame **f;
 
- /* We don't want to do anything if we are about to be removed! */
- if (!USBVISION_IS_OPERATIONAL(usbvision))
-  return;
+	/* We don't want to do anything if we are about to be removed! */
+	if (!USBVISION_IS_OPERATIONAL(usbvision))
+		return;
 
- if (!usbvision->streaming) {
-  PDEBUG(DBG_IRQ, "oops, not streaming, but interrupt");
-  return;
- }
+	f = &usbvision->curFrame;
 
- /* Copy the data received into our scratch buffer */
- len = usbvision_compress_isochronous(usbvision, urb);
+	/* Manage streaming interruption */
+	if (usbvision->streaming == Stream_Interrupt) {
+		usbvision->streaming = Stream_Off;
+		if ((*f)) {
+			(*f)->grabstate = FrameState_Ready;
+			(*f)->scanstate = ScanState_Scanning;
+		}
+		PDEBUG(DBG_IRQ, "stream interrupted");
+		wake_up_interruptible(&usbvision->wait_stream);
+	}
 
- usbvision->isocUrbCount++;
- usbvision->urb_length = len;
+	/* Copy the data received into our scratch buffer */
+	len = usbvision_compress_isochronous(usbvision, urb);
 
- for (i = 0; i < USBVISION_URB_FRAMES; i++) {
-  urb->iso_frame_desc[i].status = 0;
-  urb->iso_frame_desc[i].actual_length = 0;
- }
+	usbvision->isocUrbCount++;
+	usbvision->urb_length = len;
+
+	if (usbvision->streaming == Stream_On) {
+
+		/* If we collected enough data let's parse! */
+		if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) {	/* 12 == header_length */
+			/*If we don't have a frame we're current working on, complain */
+			if((!list_empty(&(usbvision->inqueue))) || (usbvision->overlay)) {
+				if (!(*f)) {
+					(*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame);
+				}
+				usbvision_parse_data(usbvision);
+			}
+			else {
+				PDEBUG(DBG_IRQ, "received data, but no one needs it");
+				scratch_reset(usbvision);
+			}
+		}
+	}
+
+	usbvision->timeInIrq += jiffies - startTime;
+
+	for (i = 0; i < USBVISION_URB_FRAMES; i++) {
+		urb->iso_frame_desc[i].status = 0;
+		urb->iso_frame_desc[i].actual_length = 0;
+	}
+
 	urb->status = 0;
 	urb->dev = usbvision->dev;
 	errCode = usb_submit_urb (urb, GFP_ATOMIC);
 
-/* Disable this warning.  By design of the driver. */
-//	if(errCode) {
-//		err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
-//	}
+	/* Disable this warning.  By design of the driver. */
+	//	if(errCode) {
+	//		err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
+	//	}
 
-	/* If we collected enough data let's parse! */
-	if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) {	/* 12 == header_length */
-		/*If we don't have a frame we're current working on, complain */
-		if ((usbvision->curFrameNum >= 0) || (usbvision->overlay))
-			usbvision_parse_data(usbvision);
-		else {
-			PDEBUG(DBG_IRQ, "received data, but no one needs it");
-			scratch_reset(usbvision);
-		}
-	}
-	usbvision->timeInIrq += jiffies - startTime;
 	return;
 }
 
@@ -2539,7 +2584,6 @@
 	struct usb_usbvision *usbvision;
 	struct tuner_setup tun_addr;
 	int i;
-	v4l2_std_id stdId;
 
 	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 		usbvision = (struct usb_usbvision *)client->adapter->data;
@@ -2560,13 +2604,11 @@
 		tun_addr.type = usbvision->tuner_type;
 		tun_addr.addr = ADDR_UNSET;
 		client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
-
-		call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->input.index);
+		call_i2c_clients(usbvision, VIDIOC_INT_RESET, NULL);
+		call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
+		call_i2c_clients(usbvision, VIDIOC_STREAMON, NULL);
 	}
-	// FIXME : need to add a call VIDIOC_S_CTRL for each control
-/* 	call_i2c_clients(usbvision, DECODER_SET_PICTURE, &usbvision->vpic); */
-	stdId = usbvision->input.std;
-	call_i2c_clients(usbvision, VIDIOC_S_STD, &stdId);
+	call_i2c_clients(usbvision, VIDIOC_S_STD, &usbvision->tvnorm->id);
 
 	PDEBUG(DBG_I2C, "usbvision[%d] attaches %s", usbvision->nr, client->name);
 
@@ -2995,10 +3037,10 @@
 		frameRate = FRAMERATE_MAX;
 	}
 
-	if (usbvision->input.std & V4L2_STD_625_50) {
+	if (usbvision->tvnorm->id & V4L2_STD_625_50) {
 		frameDrop = frameRate * 32 / 25 - 1;
 	}
-	else if (usbvision->input.std & V4L2_STD_525_60) {
+	else if (usbvision->tvnorm->id & V4L2_STD_525_60) {
 		frameDrop = frameRate * 32 / 30 - 1;
 	}
 
@@ -3022,6 +3064,40 @@
 
 
 /*
+ * usbvision_empty_framequeues()
+ * prepare queues for incoming and outgoing frames
+ */
+static void usbvision_empty_framequeues(struct usb_usbvision *usbvision)
+{
+	u32 i;
+
+	INIT_LIST_HEAD(&(usbvision->inqueue));
+	INIT_LIST_HEAD(&(usbvision->outqueue));
+
+	for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+		usbvision->frame[i].grabstate = FrameState_Unused;
+		usbvision->frame[i].bytes_read = 0;
+	}
+}
+
+/*
+ * usbvision_stream_interrupt()
+ * stops streaming
+ */
+static int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
+{
+	int ret = 0;
+
+	/* stop reading from the device */
+
+	usbvision->streaming = Stream_Interrupt;
+	ret = wait_event_timeout(usbvision->wait_stream,
+				 (usbvision->streaming == Stream_Off),
+				 msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
+	return ret;
+}
+
+/*
  * usbvision_set_compress_params()
  *
  */
@@ -3135,7 +3211,7 @@
 	}
 
 
-	if (usbvision->input.std & V4L2_STD_PAL) {
+	if (usbvision->tvnorm->id & V4L2_STD_PAL) {
 		value[0] = 0xC0;
 		value[1] = 0x02;	//0x02C0 -> 704 Input video line length
 		value[2] = 0x20;
@@ -3144,7 +3220,7 @@
 		value[5] = 0x00;	//0x0060 -> 96 Input video h offset
 		value[6] = 0x16;
 		value[7] = 0x00;	//0x0016 -> 22 Input video v offset
-	} else if (usbvision->input.std & V4L2_STD_SECAM) {
+	} else if (usbvision->tvnorm->id & V4L2_STD_SECAM) {
 		value[0] = 0xC0;
 		value[1] = 0x02;	//0x02C0 -> 704 Input video line length
 		value[2] = 0x20;
@@ -3434,7 +3510,7 @@
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return -EFAULT;
 
-	usbvision->curFrameNum = -1;
+	usbvision->curFrame = NULL;
 	scratch_reset(usbvision);
 
 	/* Alternate interface 1 is is the biggest frame size */
@@ -3503,7 +3579,7 @@
 		}
 	}
 
-	usbvision->streaming = 1;
+	usbvision->streaming = Stream_On;
 	PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
 	return 0;
 }
@@ -3519,7 +3595,8 @@
 {
 	int bufIdx, errCode, regValue;
 
-	if (!usbvision->streaming || (usbvision->dev == NULL))
+	// FIXME : removed the streaming==Stream_Off. This field has not the same signification than before !
+	if (usbvision->dev == NULL)
 		return;
 
 	/* Unschedule all of the iso td's */
@@ -3530,9 +3607,8 @@
 	}
 
 
-	PDEBUG(DBG_ISOC, "%s: streaming=0\n", __FUNCTION__);
-	usbvision->streaming = 0;
-
+	PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
+	usbvision->streaming = Stream_Off;
 
 	if (!usbvision->remove_pending) {
 
@@ -3552,62 +3628,7 @@
 	}
 }
 
-/*
- * usbvision_new_frame()
- *
- */
-static int usbvision_new_frame(struct usb_usbvision *usbvision, int framenum)
-{
-	struct usbvision_frame *frame;
-	int n; //byhec  , width, height;
-
-	/* If we're not grabbing a frame right now and the other frame is */
-	/*  ready to be grabbed into, then use it instead */
-	if (usbvision->curFrameNum != -1)
-		return 0;
-
-	n = (framenum - 1 + USBVISION_NUMFRAMES) % USBVISION_NUMFRAMES;
-	if (usbvision->frame[n].grabstate == FrameState_Ready)
-		framenum = n;
-
-	frame = &usbvision->frame[framenum];
-
-	frame->grabstate = FrameState_Grabbing;
-	frame->scanstate = ScanState_Scanning;
-	frame->scanlength = 0;	/* Accumulated in usbvision_parse_data() */
-	usbvision->curFrameNum = framenum;
-
-	/*
-	 * Normally we would want to copy previous frame into the current one
-	 * before we even start filling it with data; this allows us to stop
-	 * filling at any moment; top portion of the frame will be new and
-	 * bottom portion will stay as it was in previous frame. If we don't
-	 * do that then missing chunks of video stream will result in flickering
-	 * portions of old data whatever it was before.
-	 *
-	 * If we choose not to copy previous frame (to, for example, save few
-	 * bus cycles - the frame can be pretty large!) then we have an option
-	 * to clear the frame before using. If we experience losses in this
-	 * mode then missing picture will be black (flickering).
-	 *
-	 * Finally, if user chooses not to clean the current frame before
-	 * filling it with data then the old data will be visible if we fail
-	 * to refill entire frame with new data.
-	 */
-	if (!(flags & FLAGS_SEPARATE_FRAMES)) {
-		/* This copies previous frame into this one to mask losses */
-		memmove(frame->data, usbvision->frame[1 - framenum].data,
-			MAX_FRAME_SIZE);
-	} else {
-		if (flags & FLAGS_CLEAN_FRAMES) {
-			/*This provides a "clean" frame but slows things down */
-			memset(frame->data, 0, MAX_FRAME_SIZE);
-		}
-	}
-	return 0;
-}
-
-static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel, int norm)
+static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
 {
 	int mode[4];
 	int audio[]= {1, 0, 0, 0};
@@ -3618,16 +3639,10 @@
 	//channel 3 is additional video inputs to the device with audio channel 0 (line in)
 
 	RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
-	/* set the new video norm */
-	if (usbvision->input.std != norm) {
-	  v4l2_std_id video_command = norm;
-
+	usbvision->ctl_input = channel;
 	  route.input = SAA7115_COMPOSITE1;
 	  call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
-	  call_i2c_clients(usbvision, VIDIOC_S_STD, &video_command);
-	  usbvision->input.std = norm;
-	  call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->input.index);	//set norm in tuner
-	}
+	  call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
 
 	// set the new channel
 	// Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video
@@ -3703,8 +3718,13 @@
 			errCode = -ENOMEM;
 		}
 		else {
+			spin_lock_init(&usbvision->queue_lock);
+			init_waitqueue_head(&usbvision->wait_frame);
+			init_waitqueue_head(&usbvision->wait_stream);
+
 			/* Allocate all buffers */
 			for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+				usbvision->frame[i].index = i;
 				usbvision->frame[i].grabstate = FrameState_Unused;
 				usbvision->frame[i].data = usbvision->fbuf +
 				    i * MAX_FRAME_SIZE;
@@ -3804,6 +3824,9 @@
 	if (errCode) {
 	}
 
+	/* prepare queues */
+	usbvision_empty_framequeues(usbvision);
+
 	PDEBUG(DBG_IO, "success");
 	return errCode;
 }
@@ -3875,6 +3898,8 @@
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return -EFAULT;
 
+	//	if (debug & DBG_IOCTL) v4l_printk_ioctl(cmd);
+
 	switch (cmd) {
 		case UVIOCSREG:
 		{
@@ -3914,7 +3939,20 @@
 		case VIDIOC_QUERYCAP:
 		{
 			struct v4l2_capability *vc=arg;
-			*vc = usbvision->vcap;
+
+			memset(vc, 0, sizeof(*vc));
+			strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+			strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
+				sizeof(vc->card));
+			strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+				sizeof(vc->bus_info));
+			vc->version = USBVISION_DRIVER_VERSION;
+			vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+				V4L2_CAP_AUDIO |
+				V4L2_CAP_READWRITE |
+				V4L2_CAP_STREAMING |
+				(dga ? (V4L2_FBUF_CAP_LIST_CLIPPING | V4L2_CAP_VIDEO_OVERLAY) : 0) |
+				(usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
 			PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP");
 			return 0;
 		}
@@ -3975,38 +4013,24 @@
 		}
 		case VIDIOC_ENUMSTD:
 		{
-			struct v4l2_standard *vs = arg;
-			switch(vs->index) {
-			case 0:
-				vs->id = V4L2_STD_PAL;
-				strcpy(vs->name,"PAL");
-				vs->frameperiod.numerator   = 1;
-				vs->frameperiod.denominator = 25;
-				vs->framelines              = 625;
-				break;
-			case 1:
-				vs->id = V4L2_STD_NTSC;
-				strcpy(vs->name,"NTSC");
-				vs->frameperiod.numerator   = 1001;
-				vs->frameperiod.denominator = 30000;
-				vs->framelines              = 525;
-				break;
-			case 2:
-				vs->id = V4L2_STD_SECAM;
-				strcpy(vs->name,"SECAM");
-				vs->frameperiod.numerator   = 1;
-				vs->frameperiod.denominator = 25;
-				vs->framelines              = 625;
-				break;
-			default:
+			struct v4l2_standard *e = arg;
+			unsigned int i;
+			int ret;
+
+			i = e->index;
+			if (i >= TVNORMS)
 				return -EINVAL;
-			}
+			ret = v4l2_video_std_construct(e, tvnorms[e->index].id,
+						       tvnorms[e->index].name);
+			e->index = i;
+			if (ret < 0)
+				return ret;
 			return 0;
 		}
 		case VIDIOC_G_INPUT:
 		{
 			int *input = arg;
-			*input = usbvision->input.index;
+			*input = usbvision->ctl_input;
 			return 0;
 		}
 		case VIDIOC_S_INPUT:
@@ -4014,10 +4038,10 @@
 			int *input = arg;
 			if ((*input >= usbvision->video_inputs) || (*input < 0) )
 				return -EINVAL;
-			usbvision->input.index = *input;
+			usbvision->ctl_input = *input;
 
 			down(&usbvision->lock);
-			usbvision_muxsel(usbvision, usbvision->input.index, usbvision->input.std);
+			usbvision_muxsel(usbvision, usbvision->ctl_input);
 			usbvision_set_input(usbvision);
 			usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight);
 			up(&usbvision->lock);
@@ -4025,43 +4049,50 @@
 		}
 		case VIDIOC_G_STD:
 		{
-			v4l2_std_id *std = arg;
-			*std = usbvision->input.std;
-			PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%x", (unsigned)*std);
+			v4l2_std_id *id = arg;
+
+			*id = usbvision->tvnorm->id;
+
+			PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name);
 			return 0;
 		}
 		case VIDIOC_S_STD:
 		{
-			v4l2_std_id *std = arg;
+			v4l2_std_id *id = arg;
+			unsigned int i;
+
+			for (i = 0; i < TVNORMS; i++)
+				if (*id == tvnorms[i].id)
+					break;
+			if (i == TVNORMS)
+				for (i = 0; i < TVNORMS; i++)
+					if (*id & tvnorms[i].id)
+						break;
+			if (i == TVNORMS)
+				return -EINVAL;
 
 			down(&usbvision->lock);
-			usbvision_muxsel(usbvision, usbvision->input.index, *std);
-			usbvision_set_input(usbvision);
-			usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight);
+			usbvision->tvnorm = &tvnorms[i];
+
+			call_i2c_clients(usbvision, VIDIOC_S_STD,
+					 &usbvision->tvnorm->id);
+
 			up(&usbvision->lock);
 
-			usbvision->input.std = *std;
-			PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%x", (unsigned)*std);
+			PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name);
 			return 0;
 		}
 		case VIDIOC_G_TUNER:
 		{
 			struct v4l2_tuner *vt = arg;
-			struct v4l2_tuner status;
 
 			if (!usbvision->have_tuner || vt->index)	// Only tuner 0
 				return -EINVAL;
 			strcpy(vt->name, "Television");
-			vt->type = V4L2_TUNER_ANALOG_TV;
-			vt->capability = V4L2_TUNER_CAP_NORM;
-			vt->rangelow = 0;
-			vt->rangehigh = ~0;
-			vt->audmode = V4L2_TUNER_MODE_MONO;
-			vt->rxsubchans = V4L2_TUNER_SUB_MONO;
-			call_i2c_clients(usbvision,VIDIOC_G_TUNER,&status);
-			vt->signal = status.signal;
+			/* Let clients fill in the remainder of this struct */
+			call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt);
 
-			PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER");
+			PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc);
 			return 0;
 		}
 		case VIDIOC_S_TUNER:
@@ -4071,15 +4102,16 @@
 			// Only no or one tuner for now
 			if (!usbvision->have_tuner || vt->index)
 				return -EINVAL;
-			// FIXME     vt->audmode Radio mode (STEREO/MONO/...)
-			// vt->reserved Radio freq
-			// usbvision_muxsel(usbvision, vt->index, vt->mode);
+			/* let clients handle this */
+			call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
+
 			PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER");
 			return 0;
 		}
 		case VIDIOC_G_FREQUENCY:
 		{
 			struct v4l2_frequency *freq = arg;
+
 			freq->tuner = 0; // Only one tuner
 			freq->type = V4L2_TUNER_ANALOG_TV;
 			freq->frequency = usbvision->freq;
@@ -4089,6 +4121,11 @@
 		case VIDIOC_S_FREQUENCY:
 		{
 			struct v4l2_frequency *freq = arg;
+
+			// Only no or one tuner for now
+			if (!usbvision->have_tuner || freq->tuner)
+				return -EINVAL;
+
 			usbvision->freq = freq->frequency;
 			call_i2c_clients(usbvision, cmd, freq);
 			PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
@@ -4149,11 +4186,27 @@
 		case VIDIOC_REQBUFS:
 		{
 			struct v4l2_requestbuffers *vr = arg;
-			// FIXME : normally we allocate the requested number of buffers.
-			// this driver allocates statically the buffers.
-			vr->count = 2;
-			if(vr->memory != V4L2_MEMORY_MMAP)
+			int ret;
+
+			RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
+
+			// Check input validity : the user must do a VIDEO CAPTURE and MMAP method.
+			if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+			   (vr->memory != V4L2_MEMORY_MMAP))
 				return -EINVAL;
+
+			// FIXME : before this, we must control if buffers are still mapped.
+			// Then interrupt streaming if so...
+			if(usbvision->streaming == Stream_On) {
+				if ((ret = usbvision_stream_interrupt(usbvision)))
+				    return ret;
+			}
+
+			usbvision_empty_framequeues(usbvision);
+
+			usbvision->curFrame = NULL;
+
+			PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count);
 			return 0;
 		}
 		case VIDIOC_QUERYBUF:
@@ -4161,16 +4214,18 @@
 			struct v4l2_buffer *vb = arg;
 			struct usbvision_frame *frame;
 
-			// FIXME : works only on VIDEO_CAPTURE MODE, MMAP.
+			// FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called)
+
 			if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
 				return -EINVAL;
 			}
-			if(vb->index>1)  {
+			if(vb->index>=USBVISION_NUMFRAMES)  {
 				return -EINVAL;
 			}
+			// Updating the corresponding frame state
 			vb->flags = 0;
 			frame = &usbvision->frame[vb->index];
-			if(frame->grabstate == FrameState_Grabbing)
+			if(frame->grabstate >= FrameState_Ready)
 				vb->flags |= V4L2_BUF_FLAG_QUEUED;
 			if(frame->grabstate >= FrameState_Done)
 				vb->flags |= V4L2_BUF_FLAG_DONE;
@@ -4183,119 +4238,115 @@
 			else {
 				vb->m.offset = MAX_FRAME_SIZE;
 			}
+			vb->memory = V4L2_MEMORY_MMAP;
+			vb->field = V4L2_FIELD_NONE;
 			vb->length = MAX_FRAME_SIZE;
 			vb->timestamp = usbvision->frame[vb->index].timestamp;
-			vb->sequence = usbvision->frame_num;
+			vb->sequence = usbvision->frame[vb->index].sequence;
 			return 0;
 		}
-		case VIDIOC_QBUF: // VIDIOCMCAPTURE + VIDIOCSYNC
+		case VIDIOC_QBUF:
 		{
 			struct v4l2_buffer *vb = arg;
 			struct usbvision_frame *frame;
+			unsigned long lock_flags;
 
 			// FIXME : works only on VIDEO_CAPTURE MODE, MMAP.
 			if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
 				return -EINVAL;
 			}
-			if(vb->index>1)  {
+			if(vb->index>=USBVISION_NUMFRAMES)  {
 				return -EINVAL;
 			}
 
 			frame = &usbvision->frame[vb->index];
 
-			if (frame->grabstate == FrameState_Grabbing) {
-				return -EBUSY;
+			if (frame->grabstate != FrameState_Unused) {
+				return -EAGAIN;
 			}
 
-			usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight);
-
-			/* Mark it as ready */
+			/* Mark it as ready and enqueue frame */
 			frame->grabstate = FrameState_Ready;
+			frame->scanstate = ScanState_Scanning;
+			frame->scanlength = 0;	/* Accumulated in usbvision_parse_data() */
+
 			vb->flags &= ~V4L2_BUF_FLAG_DONE;
 
 			/* set v4l2_format index */
 			frame->v4l2_format = usbvision->palette;
-			PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame=%d",vb->index);
 
-			return usbvision_new_frame(usbvision, vb->index);
+			spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+			list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
+			spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+			return 0;
 		}
 		case VIDIOC_DQBUF:
 		{
 			struct v4l2_buffer *vb = arg;
-			int errCode = 0;
+			int ret;
+			struct usbvision_frame *f;
+			unsigned long lock_flags;
 
-			DECLARE_WAITQUEUE(wait, current);
-			// FIXME : not the proper way to get the last filled frame
-			vb->index=-1;
-			if(usbvision->curFrameNum != -1) vb->index=usbvision->curFrameNum;
-			else {
-				if(usbvision->frame[1].grabstate >= FrameState_Done)
-					vb->index = 1;
-				else if(usbvision->frame[0].grabstate >= FrameState_Done)
-					vb->index = 0;
-				// If no FRAME_DONE, look for a FRAME_GRABBING state.
-				// See if a frame is in process (grabbing), then use it.
-				if (vb->index == -1) {
-					if (usbvision->frame[1].grabstate == FrameState_Grabbing)
-						vb->index = 1;
-					else if (usbvision->frame[0].grabstate == FrameState_Grabbing)
-						vb->index = 0;
-				}
-			}
-			if (vb->index == -1)
+			if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 				return -EINVAL;
 
-			PDEBUG(DBG_IOCTL, "VIDIOC_DQBUF frame=%d, grabstate=%d, curframeNum=%d",
-				       vb->index, usbvision->frame[vb->index].grabstate,usbvision->curFrameNum);
-
-			switch (usbvision->frame[vb->index].grabstate) {
-			case FrameState_Unused:
-				errCode = -EINVAL;
-				break;
-			case FrameState_Grabbing:
-				add_wait_queue(&usbvision->frame[vb->index].wq, &wait);
-				current->state = TASK_INTERRUPTIBLE;
-				while (usbvision->frame[vb->index].grabstate == FrameState_Grabbing) {
-					schedule();
-					if (signal_pending(current)) {
-						remove_wait_queue(&usbvision->frame[vb->index].wq, &wait);
-						current->state = TASK_RUNNING;
-						return -EINTR;
-					}
-				}
-				remove_wait_queue(&usbvision->frame[vb->index].wq, &wait);
-				current->state = TASK_RUNNING;
-			case FrameState_Ready:
-			case FrameState_Error:
-			case FrameState_Done:
-				errCode = (usbvision->frame[vb->index].grabstate == FrameState_Error) ? -EIO : 0;
-				vb->memory = V4L2_MEMORY_MMAP;
-				vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE;
-				vb->field = V4L2_FIELD_NONE;
-				vb->sequence = usbvision->frame[vb->index].sequence;
-				usbvision->frame[vb->index].grabstate = FrameState_Unused;
-				break;
+			if (list_empty(&(usbvision->outqueue))) {
+				if (usbvision->streaming == Stream_Off)
+					return -EINVAL;
+				ret = wait_event_interruptible
+					(usbvision->wait_frame,
+					 !list_empty(&(usbvision->outqueue)));
+				if (ret)
+					return ret;
 			}
 
-			usbvision->frame[vb->index].grabstate = FrameState_Unused;
-			return errCode;
+			spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+			f = list_entry(usbvision->outqueue.next,
+				       struct usbvision_frame, frame);
+			list_del(usbvision->outqueue.next);
+			spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+			f->grabstate = FrameState_Unused;
+
+			vb->memory = V4L2_MEMORY_MMAP;
+			vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE;
+			vb->index = f->index;
+			vb->sequence = f->sequence;
+
+			return 0;
 		}
 		case VIDIOC_STREAMON:
 		{
 			int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+			if (list_empty(&usbvision->inqueue))
+				return -EINVAL;
+
+			usbvision->streaming = Stream_On;
+
 			call_i2c_clients(usbvision,VIDIOC_STREAMON , &b);
+
+			PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON");
+
 			return 0;
 		}
 		case VIDIOC_STREAMOFF:
 		{
+			int *type = arg;
 			int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-			down(&usbvision->lock);
-			// Stop all video streamings
-			call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
-			usbvision->frame_num = -1;
-			usbvision->frame[0].grabstate = FrameState_Unused;
-			usbvision->frame[1].grabstate = FrameState_Unused;
-			up(&usbvision->lock);
+
+			if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+
+			if(usbvision->streaming == Stream_On) {
+				usbvision_stream_interrupt(usbvision);
+				// Stop all video streamings
+				call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
+			}
+			usbvision_empty_framequeues(usbvision);
+
+			PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF");
 			return 0;
 		}
 		case VIDIOC_G_FBUF:
@@ -4361,6 +4412,7 @@
 		case VIDIOC_ENUM_FMT:
 		{
 			struct v4l2_fmtdesc *vfd = arg;
+
 			if ( (dga == 0) &&
 			     (vfd->type == V4L2_BUF_TYPE_VIDEO_OVERLAY) &&
 			     (usbvision->palette.format != V4L2_PIX_FMT_YVU420) &&
@@ -4539,7 +4591,7 @@
 	int frmx = -1;
 	int rc = 0;
 	struct usbvision_frame *frame;
-
+return -EINVAL;
 	PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock);
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
@@ -4574,7 +4626,8 @@
 
 	// If no frame is active, start one.
 	if (frmx == -1)
-		usbvision_new_frame(usbvision, frmx = 0);
+	// FIXME: enqueue all inqueue...
+	/* 		usbvision_new_frame(usbvision, frmx = 0); */
 
 	frame = &usbvision->frame[frmx];
 
@@ -4584,7 +4637,7 @@
 		goto usbvision_v4l2_read_done;
 	}
 	PDEBUG(DBG_IO, "Waiting frame grabbing");
-	rc = wait_event_interruptible(frame->wq, (frame->grabstate == FrameState_Done) ||
+	rc = wait_event_interruptible(usbvision->wait_frame, (frame->grabstate == FrameState_Done) ||
 						 (frame->grabstate == FrameState_Error));
 	if (rc) {
 		goto usbvision_v4l2_read_done;
@@ -4592,9 +4645,10 @@
 
 	if (frame->grabstate == FrameState_Error) {
 		frame->bytes_read = 0;
-		if (usbvision_new_frame(usbvision, frmx)) {
-			err("%s: usbvision_new_frame() failed", __FUNCTION__);
-		}
+		// FIXME: enqueue all inqueue...
+/* 		if (usbvision_new_frame(usbvision, frmx)) { */
+/* 			err("%s: usbvision_new_frame() failed", __FUNCTION__); */
+/* 		} */
 		goto restart;
 	}
 
@@ -4619,8 +4673,9 @@
 
 		/* Mark it as available to be used again. */
 		usbvision->frame[frmx].grabstate = FrameState_Unused;
-		if (usbvision_new_frame(usbvision, frmx ? 0 : 1))
-			err("%s: usbvision_new_frame() failed", __FUNCTION__);
+		// FIXME enqueue another frame
+/* 		if (usbvision_new_frame(usbvision, frmx ? 0 : 1)) */
+/* 			err("%s: usbvision_new_frame() failed", __FUNCTION__); */
 	}
 
 usbvision_v4l2_read_done:
@@ -5198,7 +5253,7 @@
 
 static void usbvision_configure_video(struct usb_usbvision *usbvision)
 {
-	int model;
+	int model,i;
 
 	if (usbvision == NULL)
 		return;
@@ -5215,17 +5270,26 @@
 
 	memset(&usbvision->vcap, 0, sizeof(usbvision->vcap));
 	strcpy(usbvision->vcap.driver, "USBVision");
-	usbvision->vcap.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
+	strlcpy(usbvision->vcap.bus_info, usbvision->dev->dev.bus_id,
+		sizeof(usbvision->vcap.bus_info));
+	usbvision->vcap.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
 		(dga ? (V4L2_FBUF_CAP_LIST_CLIPPING | V4L2_CAP_VIDEO_OVERLAY) : 0) |
 		(usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
 	usbvision->vcap.version = USBVISION_DRIVER_VERSION; 	    /* version */
 
-	usbvision->video_inputs = usbvision_device_data[model].VideoChannels;
 
-	memset(&usbvision->input, 0, sizeof(usbvision->input));
-	usbvision->input.tuner = 0;
-	usbvision->input.type = V4L2_INPUT_TYPE_TUNER|VIDEO_TYPE_CAMERA;
-	usbvision->input.std = usbvision_device_data[model].VideoNorm;
+	for (i = 0; i < TVNORMS; i++)
+		if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode)
+			break;
+	if (i == TVNORMS)
+		i = 0;
+	usbvision->tvnorm = &tvnorms[i];	/* set default norm */
+	call_i2c_clients(usbvision, VIDIOC_S_STD,
+			 &usbvision->tvnorm->id);
+
+	usbvision->video_inputs = usbvision_device_data[model].VideoChannels;
+	usbvision->ctl_input = 0;
+/* 	usbvision_muxsel(usbvision, usbvision->ctl_input); */
 
 	/* This should be here to make i2c clients to be able to register */
 	usbvision_audio_off(usbvision);	//first switch off audio
@@ -5440,7 +5504,6 @@
 static struct usb_usbvision *usbvision_alloc(struct usb_device *dev)
 {
 	struct usb_usbvision *usbvision;
-	int FrameIdx;
 
 	if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) {
 		goto err_exit;
@@ -5448,10 +5511,6 @@
 
 	usbvision->dev = dev;
 
-	for (FrameIdx = 0; FrameIdx < USBVISION_NUMFRAMES; FrameIdx++) {
-		init_waitqueue_head(&usbvision->frame[FrameIdx].wq);
-	}
-	init_waitqueue_head(&usbvision->overlay_frame.wq);
 	init_MUTEX(&usbvision->lock);	/* to 1 == available */
 
 	// prepare control urb for control messages during interrupts
@@ -5460,7 +5519,7 @@
 		goto err_exit;
 	}
 	init_waitqueue_head(&usbvision->ctrlUrb_wq);
-	init_MUTEX(&usbvision->ctrlUrbLock);
+	init_MUTEX(&usbvision->ctrlUrbLock);	/* to 1 == available */
 
 	init_timer(&usbvision->powerOffTimer);
 	usbvision->powerOffTimer.data = (long) usbvision;
@@ -5536,7 +5595,6 @@
 
 	PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
 					dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
-
 	/* Is it an USBVISION video dev? */
 	model = 0;
 	for(model = 0; usbvision_device_data[model].idVendor; model++) {
@@ -5655,6 +5713,9 @@
 	usb_put_dev(usbvision->dev);
 	usbvision->dev = NULL;	// USB device is no more
 
+	wake_up_interruptible(&usbvision->wait_frame);
+	wake_up_interruptible(&usbvision->wait_stream);
+
 	up(&usbvision->lock);
 
 	if (usbvision->user) {
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 466e11f..48afcd2 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * I2C_ALGO_USB.C
  *  i2c algorithm for USB-I2C Bridges
  *
@@ -39,7 +39,7 @@
 #include <linux/i2c.h>
 #include "usbvision-i2c.h"
 
-static int debug_i2c_usb = 0;	
+static int debug_i2c_usb = 0;
 
 #if defined(module_param)                               // Showing parameters under SYSFS
 module_param (debug_i2c_usb, int, 0444);			// debug_i2c_usb mode of the device driver
@@ -108,7 +108,7 @@
 				   unsigned char *add)
 {
 	unsigned short flags = msg->flags;
-	
+
 	unsigned char addr;
 	int ret;
 	if ((flags & I2C_M_TEN)) {
@@ -205,8 +205,6 @@
 static struct i2c_algorithm i2c_usb_algo = {
 	.master_xfer   = usb_xfer,
 	.smbus_xfer    = NULL,
-	.slave_send    = NULL,
-	.slave_recv    = NULL,
 	.algo_control  = algo_control,
 	.functionality = usb_func,
 };
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index 813b258..870c0cc 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * USBVISION.H
  *  usbvision header file
  *
@@ -38,7 +38,7 @@
 	#define USBVISION_SSPND_EN		(1 << 1)
 	#define USBVISION_RES2			(1 << 2)
 	#define USBVISION_PWR_VID		(1 << 5)
-        #define USBVISION_E2_EN			(1 << 7)
+	#define USBVISION_E2_EN			(1 << 7)
 #define USBVISION_CONFIG_REG		0x01
 #define USBVISION_ADRS_REG		0x02
 #define USBVISION_ALTER_REG		0x03
@@ -139,7 +139,7 @@
 #define USBVISION_MAX_ISOC_PACKET_SIZE 	959			// NT1003 Specs Document says 1023
 
 #define USBVISION_NUM_HEADERMARKER	20
-#define USBVISION_NUMFRAMES		2
+#define USBVISION_NUMFRAMES		3
 #define USBVISION_NUMSBUF		2
 
 #define USBVISION_POWEROFF_TIME		3 * (HZ)		// 3 seconds
@@ -225,6 +225,13 @@
 	FrameState_Error,	/* Something bad happened while processing */
 };
 
+/* stream states */
+enum StreamState {
+	Stream_Off,
+	Stream_Interrupt,
+	Stream_On,
+};
+
 enum IsocState {
 	IsocState_InFrame,	/* Isoc packet is member of frame */
 	IsocState_NoFrame,	/* Isoc packet is not member of any frame */
@@ -272,27 +279,36 @@
 	__u16 frameHeight;				/* 10 - 11 after endian correction*/
 };
 
+/* tvnorms */
+struct usbvision_tvnorm {
+	char *name;
+	v4l2_std_id id;
+	/* mode for saa7113h */
+	int mode;
+};
+
 struct usbvision_frame {
 	char *data;					/* Frame buffer */
 	struct usbvision_frame_header isocHeader;	/* Header from stream */
 
 	int width;					/* Width application is expecting */
 	int height;					/* Height */
-
+	int index;					/* Frame index */
 	int frmwidth;					/* Width the frame actually is */
 	int frmheight;					/* Height */
 
 	volatile int grabstate;				/* State of grabbing */
 	int scanstate;					/* State of scanning */
 
+	struct list_head frame;
+
 	int curline;					/* Line of frame we're working on */
 
 	long scanlength;				/* uncompressed, raw data length of frame */
 	long bytes_read;				/* amount of scanlength that has been read from data */
 	struct usbvision_v4l2_format_st v4l2_format;	/* format the user needs*/
 	int v4l2_linesize;				/* bytes for one videoline*/
-        struct timeval timestamp;
-	wait_queue_head_t wq;				/* Processes waiting */
+	struct timeval timestamp;
 	int sequence;					// How many video frames we send to user
 };
 
@@ -305,23 +321,23 @@
 #define USBVISION_I2C_CLIENTS_MAX		8
 
 struct usbvision_device_data_st {
-        int idVendor;
-        int idProduct;
-        int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
-        int Codec;
-        int VideoChannels;
-        __u64 VideoNorm;
-        int AudioChannels;
-        int Radio;
-        int vbi;
-        int Tuner;
-        int TunerType;
-        int Vin_Reg1;
-        int Vin_Reg2;
-        int X_Offset;
-        int Y_Offset;
-        int Dvi_yuv;
-        char *ModelString;
+	int idVendor;
+	int idProduct;
+	int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
+	int Codec;
+	int VideoChannels;
+	__u64 VideoNorm;
+	int AudioChannels;
+	int Radio;
+	int vbi;
+	int Tuner;
+	int TunerType;
+	int Vin_Reg1;
+	int Vin_Reg2;
+	int X_Offset;
+	int Y_Offset;
+	int Dvi_yuv;
+	char *ModelString;
 };
 
 /* Declared on usbvision-cards.c */
@@ -332,7 +348,7 @@
 	struct video_device *vdev;         				/* Video Device */
 	struct video_device *rdev;               			/* Radio Device */
 	struct video_device *vbi; 					/* VBI Device   */
-	struct video_audio audio_dev;	        			/* Current audio params */
+	struct video_audio audio_dev;					/* Current audio params */
 
 	/* i2c Declaration Section*/
 	struct i2c_adapter i2c_adap;
@@ -373,7 +389,7 @@
 	int usbvision_used;						/* Is this structure in use? */
 	int initialized;						/* Had we already sent init sequence? */
 	int DevModel;							/* What type of USBVISION device we got? */
-	int streaming;							/* Are we streaming Isochronous? */
+	enum StreamState streaming;					/* Are we streaming Isochronous? */
 	int last_error;							/* What calamity struck us? */
 	int curwidth;							/* width of the frame the device is currently set to*/
 	int curheight;      						/* height of the frame the device is currently set to*/
@@ -382,7 +398,10 @@
 	char *fbuf;							/* Videodev buffer area for mmap*/
 	int max_frame_size;						/* Bytes in one video frame */
 	int fbuf_size;							/* Videodev buffer size */
-	int curFrameNum;						// number of current frame in frame buffer mode
+	spinlock_t queue_lock;						/* spinlock for protecting mods on inqueue and outqueue */
+	struct list_head inqueue, outqueue;                             /* queued frame list and ready to dequeue frame list */
+	wait_queue_head_t wait_frame;					/* Processes waiting */
+	wait_queue_head_t wait_stream;					/* Processes waiting */
 	struct usbvision_frame *curFrame;				// pointer to current frame, set by usbvision_find_header
 	struct usbvision_frame frame[USBVISION_NUMFRAMES];		// frame buffer
 	int curSbufNum;							// number of current receiving sbuf
@@ -397,20 +416,21 @@
 	int scratch_headermarker_read_ptr;
 	int scratch_headermarker_write_ptr;
 	int isocstate;
-        /* color controls */
+	/* color controls */
 	int saturation;
 	int hue;
 	int brightness;
-        int contrast;
+	int contrast;
 	int depth;
 	struct usbvision_v4l2_format_st palette;
 
 	struct v4l2_capability vcap;					/* Video capabilities */
-	struct v4l2_input input;					/* May be used for tuner support */
+	unsigned int ctl_input;						/* selected input */
+	struct usbvision_tvnorm *tvnorm;				/* selected tv norm */
 	unsigned char video_endp;					/* 0x82 for USBVISION devices based */
 
 	// Overlay stuff:
-        struct v4l2_framebuffer vid_buf;
+	struct v4l2_framebuffer vid_buf;
 	struct v4l2_format vid_win;
 	int vid_buf_valid;						// Status: video buffer is valid (set)
 	int vid_win_valid;						// Status: video window is valid (set)
@@ -435,8 +455,8 @@
 	struct proc_dir_entry *proc_devdir;		/* Per-device proc directory */
 	struct proc_dir_entry *proc_info;		/* <minor#>/info entry */
 	struct proc_dir_entry *proc_register;		/* <minor#>/register entry */
-	struct proc_dir_entry *proc_freq; 		/* <minor#>/freq entry */ 
-	struct proc_dir_entry *proc_input; 		/* <minor#>/input entry */ 
+	struct proc_dir_entry *proc_freq; 		/* <minor#>/freq entry */
+	struct proc_dir_entry *proc_input; 		/* <minor#>/input entry */
 	struct proc_dir_entry *proc_frame;		/* <minor#>/frame entry */
 	struct proc_dir_entry *proc_button;		/* <minor#>/button entry */
 	struct proc_dir_entry *proc_control;		/* <minor#>/control entry */
@@ -463,3 +483,10 @@
 
 #endif									/* __LINUX_USBVISION_H */
 
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */