--- vdr-1.6.0/device.h 2008-02-23 15:13:04.000000000 +0200 +++ vdr-1.6.0-testing/device.h 2008-06-22 01:27:10.000000000 +0300 @@ -189,6 +189,30 @@ virtual bool HasDecoder(void) const; ///< Tells whether this device has an MPEG decoder. +// Frontend facilities + +public: + virtual cString GetInfo(void); + ///< Returns information string of this device. + virtual bool HasSignal(void); + ///< Returns true if found something above the noise level. + virtual bool HasCarrier(void); + ///< Returns true if found a DVB signal. + virtual bool HasViterbi(void); + ///< Returns true if FEC is stable. + virtual bool HasSync(void); + ///< Returns true if found sync bytes. + virtual bool HasLocked(void); + ///< Returns true if everything's working. + virtual uint16_t GetSignalStrength(void); + ///< Returns signal strength. + virtual uint16_t GetSignalToNoiseRatio(void); + ///< Returns signal-to-noise ratio. + virtual uint32_t GetBitErrorRate(void); + ///< Returns bit error rate. + virtual uint32_t GetUncorrectedBlocks(void); + ///< Returns uncorrected blocks count. + // SPU facilities private: --- vdr-1.6.0/device.c 2008-05-08 22:56:16.000000000 +0300 +++ vdr-1.6.0-testing/device.c 2008-06-22 00:58:44.000000000 +0300 @@ -337,6 +337,56 @@ return false; } +cString cDevice::GetInfo(void) +{ + return NULL; +} + +bool cDevice::HasSignal(void) +{ + return false; +} + +bool cDevice::HasCarrier(void) +{ + return false; +} + +bool cDevice::HasViterbi(void) +{ + return false; +} + +bool cDevice::HasSync(void) +{ + return false; +} + +bool cDevice::HasLocked(void) +{ + return false; +} + +uint16_t cDevice::GetSignalStrength(void) +{ + return 0; +} + +uint16_t cDevice::GetSignalToNoiseRatio(void) +{ + return 0; +} + +uint32_t cDevice::GetBitErrorRate(void) +{ + return 0; +} + +uint32_t cDevice::GetUncorrectedBlocks(void) +{ + return 0; +} + cSpuDecoder *cDevice::GetSpuDecoder(void) { return NULL; --- vdr-1.6.0/dvbdevice.h 2008-02-08 15:48:31.000000000 +0200 +++ vdr-1.6.0-testing/dvbdevice.h 2008-06-22 00:58:57.000000000 +0300 @@ -50,6 +50,20 @@ private: cCiAdapter *ciAdapter; +// Frontend facilities + +public: + virtual cString GetInfo(void); + virtual bool HasSignal(void); + virtual bool HasCarrier(void); + virtual bool HasViterbi(void); + virtual bool HasSync(void); + virtual bool HasLocked(void); + virtual uint16_t GetSignalStrength(void); + virtual uint16_t GetSignalToNoiseRatio(void); + virtual uint32_t GetBitErrorRate(void); + virtual uint32_t GetUncorrectedBlocks(void); + // SPU facilities private: --- vdr-1.6.0/dvbdevice.c 2008-02-09 18:11:44.000000000 +0200 +++ vdr-1.6.0-testing/dvbdevice.c 2008-06-22 00:59:10.000000000 +0300 @@ -77,13 +77,13 @@ int lockTimeout; time_t lastTimeoutReport; fe_type_t frontendType; + cString frontendName; cChannel channel; const char *diseqcCommands; eTunerStatus tunerStatus; cMutex mutex; cCondVar locked; cCondVar newSet; - bool GetFrontendStatus(fe_status_t &Status, int TimeoutMs = 0); bool SetFrontend(void); virtual void Action(void); public: @@ -92,10 +92,17 @@ bool IsTunedTo(const cChannel *Channel) const; void Set(const cChannel *Channel, bool Tune); bool Locked(int TimeoutMs = 0); + bool GetFrontendStatus(fe_status_t &Status, int TimeoutMs = 0); + bool GetSignal(uint16_t &Signal, int TimeoutMs = 0); + bool GetSNR(uint16_t &Snr, int TimeoutMs = 0); + bool GetBER(uint32_t &Ber, int TimeoutMs = 0); + bool GetUNC(uint32_t &Unc, int TimeoutMs = 0); + cString GetFrontendName(void) { return frontendName; } }; cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType) { + struct dvb_frontend_info info; fd_frontend = Fd_Frontend; cardIndex = CardIndex; frontendType = FrontendType; @@ -104,6 +111,8 @@ lastTimeoutReport = 0; diseqcCommands = NULL; tunerStatus = tsIdle; + CHECK(ioctl(fd_frontend, FE_GET_INFO, &info)); + frontendName = cString(info.name); if (frontendType == FE_QPSK) CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power SetDescription("tuner on device %d", cardIndex + 1); @@ -164,6 +173,82 @@ return false; } +bool cDvbTuner::GetSignal(uint16_t &Signal, int TimeoutMs) +{ + if (TimeoutMs) { + cPoller Poller(fd_frontend); + if (Poller.Poll(TimeoutMs)) { + dvb_frontend_event Event; + while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0) + ; // just to clear the event queue - we'll read the actual status below + } + } + while (1) { + if (ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1) + return true; + if (errno != EINTR) + break; + } + return false; +} + +bool cDvbTuner::GetSNR(uint16_t &Snr, int TimeoutMs) +{ + if (TimeoutMs) { + cPoller Poller(fd_frontend); + if (Poller.Poll(TimeoutMs)) { + dvb_frontend_event Event; + while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0) + ; // just to clear the event queue - we'll read the actual status below + } + } + while (1) { + if (ioctl(fd_frontend, FE_READ_SNR, &Snr) != -1) + return true; + if (errno != EINTR) + break; + } + return false; +} + +bool cDvbTuner::GetBER(uint32_t &Ber, int TimeoutMs) +{ + if (TimeoutMs) { + cPoller Poller(fd_frontend); + if (Poller.Poll(TimeoutMs)) { + dvb_frontend_event Event; + while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0) + ; // just to clear the event queue - we'll read the actual status below + } + } + while (1) { + if (ioctl(fd_frontend, FE_READ_BER, &Ber) != -1) + return true; + if (errno != EINTR) + break; + } + return false; +} + +bool cDvbTuner::GetUNC(uint32_t &Unc, int TimeoutMs) +{ + if (TimeoutMs) { + cPoller Poller(fd_frontend); + if (Poller.Poll(TimeoutMs)) { + dvb_frontend_event Event; + while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0) + ; // just to clear the event queue - we'll read the actual status below + } + } + while (1) { + if (ioctl(fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &Unc) != -1) + return true; + if (errno != EINTR) + break; + } + return false; +} + static unsigned int FrequencyToHz(unsigned int f) { while (f && f < 1000000) @@ -500,6 +585,85 @@ return true; } +cString cDvbDevice::GetInfo(void) +{ + if (dvbTuner) + return dvbTuner->GetFrontendName(); + return NULL; +} + +bool cDvbDevice::HasSignal(void) +{ + fe_status_t status; + if (dvbTuner && dvbTuner->GetFrontendStatus(status) && (status & FE_HAS_SIGNAL)) + return true; + return false; +} + +bool cDvbDevice::HasCarrier(void) +{ + fe_status_t status; + if (dvbTuner && dvbTuner->GetFrontendStatus(status) && (status & FE_HAS_CARRIER)) + return true; + return false; +} + +bool cDvbDevice::HasViterbi(void) +{ + fe_status_t status; + if (dvbTuner && dvbTuner->GetFrontendStatus(status) && (status & FE_HAS_VITERBI)) + return true; + return false; +} + +bool cDvbDevice::HasSync(void) +{ + fe_status_t status; + if (dvbTuner && dvbTuner->GetFrontendStatus(status) && (status & FE_HAS_SYNC)) + return true; + return false; +} + +bool cDvbDevice::HasLocked(void) +{ + fe_status_t status; + if (dvbTuner && dvbTuner->GetFrontendStatus(status) && (status & FE_HAS_LOCK)) + return true; + return false; +} + +uint16_t cDvbDevice::GetSignalStrength(void) +{ + uint16_t strength = 0; + if (dvbTuner && dvbTuner->GetSignal(strength)) + return strength; + return 0; +} + +uint16_t cDvbDevice::GetSignalToNoiseRatio(void) +{ + uint16_t snr = 0; + if (dvbTuner && dvbTuner->GetSNR(snr)) + return snr; + return 0; +} + +uint32_t cDvbDevice::GetBitErrorRate(void) +{ + uint32_t ber = 0; + if (dvbTuner && dvbTuner->GetBER(ber)) + return ber; + return 0; +} + +uint32_t cDvbDevice::GetUncorrectedBlocks(void) +{ + uint32_t unc = 0; + if (dvbTuner && dvbTuner->GetUNC(unc)) + return unc; + return 0; +} + cSpuDecoder *cDvbDevice::GetSpuDecoder(void) { if (!spuDecoder && IsPrimaryDevice())