From patchwork Wed Jan 4 12:36:30 2006 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Klaus Schmidinger X-Patchwork-Id: 12134 Received: from tiger.cadsoft.de ([217.7.101.210]) by www.linuxtv.org with esmtp (Exim 4.50) id 1Eu7sZ-000328-0q for vdr@linuxtv.org; Wed, 04 Jan 2006 13:36:35 +0100 Received: from raven.cadsoft.de (raven.cadsoft.de [217.7.101.211]) by tiger.cadsoft.de (8.13.4/8.13.4) with ESMTP id k04CaYSY009768 for ; Wed, 4 Jan 2006 13:36:34 +0100 Received: from [192.168.100.10] (hawk.cadsoft.de [192.168.100.10]) by raven.cadsoft.de (8.13.3/8.13.3) with ESMTP id k04CaWl6001946 for ; Wed, 4 Jan 2006 13:36:33 +0100 Message-ID: <43BBC14E.7000703@cadsoft.de> Date: Wed, 04 Jan 2006 13:36:30 +0100 From: Klaus Schmidinger Organization: CadSoft Computer GmbH User-Agent: Mozilla Thunderbird 1.0.6 (X11/20050716) X-Accept-Language: en MIME-Version: 1.0 To: vdr@linuxtv.org Subject: Re: [vdr] VDR-1.3.37: retuning -- possibly a fix for VDSB References: <43936C1D.2070904@gmx.de> <43BA606B.5010703@cadsoft.de> <43BAB324.1000902@gmx.de> <43BBB460.6050309@cadsoft.de> In-Reply-To: <43BBB460.6050309@cadsoft.de> X-Greylist: Sender DNS name whitelisted, not delayed by milter-greylist-2.0.2 (tiger.cadsoft.de [217.7.101.210]); Wed, 04 Jan 2006 13:36:34 +0100 (CET) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-2.0 (raven.cadsoft.de [192.168.1.1]); Wed, 04 Jan 2006 13:36:34 +0100 (CET) X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Jan 2006 12:36:35 -0000 Status: O X-Status: X-Keywords: X-UID: 6903 Klaus Schmidinger wrote: > Thomas Rausch wrote: > >> After 6 hours I must say that my VDR did not bring yet back the error. >> So far otherwise always. I want to hope that it functions now. :) >> >> In the LOG comes however repeatedly: >> >> Jan 3 18:15:43 cat vdr[16675]: ERROR: frontend 0 lost lock >> Jan 3 18:15:43 cat vdr[16675]: frontend 0 regained lock >> Jan 3 18:16:03 cat vdr[16675]: ERROR: frontend 0 lost lock >> Jan 3 18:16:03 cat vdr[16675]: frontend 0 regained lock >> Jan 3 18:16:25 cat vdr[16675]: ERROR: frontend 0 lost lock >> Jan 3 18:16:26 cat vdr[16675]: frontend 0 regained lock >> Jan 3 18:16:45 cat vdr[16675]: ERROR: frontend 0 lost lock >> Jan 3 18:16:45 cat vdr[16675]: frontend 0 regained lock >> Jan 3 18:17:06 cat vdr[16675]: ERROR: frontend 0 lost lock >> Jan 3 18:17:06 cat vdr[16675]: frontend 0 regained lock > > > Apparently the FE_GET_EVENT ioctl() sometimes delivers a different > status value than FE_READ_STATUS. I ran some tests, comparing both > values and whenever VDR reported a lost lock, the current FE_READ_STATUS > value still had the FE_HAS_LOCK set correctly. > > Following an old recommendation of Holger Wächtler I finally changed > the frontend status handling so that it polls the frontend and reads > any pending event (but simply discards it), and then reads the actual > status via FE_READ_STATUS. > > With the attached patch (which is again a complete patch against > dvbdevice.c of version 1.3.37) I don't get these spurious "lost lock" > messages any more. > > I've also increased the timeout for polling the event queue to 10ms, > because 1ms seemed a little hard to me. This had no effect on the > "lost lock" problem, however, so the change in status handling really > is what fixed it. > > Please try whether this also helps in your case. Unfortunately this broke the CAM menu handling, so here's a slightly different version. Sorry about that... Klaus --- dvbdevice.c 2005/11/26 13:23:11 1.138 +++ dvbdevice.c 2006/01/04 12:33:33 @@ -47,6 +40,13 @@ #define DEV_DVB_AUDIO "audio" #define DEV_DVB_CA "ca" +#define DVBS_TUNE_TIMEOUT 2000 //ms +#define DVBS_LOCK_TIMEOUT 2000 //ms +#define DVBC_TUNE_TIMEOUT 5000 //ms +#define DVBC_LOCK_TIMEOUT 2000 //ms +#define DVBT_TUNE_TIMEOUT 9000 //ms +#define DVBT_LOCK_TIMEOUT 2000 //ms + class cDvbName { private: char buffer[PATH_MAX]; @@ -73,6 +73,9 @@ enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked }; int fd_frontend; int cardIndex; + int tuneTimeout; + int lockTimeout; + time_t lastTimeoutReport; fe_type_t frontendType; cCiHandler *ciHandler; cChannel channel; @@ -81,7 +84,7 @@ cMutex mutex; cCondVar locked; cCondVar newSet; - bool GetFrontendEvent(dvb_frontend_event &Event, int TimeoutMs = 0); + bool GetFrontendStatus(fe_status_t &Status, int TimeoutMs = 0); bool SetFrontend(void); virtual void Action(void); public: @@ -98,6 +101,9 @@ cardIndex = CardIndex; frontendType = FrontendType; ciHandler = CiHandler; + tuneTimeout = 0; + lockTimeout = 0; + lastTimeoutReport = 0; diseqcCommands = NULL; tunerStatus = tsIdle; if (frontendType == FE_QPSK) @@ -125,6 +131,7 @@ if (Tune) tunerStatus = tsSet; channel = *Channel; + lastTimeoutReport = 0; newSet.Broadcast(); } @@ -140,26 +147,20 @@ return tunerStatus >= tsLocked; } -bool cDvbTuner::GetFrontendEvent(dvb_frontend_event &Event, int TimeoutMs) +bool cDvbTuner::GetFrontendStatus(fe_status_t &Status, int TimeoutMs) { if (TimeoutMs) { - struct pollfd pfd; - pfd.fd = fd_frontend; - pfd.events = POLLIN | POLLPRI; - do { - int stat = poll(&pfd, 1, TimeoutMs); - if (stat == 1) - break; - if (stat < 0) { - if (errno == EINTR) - continue; - esyslog("ERROR: frontend %d poll failed: %m", cardIndex); - } + cPoller Poller(fd_frontend); + if (Poller.Poll(TimeoutMs)) { + // just to clear the event queue - we'll read the actual status below + dvb_frontend_event Event; + CHECK(ioctl(fd_frontend, FE_GET_EVENT, &Event)); + } + else return false; - } while (0); } do { - int stat = ioctl(fd_frontend, FE_GET_EVENT, &Event); + int stat = ioctl(fd_frontend, FE_READ_STATUS, &Status); if (stat == 0) return true; if (stat < 0) { @@ -245,6 +246,9 @@ Frontend.inversion = fe_spectral_inversion_t(channel.Inversion()); Frontend.u.qpsk.symbol_rate = channel.Srate() * 1000UL; Frontend.u.qpsk.fec_inner = fe_code_rate_t(channel.CoderateH()); + + tuneTimeout = DVBS_TUNE_TIMEOUT; + lockTimeout = DVBS_LOCK_TIMEOUT; } break; case FE_QAM: { // DVB-C @@ -256,6 +260,9 @@ Frontend.u.qam.symbol_rate = channel.Srate() * 1000UL; Frontend.u.qam.fec_inner = fe_code_rate_t(channel.CoderateH()); Frontend.u.qam.modulation = fe_modulation_t(channel.Modulation()); + + tuneTimeout = DVBC_TUNE_TIMEOUT; + lockTimeout = DVBC_LOCK_TIMEOUT; } break; case FE_OFDM: { // DVB-T @@ -271,6 +278,9 @@ Frontend.u.ofdm.transmission_mode = fe_transmit_mode_t(channel.Transmission()); Frontend.u.ofdm.guard_interval = fe_guard_interval_t(channel.Guard()); Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(channel.Hierarchy()); + + tuneTimeout = DVBT_TUNE_TIMEOUT; + lockTimeout = DVBT_LOCK_TIMEOUT; } break; default: @@ -286,29 +296,57 @@ void cDvbTuner::Action(void) { - dvb_frontend_event event; + cTimeMs Timer; + bool LostLock = false; + fe_status_t Status = (fe_status_t)0; while (Running()) { - bool hasEvent = GetFrontendEvent(event, 1); - + bool StatusChanged = false; + fe_status_t NewStatus; + if (GetFrontendStatus(NewStatus, 10)) { + StatusChanged = NewStatus != Status; + Status = NewStatus; + } cMutexLock MutexLock(&mutex); switch (tunerStatus) { case tsIdle: break; case tsSet: - if (hasEvent) - continue; tunerStatus = SetFrontend() ? tsTuned : tsIdle; + Timer.Set(tuneTimeout); continue; case tsTuned: + if (Timer.TimedOut()) { + tunerStatus = tsSet; + diseqcCommands = NULL; + if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these + esyslog("ERROR: frontend %d timed out while tuning", cardIndex); + lastTimeoutReport = time(NULL); + } + continue; + } case tsLocked: - if (hasEvent) { - if (event.status & FE_REINIT) { + if (StatusChanged) { + if (Status & FE_REINIT) { tunerStatus = tsSet; - esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex); + diseqcCommands = NULL; + esyslog("ERROR: frontend %d was reinitialized", cardIndex); + lastTimeoutReport = 0; } - if (event.status & FE_HAS_LOCK) { + else if (Status & FE_HAS_LOCK) { + if (LostLock) { + esyslog("frontend %d regained lock", cardIndex); + LostLock = false; + } tunerStatus = tsLocked; locked.Broadcast(); + lastTimeoutReport = 0; + } + else if (tunerStatus == tsLocked) { + LostLock = true; + esyslog("ERROR: frontend %d lost lock", cardIndex); + tunerStatus = tsTuned; + Timer.Set(lockTimeout); + lastTimeoutReport = 0; } continue; }