summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.c13
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.h5
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.c54
3 files changed, 50 insertions, 22 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c
index 1e9d07b8f..7f3421778 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c
@@ -121,7 +121,11 @@ int dvb_generic_open(struct inode *inode, struct file *file)
if (!dvbdev->users)
return -EBUSY;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ if (!dvbdev->readers)
+ return -EBUSY;
+ dvbdev->readers--;
+ } else {
if (!dvbdev->writers)
return -EBUSY;
dvbdev->writers--;
@@ -139,9 +143,12 @@ int dvb_generic_release(struct inode *inode, struct file *file)
if (!dvbdev)
return -ENODEV;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ dvbdev->readers++;
+ } else {
dvbdev->writers++;
-
+ }
+
dvbdev->users++;
return 0;
}
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h
index 2c14d0e1f..14a872011 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h
@@ -66,8 +66,11 @@ struct dvb_device {
int type;
u32 id;
- int users;
+ /* in theory, 'users' can vanish now,
+ but I don't want to change too much now... */
+ int readers;
int writers;
+ int users;
/* don't really need those !? -- FIXME: use video_usercopy */
int (*kernel_ioctl)(struct inode *inode, struct file *file,
diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c
index 521b7f3de..b97616626 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.c
+++ b/linux/drivers/media/dvb/ttpci/av7110.c
@@ -3646,18 +3646,23 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
DEB_EE(("av7110: %p\n",av7110));
- poll_wait(file, &av7110->avout.queue, wait);
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ poll_wait(file, &av7110->avout.queue, wait);
+ }
+
poll_wait(file, &av7110->video_events.wait_queue, wait);
if (av7110->video_events.eventw != av7110->video_events.eventr)
mask = POLLPRI;
- if (av7110->playing) {
- if (FREE_COND)
- mask |= (POLLOUT | POLLWRNORM);
- } else /* if not playing: may play if asked for */
- mask |= (POLLOUT | POLLWRNORM);
-
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if (av7110->playing) {
+ if (FREE_COND)
+ mask |= (POLLOUT | POLLWRNORM);
+ } else /* if not playing: may play if asked for */
+ mask |= (POLLOUT | POLLWRNORM);
+ }
+
return mask;
}
@@ -3669,6 +3674,10 @@ static ssize_t dvb_video_write(struct file *file, const char *buf,
DEB_EE(("av7110: %p\n",av7110));
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ return -EPERM;
+ }
+
if (av7110->videostate.stream_source!=VIDEO_SOURCE_MEMORY)
return -EPERM;
@@ -3727,9 +3736,12 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
DEB_EE(("av7110: %p\n",av7110));
- if (((file->f_flags&O_ACCMODE)==O_RDONLY) &&
- (cmd!=VIDEO_GET_STATUS))
- return -EPERM;
+ if ((file->f_flags&O_ACCMODE)==O_RDONLY) {
+ if ( cmd!=VIDEO_GET_STATUS && cmd!=VIDEO_GET_EVENT &&
+ cmd!=VIDEO_GET_SIZE ) {
+ return -EPERM;
+ }
+ }
switch (cmd) {
case VIDEO_STOP:
@@ -4043,15 +4055,17 @@ static int dvb_video_open(struct inode *inode, struct file *file)
if ((err=dvb_generic_open(inode, file))<0)
return err;
- dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
- dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
- av7110->video_blank=1;
- av7110->audiostate.AV_sync_state=1;
- av7110->videostate.stream_source=VIDEO_SOURCE_DEMUX;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ av7110->video_blank=1;
+ av7110->audiostate.AV_sync_state=1;
+ av7110->videostate.stream_source=VIDEO_SOURCE_DEMUX;
+
/* empty event queue */
av7110->video_events.eventr = av7110->video_events.eventw = 0;
+ }
return 0;
}
@@ -4063,7 +4077,10 @@ static int dvb_video_release(struct inode *inode, struct file *file)
DEB_EE(("av7110: %p\n",av7110));
- AV_Stop(av7110, RP_VIDEO);
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ AV_Stop(av7110, RP_VIDEO);
+ }
+
return dvb_generic_release(inode, file);
}
@@ -4110,7 +4127,8 @@ static struct file_operations dvb_video_fops = {
static struct dvb_device dvbdev_video = {
.priv = 0,
- .users = 1,
+ .users = 6,
+ .readers = 5, /* arbitrary */
.writers = 1,
.fops = &dvb_video_fops,
.kernel_ioctl = dvb_video_ioctl,