From fe06fb6fd535d8fae8947477a5dfcf504663bf02 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Mon, 14 Apr 2014 21:29:56 +0100 Subject: [PATCH] linuxdvb: ensure that the enabled flag is properly honoured --- src/input/mpegts.h | 1 + src/input/mpegts/linuxdvb/linuxdvb_adapter.c | 7 ++- src/input/mpegts/linuxdvb/linuxdvb_frontend.c | 54 +++++++++++++++---- src/input/mpegts/linuxdvb/linuxdvb_private.h | 2 +- src/input/mpegts/mpegts_input.c | 16 ++++++ 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index e0a56df8..a4c5d755 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -487,6 +487,7 @@ struct mpegts_input * Functions */ int (*mi_is_enabled) (mpegts_input_t*); + void (*mi_enabled_updated)(mpegts_input_t*); void (*mi_display_name) (mpegts_input_t*, char *buf, size_t len); int (*mi_is_free) (mpegts_input_t*); int (*mi_get_weight) (mpegts_input_t*); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c index f48915b4..74ba3c26 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c @@ -183,6 +183,7 @@ linux_dvb_get_type(int linux_type) static void linuxdvb_adapter_add ( const char *path ) { +#define MAX_DEV_OPEN_ATTEMPTS 20 extern int linuxdvb_adapter_mask; int a, i, j, r, fd; char fe_path[512], dmx_path[512], dvr_path[512]; @@ -226,7 +227,7 @@ linuxdvb_adapter_add ( const char *path ) /* Wait for access (first FE can take a fe ms to be setup) */ if (!i) { - for (j = 0; j < 10; j++) { + for (j = 0; j < MAX_DEV_OPEN_ATTEMPTS; j++) { if (!access(fe_path, R_OK | W_OK)) break; usleep(100000); } @@ -234,7 +235,7 @@ linuxdvb_adapter_add ( const char *path ) if (access(fe_path, R_OK | W_OK)) continue; /* Get frontend info */ - for (j = 0; j < 10; j++) { + for (j = 0; j < MAX_DEV_OPEN_ATTEMPTS; j++) { if ((fd = tvh_open(fe_path, O_RDWR, 0)) > 0) break; usleep(100000); } @@ -310,6 +311,7 @@ linuxdvb_adapter_add ( const char *path ) htsmsg_destroy(conf); return; // Note: save to return here as global_lock is held } + tvhinfo("linuxdvb", "adapter added %s", path); } /* Create frontend */ @@ -418,6 +420,7 @@ devdvb_create ( fsmonitor_t *fsm, const char *path ) static void devdvb_delete ( fsmonitor_t *fsm, const char *path ) { + tvhinfo("linuxdvb", "adapter removed %s", path); linuxdvb_adapter_del(path); } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 66f41726..d34a2d0c 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -93,9 +93,9 @@ const idclass_t linuxdvb_frontend_class = }, { .type = PT_BOOL, - .id = "noclosefe", - .name = "Keep FE open", - .off = offsetof(linuxdvb_frontend_t, lfe_noclosefe), + .id = "powersave", + .name = "Power Save", + .off = offsetof(linuxdvb_frontend_t, lfe_powersave), }, {} } @@ -192,6 +192,29 @@ const idclass_t linuxdvb_frontend_atsc_class = * Class methods * *************************************************************************/ +static void +linuxdvb_frontend_enabled_updated ( mpegts_input_t *mi ) +{ + char buf[512]; + linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi; + + mi->mi_display_name(mi, buf, sizeof(buf)); + + /* Ensure disabled */ + if (!mi->mi_enabled) { + tvhtrace("linuxdvb", "%s - disabling tuner", buf); + if (lfe->lfe_fe_fd > 0) + close(lfe->lfe_fe_fd); + gtimer_disarm(&lfe->lfe_monitor_timer); + + /* Ensure FE opened (if not powersave) */ + } else if (!lfe->lfe_powersave && lfe->lfe_fe_fd <= 0 && lfe->lfe_fe_path) { + lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0); + tvhtrace("linuxdvb", "%s - opening FE %s (%d)", + buf, lfe->lfe_fe_path, lfe->lfe_fe_fd); + } +} + static int linuxdvb_frontend_is_free ( mpegts_input_t *mi ) { @@ -416,9 +439,13 @@ linuxdvb_frontend_monitor ( void *aux ) lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf)); tvhtrace("linuxdvb", "%s - checking FE status", buf); + + /* Disabled */ + if (!lfe->mi_enabled && mmi) + mmi->mmi_mux->mm_stop(mmi->mmi_mux, 1); /* Close FE */ - if (lfe->lfe_fe_fd > 0 && !mmi && !lfe->lfe_noclosefe) { + if (lfe->lfe_fe_fd > 0 && !mmi && lfe->lfe_powersave) { tvhtrace("linuxdvb", "%s - closing frontend", buf); close(lfe->lfe_fe_fd); lfe->lfe_fe_fd = -1; @@ -433,9 +460,12 @@ linuxdvb_frontend_monitor ( void *aux ) } } - gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 1); + /* Stop timer */ if (!mmi) return; + /* re-arm */ + gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 1); + /* Get current status */ if (ioctl(lfe->lfe_fe_fd, FE_READ_STATUS, &fe_status) == -1) { tvhwarn("linuxdvb", "%s - FE_READ_STATUS error %s", buf, strerror(errno)); @@ -1173,11 +1203,12 @@ linuxdvb_frontend_create lfe->lfe_dvr_path = strdup(dvr_path); /* Input callbacks */ - lfe->mi_is_enabled = linuxdvb_frontend_is_enabled; - lfe->mi_start_mux = linuxdvb_frontend_start_mux; - lfe->mi_stop_mux = linuxdvb_frontend_stop_mux; - lfe->mi_network_list = linuxdvb_frontend_network_list; - lfe->mi_open_pid = linuxdvb_frontend_open_pid; + lfe->mi_is_enabled = linuxdvb_frontend_is_enabled; + lfe->mi_start_mux = linuxdvb_frontend_start_mux; + lfe->mi_stop_mux = linuxdvb_frontend_stop_mux; + lfe->mi_network_list = linuxdvb_frontend_network_list; + lfe->mi_open_pid = linuxdvb_frontend_open_pid; + lfe->mi_enabled_updated = linuxdvb_frontend_enabled_updated; /* Adapter link */ lfe->lfe_adapter = la; @@ -1199,6 +1230,9 @@ linuxdvb_frontend_create if (lfe->lfe_type == DVB_TYPE_S && !lfe->lfe_satconf) lfe->lfe_satconf = linuxdvb_satconf_create(lfe, sctype, scuuid, scconf); + /* Double check enabled */ + linuxdvb_frontend_enabled_updated((mpegts_input_t*)lfe); + return lfe; } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index ea96b48b..b5592d9d 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -108,7 +108,7 @@ struct linuxdvb_frontend * Configuration */ int lfe_fullmux; - int lfe_noclosefe; + int lfe_powersave; /* * Satconf (DVB-S only) diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 39fedb4d..40d98553 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -99,6 +99,21 @@ mpegts_input_class_network_rend ( void *obj ) return str; } +static void +mpegts_input_enabled_notify ( void *p ) +{ + mpegts_input_t *mi = p; + mpegts_mux_instance_t *mmi; + + /* Stop */ + LIST_FOREACH(mmi, &mi->mi_mux_active, mmi_active_link) + mmi->mmi_mux->mm_stop(mmi->mmi_mux, 1); + + /* Alert */ + if (mi->mi_enabled_updated) + mi->mi_enabled_updated(mi); +} + const idclass_t mpegts_input_class = { .ic_class = "mpegts_input", @@ -110,6 +125,7 @@ const idclass_t mpegts_input_class = .id = "enabled", .name = "Enabled", .off = offsetof(mpegts_input_t, mi_enabled), + .notify = mpegts_input_enabled_notify, .def.i = 1, }, {