dmxdev.c 27.3 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
	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
379
		buffer = &dmxdevfilter->buffer;
L
Linus Torvalds 已提交
380
	else
381
		buffer = &dmxdevfilter->dev->dvr_buffer;
L
Linus Torvalds 已提交
382 383 384 385 386
	if (buffer->error) {
		spin_unlock(&dmxdevfilter->dev->lock);
		wake_up(&buffer->queue);
		return 0;
	}
387 388 389 390
	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) {
391 392
		dvb_ringbuffer_flush(buffer);
		buffer->error = ret;
L
Linus Torvalds 已提交
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 420
	}
	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)
{
421
	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
L
Linus Torvalds 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442

	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;

443 444 445 446
	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 已提交
447 448 449 450
			dvb_dmxdev_feed_start(&dmxdev->filter[i]);
			return 0;
		}

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

	return 0;
}

static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
{
459
	if (dmxdevfilter->state < DMXDEV_STATE_GO)
L
Linus Torvalds 已提交
460 461 462 463 464 465 466 467 468
		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->
469 470
			    release_filter(dmxdevfilter->feed.sec,
					   dmxdevfilter->filter.sec);
L
Linus Torvalds 已提交
471
		dvb_dmxdev_feed_restart(dmxdevfilter);
472
		dmxdevfilter->feed.sec = NULL;
L
Linus Torvalds 已提交
473 474 475 476 477 478
		break;
	case DMXDEV_TYPE_PES:
		if (!dmxdevfilter->feed.ts)
			break;
		dvb_dmxdev_feed_stop(dmxdevfilter);
		dmxdevfilter->dev->demux->
479 480 481
		    release_ts_feed(dmxdevfilter->dev->demux,
				    dmxdevfilter->feed.ts);
		dmxdevfilter->feed.ts = NULL;
L
Linus Torvalds 已提交
482 483
		break;
	default:
484
		if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
L
Linus Torvalds 已提交
485 486 487
			return 0;
		return -EINVAL;
	}
488 489

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

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

498
	dmxdevfilter->type = DMXDEV_TYPE_NONE;
L
Linus Torvalds 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
	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);

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

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

	switch (filter->type) {
	case DMXDEV_TYPE_SEC:
	{
529 530 531 532 533 534
		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 已提交
535 536 537


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

		/* if no feed found, try to allocate new one */
		if (!*secfeed) {
549 550 551 552 553 554
			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 已提交
555 556 557
				return ret;
			}

558 559 560 561 562
			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 已提交
563 564 565 566 567 568 569
				dvb_dmxdev_feed_restart(filter);
				return ret;
			}
		} else {
			dvb_dmxdev_feed_stop(filter);
		}

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

		(*secfilter)->priv = filter;

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

587 588 589 590 591
		(*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 已提交
592 593 594

		filter->todo = 0;

595
		ret = filter->feed.sec->start_filtering(filter->feed.sec);
L
Linus Torvalds 已提交
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
		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;
613
		otype = para->output;
L
Linus Torvalds 已提交
614

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

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

622
		if (otype == DMX_OUT_TS_TAP)
L
Linus Torvalds 已提交
623
			ts_type |= TS_PACKET;
624 625 626 627
		else if (otype == DMX_OUT_TSDEMUX_TAP)
			ts_type |= TS_PACKET | TS_DEMUX;
		else if (otype == DMX_OUT_TAP)
			ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
L
Linus Torvalds 已提交
628

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

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

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

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

		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)
{
664 665
	struct dvb_device *dvbdev = file->private_data;
	struct dmxdev *dmxdev = dvbdev->priv;
L
Linus Torvalds 已提交
666 667 668 669 670 671
	int i;
	struct dmxdev_filter *dmxdevfilter;

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

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

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

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

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

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

694 695
	dvbdev->users++;

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

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

	dvb_dmxdev_filter_stop(dmxdevfilter);
	dvb_dmxdev_filter_reset(dmxdevfilter);

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

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

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

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

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

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

	dvb_dmxdev_filter_stop(dmxdevfilter);

741
	dmxdevfilter->type = DMXDEV_TYPE_SEC;
L
Linus Torvalds 已提交
742 743 744 745 746
	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);

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

	return 0;
}

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

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

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

	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);

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

	return 0;
}

static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
775 776
				   struct file *file, char __user *buf,
				   size_t count, loff_t *ppos)
L
Linus Torvalds 已提交
777 778
{
	int result, hcount;
779 780 781 782 783 784 785 786 787 788 789
	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 已提交
790 791
			return result;
		}
792
		if (copy_from_user(dfil->secheader - dfil->todo, buf, result))
L
Linus Torvalds 已提交
793
			return -EFAULT;
794 795 796 797 798
		buf += result;
		done = result;
		count -= result;
		dfil->todo -= result;
		if (dfil->todo > -3)
L
Linus Torvalds 已提交
799
			return done;
800
		dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff;
L
Linus Torvalds 已提交
801 802 803
		if (!count)
			return done;
	}
804 805 806 807 808 809
	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 已提交
810
		return result;
811 812
	dfil->todo -= result;
	return (result + done);
L
Linus Torvalds 已提交
813 814 815
}

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

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

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

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

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

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

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

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

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

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

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

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

904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
	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 已提交
920 921
	case DMX_GET_STC:
		if (!dmxdev->demux->get_stc) {
922
			ret = -EINVAL;
L
Linus Torvalds 已提交
923 924 925
			break;
		}
		ret = dmxdev->demux->get_stc(dmxdev->demux,
926 927 928
					     ((struct dmx_stc *)parg)->num,
					     &((struct dmx_stc *)parg)->stc,
					     &((struct dmx_stc *)parg)->base);
L
Linus Torvalds 已提交
929 930 931
		break;

	default:
932 933
		ret = -EINVAL;
		break;
L
Linus Torvalds 已提交
934
	}
935
	mutex_unlock(&dmxdev->mutex);
L
Linus Torvalds 已提交
936 937 938 939 940 941 942 943 944
	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);
}

945
static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
L
Linus Torvalds 已提交
946
{
947
	struct dmxdev_filter *dmxdevfilter = file->private_data;
L
Linus Torvalds 已提交
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
	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);

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

	return mask;
}

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

974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
	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 已提交
989 990 991
}

static struct file_operations dvb_demux_fops = {
992 993 994 995 996 997
	.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 已提交
998 999 1000
};

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

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

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

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

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

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

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

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

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

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

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

	return mask;
}

static struct file_operations dvb_dvr_fops = {
1060 1061 1062 1063 1064 1065 1066
	.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 已提交
1067 1068 1069
};

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

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

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

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

1087
	mutex_init(&dmxdev->mutex);
L
Linus Torvalds 已提交
1088
	spin_lock_init(&dmxdev->lock);
1089 1090 1091 1092 1093
	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 已提交
1094 1095
	}

1096 1097 1098 1099
	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 已提交
1100

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

	return 0;
}
1105

L
Linus Torvalds 已提交
1106 1107
EXPORT_SYMBOL(dvb_dmxdev_init);

1108
void dvb_dmxdev_release(struct dmxdev *dmxdev)
L
Linus Torvalds 已提交
1109
{
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
	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 已提交
1120 1121 1122 1123
	dvb_unregister_device(dmxdev->dvbdev);
	dvb_unregister_device(dmxdev->dvr_dvbdev);

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

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