capmt/cwc/mpegts: change emm processing
This commit is contained in:
parent
8c4597022b
commit
e044b1f817
9 changed files with 342 additions and 115 deletions
|
@ -73,15 +73,33 @@ typedef struct descrambler_table {
|
|||
/**
|
||||
* List of CA ids
|
||||
*/
|
||||
#define CAID_REMOVE_ME ((uint16_t)-1)
|
||||
|
||||
typedef struct caid {
|
||||
LIST_ENTRY(caid) link;
|
||||
|
||||
uint8_t delete_me;
|
||||
uint16_t pid;
|
||||
uint16_t caid;
|
||||
uint32_t providerid;
|
||||
|
||||
} caid_t;
|
||||
|
||||
/**
|
||||
* List of EMM subscribers
|
||||
*/
|
||||
#define EMM_PID_UNKNOWN ((uint16_t)-1)
|
||||
|
||||
typedef struct descrambler_emm {
|
||||
TAILQ_ENTRY(descrambler_emm) link;
|
||||
|
||||
uint16_t caid;
|
||||
uint16_t pid;
|
||||
unsigned int to_be_removed:1;
|
||||
|
||||
descrambler_section_callback_t callback;
|
||||
void *opaque;
|
||||
} descrambler_emm_t;
|
||||
|
||||
/**
|
||||
* cards for which emm updates are handled
|
||||
*/
|
||||
|
@ -112,8 +130,14 @@ int descrambler_open_pid ( struct mpegts_mux *mux, void *opaque, int pid,
|
|||
descrambler_section_callback_t callback );
|
||||
int descrambler_close_pid ( struct mpegts_mux *mux, void *opaque, int pid );
|
||||
void descrambler_flush_tables ( struct mpegts_mux *mux );
|
||||
void descrambler_cat_data ( struct mpegts_mux *mux, const uint8_t *data, int len );
|
||||
int descrambler_open_emm ( struct mpegts_mux *mux, void *opaque, int caid,
|
||||
descrambler_section_callback_t callback );
|
||||
int descrambler_close_emm ( struct mpegts_mux *mux, void *opaque, int caid );
|
||||
|
||||
const char *descrambler_caid2name( uint16_t caid );
|
||||
uint16_t descrambler_name2caid ( const char *str );
|
||||
|
||||
card_type_t detect_card_type ( const uint16_t caid );
|
||||
|
||||
#endif /* __TVH_DESCRAMBLER_H__ */
|
||||
|
|
|
@ -1281,7 +1281,7 @@ capmt_thread(void *aux)
|
|||
memset(&capmt->capmt_demuxes, 0, sizeof(capmt->capmt_demuxes));
|
||||
|
||||
/* Accessible */
|
||||
if (!access(capmt->capmt_sockfile, R_OK | W_OK))
|
||||
if (capmt->capmt_sockfile && !access(capmt->capmt_sockfile, R_OK | W_OK))
|
||||
capmt_set_connected(capmt, 1);
|
||||
else
|
||||
capmt_set_connected(capmt, 0);
|
||||
|
@ -1392,7 +1392,7 @@ capmt_table_input(void *opaque, int pid, const uint8_t *data, int len)
|
|||
dmx_filter_t *f;
|
||||
|
||||
/* Validate */
|
||||
if (len > 4096) return;
|
||||
if (data == NULL || len > 4096) return;
|
||||
|
||||
for (demux_index = 0; demux_index < capmt->capmt_demuxes.max; demux_index++) {
|
||||
cf = &capmt->capmt_demuxes.filters[demux_index];
|
||||
|
|
|
@ -171,6 +171,17 @@ typedef struct cwc_message {
|
|||
} cwc_message_t;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct cwc;
|
||||
struct cs_card_data;
|
||||
typedef struct cwc_opaque_emm {
|
||||
struct cs_card_data *pcard;
|
||||
struct cwc *cwc;
|
||||
mpegts_mux_t *mux;
|
||||
} cwc_opaque_emm_t;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -198,6 +209,8 @@ typedef struct cs_card_data {
|
|||
|
||||
uint8_t cwc_ua[8];
|
||||
|
||||
cwc_opaque_emm_t cwc_opaque;
|
||||
|
||||
} cs_card_data_t;
|
||||
|
||||
/**
|
||||
|
@ -282,15 +295,15 @@ typedef struct cwc {
|
|||
*/
|
||||
|
||||
static void cwc_service_destroy(th_descrambler_t *td);
|
||||
void cwc_emm_conax(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_irdeto(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_dre(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_seca(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_nagra(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_nds(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_cryptoworks(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_bulcrypt(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len);
|
||||
void cwc_emm_conax(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_irdeto(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_dre(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_seca(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_nagra(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_nds(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_cryptoworks(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
void cwc_emm_bulcrypt(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1223,8 +1236,9 @@ cwc_thread(void *aux)
|
|||
}
|
||||
|
||||
while((cd = LIST_FIRST(&cwc->cwc_cards)) != NULL) {
|
||||
free(cd->cwc_providers);
|
||||
LIST_REMOVE(cd, cs_card);
|
||||
descrambler_close_emm(cd->cwc_opaque.mux, &cd->cwc_opaque, cd->cwc_caid);
|
||||
free(cd->cwc_providers);
|
||||
free(cd);
|
||||
}
|
||||
free((void *)cwc->cwc_password);
|
||||
|
@ -1285,61 +1299,67 @@ cwc_emm_cache_lookup(cwc_t *cwc, uint32_t crc)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id)
|
||||
static void
|
||||
cwc_emm(void *opaque, int pid, const uint8_t *data, int len)
|
||||
{
|
||||
cwc_t *cwc;
|
||||
|
||||
cwc_opaque_emm_t *o = opaque;
|
||||
struct cs_card_data *pcard;
|
||||
pthread_mutex_lock(&cwc_mutex);
|
||||
cwc_t *cwc;
|
||||
void *ca_update_id;
|
||||
|
||||
TAILQ_FOREACH(cwc, &cwcs, cwc_link) {
|
||||
LIST_FOREACH(pcard,&cwc->cwc_cards, cs_card){
|
||||
if(pcard->cwc_caid == caid &&
|
||||
cwc->cwc_forward_emm && cwc->cwc_writer_running) {
|
||||
if (cwc->cwc_emmex) {
|
||||
if (cwc->cwc_update_id != ca_update_id) {
|
||||
int64_t delta = getmonoclock() - cwc->cwc_update_time;
|
||||
if (delta < 25000000UL) /* 25 seconds */
|
||||
continue;
|
||||
}
|
||||
cwc->cwc_update_time = getmonoclock();
|
||||
}
|
||||
cwc->cwc_update_id = ca_update_id;
|
||||
switch (pcard->cwc_card_type) {
|
||||
case CARD_CONAX:
|
||||
cwc_emm_conax(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_IRDETO:
|
||||
cwc_emm_irdeto(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_SECA:
|
||||
cwc_emm_seca(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_VIACCESS:
|
||||
cwc_emm_viaccess(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_DRE:
|
||||
cwc_emm_dre(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_NAGRA:
|
||||
cwc_emm_nagra(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_NDS:
|
||||
cwc_emm_nds(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_CRYPTOWORKS:
|
||||
cwc_emm_cryptoworks(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_BULCRYPT:
|
||||
cwc_emm_bulcrypt(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
if (data == NULL) { /* end-of-data */
|
||||
o->mux = NULL;
|
||||
return;
|
||||
}
|
||||
if (o->mux == NULL)
|
||||
return;
|
||||
pthread_mutex_lock(&cwc_mutex);
|
||||
pcard = o->pcard;
|
||||
cwc = o->cwc;
|
||||
ca_update_id = o->mux;
|
||||
if (cwc->cwc_forward_emm && cwc->cwc_writer_running) {
|
||||
if (cwc->cwc_emmex) {
|
||||
if (cwc->cwc_update_id != ca_update_id) {
|
||||
int64_t delta = getmonoclock() - cwc->cwc_update_time;
|
||||
if (delta < 25000000UL) /* 25 seconds */
|
||||
goto end_of_job;
|
||||
}
|
||||
cwc->cwc_update_time = getmonoclock();
|
||||
}
|
||||
cwc->cwc_update_id = ca_update_id;
|
||||
switch (pcard->cwc_card_type) {
|
||||
case CARD_CONAX:
|
||||
cwc_emm_conax(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_IRDETO:
|
||||
cwc_emm_irdeto(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_SECA:
|
||||
cwc_emm_seca(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_VIACCESS:
|
||||
cwc_emm_viaccess(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_DRE:
|
||||
cwc_emm_dre(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_NAGRA:
|
||||
cwc_emm_nagra(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_NDS:
|
||||
cwc_emm_nds(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_CRYPTOWORKS:
|
||||
cwc_emm_cryptoworks(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_BULCRYPT:
|
||||
cwc_emm_bulcrypt(cwc, pcard, data, len);
|
||||
break;
|
||||
case CARD_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
end_of_job:
|
||||
pthread_mutex_unlock(&cwc_mutex);
|
||||
}
|
||||
|
||||
|
@ -1348,7 +1368,7 @@ cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id)
|
|||
* conax emm handler
|
||||
*/
|
||||
void
|
||||
cwc_emm_conax(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_conax(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
if (data[0] == 0x82) {
|
||||
int i;
|
||||
|
@ -1367,7 +1387,7 @@ cwc_emm_conax(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
|||
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
|
||||
*/
|
||||
void
|
||||
cwc_emm_irdeto(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_irdeto(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int emm_mode = data[3] >> 3;
|
||||
int emm_len = data[3] & 0x07;
|
||||
|
@ -1400,7 +1420,7 @@ cwc_emm_irdeto(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
|||
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
|
||||
*/
|
||||
void
|
||||
cwc_emm_seca(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_seca(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int match = 0;
|
||||
|
||||
|
@ -1432,7 +1452,7 @@ cwc_emm_seca(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
|||
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
|
||||
*/
|
||||
static
|
||||
uint8_t * nano_start(uint8_t * data)
|
||||
const uint8_t * nano_start(const uint8_t * data)
|
||||
{
|
||||
switch(data[0]) {
|
||||
case 0x88: return &data[8];
|
||||
|
@ -1446,14 +1466,14 @@ uint8_t * nano_start(uint8_t * data)
|
|||
}
|
||||
|
||||
static
|
||||
uint8_t * nano_checknano90fromnano(uint8_t * data)
|
||||
const uint8_t * nano_checknano90fromnano(const uint8_t * data)
|
||||
{
|
||||
if(data && data[0]==0x90 && data[1]==0x03) return data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
uint8_t * nano_checknano90(uint8_t * data)
|
||||
const uint8_t * nano_checknano90(const uint8_t * data)
|
||||
{
|
||||
return nano_checknano90fromnano(nano_start(data));
|
||||
}
|
||||
|
@ -1488,7 +1508,7 @@ int sort_nanos(uint8_t *dest, const uint8_t *src, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int via_provider_id(uint8_t * data)
|
||||
static int via_provider_id(const uint8_t * data)
|
||||
{
|
||||
const uint8_t * tmp;
|
||||
tmp = nano_checknano90(data);
|
||||
|
@ -1498,7 +1518,7 @@ static int via_provider_id(uint8_t * data)
|
|||
|
||||
|
||||
void
|
||||
cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int mlen)
|
||||
cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int mlen)
|
||||
{
|
||||
/* Get SCT len */
|
||||
int len = 3 + ((data[1] & 0x0f) << 8) + data[2];
|
||||
|
@ -1552,7 +1572,7 @@ cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int mlen
|
|||
if (!match) break;
|
||||
|
||||
uint8_t * tmp = alloca(len + cwc->cwc_viaccess_emm.shared_len);
|
||||
uint8_t * ass = nano_start(data);
|
||||
const uint8_t * ass = nano_start(data);
|
||||
len -= (ass - data);
|
||||
if((data[6] & 2) == 0) {
|
||||
int addrlen = len - 8;
|
||||
|
@ -1570,31 +1590,31 @@ cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int mlen
|
|||
int l = cwc->cwc_viaccess_emm.shared_len - (ass - cwc->cwc_viaccess_emm.shared_emm);
|
||||
memcpy(&tmp[len], ass, l); len += l;
|
||||
|
||||
ass = (uint8_t*) alloca(len+7);
|
||||
if(ass) {
|
||||
uint8_t *ass2 = (uint8_t*) alloca(len+7);
|
||||
if(ass2) {
|
||||
uint32_t crc;
|
||||
|
||||
memcpy(ass, data, 7);
|
||||
if (sort_nanos(ass + 7, tmp, len)) {
|
||||
memcpy(ass2, data, 7);
|
||||
if (sort_nanos(ass2 + 7, tmp, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set SCT len */
|
||||
len += 4;
|
||||
ass[1] = (len>>8) | 0x70;
|
||||
ass[2] = len & 0xff;
|
||||
ass2[1] = (len>>8) | 0x70;
|
||||
ass2[2] = len & 0xff;
|
||||
len += 3;
|
||||
|
||||
crc = tvh_crc32(ass, len, 0xffffffff);
|
||||
crc = tvh_crc32(ass2, len, 0xffffffff);
|
||||
if (!cwc_emm_cache_lookup(cwc, crc)) {
|
||||
tvhlog(LOG_DEBUG, "cwc",
|
||||
"Send EMM "
|
||||
"%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x"
|
||||
"...%02x.%02x.%02x.%02x",
|
||||
ass[0], ass[1], ass[2], ass[3],
|
||||
ass[4], ass[5], ass[6], ass[7],
|
||||
ass[len-4], ass[len-3], ass[len-2], ass[len-1]);
|
||||
cwc_send_msg(cwc, ass, len, 0, 1, 0, 0);
|
||||
ass2[0], ass2[1], ass2[2], ass2[3],
|
||||
ass2[4], ass2[5], ass2[6], ass2[7],
|
||||
ass2[len-4], ass2[len-3], ass2[len-2], ass2[len-1]);
|
||||
cwc_send_msg(cwc, ass2, len, 0, 1, 0, 0);
|
||||
cwc_emm_cache_insert(cwc, crc);
|
||||
}
|
||||
}
|
||||
|
@ -1622,6 +1642,9 @@ cwc_table_input(void *opaque, int pid, const uint8_t *data, int len)
|
|||
char chaninfo[32];
|
||||
caid_t *c;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (ct->td_keystate == DS_IDLE)
|
||||
return;
|
||||
|
||||
|
@ -1754,7 +1777,7 @@ cwc_table_input(void *opaque, int pid, const uint8_t *data, int len)
|
|||
* dre emm handler
|
||||
*/
|
||||
void
|
||||
cwc_emm_dre(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_dre(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int match = 0;
|
||||
|
||||
|
@ -1779,7 +1802,7 @@ cwc_emm_dre(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
|||
}
|
||||
|
||||
void
|
||||
cwc_emm_nagra(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_nagra(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int match = 0;
|
||||
unsigned char hexserial[4];
|
||||
|
@ -1801,7 +1824,7 @@ cwc_emm_nagra(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
|||
}
|
||||
|
||||
void
|
||||
cwc_emm_nds(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_nds(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int match = 0;
|
||||
int i;
|
||||
|
@ -1825,7 +1848,7 @@ cwc_emm_nds(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
|||
}
|
||||
|
||||
void
|
||||
cwc_emm_cryptoworks(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_cryptoworks(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int match = 0;
|
||||
|
||||
|
@ -1886,7 +1909,7 @@ cwc_emm_cryptoworks(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int l
|
|||
}
|
||||
|
||||
void
|
||||
cwc_emm_bulcrypt(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len)
|
||||
cwc_emm_bulcrypt(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len)
|
||||
{
|
||||
int match = 0;
|
||||
|
||||
|
@ -2016,6 +2039,40 @@ cwc_destroy(cwc_t *cwc)
|
|||
pthread_cond_signal(&cwc->cwc_cond);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
cwc_caid_update(mpegts_mux_t *mux, uint16_t caid, uint16_t pid, int valid)
|
||||
{
|
||||
cwc_t *cwc;
|
||||
struct cs_card_data *pcard;
|
||||
|
||||
tvhtrace("cwc",
|
||||
"caid update event - mux %p caid %04x (%i) pid %04x (%i) valid %i",
|
||||
mux, caid, caid, pid, pid, valid);
|
||||
pthread_mutex_lock(&cwc_mutex);
|
||||
TAILQ_FOREACH(cwc, &cwcs, cwc_link) {
|
||||
if (cwc->cwc_running) {
|
||||
LIST_FOREACH(pcard, &cwc->cwc_cards, cs_card) {
|
||||
if (pcard->cwc_caid == caid) {
|
||||
if (pcard->cwc_opaque.mux != mux) continue;
|
||||
if (valid) {
|
||||
pcard->cwc_opaque.cwc = cwc;
|
||||
pcard->cwc_opaque.pcard = pcard;
|
||||
pcard->cwc_opaque.mux = mux;
|
||||
descrambler_open_emm(mux, &pcard->cwc_opaque, caid, cwc_emm);
|
||||
} else {
|
||||
pcard->cwc_opaque.mux = NULL;
|
||||
descrambler_close_emm(mux, &pcard->cwc_opaque, caid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&cwc_mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
#ifndef CWC_H_
|
||||
#define CWC_H_
|
||||
|
||||
struct mpegts_mux;
|
||||
|
||||
void cwc_init(void);
|
||||
|
||||
void cwc_done(void);
|
||||
|
||||
void cwc_service_start(struct service *t);
|
||||
|
||||
void cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id);
|
||||
void cwc_caid_update(struct mpegts_mux *mux,
|
||||
uint16_t caid, uint16_t pid, int valid);
|
||||
|
||||
#endif /* CWC_H_ */
|
||||
|
|
|
@ -205,6 +205,8 @@ descrambler_open_pid( mpegts_mux_t *mux, void *opaque, int pid,
|
|||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
|
||||
if (mux == NULL)
|
||||
return 0;
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(dt, &mux->mm_descrambler_tables, link) {
|
||||
if (dt->table->mt_pid == pid) {
|
||||
|
@ -228,6 +230,7 @@ descrambler_open_pid( mpegts_mux_t *mux, void *opaque, int pid,
|
|||
ds->opaque = opaque;
|
||||
TAILQ_INSERT_TAIL(&dt->sections, ds, link);
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
tvhtrace("descrambler", "open pid %04X (%i)", pid, pid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -237,6 +240,8 @@ descrambler_close_pid( mpegts_mux_t *mux, void *opaque, int pid )
|
|||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
|
||||
if (mux == NULL)
|
||||
return 0;
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(dt, &mux->mm_descrambler_tables, link) {
|
||||
if (dt->table->mt_pid == pid) {
|
||||
|
@ -250,6 +255,7 @@ descrambler_close_pid( mpegts_mux_t *mux, void *opaque, int pid )
|
|||
free(dt);
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
tvhtrace("descrambler", "close pid %04X (%i)", pid, pid);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +270,11 @@ descrambler_flush_tables( mpegts_mux_t *mux )
|
|||
{
|
||||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
descrambler_emm_t *emm;
|
||||
|
||||
if (mux == NULL)
|
||||
return;
|
||||
tvhtrace("descrambler", "flush tables for %p", mux);
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
while ((dt = TAILQ_FIRST(&mux->mm_descrambler_tables)) != NULL) {
|
||||
while ((ds = TAILQ_FIRST(&dt->sections)) != NULL) {
|
||||
|
@ -275,9 +285,151 @@ descrambler_flush_tables( mpegts_mux_t *mux )
|
|||
mpegts_table_destroy(dt->table);
|
||||
free(dt);
|
||||
}
|
||||
while ((emm = TAILQ_FIRST(&mux->mm_descrambler_emms)) != NULL) {
|
||||
TAILQ_REMOVE(&mux->mm_descrambler_emms, emm, link);
|
||||
free(emm);
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
}
|
||||
|
||||
void
|
||||
descrambler_cat_data( mpegts_mux_t *mux, const uint8_t *data, int len )
|
||||
{
|
||||
descrambler_emm_t *emm;
|
||||
uint8_t dtag, dlen;
|
||||
uint16_t caid = 0, pid = 0;
|
||||
descrambler_section_callback_t callback = NULL;
|
||||
void *opaque = NULL;
|
||||
TAILQ_HEAD(,descrambler_emm) removing;
|
||||
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link)
|
||||
emm->to_be_removed = 1;
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
while (len > 2) {
|
||||
if (len > 2) {
|
||||
dtag = *data++;
|
||||
dlen = *data++;
|
||||
len -= 2;
|
||||
if (dtag != DVB_DESC_CA || len < 4 || dlen < 4)
|
||||
goto next;
|
||||
caid = (data[0] << 8) | data[1];
|
||||
pid = ((data[2] << 8) | data[3]) & 0x1fff;
|
||||
if (pid == 0)
|
||||
goto next;
|
||||
#if ENABLE_CWC
|
||||
cwc_caid_update(mux, caid, pid, 1);
|
||||
#endif
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link)
|
||||
if (emm->caid == caid) {
|
||||
emm->to_be_removed = 0;
|
||||
if (emm->pid == EMM_PID_UNKNOWN) {
|
||||
tvhtrace("descrambler", "attach emm caid %04X (%i) pid %04X (%i)", caid, caid, pid, pid);
|
||||
emm->pid = pid;
|
||||
callback = emm->callback;
|
||||
opaque = emm->opaque;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
if (emm)
|
||||
descrambler_open_pid(mux, opaque, pid, callback);
|
||||
next:
|
||||
data += dlen;
|
||||
len -= dlen;
|
||||
}
|
||||
}
|
||||
TAILQ_INIT(&removing);
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link)
|
||||
if (emm->to_be_removed) {
|
||||
TAILQ_REMOVE(&mux->mm_descrambler_emms, emm, link);
|
||||
TAILQ_INSERT_TAIL(&removing, emm, link);
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
while ((emm = TAILQ_FIRST(&removing)) != NULL) {
|
||||
if (emm->pid != EMM_PID_UNKNOWN) {
|
||||
caid = emm->caid;
|
||||
pid = emm->pid;
|
||||
tvhtrace("descrambler", "close emm caid %04X (%i) pid %04X (%i)", caid, caid, pid, pid);
|
||||
descrambler_close_pid(mux, emm->opaque, pid);
|
||||
#if ENABLE_CWC
|
||||
cwc_caid_update(mux, caid, pid, 0);
|
||||
#endif
|
||||
}
|
||||
TAILQ_REMOVE(&removing, emm, link);
|
||||
free(emm);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
descrambler_open_emm( mpegts_mux_t *mux, void *opaque, int caid,
|
||||
descrambler_section_callback_t callback )
|
||||
{
|
||||
descrambler_emm_t *emm;
|
||||
caid_t *c;
|
||||
int pid = EMM_PID_UNKNOWN;
|
||||
|
||||
if (mux == NULL)
|
||||
return 0;
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) {
|
||||
if (emm->caid == caid && emm->opaque == opaque) {
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
emm = calloc(1, sizeof(*emm));
|
||||
emm->caid = caid;
|
||||
emm->pid = EMM_PID_UNKNOWN;
|
||||
emm->opaque = opaque;
|
||||
emm->callback = callback;
|
||||
LIST_FOREACH(c, &mux->mm_descrambler_caids, link) {
|
||||
if (c->caid == caid) {
|
||||
emm->pid = pid = c->pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&mux->mm_descrambler_emms, emm, link);
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
if (pid != EMM_PID_UNKNOWN) {
|
||||
tvhtrace("descrambler",
|
||||
"attach emm caid %04X (%i) pid %04X (%i) - direct",
|
||||
caid, caid, pid, pid);
|
||||
descrambler_open_pid(mux, opaque, pid, callback);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
descrambler_close_emm( mpegts_mux_t *mux, void *opaque, int caid )
|
||||
{
|
||||
descrambler_emm_t *emm;
|
||||
int pid;
|
||||
|
||||
if (mux == NULL)
|
||||
return 0;
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link)
|
||||
if (emm->caid == caid && emm->opaque == opaque)
|
||||
break;
|
||||
if (!emm) {
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 0;
|
||||
}
|
||||
TAILQ_REMOVE(&mux->mm_descrambler_emms, emm, link);
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
caid = emm->caid;
|
||||
pid = emm->pid;
|
||||
free(emm);
|
||||
if (pid != EMM_PID_UNKNOWN) {
|
||||
tvhtrace("descrambler", "close emm caid %04X (%i) pid %04X (%i) - direct", caid, caid, pid, pid);
|
||||
descrambler_close_pid(mux, opaque, pid);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: might actually put const char* into caid_t
|
||||
const char *
|
||||
descrambler_caid2name(uint16_t caid)
|
||||
|
|
|
@ -347,7 +347,9 @@ struct mpegts_mux
|
|||
LIST_HEAD(, mpegts_table) mm_tables;
|
||||
TAILQ_HEAD(, mpegts_table) mm_table_queue;
|
||||
|
||||
LIST_HEAD(, caid) mm_descrambler_caids;
|
||||
TAILQ_HEAD(, descrambler_table) mm_descrambler_tables;
|
||||
TAILQ_HEAD(, descrambler_emm) mm_descrambler_emms;
|
||||
pthread_mutex_t mm_descrambler_lock;
|
||||
|
||||
/*
|
||||
|
|
|
@ -618,20 +618,6 @@ dvb_pat_callback
|
|||
/*
|
||||
* CAT processing
|
||||
*/
|
||||
|
||||
// TODO: might be a better way of handling this
|
||||
#include "descrambler/cwc.h"
|
||||
static int
|
||||
dvb_ca_callback
|
||||
(mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
|
||||
{
|
||||
(void)dvb_table_begin(mt, ptr, len, tableid, 0, 0, NULL, NULL, NULL, NULL);
|
||||
#if ENABLE_CWC
|
||||
cwc_emm((uint8_t*)ptr, len, (uintptr_t)mt->mt_opaque, mt->mt_mux);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dvb_cat_callback
|
||||
(mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
|
||||
|
@ -649,6 +635,9 @@ dvb_cat_callback
|
|||
ptr += 5;
|
||||
len -= 5;
|
||||
|
||||
/* Send CAT data for descramblers */
|
||||
descrambler_cat_data(mm, ptr, len);
|
||||
|
||||
while(len > 2) {
|
||||
dtag = *ptr++;
|
||||
dlen = *ptr++;
|
||||
|
@ -656,13 +645,12 @@ dvb_cat_callback
|
|||
|
||||
switch(dtag) {
|
||||
case DVB_DESC_CA:
|
||||
caid = ( ptr[0] << 8) | ptr[1];
|
||||
pid = ((ptr[2] & 0x1f) << 8) | ptr[3];
|
||||
tvhdebug("cat", " caid %04X (%d) pid %04X (%d)",
|
||||
(uint16_t)caid, (uint16_t)caid, pid, pid);
|
||||
if(pid != 0)
|
||||
mpegts_table_add(mm, 0, 0, dvb_ca_callback,
|
||||
(void*)caid, "ca", MT_FULL | MT_SKIPSUBS, pid);
|
||||
if (len >= 4 && dlen >= 4) {
|
||||
caid = ( ptr[0] << 8) | ptr[1];
|
||||
pid = ((ptr[2] & 0x1f) << 8) | ptr[3];
|
||||
tvhdebug("cat", " caid %04X (%d) pid %04X (%d)",
|
||||
(uint16_t)caid, (uint16_t)caid, pid, pid);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1155,7 +1143,7 @@ psi_desc_add_ca
|
|||
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
if(c->caid == caid) {
|
||||
c->delete_me = 0;
|
||||
c->pid = pid;
|
||||
|
||||
if(c->providerid != provid) {
|
||||
c->providerid = provid;
|
||||
|
@ -1169,8 +1157,7 @@ psi_desc_add_ca
|
|||
|
||||
c->caid = caid;
|
||||
c->providerid = provid;
|
||||
|
||||
c->delete_me = 0;
|
||||
c->pid = pid;
|
||||
LIST_INSERT_HEAD(&st->es_caids, c, link);
|
||||
r |= PMT_UPDATE_NEW_CAID;
|
||||
return r;
|
||||
|
@ -1327,7 +1314,7 @@ psi_parse_pmt
|
|||
st->es_delete_me = 1;
|
||||
|
||||
LIST_FOREACH(c, &st->es_caids, link)
|
||||
c->delete_me = 1;
|
||||
c->pid = CAID_REMOVE_ME;
|
||||
}
|
||||
|
||||
// Common descriptors
|
||||
|
@ -1516,7 +1503,7 @@ psi_parse_pmt
|
|||
|
||||
for(c = LIST_FIRST(&st->es_caids); c != NULL; c = cn) {
|
||||
cn = LIST_NEXT(c, link);
|
||||
if(c->delete_me) {
|
||||
if (c->pid == CAID_REMOVE_ME) {
|
||||
LIST_REMOVE(c, link);
|
||||
free(c);
|
||||
update |= PMT_UPDATE_CAID_DELETED;
|
||||
|
|
|
@ -769,7 +769,9 @@ mpegts_mux_create0
|
|||
mm->mm_open_table = mpegts_mux_open_table;
|
||||
mm->mm_close_table = mpegts_mux_close_table;
|
||||
TAILQ_INIT(&mm->mm_table_queue);
|
||||
LIST_INIT(&mm->mm_descrambler_caids);
|
||||
TAILQ_INIT(&mm->mm_descrambler_tables);
|
||||
TAILQ_INIT(&mm->mm_descrambler_emms);
|
||||
pthread_mutex_init(&mm->mm_descrambler_lock, NULL);
|
||||
|
||||
mm->mm_last_pid = -1;
|
||||
|
|
|
@ -1549,7 +1549,7 @@ add_caid(elementary_stream_t *st, uint16_t caid, uint32_t providerid)
|
|||
caid_t *c = malloc(sizeof(caid_t));
|
||||
c->caid = caid;
|
||||
c->providerid = providerid;
|
||||
c->delete_me = 0;
|
||||
c->pid = 0;
|
||||
LIST_INSERT_HEAD(&st->es_caids, c, link);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue