Example #1
0
File: dmxdev.c Project: 274914765/C
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;

    mutex_init(&dmxdev->mutex);
    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);
    }

    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_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);

    return 0;
}
Example #2
0
static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
				  struct dmxdev_filter *dmxdevfilter)
{
	if (mutex_lock_interruptible(&dmxdev->mutex))
		return -ERESTARTSYS;

	if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
		mutex_unlock(&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);
	mutex_unlock(&dmxdevfilter->mutex);
	mutex_unlock(&dmxdev->mutex);
	return 0;
}
Example #3
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 (mutex_lock_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) {
		mutex_unlock(&dmxdev->mutex);
		return -EMFILE;
	}

	dmxdevfilter = &dmxdev->filter[i];
	mutex_init(&dmxdevfilter->mutex);
	file->private_data = dmxdevfilter;

	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
	dmxdevfilter->type = DMXDEV_TYPE_NONE;
	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
	dmxdevfilter->feed.ts = NULL;
	init_timer(&dmxdevfilter->timer);

	mutex_unlock(&dmxdev->mutex);
	return 0;
}
Example #4
0
File: dmxdev.c Project: 274914765/C
static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
{
    if (dmxdevfilter->state < DMXDEV_STATE_SET)
        return 0;

    dmxdevfilter->type = DMXDEV_TYPE_NONE;
    dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
    return 0;
}
Example #5
0
File: dmxdev.c Project: 274914765/C
/* 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);
    case DMXDEV_TYPE_PES:
        return filter->feed.ts->start_filtering(filter->feed.ts);
    default:
        return -EINVAL;
    }

    return 0;
}
Example #6
0
File: dmxdev.c Project: 274914765/C
/* 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;
}
Example #7
0
File: dmxdev.c Project: 274914765/C
static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
                 struct dmxdev_filter *dmxdevfilter,
                 struct dmx_sct_filter_params *params)
{
    dprintk("function : %s\n", __func__);

    dvb_dmxdev_filter_stop(dmxdevfilter);

    dmxdevfilter->type = DMXDEV_TYPE_SEC;
    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;
}
Example #8
0
File: dmxdev.c Project: 274914765/C
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;
    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;
}
Example #9
0
static int dvb_demux_open(struct inode *inode, struct file *file)
{
	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
	struct dmxdev *dmxdev=(struct 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=0;
	init_timer(&dmxdevfilter->timer);

	up(&dmxdev->mutex);
	return 0;
}
Example #10
0
File: dmxdev.c Project: 274914765/C
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 (!filter->buffer.data) {
        mem = vmalloc(filter->buffer.size);
        if (!mem)
            return -ENOMEM;
        spin_lock_irq(&filter->dev->lock);
        filter->buffer.data = mem;
        spin_unlock_irq(&filter->dev->lock);
    }

    dvb_ringbuffer_flush(&filter->buffer);

    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].type == DMXDEV_TYPE_SEC &&
                dmxdev->filter[i].params.sec.pid == para->pid) {
                *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",
                       __func__);
                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",
                       __func__);
                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],
               &para->filter.mask[1], DMX_FILTER_SIZE - 1);
        memcpy(&(*secfilter)->filter_mode[3],
               &para->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;
        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;

        ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
                              tsfeed,
                              dvb_dmxdev_ts_callback);
        if (ret < 0)
            return ret;

        (*tsfeed)->priv = 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;
}