card_type_t detect_card_type(const uint16_t caid);
static inline int caid_is_irdeto(uint16_t caid) { return (caid >> 8) == 0x06; }
+static inline int caid_is_videoguard(uint16_t caid) { return (caid >> 8) == 0x09; }
static inline int caid_is_powervu(uint16_t caid) { return (caid >> 8) == 0x0e; }
static inline int caid_is_betacrypt(uint16_t caid) { return (caid >> 8) == 0x17; }
static inline int caid_is_dvn(uint16_t caid) { return caid == 0x4a30; }
int64_t clk, clk2, clk3;
uint8_t ki;
int i, j;
+ caid_t *ca;
+ elementary_stream_t *st;
if (len < 6)
return 0;
if (dr->dr_ecm_parity == ECM_PARITY_81EVEN_80ODD)
j ^= 1;
dr->dr_ecm_start[j] = clk;
- if (dr->dr_quick_ecm) {
- ki = 1 << (j + 6); /* 0x40 = even, 0x80 = odd */
- for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
- tk = &dr->dr_keys[i];
+ ki = 1 << (j + 6); /* 0x40 = even, 0x80 = odd */
+ for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
+ tk = &dr->dr_keys[i];
+ if (dr->dr_quick_ecm)
tk->key_valid &= ~ki;
- if (tk->key_pid == 0) break;
+ TAILQ_FOREACH(st, &mt->mt_service->s_components.set_filter, es_filter_link) {
+ if (st->es_pid != mt->mt_pid) continue;
+ LIST_FOREACH(ca, &st->es_caids, link) {
+ if (ca->use == 0) continue;
+ tk->key_csa.csa_ecm = (caid_is_videoguard(ca->caid) && (ptr[2] - ptr[4]) == 4) ? ptr[21] : 0;
+ tvhtrace(LS_DESCRAMBLER, "key ecm=%X (caid=%04X)", tk->key_csa.csa_ecm, ca->caid);
+ }
}
+ if (tk->key_pid == 0) break;
}
}
tvhtrace(LS_DESCRAMBLER, "ECM message %02x:%02x (section %d, len %d, pid %d) for service \"%s\"",
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
+#include <dlfcn.h>
#include "tvhcsa.h"
#include "input.h"
#include "descrambler/algo/libaes128dec.h"
#include "descrambler/algo/libdesdec.h"
+#if ENABLE_DVBCSA
+static int dvbcsa_dl_loaded;
+static dvbcsa_dl_bs_key_set_type dvbcsa_dl_bs_key_set_ecm;
+#endif
static void
tvhcsa_empty_flush
switch (csa->csa_type) {
case DESCRAMBLER_CSA_CBC:
#if ENABLE_DVBCSA
- dvbcsa_bs_key_set(even, csa->csa_key_even);
+ dvbcsa_bs_key_set_wrap(csa->csa_ecm, even, csa->csa_key_even);
#endif
break;
case DESCRAMBLER_DES_NCB:
switch (csa->csa_type) {
case DESCRAMBLER_CSA_CBC:
#if ENABLE_DVBCSA
- dvbcsa_bs_key_set(odd, csa->csa_key_odd);
+ dvbcsa_bs_key_set_wrap(csa->csa_ecm, odd, csa->csa_key_odd);
#endif
break;
case DESCRAMBLER_DES_NCB:
void
tvhcsa_init ( tvhcsa_t *csa )
{
+#if ENABLE_DVBCSA
+ void *dvbcsa_dlh;
+
+ if (!dvbcsa_dl_loaded)
+ {
+ dvbcsa_dl_loaded++;
+ dvbcsa_dlh = dlopen(NULL, RTLD_LAZY);
+ if (dvbcsa_dlh)
+ {
+ dvbcsa_dl_bs_key_set_ecm = (dvbcsa_dl_bs_key_set_type) dlsym(dvbcsa_dlh, "dvbcsa_bs_key_set_ecm");
+ if (dvbcsa_dl_bs_key_set_ecm)
+ tvhinfo(LS_DESCRAMBLER, "dvbcsa_bs_key_set_ecm() function detected in libdvbcsa");
+ else
+ {
+ dlclose(dvbcsa_dlh);
+ tvhinfo(LS_DESCRAMBLER, "dvbcsa_bs_key_set_ecm() function not detected in libdvbcsa");
+ }
+ }
+ else
+ {
+ dvbcsa_dl_bs_key_set_ecm = NULL;
+ tvhwarn(LS_DESCRAMBLER, "could not dlopen libdvbcsa");
+ }
+ }
+#endif
csa->csa_type = 0;
csa->csa_keylen = 0;
}
}
memset(csa, 0, sizeof(*csa));
}
+
+#if ENABLE_DVBCSA
+void
+dvbcsa_bs_key_set_wrap(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key)
+{
+ if (dvbcsa_dl_bs_key_set_ecm)
+ dvbcsa_dl_bs_key_set_ecm(ecm, cw, key);
+ else
+ dvbcsa_bs_key_set(cw, key);
+}
+#endif
uint8_t *csa_tsbcluster;
int csa_fill;
int csa_fill_size;
+ uint8_t csa_ecm;
#if ENABLE_DVBCSA
struct dvbcsa_bs_batch_s *csa_tsbbatch_even;
#endif
+#if ENABLE_DVBCSA
+typedef void* (*dvbcsa_dl_bs_key_set_type)(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key);
+void dvbcsa_bs_key_set_wrap(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key);
+#endif
+
#endif /* __TVH_CSA_H__ */