Commit 8c011362 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Linux DVB: factorize and revector frontend probing

(cherry picked from commit a9862530656860c69d51d8a8fbe75baae0149e91)
parent 9178d095
...@@ -184,7 +184,7 @@ struct dvb_device ...@@ -184,7 +184,7 @@ struct dvb_device
#ifdef HAVE_DVBPSI #ifdef HAVE_DVBPSI
cam_t *cam; cam_t *cam;
#endif #endif
struct dvb_frontend_info info; unsigned systems;
bool budget; bool budget;
//size_t buffer_size; //size_t buffer_size;
}; };
...@@ -430,12 +430,66 @@ void dvb_remove_pid (dvb_device_t *d, uint16_t pid) ...@@ -430,12 +430,66 @@ void dvb_remove_pid (dvb_device_t *d, uint16_t pid)
#endif #endif
} }
/** Enumerates the systems supported by one frontend */
static unsigned dvb_probe_frontend (dvb_device_t *d, int fd)
{
struct dvb_frontend_info info;
if (ioctl (fd, FE_GET_INFO, &info) < 0)
{
msg_Err (d->obj, "cannot get frontend info: %m");
return 0;
}
msg_Dbg (d->obj, "probing frontend: %s", info.name);
msg_Dbg (d->obj, " type %u, capabilities 0x%08X", info.type, info.caps);
msg_Dbg (d->obj, " frequencies %10"PRIu32" to %10"PRIu32,
info.frequency_min, info.frequency_max);
msg_Dbg (d->obj, " (%"PRIu32" tolerance, %"PRIu32" per step)",
info.frequency_tolerance, info.frequency_stepsize);
msg_Dbg (d->obj, " bauds rates %10"PRIu32" to %10"PRIu32,
info.symbol_rate_min, info.symbol_rate_max);
msg_Dbg (d->obj, " (%"PRIu32" tolerance)", info.symbol_rate_tolerance);
unsigned systems;
/* DVB first generation and ATSC */
switch (info.type)
{
case FE_QPSK: systems = DVB_S; break;
case FE_QAM: systems = DVB_C; break;
case FE_OFDM: systems = DVB_T; break;
case FE_ATSC: systems = ATSC; break;
default:
systems = 0;
msg_Err (d->obj, "unknown frontend type %u", info.type);
}
/* DVB 2nd generation */
switch (info.type)
{
case FE_QPSK:
case FE_QAM:
case FE_OFDM:
if (info.caps & FE_CAN_2G_MODULATION)
systems |= systems << 1; /* DVB_foo -> DVB_foo|DVB_foo2 */
default:
break;
}
/* ISDB (only terrestrial before DVBv5.5) */
if (info.type == FE_OFDM)
systems |= ISDB_T;
return systems;
}
/** Finds a frontend of the correct type */ /** Finds a frontend of the correct type */
static int dvb_find_frontend (dvb_device_t *d, fe_type_t type, fe_caps_t caps) static int dvb_find_frontend (dvb_device_t *d, unsigned system)
{ {
if (d->frontend != -1) if (d->frontend != -1)
{ {
if (d->info.type == type || (d->info.caps & caps) == caps) if (d->systems & system)
return 0; /* already got an adequate frontend */ return 0; /* already got an adequate frontend */
close (d->frontend); close (d->frontend);
...@@ -453,35 +507,15 @@ static int dvb_find_frontend (dvb_device_t *d, fe_type_t type, fe_caps_t caps) ...@@ -453,35 +507,15 @@ static int dvb_find_frontend (dvb_device_t *d, fe_type_t type, fe_caps_t caps)
continue; continue;
} }
if (ioctl (fd, FE_GET_INFO, &d->info) < 0) d->systems = dvb_probe_frontend (d, fd);
if (d->systems & system)
{ {
msg_Err (d->obj, "cannot get frontend %u info: %m", n); msg_Dbg (d->obj, "selected frontend %u", n);
goto skip; d->frontend = fd;
} return 0;
msg_Dbg (d->obj, "probing frontend %u: %s", n, d->info.name);
msg_Dbg (d->obj, " type %u, capabilities 0x%08X", d->info.type,
d->info.caps);
msg_Dbg (d->obj, " frequencies %10"PRIu32" to %10"PRIu32,
d->info.frequency_min, d->info.frequency_max);
msg_Dbg (d->obj, " (%"PRIu32" tolerance, %"PRIu32" per step)",
d->info.frequency_tolerance, d->info.frequency_stepsize);
msg_Dbg (d->obj, " bauds rates %10"PRIu32" to %10"PRIu32,
d->info.symbol_rate_min, d->info.symbol_rate_max);
msg_Dbg (d->obj, " (%"PRIu32" tolerance)",
d->info.symbol_rate_tolerance);
if (d->info.type != type || (d->info.caps & caps) != caps)
{
msg_Dbg (d->obj, "skipping frontend %u: wrong type", n);
goto skip;
} }
msg_Dbg (d->obj, "selected frontend %u", n); msg_Dbg (d->obj, "skipping frontend %u: wrong type", n);
d->frontend = fd;
return 0;
skip:
close (fd); close (fd);
} }
...@@ -508,33 +542,8 @@ unsigned dvb_enum_systems (dvb_device_t *d) ...@@ -508,33 +542,8 @@ unsigned dvb_enum_systems (dvb_device_t *d)
continue; continue;
} }
struct dvb_frontend_info info; systems |= dvb_probe_frontend (d, fd);
if (ioctl (fd, FE_GET_INFO, &info) < 0)
{
msg_Err (d->obj, "cannot get frontend %u info: %m", n);
close (fd);
continue;
}
close (fd); close (fd);
/* Linux DVB lacks detection for non-DVB/non-ATSC demods */
static const unsigned types[] = {
[FE_QPSK] = DVB_S,
[FE_QAM] = DVB_C,
[FE_OFDM] = DVB_T,
[FE_ATSC] = ATSC,
};
if (((unsigned)info.type) >= sizeof (types) / sizeof (types[0]))
{
msg_Err (d->obj, "unknown frontend type %u", info.type);
continue;
}
unsigned sys = types[info.type];
if (info.caps & FE_CAN_2G_MODULATION)
sys |= sys << 1; /* DVB_foo -> DVB_foo|DVB_foo2 */
systems |= sys;
} }
return systems; return systems;
} }
...@@ -631,7 +640,7 @@ int dvb_set_dvbc (dvb_device_t *d, uint32_t freq, const char *modstr, ...@@ -631,7 +640,7 @@ int dvb_set_dvbc (dvb_device_t *d, uint32_t freq, const char *modstr,
unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO); unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
fec = dvb_parse_fec (fec); fec = dvb_parse_fec (fec);
if (dvb_find_frontend (d, FE_QAM, FE_IS_STUPID)) if (dvb_find_frontend (d, DVB_C))
return -1; return -1;
return dvb_set_props (d, 6, DTV_CLEAR, 0, return dvb_set_props (d, 6, DTV_CLEAR, 0,
#if DVBv5(5) #if DVBv5(5)
...@@ -764,7 +773,7 @@ int dvb_set_dvbs (dvb_device_t *d, uint64_t freq_Hz, ...@@ -764,7 +773,7 @@ int dvb_set_dvbs (dvb_device_t *d, uint64_t freq_Hz,
uint32_t freq = freq_Hz / 1000; uint32_t freq = freq_Hz / 1000;
fec = dvb_parse_fec (fec); fec = dvb_parse_fec (fec);
if (dvb_find_frontend (d, FE_QPSK, FE_IS_STUPID)) if (dvb_find_frontend (d, DVB_S))
return -1; return -1;
return dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS, return dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS,
DTV_FREQUENCY, freq, DTV_SYMBOL_RATE, srate, DTV_FREQUENCY, freq, DTV_SYMBOL_RATE, srate,
...@@ -793,7 +802,7 @@ int dvb_set_dvbs2 (dvb_device_t *d, uint64_t freq_Hz, const char *modstr, ...@@ -793,7 +802,7 @@ int dvb_set_dvbs2 (dvb_device_t *d, uint64_t freq_Hz, const char *modstr,
default: rolloff = PILOT_AUTO; break; default: rolloff = PILOT_AUTO; break;
} }
if (dvb_find_frontend (d, FE_QPSK, FE_CAN_2G_MODULATION)) if (dvb_find_frontend (d, DVB_S2))
return -1; return -1;
return dvb_set_props (d, 8, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS2, return dvb_set_props (d, 8, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS2,
DTV_FREQUENCY, freq, DTV_MODULATION, mod, DTV_FREQUENCY, freq, DTV_MODULATION, mod,
...@@ -877,7 +886,7 @@ int dvb_set_dvbt (dvb_device_t *d, uint32_t freq, const char *modstr, ...@@ -877,7 +886,7 @@ int dvb_set_dvbt (dvb_device_t *d, uint32_t freq, const char *modstr,
guard = dvb_parse_guard (guard); guard = dvb_parse_guard (guard);
hierarchy = dvb_parse_hierarchy (hierarchy); hierarchy = dvb_parse_hierarchy (hierarchy);
if (dvb_find_frontend (d, FE_OFDM, FE_IS_STUPID)) if (dvb_find_frontend (d, DVB_T))
return -1; return -1;
return dvb_set_props (d, 10, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT, return dvb_set_props (d, 10, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT,
DTV_FREQUENCY, freq, DTV_MODULATION, mod, DTV_FREQUENCY, freq, DTV_MODULATION, mod,
...@@ -899,7 +908,7 @@ int dvb_set_dvbt2 (dvb_device_t *d, uint32_t freq, const char *modstr, ...@@ -899,7 +908,7 @@ int dvb_set_dvbt2 (dvb_device_t *d, uint32_t freq, const char *modstr,
transmit_mode = dvb_parse_transmit_mode (transmit_mode); transmit_mode = dvb_parse_transmit_mode (transmit_mode);
guard = dvb_parse_guard (guard); guard = dvb_parse_guard (guard);
if (dvb_find_frontend (d, FE_OFDM, FE_CAN_2G_MODULATION)) if (dvb_find_frontend (d, DVB_T2))
return -1; return -1;
return dvb_set_props (d, 8, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT2, return dvb_set_props (d, 8, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT2,
DTV_FREQUENCY, freq, DTV_MODULATION, mod, DTV_FREQUENCY, freq, DTV_MODULATION, mod,
...@@ -923,7 +932,7 @@ int dvb_set_isdbc (dvb_device_t *d, uint32_t freq, const char *modstr, ...@@ -923,7 +932,7 @@ int dvb_set_isdbc (dvb_device_t *d, uint32_t freq, const char *modstr,
unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO); unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
fec = dvb_parse_fec (fec); fec = dvb_parse_fec (fec);
if (dvb_find_frontend (d, FE_QAM, FE_IS_STUPID)) if (dvb_find_frontend (d, ISDB_C))
return -1; return -1;
return dvb_set_props (d, 6, DTV_CLEAR, 0, return dvb_set_props (d, 6, DTV_CLEAR, 0,
#if DVBv5(5) #if DVBv5(5)
...@@ -943,7 +952,7 @@ int dvb_set_isdbs (dvb_device_t *d, uint64_t freq_Hz, uint16_t ts_id) ...@@ -943,7 +952,7 @@ int dvb_set_isdbs (dvb_device_t *d, uint64_t freq_Hz, uint16_t ts_id)
#if DVBv5(1) #if DVBv5(1)
uint32_t freq = freq_Hz / 1000; uint32_t freq = freq_Hz / 1000;
if (dvb_find_frontend (d, FE_QPSK, FE_IS_STUPID)) if (dvb_find_frontend (d, ISDB_S))
return -1; return -1;
return dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBS, return dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBS,
DTV_FREQUENCY, freq, DTV_FREQUENCY, freq,
...@@ -986,7 +995,7 @@ int dvb_set_isdbt (dvb_device_t *d, uint32_t freq, uint32_t bandwidth, ...@@ -986,7 +995,7 @@ int dvb_set_isdbt (dvb_device_t *d, uint32_t freq, uint32_t bandwidth,
transmit_mode = dvb_parse_transmit_mode (transmit_mode); transmit_mode = dvb_parse_transmit_mode (transmit_mode);
guard = dvb_parse_guard (guard); guard = dvb_parse_guard (guard);
if (dvb_find_frontend (d, FE_OFDM, FE_IS_STUPID)) if (dvb_find_frontend (d, ISDB_T))
return -1; return -1;
if (dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBT, if (dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBT,
DTV_FREQUENCY, freq, DTV_BANDWIDTH_HZ, bandwidth, DTV_FREQUENCY, freq, DTV_BANDWIDTH_HZ, bandwidth,
...@@ -1011,7 +1020,7 @@ int dvb_set_atsc (dvb_device_t *d, uint32_t freq, const char *modstr) ...@@ -1011,7 +1020,7 @@ int dvb_set_atsc (dvb_device_t *d, uint32_t freq, const char *modstr)
{ {
unsigned mod = dvb_parse_modulation (modstr, VSB_8); unsigned mod = dvb_parse_modulation (modstr, VSB_8);
if (dvb_find_frontend (d, FE_ATSC, FE_IS_STUPID)) if (dvb_find_frontend (d, ATSC))
return -1; return -1;
return dvb_set_props (d, 4, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ATSC, return dvb_set_props (d, 4, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ATSC,
DTV_FREQUENCY, freq, DTV_MODULATION, mod); DTV_FREQUENCY, freq, DTV_MODULATION, mod);
...@@ -1021,7 +1030,7 @@ int dvb_set_cqam (dvb_device_t *d, uint32_t freq, const char *modstr) ...@@ -1021,7 +1030,7 @@ int dvb_set_cqam (dvb_device_t *d, uint32_t freq, const char *modstr)
{ {
unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO); unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
if (dvb_find_frontend (d, FE_QAM, FE_IS_STUPID)) if (dvb_find_frontend (d, ATSC))
return -1; return -1;
return dvb_set_props (d, 4, DTV_CLEAR, 0, return dvb_set_props (d, 4, DTV_CLEAR, 0,
DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment