diff --git a/Makefile b/Makefile index fe5a3e92..f4ce7ded 100644 --- a/Makefile +++ b/Makefile @@ -215,8 +215,9 @@ SRCS-$(CONFIG_LIBAV) += src/libav.c \ # CWC SRCS-${CONFIG_CWC} += \ - src/cwc.c \ - src/capmt.c + src/descrambler/tvhcsa.c \ + src/descrambler/cwc.c \ + src/descrambler/capmt.c # FFdecsa ifneq ($(CONFIG_DVBCSA),yes) diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index 3977efd0..a3b0dabc 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -38,20 +38,14 @@ #include #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 -#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 @@ -148,7 +142,7 @@ typedef struct capmt_caid_ecm { typedef struct capmt_service { th_descrambler_t ct_head; - service_t *ct_service; + mpegts_service_t *ct_service; struct capmt *ct_capmt; @@ -166,24 +160,7 @@ typedef struct capmt_service { 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; @@ -388,22 +365,14 @@ capmt_service_destroy(th_descrambler_t *td) 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; @@ -522,7 +491,7 @@ handle_ca0(capmt_t* capmt) { 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; } @@ -534,20 +503,12 @@ handle_ca0(capmt_t* capmt) { 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; } @@ -617,21 +578,22 @@ capmt_thread(void *aux) 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); @@ -672,14 +634,27 @@ capmt_thread(void *aux) * */ 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) { @@ -713,7 +688,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t, 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)); @@ -734,12 +709,8 @@ capmt_table_input(struct th_descrambler *td, struct service *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) @@ -857,7 +828,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t, 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; @@ -876,21 +847,12 @@ capmt_table_input(struct th_descrambler *td, struct service *t, /** * */ -#if ENABLE_DVBCSA 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; - 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; @@ -898,110 +860,10 @@ capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *s if(ct->ct_keystate != CT_RESOLVED) return -1; - pkt = ct->ct_tsbcluster + ct->ct_fill * 188; - memcpy(pkt, tsb, 188); - ct->ct_fill++; + tvhcsa_descramble(&ct->ct_csa, (mpegts_service_t*)t, st, tsb, 0); - 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_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; - - 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 @@ -1009,47 +871,46 @@ capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *s * 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; @@ -1058,7 +919,7 @@ capmt_service_start(service_t *t) 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)); @@ -1072,15 +933,6 @@ capmt_service_start(service_t *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; diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 60d2cb11..7be929ea 100644 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -31,20 +31,15 @@ #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 -#else -#include "ffdecsa/FFdecsa.h" -#endif +#include "input/mpegts.h" +#include "input/mpegts/tsdemux.h" +#include "tvhcsa.h" /** * @@ -143,7 +138,7 @@ typedef struct ecm_pid { typedef struct cwc_service { th_descrambler_t cs_head; - service_t *cs_service; + mpegts_service_t *cs_service; struct cwc *cs_cwc; @@ -170,29 +165,11 @@ typedef struct cwc_service { 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; @@ -612,7 +589,7 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) 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); @@ -776,7 +753,7 @@ static void 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; @@ -800,7 +777,7 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, 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; } @@ -812,7 +789,7 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, 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; } @@ -820,7 +797,7 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, } 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) { @@ -837,7 +814,7 @@ forbid: 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; @@ -853,7 +830,7 @@ forbid: 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", @@ -862,7 +839,7 @@ forbid: " 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], @@ -875,7 +852,7 @@ forbid: 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; } } @@ -884,7 +861,7 @@ forbid: 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; @@ -901,7 +878,7 @@ forbid: 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; } @@ -1162,7 +1139,7 @@ cwc_thread(void *aux) 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; @@ -1609,10 +1586,11 @@ cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen) * 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; @@ -1641,15 +1619,16 @@ cwc_table_input(struct th_descrambler *td, struct service *t, 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; } } @@ -1658,13 +1637,13 @@ cwc_table_input(struct th_descrambler *td, struct service *t, 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); } } } @@ -1733,7 +1712,7 @@ cwc_table_input(struct th_descrambler *td, struct service *t, 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; @@ -1909,21 +1888,13 @@ update_keys(cwc_service_t *ct) 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; } } @@ -1932,160 +1903,30 @@ update_keys(cwc_service_t *ct) /** * */ -#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) + + if(ct->cs_csa.csa_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; + tvhcsa_descramble(&ct->cs_csa, (mpegts_service_t*)t, st, tsb, + ct->cs_pending_cw_update); 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) - update_keys(ct); - - memcpy(ct->cs_tsbcluster + ct->cs_fill * 188, tsb, 188); - ct->cs_fill++; - - 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 @@ -2109,15 +1950,7 @@ cwc_service_destroy(th_descrambler_t *td) 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); } @@ -2152,6 +1985,10 @@ cwc_service_start(service_t *t) 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) @@ -2161,24 +1998,9 @@ cwc_service_start(service_t *t) 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; diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 09cd228f..57609ef8 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -88,8 +88,10 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) // Note: we always test season first, though it will only be set // if configured - if(dae->dae_serieslink) + if(dae->dae_serieslink) { if (!e->serieslink || dae->dae_serieslink != e->serieslink) return 0; + return 1; + } if(dae->dae_season) if (!e->episode->season || dae->dae_season != e->episode->season) return 0; if(dae->dae_brand)