From ad7a5665f2ec002d258d38d166019673fac7abb5 Mon Sep 17 00:00:00 2001 From: Catalin Toda Date: Fri, 14 Apr 2023 15:27:24 -0700 Subject: [PATCH] Reduce the size of the CAPMT to include only video and audio channels and only CAIDs accepted by the CAM --- src/ca.c | 33 +++++++++++++++++++++++++++++++-- src/dvbapi.c | 3 ++- src/pmt.c | 36 ++++++++---------------------------- src/pmt.h | 4 +--- src/tables.c | 10 ++++++++++ src/tables.h | 1 + 6 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/ca.c b/src/ca.c index 91b1748cd1..bc1c5201f8 100644 --- a/src/ca.c +++ b/src/ca.c @@ -280,6 +280,34 @@ void disable_cws_for_all_pmts(ca_device_t *d) { } } +int CAPMT_add_PMT(uint8_t *capmt, int len, SPMT *pmt, int cmd_id, + int added_only, int ca_id) { + int i = 0, pos = 0; + for (i = 0; i < pmt->stream_pids; i++) { + if (added_only && !find_pid(pmt->adapter, pmt->stream_pid[i].pid)) { + LOGM("%s: skipping pmt %d (ad %d) pid %d from CAPMT", __FUNCTION__, + pmt->id, pmt->adapter, pmt->stream_pid[i].pid); + continue; + } + if (!pmt->stream_pid[i].is_audio && !pmt->stream_pid[i].is_video) + continue; + capmt[pos++] = pmt->stream_pid[i].type; + copy16(capmt, pos, pmt->stream_pid[i].pid); + pos += 2; + int pi_len_pos = pos, pi_len = 0; + pos += 2; + + // append the stream descriptors + if (pmt->caids) { + capmt[pos++] = cmd_id; + pi_len = pmt_add_ca_descriptor(pmt, capmt + pos, ca_id); + pos += pi_len; + } + copy16(capmt, pi_len_pos, pi_len + 1); + } + return pos; +} + int create_capmt(SCAPMT *ca, int listmgmt, uint8_t *capmt, int capmt_len, int cmd_id, int added_only) { int pos = 0; @@ -297,10 +325,11 @@ int create_capmt(SCAPMT *ca, int listmgmt, uint8_t *capmt, int capmt_len, capmt[pos++] = 0; // PI LEN 2 bytes, set 0 capmt[pos++] = 0; - pos += CAPMT_add_PMT(capmt + pos, capmt_len - pos, pmt, cmd_id, added_only); + pos += CAPMT_add_PMT(capmt + pos, capmt_len - pos, pmt, cmd_id, added_only, + dvbca_id); if (other) { pos += CAPMT_add_PMT(capmt + pos, capmt_len - pos, other, cmd_id, - added_only); + added_only, dvbca_id); } return pos; diff --git a/src/dvbapi.c b/src/dvbapi.c index 597ab56fbb..6fe906fef3 100644 --- a/src/dvbapi.c +++ b/src/dvbapi.c @@ -458,7 +458,8 @@ int dvbapi_send_pmt(SKey *k, int cmd_id) { copy16(buf, 23, 0x8701); // ca_device_descriptor (caX) buf[25] = demux; - len = 26 + pmt_add_ca_descriptor(pmt, buf + 26); // CA description + len = + 26 + pmt_add_ca_descriptor(pmt, buf + 26, dvbapi_ca); // CA description // Pids associated with the PMT copy16(buf, 10, len - 12); diff --git a/src/pmt.c b/src/pmt.c index a77e910022..22a0a27855 100644 --- a/src/pmt.c +++ b/src/pmt.c @@ -2313,10 +2313,16 @@ int pmt_tune(adapter *ad) { return 0; } -int pmt_add_ca_descriptor(SPMT *pmt, uint8_t *buf) { +int pmt_add_ca_descriptor(SPMT *pmt, uint8_t *buf, int ca_id) { int i, len = 0; for (i = 0; i < pmt->caids; i++) { - int private_data_len = pmt->ca[i].private_data_len; +#ifndef DISABLE_TABLES + if (!match_ca_caid(ca_id, pmt->adapter, pmt->ca[i].id)){ + LOGM("SCA %d cannot handle CAID %04X, skipping", ca_id, pmt->ca[i].id); + continue; + } +#endif + int private_data_len = pmt->ca[i].private_data_len; buf[len] = 0x09; buf[len + 1] = 0x04 + private_data_len; copy16(buf, len + 2, pmt->ca[i].id); @@ -2329,32 +2335,6 @@ int pmt_add_ca_descriptor(SPMT *pmt, uint8_t *buf) { return len; } -int CAPMT_add_PMT(uint8_t *capmt, int len, SPMT *pmt, int cmd_id, - int added_only) { - int i = 0, pos = 0; - for (i = 0; i < pmt->stream_pids; i++) { - if (added_only && !find_pid(pmt->adapter, pmt->stream_pid[i].pid)) { - LOGM("%s: skipping pmt %d (ad %d) pid %d from CAPMT", __FUNCTION__, - pmt->id, pmt->adapter, pmt->stream_pid[i].pid); - continue; - } - capmt[pos++] = pmt->stream_pid[i].type; - copy16(capmt, pos, pmt->stream_pid[i].pid); - pos += 2; - int pi_len_pos = pos, pi_len = 0; - pos += 2; - - // append the stream descriptors - if (pmt->caids) { - capmt[pos++] = cmd_id; - pi_len = pmt_add_ca_descriptor(pmt, capmt + pos); - pos += pi_len; - } - copy16(capmt, pi_len_pos, pi_len + 1); - } - return pos; -} - char *get_channel_for_adapter(int aid, char *dest, int max_size) { int i, pos = 0; adapter *ad; diff --git a/src/pmt.h b/src/pmt.h index ab7c113983..c01e0bb2fa 100644 --- a/src/pmt.h +++ b/src/pmt.h @@ -223,15 +223,13 @@ int assemble_packet(SFilter *f, uint8_t *b); int clean_psi_buffer(uint8_t *pmt, uint8_t *clean, int clean_size); void disable_cw(int master_pmt); void expire_cw_for_pmt(int master_pmt, int parity, int64_t min_expiry); -int CAPMT_add_PMT(uint8_t *capmt, int len, SPMT *pmt, int cmd_id, - int added_only); int pmt_add(int i, int adapter, int sid, int pmt_pid); int test_decrypt_packet(SCW *cw, SPMT_batch *start, int len); void init_algo(); void update_cw(SPMT *pmt); int pmt_decrypt_stream(adapter *ad); int wait_pusi(adapter *ad, int len); -int pmt_add_ca_descriptor(SPMT *pmt, uint8_t *buf); +int pmt_add_ca_descriptor(SPMT *pmt, uint8_t *buf, int sca_id); void free_filters(); void stop_pmt(SPMT *pmt, adapter *ad); #endif diff --git a/src/tables.c b/src/tables.c index 25ab031080..ee06133be2 100644 --- a/src/tables.c +++ b/src/tables.c @@ -183,6 +183,16 @@ int match_caid(SPMT *pmt, int caid, int mask) { return 0; } +// return 1 if CA can handle this specific CAID on the specified adapter +int match_ca_caid(int ica, int aid, int caid) { + int i; + for (i = 0; i < ca[ica].ad_info[aid].caids; i++) + if (ca[ica].ad_info[aid].caid[i] == + (caid & ca[ica].ad_info[aid].mask[i])) + return 1; + return 0; +} + void close_pmt_for_ca(int i, adapter *ad, SPMT *pmt) { uint64_t mask = 1ULL << i; if (!ad) diff --git a/src/tables.h b/src/tables.h index e84363543d..783533f096 100644 --- a/src/tables.h +++ b/src/tables.h @@ -55,6 +55,7 @@ void close_pmt_for_ca(int i, adapter *ad, SPMT *pmt); int close_pmt_for_cas(adapter *ad, SPMT *pmt); void tables_ca_ts(adapter *ad); int match_caid(SPMT *pmt, int caid, int mask); +int match_ca_caid(int ica, int aid, int caid); void tables_update_encrypted_status(adapter *ad, SPMT *pmt); #endif