extensions to tune dvb-s2 via s2api

This commit is contained in:
Robert 2009-09-02 18:27:34 +00:00
parent 66d7585d89
commit 3ddef93591
5 changed files with 226 additions and 27 deletions

View file

@ -64,7 +64,9 @@ typedef struct dvb_mux_conf {
struct dvb_frontend_parameters dmc_fe_params;
int dmc_polarisation;
dvb_satconf_t *dmc_satconf;
fe_modulation_t dmc_fe_modulation;
fe_delivery_system_t dmc_fe_delsys;
fe_rolloff_t dmc_fe_rolloff;
} dvb_mux_conf_t;

View file

@ -601,10 +601,12 @@ dvb_fe_opts(th_dvb_adapter_t *tda, const char *which)
fe_opts_add(a, "2/3", FEC_2_3);
fe_opts_add(a, "3/4", FEC_3_4);
fe_opts_add(a, "4/5", FEC_4_5);
fe_opts_add(a, "3/5", FEC_3_5);
fe_opts_add(a, "5/6", FEC_5_6);
fe_opts_add(a, "6/7", FEC_6_7);
fe_opts_add(a, "7/8", FEC_7_8);
fe_opts_add(a, "8/9", FEC_8_9);
fe_opts_add(a, "9/10", FEC_9_10);
return a;
}

View file

@ -174,6 +174,48 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi)
}
static int check_frontend (int fe_fd, int dvr, int human_readable) {
(void)dvr;
fe_status_t status;
uint16_t snr, signal;
uint32_t ber, uncorrected_blocks;
int timeout = 0;
do {
if (ioctl(fe_fd, FE_READ_STATUS, &status) == -1)
perror("FE_READ_STATUS failed");
/* some frontends might not support all these ioctls, thus we
* avoid printing errors
*/
if (ioctl(fe_fd, FE_READ_SIGNAL_STRENGTH, &signal) == -1)
signal = -2;
if (ioctl(fe_fd, FE_READ_SNR, &snr) == -1)
snr = -2;
if (ioctl(fe_fd, FE_READ_BER, &ber) == -1)
ber = -2;
if (ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) == -1)
uncorrected_blocks = -2;
if (human_readable) {
printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | unc %d | ",
status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber, uncorrected_blocks);
} else {
printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
status, signal, snr, ber, uncorrected_blocks);
}
if (status & FE_HAS_LOCK)
printf("FE_HAS_LOCK");
printf("\n");
if ((status & FE_HAS_LOCK) || (++timeout >= 10))
break;
usleep(1000000);
} while (1);
return 0;
}
/**
*
@ -245,12 +287,62 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
"dvb", "\"%s\" tuning to \"%s\" (%s)", tda->tda_rootpath, buf,
reason);
r = ioctl(tda->tda_fe_fd, FE_SET_FRONTEND, &p);
if (tda->tda_type == FE_QPSK) {
struct dtv_property clear_p[] = {
{ .cmd = DTV_CLEAR },
};
struct dtv_properties clear_cmdseq = {
.num = 1,
.props = clear_p
};
if ((ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &clear_cmdseq)) != 0) {
perror("FE_SET_PROPERTY DTV_CLEAR failed");
return;
}
struct dvb_frontend_event ev;
/* Support for legacy satellite tune, with the new API. */
struct dtv_property _dvbs_cmdargs[] = {
{ .cmd = DTV_DELIVERY_SYSTEM, .u.data = tdmi->tdmi_conf.dmc_fe_delsys },
{ .cmd = DTV_FREQUENCY, .u.data = p.frequency },
{ .cmd = DTV_MODULATION, .u.data = tdmi->tdmi_conf.dmc_fe_modulation },
{ .cmd = DTV_SYMBOL_RATE, .u.data = p.u.qpsk.symbol_rate },
{ .cmd = DTV_INNER_FEC, .u.data = p.u.qpsk.fec_inner },
{ .cmd = DTV_INVERSION, .u.data = INVERSION_AUTO },
{ .cmd = DTV_ROLLOFF, .u.data = tdmi->tdmi_conf.dmc_fe_rolloff },
{ .cmd = DTV_PILOT, .u.data = PILOT_AUTO },
{ .cmd = DTV_TUNE },
};
struct dtv_properties _dvbs_cmdseq = {
.num = 9,
.props = _dvbs_cmdargs
};
/* discard stale QPSK events */
while (1) {
if (ioctl(tda->tda_fe_fd, FE_GET_EVENT, &ev) == -1)
break;
}
tvhlog(LOG_INFO,
"dvb", "tuning via s2api to %s, freq %d, symbolrate %d, fec %d, sys %d, mod %d",
buf, p.frequency, p.u.qpsk.symbol_rate, p.u.qpsk.fec_inner, tdmi->tdmi_conf.dmc_fe_delsys,
tdmi->tdmi_conf.dmc_fe_modulation);
r = ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &_dvbs_cmdseq);
if(0)
check_frontend (tda->tda_fe_fd, 0, 1);
} else
r = ioctl(tda->tda_fe_fd, FE_SET_FRONTEND, &p);
if(r != 0) {
tvhlog(LOG_ERR, "dvb", "\"%s\" tuning to \"%s\""
" -- Front configuration failed -- %s",
tda->tda_rootpath, buf, strerror(errno));
}
" -- Front configuration failed -- %s",
tda->tda_rootpath, buf, strerror(errno));
}
tda->tda_mux_current = tdmi;

