diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 14e8ef68..28a9587d 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -425,7 +425,7 @@ th_dvb_mux_instance_t *dvb_mux_create(th_dvb_adapter_t *tda, uint16_t onid, uint16_t tsid, const char *network, const char *logprefix, int enabled, int initialscan, const char *identifier, - dvb_satconf_t *satconf); + dvb_satconf_t *satconf, int create); void dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *name); diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 9341988d..7f0eb0c3 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -155,7 +155,7 @@ th_dvb_mux_instance_t * dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, uint16_t onid, uint16_t tsid, const char *network, const char *source, int enabled, int initialscan, const char *identifier, - dvb_satconf_t *satconf) + dvb_satconf_t *satconf, int create) { th_dvb_mux_instance_t *tdmi, *c; char buf[200]; @@ -204,6 +204,11 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, tdmi->tdmi_network_id = onid; save = 1; } + if(network && strcmp(tdmi->tdmi_network ?: "", network)) { + free(tdmi->tdmi_network); + tdmi->tdmi_network = strdup(network); + save = 1; + } /* HACK - load old transports and remove old mux config */ if(identifier) { @@ -225,6 +230,9 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, return NULL; } + if (!create) + return NULL; + tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); if(identifier == NULL) { @@ -791,7 +799,7 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) tdmi = dvb_mux_create(tda, &dmc, onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled, initscan, - identifier, NULL); + identifier, NULL, 1); if(tdmi != NULL) { if((s = htsmsg_get_str(m, "status")) != NULL) @@ -1170,7 +1178,7 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda, } dmc.dmc_polarisation = polarisation; - tdmi = dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL, NULL); + tdmi = dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL, NULL, 1); if(tdmi == NULL) return "Mux already exist"; @@ -1197,7 +1205,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, tdmi_src->tdmi_transport_stream_id, tdmi_src->tdmi_network, "copy operation", tdmi_src->tdmi_enabled, - 1, NULL, satconf); + 1, NULL, satconf, 1); if(tdmi_dst == NULL) return -1; // Already exist diff --git a/src/dvb/dvb_preconf.c b/src/dvb/dvb_preconf.c index 755340db..d1805242 100644 --- a/src/dvb/dvb_preconf.c +++ b/src/dvb/dvb_preconf.c @@ -98,7 +98,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net, dmc.dmc_satconf = dvb_satconf_entry_find(tda, satconf, 0); - dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL, NULL); + dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL, NULL, 1); } } diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index ecc540b8..26f410e9 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -332,22 +332,19 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, tsid = ptr[0] << 8 | ptr[1]; onid = ptr[5] << 8 | ptr[6]; if (tableid == 0x42) { - if(tdmi->tdmi_transport_stream_id != tsid) + if(tdmi->tdmi_transport_stream_id != tsid || tdmi->tdmi_network_id != onid) return -1; - if(!tdmi->tdmi_network_id) - dvb_mux_set_onid(tdmi, onid); } else { LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id != onid) break; - if (!tdmi) return 0; + if (!tdmi) return -1; } // version = ptr[2] >> 1 & 0x1f; // section_number = ptr[3]; // last_section_number = ptr[4]; - // original_network_id = ptr[5] << 8 | ptr[6]; // reserved = ptr[7]; if((ptr[2] & 1) == 0) { @@ -478,7 +475,6 @@ static int dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - th_dvb_mux_instance_t *other; th_dvb_adapter_t *tda = tdmi->tdmi_adapter; uint16_t service, pmt, tsid; @@ -491,21 +487,8 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, } tsid = (ptr[0] << 8) | ptr[1]; - - // Make sure this TSID is not already known on another mux - // That might indicate that we have accedentally received a PAT - // from another mux - LIST_FOREACH(other, &tda->tda_muxes, tdmi_adapter_link) - if(other != tdmi && - other->tdmi_conf.dmc_satconf == tdmi->tdmi_conf.dmc_satconf && - other->tdmi_transport_stream_id == tsid && - other->tdmi_network_id == tdmi->tdmi_network_id) - return -1; - - if(tdmi->tdmi_transport_stream_id == 0xffff) - dvb_mux_set_tsid(tdmi, tsid); - else if (tdmi->tdmi_transport_stream_id != tsid) - return -1; // TSID mismatches, skip packet, may be from another mux + if (tdmi->tdmi_transport_stream_id != tsid) + return -1; ptr += 5; len -= 5; @@ -650,14 +633,11 @@ static const fe_hierarchy_t hierarchy_info_tab [8] = { */ static int dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid) + uint16_t tsid, uint16_t onid, const char *netname) { struct dvb_mux_conf dmc; int freq, symrate; - if(!tdmi->tdmi_adapter->tda_autodiscovery) - return -1; - if(len < 11) return -1; @@ -687,8 +667,10 @@ dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07]; - dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, - "automatic mux discovery", 1, 1, NULL, NULL); + dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, netname, + "automatic mux discovery", 1, 1, NULL, NULL, + tdmi->tdmi_adapter->tda_autodiscovery); + return 0; } @@ -697,15 +679,12 @@ dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, */ static int dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid) + uint16_t tsid, uint16_t onid, const char *netname) { int freq, symrate; // uint16_t orbital_pos; struct dvb_mux_conf dmc; - if(!tdmi->tdmi_adapter->tda_autodiscovery) - return -1; - if(len < 11) return -1; @@ -772,8 +751,10 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, } #endif + dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, - "automatic mux discovery", 1, 1, NULL, tdmi->tdmi_conf.dmc_satconf); + "automatic mux discovery", 1, 1, NULL, tdmi->tdmi_conf.dmc_satconf, + tdmi->tdmi_adapter->tda_autodiscovery); return 0; } @@ -784,14 +765,11 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, */ static int dvb_table_terr_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid) + uint16_t tsid, uint16_t onid, const char *netname) { struct dvb_mux_conf dmc; int freq; - if(!tdmi->tdmi_adapter->tda_autodiscovery) - return -1; - if(len < 11) return -1; @@ -812,8 +790,9 @@ dvb_table_terr_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, dmc.dmc_fe_params.u.ofdm.guard_interval=guard_interval_tab[(ptr[6] & 0x18) >> 3]; dmc.dmc_fe_params.u.ofdm.transmission_mode=transmission_mode_tab[(ptr[6] & 0x06) >> 1]; - dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, - "automatic mux discovery", 1, 1, NULL, NULL); + dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, netname, + "automatic mux discovery", 1, 1, NULL, NULL, + tdmi->tdmi_adapter->tda_autodiscovery); return 0; } @@ -866,107 +845,89 @@ static int dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - uint8_t tag, tlen; - int ntl; - char networkname[256]; + uint8_t dtag, dlen; + uint16_t llen; + char netname[256]; uint16_t tsid, onid; uint16_t network_id = (ptr[0] << 8) | ptr[1]; + netname[0] = '\0'; - if(tdmi->tdmi_adapter->tda_nitoid) { - if(tableid != 0x41) - return -1; - - if(network_id != tdmi->tdmi_adapter->tda_nitoid) - return -1; - - } else { - if(tableid != 0x40) - return -1; - } - - if((ptr[2] & 1) == 0) { - /* current_next_indicator == next, skip this */ - return -1; - } - - ptr += 5; - len -= 5; - - ntl = ((ptr[0] & 0xf) << 8) | ptr[1]; - ptr += 2; - len -= 2; - if(ntl > len) + /* Check NID */ + if(tdmi->tdmi_adapter->tda_nitoid && + tdmi->tdmi_adapter->tda_nitoid != network_id) return -1; - while(ntl > 2) { - tag = *ptr++; - tlen = *ptr++; - len -= 2; - ntl -= 2; + /* Ignore non-current */ + if((ptr[2] & 1) == 0) + return -1; - switch(tag) { - case DVB_DESC_NETWORK_NAME: - if(dvb_get_string(networkname, sizeof(networkname), ptr, tlen, NULL, NULL)) - return -1; + /* Network descriptors */ + llen = ((ptr[5] & 0xf) << 8) | ptr[6]; + ptr += 7; + len -= llen + 7; + if (len < 0) + return -1; - if(strcmp(tdmi->tdmi_network ?: "", networkname)) - dvb_mux_set_networkname(tdmi, networkname); - break; + while(llen > 2) { + dtag = ptr[0]; + dlen = ptr[1]; + + switch(dtag) { + case DVB_DESC_NETWORK_NAME: + if(dvb_get_string(netname, sizeof(netname), ptr+2, dlen, NULL, NULL)) + return -1; + break; } - ptr += tlen; - len -= tlen; - ntl -= tlen; + ptr += dlen + 2; + llen -= dlen + 2; } - - if(len < 2) + if (llen) return -1; - ntl = ((ptr[0] & 0xf) << 8) | ptr[1]; + /* Transport loop */ + llen = ((ptr[0] & 0xf) << 8) | ptr[1]; ptr += 2; len -= 2; - - if(len < ntl) + if (llen > len) return -1; - while(len >= 6) { tsid = ( ptr[0] << 8) | ptr[1]; onid = ( ptr[2] << 8) | ptr[3]; - ntl = ((ptr[4] & 0xf) << 8) | ptr[5]; + llen = ((ptr[4] & 0xf) << 8) | ptr[5]; ptr += 6; - len -= 6; - if(ntl > len) - break; + len -= llen + 6; + if(len < 0) + return -1; - while(ntl > 2) { - tag = *ptr++; - tlen = *ptr++; - len -= 2; - ntl -= 2; + while(llen > 2) { + dtag = ptr[0]; + dlen = ptr[1]; - switch(tag) { - case DVB_DESC_SAT: - if(tdmi->tdmi_adapter->tda_type == FE_QPSK) - dvb_table_sat_delivery(tdmi, ptr, tlen, tsid, onid); - break; - case DVB_DESC_CABLE: - if(tdmi->tdmi_adapter->tda_type == FE_QAM) - dvb_table_cable_delivery(tdmi, ptr, tlen, tsid, onid); - break; - case DVB_DESC_TERR: - if(tdmi->tdmi_adapter->tda_type == FE_OFDM) - dvb_table_terr_delivery(tdmi, ptr, tlen, tsid, onid); - break; - case DVB_DESC_LOCAL_CHAN: - dvb_table_local_channel(tdmi, ptr, tlen, tsid, onid); - break; + switch(dtag) { + case DVB_DESC_SAT: + if(tdmi->tdmi_adapter->tda_type == FE_QPSK) + dvb_table_sat_delivery(tdmi, ptr+2, dlen, tsid, onid, netname); + break; + case DVB_DESC_CABLE: + if(tdmi->tdmi_adapter->tda_type == FE_QAM) + dvb_table_cable_delivery(tdmi, ptr+2, dlen, tsid, onid, netname); + break; + case DVB_DESC_TERR: + if(tdmi->tdmi_adapter->tda_type == FE_OFDM) + dvb_table_terr_delivery(tdmi, ptr+2, dlen, tsid, onid, netname); + break; + case DVB_DESC_LOCAL_CHAN: + dvb_table_local_channel(tdmi, ptr+2, dlen, tsid, onid); + break; } - ptr += tlen; - len -= tlen; - ntl -= tlen; + llen -= dlen + 2; + ptr += dlen + 2; } + if (llen) + return -1; } return 0; }