*
*/
+static void cwc_service_pid_free(cwc_service_t *ct);
static void cwc_service_destroy(th_descrambler_t *td);
void cwc_emm_conax(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
void cwc_emm_irdeto(cwc_t *cwc, struct cs_card_data *pcard, const uint8_t *data, int len);
cwc_ecm_reset(th_descrambler_t *th)
{
cwc_service_t *ct = (cwc_service_t *)th;
- mpegts_service_t *t;
+ cwc_t *cwc = ct->cs_cwc;
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)
LIST_FOREACH(es, &ep->ep_sections, es_link)
es->es_keystate = ES_UNKNOWN;
ct->ecm_state = ECM_RESET;
- t = (mpegts_service_t *)th->td_service;
- if (t->s_dvb_prefcapid_lock != PREFCAPID_FORCE)
- t->s_dvb_prefcapid = 0;
+ pthread_mutex_unlock(&cwc->cwc_mutex);
return 0;
}
cwc_ecm_idle(th_descrambler_t *th)
{
cwc_service_t *ct = (cwc_service_t *)th;
+ cwc_t *cwc = ct->cs_cwc;
ecm_pid_t *ep;
ecm_section_t *es;
+ pthread_mutex_lock(&cwc->cwc_mutex);
LIST_FOREACH(ep, &ct->cs_pids, ep_link)
LIST_FOREACH(es, &ep->ep_sections, es_link)
es->es_keystate = ES_IDLE;
ct->ecm_state = ECM_RESET;
+ pthread_mutex_unlock(&cwc->cwc_mutex);
}
static void
int len, int seq)
{
mpegts_service_t *t = (mpegts_service_t *)ct->td_service;
+ cwc_t *cwc = ct->cs_cwc;
ecm_pid_t *ep;
ecm_section_t *es2;
char chaninfo[32];
es->es_keystate = ES_RESOLVED;
es->es_resolved = 1;
+ pthread_mutex_unlock(&cwc->cwc_mutex);
descrambler_keys((th_descrambler_t *)ct, DESCRAMBLER_DES, msg + 3, msg + 3 + 8);
+ pthread_mutex_lock(&cwc->cwc_mutex);
} else {
tvhlog(LOG_DEBUG, "cwc",
"Received ECM reply%s for service \"%s\" "
es->es_keystate = ES_RESOLVED;
es->es_resolved = 1;
+ pthread_mutex_unlock(&cwc->cwc_mutex);
descrambler_keys((th_descrambler_t *)ct, DESCRAMBLER_AES, msg + 3, msg + 3 + 16);
+ pthread_mutex_lock(&cwc->cwc_mutex);
}
}
}
if (data == NULL)
return;
- if (ct->td_keystate == DS_IDLE)
- return;
-
if(len > 4096)
return;
if((data[0] & 0xf0) != 0x80)
return;
- LIST_FOREACH(ep, &ct->cs_pids, ep_link) {
- if(ep->ep_pid == pid)
- break;
+ pthread_mutex_lock(&t->s_stream_mutex);
+ pthread_mutex_lock(&cwc->cwc_mutex);
+
+ if (ct->td_keystate == DS_IDLE)
+ goto end;
+
+ if (ct->ecm_state == ECM_RESET) {
+ /* clean all */
+ cwc_service_pid_free(ct);
+ /* move to init state */
+ ct->ecm_state = ECM_INIT;
+ ct->cs_channel = -1;
+ t->s_dvb_prefcapid = 0;
+ tvhlog(LOG_DEBUG, "cwc", "Reset after unexpected or no reply for service \"%s\"", t->s_dvb_svcname);
}
- pthread_mutex_lock(&t->s_stream_mutex);
- if(ep == NULL) {
- tvhlog(LOG_DEBUG, "cwc", "ECM state %i", ct->ecm_state);
- if (ct->ecm_state == ECM_RESET) {
- ct->ecm_state = ECM_INIT;
- ct->cs_channel = -1;
- t->s_dvb_prefcapid = 0;
- tvhlog(LOG_DEBUG, "cwc", "Reset after unexpected or no reply for service \"%s\"", t->s_dvb_svcname);
- }
+ LIST_FOREACH(ep, &ct->cs_pids, ep_link)
+ if(ep->ep_pid == pid) break;
+ if(ep == NULL) {
if (ct->ecm_state == ECM_INIT) {
// Validate prefered ECM PID
+ tvhlog(LOG_DEBUG, "cwc", "ECM state INIT");
+
if(t->s_dvb_prefcapid != PREFCAPID_OFF) {
struct elementary_stream *prefca
= service_stream_find((service_t*)t, t->s_dvb_prefcapid);
}
}
}
-
- if(ep == NULL) {
- pthread_mutex_unlock(&t->s_stream_mutex);
- return;
- }
+ if(ep == NULL)
+ goto end;
st = service_stream_find((service_t *)t, pid);
if (st) {
goto found;
}
- pthread_mutex_unlock(&t->s_stream_mutex);
- return;
+ goto end;
found:
caid = c->caid;
providerid = c->providerid;
- pthread_mutex_unlock(&t->s_stream_mutex);
-
switch(data[0]) {
case 0x80:
case 0x81:
if(ct->cs_channel >= 0 && channel != -1 &&
ct->cs_channel != channel) {
tvhlog(LOG_DEBUG, "cwc", "Filtering ECM (PID %d)", channel);
- return;
+ goto end;
}
es->es_seq = cwc_send_msg(cwc, data, len, sid, 1, caid, providerid);
cwc_send_msg(cwc, data, len, sid, 1, 0, 0);
break;
}
+
+end:
+ pthread_mutex_unlock(&cwc->cwc_mutex);
+ pthread_mutex_unlock(&t->s_stream_mutex);
}
/**
* s_stream_mutex is held
*/
static void
-cwc_service_destroy(th_descrambler_t *td)
+cwc_service_pid_free(cwc_service_t *ct)
{
- cwc_service_t *ct = (cwc_service_t *)td;
ecm_pid_t *ep;
ecm_section_t *es;
- int i;
-
- for (i = 0; i < CWC_ES_PIDS; i++)
- if (ct->cs_epids[i])
- descrambler_close_pid(ct->cs_mux, ct, ct->cs_epids[i]);
while((ep = LIST_FIRST(&ct->cs_pids)) != NULL) {
while ((es = LIST_FIRST(&ep->ep_sections)) != NULL) {
LIST_REMOVE(ep, ep_link);
free(ep);
}
+}
+
+/**
+ * cwc_mutex is held
+ * s_stream_mutex is held
+ */
+static void
+cwc_service_destroy(th_descrambler_t *td)
+{
+ cwc_service_t *ct = (cwc_service_t *)td;
+ int i;
+
+ for (i = 0; i < CWC_ES_PIDS; i++)
+ if (ct->cs_epids[i])
+ descrambler_close_pid(ct->cs_mux, ct, ct->cs_epids[i]);
+
+ cwc_service_pid_free(ct);
LIST_REMOVE(td, td_service_link);
if (!idnode_is_instance(&t->s_id, &mpegts_service_class))
return;
+ pthread_mutex_lock(&t->s_stream_mutex);
pthread_mutex_lock(&cwc->cwc_mutex);
LIST_FOREACH(ct, &cwc->cwc_services, cs_link) {
if (ct->td_service == t && ct->cs_cwc == cwc)
break;
}
- pthread_mutex_lock(&t->s_stream_mutex);
LIST_FOREACH(pcard, &cwc->cwc_cards, cs_card) {
if (pcard->cwc_caid == 0) continue;
TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) {
}
if (!pcard) {
if (ct) cwc_service_destroy((th_descrambler_t*)ct);
- pthread_mutex_unlock(&t->s_stream_mutex);
- pthread_mutex_unlock(&cwc->cwc_mutex);
- return;
- }
-
- pthread_mutex_unlock(&t->s_stream_mutex);
- if (ct) {
- pthread_mutex_unlock(&cwc->cwc_mutex);
- return;
+ goto end;
}
+ if (ct)
+ goto end;
ct = calloc(1, sizeof(cwc_service_t));
ct->cs_cwc = cwc;
LIST_INSERT_HEAD(&cwc->cwc_services, ct, cs_link);
- pthread_mutex_lock(&t->s_stream_mutex);
i = 0;
TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) {
LIST_FOREACH(c, &st->es_caids, link)
}
if (i == CWC_ES_PIDS) break;
}
- pthread_mutex_unlock(&t->s_stream_mutex);
for (i = 0; i < CWC_ES_PIDS; i++)
if (ct->cs_epids[i])
tvhlog(LOG_DEBUG, "cwc", "%s using CWC %s:%d",
service_nicename(t), cwc->cwc_hostname, cwc->cwc_port);
+end:
pthread_mutex_unlock(&cwc->cwc_mutex);
+ pthread_mutex_unlock(&t->s_stream_mutex);
}
while((ct = LIST_FIRST(&cwc->cwc_services)) != NULL) {
t = (mpegts_service_t *)ct->td_service;
pthread_mutex_lock(&t->s_stream_mutex);
+ pthread_mutex_lock(&cwc->cwc_mutex);
cwc_service_destroy((th_descrambler_t *)&ct);
+ pthread_mutex_lock(&cwc->cwc_mutex);
pthread_mutex_unlock(&t->s_stream_mutex);
}