Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e31ced8 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

V4L/DVB (6584): Fix read() method



Backport read() fixes from Markus Rechberger.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent a225452e
Loading
Loading
Loading
Loading
+22 −8
Original line number Diff line number Diff line
@@ -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,10 +501,26 @@ 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);

	em28xx_queue_unusedframes(dev);

	if (count > f->buf.length)
		count = f->buf.length;

	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;
@@ -509,14 +528,9 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
		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);
		return -EFAULT;
		dev->video_bytesread = 0;
	}

	*f_pos += count;

	mutex_unlock(&dev->lock);
+2 −0
Original line number Diff line number Diff line
@@ -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;