From: Jaroslav Kysela Date: Sun, 4 Oct 2015 14:48:26 +0000 (+0200) Subject: linuxdvb: add master tuner support, fixes #2952 X-Git-Tag: v4.2.1~1977 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ac47b98dd610c9b4a35f6321f2e2378758844e09;p=thirdparty%2Ftvheadend.git linuxdvb: add master tuner support, fixes #2952 --- diff --git a/src/descrambler/dvbcam.c b/src/descrambler/dvbcam.c index 273997b77..3fe0c9a92 100644 --- a/src/descrambler/dvbcam.c +++ b/src/descrambler/dvbcam.c @@ -218,10 +218,10 @@ dvbcam_service_start(service_t *t) void dvbcam_service_stop(service_t *t) { - dvbcam_active_service_t *as, *as_tmp; + dvbcam_active_service_t *as, *as_tmp; linuxdvb_ca_t *ca = NULL; dvbcam_active_cam_t *ac2; - uint8_t slot; + uint8_t slot = -1; tvhtrace("dvbcam", "stop service %p", t); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index ea21380fb..e33b2a138 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -184,6 +184,13 @@ linuxdvb_en50494_freq return rfreq; } +static int +linuxdvb_en50494_match + ( linuxdvb_diseqc_t *ld, dvb_mux_t *lm1, dvb_mux_t *lm2 ) +{ + return lm1 == lm2; +} + static int linuxdvb_en50494_tune ( linuxdvb_diseqc_t *ld, dvb_mux_t *lm, @@ -321,6 +328,7 @@ linuxdvb_en50494_create0 le->le_frequency = 0; le->le_pin = LINUXDVB_EN50494_NOPIN; le->ld_freq = linuxdvb_en50494_freq; + le->ld_match = linuxdvb_en50494_match; ld = linuxdvb_diseqc_create0((linuxdvb_diseqc_t *)le, NULL, &linuxdvb_en50494_class, conf, diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 03b64d61c..fc75e7327 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -189,6 +189,32 @@ linuxdvb_frontend_dvbs_class_satconf_get ( void *self ) return &s; } +static htsmsg_t * +linuxdvb_frontend_dvbs_class_master_enum( void * self, const char *lang ) +{ + linuxdvb_frontend_t *lfe = self, *lfe2; + linuxdvb_adapter_t *la; + tvh_hardware_t *th; + htsmsg_t *m = htsmsg_create_list(); + htsmsg_t *e = htsmsg_create_map(); + htsmsg_add_str(e, "key", ""); + htsmsg_add_str(e, "val", N_("This Tuner")); + htsmsg_add_msg(m, NULL, e); + LIST_FOREACH(th, &tvh_hardware, th_link) { + if (!idnode_is_instance(&th->th_id, &linuxdvb_adapter_class)) continue; + la = (linuxdvb_adapter_t*)th; + LIST_FOREACH(lfe2, &la->la_frontends, lfe_link) { + if (lfe2 != lfe && lfe2->lfe_type == lfe->lfe_type) { + e = htsmsg_create_map(); + htsmsg_add_str(e, "key", idnode_uuid_as_sstr(&lfe2->ti_id)); + htsmsg_add_str(e, "val", lfe2->mi_name); + htsmsg_add_msg(m, NULL, e); + } + } + } + return m; +} + const idclass_t linuxdvb_frontend_dvbs_class = { .ic_super = &linuxdvb_frontend_class, @@ -206,6 +232,34 @@ const idclass_t linuxdvb_frontend_dvbs_class = .list = linuxdvb_satconf_type_list, .def.s = "simple" }, + { + .type = PT_STR, + .id = "fe_master", + .name = N_("Master Tuner"), + .list = linuxdvb_frontend_dvbs_class_master_enum, + .off = offsetof(linuxdvb_frontend_t, lfe_master), + }, + { + .id = "networks", + .type = PT_NONE, + }, + {} + } +}; + +const idclass_t linuxdvb_frontend_dvbs_slave_class = +{ + .ic_super = &linuxdvb_frontend_class, + .ic_class = "linuxdvb_frontend_dvbs", + .ic_caption = N_("Linux DVB-S Slave Frontend"), + .ic_properties = (const property_t[]){ + { + .type = PT_STR, + .id = "fe_master", + .name = N_("Master Tuner"), + .list = linuxdvb_frontend_dvbs_class_master_enum, + .off = offsetof(linuxdvb_frontend_t, lfe_master), + }, { .id = "networks", .type = PT_NONE, @@ -303,11 +357,37 @@ linuxdvb_frontend_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm ) static int linuxdvb_frontend_is_enabled ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags ) { - linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi; + linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2; + linuxdvb_adapter_t *la; + tvh_hardware_t *th; + if (lfe->lfe_fe_path == NULL) return 0; if (!mpegts_input_is_enabled(mi, mm, flags)) return 0; if (access(lfe->lfe_fe_path, R_OK | W_OK)) return 0; if (lfe->lfe_in_setup) return 0; + if (lfe->lfe_type != DVB_TYPE_S) return 0; + + /* check if any "blocking" tuner is running */ + LIST_FOREACH(th, &tvh_hardware, th_link) { + if (!idnode_is_instance(&th->th_id, &linuxdvb_adapter_class)) continue; + la = (linuxdvb_adapter_t*)th; + LIST_FOREACH(lfe2, &la->la_frontends, lfe_link) { + if (lfe2 == lfe) continue; + if (lfe2->lfe_type != DVB_TYPE_S) continue; + if (lfe->lfe_master && !strcmp(lfe->lfe_master, idnode_uuid_as_sstr(&lfe2->ti_id))) { + if (lfe2->lfe_satconf == NULL) + return 0; /* invalid master */ + return linuxdvb_satconf_match_mux(lfe2->lfe_satconf, mm); + } + if (lfe2->lfe_master && + !strcmp(lfe2->lfe_master, idnode_uuid_as_sstr(&lfe->ti_id)) && + lfe2->lfe_refcount > 0) { + if (lfe->lfe_satconf == NULL) + return 0; + return linuxdvb_satconf_match_mux(lfe->lfe_satconf, mm); + } + } + } return 1; } @@ -316,8 +396,11 @@ linuxdvb_frontend_stop_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) { char buf1[256], buf2[256]; - - linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi; + linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2; + + if (lfe->lfe_master) + assert(lfe->lfe_type == DVB_TYPE_S); + mi->mi_display_name(mi, buf1, sizeof(buf1)); mpegts_mux_nice_name(mmi->mmi_mux, buf2, sizeof(buf2)); tvhdebug("linuxdvb", "%s - stopping %s", buf1, buf2); @@ -340,9 +423,31 @@ linuxdvb_frontend_stop_mux /* Ensure it won't happen immediately */ gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 2); - if (lfe->lfe_satconf) + if (lfe->lfe_satconf && lfe->lfe_refcount == 1) linuxdvb_satconf_post_stop_mux(lfe->lfe_satconf); + if (lfe->lfe_master) { + lfe2 = (linuxdvb_frontend_t *)idnode_find(lfe->lfe_master, &linuxdvb_frontend_class, NULL); + if (lfe2->lfe_type != lfe->lfe_type) + lfe2 = NULL; + if (lfe2) { /* master tuner shutdown procedure */ + assert(lfe2->lfe_refcount >= 0); + if (--lfe2->lfe_refcount == 0) { + lfe2->lfe_ready = 0; + lfe2->lfe_locked = 0; + lfe2->lfe_status = 0; + lfe2->lfe_status2 = 0; + /* Ensure it won't happen immediately */ + gtimer_arm(&lfe2->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 2); + if (lfe2->lfe_satconf) + linuxdvb_satconf_post_stop_mux(lfe2->lfe_satconf); + lfe2->lfe_in_setup = 0; + lfe2->lfe_freq = 0; + } + } + } + + lfe->lfe_refcount--; lfe->lfe_in_setup = 0; lfe->lfe_freq = 0; mpegts_pid_done(&lfe->lfe_pids); @@ -352,17 +457,47 @@ static int linuxdvb_frontend_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) { - linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi; - int res; + linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2; + int res, f; + + assert(lfe->lfe_in_setup == 0); + lfe->lfe_refcount++; lfe->lfe_in_setup = 1; lfe->lfe_ioctls = 0; + + if (lfe->lfe_master) { + assert(lfe->lfe_type == DVB_TYPE_S); + lfe2 = (linuxdvb_frontend_t *)idnode_find(lfe->lfe_master, &linuxdvb_frontend_class, NULL); + if (lfe2->lfe_type != lfe->lfe_type) + lfe2 = NULL; + res = SM_CODE_TUNING_FAILED; + if (lfe2) { + f = linuxdvb_satconf_lnb_freq(lfe2->lfe_satconf, mmi); + if (f <= 0) + goto end; + if (lfe2->lfe_refcount++ == 0) { + lfe2->lfe_in_setup = 1; + lfe2->lfe_ioctls = 0; + res = linuxdvb_satconf_start_mux(lfe2->lfe_satconf, mmi, 0); + if (res) + goto end; + } + res = linuxdvb_frontend_tune1((linuxdvb_frontend_t*)mi, mmi, f); + } + goto end; + } + if (lfe->lfe_satconf) - res = linuxdvb_satconf_start_mux(lfe->lfe_satconf, mmi); + res = linuxdvb_satconf_start_mux(lfe->lfe_satconf, mmi, lfe->lfe_refcount > 1); else res = linuxdvb_frontend_tune1((linuxdvb_frontend_t*)mi, mmi, -1); - if (res) + +end: + if (res) { lfe->lfe_in_setup = 0; + lfe->lfe_refcount--; + } return res; } @@ -459,7 +594,7 @@ linuxdvb_frontend_monitor ( void *aux ) mmi->mmi_mux->mm_stop(mmi->mmi_mux, 1, SM_CODE_ABORTED); /* Close FE */ - if (lfe->lfe_fe_fd > 0 && !mmi && lfe->lfe_powersave) { + if (lfe->lfe_fe_fd > 0 && !lfe->lfe_refcount && lfe->lfe_powersave) { tvhtrace("linuxdvb", "%s - closing frontend", buf); close(lfe->lfe_fe_fd); lfe->lfe_fe_fd = -1; @@ -1116,6 +1251,7 @@ linuxdvb_frontend_clear /* Open FE */ lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1)); + tvhtrace("linuxdvb", "%s - frontend clear", buf1); if (lfe->lfe_fe_fd <= 0) { lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0); @@ -1513,11 +1649,19 @@ linuxdvb_frontend_create dvb_fe_type_t type, const char *name ) { const idclass_t *idc; - const char *str, *uuid = NULL, *scuuid = NULL, *sctype = NULL; - char id[12], lname[256]; + const char *str, *uuid = NULL, *muuid = NULL, *scuuid = NULL, *sctype = NULL; + char id[16], lname[256]; linuxdvb_frontend_t *lfe; htsmsg_t *scconf = NULL; + /* Tuner slave */ + snprintf(id, sizeof(id), "master for #%d", number); + if (conf && type == DVB_TYPE_S) { + muuid = htsmsg_get_str(conf, id); + if (muuid && uuid && !strcmp(muuid, uuid)) + muuid = NULL; + } + /* Internal config ID */ snprintf(id, sizeof(id), "%s #%d", dvb_type2str(type), number); if (conf) @@ -1537,7 +1681,8 @@ linuxdvb_frontend_create /* Class */ if (type == DVB_TYPE_S) - idc = &linuxdvb_frontend_dvbs_class; + idc = muuid ? &linuxdvb_frontend_dvbs_slave_class : + &linuxdvb_frontend_dvbs_class; else if (type == DVB_TYPE_C) idc = &linuxdvb_frontend_dvbc_class; else if (type == DVB_TYPE_T) @@ -1555,7 +1700,8 @@ linuxdvb_frontend_create // in mpegts_input_create()). So we must set early. lfe = calloc(1, sizeof(linuxdvb_frontend_t)); lfe->lfe_number = number; - lfe->lfe_type = type; + lfe->lfe_type = type; + lfe->lfe_master = muuid ? strdup(muuid) : NULL; strncpy(lfe->lfe_name, name, sizeof(lfe->lfe_name)); lfe->lfe_name[sizeof(lfe->lfe_name)-1] = '\0'; lfe->lfe_ibuf_size = 18800; @@ -1598,7 +1744,7 @@ linuxdvb_frontend_create mpegts_pid_init(&lfe->lfe_pids); /* Satconf */ - if (conf) { + if (conf && !muuid) { if ((scconf = htsmsg_get_map(conf, "satconf"))) { sctype = htsmsg_get_str(scconf, "type"); scuuid = htsmsg_get_str(scconf, "uuid"); @@ -1606,7 +1752,7 @@ linuxdvb_frontend_create } /* Create satconf */ - if (lfe->lfe_type == DVB_TYPE_S && !lfe->lfe_satconf) + if (lfe->lfe_type == DVB_TYPE_S && !lfe->lfe_satconf && !muuid) lfe->lfe_satconf = linuxdvb_satconf_create(lfe, sctype, scuuid, scconf); /* Double check enabled */ @@ -1618,23 +1764,29 @@ linuxdvb_frontend_create void linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *fe ) { - char id[12]; + char id[16]; htsmsg_t *m = htsmsg_create_map(); /* Save frontend */ mpegts_input_save((mpegts_input_t*)lfe, m); htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_type)); htsmsg_add_str(m, "uuid", idnode_uuid_as_sstr(&lfe->ti_id)); - if (lfe->lfe_satconf) { + if (lfe->lfe_satconf && !lfe->lfe_master) { htsmsg_t *s = htsmsg_create_map(); linuxdvb_satconf_save(lfe->lfe_satconf, s); htsmsg_add_str(s, "uuid", idnode_uuid_as_sstr(&lfe->lfe_satconf->ls_id)); htsmsg_add_msg(m, "satconf", s); } + htsmsg_delete_field(m, "fe_master"); /* Add to list */ snprintf(id, sizeof(id), "%s #%d", dvb_type2str(lfe->lfe_type), lfe->lfe_number); htsmsg_add_msg(fe, id, m); + + if (lfe->lfe_master) { + snprintf(id, sizeof(id), "master for #%d", lfe->lfe_number); + htsmsg_add_str(fe, id, lfe->lfe_master); + } } void @@ -1659,6 +1811,7 @@ linuxdvb_frontend_delete ( linuxdvb_frontend_t *lfe ) free(lfe->lfe_fe_path); free(lfe->lfe_dmx_path); free(lfe->lfe_dvr_path); + free(lfe->lfe_master); /* Delete satconf */ if (lfe->lfe_satconf) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_lnb.c b/src/input/mpegts/linuxdvb/linuxdvb_lnb.c index 7b095920a..94c50e137 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_lnb.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_lnb.c @@ -83,6 +83,25 @@ linuxdvb_lnb_standard_freq return (uint32_t)abs(f); } +static int +linuxdvb_lnb_standard_match + ( linuxdvb_lnb_t *l, dvb_mux_t *lm1, dvb_mux_t *lm2 ) +{ + linuxdvb_lnb_conf_t *lnb = (linuxdvb_lnb_conf_t*)l; + dvb_mux_conf_t *dmc1 = &lm1->lm_tuning; + dvb_mux_conf_t *dmc2 = &lm2->lm_tuning; + + if (lnb->lnb_switch) { + uint32_t hi1 = dmc1->dmc_fe_freq > lnb->lnb_switch; + uint32_t hi2 = dmc2->dmc_fe_freq > lnb->lnb_switch; + if (hi1 != hi2) + return 0; + } + if (dmc1->u.dmc_fe_qpsk.polarisation != dmc2->u.dmc_fe_qpsk.polarisation) + return 0; + return 1; +} + static int linuxdvb_lnb_standard_band ( linuxdvb_lnb_t *l, dvb_mux_t *lm ) @@ -165,6 +184,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -178,6 +198,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -191,6 +212,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -204,6 +226,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -217,6 +240,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -230,6 +254,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -243,6 +268,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_inverted_pol, }, @@ -256,6 +282,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -269,6 +296,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -282,6 +310,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_standard_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_standard_band, .lnb_pol = linuxdvb_lnb_standard_pol, }, @@ -295,6 +324,7 @@ struct linuxdvb_lnb_conf linuxdvb_lnb_all[] = { .ld_tune = linuxdvb_lnb_standard_tune, }, .lnb_freq = linuxdvb_lnb_bandstack_freq, + .lnb_match = linuxdvb_lnb_standard_match, .lnb_band = linuxdvb_lnb_bandstack_band, .lnb_pol = linuxdvb_lnb_bandstack_pol, }, diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 079353606..cc7e98f4e 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -68,6 +68,8 @@ typedef TAILQ_HEAD(linuxdvb_satconf_ele_list,linuxdvb_satconf_ele) linuxdvb_satc typedef TAILQ_HEAD(linuxdvb_ca_capmt_queue,linuxdvb_ca_capmt) linuxdvb_ca_capmt_queue_t; #endif +extern const idclass_t linuxdvb_adapter_class; + struct linuxdvb_adapter { tvh_hardware_t; @@ -131,6 +133,7 @@ struct linuxdvb_frontend /* * Tuning */ + int lfe_refcount; int lfe_ready; int lfe_in_setup; int lfe_locked; @@ -146,6 +149,7 @@ struct linuxdvb_frontend /* * Configuration */ + char *lfe_master; int lfe_powersave; int lfe_tune_repeats; uint32_t lfe_skip_bytes; @@ -310,6 +314,7 @@ struct linuxdvb_diseqc linuxdvb_satconf_ele_t *ld_satconf; int (*ld_grace) (linuxdvb_diseqc_t *ld, dvb_mux_t *lm); int (*ld_freq) (linuxdvb_diseqc_t *ld, dvb_mux_t *lm, int freq); + int (*ld_match) (linuxdvb_diseqc_t *ld, dvb_mux_t *lm1, dvb_mux_t *lm2); int (*ld_tune) (linuxdvb_diseqc_t *ld, dvb_mux_t *lm, linuxdvb_satconf_t *lsp, linuxdvb_satconf_ele_t *ls, int vol, int pol, int band, int freq); @@ -320,9 +325,10 @@ struct linuxdvb_diseqc struct linuxdvb_lnb { linuxdvb_diseqc_t; - uint32_t (*lnb_freq)(linuxdvb_lnb_t*, dvb_mux_t*); - int (*lnb_band)(linuxdvb_lnb_t*, dvb_mux_t*); - int (*lnb_pol) (linuxdvb_lnb_t*, dvb_mux_t*); + uint32_t (*lnb_freq) (linuxdvb_lnb_t*, dvb_mux_t*); + int (*lnb_match)(linuxdvb_lnb_t*, dvb_mux_t*, dvb_mux_t*); + int (*lnb_band) (linuxdvb_lnb_t*, dvb_mux_t*); + int (*lnb_pol) (linuxdvb_lnb_t*, dvb_mux_t*); }; struct linuxdvb_en50494 @@ -455,11 +461,17 @@ int linuxdvb_satconf_get_priority int linuxdvb_satconf_get_grace ( linuxdvb_satconf_t *ls, mpegts_mux_t *mm ); - + +int linuxdvb_satconf_lnb_freq + ( linuxdvb_satconf_t *ls, mpegts_mux_instance_t *mmi ); + void linuxdvb_satconf_post_stop_mux( linuxdvb_satconf_t *ls ); int linuxdvb_satconf_start_mux - ( linuxdvb_satconf_t *ls, mpegts_mux_instance_t *mmi ); + ( linuxdvb_satconf_t *ls, mpegts_mux_instance_t *mmi, int skip_diseqc ); + +int linuxdvb_satconf_match_mux + ( linuxdvb_satconf_t *ls, mpegts_mux_t *mm ); int linuxdvb_satconf_start ( linuxdvb_satconf_t *ls, int delay, int vol ); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 157be159d..7751d0460 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -665,6 +665,7 @@ void linuxdvb_satconf_post_stop_mux ( linuxdvb_satconf_t *ls ) { + ls->ls_mmi = NULL; gtimer_disarm(&ls->ls_diseqc_timer); if (ls->ls_frontend && ls->ls_lnb_poweroff) { linuxdvb_diseqc_set_volt(ls, -1); @@ -825,14 +826,39 @@ linuxdvb_satconf_ele_tune_cb ( void *o ) } int -linuxdvb_satconf_start_mux +linuxdvb_satconf_lnb_freq ( linuxdvb_satconf_t *ls, mpegts_mux_instance_t *mmi ) +{ + int f; + linuxdvb_satconf_ele_t *lse = linuxdvb_satconf_find_ele(ls, mmi->mmi_mux); + dvb_mux_t *lm = (dvb_mux_t*)mmi->mmi_mux; + + if (!lse->lse_lnb) + return -1; + + f = lse->lse_lnb->lnb_freq(lse->lse_lnb, lm); + if (f == (uint32_t)-1) + return -1; + + /* calculate tuning frequency for en50494 */ + if (lse->lse_en50494) { + f = lse->lse_en50494->ld_freq(lse->lse_en50494, lm, f); + if (f < 0) { + tvherror("en50494", "invalid tuning freq"); + return -1; + } + } + return f; +} + +int +linuxdvb_satconf_start_mux + ( linuxdvb_satconf_t *ls, mpegts_mux_instance_t *mmi, int skip_diseqc ) { int r; uint32_t f; linuxdvb_satconf_ele_t *lse = linuxdvb_satconf_find_ele(ls, mmi->mmi_mux); linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)ls->ls_frontend; - dvb_mux_t *lm = (dvb_mux_t*)mmi->mmi_mux; /* Not fully configured */ if (!lse) return SM_CODE_TUNING_FAILED; @@ -845,23 +871,16 @@ linuxdvb_satconf_start_mux if (!lse->lse_lnb) return SM_CODE_TUNING_FAILED; + if (skip_diseqc) { + f = linuxdvb_satconf_lnb_freq(ls, mmi); + if (f < 0) + return SM_CODE_TUNING_FAILED; + return linuxdvb_frontend_tune1(lfe, mmi, f); + } if (ls->ls_early_tune) { - - f = lse->lse_lnb->lnb_freq(lse->lse_lnb, lm); - if (f == (uint32_t)-1) + f = linuxdvb_satconf_lnb_freq(ls, mmi); + if (f < 0) return SM_CODE_TUNING_FAILED; - - /* calculate tuning frequency for en50494 */ - if (lse->lse_en50494) { - r = lse->lse_en50494->ld_freq(lse->lse_en50494, lm, f); - if (r < 0) { - tvherror("en50494", "invalid tuning freq"); - return -1; - } - /* tune frequency for the frontend */ - f = r; - } - r = linuxdvb_frontend_tune0(lfe, mmi, f); if (r) return r; } else { @@ -889,6 +908,47 @@ linuxdvb_satconf_reset ls->ls_last_tone_off = 0; } +/* + * return 0 if passed mux cannot be used simultanously with given + * diseqc config + */ +int +linuxdvb_satconf_match_mux + ( linuxdvb_satconf_t *ls, mpegts_mux_t *mm ) +{ + mpegts_mux_instance_t *mmi = ls->ls_mmi; + + if (mmi == NULL || mmi->mmi_mux == NULL) + return 1; + + linuxdvb_satconf_ele_t *lse1 = linuxdvb_satconf_find_ele(ls, mm); + linuxdvb_satconf_ele_t *lse2 = linuxdvb_satconf_find_ele(ls, mmi->mmi_mux); + dvb_mux_t *lm1 = (dvb_mux_t*)mmi->mmi_mux; + dvb_mux_t *lm2 = (dvb_mux_t*)mm; + +#if ENABLE_TRACE + char buf1[256], buf2[256]; + dvb_mux_conf_str(&lm1->lm_tuning, buf1, sizeof(buf1)); + dvb_mux_conf_str(&lm2->lm_tuning, buf2, sizeof(buf2)); + tvhtrace("diseqc", "match mux 1 - %s", buf1); + tvhtrace("diseqc", "match mux 2 - %s", buf2); +#endif + + if (lse1 != lse2) { + tvhtrace("diseqc", "match position failed"); + return 0; + } + if (!lse1->lse_lnb->lnb_match(lse1->lse_lnb, lm1, lm2)) { + tvhtrace("diseqc", "match LNB failed"); + return 0; + } + if (lse1->lse_en50494 && !lse1->lse_en50494->ld_match(lse1->lse_en50494, lm1, lm2)) { + tvhtrace("diseqc", "match en50494 failed"); + return 0; + } + return 1; +} + /* ************************************************************************** * Create/Delete satconf * *************************************************************************/