media: dvb: Add support for monitoring scrambling bits

Query of scrambling bits and notification when these change
are required by some applications.

Change-Id: If39dccb712c6bb14f2e277c8919eb34798f84146
Signed-off-by: Hamad Kadmany <hkadmany@codeaurora.org>
This commit is contained in:
Hamad Kadmany
2013-05-13 18:56:06 +03:00
parent 6c81198143
commit d0abf313ca
5 changed files with 187 additions and 8 deletions
+5 -1
View File
@@ -75,7 +75,8 @@ enum dmx_success {
DMX_FIFO_ERROR, /* Receiver FIFO overrun */
DMX_MISSED_ERROR, /* Receiver missed packet */
DMX_OK_DECODER_BUF, /* Received OK, new ES data in decoder buffer */
DMX_OK_IDX /* Received OK, new index event */
DMX_OK_IDX, /* Received OK, new index event */
DMX_OK_SCRAMBLING_STATUS, /* Received OK, new scrambling status */
} ;
@@ -135,6 +136,7 @@ struct dmx_data_ready {
} marker;
struct dmx_index_event_info idx_event;
struct dmx_scrambling_status_event_info scrambling_bits;
};
};
@@ -250,6 +252,7 @@ struct dmx_ts_feed {
int (*ts_insertion_terminate)(struct dmx_ts_feed *feed);
int (*ts_insertion_insert_buffer)(struct dmx_ts_feed *feed,
char *data, size_t size);
int (*get_scrambling_bits)(struct dmx_ts_feed *feed, u8 *value);
};
/*--------------------------------------------------------------------------*/
@@ -300,6 +303,7 @@ struct dmx_section_feed {
struct dmx_secure_mode *sec_mode);
int (*oob_command) (struct dmx_section_feed *feed,
struct dmx_oob_command *cmd);
int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
};
/*--------------------------------------------------------------------------*/
+67 -2
View File
@@ -1796,6 +1796,35 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter,
return 0;
}
static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter,
struct dmx_scrambling_bits *scrambling_bits)
{
struct dmxdev_feed *feed;
if (!scrambling_bits ||
(filter->state != DMXDEV_STATE_GO))
return -EINVAL;
if (filter->type == DMXDEV_TYPE_SEC) {
if (filter->feed.sec.feed->get_scrambling_bits)
return filter->feed.sec.feed->get_scrambling_bits(
filter->feed.sec.feed,
&scrambling_bits->value);
return -EINVAL;
}
list_for_each_entry(feed, &filter->feed.ts, next) {
if (feed->pid == scrambling_bits->pid) {
if (feed->ts->get_scrambling_bits)
return feed->ts->get_scrambling_bits(feed->ts,
&scrambling_bits->value);
return -EINVAL;
}
}
return -EINVAL;
}
static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
{
struct ts_insertion_buffer *ts_buffer =
@@ -2519,6 +2548,13 @@ static int dvb_dmxdev_section_event_cb(struct dmx_section_filter *filter,
dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
spin_unlock(&dmxdevfilter->dev->lock);
wake_up_all(&dmxdevfilter->buffer.queue);
} else if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
event.params.scrambling_status =
dmx_data_ready->scrambling_bits;
dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
spin_unlock(&dmxdevfilter->dev->lock);
wake_up_all(&dmxdevfilter->buffer.queue);
} else {
spin_unlock(&dmxdevfilter->dev->lock);
}
@@ -2635,6 +2671,16 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed,
return 0;
}
if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
event.params.scrambling_status =
dmx_data_ready->scrambling_bits;
dvb_dmxdev_add_event(events, &event);
spin_unlock(&dmxdevfilter->dev->lock);
wake_up_all(&buffer->queue);
return 0;
}
if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
event.type = DMX_EVENT_NEW_ES_DATA;
event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
@@ -3938,6 +3984,15 @@ static int dvb_demux_do_ioctl(struct file *file,
mutex_unlock(&dmxdevfilter->mutex);
break;
case DMX_GET_SCRAMBLING_BITS:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_dmxdev_get_scrambling_bits(dmxdevfilter, parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
default:
ret = -EINVAL;
break;
@@ -4193,6 +4248,7 @@ static int dvb_dmxdev_dbgfs_print(struct seq_file *s, void *p)
struct dmxdev_filter *filter;
int active_count = 0;
struct dmx_buffer_status buffer_status;
struct dmx_scrambling_bits scrambling_bits;
const char *pes_feeds[] = {"DEC", "PES", "DVR", "REC"};
if (!dmxdev)
@@ -4209,23 +4265,32 @@ static int dvb_dmxdev_dbgfs_print(struct seq_file *s, void *p)
seq_printf(s, "type: SEC, ");
seq_printf(s, "PID %04d ",
filter->params.sec.pid);
scrambling_bits.pid = filter->params.sec.pid;
} else {
seq_printf(s, "type: %s, ",
pes_feeds[filter->params.pes.output]);
seq_printf(s, "PID: %04d ",
filter->params.pes.pid);
scrambling_bits.pid = filter->params.pes.pid;
}
dvb_dmxdev_get_scrambling_bits(filter,
&scrambling_bits);
if (0 == dvb_dmxdev_get_buffer_status(
filter, &buffer_status)) {
seq_printf(s, "size: %08d, ",
buffer_status.size);
seq_printf(s, "fullness: %08d, ",
buffer_status.fullness);
seq_printf(s, "error: %d\n",
seq_printf(s, "error: %d, ",
buffer_status.error);
seq_printf(s, "scramble: %d\n",
scrambling_bits.value);
} else {
seq_printf(s, "\n");
seq_printf(s, "scramble: %d\n",
scrambling_bits.value);
}
}
}
+73
View File
@@ -164,6 +164,11 @@ static inline u16 ts_pid(const u8 *buf)
return ((buf[1] & 0x1f) << 8) + buf[2];
}
static inline u16 ts_scrambling_ctrl(const u8 *buf)
{
return (buf[3] >> 6) & 0x3;
}
static inline u8 payload(const u8 *tsp)
{
if (!(tsp[3] & 0x10)) // no payload?
@@ -1284,6 +1289,32 @@ static inline int dvb_dmx_swfilter_buffer_check(
static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
const u8 *buf, const u8 timestamp[TIMESTAMP_LEN])
{
u16 pid = ts_pid(buf);
u8 scrambling_bits = ts_scrambling_ctrl(buf);
struct dmx_data_ready dmx_data_ready;
/*
* Notify on scrambling status change only when we move
* from clear (0) to non-clear and vise-versa
*/
if ((scrambling_bits && !feed->scrambling_bits) ||
(!scrambling_bits && feed->scrambling_bits)) {
dmx_data_ready.status = DMX_OK_SCRAMBLING_STATUS;
dmx_data_ready.data_length = 0;
dmx_data_ready.scrambling_bits.pid = pid;
dmx_data_ready.scrambling_bits.old_value =
feed->scrambling_bits;
dmx_data_ready.scrambling_bits.new_value = scrambling_bits;
if (feed->type == DMX_TYPE_SEC)
feed->data_ready_cb.sec(&feed->filter->filter,
&dmx_data_ready);
else
feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
}
feed->scrambling_bits = scrambling_bits;
switch (feed->type) {
case DMX_TYPE_TS:
if (!feed->feed.ts.is_filtering)
@@ -2044,6 +2075,7 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
}
feed->first_cc = 1;
feed->scrambling_bits = 0;
if ((feed->ts_type & TS_PACKET) &&
!(feed->ts_type & TS_PAYLOAD_ONLY)) {
@@ -2331,6 +2363,25 @@ static int dvbdmx_ts_feed_oob_cmd(struct dmx_ts_feed *ts_feed,
return ret;
}
static int dvbdmx_ts_get_scrambling_bits(struct dmx_ts_feed *ts_feed,
u8 *value)
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
spin_lock(&demux->lock);
if (!ts_feed->is_filtering) {
spin_unlock(&demux->lock);
return -EINVAL;
}
*value = feed->scrambling_bits;
spin_unlock(&demux->lock);
return 0;
}
static int dvbdmx_ts_insertion_insert_buffer(struct dmx_ts_feed *ts_feed,
char *data, size_t size)
{
@@ -2420,6 +2471,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
(*ts_feed)->notify_data_read = NULL;
(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
(*ts_feed)->ts_insertion_init = NULL;
(*ts_feed)->ts_insertion_terminate = NULL;
(*ts_feed)->ts_insertion_insert_buffer =
@@ -2586,6 +2638,7 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
dvbdmxfeed->feed.sec.secbufp = 0;
dvbdmxfeed->feed.sec.seclen = 0;
dvbdmxfeed->first_cc = 1;
dvbdmxfeed->scrambling_bits = 0;
if (!dvbdmx->start_feed) {
mutex_unlock(&dvbdmx->mutex);
@@ -2752,6 +2805,25 @@ static int dvbdmx_section_feed_oob_cmd(struct dmx_section_feed *section_feed,
return ret;
}
static int dvbdmx_section_get_scrambling_bits(
struct dmx_section_feed *section_feed, u8 *value)
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
struct dvb_demux *demux = feed->demux;
spin_lock(&demux->lock);
if (!section_feed->is_filtering) {
spin_unlock(&demux->lock);
return -EINVAL;
}
*value = feed->scrambling_bits;
spin_unlock(&demux->lock);
return 0;
}
static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
struct dmx_section_feed **feed,
dmx_section_cb callback)
@@ -2792,6 +2864,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
(*feed)->notify_data_read = NULL;
(*feed)->set_secure_mode = dmx_section_set_secure_mode;
(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
mutex_unlock(&dvbdmx->mutex);
return 0;
+2
View File
@@ -187,6 +187,8 @@ struct dvb_demux_feed {
int first_cc;
int pusi_seen; /* prevents feeding of garbage from previous section */
u8 scrambling_bits;
struct dvb_demux_rec_info *rec_info;
u64 prev_tsp_num;
u64 prev_stc;
+40 -5
View File
@@ -195,7 +195,7 @@ struct dmx_buffer_status {
/* write pointer offset in bytes */
unsigned int write_offset;
/* non-zero if data error occured */
/* non-zero if data error occurred */
int error;
};
@@ -237,7 +237,10 @@ enum dmx_event {
* (dmx_sct_filter_params) and no sections were
* received for the given time.
*/
DMX_EVENT_SECTION_TIMEOUT = 0x00000400
DMX_EVENT_SECTION_TIMEOUT = 0x00000400,
/* Scrambling bits change between clear and scrambled */
DMX_EVENT_SCRAMBLING_STATUS_CHANGE = 0x00000800
};
enum dmx_oob_cmd {
@@ -256,7 +259,7 @@ enum dmx_oob_cmd {
/* Discontinuity indicator was set */
#define DMX_FILTER_DISCONTINUITY_INDICATOR 0x02
/* PES legnth in PES header is not correct */
/* PES length in PES header is not correct */
#define DMX_FILTER_PES_LENGTH_ERROR 0x04
@@ -412,7 +415,7 @@ struct dmx_index_event_info {
/*
* The PID the index entry belongs to.
* In case of recording filter, multiple PIDs may exist in the same
* filter through DMX_ADD_PID ioctl and each can be indexed seperatly.
* filter through DMX_ADD_PID ioctl and each can be indexed separately.
*/
__u16 pid;
@@ -423,7 +426,7 @@ struct dmx_index_event_info {
__u64 match_tsp_num;
/*
* The TS packet number in the recorded data preceeding
* The TS packet number in the recorded data preceding
* match_tsp_num and has PUSI set.
*/
__u64 last_pusi_tsp_num;
@@ -432,6 +435,23 @@ struct dmx_index_event_info {
__u64 stc;
};
/* Scrambling information associated with DMX_EVENT_SCRAMBLING_STATUS_CHANGE */
struct dmx_scrambling_status_event_info {
/*
* The PID which its scrambling bit status changed.
* In case of recording filter, multiple PIDs may exist in the same
* filter through DMX_ADD_PID ioctl, each may have
* different scrambling bits status.
*/
__u16 pid;
/* old value of scrambling bits */
__u8 old_value;
/* new value of scrambling bits */
__u8 new_value;
};
/*
* Filter's event returned through DMX_GET_EVENT.
* poll with POLLPRI would block until events are available.
@@ -447,6 +467,7 @@ struct dmx_filter_event {
struct dmx_es_data_event_info es_data;
struct dmx_marker_event_info marker;
struct dmx_index_event_info index;
struct dmx_scrambling_status_event_info scrambling_status;
} params;
};
@@ -754,6 +775,19 @@ struct dmx_abort_ts_insertion {
__u32 identifier;
};
struct dmx_scrambling_bits {
/*
* The PID to return its scrambling bit value.
* In case of recording filter, multiple PIDs may exist in the same
* filter through DMX_ADD_PID ioctl, each may have different
* scrambling bits status.
*/
__u16 pid;
/* Current value of scrambling bits: 0, 1, 2 or 3 */
__u8 value;
};
#define DMX_START _IO('o', 41)
#define DMX_STOP _IO('o', 42)
#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
@@ -784,5 +818,6 @@ struct dmx_abort_ts_insertion {
#define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
#define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
#define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
#define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
#endif /*_DVBDMX_H_*/