mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Added support for devices with more than one delivery system per frontend
This commit is contained in:
parent
76b6ae2cab
commit
e197b04e4d
6
HISTORY
6
HISTORY
@ -6781,7 +6781,7 @@ Video Disk Recorder Revision History
|
|||||||
- Replaced all calls to sleep() with cCondWait::SleepMs() (thanks to Rolf Ahrenberg).
|
- Replaced all calls to sleep() with cCondWait::SleepMs() (thanks to Rolf Ahrenberg).
|
||||||
- Fixed a crash with malformed SI data (patch from vdr-portal).
|
- Fixed a crash with malformed SI data (patch from vdr-portal).
|
||||||
|
|
||||||
2011-12-10: Version 1.7.23
|
2012-01-07: Version 1.7.23
|
||||||
|
|
||||||
- Removed the '.pl' suffix from svdrpsend.pl (sorry, I missed that one).
|
- Removed the '.pl' suffix from svdrpsend.pl (sorry, I missed that one).
|
||||||
- Fixed bonding more than two devices.
|
- Fixed bonding more than two devices.
|
||||||
@ -6796,3 +6796,7 @@ Video Disk Recorder Revision History
|
|||||||
(triggered by Ville Skyttä pointing out that the variable HasSnr was unused).
|
(triggered by Ville Skyttä pointing out that the variable HasSnr was unused).
|
||||||
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
||||||
- Added support for HbbTV to libsi (thanks to Christoph Haubrich).
|
- Added support for HbbTV to libsi (thanks to Christoph Haubrich).
|
||||||
|
- Added support for devices with more than one delivery system per frontend.
|
||||||
|
This requires a DVB driver with version 5.5 or higher that can handle the
|
||||||
|
DTV_ENUM_DELSYS call. With older drivers it will fall back to one delivery
|
||||||
|
system per frontend.
|
||||||
|
226
dvbdevice.c
226
dvbdevice.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbdevice.c 2.50 2011/12/10 14:59:34 kls Exp $
|
* $Id: dvbdevice.c 2.51 2012/01/07 10:42:47 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbdevice.h"
|
#include "dvbdevice.h"
|
||||||
@ -81,9 +81,18 @@ const tDvbParameterMap ModulationValues[] = {
|
|||||||
{ -1, 0, NULL }
|
{ -1, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
const tDvbParameterMap SystemValues[] = {
|
#define DVB_SYSTEM_1 0 // see also nit.c
|
||||||
{ 0, SYS_DVBS, "DVB-S" },
|
#define DVB_SYSTEM_2 1
|
||||||
{ 1, SYS_DVBS2, "DVB-S2" },
|
|
||||||
|
const tDvbParameterMap SystemValuesSat[] = {
|
||||||
|
{ 0, DVB_SYSTEM_1, "DVB-S" },
|
||||||
|
{ 1, DVB_SYSTEM_2, "DVB-S2" },
|
||||||
|
{ -1, 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const tDvbParameterMap SystemValuesTerr[] = {
|
||||||
|
{ 0, DVB_SYSTEM_1, "DVB-T" },
|
||||||
|
{ 1, DVB_SYSTEM_2, "DVB-T2" },
|
||||||
{ -1, 0, NULL }
|
{ -1, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -179,7 +188,7 @@ cDvbTransponderParameters::cDvbTransponderParameters(const char *Parameters)
|
|||||||
coderateH = FEC_AUTO;
|
coderateH = FEC_AUTO;
|
||||||
coderateL = FEC_AUTO;
|
coderateL = FEC_AUTO;
|
||||||
modulation = QPSK;
|
modulation = QPSK;
|
||||||
system = SYS_DVBS;
|
system = DVB_SYSTEM_1;
|
||||||
transmission = TRANSMISSION_MODE_AUTO;
|
transmission = TRANSMISSION_MODE_AUTO;
|
||||||
guard = GUARD_INTERVAL_AUTO;
|
guard = GUARD_INTERVAL_AUTO;
|
||||||
hierarchy = HIERARCHY_AUTO;
|
hierarchy = HIERARCHY_AUTO;
|
||||||
@ -206,7 +215,7 @@ cString cDvbTransponderParameters::ToString(char Type) const
|
|||||||
ST("ACST") q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
|
ST("ACST") q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
|
||||||
ST("ACST") q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
|
ST("ACST") q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
|
||||||
ST(" S ") q += PrintParameter(q, 'O', MapToUser(rollOff, RollOffValues));
|
ST(" S ") q += PrintParameter(q, 'O', MapToUser(rollOff, RollOffValues));
|
||||||
ST(" S ") q += PrintParameter(q, 'S', MapToUser(system, SystemValues));
|
ST(" S ") q += PrintParameter(q, 'S', MapToUser(system, SystemValuesSat)); // we only need the numerical value, so Sat or Terr doesn't matter
|
||||||
ST(" T") q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
|
ST(" T") q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
|
||||||
ST(" T") q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
|
ST(" T") q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
|
||||||
return buffer;
|
return buffer;
|
||||||
@ -242,7 +251,7 @@ bool cDvbTransponderParameters::Parse(const char *s)
|
|||||||
case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
|
case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
|
||||||
case 'O': s = ParseParameter(s, rollOff, RollOffValues); break;
|
case 'O': s = ParseParameter(s, rollOff, RollOffValues); break;
|
||||||
case 'R': polarization = *s++; break;
|
case 'R': polarization = *s++; break;
|
||||||
case 'S': s = ParseParameter(s, system, SystemValues); break;
|
case 'S': s = ParseParameter(s, system, SystemValuesSat); break; // we only need the numerical value, so Sat or Terr doesn't matter
|
||||||
case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
|
case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
|
||||||
case 'V': polarization = *s++; break;
|
case 'V': polarization = *s++; break;
|
||||||
case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
|
case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
|
||||||
@ -268,10 +277,10 @@ private:
|
|||||||
int tuneTimeout;
|
int tuneTimeout;
|
||||||
int lockTimeout;
|
int lockTimeout;
|
||||||
time_t lastTimeoutReport;
|
time_t lastTimeoutReport;
|
||||||
fe_delivery_system frontendType;
|
|
||||||
cChannel channel;
|
cChannel channel;
|
||||||
const cDiseqc *lastDiseqc;
|
const cDiseqc *lastDiseqc;
|
||||||
const cScr *scr;
|
const cScr *scr;
|
||||||
|
bool lnbPowerTurnedOn;
|
||||||
eTunerStatus tunerStatus;
|
eTunerStatus tunerStatus;
|
||||||
cMutex mutex;
|
cMutex mutex;
|
||||||
cCondVar locked;
|
cCondVar locked;
|
||||||
@ -279,6 +288,7 @@ private:
|
|||||||
cDvbTuner *bondedTuner;
|
cDvbTuner *bondedTuner;
|
||||||
bool bondedMaster;
|
bool bondedMaster;
|
||||||
bool bondedMasterFailed;
|
bool bondedMasterFailed;
|
||||||
|
bool SetFrontendType(const cChannel *Channel);
|
||||||
cString GetBondingParams(const cChannel *Channel = NULL) const;
|
cString GetBondingParams(const cChannel *Channel = NULL) const;
|
||||||
void ClearEventQueue(void) const;
|
void ClearEventQueue(void) const;
|
||||||
bool GetFrontendStatus(fe_status_t &Status) const;
|
bool GetFrontendStatus(fe_status_t &Status) const;
|
||||||
@ -287,7 +297,7 @@ private:
|
|||||||
bool SetFrontend(void);
|
bool SetFrontend(void);
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
public:
|
public:
|
||||||
cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType);
|
cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend);
|
||||||
virtual ~cDvbTuner();
|
virtual ~cDvbTuner();
|
||||||
bool Bond(cDvbTuner *Tuner);
|
bool Bond(cDvbTuner *Tuner);
|
||||||
void UnBond(void);
|
void UnBond(void);
|
||||||
@ -304,25 +314,23 @@ public:
|
|||||||
|
|
||||||
cMutex cDvbTuner::bondMutex;
|
cMutex cDvbTuner::bondMutex;
|
||||||
|
|
||||||
cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType)
|
cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend)
|
||||||
{
|
{
|
||||||
device = Device;
|
device = Device;
|
||||||
fd_frontend = Fd_Frontend;
|
fd_frontend = Fd_Frontend;
|
||||||
adapter = Adapter;
|
adapter = Adapter;
|
||||||
frontend = Frontend;
|
frontend = Frontend;
|
||||||
frontendType = FrontendType;
|
|
||||||
subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
|
subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
|
||||||
tuneTimeout = 0;
|
tuneTimeout = 0;
|
||||||
lockTimeout = 0;
|
lockTimeout = 0;
|
||||||
lastTimeoutReport = 0;
|
lastTimeoutReport = 0;
|
||||||
lastDiseqc = NULL;
|
lastDiseqc = NULL;
|
||||||
scr = NULL;
|
scr = NULL;
|
||||||
|
lnbPowerTurnedOn = false;
|
||||||
tunerStatus = tsIdle;
|
tunerStatus = tsIdle;
|
||||||
bondedTuner = NULL;
|
bondedTuner = NULL;
|
||||||
bondedMaster = false;
|
bondedMaster = false;
|
||||||
bondedMasterFailed = false;
|
bondedMasterFailed = false;
|
||||||
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2)
|
|
||||||
ResetToneAndVoltage(); // must explicitly turn on LNB power
|
|
||||||
SetDescription("tuner on frontend %d/%d", adapter, frontend);
|
SetDescription("tuner on frontend %d/%d", adapter, frontend);
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
@ -346,16 +354,12 @@ bool cDvbTuner::Bond(cDvbTuner *Tuner)
|
|||||||
{
|
{
|
||||||
cMutexLock MutexLock(&bondMutex);
|
cMutexLock MutexLock(&bondMutex);
|
||||||
if (!bondedTuner) {
|
if (!bondedTuner) {
|
||||||
if ((frontendType == SYS_DVBS || frontendType == SYS_DVBS2) && (Tuner->frontendType == SYS_DVBS || Tuner->frontendType == SYS_DVBS2)) {
|
ResetToneAndVoltage();
|
||||||
ResetToneAndVoltage();
|
bondedMaster = false; // makes sure we don't disturb an existing master
|
||||||
bondedMaster = false; // makes sure we don't disturb an existing master
|
bondedTuner = Tuner->bondedTuner ? Tuner->bondedTuner : Tuner;
|
||||||
bondedTuner = Tuner->bondedTuner ? Tuner->bondedTuner : Tuner;
|
Tuner->bondedTuner = this;
|
||||||
Tuner->bondedTuner = this;
|
dsyslog("tuner %d/%d bonded with tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend);
|
||||||
dsyslog("tuner %d/%d bonded with tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend);
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("ERROR: can't bond tuner %d/%d with tuner %d/%d (only DVB-S(2) tuners can be bonded)", adapter, frontend, Tuner->adapter, Tuner->frontend);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
esyslog("ERROR: tuner %d/%d already bonded with tuner %d/%d, can't bond with tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend, Tuner->adapter, Tuner->frontend);
|
esyslog("ERROR: tuner %d/%d already bonded with tuner %d/%d, can't bond with tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend, Tuner->adapter, Tuner->frontend);
|
||||||
@ -634,6 +638,10 @@ static unsigned int FrequencyToHz(unsigned int f)
|
|||||||
|
|
||||||
void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
|
void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
|
||||||
{
|
{
|
||||||
|
if (!lnbPowerTurnedOn) {
|
||||||
|
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
|
||||||
|
lnbPowerTurnedOn = true;
|
||||||
|
}
|
||||||
struct dvb_diseqc_master_cmd cmd;
|
struct dvb_diseqc_master_cmd cmd;
|
||||||
const char *CurrentAction = NULL;
|
const char *CurrentAction = NULL;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -662,6 +670,22 @@ void cDvbTuner::ResetToneAndVoltage(void)
|
|||||||
CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
|
CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTransponderParameters *Dtp)
|
||||||
|
{
|
||||||
|
int ds = SYS_UNDEFINED;
|
||||||
|
if (Channel->IsAtsc())
|
||||||
|
ds = SYS_ATSC;
|
||||||
|
else if (Channel->IsCable())
|
||||||
|
ds = SYS_DVBC_ANNEX_AC;
|
||||||
|
else if (Channel->IsSat())
|
||||||
|
ds = Dtp->System() == DVB_SYSTEM_1 ? SYS_DVBS : SYS_DVBS2;
|
||||||
|
else if (Channel->IsTerr())
|
||||||
|
ds = Dtp->System() == DVB_SYSTEM_1 ? SYS_DVBT : SYS_DVBT2;
|
||||||
|
else
|
||||||
|
esyslog("ERROR: can't determine frontend type for channel %d", Channel->Number());
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
bool cDvbTuner::SetFrontend(void)
|
bool cDvbTuner::SetFrontend(void)
|
||||||
{
|
{
|
||||||
#define MAXFRONTENDCMDS 16
|
#define MAXFRONTENDCMDS 16
|
||||||
@ -686,6 +710,12 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
|
|
||||||
cDvbTransponderParameters dtp(channel.Parameters());
|
cDvbTransponderParameters dtp(channel.Parameters());
|
||||||
|
|
||||||
|
// Determine the required frontend type:
|
||||||
|
int frontendType = GetRequiredDeliverySystem(&channel, &dtp);
|
||||||
|
if (frontendType == SYS_UNDEFINED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SETCMD(DTV_DELIVERY_SYSTEM, frontendType);
|
||||||
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) {
|
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) {
|
||||||
unsigned int frequency = channel.Frequency();
|
unsigned int frequency = channel.Frequency();
|
||||||
if (Setup.DiSEqC) {
|
if (Setup.DiSEqC) {
|
||||||
@ -728,22 +758,15 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
frequency = abs(frequency); // Allow for C-band, where the frequency is less than the LOF
|
frequency = abs(frequency); // Allow for C-band, where the frequency is less than the LOF
|
||||||
|
|
||||||
// DVB-S/DVB-S2 (common parts)
|
// DVB-S/DVB-S2 (common parts)
|
||||||
SETCMD(DTV_DELIVERY_SYSTEM, dtp.System());
|
|
||||||
SETCMD(DTV_FREQUENCY, frequency * 1000UL);
|
SETCMD(DTV_FREQUENCY, frequency * 1000UL);
|
||||||
SETCMD(DTV_MODULATION, dtp.Modulation());
|
SETCMD(DTV_MODULATION, dtp.Modulation());
|
||||||
SETCMD(DTV_SYMBOL_RATE, channel.Srate() * 1000UL);
|
SETCMD(DTV_SYMBOL_RATE, channel.Srate() * 1000UL);
|
||||||
SETCMD(DTV_INNER_FEC, dtp.CoderateH());
|
SETCMD(DTV_INNER_FEC, dtp.CoderateH());
|
||||||
SETCMD(DTV_INVERSION, dtp.Inversion());
|
SETCMD(DTV_INVERSION, dtp.Inversion());
|
||||||
if (dtp.System() == SYS_DVBS2) {
|
if (frontendType == SYS_DVBS2) {
|
||||||
if (frontendType == SYS_DVBS2) {
|
// DVB-S2
|
||||||
// DVB-S2
|
SETCMD(DTV_PILOT, PILOT_AUTO);
|
||||||
SETCMD(DTV_PILOT, PILOT_AUTO);
|
SETCMD(DTV_ROLLOFF, dtp.RollOff());
|
||||||
SETCMD(DTV_ROLLOFF, dtp.RollOff());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
esyslog("ERROR: frontend %d/%d doesn't provide DVB-S2", adapter, frontend);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// DVB-S
|
// DVB-S
|
||||||
@ -755,7 +778,6 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
}
|
}
|
||||||
else if (frontendType == SYS_DVBC_ANNEX_AC || frontendType == SYS_DVBC_ANNEX_B) {
|
else if (frontendType == SYS_DVBC_ANNEX_AC || frontendType == SYS_DVBC_ANNEX_B) {
|
||||||
// DVB-C
|
// DVB-C
|
||||||
SETCMD(DTV_DELIVERY_SYSTEM, frontendType);
|
|
||||||
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
||||||
SETCMD(DTV_INVERSION, dtp.Inversion());
|
SETCMD(DTV_INVERSION, dtp.Inversion());
|
||||||
SETCMD(DTV_SYMBOL_RATE, channel.Srate() * 1000UL);
|
SETCMD(DTV_SYMBOL_RATE, channel.Srate() * 1000UL);
|
||||||
@ -767,7 +789,6 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
}
|
}
|
||||||
else if (frontendType == SYS_DVBT) {
|
else if (frontendType == SYS_DVBT) {
|
||||||
// DVB-T
|
// DVB-T
|
||||||
SETCMD(DTV_DELIVERY_SYSTEM, frontendType);
|
|
||||||
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
||||||
SETCMD(DTV_INVERSION, dtp.Inversion());
|
SETCMD(DTV_INVERSION, dtp.Inversion());
|
||||||
SETCMD(DTV_BANDWIDTH_HZ, dtp.Bandwidth());
|
SETCMD(DTV_BANDWIDTH_HZ, dtp.Bandwidth());
|
||||||
@ -783,7 +804,6 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
}
|
}
|
||||||
else if (frontendType == SYS_ATSC) {
|
else if (frontendType == SYS_ATSC) {
|
||||||
// ATSC
|
// ATSC
|
||||||
SETCMD(DTV_DELIVERY_SYSTEM, frontendType);
|
|
||||||
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
||||||
SETCMD(DTV_INVERSION, dtp.Inversion());
|
SETCMD(DTV_INVERSION, dtp.Inversion());
|
||||||
SETCMD(DTV_MODULATION, dtp.Modulation());
|
SETCMD(DTV_MODULATION, dtp.Modulation());
|
||||||
@ -903,6 +923,7 @@ void cDvbSourceParam::GetData(cChannel *Channel)
|
|||||||
cOsdItem *cDvbSourceParam::GetOsdItem(void)
|
cOsdItem *cDvbSourceParam::GetOsdItem(void)
|
||||||
{
|
{
|
||||||
char type = Source();
|
char type = Source();
|
||||||
|
const tDvbParameterMap *SystemValues = type == 'S' ? SystemValuesSat : SystemValuesTerr;
|
||||||
#undef ST
|
#undef ST
|
||||||
#define ST(s) if (strchr(s, type))
|
#define ST(s) if (strchr(s, type))
|
||||||
switch (param++) {
|
switch (param++) {
|
||||||
@ -928,7 +949,7 @@ cOsdItem *cDvbSourceParam::GetOsdItem(void)
|
|||||||
int cDvbDevice::setTransferModeForDolbyDigital = 1;
|
int cDvbDevice::setTransferModeForDolbyDigital = 1;
|
||||||
cMutex cDvbDevice::bondMutex;
|
cMutex cDvbDevice::bondMutex;
|
||||||
|
|
||||||
const char *DeliverySystems[] = {
|
const char *DeliverySystemNames[] = {
|
||||||
"UNDEFINED",
|
"UNDEFINED",
|
||||||
"DVB-C",
|
"DVB-C",
|
||||||
"DVB-C",
|
"DVB-C",
|
||||||
@ -945,6 +966,8 @@ const char *DeliverySystems[] = {
|
|||||||
"DMBTH",
|
"DMBTH",
|
||||||
"CMMB",
|
"CMMB",
|
||||||
"DAB",
|
"DAB",
|
||||||
|
"DVB-T2",
|
||||||
|
"TURBO",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -954,8 +977,8 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
|
|||||||
frontend = Frontend;
|
frontend = Frontend;
|
||||||
ciAdapter = NULL;
|
ciAdapter = NULL;
|
||||||
dvbTuner = NULL;
|
dvbTuner = NULL;
|
||||||
frontendType = SYS_UNDEFINED;
|
numDeliverySystems = 0;
|
||||||
numProvidedSystems = 0;
|
numModulations = 0;
|
||||||
bondedDevice = NULL;
|
bondedDevice = NULL;
|
||||||
needsDetachBondedReceivers = false;
|
needsDetachBondedReceivers = false;
|
||||||
|
|
||||||
@ -976,39 +999,8 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
|
|||||||
// We only check the devices that must be present - the others will be checked before accessing them://XXX
|
// We only check the devices that must be present - the others will be checked before accessing them://XXX
|
||||||
|
|
||||||
if (fd_frontend >= 0) {
|
if (fd_frontend >= 0) {
|
||||||
if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) >= 0) {
|
if (QueryDeliverySystems(fd_frontend))
|
||||||
switch (frontendInfo.type) {
|
dvbTuner = new cDvbTuner(this, fd_frontend, adapter, frontend);
|
||||||
case FE_QPSK: frontendType = (frontendInfo.caps & FE_CAN_2G_MODULATION) ? SYS_DVBS2 : SYS_DVBS; break;
|
|
||||||
case FE_OFDM: frontendType = SYS_DVBT; break;
|
|
||||||
case FE_QAM: frontendType = SYS_DVBC_ANNEX_AC; break;
|
|
||||||
case FE_ATSC: frontendType = SYS_ATSC; break;
|
|
||||||
default: esyslog("ERROR: unknown frontend type %d on frontend %d/%d", frontendInfo.type, adapter, frontend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LOG_ERROR;
|
|
||||||
if (frontendType != SYS_UNDEFINED) {
|
|
||||||
numProvidedSystems++;
|
|
||||||
if (frontendType == SYS_DVBS2)
|
|
||||||
numProvidedSystems++;
|
|
||||||
char Modulations[64];
|
|
||||||
char *p = Modulations;
|
|
||||||
if (frontendInfo.caps & FE_CAN_QPSK) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(QPSK, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_QAM_16) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(QAM_16, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_QAM_32) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(QAM_32, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_QAM_64) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(QAM_64, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_QAM_128) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(QAM_128, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_QAM_256) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(QAM_256, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_8VSB) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(VSB_8, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_16VSB) { numProvidedSystems++; p += sprintf(p, ",%s", MapToUserString(VSB_16, ModulationValues)); }
|
|
||||||
if (frontendInfo.caps & FE_CAN_TURBO_FEC){numProvidedSystems++; p += sprintf(p, ",%s", "TURBO_FEC"); }
|
|
||||||
if (p != Modulations)
|
|
||||||
p = Modulations + 1; // skips first ','
|
|
||||||
else
|
|
||||||
p = (char *)"unknown modulations";
|
|
||||||
isyslog("frontend %d/%d provides %s with %s (\"%s\")", adapter, frontend, DeliverySystems[frontendType], p, frontendInfo.name);
|
|
||||||
dvbTuner = new cDvbTuner(this, fd_frontend, adapter, frontend, frontendType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
esyslog("ERROR: can't open DVB device %d/%d", adapter, frontend);
|
esyslog("ERROR: can't open DVB device %d/%d", adapter, frontend);
|
||||||
@ -1106,6 +1098,71 @@ LastAdapter:
|
|||||||
return Found > 0;
|
return Found > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cDvbDevice::QueryDeliverySystems(int fd_frontend)
|
||||||
|
{
|
||||||
|
numDeliverySystems = 0;
|
||||||
|
if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) < 0) {
|
||||||
|
LOG_ERROR;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if DVB_API_VERSION > 5 || DVB_API_VERSION_MINOR >= 5
|
||||||
|
dtv_property Frontend[1];
|
||||||
|
memset(&Frontend, 0, sizeof(Frontend));
|
||||||
|
dtv_properties CmdSeq;
|
||||||
|
memset(&CmdSeq, 0, sizeof(CmdSeq));
|
||||||
|
CmdSeq.props = Frontend;
|
||||||
|
SETCMD(DTV_ENUM_DELSYS, 0);
|
||||||
|
int Result = ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq);
|
||||||
|
if (Result == 0) {
|
||||||
|
for (uint i = 0; i < Frontend[0].u.buffer.len; i++) {
|
||||||
|
if (numDeliverySystems >= MAXDELIVERYSYSTEMS) {
|
||||||
|
esyslog("ERROR: too many delivery systems on frontend %d/%d", adapter, frontend);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deliverySystems[numDeliverySystems++] = Frontend[0].u.buffer.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
esyslog("ERROR: can't query delivery systems on frontend %d/%d - falling back to legacy mode", adapter, frontend);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
// Legacy mode (DVB-API < 5.5):
|
||||||
|
switch (frontendInfo.type) {
|
||||||
|
case FE_QPSK: deliverySystems[numDeliverySystems++] = SYS_DVBS;
|
||||||
|
if (frontendInfo.caps & FE_CAN_2G_MODULATION)
|
||||||
|
deliverySystems[numDeliverySystems++] = SYS_DVBS2;
|
||||||
|
break;
|
||||||
|
case FE_OFDM: deliverySystems[numDeliverySystems++] = SYS_DVBT; break;
|
||||||
|
case FE_QAM: deliverySystems[numDeliverySystems++] = SYS_DVBC_ANNEX_AC; break;
|
||||||
|
case FE_ATSC: deliverySystems[numDeliverySystems++] = SYS_ATSC; break;
|
||||||
|
default: esyslog("ERROR: unknown frontend type %d on frontend %d/%d", frontendInfo.type, adapter, frontend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numDeliverySystems > 0) {
|
||||||
|
cString ds("");
|
||||||
|
for (int i = 0; i < numDeliverySystems; i++)
|
||||||
|
ds = cString::sprintf("%s%s%s", *ds, i ? "," : "", DeliverySystemNames[deliverySystems[i]]);
|
||||||
|
cString ms("");
|
||||||
|
if (frontendInfo.caps & FE_CAN_QPSK) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QPSK, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_QAM_16) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_16, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_QAM_32) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_32, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_QAM_64) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_64, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_QAM_128) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_128, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_QAM_256) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_256, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_8VSB) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(VSB_8, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_16VSB) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(VSB_16, ModulationValues)); }
|
||||||
|
if (frontendInfo.caps & FE_CAN_TURBO_FEC) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", "TURBO_FEC"); }
|
||||||
|
if (!**ms)
|
||||||
|
ms = "unknown modulations";
|
||||||
|
isyslog("frontend %d/%d provides %s with %s (\"%s\")", adapter, frontend, *ds, *ms, frontendInfo.name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog("ERROR: frontend %d/%d doesn't provide any delivery systems", adapter, frontend);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool cDvbDevice::Ready(void)
|
bool cDvbDevice::Ready(void)
|
||||||
{
|
{
|
||||||
if (ciAdapter)
|
if (ciAdapter)
|
||||||
@ -1167,7 +1224,7 @@ bool cDvbDevice::Bond(cDvbDevice *Device)
|
|||||||
cMutexLock MutexLock(&bondMutex);
|
cMutexLock MutexLock(&bondMutex);
|
||||||
if (!bondedDevice) {
|
if (!bondedDevice) {
|
||||||
if (Device != this) {
|
if (Device != this) {
|
||||||
if ((frontendType == SYS_DVBS || frontendType == SYS_DVBS2) && (Device->frontendType == SYS_DVBS || Device->frontendType == SYS_DVBS2)) {
|
if ((ProvidesDeliverySystem(SYS_DVBS) || ProvidesDeliverySystem(SYS_DVBS2)) && (Device->ProvidesDeliverySystem(SYS_DVBS) || Device->ProvidesDeliverySystem(SYS_DVBS2))) {
|
||||||
if (dvbTuner && Device->dvbTuner && dvbTuner->Bond(Device->dvbTuner)) {
|
if (dvbTuner && Device->dvbTuner && dvbTuner->Bond(Device->dvbTuner)) {
|
||||||
bondedDevice = Device->bondedDevice ? Device->bondedDevice : Device;
|
bondedDevice = Device->bondedDevice ? Device->bondedDevice : Device;
|
||||||
Device->bondedDevice = this;
|
Device->bondedDevice = this;
|
||||||
@ -1285,14 +1342,23 @@ void cDvbDevice::CloseFilter(int Handle)
|
|||||||
close(Handle);
|
close(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cDvbDevice::ProvidesDeliverySystem(int DeliverySystem) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numDeliverySystems; i++) {
|
||||||
|
if (deliverySystems[i] == DeliverySystem)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool cDvbDevice::ProvidesSource(int Source) const
|
bool cDvbDevice::ProvidesSource(int Source) const
|
||||||
{
|
{
|
||||||
int type = Source & cSource::st_Mask;
|
int type = Source & cSource::st_Mask;
|
||||||
return type == cSource::stNone
|
return type == cSource::stNone
|
||||||
|| type == cSource::stAtsc && (frontendType == SYS_ATSC)
|
|| type == cSource::stAtsc && ProvidesDeliverySystem(SYS_ATSC)
|
||||||
|| type == cSource::stCable && (frontendType == SYS_DVBC_ANNEX_AC || frontendType == SYS_DVBC_ANNEX_B)
|
|| type == cSource::stCable && (ProvidesDeliverySystem(SYS_DVBC_ANNEX_AC) || ProvidesDeliverySystem(SYS_DVBC_ANNEX_B))
|
||||||
|| type == cSource::stSat && (frontendType == SYS_DVBS || frontendType == SYS_DVBS2)
|
|| type == cSource::stSat && (ProvidesDeliverySystem(SYS_DVBS) || ProvidesDeliverySystem(SYS_DVBS2))
|
||||||
|| type == cSource::stTerr && (frontendType == SYS_DVBT);
|
|| type == cSource::stTerr && ProvidesDeliverySystem(SYS_DVBT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
|
bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
|
||||||
@ -1300,7 +1366,7 @@ bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
|
|||||||
if (!ProvidesSource(Channel->Source()))
|
if (!ProvidesSource(Channel->Source()))
|
||||||
return false; // doesn't provide source
|
return false; // doesn't provide source
|
||||||
cDvbTransponderParameters dtp(Channel->Parameters());
|
cDvbTransponderParameters dtp(Channel->Parameters());
|
||||||
if (dtp.System() == SYS_DVBS2 && frontendType == SYS_DVBS ||
|
if (!ProvidesDeliverySystem(GetRequiredDeliverySystem(Channel, &dtp)) ||
|
||||||
dtp.Modulation() == QPSK && !(frontendInfo.caps & FE_CAN_QPSK) ||
|
dtp.Modulation() == QPSK && !(frontendInfo.caps & FE_CAN_QPSK) ||
|
||||||
dtp.Modulation() == QAM_16 && !(frontendInfo.caps & FE_CAN_QAM_16) ||
|
dtp.Modulation() == QAM_16 && !(frontendInfo.caps & FE_CAN_QAM_16) ||
|
||||||
dtp.Modulation() == QAM_32 && !(frontendInfo.caps & FE_CAN_QAM_32) ||
|
dtp.Modulation() == QAM_32 && !(frontendInfo.caps & FE_CAN_QAM_32) ||
|
||||||
@ -1375,7 +1441,7 @@ bool cDvbDevice::ProvidesEIT(void) const
|
|||||||
|
|
||||||
int cDvbDevice::NumProvidedSystems(void) const
|
int cDvbDevice::NumProvidedSystems(void) const
|
||||||
{
|
{
|
||||||
return numProvidedSystems;
|
return numDeliverySystems + numModulations;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cDvbDevice::SignalStrength(void) const
|
int cDvbDevice::SignalStrength(void) const
|
||||||
|
14
dvbdevice.h
14
dvbdevice.h
@ -4,13 +4,12 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbdevice.h 2.18 2011/12/04 13:38:17 kls Exp $
|
* $Id: dvbdevice.h 2.19 2012/01/06 13:29:46 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBDEVICE_H
|
#ifndef __DVBDEVICE_H
|
||||||
#define __DVBDEVICE_H
|
#define __DVBDEVICE_H
|
||||||
|
|
||||||
#include <sys/mman.h> // FIXME: workaround for broken linux-dvb header files
|
|
||||||
#include <linux/dvb/frontend.h>
|
#include <linux/dvb/frontend.h>
|
||||||
#include <linux/dvb/version.h>
|
#include <linux/dvb/version.h>
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
@ -20,6 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAXDVBDEVICES 8
|
#define MAXDVBDEVICES 8
|
||||||
|
#define MAXDELIVERYSYSTEMS 8
|
||||||
|
|
||||||
#define DEV_VIDEO "/dev/video"
|
#define DEV_VIDEO "/dev/video"
|
||||||
#define DEV_DVB_ADAPTER "/dev/dvb/adapter"
|
#define DEV_DVB_ADAPTER "/dev/dvb/adapter"
|
||||||
@ -47,7 +47,8 @@ extern const tDvbParameterMap InversionValues[];
|
|||||||
extern const tDvbParameterMap BandwidthValues[];
|
extern const tDvbParameterMap BandwidthValues[];
|
||||||
extern const tDvbParameterMap CoderateValues[];
|
extern const tDvbParameterMap CoderateValues[];
|
||||||
extern const tDvbParameterMap ModulationValues[];
|
extern const tDvbParameterMap ModulationValues[];
|
||||||
extern const tDvbParameterMap SystemValues[];
|
extern const tDvbParameterMap SystemValuesSat[];
|
||||||
|
extern const tDvbParameterMap SystemValuesTerr[];
|
||||||
extern const tDvbParameterMap TransmissionValues[];
|
extern const tDvbParameterMap TransmissionValues[];
|
||||||
extern const tDvbParameterMap GuardValues[];
|
extern const tDvbParameterMap GuardValues[];
|
||||||
extern const tDvbParameterMap HierarchyValues[];
|
extern const tDvbParameterMap HierarchyValues[];
|
||||||
@ -119,12 +120,14 @@ protected:
|
|||||||
int adapter, frontend;
|
int adapter, frontend;
|
||||||
private:
|
private:
|
||||||
dvb_frontend_info frontendInfo;
|
dvb_frontend_info frontendInfo;
|
||||||
int numProvidedSystems;
|
int deliverySystems[MAXDELIVERYSYSTEMS];
|
||||||
fe_delivery_system frontendType;
|
int numDeliverySystems;
|
||||||
|
int numModulations;
|
||||||
int fd_dvr, fd_ca;
|
int fd_dvr, fd_ca;
|
||||||
static cMutex bondMutex;
|
static cMutex bondMutex;
|
||||||
cDvbDevice *bondedDevice;
|
cDvbDevice *bondedDevice;
|
||||||
mutable bool needsDetachBondedReceivers;
|
mutable bool needsDetachBondedReceivers;
|
||||||
|
bool QueryDeliverySystems(int fd_frontend);
|
||||||
public:
|
public:
|
||||||
cDvbDevice(int Adapter, int Frontend);
|
cDvbDevice(int Adapter, int Frontend);
|
||||||
virtual ~cDvbDevice();
|
virtual ~cDvbDevice();
|
||||||
@ -167,6 +170,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
cDvbTuner *dvbTuner;
|
cDvbTuner *dvbTuner;
|
||||||
public:
|
public:
|
||||||
|
virtual bool ProvidesDeliverySystem(int DeliverySystem) const;
|
||||||
virtual bool ProvidesSource(int Source) const;
|
virtual bool ProvidesSource(int Source) const;
|
||||||
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
||||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||||
|
7
nit.c
7
nit.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: nit.c 2.6 2011/08/12 14:27:31 kls Exp $
|
* $Id: nit.c 2.7 2012/01/06 12:45:39 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nit.h"
|
#include "nit.h"
|
||||||
@ -16,6 +16,9 @@
|
|||||||
#include "libsi/descriptor.h"
|
#include "libsi/descriptor.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
|
#define DVB_SYSTEM_1 0 // see also dvbdevice.c
|
||||||
|
#define DVB_SYSTEM_2 1
|
||||||
|
|
||||||
cNitFilter::cNitFilter(void)
|
cNitFilter::cNitFilter(void)
|
||||||
{
|
{
|
||||||
numNits = 0;
|
numNits = 0;
|
||||||
@ -134,7 +137,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
|||||||
dtp.SetCoderateH(CodeRates[sd->getFecInner()]);
|
dtp.SetCoderateH(CodeRates[sd->getFecInner()]);
|
||||||
static int Modulations[] = { QAM_AUTO, QPSK, PSK_8, QAM_16 };
|
static int Modulations[] = { QAM_AUTO, QPSK, PSK_8, QAM_16 };
|
||||||
dtp.SetModulation(Modulations[sd->getModulationType()]);
|
dtp.SetModulation(Modulations[sd->getModulationType()]);
|
||||||
dtp.SetSystem(sd->getModulationSystem() ? SYS_DVBS2 : SYS_DVBS);
|
dtp.SetSystem(sd->getModulationSystem() ? DVB_SYSTEM_2 : DVB_SYSTEM_1);
|
||||||
static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
|
static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
|
||||||
dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
|
dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
|
||||||
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
|
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
|
||||||
|
Loading…
Reference in New Issue
Block a user