#include "streaming.h"
#define MAX_QUICK_ECM_ENTRIES 100
+#define MAX_CONSTCW_ENTRIES 100
typedef struct th_descrambler_data {
TAILQ_ENTRY(th_descrambler_data) dd_link;
TAILQ_HEAD(th_descrambler_queue, th_descrambler_data);
uint16_t *quick_ecm_table = NULL;
+uint16_t *constcw_table = NULL;
/*
*
if (quick_ecm_table)
quick_ecm_table[idx] = 0;
}
+ if ((q = htsmsg_get_list(c, "const_cw")) != NULL) {
+ HTSMSG_FOREACH(f, q) {
+ if (!(e = htsmsg_field_get_map(f))) continue;
+ if (idx + 1 >= MAX_CONSTCW_ENTRIES) continue;
+ if ((s = htsmsg_get_str(e, "caid")) == NULL) continue;
+ caid = strtol(s, NULL, 16);
+ tvhinfo("descrambler", "adding CAID %04X as constant crypto-word (%s)", caid, htsmsg_get_str(e, "name") ?: "unknown");
+ if (!constcw_table)
+ constcw_table = malloc(sizeof(uint16_t) * MAX_CONSTCW_ENTRIES);
+ constcw_table[idx++] = caid;
+ }
+ if (constcw_table)
+ constcw_table[idx] = 0;
+ }
htsmsg_destroy(c);
}
}
caclient_done();
free(quick_ecm_table);
quick_ecm_table = NULL;
+ free(constcw_table);
+ constcw_table = NULL;
}
/*
{
th_descrambler_runtime_t *dr;
elementary_stream_t *st;
+ caid_t *ca;
+ int count, constcw = 0;
+ uint16_t *p;
if (t->s_scrambled_pass)
return;
if (!((mpegts_service_t *)t)->s_dvb_forcecaid) {
- TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link)
- if (LIST_FIRST(&st->es_caids) != NULL)
- break;
+ count = 0;
+ TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) {
+ LIST_FOREACH(ca, &st->es_caids, link)
+ for (p = quick_ecm_table; *p; p++)
+ if (ca->caid == *p) {
+ constcw = 1;
+ break;
+ }
+ count++;
+ }
/* Do not run descrambler on FTA channels */
- if (!st)
+ if (count == 0)
return;
}
TAILQ_INIT(&dr->dr_queue);
dr->dr_key_index = 0xff;
dr->dr_key_interval = 10;
+ dr->dr_key_const = constcw;
+ if (constcw)
+ tvhtrace("descrambler", "using constcw for \"%s\"", t->s_nicename);
dr->dr_skip = 0;
tvhcsa_init(&dr->dr_csa);
}
if (td2 != td && td2->td_keystate == DS_RESOLVED) {
tvhlog(LOG_DEBUG, "descrambler",
"Already has a key from %s for service \"%s\", "
- "ignoring key from \"%s\"",
+ "ignoring key from \"%s\"%s",
td2->td_nicename,
((mpegts_service_t *)td2->td_service)->s_dvb_svcname,
- td->td_nicename);
+ td->td_nicename,
+ dr->dr_key_const ? " (const)" : "");
td->td_keystate = DS_IDLE;
if (td->td_ecm_idle)
td->td_ecm_idle(td);
if (j) {
if (td->td_keystate != DS_RESOLVED)
tvhlog(LOG_DEBUG, "descrambler",
- "Obtained keys from %s for service \"%s\"",
+ "Obtained keys from %s for service \"%s\"%s",
td->td_nicename,
- ((mpegts_service_t *)t)->s_dvb_svcname);
+ ((mpegts_service_t *)t)->s_dvb_svcname,
+ dr->dr_key_const ? " (const)" : "");
if (dr->dr_csa.csa_keylen == 8) {
tvhtrace("descrambler", "Obtained keys "
"%02X%02X%02X%02X%02X%02X%02X%02X:%02X%02X%02X%02X%02X%02X%02X%02X"
td->td_service->s_descrambler = td;
} else {
tvhlog(LOG_DEBUG, "descrambler",
- "Empty keys received from %s for service \"%s\"",
+ "Empty keys received from %s for service \"%s\"%s",
td->td_nicename,
- ((mpegts_service_t *)t)->s_dvb_svcname);
+ ((mpegts_service_t *)t)->s_dvb_svcname,
+ dr->dr_key_const ? " (const)" : "");
}
fin:
key_late( th_descrambler_runtime_t *dr, uint8_t ki, time_t timestamp )
{
uint8_t kidx = (ki & 0x40) >> 6;
+ /* constcw - do not handle keys */
+ if (dr->dr_key_const)
+ return 0;
/* required key is older than previous? */
if (dr->dr_key_timestamp[kidx] < dr->dr_key_timestamp[kidx^1]) {
/* but don't take in account the keys modified just now */