capmt/cwc/mpegts: change emm processing

This commit is contained in:
Jaroslav Kysela 2014-06-06 23:47:40 +02:00
parent 8c4597022b
commit e044b1f817
9 changed files with 342 additions and 115 deletions

View file

@ -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__ */

View file

@ -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];

View file

@ -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);
}
/**
*

View file

@ -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_ */

View file

@ -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)

View file

@ -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;
/*

View file

@ -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;

View file

@ -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;

View file

@ -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);
}