View file

@ -133,7 +133,10 @@ tdmi_compare_conf(int adapter_type,
case FE_QPSK:
return memcmp(&a->dmc_fe_params.u.qpsk,
&b->dmc_fe_params.u.qpsk,
sizeof(a->dmc_fe_params.u.qpsk));
sizeof(a->dmc_fe_params.u.qpsk)) ||
a->dmc_fe_modulation != b->dmc_fe_modulation ||
a->dmc_fe_delsys != b->dmc_fe_delsys ||
a->dmc_fe_rolloff != b->dmc_fe_rolloff;
}
return 0;
}
@ -166,6 +169,8 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
if(!tdmi_compare_conf(tda->tda_type, &tdmi->tdmi_conf, dmc))
return NULL; // Nothings changed
memcpy(&tdmi->tdmi_conf, dmc, sizeof(struct dvb_mux_conf));
dvb_mux_save(tdmi);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
@ -315,9 +320,12 @@ dvb_mux_find_by_identifier(const char *identifier)
}
static struct strtab rollofftab[] = {
{ "ROLLOFF_35", ROLLOFF_35 },
{ "ROLLOFF_20", ROLLOFF_20 },
{ "ROLLOFF_25", ROLLOFF_25 },
{ "ROLLOFF_AUTO", ROLLOFF_AUTO }
};
static struct strtab fectab[] = {
{ "NONE", FEC_NONE },
@ -329,19 +337,44 @@ static struct strtab fectab[] = {
{ "6/7", FEC_6_7 },
{ "7/8", FEC_7_8 },
{ "8/9", FEC_8_9 },
{ "AUTO", FEC_AUTO }
{ "AUTO", FEC_AUTO },
{ "3/5", FEC_3_4 },
{ "9/10", FEC_9_10 }
};
static struct strtab qamtab[] = {
{ "QPSK", QPSK },
{ "QAM16", QAM_16 },
{ "QAM32", QAM_32 },
{ "QAM64", QAM_64 },
{ "QAM128", QAM_128 },
{ "QAM256", QAM_256 },
{ "AUTO", QAM_AUTO },
{ "8VSB", VSB_8 },
{ "16VSB", VSB_16 }
{ "QPSK", QPSK },
{ "QAM16", QAM_16 },
{ "QAM32", QAM_32 },
{ "QAM64", QAM_64 },
{ "QAM128", QAM_128 },
{ "QAM256", QAM_256 },
{ "AUTO", QAM_AUTO },
{ "8VSB", VSB_8 },
{ "16VSB", VSB_16 },
{ "PSK_8", PSK_8 },
{ "APSK_16", APSK_16 },
{ "APSK_32", APSK_32 },
{ "DQPSK", DQPSK }
};
static struct strtab delsystab[] = {
{ "SYS_UNDEFINED", SYS_UNDEFINED },
{ "SYS_DVBC_ANNEX_AC", SYS_DVBC_ANNEX_AC },
{ "SYS_DVBC_ANNEX_B", SYS_DVBC_ANNEX_B },
{ "SYS_DVBT", SYS_DVBT },
{ "SYS_DSS", SYS_DSS },
{ "SYS_DVBS", SYS_DVBS },
{ "SYS_DVBS2", SYS_DVBS2 },
{ "SYS_DVBH", SYS_DVBH },
{ "SYS_ISDBT", SYS_ISDBT },
{ "SYS_ISDBS", SYS_ISDBS },
{ "SYS_ISDBC", SYS_ISDBC },
{ "SYS_ATSC", SYS_ATSC },
{ "SYS_ATSCMH", SYS_ATSCMH },
{ "SYS_DMBTH", SYS_DMBTH },
{ "SYS_CMMB", SYS_CMMB },
{ "SYS_DAB", SYS_DAB }
};
static struct strtab bwtab[] = {
@ -429,10 +462,19 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi)
htsmsg_add_u32(m, "symbol_rate", f->u.qpsk.symbol_rate);
htsmsg_add_str(m, "fec",
val2str(f->u.qpsk.fec_inner, fectab));
val2str(f->u.qpsk.fec_inner, fectab));
htsmsg_add_str(m, "polarisation",
val2str(tdmi->tdmi_conf.dmc_polarisation, poltab));
val2str(tdmi->tdmi_conf.dmc_polarisation, poltab));
htsmsg_add_str(m, "modulation",
val2str(tdmi->tdmi_conf.dmc_fe_modulation, qamtab));
htsmsg_add_str(m, "delivery_system",
val2str(tdmi->tdmi_conf.dmc_fe_delsys, delsystab));
htsmsg_add_str(m, "rolloff",
val2str(tdmi->tdmi_conf.dmc_fe_rolloff, rollofftab));
break;
case FE_QAM:
@ -470,7 +512,6 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier)
struct dvb_mux_conf dmc;
const char *s;
int r;
int polarisation = 0;
unsigned int tsid, u32, enabled;
dvb_satconf_t *sc;
@ -531,7 +572,31 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier)
s = htsmsg_get_str(m, "polarisation");
if(s == NULL || (r = str2val(s, poltab)) < 0)
return "Invalid polarisation";
polarisation = r;
dmc.dmc_polarisation = r;
s = htsmsg_get_str(m, "modulation");
if(s == NULL || (r = str2val(s, qamtab)) < 0) {
r = str2val("QPSK", qamtab);
tvhlog(LOG_INFO,
"dvb", "no modulation for mux found, defaulting to QPSK");
}
dmc.dmc_fe_modulation = r;
s = htsmsg_get_str(m, "delivery_system");
if(s == NULL || (r = str2val(s, delsystab)) < 0) {
r = str2val("SYS_DVBS", delsystab);
tvhlog(LOG_INFO,
"dvb", "no delivery system for mux found, defaulting to SYS_DVBS");
}
dmc.dmc_fe_delsys = r;
s = htsmsg_get_str(m, "rolloff");
if(s == NULL || (r = str2val(s, rollofftab)) < 0) {
r = str2val("ROLLOFF_35", rollofftab);
tvhlog(LOG_INFO,
"dvb", "no rolloff for mux found, defaulting to ROLLOFF_35");
}
dmc.dmc_fe_rolloff = r;
break;
case FE_QAM:

