From patchwork Sun Oct 13 09:02:52 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christopher Reimer X-Patchwork-Id: 20378 Received: from localhost ([127.0.0.1] helo=www.linuxtv.org) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1VVHZj-0004be-1o; Sun, 13 Oct 2013 11:02:59 +0200 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1VVHZe-0004bY-OA for vdr@linuxtv.org; Sun, 13 Oct 2013 11:02:55 +0200 X-tubIT-Incoming-IP: 95.143.172.183 Received: from sculptor.uberspace.de ([95.143.172.183]) by mail.tu-berlin.de (exim-4.72/mailfrontend-5) with smtp for id 1VVHZd-0006xR-7o; Sun, 13 Oct 2013 11:02:54 +0200 Received: (qmail 27486 invoked from network); 13 Oct 2013 09:02:52 -0000 Received: from unknown (HELO creimer.sculptor.uberspace.de) (127.0.0.1) by localhost with SMTP; 13 Oct 2013 09:02:52 -0000 MIME-Version: 1.0 Date: Sun, 13 Oct 2013 11:02:52 +0200 From: Christopher Reimer To: VDR Mailing List In-Reply-To: <525A5D0A.2000908@tvdr.de> References: " <5259A128.8000106@alice.it>" <5259BA56.9070508@tvdr.de> <525A5D0A.2000908@tvdr.de> Message-ID: <1fbcbe780934f0220d36a97cccd8b7d3@creimer.sculptor.uberspace.de> X-Sender: vdr@creimer.net User-Agent: Roundcube Webmail/0.9.4 X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2013.10.13.85414 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' HTML_50_70 0.1, SUPERLONG_LINE 0.05, BODYTEXTH_SIZE_10000_LESS 0, BODYTEXTP_SIZE_3000_LESS 0, BODY_SIZE_10000_PLUS 0, WEBMAIL_SOURCE 0, WEBMAIL_USER_AGENT 0, __ANY_URI 0, __BOUNCE_CHALLENGE_SUBJ 0, __BOUNCE_NDR_SUBJ_EXEMPT 0, __CP_URI_IN_BODY 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __CTYPE_MULTIPART_MIXED 0, __FORWARDED_MSG 0, __HAS_FROM 0, __HAS_HTML 0, __HAS_MSGID 0, __IN_REP_TO 0, __MIME_HTML 0, __MIME_VERSION 0, __SANE_MSGID 0, __SUBJ_ALPHA_NEGATE 0, __TAG_EXISTS_HTML 0, __TO_MALFORMED_2 0, __URI_NS , __USER_AGENT 0' X-LSpam-Score: 0.9 (/) X-LSpam-Report: No, score=0.9 required=5.0 tests=BAYES_00=-1.9, HTML_MESSAGE=2, RDNS_NONE=0.793, URIBL_BLOCKED=0.001 autolearn=no Subject: Re: [vdr] Fix SIGNALSTRENGTH in vdr 2.0.3 TechniSat SkyStar 2 DVB-S rev 2.3P - dvbdevice.c X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.13 Precedence: list Reply-To: VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: vdr-bounces@linuxtv.org Errors-To: vdr-bounces@linuxtv.org What's the problem? I wasn't difficult at all to generate a diff. Christopher Am 13.10.2013 10:42, schrieb Klaus Schmidinger: > On 13.10.2013 01:45, VDR User wrote: > >> Shouldn't something like this be fixed in the driver? > > I don't know - haven't seen the 'diff' yet ;-) > > Klaus > On Sat, Oct 12, 2013 at 2:08 PM, Klaus Schmidinger wrote: On 12.10.2013 21:21, knap.home wrote: With this change to the source I was able to run properly "SIGNAL STRENGTH." Using the device Netsystem TechniSat SkyStar 2 DVB-S rev 2.3P. Great as a solution ... Modified Source -> /usr/local/src/vdr-2.0.3/dvbdevice.c Please send just the differences (diff -u) between the original and the modified code. I'm afraid even though I tried I can't seem to generate a proper diff from what you've posted. And please send it as an attachment, not inline (lines get wrapped). Klaus --- dvbdevice.c 2013-08-23 11:52:14.000000000 +0200 +++ dvbdevice.c.edit 2013-10-13 10:58:44.262951623 +0200 @@ -285,9 +285,10 @@ private: static cMutex bondMutex; enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked }; + bool SendDiseqc; int frontendType; const cDvbDevice *device; - int fd_frontend; + mutable int fd_frontend; int adapter, frontend; uint32_t subsystemId; int tuneTimeout; @@ -298,9 +299,10 @@ const cScr *scr; bool lnbPowerTurnedOn; eTunerStatus tunerStatus; - cMutex mutex; + mutable cMutex mutex; cCondVar locked; cCondVar newSet; + dvb_diseqc_master_cmd diseqc_cmd; cDvbTuner *bondedTuner; bool bondedMaster; bool SetFrontendType(const cChannel *Channel); @@ -313,6 +315,10 @@ void ResetToneAndVoltage(void); bool SetFrontend(void); virtual void Action(void); + + mutable bool isIdle; + bool OpenFrontend(void) const; + bool CloseFrontend(void); public: cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend); virtual ~cDvbTuner(); @@ -327,12 +333,18 @@ bool Locked(int TimeoutMs = 0); int GetSignalStrength(void) const; int GetSignalQuality(void) const; + bool SetIdle(bool Idle); + bool IsIdle(void) const { return isIdle; } + bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd); +private: + int GetCurrentDeliverySystem(void); }; cMutex cDvbTuner::bondMutex; cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend) { + SendDiseqc = false; frontendType = SYS_UNDEFINED; device = Device; fd_frontend = Fd_Frontend; @@ -348,6 +360,7 @@ tunerStatus = tsIdle; bondedTuner = NULL; bondedMaster = false; + isIdle = false; SetDescription("tuner on frontend %d/%d", adapter, frontend); Start(); } @@ -365,6 +378,8 @@ ExecuteDiseqc(lastDiseqc, &Frequency); } */ + if (device && device->IsSubDevice()) + CloseFrontend(); } bool cDvbTuner::Bond(cDvbTuner *Tuner) @@ -509,6 +524,8 @@ void cDvbTuner::ClearEventQueue(void) const { + if (!OpenFrontend()) + return; cPoller Poller(fd_frontend); if (Poller.Poll(TUNER_POLL_TIMEOUT)) { dvb_frontend_event Event; @@ -531,32 +548,104 @@ //#define DEBUG_SIGNALSTRENGTH //#define DEBUG_SIGNALQUALITY - +#define LOCK_THRESHOLD 5 // indicates that all 5 FE_HAS_* flags are set +// Inizio Modifica int cDvbTuner::GetSignalStrength(void) const { - ClearEventQueue(); - uint16_t Signal; - while (1) { - if (ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1) - break; - if (errno != EINTR) - return -1; + fe_status_t Status; + if (GetFrontendStatus(Status)) { + // Actually one would expect these checks to be done from FE_HAS_SIGNAL to FE_HAS_LOCK, but some drivers (like the stb0899) are broken, so FE_HAS_LOCK is the only one that (hopefully) is generally reliable... + if ((Status & FE_HAS_LOCK) == 0) { + if ((Status & FE_HAS_SIGNAL) == 0) + return 0; + if ((Status & FE_HAS_CARRIER) == 0) + return 1; + if ((Status & FE_HAS_VITERBI) == 0) + return 2; + if ((Status & FE_HAS_SYNC) == 0) + return 3; + return 4; } - uint16_t MaxSignal = 0xFFFF; // Let's assume the default is using the entire range. - // Use the subsystemId to identify individual devices in case they need - // special treatment to map their Signal value into the range 0...0xFFFF. - switch (subsystemId) { - case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2) - case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2) - MaxSignal = 670; break; - } - int s = int(Signal) * 100 / MaxSignal; - if (s > 100) - s = 100; #ifdef DEBUG_SIGNALSTRENGTH - fprintf(stderr, "FE %d/%d: %08X S = %04X %04X %3d%%\n", adapter, frontend, subsystemId, MaxSignal, Signal, s); + bool HasSignal = true; #endif - return s; + uint16_t Signal; + while (1) { + if (ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1) + break; + if (errno != EINTR) { + Signal = 0xFFFF; +#ifdef DEBUG_SIGNALSTRENGTH + HasSignal = false; +#endif + break; + } + } +#ifdef DEBUG_SIGNALSTRENGTH + bool HasBer = true; +#endif + uint32_t Ber; + while (1) { + if (ioctl(fd_frontend, FE_READ_BER, &Ber) != -1) + break; + if (errno != EINTR) { + Ber = 0; +#ifdef DEBUG_SIGNALSTRENGTH + HasBer = false; +#endif + break; + } + } +#ifdef DEBUG_SIGNALSTRENGTH + bool HasUnc = true; +#endif + uint32_t Unc; + while (1) { + if (ioctl(fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &Unc) != -1) + break; + if (errno != EINTR) { + Unc = 0; +#ifdef DEBUG_SIGNALSTRENGTH + HasUnc = false; +#endif + break; + } + } + uint16_t MinSignal = 0x0000; + uint16_t MaxSignal = 0xFFFF; // Let's assume the default is using the entire range. + // Use the subsystemId to identify individual devices in case they need + // special treatment to map their Snr value into the range 0...0xFFFF. + switch (subsystemId) { + case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2) + case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2) + if (frontendType == SYS_DVBS2) { + MinSignal = 10; + MaxSignal = 70; + } + else +// MaxSignal = 200; + MaxSignal = 670; + + break; + case 0x20130245: // PCTV Systems PCTV 73ESE + case 0x2013024F: // PCTV Systems nanoStick T2 290e +// MaxSignal = 255; break; + MaxSignal = 670; + + } + int a = int(constrain(Signal, MinSignal, MaxSignal)) * 350 / (MaxSignal - MinSignal); + int b = 100 - (Unc * 10 + (Ber / 256) * 5); + if (b < 0) + b = 0; + int s = LOCK_THRESHOLD + a * b * (100 - LOCK_THRESHOLD) / 100 / 100; + if (s > 100) + s = 100; + #ifdef DEBUG_SIGNALSTRENGTH + fprintf(stderr, "FE %d/%d: %08X S = %04X %04X %d %5d %5d %3d%%\n", adapter, frontend, subsystemId, MaxSignal, Signal, HasSignal, HasBer ? int(Ber) : -1, HasUnc ? int(Unc) : -1, s); +#endif + return s; + } + return -1; } #define LOCK_THRESHOLD 5 // indicates that all 5 FE_HAS_* flags are set @@ -655,6 +744,35 @@ return -1; } +int cDvbTuner::GetCurrentDeliverySystem() +{ + dtv_property Frontend[1]; + memset(&Frontend, 0, sizeof(Frontend)); + dtv_properties CmdSeq; + memset(&CmdSeq, 0, sizeof(CmdSeq)); + CmdSeq.props = Frontend; + Frontend[0].cmd = DTV_DELIVERY_SYSTEM; + Frontend[0].u.data = 0; + if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) < 0) { + esyslog("ERROR: frontend %d/%d: %m", adapter, frontend); + return SYS_UNDEFINED; + } + return Frontend[0].u.data; +} + +bool cDvbTuner::SendDiseqcCmd(dvb_diseqc_master_cmd cmd) +{ + cMutexLock MutexLock(&mutex); + int frontendType = GetCurrentDeliverySystem(); + if ((frontendType != SYS_DVBS && frontendType != SYS_DVBS2) || SendDiseqc) + return false; + diseqc_cmd=cmd; + SendDiseqc=true; + newSet.Broadcast(); + return true; +} + + static unsigned int FrequencyToHz(unsigned int f) { while (f && f < 1000000) @@ -719,6 +837,8 @@ bool cDvbTuner::SetFrontend(void) { + if (!OpenFrontend()) + return false; #define MAXFRONTENDCMDS 16 #define SETCMD(c, d) { Frontend[CmdSeq.num].cmd = (c);\ Frontend[CmdSeq.num].u.data = (d);\ @@ -870,10 +990,16 @@ bool LostLock = false; fe_status_t Status = (fe_status_t)0; while (Running()) { - fe_status_t NewStatus; - if (GetFrontendStatus(NewStatus)) - Status = NewStatus; + if (!isIdle) { + fe_status_t NewStatus; + if (GetFrontendStatus(NewStatus)) + Status = NewStatus; + } cMutexLock MutexLock(&mutex); + if (SendDiseqc) { + CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &diseqc_cmd)); + SendDiseqc=false; + } int WaitTime = 1000; switch (tunerStatus) { case tsIdle: @@ -925,6 +1051,40 @@ } } +bool cDvbTuner::SetIdle(bool Idle) +{ + if (isIdle == Idle) + return true; + isIdle = Idle; + if (Idle) + return CloseFrontend(); + return OpenFrontend(); +} + +bool cDvbTuner::OpenFrontend(void) const +{ + if (fd_frontend >= 0) + return true; + cMutexLock MutexLock(&mutex); + fd_frontend = cDvbDevice::DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK); + if (fd_frontend < 0) + return false; + isIdle = false; + return true; +} + +bool cDvbTuner::CloseFrontend(void) +{ + if (fd_frontend < 0) + return true; + cMutexLock MutexLock(&mutex); + tunerStatus = tsIdle; + newSet.Broadcast(); + close(fd_frontend); + fd_frontend = -1; + return true; +} + // --- cDvbSourceParam ------------------------------------------------------- class cDvbSourceParam : public cSourceParam { @@ -1010,7 +1170,8 @@ NULL }; -cDvbDevice::cDvbDevice(int Adapter, int Frontend) +cDvbDevice::cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice) +:cDevice(ParentDevice) { adapter = Adapter; frontend = Frontend; @@ -1028,9 +1189,8 @@ // Common Interface: - fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR); - if (fd_ca >= 0) - ciAdapter = cDvbCiAdapter::CreateCiAdapter(this, fd_ca); + int fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR); + ciAdapter = cDvbCiAdapter::CreateCiAdapter(parentDevice ? parentDevice : this, fd_ca, adapter, frontend); // The DVR device (will be opened and closed as needed): @@ -1274,7 +1434,11 @@ if (d >= 0) { int ErrorDevice = 0; if (cDevice *Device1 = cDevice::GetDevice(i)) { + if (Device1->HasSubDevice()) + Device1 = Device1->SubDevice(); if (cDevice *Device2 = cDevice::GetDevice(d)) { + if (Device2->HasSubDevice()) + Device2 = Device2->SubDevice(); if (cDvbDevice *DvbDevice1 = dynamic_cast(Device1)) { if (cDvbDevice *DvbDevice2 = dynamic_cast(Device2)) { if (!DvbDevice1->Bond(DvbDevice2)) @@ -1308,7 +1472,10 @@ void cDvbDevice::UnBondDevices(void) { for (int i = 0; i < cDevice::NumDevices(); i++) { - if (cDvbDevice *d = dynamic_cast(cDevice::GetDevice(i))) + cDevice *dev = cDevice::GetDevice(i); + if (dev && dev->HasSubDevice()) + dev = dev->SubDevice(); + if (cDvbDevice *d = dynamic_cast(dev)) d->UnBond(); } } @@ -1362,6 +1529,26 @@ return true; } +bool cDvbDevice::SetIdleDevice(bool Idle, bool TestOnly) +{ + if (TestOnly) { + if (ciAdapter) + return ciAdapter->SetIdle(Idle, true); + return true; + } + if (!dvbTuner->SetIdle(Idle)) + return false; + if (ciAdapter && !ciAdapter->SetIdle(Idle, false)) { + dvbTuner->SetIdle(!Idle); + return false; + } + if (Idle) + StopSectionHandler(); + else + StartSectionHandler(); + return true; +} + bool cDvbDevice::HasCi(void) { return ciAdapter; @@ -1447,6 +1634,10 @@ bool cDvbDevice::ProvidesSource(int Source) const { + if (Setup.ChannelBlocker == 1) { + if (IsPrimaryDevice()) return false; + //isyslog("ChannelBlocker aktive on primary Interface"); + } int type = Source & cSource::st_Mask; return type == cSource::stNone || type == cSource::stAtsc && ProvidesDeliverySystem(SYS_ATSC) @@ -1531,7 +1722,7 @@ bool cDvbDevice::ProvidesEIT(void) const { - return dvbTuner != NULL; + return !IsIdle() && (dvbTuner != NULL) && !dvbTuner->IsIdle() && ((ciAdapter == NULL) || !ciAdapter->IsIdle()); } int cDvbDevice::NumProvidedSystems(void) const @@ -1576,6 +1767,11 @@ return dvbTuner ? dvbTuner->Locked(TimeoutMs) : false; } +bool cDvbDevice::SendDiseqcCmd(dvb_diseqc_master_cmd cmd) +{ + return dvbTuner->SendDiseqcCmd(cmd); +} + void cDvbDevice::SetTransferModeForDolbyDigital(int Mode) { setTransferModeForDolbyDigital = Mode; @@ -1585,8 +1781,12 @@ { CloseDvr(); fd_dvr = DvbOpen(DEV_DVB_DVR, adapter, frontend, O_RDONLY | O_NONBLOCK, true); - if (fd_dvr >= 0) - tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(5), CardIndex() + 1); + if (fd_dvr >= 0) { + if (ciAdapter) + tsBuffer = ciAdapter->GetTSBuffer(fd_dvr); + if (tsBuffer == NULL) + tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(5), CardIndex() + 1); + } return fd_dvr >= 0; }