The patch number 8181 was added via Jean-Francois Moine <[EMAIL PROTECTED]>
to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel
If anyone has any objections, please let us know by sending a message to:
[EMAIL PROTECTED]
------
From: Jean-Francois Moine <[EMAIL PROTECTED]>
gspca: read() did not work (loop in kernel, timeout...)
main: Remove some vidioc_xx traces.
main: read() did not work (user irq instead of mmap irq).
main: Lack of v4l1 compat.
main: Process loop inside kernel when no frame arriving.
main: Double qbuf in read() when too many buffered frames.
Signed-off-by: Jean-Francois Moine <[EMAIL PROTECTED]>
---
linux/drivers/media/video/gspca/gspca.c | 73 +++++++++---------------
1 file changed, 29 insertions(+), 44 deletions(-)
diff -r 0a2b95002028 -r 2bbb47f61a95 linux/drivers/media/video/gspca/gspca.c
--- a/linux/drivers/media/video/gspca/gspca.c Tue Jul 01 12:03:42 2008 +0200
+++ b/linux/drivers/media/video/gspca/gspca.c Wed Jul 02 11:14:56 2008 +0200
@@ -35,8 +35,6 @@
#include "gspca.h"
-#undef CONFIG_VIDEO_V4L1_COMPAT
-
/* global values */
#define DEF_NURBS 2 /* default number of URBs (mmap) */
#define USR_NURBS 5 /* default number of URBs (userptr) */
@@ -45,8 +43,8 @@ MODULE_DESCRIPTION("GSPCA USB Camera Dri
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 1)
-static const char version[] = "2.1.1";
+#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 2)
+static const char version[] = "2.1.2";
static int video_nr = -1;
@@ -287,10 +285,16 @@ struct gspca_frame *gspca_frame_add(stru
frame->v4l2_buf.length);
packet_type = DISCARD_PACKET;
} else {
- if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR)
+ if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) {
memcpy(frame->data_end, data, len);
- else
- copy_to_user(frame->data_end, data, len);
+ } else {
+ if (copy_to_user(frame->data_end,
+ data, len) != 0) {
+ PDEBUG(D_ERR|D_PACK,
+ "copy to user failed");
+ packet_type = DISCARD_PACKET;
+ }
+ }
frame->data_end += len;
}
}
@@ -571,9 +575,8 @@ static int create_urbs(struct gspca_dev
bsize = psize * npkt;
PDEBUG(D_STREAM,
"isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
-/*fixme:change for userptr*/
/*fixme:don't submit all URBs when userptr*/
- if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
+ if (gspca_dev->memory != V4L2_MEMORY_USERPTR) {
usb_complete = isoc_irq_mmap;
nurbs = DEF_NURBS;
} else {
@@ -752,8 +755,6 @@ static int vidioc_enum_fmt_vid_cap(struc
int i, j, index;
__u32 fmt_tb[8];
- PDEBUG(D_CONF, "enum fmt cap");
-
/* give an index to each format */
index = 0;
j = 0;
@@ -798,14 +799,6 @@ static int vidioc_g_fmt_vid_cap(struct f
fmt->fmt.pix.width = gspca_dev->width;
fmt->fmt.pix.height = gspca_dev->height;
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
-#ifdef VIDEO_ADV_DEBUG
- if (gspca_debug & D_CONF) {
- PDEBUG_MODE("get fmt cap",
- fmt->fmt.pix.pixelformat,
- fmt->fmt.pix.width,
- fmt->fmt.pix.height);
- }
-#endif
fmt->fmt.pix.field = V4L2_FIELD_NONE;
fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
* fmt->fmt.pix.width / 8;
@@ -898,13 +891,6 @@ static int vidioc_s_fmt_vid_cap(struct f
fmt->fmt.pix.height = gspca_dev->height;
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
return 0;
- }
-#endif
-#ifdef VIDEO_ADV_DEBUG
- if (gspca_debug & D_CONF) {
- PDEBUG_MODE("set fmt cap",
- fmt->fmt.pix.pixelformat,
- fmt->fmt.pix.width, fmt->fmt.pix.height);
}
#endif
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
@@ -1019,7 +1005,6 @@ static int vidioc_querycap(struct file *
{
struct gspca_dev *gspca_dev = priv;
- PDEBUG(D_CONF, "querycap");
memset(cap, 0, sizeof *cap);
strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
@@ -1077,7 +1062,6 @@ static int vidioc_s_ctrl(struct file *fi
struct ctrl *ctrls;
int i, ret;
- PDEBUG(D_CONF, "set ctrl");
for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
i < gspca_dev->sd_desc->nctrls;
i++, ctrls++) {
@@ -1161,7 +1145,6 @@ static int vidioc_reqbufs(struct file *f
struct gspca_dev *gspca_dev = priv;
int i, ret = 0;
- PDEBUG(D_STREAM, "reqbufs %d", rb->count);
if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
switch (rb->memory) {
@@ -1211,7 +1194,6 @@ static int vidioc_querybuf(struct file *
struct gspca_dev *gspca_dev = priv;
struct gspca_frame *frame;
- PDEBUG(D_STREAM, "querybuf");
if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
|| v4l2_buf->index < 0
|| v4l2_buf->index >= gspca_dev->nframes)
@@ -1228,7 +1210,6 @@ static int vidioc_streamon(struct file *
struct gspca_dev *gspca_dev = priv;
int ret;
- PDEBUG(D_STREAM, "stream on");
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
@@ -1270,7 +1251,6 @@ static int vidioc_streamoff(struct file
struct gspca_dev *gspca_dev = priv;
int ret;
- PDEBUG(D_STREAM, "stream off");
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (!gspca_dev->streaming)
@@ -1505,8 +1485,10 @@ static int frame_wait(struct gspca_dev *
i = gspca_dev->fr_o;
j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j];
- if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
+ if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
+ atomic_dec(&gspca_dev->nevent);
goto ok;
+ }
if (nonblock_ing) /* no frame yet */
return -EAGAIN;
@@ -1517,9 +1499,10 @@ static int frame_wait(struct gspca_dev *
msecs_to_jiffies(3000));
if (ret <= 0) {
if (ret < 0)
- return ret;
- return -EIO;
- }
+ return ret; /* interrupt */
+ return -EIO; /* timeout */
+ }
+ atomic_dec(&gspca_dev->nevent);
if (!gspca_dev->streaming || !gspca_dev->present)
return -EIO;
if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
@@ -1531,7 +1514,6 @@ static int frame_wait(struct gspca_dev *
break;
}
ok:
- atomic_dec(&gspca_dev->nevent);
gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
gspca_dev->fr_q,
@@ -1731,7 +1713,7 @@ static unsigned int dev_poll(struct file
goto out;
}
- /* if not mmap, treat the awaiting URBs */
+ /* if userptr, treat the awaiting URBs */
if (gspca_dev->memory == V4L2_MEMORY_USERPTR
&& gspca_dev->capt_file == file)
isoc_transfer(gspca_dev);
@@ -1754,7 +1736,7 @@ static ssize_t dev_read(struct file *fil
struct gspca_frame *frame;
struct v4l2_buffer v4l2_buf;
struct timeval timestamp;
- int i, ret, ret2;
+ int n, ret, ret2;
PDEBUG(D_FRAM, "read (%d)", count);
if (!gspca_dev->present)
@@ -1766,9 +1748,9 @@ static ssize_t dev_read(struct file *fil
return ret;
break;
case GSPCA_MEMORY_READ:
- if (gspca_dev->capt_file != file)
- return -EINVAL;
- break;
+ if (gspca_dev->capt_file == file)
+ break;
+ /* fall thru */
default:
return -EINVAL;
}
@@ -1776,7 +1758,8 @@ static ssize_t dev_read(struct file *fil
/* get a frame */
jiffies_to_timeval(get_jiffies_64(), ×tamp);
timestamp.tv_sec--;
- for (i = 0; i < 2; i++) {
+ n = 2;
+ for (;;) {
memset(&v4l2_buf, 0, sizeof v4l2_buf);
v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_buf.memory = V4L2_MEMORY_MMAP;
@@ -1787,8 +1770,10 @@ static ssize_t dev_read(struct file *fil
}
/* if the process slept for more than 1 second,
- * get a brand new frame */
+ * get anewer frame */
frame = &gspca_dev->frame[v4l2_buf.index];
+ if (--n < 0)
+ break; /* avoid infinite loop */
if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
break;
ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
---
Patch is available at:
http://linuxtv.org/hg/v4l-dvb/rev/2bbb47f61a950ef6ba7a613fc6c4e5cd7eb81ce9
_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits