dmxdev.c 27.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * dmxdev.c - DVB demultiplexer device
 *
4 5
 * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
 *		      for convergence integrated media GmbH
L
Linus Torvalds 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/ioctl.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include "dmxdev.h"

static int debug;

module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");

#define dprintk	if (debug) printk

41 42
static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
				   const u8 *src, size_t len)
L
Linus Torvalds 已提交
43
{
44
	ssize_t free;
L
Linus Torvalds 已提交
45 46 47 48 49 50

	if (!len)
		return 0;
	if (!buf->data)
		return 0;

51 52
	free = dvb_ringbuffer_free(buf);
	if (len > free) {
L
Linus Torvalds 已提交
53
		dprintk("dmxdev: buffer overflow\n");
54
		return -EOVERFLOW;
L
Linus Torvalds 已提交
55
	}
56 57

	return dvb_ringbuffer_write(buf, src, len);
L
Linus Torvalds 已提交
58 59
}

60
static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
61 62
				      int non_blocking, char __user *buf,
				      size_t count, loff_t *ppos)
L
Linus Torvalds 已提交
63
{
64 65 66
	size_t todo;
	ssize_t avail;
	ssize_t ret = 0;
L
Linus Torvalds 已提交
67 68 69 70

	if (!src->data)
		return 0;

71 72 73 74
	if (src->error) {
		ret = src->error;
		dvb_ringbuffer_flush(src);
		return ret;
L
Linus Torvalds 已提交
75 76
	}

77 78 79 80 81
	for (todo = count; todo > 0; todo -= ret) {
		if (non_blocking && dvb_ringbuffer_empty(src)) {
			ret = -EWOULDBLOCK;
			break;
		}
L
Linus Torvalds 已提交
82

83 84 85 86 87
		ret = wait_event_interruptible(src->queue,
					       !dvb_ringbuffer_empty(src) ||
					       (src->error != 0));
		if (ret < 0)
			break;
L
Linus Torvalds 已提交
88

89 90 91 92
		if (src->error) {
			ret = src->error;
			dvb_ringbuffer_flush(src);
			break;
L
Linus Torvalds 已提交
93 94
		}

95
		avail = dvb_ringbuffer_avail(src);
96 97
		if (avail > todo)
			avail = todo;
98

99
		ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
100 101 102 103
		if (ret < 0)
			break;

		buf += ret;
L
Linus Torvalds 已提交
104
	}
105 106

	return (count - todo) ? (count - todo) : ret;
L
Linus Torvalds 已提交
107 108
}

109
static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type)
L
Linus Torvalds 已提交
110 111 112
{
	struct list_head *head, *pos;

113
	head = demux->get_frontends(demux);
L
Linus Torvalds 已提交
114 115 116
	if (!head)
		return NULL;
	list_for_each(pos, head)
117
		if (DMX_FE_ENTRY(pos)->source == type)
L
Linus Torvalds 已提交
118 119 120 121 122 123 124
			return DMX_FE_ENTRY(pos);

	return NULL;
}

static int dvb_dvr_open(struct inode *inode, struct file *file)
{
125 126
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
127 128
	struct dmx_frontend *front;

129
	dprintk("function : %s\n", __FUNCTION__);
L
Linus Torvalds 已提交
130

131
	if (mutex_lock_interruptible(&dmxdev->mutex))
L
Linus Torvalds 已提交
132 133
		return -ERESTARTSYS;

134 135 136 137 138
	if (dmxdev->exit) {
		mutex_unlock(&dmxdev->mutex);
		return -ENODEV;
	}

139 140
	if ((file->f_flags & O_ACCMODE) == O_RDWR) {
		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
141
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
142 143 144 145
			return -EOPNOTSUPP;
		}
	}

146
	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
147 148 149 150 151 152
		void *mem;
		if (!dvbdev->readers) {
			mutex_unlock(&dmxdev->mutex);
			return -EBUSY;
		}
		mem = vmalloc(DVR_BUFFER_SIZE);
153
		if (!mem) {
154 155 156
			mutex_unlock(&dmxdev->mutex);
			return -ENOMEM;
		}
157
		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
158
		dvbdev->readers--;
L
Linus Torvalds 已提交
159 160
	}

161 162
	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
		dmxdev->dvr_orig_fe = dmxdev->demux->frontend;
L
Linus Torvalds 已提交
163 164

		if (!dmxdev->demux->write) {
165
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
166 167 168
			return -EOPNOTSUPP;
		}

169
		front = get_fe(dmxdev->demux, DMX_MEMORY_FE);
L
Linus Torvalds 已提交
170 171

		if (!front) {
172
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
173 174 175 176 177
			return -EINVAL;
		}
		dmxdev->demux->disconnect_frontend(dmxdev->demux);
		dmxdev->demux->connect_frontend(dmxdev->demux, front);
	}
178
	dvbdev->users++;
179
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
180 181 182 183 184
	return 0;
}

static int dvb_dvr_release(struct inode *inode, struct file *file)
{
185 186
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
187

188
	mutex_lock(&dmxdev->mutex);
L
Linus Torvalds 已提交
189

190
	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
L
Linus Torvalds 已提交
191 192 193 194
		dmxdev->demux->disconnect_frontend(dmxdev->demux);
		dmxdev->demux->connect_frontend(dmxdev->demux,
						dmxdev->dvr_orig_fe);
	}
195
	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
196
		dvbdev->readers++;
L
Linus Torvalds 已提交
197
		if (dmxdev->dvr_buffer.data) {
198
			void *mem = dmxdev->dvr_buffer.data;
L
Linus Torvalds 已提交
199 200
			mb();
			spin_lock_irq(&dmxdev->lock);
201
			dmxdev->dvr_buffer.data = NULL;
L
Linus Torvalds 已提交
202 203 204 205
			spin_unlock_irq(&dmxdev->lock);
			vfree(mem);
		}
	}
206 207 208 209 210 211 212 213 214 215
	/* 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);

L
Linus Torvalds 已提交
216 217 218 219
	return 0;
}

static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
220
			     size_t count, loff_t *ppos)
L
Linus Torvalds 已提交
221
{
222 223
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
224 225 226 227
	int ret;

	if (!dmxdev->demux->write)
		return -EOPNOTSUPP;
228
	if ((file->f_flags & O_ACCMODE) != O_WRONLY)
L
Linus Torvalds 已提交
229
		return -EINVAL;
230
	if (mutex_lock_interruptible(&dmxdev->mutex))
L
Linus Torvalds 已提交
231
		return -ERESTARTSYS;
232 233 234 235 236

	if (dmxdev->exit) {
		mutex_unlock(&dmxdev->mutex);
		return -ENODEV;
	}
237
	ret = dmxdev->demux->write(dmxdev->demux, buf, count);
238
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
239 240 241 242
	return ret;
}

static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
243
			    loff_t *ppos)
L
Linus Torvalds 已提交
244
{
245 246
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
247 248
	int ret;

249 250 251 252 253
	if (dmxdev->exit) {
		mutex_unlock(&dmxdev->mutex);
		return -ENODEV;
	}

254
	//mutex_lock(&dmxdev->mutex);
255 256 257
	ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
				     file->f_flags & O_NONBLOCK,
				     buf, count, ppos);
258
	//mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
259 260 261
	return ret;
}

262 263
static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
					       *dmxdevfilter, int state)
L
Linus Torvalds 已提交
264 265
{
	spin_lock_irq(&dmxdevfilter->dev->lock);
266
	dmxdevfilter->state = state;
L
Linus Torvalds 已提交
267 268 269
	spin_unlock_irq(&dmxdevfilter->dev->lock);
}

270 271
static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
				      unsigned long size)
L
Linus Torvalds 已提交
272
{
273
	struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
L
Linus Torvalds 已提交
274 275
	void *mem;

276
	if (buf->size == size)
L
Linus Torvalds 已提交
277
		return 0;
278
	if (dmxdevfilter->state >= DMXDEV_STATE_GO)
L
Linus Torvalds 已提交
279 280
		return -EBUSY;
	spin_lock_irq(&dmxdevfilter->dev->lock);
281 282 283
	mem = buf->data;
	buf->data = NULL;
	buf->size = size;
284
	dvb_ringbuffer_flush(buf);
L
Linus Torvalds 已提交
285 286 287 288
	spin_unlock_irq(&dmxdevfilter->dev->lock);
	vfree(mem);

	if (buf->size) {
289
		mem = vmalloc(dmxdevfilter->buffer.size);
L
Linus Torvalds 已提交
290 291 292
		if (!mem)
			return -ENOMEM;
		spin_lock_irq(&dmxdevfilter->dev->lock);
293
		buf->data = mem;
L
Linus Torvalds 已提交
294 295 296 297 298 299 300
		spin_unlock_irq(&dmxdevfilter->dev->lock);
	}
	return 0;
}

static void dvb_dmxdev_filter_timeout(unsigned long data)
{
301
	struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
L
Linus Torvalds 已提交
302

303
	dmxdevfilter->buffer.error = -ETIMEDOUT;
L
Linus Torvalds 已提交
304
	spin_lock_irq(&dmxdevfilter->dev->lock);
305
	dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
L
Linus Torvalds 已提交
306 307 308 309 310 311
	spin_unlock_irq(&dmxdevfilter->dev->lock);
	wake_up(&dmxdevfilter->buffer.queue);
}

static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
{
312
	struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
L
Linus Torvalds 已提交
313 314 315

	del_timer(&dmxdevfilter->timer);
	if (para->timeout) {
316 317 318 319
		dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout;
		dmxdevfilter->timer.data = (unsigned long)dmxdevfilter;
		dmxdevfilter->timer.expires =
		    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
L
Linus Torvalds 已提交
320 321 322 323 324
		add_timer(&dmxdevfilter->timer);
	}
}

static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
325 326 327
				       const u8 *buffer2, size_t buffer2_len,
				       struct dmx_section_filter *filter,
				       enum dmx_success success)
L
Linus Torvalds 已提交
328
{
329
	struct dmxdev_filter *dmxdevfilter = filter->priv;
L
Linus Torvalds 已提交
330 331 332 333 334 335 336
	int ret;

	if (dmxdevfilter->buffer.error) {
		wake_up(&dmxdevfilter->buffer.queue);
		return 0;
	}
	spin_lock(&dmxdevfilter->dev->lock);
337
	if (dmxdevfilter->state != DMXDEV_STATE_GO) {
L
Linus Torvalds 已提交
338 339 340 341 342 343
		spin_unlock(&dmxdevfilter->dev->lock);
		return 0;
	}
	del_timer(&dmxdevfilter->timer);
	dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n",
		buffer1[0], buffer1[1],
344 345 346 347 348 349
		buffer1[2], buffer1[3], buffer1[4], buffer1[5]);
	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
				      buffer1_len);
	if (ret == buffer1_len) {
		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
					      buffer2_len);
L
Linus Torvalds 已提交
350
	}
351
	if (ret < 0) {
352 353
		dvb_ringbuffer_flush(&dmxdevfilter->buffer);
		dmxdevfilter->buffer.error = ret;
L
Linus Torvalds 已提交
354
	}
355 356
	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
		dmxdevfilter->state = DMXDEV_STATE_DONE;
L
Linus Torvalds 已提交
357 358 359 360 361 362
	spin_unlock(&dmxdevfilter->dev->lock);
	wake_up(&dmxdevfilter->buffer.queue);
	return 0;
}

static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
363 364 365
				  const u8 *buffer2, size_t buffer2_len,
				  struct dmx_ts_feed *feed,
				  enum dmx_success success)
L
Linus Torvalds 已提交
366
{
367
	struct dmxdev_filter *dmxdevfilter = feed->priv;
368
	struct dvb_ringbuffer *buffer;
L
Linus Torvalds 已提交
369 370 371
	int ret;

	spin_lock(&dmxdevfilter->dev->lock);
372
	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
L
Linus Torvalds 已提交
373 374 375 376
		spin_unlock(&dmxdevfilter->dev->lock);
		return 0;
	}

377 378
	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP)
		buffer = &dmxdevfilter->buffer;
L
Linus Torvalds 已提交
379
	else
380
		buffer = &dmxdevfilter->dev->dvr_buffer;
L
Linus Torvalds 已提交
381 382 383 384 385
	if (buffer->error) {
		spin_unlock(&dmxdevfilter->dev->lock);
		wake_up(&buffer->queue);
		return 0;
	}
386 387 388 389
	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
	if (ret == buffer1_len)
		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
	if (ret < 0) {
390 391
		dvb_ringbuffer_flush(buffer);
		buffer->error = ret;
L
Linus Torvalds 已提交
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
	}
	spin_unlock(&dmxdevfilter->dev->lock);
	wake_up(&buffer->queue);
	return 0;
}

/* stop feed but only mark the specified filter as stopped (state set) */
static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
{
	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);

	switch (dmxdevfilter->type) {
	case DMXDEV_TYPE_SEC:
		del_timer(&dmxdevfilter->timer);
		dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec);
		break;
	case DMXDEV_TYPE_PES:
		dmxdevfilter->feed.ts->stop_filtering(dmxdevfilter->feed.ts);
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

/* start feed associated with the specified filter */
static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
{
420
	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
L
Linus Torvalds 已提交
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441

	switch (filter->type) {
	case DMXDEV_TYPE_SEC:
		return filter->feed.sec->start_filtering(filter->feed.sec);
	case DMXDEV_TYPE_PES:
		return filter->feed.ts->start_filtering(filter->feed.ts);
	default:
		return -EINVAL;
	}

	return 0;
}

/* restart section feed if it has filters left associated with it,
   otherwise release the feed */
static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
{
	int i;
	struct dmxdev *dmxdev = filter->dev;
	u16 pid = filter->params.sec.pid;

442 443 444 445
	for (i = 0; i < dmxdev->filternum; i++)
		if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
		    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
		    dmxdev->filter[i].params.sec.pid == pid) {
L
Linus Torvalds 已提交
446 447 448 449
			dvb_dmxdev_feed_start(&dmxdev->filter[i]);
			return 0;
		}

450 451
	filter->dev->demux->release_section_feed(dmxdev->demux,
						 filter->feed.sec);
L
Linus Torvalds 已提交
452 453 454 455 456 457

	return 0;
}

static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
{
458
	if (dmxdevfilter->state < DMXDEV_STATE_GO)
L
Linus Torvalds 已提交
459 460 461 462 463 464 465 466 467
		return 0;

	switch (dmxdevfilter->type) {
	case DMXDEV_TYPE_SEC:
		if (!dmxdevfilter->feed.sec)
			break;
		dvb_dmxdev_feed_stop(dmxdevfilter);
		if (dmxdevfilter->filter.sec)
			dmxdevfilter->feed.sec->
468 469
			    release_filter(dmxdevfilter->feed.sec,
					   dmxdevfilter->filter.sec);
L
Linus Torvalds 已提交
470
		dvb_dmxdev_feed_restart(dmxdevfilter);
471
		dmxdevfilter->feed.sec = NULL;
L
Linus Torvalds 已提交
472 473 474 475 476 477
		break;
	case DMXDEV_TYPE_PES:
		if (!dmxdevfilter->feed.ts)
			break;
		dvb_dmxdev_feed_stop(dmxdevfilter);
		dmxdevfilter->dev->demux->
478 479 480
		    release_ts_feed(dmxdevfilter->dev->demux,
				    dmxdevfilter->feed.ts);
		dmxdevfilter->feed.ts = NULL;
L
Linus Torvalds 已提交
481 482
		break;
	default:
483
		if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
L
Linus Torvalds 已提交
484 485 486
			return 0;
		return -EINVAL;
	}
487 488

	dvb_ringbuffer_flush(&dmxdevfilter->buffer);
L
Linus Torvalds 已提交
489 490 491 492 493
	return 0;
}

static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
{
494
	if (dmxdevfilter->state < DMXDEV_STATE_SET)
L
Linus Torvalds 已提交
495 496
		return 0;

497
	dmxdevfilter->type = DMXDEV_TYPE_NONE;
L
Linus Torvalds 已提交
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
	return 0;
}

static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
{
	struct dmxdev *dmxdev = filter->dev;
	void *mem;
	int ret, i;

	if (filter->state < DMXDEV_STATE_SET)
		return -EINVAL;

	if (filter->state >= DMXDEV_STATE_GO)
		dvb_dmxdev_filter_stop(filter);

514
	if (!filter->buffer.data) {
L
Linus Torvalds 已提交
515
		mem = vmalloc(filter->buffer.size);
516 517
		if (!mem)
			return -ENOMEM;
L
Linus Torvalds 已提交
518
		spin_lock_irq(&filter->dev->lock);
519
		filter->buffer.data = mem;
L
Linus Torvalds 已提交
520 521 522
		spin_unlock_irq(&filter->dev->lock);
	}

523
	dvb_ringbuffer_flush(&filter->buffer);
L
Linus Torvalds 已提交
524 525 526 527

	switch (filter->type) {
	case DMXDEV_TYPE_SEC:
	{
528 529 530 531 532 533
		struct dmx_sct_filter_params *para = &filter->params.sec;
		struct dmx_section_filter **secfilter = &filter->filter.sec;
		struct dmx_section_feed **secfeed = &filter->feed.sec;

		*secfilter = NULL;
		*secfeed = NULL;
L
Linus Torvalds 已提交
534 535 536


		/* find active filter/feed with same PID */
537
		for (i = 0; i < dmxdev->filternum; i++) {
L
Linus Torvalds 已提交
538
			if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
539 540
			    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
			    dmxdev->filter[i].params.sec.pid == para->pid) {
L
Linus Torvalds 已提交
541 542 543 544 545 546 547
				*secfeed = dmxdev->filter[i].feed.sec;
				break;
			}
		}

		/* if no feed found, try to allocate new one */
		if (!*secfeed) {
548 549 550 551 552 553
			ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
								   secfeed,
								   dvb_dmxdev_section_callback);
			if (ret < 0) {
				printk("DVB (%s): could not alloc feed\n",
				       __FUNCTION__);
L
Linus Torvalds 已提交
554 555 556
				return ret;
			}

557 558 559 560 561
			ret = (*secfeed)->set(*secfeed, para->pid, 32768,
					      (para->flags & DMX_CHECK_CRC) ? 1 : 0);
			if (ret < 0) {
				printk("DVB (%s): could not set feed\n",
				       __FUNCTION__);
L
Linus Torvalds 已提交
562 563 564 565 566 567 568
				dvb_dmxdev_feed_restart(filter);
				return ret;
			}
		} else {
			dvb_dmxdev_feed_stop(filter);
		}

569
		ret = (*secfeed)->allocate_filter(*secfeed, secfilter);
L
Linus Torvalds 已提交
570 571 572
		if (ret < 0) {
			dvb_dmxdev_feed_restart(filter);
			filter->feed.sec->start_filtering(*secfeed);
573
			dprintk("could not get filter\n");
L
Linus Torvalds 已提交
574 575 576 577 578 579
			return ret;
		}

		(*secfilter)->priv = filter;

		memcpy(&((*secfilter)->filter_value[3]),
580
		       &(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
L
Linus Torvalds 已提交
581
		memcpy(&(*secfilter)->filter_mask[3],
582
		       &para->filter.mask[1], DMX_FILTER_SIZE - 1);
L
Linus Torvalds 已提交
583
		memcpy(&(*secfilter)->filter_mode[3],
584
		       &para->filter.mode[1], DMX_FILTER_SIZE - 1);
L
Linus Torvalds 已提交
585

586 587 588 589 590
		(*secfilter)->filter_value[0] = para->filter.filter[0];
		(*secfilter)->filter_mask[0] = para->filter.mask[0];
		(*secfilter)->filter_mode[0] = para->filter.mode[0];
		(*secfilter)->filter_mask[1] = 0;
		(*secfilter)->filter_mask[2] = 0;
L
Linus Torvalds 已提交
591 592 593

		filter->todo = 0;

594
		ret = filter->feed.sec->start_filtering(filter->feed.sec);
L
Linus Torvalds 已提交
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
		if (ret < 0)
			return ret;

		dvb_dmxdev_filter_timer(filter);
		break;
	}
	case DMXDEV_TYPE_PES:
	{
		struct timespec timeout = { 0 };
		struct dmx_pes_filter_params *para = &filter->params.pes;
		dmx_output_t otype;
		int ret;
		int ts_type;
		enum dmx_ts_pes ts_pes;
		struct dmx_ts_feed **tsfeed = &filter->feed.ts;

		filter->feed.ts = NULL;
612
		otype = para->output;
L
Linus Torvalds 已提交
613

614
		ts_pes = (enum dmx_ts_pes)para->pes_type;
L
Linus Torvalds 已提交
615

616 617
		if (ts_pes < DMX_PES_OTHER)
			ts_type = TS_DECODER;
L
Linus Torvalds 已提交
618
		else
619
			ts_type = 0;
L
Linus Torvalds 已提交
620 621 622 623 624

		if (otype == DMX_OUT_TS_TAP)
			ts_type |= TS_PACKET;

		if (otype == DMX_OUT_TAP)
625
			ts_type |= TS_PAYLOAD_ONLY | TS_PACKET;
L
Linus Torvalds 已提交
626

627 628 629 630
		ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
						      tsfeed,
						      dvb_dmxdev_ts_callback);
		if (ret < 0)
L
Linus Torvalds 已提交
631 632
			return ret;

633
		(*tsfeed)->priv = filter;
L
Linus Torvalds 已提交
634 635

		ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes,
636
				     32768, timeout);
L
Linus Torvalds 已提交
637
		if (ret < 0) {
638 639
			dmxdev->demux->release_ts_feed(dmxdev->demux,
						       *tsfeed);
L
Linus Torvalds 已提交
640 641 642 643
			return ret;
		}

		ret = filter->feed.ts->start_filtering(filter->feed.ts);
644
		if (ret < 0) {
645 646
			dmxdev->demux->release_ts_feed(dmxdev->demux,
						       *tsfeed);
L
Linus Torvalds 已提交
647
			return ret;
648
		}
L
Linus Torvalds 已提交
649 650 651 652 653 654 655 656 657 658 659 660 661

		break;
	}
	default:
		return -EINVAL;
	}

	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
	return 0;
}

static int dvb_demux_open(struct inode *inode, struct file *file)
{
662 663
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
664 665 666 667 668 669
	int i;
	struct dmxdev_filter *dmxdevfilter;

	if (!dmxdev->filter)
		return -EINVAL;

670
	if (mutex_lock_interruptible(&dmxdev->mutex))
L
Linus Torvalds 已提交
671 672
		return -ERESTARTSYS;

673 674
	for (i = 0; i < dmxdev->filternum; i++)
		if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
L
Linus Torvalds 已提交
675 676
			break;

677
	if (i == dmxdev->filternum) {
678
		mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
679 680 681
		return -EMFILE;
	}

682
	dmxdevfilter = &dmxdev->filter[i];
683
	mutex_init(&dmxdevfilter->mutex);
684
	file->private_data = dmxdevfilter;
L
Linus Torvalds 已提交
685

686
	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
687
	dmxdevfilter->type = DMXDEV_TYPE_NONE;
L
Linus Torvalds 已提交
688
	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
689
	dmxdevfilter->feed.ts = NULL;
L
Linus Torvalds 已提交
690 691
	init_timer(&dmxdevfilter->timer);

692 693
	dvbdev->users++;

694
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
695 696 697
	return 0;
}

698 699
static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
				  struct dmxdev_filter *dmxdevfilter)
L
Linus Torvalds 已提交
700
{
701 702
	mutex_lock(&dmxdev->mutex);
	mutex_lock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
703 704 705 706 707

	dvb_dmxdev_filter_stop(dmxdevfilter);
	dvb_dmxdev_filter_reset(dmxdevfilter);

	if (dmxdevfilter->buffer.data) {
708
		void *mem = dmxdevfilter->buffer.data;
L
Linus Torvalds 已提交
709 710

		spin_lock_irq(&dmxdev->lock);
711
		dmxdevfilter->buffer.data = NULL;
L
Linus Torvalds 已提交
712 713 714 715 716 717
		spin_unlock_irq(&dmxdev->lock);
		vfree(mem);
	}

	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE);
	wake_up(&dmxdevfilter->buffer.queue);
718 719
	mutex_unlock(&dmxdevfilter->mutex);
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
720 721 722 723 724 725 726
	return 0;
}

static inline void invert_mode(dmx_filter_t *filter)
{
	int i;

727 728
	for (i = 0; i < DMX_FILTER_SIZE; i++)
		filter->mode[i] ^= 0xff;
L
Linus Torvalds 已提交
729 730 731
}

static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
732 733
				 struct dmxdev_filter *dmxdevfilter,
				 struct dmx_sct_filter_params *params)
L
Linus Torvalds 已提交
734
{
735
	dprintk("function : %s\n", __FUNCTION__);
L
Linus Torvalds 已提交
736 737 738

	dvb_dmxdev_filter_stop(dmxdevfilter);

739
	dmxdevfilter->type = DMXDEV_TYPE_SEC;
L
Linus Torvalds 已提交
740 741 742 743 744
	memcpy(&dmxdevfilter->params.sec,
	       params, sizeof(struct dmx_sct_filter_params));
	invert_mode(&dmxdevfilter->params.sec.filter);
	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);

745
	if (params->flags & DMX_IMMEDIATE_START)
L
Linus Torvalds 已提交
746 747 748 749 750 751
		return dvb_dmxdev_filter_start(dmxdevfilter);

	return 0;
}

static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
752 753
				     struct dmxdev_filter *dmxdevfilter,
				     struct dmx_pes_filter_params *params)
L
Linus Torvalds 已提交
754 755 756
{
	dvb_dmxdev_filter_stop(dmxdevfilter);

757
	if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
L
Linus Torvalds 已提交
758 759
		return -EINVAL;

760 761 762
	dmxdevfilter->type = DMXDEV_TYPE_PES;
	memcpy(&dmxdevfilter->params, params,
	       sizeof(struct dmx_pes_filter_params));
L
Linus Torvalds 已提交
763 764 765

	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);

766
	if (params->flags & DMX_IMMEDIATE_START)
L
Linus Torvalds 已提交
767 768 769 770 771 772
		return dvb_dmxdev_filter_start(dmxdevfilter);

	return 0;
}

static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
773 774
				   struct file *file, char __user *buf,
				   size_t count, loff_t *ppos)
L
Linus Torvalds 已提交
775 776
{
	int result, hcount;
777 778 779 780 781 782 783 784 785 786 787
	int done = 0;

	if (dfil->todo <= 0) {
		hcount = 3 + dfil->todo;
		if (hcount > count)
			hcount = count;
		result = dvb_dmxdev_buffer_read(&dfil->buffer,
						file->f_flags & O_NONBLOCK,
						buf, hcount, ppos);
		if (result < 0) {
			dfil->todo = 0;
L
Linus Torvalds 已提交
788 789
			return result;
		}
790
		if (copy_from_user(dfil->secheader - dfil->todo, buf, result))
L
Linus Torvalds 已提交
791
			return -EFAULT;
792 793 794 795 796
		buf += result;
		done = result;
		count -= result;
		dfil->todo -= result;
		if (dfil->todo > -3)
L
Linus Torvalds 已提交
797
			return done;
798
		dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff;
L
Linus Torvalds 已提交
799 800 801
		if (!count)
			return done;
	}
802 803 804 805 806 807
	if (count > dfil->todo)
		count = dfil->todo;
	result = dvb_dmxdev_buffer_read(&dfil->buffer,
					file->f_flags & O_NONBLOCK,
					buf, count, ppos);
	if (result < 0)
L
Linus Torvalds 已提交
808
		return result;
809 810
	dfil->todo -= result;
	return (result + done);
L
Linus Torvalds 已提交
811 812 813
}

static ssize_t
814 815
dvb_demux_read(struct file *file, char __user *buf, size_t count,
	       loff_t *ppos)
L
Linus Torvalds 已提交
816
{
817 818
	struct dmxdev_filter *dmxdevfilter = file->private_data;
	int ret;
L
Linus Torvalds 已提交
819

820
	if (mutex_lock_interruptible(&dmxdevfilter->mutex))
L
Linus Torvalds 已提交
821 822
		return -ERESTARTSYS;

823 824
	if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
		ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
L
Linus Torvalds 已提交
825
	else
826 827 828
		ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
					     file->f_flags & O_NONBLOCK,
					     buf, count, ppos);
L
Linus Torvalds 已提交
829

830
	mutex_unlock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
831 832 833 834 835 836
	return ret;
}

static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
			      unsigned int cmd, void *parg)
{
837
	struct dmxdev_filter *dmxdevfilter = file->private_data;
838 839 840
	struct dmxdev *dmxdev = dmxdevfilter->dev;
	unsigned long arg = (unsigned long)parg;
	int ret = 0;
L
Linus Torvalds 已提交
841

842
	if (mutex_lock_interruptible(&dmxdev->mutex))
L
Linus Torvalds 已提交
843 844 845 846
		return -ERESTARTSYS;

	switch (cmd) {
	case DMX_START:
847 848
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
849 850
			return -ERESTARTSYS;
		}
851
		if (dmxdevfilter->state < DMXDEV_STATE_SET)
L
Linus Torvalds 已提交
852 853 854
			ret = -EINVAL;
		else
			ret = dvb_dmxdev_filter_start(dmxdevfilter);
855
		mutex_unlock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
856 857 858
		break;

	case DMX_STOP:
859 860
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
861 862
			return -ERESTARTSYS;
		}
863
		ret = dvb_dmxdev_filter_stop(dmxdevfilter);
864
		mutex_unlock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
865 866 867
		break;

	case DMX_SET_FILTER:
868 869
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
870 871
			return -ERESTARTSYS;
		}
872
		ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg);
873
		mutex_unlock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
874 875 876
		break;

	case DMX_SET_PES_FILTER:
877 878
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
879 880
			return -ERESTARTSYS;
		}
881
		ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg);
882
		mutex_unlock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
883 884 885
		break;

	case DMX_SET_BUFFER_SIZE:
886 887
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
			mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
888 889
			return -ERESTARTSYS;
		}
890
		ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
891
		mutex_unlock(&dmxdevfilter->mutex);
L
Linus Torvalds 已提交
892 893 894 895
		break;

	case DMX_GET_PES_PIDS:
		if (!dmxdev->demux->get_pes_pids) {
896
			ret = -EINVAL;
L
Linus Torvalds 已提交
897 898
			break;
		}
899
		dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
L
Linus Torvalds 已提交
900 901
		break;

902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
	case DMX_GET_CAPS:
		if (!dmxdev->demux->get_caps) {
			ret = -EINVAL;
			break;
		}
		ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
		break;

	case DMX_SET_SOURCE:
		if (!dmxdev->demux->set_source) {
			ret = -EINVAL;
			break;
		}
		ret = dmxdev->demux->set_source(dmxdev->demux, parg);
		break;

L
Linus Torvalds 已提交
918 919
	case DMX_GET_STC:
		if (!dmxdev->demux->get_stc) {
920
			ret = -EINVAL;
L
Linus Torvalds 已提交
921 922 923
			break;
		}
		ret = dmxdev->demux->get_stc(dmxdev->demux,
924 925 926
					     ((struct dmx_stc *)parg)->num,
					     &((struct dmx_stc *)parg)->stc,
					     &((struct dmx_stc *)parg)->base);
L
Linus Torvalds 已提交
927 928 929
		break;

	default:
930 931
		ret = -EINVAL;
		break;
L
Linus Torvalds 已提交
932
	}
933
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
934 935 936 937 938 939 940 941 942
	return ret;
}

static int dvb_demux_ioctl(struct inode *inode, struct file *file,
			   unsigned int cmd, unsigned long arg)
{
	return dvb_usercopy(inode, file, cmd, arg, dvb_demux_do_ioctl);
}

943
static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
L
Linus Torvalds 已提交
944
{
945
	struct dmxdev_filter *dmxdevfilter = file->private_data;
L
Linus Torvalds 已提交
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
	unsigned int mask = 0;

	if (!dmxdevfilter)
		return -EINVAL;

	poll_wait(file, &dmxdevfilter->buffer.queue, wait);

	if (dmxdevfilter->state != DMXDEV_STATE_GO &&
	    dmxdevfilter->state != DMXDEV_STATE_DONE &&
	    dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT)
		return 0;

	if (dmxdevfilter->buffer.error)
		mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);

961
	if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
L
Linus Torvalds 已提交
962 963 964 965 966 967 968
		mask |= (POLLIN | POLLRDNORM | POLLPRI);

	return mask;
}

static int dvb_demux_release(struct inode *inode, struct file *file)
{
969
	struct dmxdev_filter *dmxdevfilter = file->private_data;
L
Linus Torvalds 已提交
970 971
	struct dmxdev *dmxdev = dmxdevfilter->dev;

972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
	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;
L
Linus Torvalds 已提交
987 988 989
}

static struct file_operations dvb_demux_fops = {
990 991 992 993 994 995
	.owner = THIS_MODULE,
	.read = dvb_demux_read,
	.ioctl = dvb_demux_ioctl,
	.open = dvb_demux_open,
	.release = dvb_demux_release,
	.poll = dvb_demux_poll,
L
Linus Torvalds 已提交
996 997 998
};

