static void tsif_notify(void *data) { struct tsif_chrdev *the_dev = data; tsif_get_state(the_dev->cookie, &the_dev->ri, &the_dev->wi, &the_dev->state); wake_up_interruptible(&the_dev->wq_read); }
/** * Demux thread function handling data from specific TSIF. * * @arg: TSIF number */ static int mpq_dmx_tsif_thread(void *arg) { struct mpq_demux *mpq_demux; struct tsif_driver_info *tsif_driver; size_t packets = 0; int tsif = (int)arg; int ret; do { ret = wait_event_interruptible( mpq_dmx_tsif_info.tsif[tsif].wait_queue, (atomic_read( &mpq_dmx_tsif_info.tsif[tsif].data_cnt) != 0) || kthread_should_stop()); if ((ret < 0) || kthread_should_stop()) { MPQ_DVB_DBG_PRINT("%s: exit\n", __func__); break; } if (mutex_lock_interruptible( &mpq_dmx_tsif_info.tsif[tsif].mutex)) return -ERESTARTSYS; tsif_driver = &(mpq_dmx_tsif_info.tsif[tsif].tsif_driver); mpq_demux = mpq_dmx_tsif_info.tsif[tsif].mpq_demux; /* Check if driver handler is still valid */ if (tsif_driver->tsif_handler == NULL) { mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex); MPQ_DVB_DBG_PRINT( "%s: tsif was detached\n", __func__); continue; } tsif_get_state( tsif_driver->tsif_handler, &(tsif_driver->ri), &(tsif_driver->wi), &(tsif_driver->state)); if ((tsif_driver->wi == tsif_driver->ri) || (tsif_driver->state == tsif_state_stopped) || (tsif_driver->state == tsif_state_error)) { mpq_demux->hw_notification_size = 0; mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex); MPQ_DVB_DBG_PRINT( "%s: TSIF invalid state %d, %d, %d\n", __func__, tsif_driver->state, tsif_driver->wi, tsif_driver->ri); continue; } atomic_dec(&mpq_dmx_tsif_info.tsif[tsif].data_cnt); if (tsif_driver->wi > tsif_driver->ri) { packets = (tsif_driver->wi - tsif_driver->ri); mpq_demux->hw_notification_size = packets; dvb_dmx_swfilter_format( &mpq_demux->demux, (tsif_driver->data_buffer + (tsif_driver->ri * TSIF_PKT_SIZE)), (packets * TSIF_PKT_SIZE), DMX_TSP_FORMAT_192_TAIL); tsif_driver->ri = (tsif_driver->ri + packets) % tsif_driver->buffer_size; tsif_reclaim_packets( tsif_driver->tsif_handler, tsif_driver->ri); } else { /* * wi < ri, means wraparound on cyclic buffer. * Handle in two stages. */ packets = (tsif_driver->buffer_size - tsif_driver->ri); mpq_demux->hw_notification_size = packets; dvb_dmx_swfilter_format( &mpq_demux->demux, (tsif_driver->data_buffer + (tsif_driver->ri * TSIF_PKT_SIZE)), (packets * TSIF_PKT_SIZE), DMX_TSP_FORMAT_192_TAIL); /* tsif_driver->ri should be 0 after this */ tsif_driver->ri = (tsif_driver->ri + packets) % tsif_driver->buffer_size; packets = tsif_driver->wi; if (packets > 0) { mpq_demux->hw_notification_size += packets; dvb_dmx_swfilter_format( &mpq_demux->demux, (tsif_driver->data_buffer + (tsif_driver->ri * TSIF_PKT_SIZE)), (packets * TSIF_PKT_SIZE), DMX_TSP_FORMAT_192_TAIL); tsif_driver->ri = (tsif_driver->ri + packets) % tsif_driver->buffer_size; } tsif_reclaim_packets( tsif_driver->tsif_handler, tsif_driver->ri); } mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex); } while (1); return 0; }
static ssize_t tsif_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { int avail = 0; int wi; #ifdef FEATURE_TSIF_DEBUG_MSG pr_info("[%s] !!!!!!!\n", __func__); //g_packet_read_cnt ++; #endif struct tsif_chrdev *the_dev = filp->private_data; tsif_get_state(the_dev->cookie, &the_dev->ri, &the_dev->wi, &the_dev->state); /* consistency check */ if (the_dev->ri != (the_dev->rptr / TSIF_PKT_SIZE)) { dev_err(the_dev->dev, "%s: inconsistent read pointers: ri %d rptr %d\n", __func__, the_dev->ri, the_dev->rptr); the_dev->rptr = the_dev->ri * TSIF_PKT_SIZE; } /* ri == wi if no data */ if (the_dev->ri == the_dev->wi) { /* shall I block waiting for data? */ if (filp->f_flags & O_NONBLOCK) { if (the_dev->state == tsif_state_running) { return -EAGAIN; } else { /* not running -> EOF */ return 0; } } #if 0 if (wait_event_interruptible(the_dev->wq_read, (the_dev->ri != the_dev->wi) || (the_dev->state != tsif_state_running))) { /* got signal -> tell FS to handle it */ return -ERESTARTSYS; } #else if (wait_event_interruptible_timeout(the_dev->wq_read, ((the_dev->ri != the_dev->wi) || (the_dev->state != tsif_state_running)),msecs_to_jiffies(50))) { /* got signal -> tell FS to handle it */ return -ERESTARTSYS; } #endif if (the_dev->ri == the_dev->wi) { /* still no data -> EOF */ return 0; } } /* contiguous chunk last up to wi or end of buffer */ wi = (the_dev->wi > the_dev->ri) ? the_dev->wi : the_dev->buf_size_packets; avail = min(wi * TSIF_PKT_SIZE - the_dev->rptr, count); #ifdef FEATURE_TSIF_DEBUG_MSG pr_info("[%s] size [%d] !!!!!!!\n", __func__, avail); #endif //if (copy_to_user(buf, the_dev->data_buffer + the_dev->rptr, avail)) // return -EFAULT; #ifdef CONFIG_SKY_TDMB_TSIF_IF tdmb_tsif_data_parser(buf, the_dev->data_buffer + the_dev->rptr, avail); #endif the_dev->rptr = (the_dev->rptr + avail) % (TSIF_PKT_SIZE * the_dev->buf_size_packets); the_dev->ri = the_dev->rptr / TSIF_PKT_SIZE; *f_pos += avail; tsif_reclaim_packets(the_dev->cookie, the_dev->ri); return avail; }