|
@@ -132,6 +132,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
|
+ if (dmxdev->exit) {
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
|
|
|
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
@@ -171,6 +176,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
|
|
dmxdev->demux->disconnect_frontend(dmxdev->demux);
|
|
|
dmxdev->demux->connect_frontend(dmxdev->demux, front);
|
|
|
}
|
|
|
+ dvbdev->users++;
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
return 0;
|
|
|
}
|
|
@@ -198,7 +204,16 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
|
|
vfree(mem);
|
|
|
}
|
|
|
}
|
|
|
- mutex_unlock(&dmxdev->mutex);
|
|
|
+ /* TODO */
|
|
|
+ dvbdev->users--;
|
|
|
+ if(dvbdev->users==-1 && dmxdev->exit==1) {
|
|
|
+ fops_put(file->f_op);
|
|
|
+ file->f_op = NULL;
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+ wake_up(&dvbdev->wait_queue);
|
|
|
+ } else
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -215,6 +230,11 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
|
|
|
return -EINVAL;
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
|
|
return -ERESTARTSYS;
|
|
|
+
|
|
|
+ if (dmxdev->exit) {
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
ret = dmxdev->demux->write(dmxdev->demux, buf, count);
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
return ret;
|
|
@@ -227,6 +247,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
|
|
int ret;
|
|
|
|
|
|
+ if (dmxdev->exit) {
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
//mutex_lock(&dmxdev->mutex);
|
|
|
ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
|
|
|
file->f_flags & O_NONBLOCK,
|
|
@@ -665,6 +690,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
|
|
|
dmxdevfilter->feed.ts = NULL;
|
|
|
init_timer(&dmxdevfilter->timer);
|
|
|
|
|
|
+ dvbdev->users++;
|
|
|
+
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
return 0;
|
|
|
}
|
|
@@ -943,7 +970,21 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
|
|
|
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
|
|
struct dmxdev *dmxdev = dmxdevfilter->dev;
|
|
|
|
|
|
- return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
|
|
|
+
|
|
|
+ mutex_lock(&dmxdev->mutex);
|
|
|
+ dmxdev->dvbdev->users--;
|
|
|
+ if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
|
|
|
+ fops_put(file->f_op);
|
|
|
+ file->f_op = NULL;
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+ wake_up(&dmxdev->dvbdev->wait_queue);
|
|
|
+ } else
|
|
|
+ mutex_unlock(&dmxdev->mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static struct file_operations dvb_demux_fops = {
|
|
@@ -1027,6 +1068,7 @@ static struct file_operations dvb_dvr_fops = {
|
|
|
static struct dvb_device dvbdev_dvr = {
|
|
|
.priv = NULL,
|
|
|
.readers = 1,
|
|
|
+ .users = 1,
|
|
|
.fops = &dvb_dvr_fops
|
|
|
};
|
|
|
|
|
@@ -1064,6 +1106,16 @@ EXPORT_SYMBOL(dvb_dmxdev_init);
|
|
|
|
|
|
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
|
|
{
|
|
|
+ dmxdev->exit=1;
|
|
|
+ if (dmxdev->dvbdev->users > 1) {
|
|
|
+ wait_event(dmxdev->dvbdev->wait_queue,
|
|
|
+ dmxdev->dvbdev->users==1);
|
|
|
+ }
|
|
|
+ if (dmxdev->dvr_dvbdev->users > 1) {
|
|
|
+ wait_event(dmxdev->dvr_dvbdev->wait_queue,
|
|
|
+ dmxdev->dvr_dvbdev->users==1);
|
|
|
+ }
|
|
|
+
|
|
|
dvb_unregister_device(dmxdev->dvbdev);
|
|
|
dvb_unregister_device(dmxdev->dvr_dvbdev);
|
|
|
|