diff options
Diffstat (limited to 'drivers/media/dvb/dvb-core/dmxdev.c')
| -rw-r--r-- | drivers/media/dvb/dvb-core/dmxdev.c | 1148 |
1 files changed, 0 insertions, 1148 deletions
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c deleted file mode 100644 index 8028c3a5e28..00000000000 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ /dev/null @@ -1,1148 +0,0 @@ -/* - * dmxdev.c - DVB demultiplexer device - * - * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> - * & Marcus Metzler <marcus@convergence.de> - for convergence integrated media GmbH - * - * 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/moduleparam.h> -#include <linux/sched.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 - -static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) -{ - buffer->data=NULL; - buffer->size=8192; - buffer->pread=0; - buffer->pwrite=0; - buffer->error=0; - init_waitqueue_head(&buffer->queue); -} - -static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *src, int len) -{ - int split; - int free; - int todo; - - if (!len) - return 0; - if (!buf->data) - return 0; - - free=buf->pread-buf->pwrite; - split=0; - if (free<=0) { - free+=buf->size; - split=buf->size-buf->pwrite; - } - if (len>=free) { - dprintk("dmxdev: buffer overflow\n"); - return -1; - } - if (split>=len) - split=0; - todo=len; - if (split) { - memcpy(buf->data + buf->pwrite, src, split); - todo-=split; - buf->pwrite=0; - } - memcpy(buf->data + buf->pwrite, src+split, todo); - buf->pwrite=(buf->pwrite+todo)%buf->size; - return len; -} - -static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src, - int non_blocking, char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long todo=count; - int split, avail, error; - - if (!src->data) - return 0; - - if ((error=src->error)) { - src->pwrite=src->pread; - src->error=0; - return error; - } - - if (non_blocking && (src->pwrite==src->pread)) - return -EWOULDBLOCK; - - while (todo>0) { - if (non_blocking && (src->pwrite==src->pread)) - return (count-todo) ? (count-todo) : -EWOULDBLOCK; - - if (wait_event_interruptible(src->queue, - (src->pread!=src->pwrite) || - (src->error))<0) - return count-todo; - - if ((error=src->error)) { - src->pwrite=src->pread; - src->error=0; - return error; - } - - split=src->size; - avail=src->pwrite - src->pread; - if (avail<0) { - avail+=src->size; - split=src->size - src->pread; - } - if (avail>todo) - avail=todo; - if (split<avail) { - if (copy_to_user(buf, src->data+src->pread, split)) - return -EFAULT; - buf+=split; - src->pread=0; - todo-=split; - avail-=split; - } - if (avail) { - if (copy_to_user(buf, src->data+src->pread, avail)) - return -EFAULT; - src->pread = (src->pread + avail) % src->size; - todo-=avail; - buf+=avail; - } - } - return count; -} - -static struct dmx_frontend * get_fe(struct dmx_demux *demux, int type) -{ - struct list_head *head, *pos; - - head=demux->get_frontends(demux); - if (!head) - return NULL; - list_for_each(pos, head) - if (DMX_FE_ENTRY(pos)->source==type) - return DMX_FE_ENTRY(pos); - - return NULL; -} - -static inline void dvb_dmxdev_dvr_state_set(struct dmxdev_dvr *dmxdevdvr, int state) -{ - spin_lock_irq(&dmxdevdvr->dev->lock); - dmxdevdvr->state=state; - spin_unlock_irq(&dmxdevdvr->dev->lock); -} - -static int dvb_dvr_open(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - struct dmx_frontend *front; - - dprintk ("function : %s\n", __FUNCTION__); - - if (down_interruptible (&dmxdev->mutex)) - return -ERESTARTSYS; - - if ((file->f_flags&O_ACCMODE)==O_RDWR) { - if (!(dmxdev->capabilities&DMXDEV_CAP_DUPLEX)) { - up(&dmxdev->mutex); - return -EOPNOTSUPP; - } - } - - if ((file->f_flags&O_ACCMODE)==O_RDONLY) { - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); - dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; - dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); - if (!dmxdev->dvr_buffer.data) { - up(&dmxdev->mutex); - return -ENOMEM; - } - } - - if ((file->f_flags&O_ACCMODE)==O_WRONLY) { - dmxdev->dvr_orig_fe=dmxdev->demux->frontend; - - if (!dmxdev->demux->write) { - up(&dmxdev->mutex); - return -EOPNOTSUPP; - } - - front=get_fe(dmxdev->demux, DMX_MEMORY_FE); - - if (!front) { - up(&dmxdev->mutex); - return -EINVAL; - } - dmxdev->demux->disconnect_frontend(dmxdev->demux); - dmxdev->demux->connect_frontend(dmxdev->demux, front); - } - up(&dmxdev->mutex); - return 0; -} - -static int dvb_dvr_release(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - - if (down_interruptible (&dmxdev->mutex)) - return -ERESTARTSYS; - - if ((file->f_flags&O_ACCMODE)==O_WRONLY) { - dmxdev->demux->disconnect_frontend(dmxdev->demux); - dmxdev->demux->connect_frontend(dmxdev->demux, - dmxdev->dvr_orig_fe); - } - if ((file->f_flags&O_ACCMODE)==O_RDONLY) { - if (dmxdev->dvr_buffer.data) { - void *mem=dmxdev->dvr_buffer.data; - mb(); - spin_lock_irq(&dmxdev->lock); - dmxdev->dvr_buffer.data=NULL; - spin_unlock_irq(&dmxdev->lock); - vfree(mem); - } - } - up(&dmxdev->mutex); - return 0; -} - -static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - int ret; - - if (!dmxdev->demux->write) - return -EOPNOTSUPP; - if ((file->f_flags&O_ACCMODE)!=O_WRONLY) - return -EINVAL; - if (down_interruptible (&dmxdev->mutex)) - return -ERESTARTSYS; - ret=dmxdev->demux->write(dmxdev->demux, buf, count); - up(&dmxdev->mutex); - return ret; -} - -static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - int ret; - - //down(&dmxdev->mutex); - ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, - file->f_flags&O_NONBLOCK, - buf, count, ppos); - //up(&dmxdev->mutex); - return ret; -} - -static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter *dmxdevfilter, int state) -{ - spin_lock_irq(&dmxdevfilter->dev->lock); - dmxdevfilter->state=state; - spin_unlock_irq(&dmxdevfilter->dev->lock); -} - -static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsigned long size) -{ - struct dmxdev_buffer *buf=&dmxdevfilter->buffer; - void *mem; - - if (buf->size==size) - return 0; - if (dmxdevfilter->state>=DMXDEV_STATE_GO) - return -EBUSY; - spin_lock_irq(&dmxdevfilter->dev->lock); - mem=buf->data; - buf->data=NULL; - buf->size=size; - buf->pwrite=buf->pread=0; - spin_unlock_irq(&dmxdevfilter->dev->lock); - vfree(mem); - - if (buf->size) { - mem=vmalloc(dmxdevfilter->buffer.size); - if (!mem) - return -ENOMEM; - spin_lock_irq(&dmxdevfilter->dev->lock); - buf->data=mem; - spin_unlock_irq(&dmxdevfilter->dev->lock); - } - return 0; -} - -static void dvb_dmxdev_filter_timeout(unsigned long data) -{ - struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *)data; - - dmxdevfilter->buffer.error=-ETIMEDOUT; - spin_lock_irq(&dmxdevfilter->dev->lock); - dmxdevfilter->state=DMXDEV_STATE_TIMEDOUT; - spin_unlock_irq(&dmxdevfilter->dev->lock); - wake_up(&dmxdevfilter->buffer.queue); -} - -static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) -{ - struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec; - - del_timer(&dmxdevfilter->timer); - if (para->timeout) { - dmxdevfilter->timer.function=dvb_dmxdev_filter_timeout; - dmxdevfilter->timer.data=(unsigned long) dmxdevfilter; - dmxdevfilter->timer.expires=jiffies+1+(HZ/2+HZ*para->timeout)/1000; - add_timer(&dmxdevfilter->timer); - } -} - -static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, - const u8 *buffer2, size_t buffer2_len, - struct dmx_section_filter *filter, enum dmx_success success) -{ - struct dmxdev_filter *dmxdevfilter = filter->priv; - int ret; - - if (dmxdevfilter->buffer.error) { - wake_up(&dmxdevfilter->buffer.queue); - return 0; - } - spin_lock(&dmxdevfilter->dev->lock); - if (dmxdevfilter->state!=DMXDEV_STATE_GO) { - 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], - 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); - } - if (ret<0) { - dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread; - dmxdevfilter->buffer.error=-EOVERFLOW; - } - if (dmxdevfilter->params.sec.flags&DMX_ONESHOT) - dmxdevfilter->state=DMXDEV_STATE_DONE; - 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, - const u8 *buffer2, size_t buffer2_len, - struct dmx_ts_feed *feed, enum dmx_success success) -{ - struct dmxdev_filter *dmxdevfilter = feed->priv; - struct dmxdev_buffer *buffer; - int ret; - - spin_lock(&dmxdevfilter->dev->lock); - if (dmxdevfilter->params.pes.output==DMX_OUT_DECODER) { - spin_unlock(&dmxdevfilter->dev->lock); - return 0; - } - - if (dmxdevfilter->params.pes.output==DMX_OUT_TAP) - buffer=&dmxdevfilter->buffer; - else - buffer=&dmxdevfilter->dev->dvr_buffer; - if (buffer->error) { - spin_unlock(&dmxdevfilter->dev->lock); - wake_up(&buffer->queue); - return 0; - } - 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) { - buffer->pwrite=buffer->pread; - buffer->error=-EOVERFLOW; - } - 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) -{ - dvb_dmxdev_filter_state_set (filter, DMXDEV_STATE_GO); - - switch (filter->type) { - case DMXDEV_TYPE_SEC: - return filter->feed.sec->start_filtering(filter->feed.sec); - break; - case DMXDEV_TYPE_PES: - return filter->feed.ts->start_filtering(filter->feed.ts); - break; - 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; - - 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].pid==pid) { - dvb_dmxdev_feed_start(&dmxdev->filter[i]); - return 0; - } - - filter->dev->demux->release_section_feed(dmxdev->demux, filter->feed.sec); - - return 0; -} - -static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) -{ - if (dmxdevfilter->state<DMXDEV_STATE_GO) - 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-> - release_filter(dmxdevfilter->feed.sec, - dmxdevfilter->filter.sec); - dvb_dmxdev_feed_restart(dmxdevfilter); - dmxdevfilter->feed.sec=NULL; - break; - case DMXDEV_TYPE_PES: - if (!dmxdevfilter->feed.ts) - break; - dvb_dmxdev_feed_stop(dmxdevfilter); - dmxdevfilter->dev->demux-> - release_ts_feed(dmxdevfilter->dev->demux, - dmxdevfilter->feed.ts); - dmxdevfilter->feed.ts=NULL; - break; - default: - if (dmxdevfilter->state==DMXDEV_STATE_ALLOCATED) - return 0; - return -EINVAL; - } - dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0; - return 0; -} - -static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) -{ - if (dmxdevfilter->state<DMXDEV_STATE_SET) - return 0; - - dmxdevfilter->type=DMXDEV_TYPE_NONE; - dmxdevfilter->pid=0xffff; - 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); - - if (!(mem = filter->buffer.data)) { - mem = vmalloc(filter->buffer.size); - spin_lock_irq(&filter->dev->lock); - filter->buffer.data=mem; - spin_unlock_irq(&filter->dev->lock); - if (!filter->buffer.data) - return -ENOMEM; - } - - filter->buffer.pwrite = filter->buffer.pread = 0; - - switch (filter->type) { - case DMXDEV_TYPE_SEC: - { - 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; - - /* find active filter/feed with same PID */ - for (i=0; i<dmxdev->filternum; i++) { - if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && - dmxdev->filter[i].pid == para->pid && - dmxdev->filter[i].type == DMXDEV_TYPE_SEC) { - *secfeed = dmxdev->filter[i].feed.sec; - break; - } - } - - /* if no feed found, try to allocate new one */ - if (!*secfeed) { - 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__); - return ret; - } - - 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__); - dvb_dmxdev_feed_restart(filter); - return ret; - } - } else { - dvb_dmxdev_feed_stop(filter); - } - - ret=(*secfeed)->allocate_filter(*secfeed, secfilter); - - if (ret < 0) { - dvb_dmxdev_feed_restart(filter); - filter->feed.sec->start_filtering(*secfeed); - dprintk ("could not get filter\n"); - return ret; - } - - (*secfilter)->priv = filter; - - memcpy(&((*secfilter)->filter_value[3]), - &(para->filter.filter[1]), DMX_FILTER_SIZE-1); - memcpy(&(*secfilter)->filter_mask[3], - ¶->filter.mask[1], DMX_FILTER_SIZE-1); - memcpy(&(*secfilter)->filter_mode[3], - ¶->filter.mode[1], DMX_FILTER_SIZE-1); - - (*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; - - filter->todo = 0; - - ret = filter->feed.sec->start_filtering (filter->feed.sec); - - 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; - otype=para->output; - - ts_pes=(enum dmx_ts_pes) para->pes_type; - - if (ts_pes<DMX_PES_OTHER) - ts_type=TS_DECODER; - else - ts_type=0; - - if (otype == DMX_OUT_TS_TAP) - ts_type |= TS_PACKET; - - if (otype == DMX_OUT_TAP) - ts_type |= TS_PAYLOAD_ONLY|TS_PACKET; - - ret=dmxdev->demux->allocate_ts_feed(dmxdev->demux, - tsfeed, - dvb_dmxdev_ts_callback); - if (ret<0) - return ret; - - (*tsfeed)->priv = (void *) filter; - - ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes, - 32768, timeout); - - if (ret < 0) { - dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed); - return ret; - } - - ret = filter->feed.ts->start_filtering(filter->feed.ts); - - if (ret < 0) { - dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed); - return ret; - } - - 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) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - int i; - struct dmxdev_filter *dmxdevfilter; - - if (!dmxdev->filter) - return -EINVAL; - - if (down_interruptible(&dmxdev->mutex)) - return -ERESTARTSYS; - - for (i=0; i<dmxdev->filternum; i++) - if (dmxdev->filter[i].state==DMXDEV_STATE_FREE) - break; - - if (i==dmxdev->filternum) { - up(&dmxdev->mutex); - return -EMFILE; - } - - dmxdevfilter=&dmxdev->filter[i]; - sema_init(&dmxdevfilter->mutex, 1); - dmxdevfilter->dvbdev=dmxdev->dvbdev; - file->private_data=dmxdevfilter; - - dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); - dmxdevfilter->type=DMXDEV_TYPE_NONE; - dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); - dmxdevfilter->feed.ts=NULL; - init_timer(&dmxdevfilter->timer); - - up(&dmxdev->mutex); - return 0; -} - - -static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter) -{ - if (down_interruptible(&dmxdev->mutex)) - return -ERESTARTSYS; - - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); - return -ERESTARTSYS; - } - - dvb_dmxdev_filter_stop(dmxdevfilter); - dvb_dmxdev_filter_reset(dmxdevfilter); - - if (dmxdevfilter->buffer.data) { - void *mem=dmxdevfilter->buffer.data; - - spin_lock_irq(&dmxdev->lock); - dmxdevfilter->buffer.data=NULL; - spin_unlock_irq(&dmxdev->lock); - vfree(mem); - } - - dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); - wake_up(&dmxdevfilter->buffer.queue); - up(&dmxdevfilter->mutex); - up(&dmxdev->mutex); - return 0; -} - -static inline void invert_mode(dmx_filter_t *filter) -{ - int i; - - for (i=0; i<DMX_FILTER_SIZE; i++) - filter->mode[i]^=0xff; -} - - -static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, - struct dmxdev_filter *dmxdevfilter, - struct dmx_sct_filter_params *params) -{ - dprintk ("function : %s\n", __FUNCTION__); - - dvb_dmxdev_filter_stop(dmxdevfilter); - - dmxdevfilter->type=DMXDEV_TYPE_SEC; - dmxdevfilter->pid=params->pid; - 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); - - if (params->flags&DMX_IMMEDIATE_START) - return dvb_dmxdev_filter_start(dmxdevfilter); - - return 0; -} - -static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, - struct dmxdev_filter *dmxdevfilter, - struct dmx_pes_filter_params *params) -{ - dvb_dmxdev_filter_stop(dmxdevfilter); - - if (params->pes_type>DMX_PES_OTHER || params->pes_type<0) - return -EINVAL; - - dmxdevfilter->type=DMXDEV_TYPE_PES; - dmxdevfilter->pid=params->pid; - memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params)); - - dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); - - if (params->flags&DMX_IMMEDIATE_START) - return dvb_dmxdev_filter_start(dmxdevfilter); - - return 0; -} - -static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, - struct file *file, char __user *buf, size_t count, loff_t *ppos) -{ - int result, hcount; - 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; - return result; - } - if (copy_from_user(dfil->secheader-dfil->todo, buf, result)) - return -EFAULT; - buf+=result; - done=result; - count-=result; - dfil->todo-=result; - if (dfil->todo>-3) - return done; - dfil->todo=((dfil->secheader[1]<<8)|dfil->secheader[2])&0xfff; - if (!count) - return done; - } - 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) - return result; - dfil->todo-=result; - return (result+done); -} - - -static ssize_t -dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) -{ - struct dmxdev_filter *dmxdevfilter= file->private_data; - int ret=0; - - if (down_interruptible(&dmxdevfilter->mutex)) - return -ERESTARTSYS; - - if (dmxdevfilter->type==DMXDEV_TYPE_SEC) - ret=dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); - else - ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, - file->f_flags&O_NONBLOCK, - buf, count, ppos); - - up(&dmxdevfilter->mutex); - return ret; -} - - -static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *parg) -{ - struct dmxdev_filter *dmxdevfilter = file->private_data; - struct dmxdev *dmxdev=dmxdevfilter->dev; - unsigned long arg=(unsigned long) parg; - int ret=0; - - if (down_interruptible (&dmxdev->mutex)) - return -ERESTARTSYS; - - switch (cmd) { - case DMX_START: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); - return -ERESTARTSYS; - } - if (dmxdevfilter->state<DMXDEV_STATE_SET) - ret = -EINVAL; - else - ret = dvb_dmxdev_filter_start(dmxdevfilter); - up(&dmxdevfilter->mutex); - break; - - case DMX_STOP: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); - return -ERESTARTSYS; - } - ret=dvb_dmxdev_filter_stop(dmxdevfilter); - up(&dmxdevfilter->mutex); - break; - - case DMX_SET_FILTER: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); - return -ERESTARTSYS; - } - ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, - (struct dmx_sct_filter_params *)parg); - up(&dmxdevfilter->mutex); - break; - - case DMX_SET_PES_FILTER: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); - return -ERESTARTSYS; - } - ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, - (struct dmx_pes_filter_params *)parg); - up(&dmxdevfilter->mutex); - break; - - case DMX_SET_BUFFER_SIZE: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); - return -ERESTARTSYS; - } - ret=dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); - up(&dmxdevfilter->mutex); - break; - - case DMX_GET_EVENT: - break; - - case DMX_GET_PES_PIDS: - if (!dmxdev->demux->get_pes_pids) { - ret=-EINVAL; - break; - } - dmxdev->demux->get_pes_pids(dmxdev->demux, (u16 *)parg); - break; - - 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; - - case DMX_GET_STC: - if (!dmxdev->demux->get_stc) { - ret=-EINVAL; - break; - } - ret = dmxdev->demux->get_stc(dmxdev->demux, - ((struct dmx_stc *)parg)->num, - &((struct dmx_stc *)parg)->stc, - &((struct dmx_stc *)parg)->base); - break; - - default: - ret=-EINVAL; - } - up(&dmxdev->mutex); - 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); -} - - -static unsigned int dvb_demux_poll (struct file *file, poll_table *wait) -{ - struct dmxdev_filter *dmxdevfilter = file->private_data; - 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); - - if (dmxdevfilter->buffer.pread != dmxdevfilter->buffer.pwrite) - mask |= (POLLIN | POLLRDNORM | POLLPRI); - - return mask; -} - - -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); -} - - -static struct file_operations dvb_demux_fops = { - .owner = THIS_MODULE, - .read = dvb_demux_read, - .ioctl = dvb_demux_ioctl, - .open = dvb_demux_open, - .release = dvb_demux_release, - .poll = dvb_demux_poll, -}; - - -static struct dvb_device dvbdev_demux = { - .priv = NULL, - .users = 1, - .writers = 1, - .fops = &dvb_demux_fops -}; - - -static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *parg) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - - int ret=0; - - if (down_interruptible (&dmxdev->mutex)) - return -ERESTARTSYS; - - switch (cmd) { - case DMX_SET_BUFFER_SIZE: - // FIXME: implement - ret=0; - break; - - default: - ret=-EINVAL; - } - up(&dmxdev->mutex); - return ret; -} - - -static int dvb_dvr_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return dvb_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl); -} - - -static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait) -{ - struct dvb_device *dvbdev = file->private_data; - struct dmxdev *dmxdev = dvbdev->priv; - unsigned int mask = 0; - - dprintk ("function : %s\n", __FUNCTION__); - - poll_wait(file, &dmxdev->dvr_buffer.queue, wait); - - if ((file->f_flags&O_ACCMODE) == O_RDONLY) { - if (dmxdev->dvr_buffer.error) - mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - - if (dmxdev->dvr_buffer.pread!=dmxdev->dvr_buffer.pwrite) - mask |= (POLLIN | POLLRDNORM | POLLPRI); - } else - mask |= (POLLOUT | POLLWRNORM | POLLPRI); - - return mask; -} - - -static struct file_operations dvb_dvr_fops = { - .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, -}; - -static struct dvb_device dvbdev_dvr = { - .priv = NULL, - .users = 1, - .writers = 1, - .fops = &dvb_dvr_fops -}; - -int -dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) -{ - int i; - - if (dmxdev->demux->open(dmxdev->demux) < 0) - return -EUSERS; - - dmxdev->filter = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_filter)); - if (!dmxdev->filter) - return -ENOMEM; - - dmxdev->dvr = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_dvr)); - if (!dmxdev->dvr) { - vfree(dmxdev->filter); - dmxdev->filter = NULL; - return -ENOMEM; - } - - sema_init(&dmxdev->mutex, 1); - spin_lock_init(&dmxdev->lock); - 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); - dmxdev->dvr[i].dev=dmxdev; - dmxdev->dvr[i].buffer.data=NULL; - dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE); - } - - 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); - - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); - - return 0; -} -EXPORT_SYMBOL(dvb_dmxdev_init); - -void -dvb_dmxdev_release(struct dmxdev *dmxdev) -{ - dvb_unregister_device(dmxdev->dvbdev); - dvb_unregister_device(dmxdev->dvr_dvbdev); - - vfree(dmxdev->filter); - dmxdev->filter=NULL; - vfree(dmxdev->dvr); - dmxdev->dvr=NULL; - dmxdev->demux->close(dmxdev->demux); -} -EXPORT_SYMBOL(dvb_dmxdev_release); |
