summaryrefslogtreecommitdiffstats
path: root/stream/dvb_tune.c
diff options
context:
space:
mode:
Diffstat (limited to 'stream/dvb_tune.c')
-rw-r--r--stream/dvb_tune.c156
1 files changed, 123 insertions, 33 deletions
diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c
index 7ec4bcd9e8..b83da040d0 100644
--- a/stream/dvb_tune.c
+++ b/stream/dvb_tune.c
@@ -40,8 +40,62 @@
#include "dvb_tune.h"
#include "common/msg.h"
-int dvb_get_tuner_type(int fe_fd, struct mp_log *log)
+int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types)
{
+#ifdef DVB_USE_S2API
+ /* S2API is the DVB API new since 2.6.28.
+ It allows to query frontends with multiple delivery systems. */
+ struct dtv_property p[] = {{ .cmd = DTV_ENUM_DELSYS }};
+ struct dtv_properties cmdseq = {.num = 1, .props = p};
+ mp_verbose(log, "Querying tuner type via DVBv5 API for frontend FD %d\n",
+ fe_fd);
+ if ((ioctl(fe_fd, FE_GET_PROPERTY, &cmdseq)) < -0) {
+ mp_err(log, "FE_GET_PROPERTY error: %d, FD: %d\n\n", errno, fe_fd);
+ return 0;
+ }
+ int num_tuner_types = p[0].u.buffer.len;
+ mp_verbose(log, "Number of supported delivery systems: %d\n", num_tuner_types);
+ if (num_tuner_types == 0) {
+ mp_err(log, "Frontend FD %d returned no delivery systems!", fe_fd);
+ return 0;
+ }
+ (*tuner_types) = talloc_array(NULL, int, num_tuner_types);
+ int supported_tuners = 0;
+ for(;p[0].u.buffer.len > 0; p[0].u.buffer.len--) {
+ fe_delivery_system_t delsys = p[0].u.buffer.data[p[0].u.buffer.len - 1];
+ /* Second level standards like like DVB-T2, DVB-S2 not treated here -
+ Cards can usually either only do S/T/C or both levels.
+ DVB-T2 probably needs more implementation details,
+ DVB-S2 is treated in the DVB-S branch already. */
+ switch (delsys) {
+ case SYS_DVBT:
+ mp_verbose(log, "Tuner type seems to be DVB-T\n");
+ (*tuner_types)[supported_tuners++] = TUNER_TER;
+ break;
+ case SYS_DVBC_ANNEX_AC:
+ mp_verbose(log, "Tuner type seems to be DVB-C\n");
+ (*tuner_types)[supported_tuners++] = TUNER_CBL;
+ break;
+ case SYS_DVBS:
+ mp_verbose(log, "Tuner type seems to be DVB-S\n");
+ (*tuner_types)[supported_tuners++] = TUNER_SAT;
+ break;
+#ifdef DVB_ATSC
+ case SYS_ATSC:
+ mp_verbose(log, "Tuner type seems to be DVB-ATSC\n");
+ (*tuner_types)[supported_tuners++] = TUNER_ATSC;
+ break;
+#endif
+ case SYS_DVBS2:
+ // We actually handle that in the DVB-S branch, ok to ignore here.
+ mp_verbose(log, "Tuner supports DVB-S2\n");
+ break;
+ default:
+ mp_err(log, "Unhandled tuner type: %d\n", delsys);
+ }
+ }
+ return supported_tuners;
+#else
struct dvb_frontend_info fe_info;
int res = ioctl(fe_fd, FE_GET_INFO, &fe_info);
if (res < 0) {
@@ -49,29 +103,36 @@ int dvb_get_tuner_type(int fe_fd, struct mp_log *log)
return 0;
}
+ mp_verbose(log, "Queried tuner type of device named '%s', FD: %d\n",
+ fe_info.name, fe_fd);
switch (fe_info.type) {
case FE_OFDM:
- mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n");
- return TUNER_TER;
-
+ mp_verbose(log, "Tuner type seems to be DVB-T\n");
+ *tuner_types = talloc_array(NULL, int, 1);
+ (*tuner_types)[0] = TUNER_TER;
+ return 1;
case FE_QPSK:
- mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-S\n");
- return TUNER_SAT;
-
+ mp_verbose(log, "Tuner type seems to be DVB-S\n");
+ *tuner_types = talloc_array(NULL, int, 1);
+ (*tuner_types)[0] = TUNER_SAT;
+ return 1;
case FE_QAM:
- mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-C\n");
- return TUNER_CBL;
-
+ mp_verbose(log, "Tuner type seems to be DVB-C\n");
+ *tuner_types = talloc_array(NULL, int, 1);
+ (*tuner_types)[0] = TUNER_CBL;
+ return 1;
#ifdef DVB_ATSC
case FE_ATSC:
- mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-ATSC\n");
- return TUNER_ATSC;
+ mp_verbose(log, "Tuner type seems to be DVB-ATSC\n");
+ *tuner_types = talloc_array(NULL, int, 1);
+ (*tuner_types)[0] = TUNER_ATSC;
+ return 1;
#endif
default:
- mp_err(log, "UNKNOWN TUNER TYPE\n");
+ mp_err(log, "Unknown tuner type: %d\n", fe_info.type);
return 0;
}
-
+#endif
}
int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt)
@@ -80,7 +141,7 @@ int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt)
char frontend_dev[32], dvr_dev[32], demux_dev[32];
dvb_state_t* state = priv->state;
-
+
sprintf(frontend_dev, "/dev/dvb/adapter%d/frontend0", n);
sprintf(dvr_dev, "/dev/dvb/adapter%d/dvr0", n);
sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", n);
@@ -119,7 +180,7 @@ int dvb_fix_demuxes(dvb_priv_t *priv, int cnt)
{
int i;
char demux_dev[32];
-
+
dvb_state_t* state = priv->state;
sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", state->card);
@@ -374,7 +435,7 @@ static int do_diseqc(int secfd, int sat_no, int polv, int hi_lo)
(sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A);
}
-static int tune_it(dvb_priv_t *priv, int fd_frontend,
+static int tune_it(dvb_priv_t *priv, int fd_frontend,
unsigned int freq, unsigned int srate, char pol, int tone,
bool is_dvb_s2, int stream_id,
fe_spectral_inversion_t specInv, unsigned int diseqc,
@@ -387,21 +448,19 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend,
int timeout)
{
int hi_lo = 0, dfd;
+
+ dvb_state_t* state = priv->state;
+
struct dvb_frontend_parameters feparams;
- struct dvb_frontend_info fe_info;
MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, freq %lu, srate %lu, "
- "pol %c, tone %i, diseqc %u\n", fd_frontend,
+ "pol %c, tone %i, diseqc %u\n", fd_frontend,
(long unsigned int)freq, (long unsigned int)srate, pol,
tone, diseqc);
memset(&feparams, 0, sizeof(feparams));
- if (ioctl(fd_frontend, FE_GET_INFO, &fe_info) < 0) {
- MP_FATAL(priv, "FE_GET_INFO FAILED\n");
- return -1;
- }
- MP_VERBOSE(priv, "Using DVB card \"%s\"\n", fe_info.name);
+ MP_VERBOSE(priv, "Using DVB card \"%s\"\n", state->cards[state->card].name);
{
/* discard stale QPSK events */
@@ -412,8 +471,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend,
}
}
- switch (fe_info.type) {
- case FE_OFDM:
+ switch (state->tuner_type) {
+ case TUNER_TER: {
if (freq < 1000000)
freq *= 1000UL;
feparams.frequency = freq;
@@ -431,8 +490,9 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend,
MP_ERR(priv, "ERROR tuning channel\n");
return -1;
}
- break;
- case FE_QPSK:
+ }
+ break;
+ case TUNER_SAT: {
// DVB-S
if (freq > 2200000) {
// this must be an absolute frequency
@@ -509,8 +569,35 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend,
return -1;
}
#endif
- break;
- case FE_QAM:
+ }
+ break;
+ case TUNER_CBL: {
+#ifdef DVB_USE_S2API
+ /* S2API is the DVB API new since 2.6.28.
+ * It is also needed for devices supporting multiple delivery systems,
+ * commonly DVB-C + DVB-T are supported here.
+ */
+ fe_delivery_system_t delsys = SYS_DVBC_ANNEX_AC;
+ struct dtv_property p[] = {
+ { .cmd = DTV_DELIVERY_SYSTEM, .u.data = delsys },
+ { .cmd = DTV_FREQUENCY, .u.data = freq },
+ { .cmd = DTV_INVERSION, .u.data = specInv },
+ { .cmd = DTV_MODULATION, .u.data = modulation },
+ { .cmd = DTV_SYMBOL_RATE, .u.data = srate },
+ { .cmd = DTV_INNER_FEC, .u.data = HP_CodeRate },
+ { .cmd = DTV_TUNE },
+ };
+ struct dtv_properties cmdseq = {
+ .num = sizeof(p) / sizeof(p[0]),
+ .props = p
+ };
+ MP_VERBOSE(priv, "tuning DVB-C to %d, srate=%d using DVBv5 API...\n",
+ freq, srate);
+ if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdseq)) == -1) {
+ MP_ERR(priv, "ERROR tuning channel\n");
+ return -1;
+ }
+#else
feparams.frequency = freq;
feparams.inversion = specInv;
feparams.u.qam.symbol_rate = srate;
@@ -521,9 +608,11 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend,
MP_ERR(priv, "ERROR tuning channel\n");
return -1;
}
- break;
+#endif
+ }
+ break;
#ifdef DVB_ATSC
- case FE_ATSC:
+ case TUNER_ATSC: {
feparams.frequency = freq;
feparams.u.vsb.modulation = modulation;
MP_VERBOSE(priv, "tuning ATSC to %d, modulation=%d\n", freq, modulation);
@@ -531,7 +620,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend,
MP_ERR(priv, "ERROR tuning channel\n");
return -1;
}
- break;
+ }
+ break;
#endif
default:
MP_VERBOSE(priv, "Unknown FE type. Aborting\n");