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(), &timestamp);
        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

Reply via email to