linuxdvb: early stage of getting DVB-S to work.

I've added missing config (delsys) to muxes and I've got satconf working
as a full proxy of frontend (may still be a few small issues). Satconf
is not yet doing anything useful, its hardcoded to a universal LNB and
no switch/rotor support.
This commit is contained in:
Adam Sutton 2013-06-15 14:34:06 +01:00
parent 696fcf9751
commit e20aa94685
5 changed files with 204 additions and 72 deletions

View file

@ -176,6 +176,7 @@ SRCS-${CONFIG_LINUXDVB} += \
src/input/mpegts/linuxdvb/linuxdvb_mux.c \
src/input/mpegts/linuxdvb/linuxdvb_service.c \
src/input/mpegts/linuxdvb/linuxdvb_satconf.c \
src/input/mpegts/linuxdvb/diseqc.c
# IPTV
SRCS-${CONFIG_IPTV} += \

View file

@ -257,7 +257,7 @@ linuxdvb_frontend_is_enabled ( mpegts_input_t *mi )
static void
linuxdvb_frontend_display_name ( mpegts_input_t* mi, char *buf, size_t len )
{
strncpy(buf, linuxdvb_frontend_class_get_title(&mi->mi_id), len);
strncpy(buf, linuxdvb_frontend_class_get_title(&mi->mi_id) ?: "", len);
}
#if 0
@ -312,55 +312,7 @@ static int
linuxdvb_frontend_start_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
int r;
char buf1[256], buf2[256];
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
mpegts_mux_instance_t *cur = LIST_FIRST(&mi->mi_mux_active);
mi->mi_display_name(mi, buf1, sizeof(buf1));
mmi->mmi_mux->mm_display_name(mmi->mmi_mux, buf2, sizeof(buf2));
tvhdebug("linuxdvb", "%s - starting %s", buf1, buf2);
// Not sure if this is right place?
/* Currently active */
if (cur != NULL) {
/* Already tuned */
if (mmi == cur)
return 0;
/* Stop current */
cur->mmi_mux->mm_stop(cur->mmi_mux);
}
assert(LIST_FIRST(&mi->mi_mux_active) == NULL);
/* Open FE */
if (lfe->lfe_fe_fd <= 0) {
lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0);
tvhtrace("linuxdvb", "%s - opening FE %s (%d)", buf1, lfe->lfe_fe_path, lfe->lfe_fe_fd);
if (lfe->lfe_fe_fd <= 0) {
return SM_CODE_TUNING_FAILED;
}
}
/* Tune */
tvhtrace("linuxdvb", "%s - tuning", buf1);
r = linuxdvb_frontend_tune(lfe, (linuxdvb_mux_t*)mmi->mmi_mux, -1);
/* Failed */
if (r != 0) {
tvherror("linuxdvb", "%s - failed to tune [e=%s]", buf1, strerror(errno));
if (errno == EINVAL)
mmi->mmi_tune_failed = 1;
return SM_CODE_TUNING_FAILED;
}
/* Start monitor */
time(&lfe->lfe_monitor);
lfe->lfe_monitor += 4;
gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
return r;
return linuxdvb_frontend_tune1((linuxdvb_frontend_t*)mi, mmi, -1);
}
static int
@ -512,7 +464,7 @@ linuxdvb_frontend_monitor ( void *aux )
if (!mmi) return;
mm = mmi->mmi_mux;
lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
tvhdebug("linuxdvb", "%s - checking FE status", buf);
tvhtrace("linuxdvb", "%s - checking FE status", buf);
/* Get current status */
if (ioctl(lfe->lfe_fe_fd, FE_READ_STATUS, &fe_status) == -1) {
@ -529,6 +481,7 @@ linuxdvb_frontend_monitor ( void *aux )
/* Set default period */
gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 1);
tvhtrace("linuxdvb", "%s - starus %d", buf, status);
/* Waiting for lock */
if (!lfe->lfe_locked) {
@ -665,11 +618,37 @@ linuxdvb_frontend_input_thread ( void *aux )
* *************************************************************************/
int
linuxdvb_frontend_tune
( linuxdvb_frontend_t *lfe, linuxdvb_mux_t *lm, uint32_t freq )
linuxdvb_frontend_tune0
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq )
{
int r;
struct dvb_frontend_event ev;
char buf1[256];
mpegts_mux_instance_t *cur = LIST_FIRST(&lfe->mi_mux_active);
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mmi->mmi_mux;
// Not sure if this is right place?
/* Currently active */
if (cur != NULL) {
/* Already tuned */
if (mmi == cur)
return 0;
/* Stop current */
cur->mmi_mux->mm_stop(cur->mmi_mux);
}
assert(LIST_FIRST(&lfe->mi_mux_active) == NULL);
/* Open FE */
if (lfe->lfe_fe_fd <= 0) {
lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0);
tvhtrace("linuxdvb", "%s - opening FE %s (%d)", buf1, lfe->lfe_fe_path, lfe->lfe_fe_fd);
if (lfe->lfe_fe_fd <= 0) {
return SM_CODE_TUNING_FAILED;
}
}
/* S2 tuning */
#if DVB_API_VERSION >= 5
@ -753,6 +732,37 @@ linuxdvb_frontend_tune
r = ioctl(lfe->lfe_fe_fd, FE_SET_FRONTEND, p);
#endif
/* Failed */
if (r != 0) {
tvherror("linuxdvb", "%s - failed to tune [e=%s]", buf1, strerror(errno));
if (errno == EINVAL)
mmi->mmi_tune_failed = 1;
return SM_CODE_TUNING_FAILED;
}
return r;
}
int
linuxdvb_frontend_tune1
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq )
{
int r;
char buf1[256], buf2[256];
lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
mmi->mmi_mux->mm_display_name(mmi->mmi_mux, buf2, sizeof(buf2));
tvhdebug("linuxdvb", "%s - starting %s", buf1, buf2);
/* Tune */
tvhtrace("linuxdvb", "%s - tuning", buf1);
r = linuxdvb_frontend_tune0(lfe, mmi, freq);
/* Start monitor */
time(&lfe->lfe_monitor);
lfe->lfe_monitor += 4;
gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
return r;
}
@ -802,9 +812,9 @@ linuxdvb_frontend_create0
lfe->mi_stop_mux = linuxdvb_frontend_stop_mux;
lfe->mi_open_service = linuxdvb_frontend_open_service;
lfe->mi_close_service = linuxdvb_frontend_close_service;
lfe->lfe_open_pid = linuxdvb_frontend_open_pid;
lfe->mi_network_class = linuxdvb_frontend_network_class;
lfe->mi_network_create = linuxdvb_frontend_network_create;
lfe->lfe_open_pid = linuxdvb_frontend_open_pid;
/* Adapter link */
lfe->lh_parent = (linuxdvb_hardware_t*)la;

