static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, int non_blocking, char __user *buf, size_t count, loff_t *ppos) { size_t todo; ssize_t avail; ssize_t ret = 0; if (!src->data) return 0; if (src->error) { ret = src->error; dvb_ringbuffer_flush(src); return ret; } for (todo = count; todo > 0; todo -= ret) { if (non_blocking && dvb_ringbuffer_empty(src)) { ret = -EWOULDBLOCK; break; } ret = wait_event_interruptible(src->queue, !dvb_ringbuffer_empty(src) || (src->error != 0)); if (ret < 0) break; if (src->error) { ret = src->error; dvb_ringbuffer_flush(src); break; } avail = dvb_ringbuffer_avail(src); if (avail > todo) avail = todo; ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1); if (ret < 0) break; buf += ret; } return (count - todo) ? (count - todo) : ret; }
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; } dvb_ringbuffer_flush(&dmxdevfilter->buffer); 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 dvb_ringbuffer *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) { dvb_ringbuffer_flush(buffer); buffer->error = ret; } spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; }
static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsigned long size) { struct dvb_ringbuffer *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; dvb_ringbuffer_flush(buf); 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; }
void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) { unsigned long flags; spin_lock_irqsave(&rbuf->lock, flags); dvb_ringbuffer_flush(rbuf); spin_unlock_irqrestore(&rbuf->lock, flags); wake_up(&rbuf->queue); }
static int audio_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct ngene_channel *chan = dvbdev->priv; struct ngene *dev = chan->dev; struct ngene_channel *chan2 = &chan->dev->channel[2]; int ret; ret = dvb_generic_open(inode, file); if (ret < 0) return ret; dvb_ringbuffer_flush(&dev->ain_rbuf); chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; chan2->pBufferExchange = ain_exchange; ngene_command_stream_control(chan2->dev, chan2->number, 0x80, SMODE_AUDIO_CAPTURE, 0); return ret; }
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) { dvb_ringbuffer_flush(&dmxdevfilter->buffer); dmxdevfilter->buffer.error = ret; } 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 video_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct ngene_channel *chan = dvbdev->priv; struct ngene *dev = chan->dev; struct ngene_channel *chan0 = &chan->dev->channel[0]; int ret; ret = dvb_generic_open(inode, file); if (ret < 0) return ret; if ((file->f_flags & O_ACCMODE) != O_RDONLY) return ret; dvb_ringbuffer_flush(&dev->vin_rbuf); chan0->nBytesPerLine = 1920 * 2; chan0->nLines = 540; chan0->Capture1Length = 1920 * 2 * 540; chan0->pBufferExchange = vcap_exchange; chan0->itumode = 2; ngene_command_stream_control(chan0->dev, chan0->number, 0x80, SMODE_VIDEO_CAPTURE, 0); return ret; }
void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) { unsigned long flags; #ifdef LEXRA5280_VEC_PATCH unsigned long vflags; #endif //#ifdef LEXRA5280_VEC_PATCH #ifdef LEXRA5280_VEC_PATCH spin_lock_irqsave(&rbuf->lock, flags, vflags);//tdl for Lexra 5280 vector interrupts #else spin_lock_irqsave(&rbuf->lock, flags); #endif //#ifdef LEXRA5280_VEC_PATCH dvb_ringbuffer_flush(rbuf); #ifdef LEXRA5280_VEC_PATCH spin_unlock_irqrestore(&rbuf->lock, flags, vflags);//tdl for Lexra 5280 vector interrupts #else spin_unlock_irqrestore(&rbuf->lock, flags); #endif //#ifdef LEXRA5280_VEC_PATCH wake_up(&rbuf->queue); }
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], ¶->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; 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; }