forked from rubenslte/android_kernel_samsung_msm8226
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:
@@ -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);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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_*/
|
||||
|
||||
Reference in New Issue
Block a user