View file

@ -73,6 +73,20 @@ linuxdvb_mux_##c##_class_##l##_enum (void *o)\
.str_set = linuxdvb_mux_##t##_class_##l##_set,\
.str_enum = linuxdvb_mux_##t##_class_##l##_enum
static const char *
linuxdvb_mux_class_delsys_get (void *o)
{
linuxdvb_mux_t *lm = o;
return dvb_delsys2str(lm->lm_tuning.dmc_fe_delsys);
}
static int
linuxdvb_mux_class_delsys_set (void *o, const char *s)
{
linuxdvb_mux_t *lm = o;
lm->lm_tuning.dmc_fe_delsys = dvb_str2delsys(s);
return 1;
}
const idclass_t linuxdvb_mux_class =
{
.ic_super = &mpegts_mux_class,
@ -135,12 +149,27 @@ linuxdvb_mux_class_X(dvbt, ofdm, code_rate_LP, feclo,
#endif
);
#define linuxdvb_mux_dvbt_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_dvbt_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_dvbt_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBT));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBT2));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_TURBO));
return list;
}
const idclass_t linuxdvb_mux_dvbt_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_dvbt",
.ic_caption = "Linux DVB-T Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbt, delsys),
},
{
.type = PT_U32,
.id = "frequency",
@ -187,12 +216,27 @@ linuxdvb_mux_class_X(dvbc, qam, fec_inner, fec,
, FEC_9_10
#endif
);
#define linuxdvb_mux_dvbc_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_dvbc_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_dvbc_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBC_ANNEX_AC));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBC_ANNEX_B));
return list;
}
const idclass_t linuxdvb_mux_dvbc_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_dvbc",
.ic_caption = "Linux DVB-C Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbc, delsys),
},
{
.type = PT_U32,
.id = "frequency",
@ -255,12 +299,26 @@ linuxdvb_mux_dvbs_class_polarity_enum (void *o)
return list;
}
#define linuxdvb_mux_dvbs_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_dvbs_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_dvbs_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBS));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBS2));
return list;
}
const idclass_t linuxdvb_mux_dvbs_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_dvbs",
.ic_caption = "Linux DVB-S Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbs, delsys),
},
{
.type = PT_U32,
.id = "frequency",
@ -288,12 +346,26 @@ const idclass_t linuxdvb_mux_dvbs_class =
}
};
#define linuxdvb_mux_atsc_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_atsc_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_atsc_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_ATSC));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_ATSCMH));
return list;
}
const idclass_t linuxdvb_mux_atsc_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_atsc",
.ic_caption = "Linux ATSC Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", atsc, delsys),
},
{}
}
};

View file

@ -171,8 +171,10 @@ linuxdvb_frontend_added
void linuxdvb_frontend_add_network
( linuxdvb_frontend_t *lfe, linuxdvb_network_t *net );
int linuxdvb_frontend_tune
( linuxdvb_frontend_t *lfe, linuxdvb_mux_t *lm, uint32_t freq );
int linuxdvb_frontend_tune0
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq );
int linuxdvb_frontend_tune1
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq );
/*
* Network
@ -233,7 +235,7 @@ struct linuxdvb_lnb
*/
struct linuxdvb_satconf
{
mpegts_input_t;
linuxdvb_frontend_t;
/* Links */
mpegts_input_t *ls_frontend;

View file

@ -19,6 +19,7 @@
#include "tvheadend.h"
#include "linuxdvb_private.h"
#include "diseqc.h"
#include <sys/ioctl.h>
#include <sys/types.h>
@ -33,7 +34,7 @@
* Class definition
* *************************************************************************/
extern const idclass_t linuxdvb_hardware_class;
extern const idclass_t mpegts_input_class;
static const char*
linuxdvb_satconf_class_network_get(void *o)
@ -47,19 +48,21 @@ linuxdvb_satconf_class_network_get(void *o)
static int
linuxdvb_satconf_class_network_set(void *o, const char *s)
{
extern const idclass_t linuxdvb_network_class;
mpegts_input_t *mi = o;
mpegts_network_t *mn = mi->mi_network;
linuxdvb_network_t *ln = (linuxdvb_network_t*)mn;
if (mi->mi_network && !strcmp(idnode_uuid_as_str(&mn->mn_id), s ?: ""))
return 0;
if (ln->ln_type != FE_QPSK) {
mn = s ? idnode_find(s, &linuxdvb_network_class) : NULL;
if (mn && ((linuxdvb_network_t*)mn)->ln_type != FE_QPSK) {
tvherror("linuxdvb", "attempt to set network of wrong type");
return 0;
}
mpegts_input_set_network(mi, s ? mpegts_network_find(s) : NULL);
mpegts_input_set_network(mi, mn);
return 1;
}
@ -130,7 +133,7 @@ linuxdvb_satconf_class_frontend_enum (void *o)
const idclass_t linuxdvb_satconf_class =
{
.ic_super = &linuxdvb_hardware_class,
.ic_super = &mpegts_input_class,
.ic_class = "linuxdvb_satconf",
.ic_caption = "Linux DVB Satconf",
//.ic_get_title = linuxdvb_satconf_class_get_title,
@ -164,7 +167,7 @@ static void
linuxdvb_satconf_display_name ( mpegts_input_t* mi, char *buf, size_t len )
{
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
ls->mi_display_name(ls->ls_frontend, buf, len);
ls->ls_frontend->mi_display_name(ls->ls_frontend, buf, len);
}
static const idclass_t *
@ -192,7 +195,8 @@ static int
linuxdvb_satconf_is_free ( mpegts_input_t *mi )
{
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
return ls->ls_frontend->mi_is_free(ls->ls_frontend);
int r = ls->ls_frontend->mi_is_free(ls->ls_frontend);
return r;
}
static int
@ -218,7 +222,7 @@ linuxdvb_satconf_start_mux
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;
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mmi->mmi_mux;
/* Test run */
// Note: basically this ensures the tuning params are acceptable
@ -227,9 +231,9 @@ linuxdvb_satconf_start_mux
if (!ls->ls_lnb)
return SM_CODE_TUNING_FAILED;
f = ls->ls_lnb->lnb_frequency(ls->ls_lnb, lm);
if (f < 0)
if (f == (uint32_t)-1)
return SM_CODE_TUNING_FAILED;
r = linuxdvb_frontend_tune(lfe, lm, f);
r = linuxdvb_frontend_tune0(lfe, mmi, f);
if (r) return r;
/* Switch */
@ -241,7 +245,7 @@ linuxdvb_satconf_start_mux
return SM_CODE_TUNING_FAILED;
/* Tune */
return mi->mi_start_mux(mi, mmi);
return linuxdvb_frontend_tune1(lfe, mmi, f);
}
static void
@ -261,16 +265,52 @@ linuxdvb_satconf_close_service
}
static void
linuxdvb_satconf_create_mux_instance
( mpegts_input_t *mi, mpegts_mux_t *mm )
linuxdvb_satconf_started_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
ls->ls_frontend->mi_create_mux_instance(ls->ls_frontend, mm);
ls->ls_frontend->mi_started_mux(ls->ls_frontend, mmi);
}
static void
linuxdvb_satconf_stopped_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)mi;
ls->ls_frontend->mi_stopped_mux(ls->ls_frontend, mmi);
}
static int
linuxdvb_satconf_open_pid
( linuxdvb_frontend_t *lfe, int pid, const char *name )
{
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)lfe;
lfe = (linuxdvb_frontend_t*)ls->ls_frontend;
return lfe->lfe_open_pid(lfe, pid, name);
}
/* **************************************************************************
* 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;
return diseqc_setup(fd, 0, 0, p->frequency > 11700000, 0, 0);
}
linuxdvb_satconf_t *
linuxdvb_satconf_create0
@ -289,7 +329,14 @@ linuxdvb_satconf_create0
ls->mi_close_service = linuxdvb_satconf_close_service;
ls->mi_network_class = linuxdvb_satconf_network_class;
ls->mi_network_create = linuxdvb_satconf_network_create;
ls->mi_create_mux_instance = linuxdvb_satconf_create_mux_instance;
ls->mi_started_mux = linuxdvb_satconf_started_mux;
ls->mi_stopped_mux = linuxdvb_satconf_stopped_mux;
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;
}