]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: unify, fix and improve the constcw handling, fixes #3313
authorJaroslav Kysela <perex@perex.cz>
Wed, 18 Nov 2015 08:31:22 +0000 (09:31 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 18 Nov 2015 08:31:22 +0000 (09:31 +0100)
data/conf/descrambler
src/descrambler.h
src/descrambler/capmt.c
src/descrambler/cwc.c
src/descrambler/descrambler.c

index f9acf06b85d6e3fc1a67c4f2bc583c0c38323045..8caabfbc0653d48eb59254848fcb04fc85917745 100644 (file)
@@ -1,4 +1,10 @@
 {
+  "const_cw" : [
+    {
+      "name" : "BISS",
+      "caid" : "2600"
+    }
+  ],
   "quick_ecm" : [
     {
       "name" : "Sky UK",
index d5cabf56d305c9bf77a687a8d4a960e927f3233e..1886e13d0a91b64ad30d7ab0963f1ce8395455c9 100644 (file)
@@ -68,6 +68,7 @@ typedef struct th_descrambler_runtime {
   uint32_t dr_quick_ecm:1;
   uint32_t dr_key:1;
   uint32_t dr_key_first:1;
+  uint32_t dr_key_const:1;
   uint8_t  dr_key_index;
   uint8_t  dr_key_valid;
   uint8_t  dr_key_changed;
index af6be2a172dda168d988fc01b766d2fc6a320ec0..67aab3cbe3258fed9156915b8981646ab123f770 100644 (file)
@@ -195,7 +195,6 @@ typedef struct capmt_service {
 
   /* list of used ca-systems with ids and last ecm */
   struct capmt_caid_ecm_list ct_caid_ecm;
-  int ct_constcw; /* fast flag */
 
   /* current sequence number */
   uint16_t ct_seq;
@@ -1046,8 +1045,6 @@ capmt_ecm_reset(th_descrambler_t *th)
 {
   capmt_service_t *ct = (capmt_service_t *)th;
 
-  if (ct->ct_constcw)
-    return 1; /* keys will not change */
   ct->td_keystate = DS_UNKNOWN;
   return 0;
 }
@@ -1836,7 +1833,6 @@ capmt_caid_change(th_descrambler_t *td)
       cce->cce_providerid = c->providerid;
       cce->cce_service = t;
       LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
-      ct->ct_constcw |= c->caid == 0x2600 ? 1 : 0;
       change = 1;
     }
   }
@@ -2126,7 +2122,6 @@ capmt_service_start(caclient_t *cac, service_t *s)
       cce->cce_providerid = c->providerid;
       cce->cce_service = t;
       LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
-      ct->ct_constcw |= c->caid == 0x2600 ? 1 : 0;
       change = 1;
     }
   }
index f4b200f52c6d6ee223641d9dfc1ffaf2f71fb37f..42ebc9b6ddc51e018b4a95a02b3dd33913989e77 100644 (file)
@@ -151,7 +151,6 @@ typedef struct cwc_service {
   } ecm_state;
 
   LIST_HEAD(, ecm_pid) cs_pids;
-  int cs_constcw;
 
 } cwc_service_t;
 
@@ -619,9 +618,6 @@ cwc_ecm_reset(th_descrambler_t *th)
   ecm_pid_t *ep;
   ecm_section_t *es;
 
-  if (ct->cs_constcw)
-    return 1;  /* keys will not change */
-
   pthread_mutex_lock(&cwc->cwc_mutex);
   ct->td_keystate = DS_UNKNOWN;
   LIST_FOREACH(ep, &ct->cs_pids, ep_link)
@@ -1515,7 +1511,6 @@ cwc_service_start(caclient_t *cac, service_t *t)
   ct->cs_channel       = -1;
   ct->cs_mux           = ((mpegts_service_t *)t)->s_dvb_mux;
   ct->ecm_state        = ECM_INIT;
-  ct->cs_constcw       = pcard->cs_ra.caid == 0x2600;
 
   td                   = (th_descrambler_t *)ct;
   snprintf(buf, sizeof(buf), "cwc-%s-%i-%04X", cwc->cwc_hostname, cwc->cwc_port, pcard->cs_ra.caid);
index b63f82c3a7177f033aa934f19df00bf8f35e867f..aebb0654d92d7f0e693480e98eeb69f5b57eb92f 100644 (file)
@@ -31,6 +31,7 @@
 #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;
@@ -41,6 +42,7 @@ typedef struct th_descrambler_data {
 TAILQ_HEAD(th_descrambler_queue, th_descrambler_data);
 
 uint16_t *quick_ecm_table = NULL;
+uint16_t *constcw_table = NULL;
 
 /*
  *
@@ -173,6 +175,20 @@ descrambler_init ( void )
       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);
   }
 }
@@ -183,6 +199,8 @@ descrambler_done ( void )
   caclient_done();
   free(quick_ecm_table);
   quick_ecm_table = NULL;
+  free(constcw_table);
+  constcw_table = NULL;
 }
 
 /*
@@ -217,18 +235,28 @@ descrambler_service_start ( service_t *t )
 {
   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;
 
   }
@@ -240,6 +268,9 @@ descrambler_service_start ( service_t *t )
     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);
   }
@@ -366,10 +397,11 @@ descrambler_keys ( th_descrambler_t *td, int type,
     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);
@@ -394,9 +426,10 @@ descrambler_keys ( th_descrambler_t *td, int type,
   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"
@@ -425,9 +458,10 @@ descrambler_keys ( th_descrambler_t *td, int type,
     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:
@@ -530,6 +564,9 @@ static inline int
 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 */