diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-11-10 23:13:49 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:02:07 -0500 |
commit | 9e31ced888d1ca49ec5be51ef295e3ce994366c4 (patch) | |
tree | 23593504461672ce1f6ef405171b859c42404019 /drivers/media/video/em28xx | |
parent | a225452ef80a7bd894fd2dfd01a4973d444152f4 (diff) |
V4L/DVB (6584): Fix read() method
Backport read() fixes from Markus Rechberger.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 30 | ||||
-rw-r--r-- | 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 f0191779a8e2..8a4d221a4fe4 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, | |||
416 | struct em28xx_fh *fh = filp->private_data; | 416 | struct em28xx_fh *fh = filp->private_data; |
417 | struct em28xx *dev = fh->dev; | 417 | struct em28xx *dev = fh->dev; |
418 | 418 | ||
419 | /* FIXME: read() is not prepared to allow changing the video | ||
420 | resolution while streaming. Seems a bug at em28xx_set_fmt | ||
421 | */ | ||
419 | 422 | ||
420 | if (unlikely(res_get(fh) < 0)) | 423 | if (unlikely(res_get(fh) < 0)) |
421 | return -EBUSY; | 424 | return -EBUSY; |
@@ -498,25 +501,36 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, | |||
498 | mutex_unlock(&dev->lock); | 501 | mutex_unlock(&dev->lock); |
499 | return -ENODEV; | 502 | return -ENODEV; |
500 | } | 503 | } |
504 | dev->video_bytesread = 0; | ||
501 | } | 505 | } |
502 | 506 | ||
503 | f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame); | 507 | f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame); |
504 | 508 | ||
505 | spin_lock_irqsave(&dev->queue_lock, lock_flags); | ||
506 | list_for_each_entry(i, &dev->outqueue, frame) | ||
507 | i->state = F_UNUSED; | ||
508 | INIT_LIST_HEAD(&dev->outqueue); | ||
509 | spin_unlock_irqrestore(&dev->queue_lock, lock_flags); | ||
510 | |||
511 | em28xx_queue_unusedframes(dev); | 509 | em28xx_queue_unusedframes(dev); |
512 | 510 | ||
513 | if (count > f->buf.length) | 511 | if (count > f->buf.length) |
514 | count = f->buf.length; | 512 | count = f->buf.length; |
515 | 513 | ||
516 | if (copy_to_user(buf, f->bufmem, count)) { | 514 | if ((dev->video_bytesread + count) > dev->frame_size) |
517 | mutex_unlock(&dev->lock); | 515 | count = dev->frame_size - dev->video_bytesread; |
516 | |||
517 | if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) { | ||
518 | em28xx_err("Error while copying to user\n"); | ||
518 | return -EFAULT; | 519 | return -EFAULT; |
519 | } | 520 | } |
521 | dev->video_bytesread += count; | ||
522 | |||
523 | if (dev->video_bytesread == dev->frame_size) { | ||
524 | spin_lock_irqsave(&dev->queue_lock, lock_flags); | ||
525 | list_for_each_entry(i, &dev->outqueue, frame) | ||
526 | i->state = F_UNUSED; | ||
527 | INIT_LIST_HEAD(&dev->outqueue); | ||
528 | spin_unlock_irqrestore(&dev->queue_lock, lock_flags); | ||
529 | |||
530 | em28xx_queue_unusedframes(dev); | ||
531 | dev->video_bytesread = 0; | ||
532 | } | ||
533 | |||
520 | *f_pos += count; | 534 | *f_pos += count; |
521 | 535 | ||
522 | mutex_unlock(&dev->lock); | 536 | mutex_unlock(&dev->lock); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 3efc05d2df67..672880383de8 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -260,6 +260,7 @@ struct em28xx { | |||
260 | int vscale; /* vertical scale factor (see datasheet) */ | 260 | int vscale; /* vertical scale factor (see datasheet) */ |
261 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ | 261 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ |
262 | int type; | 262 | int type; |
263 | unsigned int video_bytesread; /* Number of bytes read */ | ||
263 | 264 | ||
264 | unsigned long hash; /* eeprom hash - for boards with generic ID */ | 265 | unsigned long hash; /* eeprom hash - for boards with generic ID */ |
265 | unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */ | 266 | unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */ |
@@ -268,6 +269,7 @@ struct em28xx { | |||
268 | enum em28xx_dev_state state; | 269 | enum em28xx_dev_state state; |
269 | enum em28xx_stream_state stream; | 270 | enum em28xx_stream_state stream; |
270 | enum em28xx_io_method io; | 271 | enum em28xx_io_method io; |
272 | |||
271 | /* locks */ | 273 | /* locks */ |
272 | struct mutex lock; | 274 | struct mutex lock; |
273 | spinlock_t queue_lock; | 275 | spinlock_t queue_lock; |