From 88067f869e33572b6d0c683c5c63f72edd139076 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Mon, 26 Nov 2012 02:11:51 +0400 Subject: [PATCH] [PR-177] Added preferred CA pid support Added prefrerred CA pid field in user interface and use field value to store ECM only from stream which is answer ok. Field could be refreshed by program or manually. --- src/cwc.c | 65 ++++++++++++++++++++++++++++++------- src/dvb/dvb_service.c | 6 ++++ src/service.c | 9 +++++ src/service.h | 3 ++ src/webui/extjs.c | 6 ++++ src/webui/static/app/dvb.js | 7 +++- 6 files changed, 84 insertions(+), 12 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 51b8f2e7..52a4489e 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -27,7 +27,6 @@ #include #include #include - #include "tvheadend.h" #include "tcp.h" #include "psi.h" @@ -38,7 +37,7 @@ #include "atomic.h" #include "dtable.h" #include "subscriptions.h" - +#include "service.h" #include /** @@ -754,9 +753,9 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, int len, int seq) { service_t *t = ct->cs_service; + ecm_pid_t *ep, *epn; cwc_service_t *ct2; cwc_t *cwc2; - ecm_pid_t *ep; char chaninfo[32]; int i; int64_t delay = (getmonoclock() - es->es_time) / 1000LL; // in ms @@ -773,9 +772,6 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, /* ERROR */ - if(ct->cs_okchannel == es->es_channel) - ct->cs_okchannel = -1; - if (es->es_nok < 3) es->es_nok++; @@ -829,6 +825,11 @@ forbid: } else { ct->cs_okchannel = es->es_channel; + tvhlog(LOG_DEBUG, "cwc", "es->es_nok %d t->tht_prefcapid %d", es->es_nok, t->s_prefcapid); + if(es->es_nok == 1 || t->s_prefcapid == 0) { + t->s_prefcapid = ct->cs_okchannel; + service_request_save(t, 0); + } es->es_nok = 0; tvhlog(LOG_DEBUG, "cwc", @@ -865,6 +866,22 @@ forbid: ct->cs_keystate = CS_RESOLVED; memcpy(ct->cs_cw, msg + 3, 16); ct->cs_pending_cw_update = 1; + + ep = LIST_FIRST(&ct->cs_pids); + while(ep != NULL) { + if (ct->cs_okchannel == ep->ep_pid) { + ep = LIST_NEXT(ep, ep_link); + } + else { + epn = LIST_NEXT(ep, ep_link); + for(i = 0; i < 256; i++) + free(ep->ep_sections[i]); + LIST_REMOVE(ep, ep_link); + tvhlog(LOG_WARNING, "cwc", "Delete ECMpid %d", ep->ep_pid); + free(ep); + ep = epn; + } + } } } @@ -902,6 +919,10 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len) } } tvhlog(LOG_WARNING, "cwc", "Got unexpected ECM reply (seqno: %d)", seq); + LIST_FOREACH(ct, &cwc->cwc_services, cs_link) { + tvhlog(LOG_DEBUG, "cwc", "After got unexpected (ct->cs_okchannel: %d)", ct->cs_okchannel); + if (ct->cs_okchannel == -3) ct->cs_okchannel = -2; + } break; } return 0; @@ -1592,9 +1613,28 @@ cwc_table_input(struct th_descrambler *td, struct service *t, } if(ep == NULL) { - ep = calloc(1, sizeof(ecm_pid_t)); - ep->ep_pid = st->es_pid; - LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link); + if (ct->cs_okchannel == -2) { + t->s_prefcapid = 0; + ct->cs_okchannel = -1; + tvhlog(LOG_DEBUG, "cwc", "Insert after unexpected reply"); + } + + if (ct->cs_okchannel == -3 && t->s_prefcapid == st->es_pid) { + 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 only one new ECM channel %d for service id %d", t->s_prefcapid, sid); + } + + if (ct->cs_okchannel == -1 || (ct->cs_okchannel == -3 && 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 channel %d", st->es_pid); + } + else { + return; + } } @@ -1626,6 +1666,9 @@ cwc_table_input(struct th_descrambler *td, struct service *t, section = 0; } + channel = st->es_pid; + snprintf(chaninfo, sizeof(chaninfo), " (channel %d)", channel); + if(ep->ep_sections[section] == NULL) ep->ep_sections[section] = calloc(1, sizeof(ecm_section_t)); @@ -1650,7 +1693,7 @@ cwc_table_input(struct th_descrambler *td, struct service *t, memcpy(es->es_ecm, data, len); es->es_ecmsize = len; - if(ct->cs_okchannel != -1 && channel != -1 && + if(ct->cs_okchannel >= 0 && channel != -1 && ct->cs_okchannel != channel) { tvhlog(LOG_DEBUG, "cwc", "Filtering ECM channel %d", channel); return; @@ -1988,7 +2031,7 @@ cwc_service_start(service_t *t) ct->cs_keys = get_key_struct(); ct->cs_cwc = cwc; ct->cs_service = t; - ct->cs_okchannel = -1; + ct->cs_okchannel = -3; td = &ct->cs_head; td->td_stop = cwc_service_destroy; diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 82621227..65b7fbf5 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -259,6 +259,10 @@ dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier) if(s && u32) service_map_channel(t, channel_find_by_name(s, 1, 0), 0); + if(htsmsg_get_u32(c, "prefcapid", &u32)) + u32 = 0; + t->s_prefcapid = u32; + /* HACK - force save for old config */ if(old) dvb_service_save(t); @@ -471,6 +475,8 @@ dvb_service_build_msg(service_t *t) htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable); + htsmsg_add_u32(m, "prefcapid", t->s_prefcapid); + return m; } diff --git a/src/service.c b/src/service.c index 6548f104..e189ae1d 100644 --- a/src/service.c +++ b/src/service.c @@ -933,6 +933,15 @@ service_set_enable(service_t *t, int enabled) subscription_reschedule(); } +void +service_set_prefcapid(service_t *t, uint32_t prefcapid) +{ + if(t->s_prefcapid == prefcapid) + return; + + t->s_prefcapid = prefcapid; + t->s_config_save(t); +} static pthread_mutex_t pending_save_mutex; static pthread_cond_t pending_save_cond; diff --git a/src/service.h b/src/service.h index 11e39b5d..b6463fc0 100644 --- a/src/service.h +++ b/src/service.h @@ -474,6 +474,7 @@ typedef struct service { int s_scrambled; int s_scrambled_seen; int s_caid; + uint16_t s_prefcapid; /** * PCR drift compensation. This should really be per-packet. @@ -597,6 +598,8 @@ void service_set_dvb_charset(service_t *t, const char *dvb_charset); void service_set_dvb_eit_enable(service_t *t, int dvb_eit_enable); +void service_set_prefcapid(service_t *t, uint32_t prefcapid); + int service_is_primary_epg (service_t *t); htsmsg_t *servicetype_list (void); diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 10829e2e..6355e236 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -1469,6 +1469,9 @@ service_update(htsmsg_t *in) if((chname = htsmsg_get_str(c, "channelname")) != NULL) service_map_channel(t, channel_find_by_name(chname, 1, 0), 1); + if(!htsmsg_get_u32(c, "prefcapid", &u32)) + service_set_prefcapid(t, u32); + if((dvb_charset = htsmsg_get_str(c, "dvb_charset")) != NULL) service_set_dvb_charset(t, dvb_charset); @@ -1800,6 +1803,9 @@ extjs_service_update(htsmsg_t *in) if(!htsmsg_get_u32(c, "enabled", &u32)) service_set_enable(t, u32); + if(!htsmsg_get_u32(c, "prefcapid", &u32)) + service_set_prefcapid(t, u32); + if((chname = htsmsg_get_str(c, "channelname")) != NULL) service_map_channel(t, channel_find_by_name(chname, 1, 0), 1); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 746ac7d6..0f1b836f 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -506,6 +506,11 @@ tvheadend.dvb_services = function(adapterId) { dataIndex : 'sid', width : 50, hidden : true + }, { + header: "Preffered CA pid", + dataIndex: 'prefcapid', + width: 50, + editor: new fm.TextField({allowBlank: true}) }, { header : "PMT PID", dataIndex : 'pmt', @@ -521,7 +526,7 @@ tvheadend.dvb_services = function(adapterId) { var store = new Ext.data.JsonStore({ root : 'entries', fields : Ext.data.Record.create([ 'id', 'enabled', 'type', 'sid', 'pmt', - 'pcr', 'svcname', 'network', 'provider', 'mux', 'channelname', + 'pcr', 'svcname', 'network', 'provider', 'mux', 'channelname', 'prefcapid', 'dvb_charset', 'dvb_eit_enable' ]), url : "dvb/services/" + adapterId, autoLoad : true,