static struct dvb_device dvbdev_demux = {
999 1000 1001 1002
	.priv = NULL,
	.users = 1,
	.writers = 1,
	.fops = &dvb_demux_fops
L
Linus Torvalds 已提交
1003 1004 1005
};

static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
1006
			    unsigned int cmd, void *parg)
L
Linus Torvalds 已提交
1007
{
1008 1009
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
1010
	int ret;
L
Linus Torvalds 已提交
1011

1012
	if (mutex_lock_interruptible(&dmxdev->mutex))
L
Linus Torvalds 已提交
1013 1014 1015 1016 1017
		return -ERESTARTSYS;

	switch (cmd) {
	case DMX_SET_BUFFER_SIZE:
		// FIXME: implement
1018
		ret = 0;
L
Linus Torvalds 已提交
1019 1020 1021
		break;

	default:
1022 1023
		ret = -EINVAL;
		break;
L
Linus Torvalds 已提交
1024
	}
1025
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
1026 1027 1028 1029
	return ret;
}

static int dvb_dvr_ioctl(struct inode *inode, struct file *file,
1030
			 unsigned int cmd, unsigned long arg)
L
Linus Torvalds 已提交
1031 1032 1033 1034
{
	return dvb_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl);
}

1035
static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
L
Linus Torvalds 已提交
1036
{
1037 1038
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
1039 1040
	unsigned int mask = 0;

1041
	dprintk("function : %s\n", __FUNCTION__);
L
Linus Torvalds 已提交
1042 1043 1044

	poll_wait(file, &dmxdev->dvr_buffer.queue, wait);

1045
	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
L
Linus Torvalds 已提交
1046 1047 1048
		if (dmxdev->dvr_buffer.error)
			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);

1049
		if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
L
Linus Torvalds 已提交
1050 1051 1052 1053 1054 1055 1056 1057
			mask |= (POLLIN | POLLRDNORM | POLLPRI);
	} else
		mask |= (POLLOUT | POLLWRNORM | POLLPRI);

	return mask;
}

static struct file_operations dvb_dvr_fops = {
1058 1059 1060 1061 1062 1063 1064
	.owner = THIS_MODULE,
	.read = dvb_dvr_read,
	.write = dvb_dvr_write,
	.ioctl = dvb_dvr_ioctl,
	.open = dvb_dvr_open,
	.release = dvb_dvr_release,
	.poll = dvb_dvr_poll,
L
Linus Torvalds 已提交
1065 1066 1067
};

static struct dvb_device dvbdev_dvr = {
1068
	.priv = NULL,
1069
	.readers = 1,
1070
	.users = 1,
1071
	.fops = &dvb_dvr_fops
L
Linus Torvalds 已提交
1072 1073
};

1074
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
L
Linus Torvalds 已提交
1075 1076 1077 1078 1079 1080
{
	int i;

	if (dmxdev->demux->open(dmxdev->demux) < 0)
		return -EUSERS;

1081
	dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
L
Linus Torvalds 已提交
1082 1083 1084
	if (!dmxdev->filter)
		return -ENOMEM;

1085
	mutex_init(&dmxdev->mutex);
L
Linus Torvalds 已提交
1086
	spin_lock_init(&dmxdev->lock);
1087 1088 1089 1090 1091
	for (i = 0; i < dmxdev->filternum; i++) {
		dmxdev->filter[i].dev = dmxdev;
		dmxdev->filter[i].buffer.data = NULL;
		dvb_dmxdev_filter_state_set(&dmxdev->filter[i],
					    DMXDEV_STATE_FREE);
L
Linus Torvalds 已提交
1092 1093
	}

1094 1095 1096 1097
	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
			    DVB_DEVICE_DEMUX);
	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
			    dmxdev, DVB_DEVICE_DVR);
L
Linus Torvalds 已提交
1098

1099
	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
L
Linus Torvalds 已提交
1100 1101 1102

	return 0;
}
1103

L
Linus Torvalds 已提交
1104 1105
EXPORT_SYMBOL(dvb_dmxdev_init);

1106
void dvb_dmxdev_release(struct dmxdev *dmxdev)
L
Linus Torvalds 已提交
1107
{
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
	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);
	}

L
Linus Torvalds 已提交
1118 1119 1120 1121
	dvb_unregister_device(dmxdev->dvbdev);
	dvb_unregister_device(dmxdev->dvr_dvbdev);

	vfree(dmxdev->filter);
1122
	dmxdev->filter = NULL;
L
Linus Torvalds 已提交
1123 1124
	dmxdev->demux->close(dmxdev->demux);
}
1125

L
Linus Torvalds 已提交
1126
EXPORT_SYMBOL(dvb_dmxdev_release);