View file

@ -800,9 +800,11 @@ dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
/**
* Tables for delivery descriptor parsing
*/
static const fe_code_rate_t fec_tab [8] = {
static const fe_code_rate_t fec_tab [16] = {
FEC_AUTO, FEC_1_2, FEC_2_3, FEC_3_4,
FEC_5_6, FEC_7_8, FEC_NONE, FEC_NONE
FEC_5_6, FEC_7_8, FEC_8_9, FEC_3_5,
FEC_4_5, FEC_9_10, FEC_NONE, FEC_NONE,
FEC_NONE, FEC_NONE, FEC_NONE, FEC_NONE
};
@ -862,7 +864,7 @@ static int
dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
uint16_t tsid)
{
int freq, symrate;
int freq, symrate, modulation;
struct dvb_mux_conf dmc;
if(!tdmi->tdmi_adapter->tda_autodiscovery)
@ -884,14 +886,50 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
bcdtoint(ptr[9]) * 10 + (ptr[10] >> 4);
dmc.dmc_fe_params.u.qam.symbol_rate = symrate * 100;
dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07];
dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x0f];
dmc.dmc_polarisation = (ptr[6] >> 5) & 0x03;
// Same satconf (lnb, switch, etc)
dmc.dmc_satconf = tdmi->tdmi_conf.dmc_satconf;
modulation = (ptr[6] & 0x03);
if (modulation == 0x01)
dmc.dmc_fe_modulation = QPSK;
else if (modulation == 0x02)
dmc.dmc_fe_modulation = PSK_8;
else if (modulation == 0x03)
dmc.dmc_fe_modulation = QAM_16;
else
dmc.dmc_fe_modulation = 0;
if (ptr[6] & 0x04) {
dmc.dmc_fe_delsys = SYS_DVBS2;
switch ((ptr[6] >> 3) & 0x03) {
case 0x00:
dmc.dmc_fe_rolloff = ROLLOFF_35;
break;
case 0x01:
dmc.dmc_fe_rolloff = ROLLOFF_25;
break;
case 0x02:
dmc.dmc_fe_rolloff = ROLLOFF_20;
break;
default:
case 0x03:
dmc.dmc_fe_rolloff = ROLLOFF_AUTO;
break;
}
}
else {
dmc.dmc_fe_delsys = SYS_DVBS;
dmc.dmc_fe_rolloff = ROLLOFF_35;
}
dvb_mux_create(tdmi->tdmi_adapter, &dmc, tsid, NULL,
"automatic mux discovery", 1, NULL);
return 0;
}