#include <fcntl.h>
#include "tvheadend.h"
-#include "dvb/dvb.h"
+#include "input/mpegts.h"
#include "tcp.h"
-#include "psi.h"
-#include "tsdemux.h"
#include "capmt.h"
#include "notify.h"
#include "subscriptions.h"
#include "dtable.h"
-
-#if ENABLE_DVBCSA
-#include <dvbcsa/dvbcsa.h>
-#else
-#include "ffdecsa/FFdecsa.h"
-#endif
+#include "tvhcsa.h"
+#include "input/mpegts/linuxdvb/linuxdvb_private.h"
// ca_pmt_list_management values:
#define CAPMT_LIST_MORE 0x00 // append a 'MORE' CAPMT object the list and start receiving the next object
typedef struct capmt_service {
th_descrambler_t ct_head;
- service_t *ct_service;
+ mpegts_service_t *ct_service;
struct capmt *ct_capmt;
CT_FORBIDDEN
} ct_keystate;
- /* buffers for keystructs */
-#if ENABLE_DVBCSA
- struct dvbcsa_bs_key_s *ct_key_even;
- struct dvbcsa_bs_key_s *ct_key_odd;
-#else
- void *ct_keys;
-#endif
-
- /* CSA */
- int ct_cluster_size;
- uint8_t *ct_tsbcluster;
- int ct_fill;
-#if ENABLE_DVBCSA
- struct dvbcsa_bs_batch_s *ct_tsbbatch_even;
- struct dvbcsa_bs_batch_s *ct_tsbbatch_odd;
- int ct_fill_even;
- int ct_fill_odd;
-#endif
+ tvhcsa_t ct_csa;
/* current sequence number */
uint16_t ct_seq;
LIST_REMOVE(ct, ct_link);
-#if ENABLE_DVBCSA
- dvbcsa_bs_key_free(ct->ct_key_odd);
- dvbcsa_bs_key_free(ct->ct_key_even);
- free(ct->ct_tsbbatch_odd);
- free(ct->ct_tsbbatch_even);
-#else
- free_key_struct(ct->ct_keys);
-#endif
- free(ct->ct_tsbcluster);
+ tvhcsa_destroy(&ct->ct_csa);
free(ct);
}
static void
handle_ca0(capmt_t* capmt) {
capmt_service_t *ct;
- service_t *t;
+ mpegts_service_t *t;
int ret, bufsize;
int *request;
ca_descr_t *ca;
if(ret < bufsize) {
if(ct->ct_keystate != CT_FORBIDDEN) {
- tvhlog(LOG_ERR, "capmt", "Can not descramble service \"%s\", access denied", t->s_svcname);
+ tvhlog(LOG_ERR, "capmt", "Can not descramble service \"%s\", access denied", t->s_dvb_svcname);
ct->ct_keystate = CT_FORBIDDEN;
}
continue;
if (memcmp(even, invalid, 8))
-#if ENABLE_DVBCSA
- dvbcsa_bs_key_set(even, ct->ct_key_even);
-#else
- set_even_control_word(ct->ct_keys, even);
-#endif
+ tvhcsa_set_key_even(&ct->ct_csa, even);
if (memcmp(odd, invalid, 8))
-#if ENABLE_DVBCSA
- dvbcsa_bs_key_set(odd, ct->ct_key_odd);
-#else
- set_odd_control_word(ct->ct_keys, odd);
-#endif
+ tvhcsa_set_key_odd(&ct->ct_csa, odd);
if(ct->ct_keystate != CT_RESOLVED)
- tvhlog(LOG_DEBUG, "capmt", "Obtained key for service \"%s\"",t->s_svcname);
+ tvhlog(LOG_DEBUG, "capmt", "Obtained key for service \"%s\"",t->s_dvb_svcname);
ct->ct_keystate = CT_RESOLVED;
}
if (!capmt->capmt_oscam) {
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[0], capmt->capmt_port);
} else {
-#if TODO_FIX_THIS //ENABLE_LINUXDVB
- th_dvb_adapter_t *tda;
- TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
- if (!tda->tda_enabled)
+ int i;
+ extern const idclass_t linuxdvb_adapter_class;
+ linuxdvb_adapter_t *la;
+ idnode_set_t *is = idnode_find_all(&linuxdvb_adapter_class);
+ for (i = 0; i < is->is_count; i++) {
+ la = (linuxdvb_adapter_t*)is->is_array[i];
+ if (!la->mi_enabled) continue;
+ if (!la->la_rootpath) continue;
+ if (la->la_number > MAX_CA) {
+ tvhlog(LOG_ERR, "capmt", "adapter number > MAX_CA");
continue;
- if (tda->tda_rootpath) { //if rootpath is NULL then can't rely on tda_adapter_num because it is always 0
- if (tda->tda_adapter_num > MAX_CA) {
- tvhlog(LOG_ERR, "capmt", "adapter number > MAX_CA");
- continue;
- }
- tvhlog(LOG_INFO, "capmt", "Creating capmt UDP socket for adapter %d", tda->tda_adapter_num);
- bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[tda->tda_adapter_num], 9000 + tda->tda_adapter_num);
}
+ tvhlog(LOG_INFO, "capmt", "Creating capmt UDP socket for adapter %d",
+ la->la_number);
+ bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[la->la_number], 9000 + la->la_number);
}
-#endif
}
if (bind_ok)
handle_ca0(capmt);
*
*/
static void
-capmt_table_input(struct th_descrambler *td, struct service *t,
+capmt_table_input(struct th_descrambler *td, struct service *s,
struct elementary_stream *st, const uint8_t *data, int len)
{
+ extern const idclass_t mpegts_service_class;
+ extern const idclass_t linuxdvb_frontend_class;
capmt_service_t *ct = (capmt_service_t *)td;
capmt_t *capmt = ct->ct_capmt;
- int adapter_num = t->s_dvb_mux->dm_current_tdmi->tdmi_adapter->tda_adapter_num;
+ mpegts_service_t *t = (mpegts_service_t*)s;
+ linuxdvb_frontend_t *lfe;
+ int adapter_num;
int total_caids = 0, current_caid = 0;
+ /* Validate */
+ if (!idnode_is_instance(&s->s_id, &mpegts_service_class))
+ return;
+ if (!t->s_dvb_active_input) return;
+ lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
+ if (!idnode_is_instance(&lfe->mi_id, &linuxdvb_frontend_class))
+ return;
+ adapter_num = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
+
caid_t *c;
LIST_FOREACH(c, &st->es_caids, link) {
if (!cce)
{
tvhlog(LOG_DEBUG, "capmt",
- "New caid 0x%04X for service \"%s\"", c->caid, t->s_svcname);
+ "New caid 0x%04X for service \"%s\"", c->caid, t->s_dvb_svcname);
/* ecmpid not already seen, add it to list */
cce = calloc(1, sizeof(capmt_caid_ecm_t));
uint16_t sid = t->s_dvb_service_id;
uint16_t ecmpid = st->es_pid;
-#if TODO_FIX_THIS
- uint16_t transponder = t->s_dvb_mux_instance->tdmi_transport_stream_id;
- uint16_t onid = t->s_dvb_mux_instance->tdmi_network_id;
-#else
- uint16_t transponder = 0, onid = 0;
-#endif
+ uint16_t transponder = t->s_dvb_mux->mm_tsid;
+ uint16_t onid = t->s_dvb_mux->mm_onid;
/* don't do too much requests */
if (current_caid == total_caids && caid != ct->ct_caid_last)
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_DEBUG, "capmt",
- "Trying to obtain key for service \"%s\"",t->s_svcname);
+ "Trying to obtain key for service \"%s\"",t->s_dvb_svcname);
buf[9] = pmtversion;
pmtversion = (pmtversion + 1) & 0x1F;
/**
*
*/
-#if ENABLE_DVBCSA
-static int
-capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
- const uint8_t *tsb)
-{
- capmt_service_t *ct = (capmt_service_t *)td;
- uint8_t *pkt;
- int xc0;
- int ev_od;
- int len;
- int offset;
- int n;
- // FIXME: //int residue;
- int i;
- uint8_t *t0;
-
- if(ct->ct_keystate == CT_FORBIDDEN)
- return 1;
-
- if(ct->ct_keystate != CT_RESOLVED)
- return -1;
-
- pkt = ct->ct_tsbcluster + ct->ct_fill * 188;
- memcpy(pkt, tsb, 188);
- ct->ct_fill++;
-
- do { // handle this packet
- xc0 = pkt[3] & 0xc0;
- if(xc0 == 0x00) { // clear
- break;
- }
- if(xc0 == 0x40) { // reserved
- break;
- }
- if(xc0 == 0x80 || xc0 == 0xc0) { // encrypted
- ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
- pkt[3] &= 0x3f; // consider it decrypted now
- if(pkt[3] & 0x20) { // incomplete packet
- offset = 4 + pkt[4] + 1;
- len = 188 - offset;
- n = len >> 3;
- // FIXME: //residue = len - (n << 3);
- if(n == 0) { // decrypted==encrypted!
- break; // this doesn't need more processing
- }
- } else {
- len = 184;
- offset = 4;
- // FIXME: //n = 23;
- // FIXME: //residue = 0;
- }
- if(ev_od == 0) {
- ct->ct_tsbbatch_even[ct->ct_fill_even].data = pkt + offset;
- ct->ct_tsbbatch_even[ct->ct_fill_even].len = len;
- ct->ct_fill_even++;
- } else {
- ct->ct_tsbbatch_odd[ct->ct_fill_odd].data = pkt + offset;
- ct->ct_tsbbatch_odd[ct->ct_fill_odd].len = len;
- ct->ct_fill_odd++;
- }
- }
- } while(0);
-
- if(ct->ct_fill != ct->ct_cluster_size)
- return 0;
-
- if(ct->ct_fill_even) {
- ct->ct_tsbbatch_even[ct->ct_fill_even].data = NULL;
- dvbcsa_bs_decrypt(ct->ct_key_even, ct->ct_tsbbatch_even, 184);
- ct->ct_fill_even = 0;
- }
- if(ct->ct_fill_odd) {
- ct->ct_tsbbatch_odd[ct->ct_fill_odd].data = NULL;
- dvbcsa_bs_decrypt(ct->ct_key_odd, ct->ct_tsbbatch_odd, 184);
- ct->ct_fill_odd = 0;
- }
-
- t0 = ct->ct_tsbcluster;
- for(i = 0; i < ct->ct_fill; i++) {
- ts_recv_packet2(t, t0);
- t0 += 188;
- }
- ct->ct_fill = 0;
- return 0;
-}
-#else
static int
-capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
- const uint8_t *tsb)
+capmt_descramble
+ (th_descrambler_t *td, service_t *t, struct elementary_stream *st,
+ const uint8_t *tsb)
{
capmt_service_t *ct = (capmt_service_t *)td;
- int r, i;
- unsigned char *vec[3];
- uint8_t *t0;
if(ct->ct_keystate == CT_FORBIDDEN)
return 1;
if(ct->ct_keystate != CT_RESOLVED)
return -1;
- memcpy(ct->ct_tsbcluster + ct->ct_fill * 188, tsb, 188);
- ct->ct_fill++;
-
- if(ct->ct_fill != ct->ct_cluster_size)
- return 0;
-
- ct->ct_fill = 0;
-
- vec[0] = ct->ct_tsbcluster;
- vec[1] = ct->ct_tsbcluster + ct->ct_cluster_size * 188;
- vec[2] = NULL;
+ tvhcsa_descramble(&ct->ct_csa, (mpegts_service_t*)t, st, tsb, 0);
- while(1) {
- t0 = vec[0];
- r = decrypt_packets(ct->ct_keys, vec);
- if(r == 0)
- break;
- for(i = 0; i < r; i++) {
- ts_recv_packet2(t, t0);
- t0 += 188;
- }
- }
return 0;
}
-#endif
/**
* Check if our CAID's matches, and if so, link
* global_lock is held
*/
void
-capmt_service_start(service_t *t)
+capmt_service_start(service_t *s)
{
+ extern const idclass_t mpegts_service_class;
+ extern const idclass_t linuxdvb_frontend_class;
capmt_t *capmt;
capmt_service_t *ct;
capmt_caid_ecm_t *cce;
th_descrambler_t *td;
+ mpegts_service_t *t = (mpegts_service_t*)s;
+ linuxdvb_frontend_t *lfe;
+ int tuner = 0;
lock_assert(&global_lock);
+ /* Validate */
+ if (!idnode_is_instance(&s->s_id, &mpegts_service_class))
+ return;
+ if (!t->s_dvb_active_input) return;
+ lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
+ if (!idnode_is_instance(&lfe->mi_id, &linuxdvb_frontend_class))
+ return;
+ tuner = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
+
TAILQ_FOREACH(capmt, &capmts, capmt_link) {
/* skip, if we're not active */
if (!capmt->capmt_enabled)
continue;
-#if TODO_FIX_THIS
- if (!(t->s_dvb_mux_instance && t->s_dvb_mux_instance->tdmi_adapter))
- continue;
-#endif
-
tvhlog(LOG_INFO, "capmt",
"Starting capmt server for service \"%s\" on tuner %d",
- t->s_svcname,
- t->s_dvb_mux->dm_current_tdmi->tdmi_adapter->tda_adapter_num);
+ t->s_dvb_svcname, tuner);
elementary_stream_t *st;
/* create new capmt service */
- ct = calloc(1, sizeof(capmt_service_t));
-#if ENABLE_DVBCSA
- ct->ct_cluster_size = dvbcsa_bs_batch_size();
-#else
- ct->ct_cluster_size = get_suggested_cluster_size();
-#endif
- ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
- ct->ct_seq = capmt->capmt_seq++;
-#if ENABLE_DVBCSA
- ct->ct_tsbbatch_even = malloc((ct->ct_cluster_size + 1) *
- sizeof(struct dvbcsa_bs_batch_s));
- ct->ct_tsbbatch_odd = malloc((ct->ct_cluster_size + 1) *
- sizeof(struct dvbcsa_bs_batch_s));
-#endif
+ ct = calloc(1, sizeof(capmt_service_t));
+ tvhcsa_init(&ct->ct_csa);
+ ct->ct_capmt = capmt;
+ ct->ct_service = t;
+
TAILQ_FOREACH(st, &t->s_components, es_link) {
caid_t *c;
continue;
tvhlog(LOG_DEBUG, "capmt",
- "New caid 0x%04X for service \"%s\"", c->caid, t->s_svcname);
+ "New caid 0x%04X for service \"%s\"", c->caid, t->s_dvb_svcname);
/* add it to list */
cce = calloc(1, sizeof(capmt_caid_ecm_t));
}
}
-#if ENABLE_DVBCSA
- ct->ct_key_even = dvbcsa_bs_key_alloc();
- ct->ct_key_odd = dvbcsa_bs_key_alloc();
-#else
- ct->ct_keys = get_key_struct();
-#endif
- ct->ct_capmt = capmt;
- ct->ct_service = t;
-
td = &ct->ct_head;
td->td_stop = capmt_service_destroy;
td->td_table = capmt_table_input;
#include "tvheadend.h"
#include "tcp.h"
-#include "psi.h"
-#include "tsdemux.h"
#include "cwc.h"
#include "notify.h"
#include "atomic.h"
#include "dtable.h"
#include "subscriptions.h"
#include "service.h"
-
-#if ENABLE_DVBCSA
-#include <dvbcsa/dvbcsa.h>
-#else
-#include "ffdecsa/FFdecsa.h"
-#endif
+#include "input/mpegts.h"
+#include "input/mpegts/tsdemux.h"
+#include "tvhcsa.h"
/**
*
typedef struct cwc_service {
th_descrambler_t cs_head;
- service_t *cs_service;
+ mpegts_service_t *cs_service;
struct cwc *cs_cwc;
CS_IDLE
} cs_keystate;
-#if ENABLE_DVBCSA
- struct dvbcsa_bs_key_s *cs_key_even;
- struct dvbcsa_bs_key_s *cs_key_odd;
-#else
- void *cs_keys;
-#endif
-
uint8_t cs_cw[16];
int cs_pending_cw_update;
- /**
- * CSA
- */
- int cs_cluster_size;
- uint8_t *cs_tsbcluster;
- int cs_fill;
-#if ENABLE_DVBCSA
- struct dvbcsa_bs_batch_s *cs_tsbbatch_even;
- struct dvbcsa_bs_batch_s *cs_tsbbatch_odd;
- int cs_fill_even;
- int cs_fill_odd;
-#endif
-
+ tvhcsa_t cs_csa;
+
LIST_HEAD(, ecm_pid) cs_pids;
} cwc_service_t;
cwc->cwc_connected = 1;
cwc_comet_status_update(cwc);
cwc->cwc_caid = (msg[4] << 8) | msg[5];
- n = psi_caid2name(cwc->cwc_caid & 0xff00) ?: "Unknown";
+ n = descrambler_caid2name(cwc->cwc_caid & 0xff00) ?: "Unknown";
memcpy(cwc->cwc_ua, &msg[6], 8);
handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg,
int len, int seq)
{
- service_t *t = ct->cs_service;
+ mpegts_service_t *t = ct->cs_service;
ecm_pid_t *ep, *epn;
cwc_service_t *ct2;
cwc_t *cwc2;
if (es->es_nok > 2) {
tvhlog(LOG_DEBUG, "cwc",
"Too many NOKs for service \"%s\"%s from %s:%i",
- t->s_svcname, chaninfo, ct->cs_cwc->cwc_hostname,
+ t->s_dvb_svcname, chaninfo, ct->cs_cwc->cwc_hostname,
ct->cs_cwc->cwc_port);
goto forbid;
}
tvhlog(LOG_DEBUG, "cwc",
"NOK from %s:%i: Already has a key for service \"%s\", from %s:%i",
ct->cs_cwc->cwc_hostname, ct->cs_cwc->cwc_port,
- t->s_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port);
+ t->s_dvb_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port);
es->es_nok = 3; /* do not send more ECM requests */
goto forbid;
}
}
tvhlog(LOG_DEBUG, "cwc", "Received NOK for service \"%s\"%s (seqno: %d "
- "Req delay: %"PRId64" ms)", t->s_svcname, chaninfo, seq, delay);
+ "Req delay: %"PRId64" ms)", t->s_dvb_svcname, chaninfo, seq, delay);
forbid:
LIST_FOREACH(ep, &ct->cs_pids, ep_link) {
tvhlog(LOG_ERR, "cwc",
"Can not descramble service \"%s\", access denied (seqno: %d "
"Req delay: %"PRId64" ms)",
- t->s_svcname, seq, delay);
+ t->s_dvb_svcname, seq, delay);
ct->cs_keystate = CS_FORBIDDEN;
ct->ecm_state = ECM_RESET;
if(t->s_prefcapid == 0 || t->s_prefcapid != ct->cs_channel) {
t->s_prefcapid = ct->cs_channel;
tvhlog(LOG_DEBUG, "cwc", "Saving prefered PID %d", t->s_prefcapid);
- service_request_save(t, 0);
+ service_request_save((service_t*)t, 0);
}
tvhlog(LOG_DEBUG, "cwc",
" odd: %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x (seqno: %d "
"Req delay: %"PRId64" ms)",
chaninfo,
- t->s_svcname,
+ t->s_dvb_svcname,
msg[3 + 0], msg[3 + 1], msg[3 + 2], msg[3 + 3], msg[3 + 4],
msg[3 + 5], msg[3 + 6], msg[3 + 7], msg[3 + 8], msg[3 + 9],
msg[3 + 10],msg[3 + 11],msg[3 + 12],msg[3 + 13],msg[3 + 14],
ct->cs_keystate = CS_IDLE;
tvhlog(LOG_DEBUG, "cwc",
"Already has a key for service \"%s\", from %s:%i",
- t->s_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port);
+ t->s_dvb_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port);
return;
}
}
if(ct->cs_keystate != CS_RESOLVED)
tvhlog(LOG_DEBUG, "cwc",
"Obtained key for service \"%s\" in %"PRId64" ms, from %s:%i",
- t->s_svcname, delay, ct->cs_cwc->cwc_hostname,
+ t->s_dvb_svcname, delay, ct->cs_cwc->cwc_hostname,
ct->cs_cwc->cwc_port);
ct->cs_keystate = CS_RESOLVED;
for(i = 0; i < 256; i++)
free(ep->ep_sections[i]);
LIST_REMOVE(ep, ep_link);
- tvhlog(LOG_WARNING, "cwc", "Delete ECM (PID %d) for service \"%s\"", ep->ep_pid, t->s_svcname);
+ tvhlog(LOG_WARNING, "cwc", "Delete ECM (PID %d) for service \"%s\"", ep->ep_pid, t->s_dvb_svcname);
free(ep);
ep = epn;
}
cwc_t *cwc = aux;
int fd, d;
char errbuf[100];
- service_t *t;
+ mpegts_service_t *t;
char hostname[256];
int port;
struct timespec ts;
* t->s_streaming_mutex is held
*/
static void
-cwc_table_input(struct th_descrambler *td, struct service *t,
+cwc_table_input(struct th_descrambler *td, service_t *s,
struct elementary_stream *st, const uint8_t *data, int len)
{
cwc_service_t *ct = (cwc_service_t *)td;
+ mpegts_service_t *t = (mpegts_service_t*)s;
uint16_t sid = t->s_dvb_service_id;
cwc_t *cwc = ct->cs_cwc;
int channel;
ct->ecm_state = ECM_INIT;
ct->cs_channel = -1;
t->s_prefcapid = 0;
- tvhlog(LOG_DEBUG, "cwc", "Reset after unexpected or no reply for service \"%s\"", t->s_svcname);
+ tvhlog(LOG_DEBUG, "cwc", "Reset after unexpected or no reply for service \"%s\"", t->s_dvb_svcname);
}
if (ct->ecm_state == ECM_INIT) {
// Validate prefered ECM PID
if(t->s_prefcapid != 0) {
- struct elementary_stream *prefca = service_stream_find(t, t->s_prefcapid);
+ struct elementary_stream *prefca
+ = service_stream_find((service_t*)t, t->s_prefcapid);
if (!prefca || prefca->es_type != SCT_CA) {
- tvhlog(LOG_DEBUG, "cwc", "Invalid prefered ECM (PID %d) found for service \"%s\"", t->s_prefcapid, t->s_svcname);
+ tvhlog(LOG_DEBUG, "cwc", "Invalid prefered ECM (PID %d) found for service \"%s\"", t->s_prefcapid, t->s_dvb_svcname);
t->s_prefcapid = 0;
}
}
ep = calloc(1, sizeof(ecm_pid_t));
ep->ep_pid = t->s_prefcapid;
LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link);
- tvhlog(LOG_DEBUG, "cwc", "Insert prefered ECM (PID %d) for service \"%s\"", t->s_prefcapid, t->s_svcname);
+ tvhlog(LOG_DEBUG, "cwc", "Insert prefered ECM (PID %d) for service \"%s\"", t->s_prefcapid, t->s_dvb_svcname);
}
else if(t->s_prefcapid == 0) {
ep = calloc(1, sizeof(ecm_pid_t));
ep->ep_pid = st->es_pid;
LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link);
- tvhlog(LOG_DEBUG, "cwc", "Insert new ECM (PID %d) for service \"%s\"", st->es_pid, t->s_svcname);
+ tvhlog(LOG_DEBUG, "cwc", "Insert new ECM (PID %d) for service \"%s\"", st->es_pid, t->s_dvb_svcname);
}
}
}
tvhlog(LOG_DEBUG, "cwc",
"Sending ECM%s section=%d/%d, for service \"%s\" (seqno: %d)",
- chaninfo, section, ep->ep_last_section, t->s_svcname, es->es_seq);
+ chaninfo, section, ep->ep_last_section, t->s_dvb_svcname, es->es_seq);
es->es_time = getmonoclock();
break;
ct->cs_pending_cw_update = 0;
for(i = 0; i < 8; i++)
if(ct->cs_cw[i]) {
-#if ENABLE_DVBCSA
- dvbcsa_bs_key_set(ct->cs_cw, ct->cs_key_even);
-#else
- set_even_control_word(ct->cs_keys, ct->cs_cw);
-#endif
+ tvhcsa_set_key_even(&ct->cs_csa, ct->cs_cw);
break;
}
for(i = 0; i < 8; i++)
if(ct->cs_cw[8 + i]) {
-#if ENABLE_DVBCSA
- dvbcsa_bs_key_set(ct->cs_cw + 8, ct->cs_key_odd);
-#else
- set_odd_control_word(ct->cs_keys, ct->cs_cw + 8);
-#endif
+ tvhcsa_set_key_odd(&ct->cs_csa, ct->cs_cw);
break;
}
}
/**
*
*/
-#if ENABLE_DVBCSA
static int
-cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
- const uint8_t *tsb)
+cwc_descramble
+ (th_descrambler_t *td, service_t *t, struct elementary_stream *st,
+ const uint8_t *tsb)
{
cwc_service_t *ct = (cwc_service_t *)td;
- uint8_t *pkt;
- int xc0;
- int ev_od;
- int len;
- int offset;
- int n;
- // FIXME: //int residue;
if(ct->cs_keystate == CS_FORBIDDEN)
return 1;
if(ct->cs_keystate != CS_RESOLVED)
return -1;
-
- if(ct->cs_fill == 0 && ct->cs_pending_cw_update)
- update_keys(ct);
-
- pkt = ct->cs_tsbcluster + ct->cs_fill * 188;
- memcpy(pkt, tsb, 188);
- ct->cs_fill++;
-
- do { // handle this packet
- xc0 = pkt[3] & 0xc0;
- if(xc0 == 0x00) { // clear
- break;
- }
- if(xc0 == 0x40) { // reserved
- break;
- }
- if(xc0 == 0x80 || xc0 == 0xc0) { // encrypted
- ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
- pkt[3] &= 0x3f; // consider it decrypted now
- if(pkt[3] & 0x20) { // incomplete packet
- offset = 4 + pkt[4] + 1;
- len = 188 - offset;
- n = len >> 3;
- // FIXME: //residue = len - (n << 3);
- if(n == 0) { // decrypted==encrypted!
- break; // this doesn't need more processing
- }
- } else {
- len = 184;
- offset = 4;
- // FIXME: //n = 23;
- // FIXME: //residue = 0;
- }
- if(ev_od == 0) {
- ct->cs_tsbbatch_even[ct->cs_fill_even].data = pkt + offset;
- ct->cs_tsbbatch_even[ct->cs_fill_even].len = len;
- ct->cs_fill_even++;
- } else {
- ct->cs_tsbbatch_odd[ct->cs_fill_odd].data = pkt + offset;
- ct->cs_tsbbatch_odd[ct->cs_fill_odd].len = len;
- ct->cs_fill_odd++;
- }
- }
- } while(0);
-
- if(ct->cs_fill != ct->cs_cluster_size)
- return 0;
-
- if(ct->cs_fill_even) {
- ct->cs_tsbbatch_even[ct->cs_fill_even].data = NULL;
- dvbcsa_bs_decrypt(ct->cs_key_even, ct->cs_tsbbatch_even, 184);
- ct->cs_fill_even = 0;
- }
- if(ct->cs_fill_odd) {
- ct->cs_tsbbatch_odd[ct->cs_fill_odd].data = NULL;
- dvbcsa_bs_decrypt(ct->cs_key_odd, ct->cs_tsbbatch_odd, 184);
- ct->cs_fill_odd = 0;
- }
-
- {
- int i;
- const uint8_t *t0 = ct->cs_tsbcluster;
-
- for(i = 0; i < ct->cs_fill; i++) {
- ts_recv_packet2(t, t0);
- t0 += 188;
- }
- }
- ct->cs_fill = 0;
-
- if(ct->cs_pending_cw_update)
- update_keys(ct);
-
- return 0;
-}
-#else
-static int
-cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
- const uint8_t *tsb)
-{
- cwc_service_t *ct = (cwc_service_t *)td;
- int r;
- unsigned char *vec[3];
-
- if(ct->cs_keystate == CS_FORBIDDEN)
- return 1;
-
- if(ct->cs_keystate != CS_RESOLVED)
- return -1;
-
- if(ct->cs_fill == 0 && ct->cs_pending_cw_update)
+
+ if(ct->cs_csa.csa_fill == 0 && ct->cs_pending_cw_update)
update_keys(ct);
- memcpy(ct->cs_tsbcluster + ct->cs_fill * 188, tsb, 188);
- ct->cs_fill++;
+ tvhcsa_descramble(&ct->cs_csa, (mpegts_service_t*)t, st, tsb,
+ ct->cs_pending_cw_update);
- if(ct->cs_fill != ct->cs_cluster_size)
- return 0;
-
- while(1) {
-
- vec[0] = ct->cs_tsbcluster;
- vec[1] = ct->cs_tsbcluster + ct->cs_fill * 188;
- vec[2] = NULL;
-
- r = decrypt_packets(ct->cs_keys, vec);
- if(r > 0) {
- int i;
- const uint8_t *t0 = ct->cs_tsbcluster;
-
- for(i = 0; i < r; i++) {
- ts_recv_packet2(t, t0);
- t0 += 188;
- }
-
- r = ct->cs_fill - r;
- assert(r >= 0);
-
- if(r > 0)
- memmove(ct->cs_tsbcluster, t0, r * 188);
- ct->cs_fill = r;
-
- if(ct->cs_pending_cw_update && r > 0)
- continue;
- } else {
- ct->cs_fill = 0;
- }
- break;
- }
if(ct->cs_pending_cw_update)
update_keys(ct);
return 0;
}
-#endif
/**
* cwc_mutex is held
LIST_REMOVE(ct, cs_link);
-#if ENABLE_DVBCSA
- dvbcsa_bs_key_free(ct->cs_key_odd);
- dvbcsa_bs_key_free(ct->cs_key_even);
- free(ct->cs_tsbbatch_odd);
- free(ct->cs_tsbbatch_even);
-#else
- free_key_struct(ct->cs_keys);
-#endif
- free(ct->cs_tsbcluster);
+ tvhcsa_destroy(&ct->cs_csa);
free(ct);
}
cwc_service_t *ct;
th_descrambler_t *td;
+ extern const idclass_t mpegts_service_class;
+ if (!idnode_is_instance(&t->s_id, &mpegts_service_class))
+ return;
+
pthread_mutex_lock(&cwc_mutex);
TAILQ_FOREACH(cwc, &cwcs, cwc_link) {
if(cwc->cwc_caid == 0)
continue;
ct = calloc(1, sizeof(cwc_service_t));
-#if ENABLE_DVBCSA
- ct->cs_cluster_size = dvbcsa_bs_batch_size();
-#else
- ct->cs_cluster_size = get_suggested_cluster_size();
-#endif
- ct->cs_tsbcluster = malloc(ct->cs_cluster_size * 188);
-#if ENABLE_DVBCSA
- ct->cs_tsbbatch_even = malloc((ct->cs_cluster_size + 1) *
- sizeof(struct dvbcsa_bs_batch_s));
- ct->cs_tsbbatch_odd = malloc((ct->cs_cluster_size + 1) *
- sizeof(struct dvbcsa_bs_batch_s));
- ct->cs_key_even = dvbcsa_bs_key_alloc();
- ct->cs_key_odd = dvbcsa_bs_key_alloc();
-#else
- ct->cs_keys = get_key_struct();
-#endif
+ tvhcsa_init(&ct->cs_csa);
ct->cs_cwc = cwc;
- ct->cs_service = t;
+ ct->cs_service = (mpegts_service_t*)t;
ct->cs_channel = -1;
ct->ecm_state = ECM_INIT;