Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9e31ced888d1ca49ec5be51ef295e3ce994366c4
Commit:     9e31ced888d1ca49ec5be51ef295e3ce994366c4
Parent:     a225452ef80a7bd894fd2dfd01a4973d444152f4
Author:     Mauro Carvalho Chehab <[EMAIL PROTECTED]>
AuthorDate: Sun Nov 11 01:13:49 2007 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Fri Jan 25 19:02:07 2008 -0200

    V4L/DVB (6584): Fix read() method
    
    Backport read() fixes from Markus Rechberger.
    
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/video/em28xx/em28xx-video.c |   30 +++++++++++++++++++++-------
 drivers/media/video/em28xx/em28xx.h       |    2 +
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/media/video/em28xx/em28xx-video.c 
b/drivers/media/video/em28xx/em28xx-video.c
index f019177..8a4d221 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -416,6 +416,9 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, 
size_t count,
        struct em28xx_fh *fh = filp->private_data;
        struct em28xx *dev = fh->dev;
 
+       /* FIXME: read() is not prepared to allow changing the video
+          resolution while streaming. Seems a bug at em28xx_set_fmt
+        */
 
        if (unlikely(res_get(fh) < 0))
                return -EBUSY;
@@ -498,25 +501,36 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, 
size_t count,
                        mutex_unlock(&dev->lock);
                        return -ENODEV;
                }
+               dev->video_bytesread = 0;
        }
 
        f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
 
-       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-       list_for_each_entry(i, &dev->outqueue, frame)
-           i->state = F_UNUSED;
-       INIT_LIST_HEAD(&dev->outqueue);
-       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
        em28xx_queue_unusedframes(dev);
 
        if (count > f->buf.length)
                count = f->buf.length;
 
-       if (copy_to_user(buf, f->bufmem, count)) {
-               mutex_unlock(&dev->lock);
+       if ((dev->video_bytesread + count) > dev->frame_size)
+               count = dev->frame_size - dev->video_bytesread;
+
+       if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
+               em28xx_err("Error while copying to user\n");
                return -EFAULT;
        }
+       dev->video_bytesread += count;
+
+       if (dev->video_bytesread == dev->frame_size) {
+               spin_lock_irqsave(&dev->queue_lock, lock_flags);
+               list_for_each_entry(i, &dev->outqueue, frame)
+                                   i->state = F_UNUSED;
+               INIT_LIST_HEAD(&dev->outqueue);
+               spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+
+               em28xx_queue_unusedframes(dev);
+               dev->video_bytesread = 0;
+       }
+
        *f_pos += count;
 
        mutex_unlock(&dev->lock);
diff --git a/drivers/media/video/em28xx/em28xx.h 
b/drivers/media/video/em28xx/em28xx.h
index 3efc05d..6728803 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -260,6 +260,7 @@ struct em28xx {
        int vscale;             /* vertical scale factor (see datasheet) */
        int interlaced;         /* 1=interlace fileds, 0=just top fileds */
        int type;
+       unsigned int video_bytesread;   /* Number of bytes read */
 
        unsigned long hash;     /* eeprom hash - for boards with generic ID */
        unsigned long i2c_hash; /* i2c devicelist hash - for boards with 
generic ID */
@@ -268,6 +269,7 @@ struct em28xx {
        enum em28xx_dev_state state;
        enum em28xx_stream_state stream;
        enum em28xx_io_method io;
+
        /* locks */
        struct mutex lock;
        spinlock_t queue_lock;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to