linuxdvb: I now have basic diseqc framework (untested) in place.

This includes delayed progamming of diseqc commands and a dynamic grace
period that includes the total diseqc delay.

I think that I still need to understand whether doing independent progamming
of each component in the way I have will work. I'm honestly not sure!
This commit is contained in:
Adam Sutton 2013-06-21 17:06:44 +01:00
parent 120c69e672
commit 02c14a12a9
5 changed files with 128 additions and 50 deletions

View file

@ -405,6 +405,7 @@ struct mpegts_input
void (*mi_started_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
void (*mi_stopped_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
int (*mi_has_subscription) (mpegts_input_t*, mpegts_mux_t *mm);
int (*mi_grace_period) (mpegts_input_t*, mpegts_mux_t *mm);
};
#endif /* __TVH_MPEGTS_H__ */

View file

@ -29,7 +29,6 @@ typedef struct linuxdvb_frontend linuxdvb_frontend_t;
typedef struct linuxdvb_network linuxdvb_network_t;
typedef struct linuxdvb_mux linuxdvb_mux_t;
typedef struct linuxdvb_satconf linuxdvb_satconf_t;
typedef struct linuxdvb_lnb linuxdvb_lnb_t;
typedef LIST_HEAD(,linuxdvb_hardware) linuxdvb_hardware_list_t;
@ -222,12 +221,21 @@ mpegts_service_t *linuxdvb_service_create0
const char *uuid, htsmsg_t *conf);
/*
* LNB
* Diseqc gear
*/
typedef struct linuxdvb_diseqc linuxdvb_diseqc_t;
typedef struct linuxdvb_lnb linuxdvb_lnb_t;
struct linuxdvb_diseqc
{
int (*ld_grace) (linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm);
int (*ld_tune) (linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, int fd);
};
struct linuxdvb_lnb
{
uint32_t (*lnb_frequency)(linuxdvb_lnb_t*, linuxdvb_mux_t*);
int (*lnb_tune)(linuxdvb_lnb_t*, linuxdvb_mux_t *lm, int fd);
linuxdvb_diseqc_t;
uint32_t (*lnb_freq)(linuxdvb_lnb_t*, linuxdvb_mux_t*);
};
/*
@ -237,9 +245,16 @@ struct linuxdvb_satconf
{
linuxdvb_frontend_t;
/* Links */
mpegts_input_t *ls_frontend;
linuxdvb_lnb_t *ls_lnb;
mpegts_input_t *ls_frontend;
mpegts_mux_instance_t *ls_mmi;
/* Diseqc gear */
linuxdvb_lnb_t *ls_lnb;
linuxdvb_diseqc_t *ls_switch;
linuxdvb_diseqc_t *ls_rotor;
gtimer_t ls_diseqc_timer;
int ls_diseqc_idx;
};
void linuxdvb_satconf_init ( void );

View file

@ -231,6 +231,56 @@ linuxdvb_satconf_stop_mux
{
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
ls->ls_frontend->mi_stop_mux(ls->ls_frontend, mmi);
gtimer_disarm(&ls->ls_diseqc_timer);
}
static void linuxdvb_satconf_tune_cb ( void *o );
static int
linuxdvb_satconf_tune ( linuxdvb_satconf_t *ls )
{
int r, i;
uint32_t f;
/* Get beans in a row */
mpegts_mux_instance_t *mmi = ls->ls_mmi;
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)ls->ls_frontend;
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mmi->mmi_mux;
linuxdvb_diseqc_t *lds[] = {
(linuxdvb_diseqc_t*)ls->ls_switch,
(linuxdvb_diseqc_t*)ls->ls_rotor,
(linuxdvb_diseqc_t*)ls->ls_lnb
};
/* Diseqc */
i = ls->ls_diseqc_idx;
for (i = ls->ls_diseqc_idx; i < 3; i++) {
if (!lds[i]) continue;
r = lds[i]->ld_tune(lds[i], lm, lfe->lfe_fe_fd);
/* Error */
if (r < 0) return r;
/* Pending */
if (r != 0) {
gtimer_arm_ms(&ls->ls_diseqc_timer, linuxdvb_satconf_tune_cb, ls, r);
ls->ls_diseqc_idx = i + 1;
return 0;
}
}
/* Frontend */
f = ls->ls_lnb->lnb_freq(ls->ls_lnb, lm);
return linuxdvb_frontend_tune1(lfe, mmi, f);
}
static void
linuxdvb_satconf_tune_cb ( void *o )
{
linuxdvb_satconf_t *ls = o;
if (linuxdvb_satconf_tune(ls) < 0) {
// TODO: how do we signal this?
}
}
static int
@ -239,9 +289,9 @@ linuxdvb_satconf_start_mux
{
int r;
uint32_t f;
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)(mi = ls->ls_frontend);
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mmi->mmi_mux;
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)ls->ls_frontend;
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mmi->mmi_mux;
/* Test run */
// Note: basically this ensures the tuning params are acceptable
@ -249,22 +299,16 @@ linuxdvb_satconf_start_mux
// for things like rotors and switches
if (!ls->ls_lnb)
return SM_CODE_TUNING_FAILED;
f = ls->ls_lnb->lnb_frequency(ls->ls_lnb, lm);
f = ls->ls_lnb->lnb_freq(ls->ls_lnb, lm);
if (f == (uint32_t)-1)
return SM_CODE_TUNING_FAILED;
r = linuxdvb_frontend_tune0(lfe, mmi, f);
if (r) return r;
/* Switch */
/* Rotor */
/* LNB */
if (ls->ls_lnb->lnb_tune(ls->ls_lnb, lm, lfe->lfe_fe_fd))
return SM_CODE_TUNING_FAILED;
/* Tune */
return linuxdvb_frontend_tune1(lfe, mmi, f);
/* Diseqc */
ls->ls_mmi = mmi;
ls->ls_diseqc_idx = 0;
return linuxdvb_satconf_tune(ls);
}
static void
@ -307,6 +351,33 @@ linuxdvb_satconf_has_subscription
return ls->ls_frontend->mi_has_subscription(ls->ls_frontend, mm);
}
static int
linuxdvb_satconf_grace_period
( mpegts_input_t *mi, mpegts_mux_t *mm )
{
int i, r;
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
linuxdvb_diseqc_t *lds[] = {
(linuxdvb_diseqc_t*)ls->ls_switch,
(linuxdvb_diseqc_t*)ls->ls_rotor,
(linuxdvb_diseqc_t*)ls->ls_lnb
};
/* Get underlying value */
if (ls->ls_frontend->mi_grace_period)
r = ls->ls_frontend->mi_grace_period(mi, mm);
else
r = 10;
/* Add diseqc delay */
for (i = 0; i < 3; i++) {
if (lds[i] && lds[i]->ld_grace)
r += lds[i]->ld_grace(lds[i], (linuxdvb_mux_t*)mm);
}
return r;
}
static int
linuxdvb_satconf_open_pid
( linuxdvb_frontend_t *lfe, int pid, const char *name )
@ -320,27 +391,6 @@ linuxdvb_satconf_open_pid
* Creation/Config
* *************************************************************************/
static uint32_t uni_freq
( linuxdvb_lnb_t *lnb, linuxdvb_mux_t *lm )
{
dvb_mux_conf_t *dmc = &lm->lm_tuning;
struct dvb_frontend_parameters *p = &dmc->dmc_fe_params;
if (p->frequency > 11700000)
return abs(p->frequency - 10600000);
else
return abs(p->frequency - 9750000);
}
static int uni_tune
( linuxdvb_lnb_t *lnb, linuxdvb_mux_t *lm, int fd )
{
dvb_mux_conf_t *dmc = &lm->lm_tuning;
struct dvb_frontend_parameters *p = &dmc->dmc_fe_params;
int pol = dmc->dmc_fe_polarisation == POLARISATION_HORIZONTAL ||
dmc->dmc_fe_polarisation == POLARISATION_CIRCULAR_LEFT;
return diseqc_setup(fd, 0, pol, p->frequency > 11700000, 0, 0);
}
linuxdvb_satconf_t *
linuxdvb_satconf_create0
( const char *uuid, htsmsg_t *conf )
@ -361,13 +411,9 @@ linuxdvb_satconf_create0
ls->mi_started_mux = linuxdvb_satconf_started_mux;
ls->mi_stopped_mux = linuxdvb_satconf_stopped_mux;
ls->mi_has_subscription = linuxdvb_satconf_has_subscription;
ls->mi_grace_period = linuxdvb_satconf_grace_period;
ls->lfe_open_pid = linuxdvb_satconf_open_pid;
/* Unoversal LMB */
ls->ls_lnb = calloc(1, sizeof(linuxdvb_lnb_t));
ls->ls_lnb->lnb_frequency = uni_freq;
ls->ls_lnb->lnb_tune = uni_tune;
return ls;
}

View file

@ -52,6 +52,6 @@ linuxdvb_service_create0
mpegts_service_t *s
= mpegts_service_create1(uuid, (mpegts_mux_t*)mm, sid, pmt_pid, conf);
if (s)
s->s_config_save = linuxdvb_service_config_save;
s->s_config_save = linuxdvb_service_config_save;
return s;
}

View file

@ -248,6 +248,24 @@ mpegts_service_setsourceinfo(service_t *t, source_info_t *si)
si->si_service = strdup(s->s_dvb_svcname);
}
/*
* Grace period
*/
static int
mpegts_service_grace_period(service_t *t)
{
int r = 0;
mpegts_service_t *ms = (mpegts_service_t*)t;
mpegts_mux_t *mm = ms->s_dvb_mux;
mpegts_input_t *mi = ms->s_dvb_active_input;
assert(mi != NULL);
if (mi && mi->mi_grace_period)
r = mi->mi_grace_period(mi, mm);
return r ?: 10;
}
/* **************************************************************************
* Creation/Location
* *************************************************************************/
@ -279,9 +297,7 @@ mpegts_service_create0
s->s_stop_feed = mpegts_service_stop;
s->s_refresh_feed = mpegts_service_refresh;
s->s_setsourceinfo = mpegts_service_setsourceinfo;
#if 0
s->s_grace_period = mpegts_service_grace_period;
#endif
pthread_mutex_lock(&s->s_stream_mutex);
service_make_nicename((service_t*)s);