[vdr] 02/02: Added power saving patch by Sergey Chernyavskiy

Tobias Grimm tiber-guest at moszumanska.debian.org
Sat Jan 7 11:32:26 UTC 2017


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to annotated tag debian/2.2.0-6_etobi1
in repository vdr.

commit d8aa273e832a2cb91f968d8e88947ca29fa27080
Author: Tobias Grimm <etobi at debian.org>
Date:   Mon Jun 6 19:33:14 2016 +0200

    Added power saving patch by Sergey Chernyavskiy
---
 debian/patches/opt-60_power-saving.patch | 396 +++++++++++++++++++++++++++++++
 debian/patches/series                    |   3 +
 2 files changed, 399 insertions(+)

diff --git a/debian/patches/opt-60_power-saving.patch b/debian/patches/opt-60_power-saving.patch
new file mode 100644
index 0000000..cbde3a6
--- /dev/null
+++ b/debian/patches/opt-60_power-saving.patch
@@ -0,0 +1,396 @@
+Description: Power down DVB decices which are idle
+Author: Sergey Chernyavskiy <glenvt18 at gmail.com>
+
+--- a/config.c
++++ b/config.c
+@@ -395,6 +395,9 @@
+   PositionerSpeed = 15;
+   PositionerSwing = 650;
+   PositionerLastLon = 0;
++  PowerdownEnabled = 0;
++  PowerdownTimeoutM = 15;
++  PowerdownWakeupH = 4;
+   SetSystemTime = 0;
+   TimeSource = 0;
+   TimeTransponder = 0;
+@@ -618,6 +621,9 @@
+   else if (!strcasecmp(Name, "PositionerSpeed"))     PositionerSpeed    = atoi(Value);
+   else if (!strcasecmp(Name, "PositionerSwing"))     PositionerSwing    = atoi(Value);
+   else if (!strcasecmp(Name, "PositionerLastLon"))   PositionerLastLon  = atoi(Value);
++  else if (!strcasecmp(Name, "PowerdownEnabled"))    PowerdownEnabled   = atoi(Value);
++  else if (!strcasecmp(Name, "PowerdownTimeoutM"))   PowerdownTimeoutM  = atoi(Value);
++  else if (!strcasecmp(Name, "PowerdownWakeupH"))    PowerdownWakeupH   = atoi(Value);
+   else if (!strcasecmp(Name, "SetSystemTime"))       SetSystemTime      = atoi(Value);
+   else if (!strcasecmp(Name, "TimeSource"))          TimeSource         = cSource::FromString(Value);
+   else if (!strcasecmp(Name, "TimeTransponder"))     TimeTransponder    = atoi(Value);
+@@ -745,6 +751,9 @@
+   Store("PositionerSpeed",    PositionerSpeed);
+   Store("PositionerSwing",    PositionerSwing);
+   Store("PositionerLastLon",  PositionerLastLon);
++  Store("PowerdownEnabled",   PowerdownEnabled);
++  Store("PowerdownTimeoutM",  PowerdownTimeoutM);
++  Store("PowerdownWakeupH",   PowerdownWakeupH);
+   Store("SetSystemTime",      SetSystemTime);
+   Store("TimeSource",         cSource::ToString(TimeSource));
+   Store("TimeTransponder",    TimeTransponder);
+--- a/config.h
++++ b/config.h
+@@ -275,6 +275,9 @@
+   int PositionerSpeed;
+   int PositionerSwing;
+   int PositionerLastLon;
++  int PowerdownEnabled;
++  int PowerdownTimeoutM;
++  int PowerdownWakeupH;
+   int SetSystemTime;
+   int TimeSource;
+   int TimeTransponder;
+--- a/device.c
++++ b/device.c
+@@ -105,6 +105,9 @@
+   dvbSubtitleConverter = NULL;
+   autoSelectPreferredSubtitleLanguage = true;
+ 
++  idleTimerExpires = time(NULL) + Setup.PowerdownTimeoutM * 60;
++  wakeupTimerExpires = 0;
++
+   for (int i = 0; i < MAXRECEIVERS; i++)
+       receiver[i] = NULL;
+ 
+@@ -745,6 +748,11 @@
+   return result;
+ }
+ 
++// While switching to a channel, the device will be kept powered up
++// for at least this number of seconds before a receiver is attached.
++// Must be less than cEITScanner::ScanTimeout.
++#define CHANNEL_SWITCH_POWERUP_TIMEOUT  10
++
+ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
+ {
+   cStatus::MsgChannelSwitch(this, 0, LiveView);
+@@ -779,6 +787,8 @@
+      }
+   else {
+      Channels.Lock(false);
++     // Power up the device
++     PowerUp(CHANNEL_SWITCH_POWERUP_TIMEOUT);
+      // Stop section handling:
+      if (sectionHandler) {
+         sectionHandler->SetStatus(false);
+@@ -844,8 +854,11 @@
+ 
+ void cDevice::SetOccupied(int Seconds)
+ {
+-  if (Seconds >= 0)
++  if (Seconds >= 0) {
+      occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
++     // avoid short power-down/power-up cycles
++     SetIdleTimer(true, Seconds + 30);
++     }
+ }
+ 
+ bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
+@@ -1695,6 +1708,7 @@
+             startScrambleDetection = time(NULL);
+             }
+          Start();
++         SetIdleTimer(false);
+          return true;
+          }
+       }
+@@ -1728,8 +1742,10 @@
+            camSlot->Assign(NULL);
+         }
+      }
+-  if (!receiversLeft)
++  if (!receiversLeft) {
+      Cancel(-1);
++     SetIdleTimer(true);
++     }
+ }
+ 
+ void cDevice::DetachAll(int Pid)
+@@ -1751,6 +1767,82 @@
+       Detach(receiver[i]);
+ }
+ 
++void cDevice::CheckIdle(void)
++{
++  if (!SupportsPowerDown() || !Setup.PowerdownEnabled)
++     return;
++  cMutexLock MutexLock(&mutexPowerSaving);
++  if (idleTimerExpires != 0 && time(NULL) > idleTimerExpires) {
++     // idle, powered up
++     dsyslog("power saving: device %d idle timer expired", CardIndex() + 1);
++     SetIdleTimer(false);
++     if (Setup.PowerdownWakeupH != 0)
++        wakeupTimerExpires = time(NULL) + Setup.PowerdownWakeupH * 3600;
++     else
++        dsyslog("power saving: waking up is disabled");
++     if (!IsPoweredDown()) {
++        dsyslog("power saving: powering device %d down", CardIndex() + 1);
++        if (sectionHandler) {
++           sectionHandler->SetStatus(false);
++           sectionHandler->SetChannel(NULL);
++           }
++        PowerDown(true);
++        }
++     }
++  if (wakeupTimerExpires != 0 && time(NULL) > wakeupTimerExpires) {
++     // idle, powered down
++     dsyslog("power saving: device %d wakeup timer expired", CardIndex() + 1);
++     SetIdleTimer(true);
++     if (IsPoweredDown()) {
++        dsyslog("power saving: waking up device %d", CardIndex() + 1);
++        PowerDown(false);
++        }
++     }
++}
++
++void cDevice::SetIdleTimer(bool On, int ExtraTimeoutS)
++{
++  if (!SupportsPowerDown())
++     return;
++  cMutexLock MutexLock(&mutexPowerSaving);
++  if (On) {
++     int Tout = Setup.PowerdownTimeoutM * 60;
++     time_t Now = time(NULL);
++     if (ExtraTimeoutS > 0) {
++        if (idleTimerExpires >= Now + ExtraTimeoutS)
++           return;
++        Tout = ExtraTimeoutS;
++        }
++     idleTimerExpires = Now + Tout;
++     if (Setup.PowerdownEnabled)
++        dsyslog("power saving: set device %d idle timer to %d sec", CardIndex() + 1, Tout);
++     }
++  else {
++     idleTimerExpires = 0;
++     if (Setup.PowerdownEnabled)
++        dsyslog("power saving: disable device %d idle timer", CardIndex() + 1);
++     }
++  wakeupTimerExpires = 0;
++}
++
++bool cDevice::PoweredDown(void)
++{
++  if (SupportsPowerDown() && Setup.PowerdownEnabled) {
++     cMutexLock MutexLock(&mutexPowerSaving);
++     return IsPoweredDown();
++     }
++  else
++     return false;
++}
++
++void cDevice::PowerUp(int ExtraTimeoutS)
++{
++  cMutexLock MutexLock(&mutexPowerSaving);
++  SetIdleTimer(true, ExtraTimeoutS);
++  if (SupportsPowerDown() && IsPoweredDown())
++     PowerDown(false);
++}
++
+ // --- cTSBuffer -------------------------------------------------------------
+ 
+ cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
+--- a/device.h
++++ b/device.h
+@@ -822,6 +822,35 @@
+        ///< Detaches all receivers from this device for this pid.
+   virtual void DetachAllReceivers(void);
+        ///< Detaches all receivers from this device.
++
++// Power saving facilities
++
++private:
++  cMutex mutexPowerSaving;
++  time_t idleTimerExpires, wakeupTimerExpires;
++  void PowerUp(int ExtraTimeoutS);
++       ///< If the device is powered down, powers it up and keeps it
++       ///< powered up for at least ExtraTimeoutS seconds (see
++       ///< cDevice::SetIdleTimer()).
++public:
++  void CheckIdle(void);
++       ///< Should be called periodically in the main loop.
++  bool PoweredDown(void);
++       ///< Returns true if the device is powered down "logically", that is,
++       ///< idle tasks like EPG scanning are disabled.
++  void SetIdleTimer(bool On, int ExtraTimeoutS = 0);
++       ///< Starts/disables the idle timer. This timer must be started when
++       ///< a device gets idle and must be disabled when it is receiving.
++       ///< If ExtraTimeoutS is greater than zero and On is true, a new timer
++       ///< won't be set, but the device will be kept powered up for at least
++       ///< ExtraTimeoutS seconds.
++protected:
++  virtual bool IsPoweredDown(void) {return false;}
++       ///< Returns true if the device is powered down "physically".
++  virtual void PowerDown(bool On) {};
++       ///< Actually powers the device down/up.
++  virtual bool SupportsPowerDown() {return false;}
++       ///< Returns true if a derived device supports power saving.
+   };
+ 
+ /// Derived cDevice classes that can receive channels will have to provide
+--- a/dvbdevice.c
++++ b/dvbdevice.c
+@@ -348,6 +348,8 @@
+   const cPositioner *Positioner(void) const { return positioner; }
+   int GetSignalStrength(void) const;
+   int GetSignalQuality(void) const;
++  bool IsPoweredDown(void) {return fd_frontend < 0;}
++  void PowerDown(bool On);
+   };
+ 
+ cMutex cDvbTuner::bondMutex;
+@@ -544,6 +546,8 @@
+ 
+ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
+ {
++  if (fd_frontend < 0)
++     return false;
+   ClearEventQueue();
+   while (1) {
+         if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1)
+@@ -559,6 +563,8 @@
+ 
+ int cDvbTuner::GetSignalStrength(void) const
+ {
++  if (fd_frontend < 0)
++     return -1;
+   ClearEventQueue();
+   uint16_t Signal;
+   while (1) {
+@@ -1001,6 +1007,26 @@
+         }
+ }
+ 
++void cDvbTuner::PowerDown(bool On)
++{
++  cMutexLock MutexLock(&mutex);
++  if (On && fd_frontend >= 0) {
++     isyslog("dvb tuner: power-down - closing frontend %d/%d", adapter, frontend);
++     tunerStatus = tsIdle;
++     close(fd_frontend);
++     fd_frontend = -1;
++     }
++  if (!On && fd_frontend < 0) {
++     cString Filename = cString::sprintf("%s/%s%d/%s%d",
++        DEV_DVB_BASE, DEV_DVB_ADAPTER, adapter, DEV_DVB_FRONTEND, frontend);
++     isyslog("dvb tuner: power-up - opening frontend %d/%d", adapter, frontend);
++     fd_frontend = open(Filename, O_RDWR | O_NONBLOCK);
++     if (fd_frontend < 0)
++        esyslog("ERROR: can't open DVB device frontend %d/%d", adapter, frontend);
++     tunerStatus = tsIdle;
++     }
++}
++
+ // --- cDvbSourceParam -------------------------------------------------------
+ 
+ class cDvbSourceParam : public cSourceParam {
+@@ -1711,6 +1737,19 @@
+   needsDetachBondedReceivers = false;
+ }
+ 
++bool cDvbDevice::IsPoweredDown(void)
++{
++  if (dvbTuner)
++     return dvbTuner->IsPoweredDown();
++  return false;
++}
++
++void cDvbDevice::PowerDown(bool On)
++{
++  if (dvbTuner)
++     dvbTuner->PowerDown(On);
++}
++
+ // --- cDvbDeviceProbe -------------------------------------------------------
+ 
+ cList<cDvbDeviceProbe> DvbDeviceProbes;
+--- a/dvbdevice.h
++++ b/dvbdevice.h
+@@ -289,6 +289,13 @@
+   virtual void CloseDvr(void);
+   virtual bool GetTSPacket(uchar *&Data);
+   virtual void DetachAllReceivers(void);
++
++// Power saving facilities
++
++protected:
++  virtual bool IsPoweredDown(void);
++  virtual void PowerDown(bool On);
++  virtual bool SupportsPowerDown() {return true;}
+   };
+ 
+ // A plugin that implements a DVB device derived from cDvbDevice needs to create
+--- a/eitscan.c
++++ b/eitscan.c
+@@ -142,7 +142,8 @@
+            bool AnyDeviceSwitched = false;
+            for (int i = 0; i < cDevice::NumDevices(); i++) {
+                cDevice *Device = cDevice::GetDevice(i);
+-               if (Device && Device->ProvidesEIT()) {
++               if (Device && Device->ProvidesEIT()
++                     && (!Device->PoweredDown() || lastActivity == 0)) { // powered up or forced scan
+                   for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) {
+                       const cChannel *Channel = ScanData->GetChannel();
+                       if (Channel) {
+@@ -159,6 +160,10 @@
+                                            }
+                                         }
+                                      //dsyslog("EIT scan: device %d  source  %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
++                                     if (lastActivity == 0)
++                                        // forced scan - set idle timer for each channel switch;
++                                        // this prevents powering down while scanning a transponder
++                                        Device->SetIdleTimer(true, ScanTimeout + 5);
+                                      Device->SwitchChannel(Channel, false);
+                                      scanList->Del(ScanData);
+                                      AnyDeviceSwitched = true;
+--- a/menu.c
++++ b/menu.c
+@@ -3631,6 +3631,12 @@
+      Add(new cMenuEditIntxItem(tr("Setup.LNB$Positioner speed (degrees/s)"), &data.PositionerSpeed, 1, 1800, 10));
+      }
+ 
++  Add(new cMenuEditBoolItem(tr("Setup.LNB$Enable power saving"), &data.PowerdownEnabled));
++  if (data.PowerdownEnabled) {
++     Add(new cMenuEditIntItem(tr("Setup.LNB$Power down an idle device after (min)"), &data.PowerdownTimeoutM));
++     Add(new cMenuEditIntItem(tr("Setup.LNB$Wake up from power-down after (h)"), &data.PowerdownWakeupH));
++     }
++
+   SetCurrent(Get(current));
+   Display();
+ }
+@@ -3639,6 +3645,7 @@
+ {
+   int oldDiSEqC = data.DiSEqC;
+   int oldUsePositioner = data.UsePositioner;
++  int oldPowerdownEnabled = data.PowerdownEnabled;
+   bool DeviceBondingsChanged = false;
+   if (Key == kOk) {
+      cString NewDeviceBondings = satCableNumbers.ToString();
+@@ -3647,7 +3654,7 @@
+      }
+   eOSState state = cMenuSetupBase::ProcessKey(Key);
+ 
+-  if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner))
++  if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner || data.PowerdownEnabled != oldPowerdownEnabled))
+      Setup();
+   else if (DeviceBondingsChanged)
+      cDvbDevice::BondDevices(data.DeviceBondings);
+--- a/vdr.c
++++ b/vdr.c
+@@ -1444,6 +1444,12 @@
+ 
+         ReportEpgBugFixStats();
+ 
++        for (int i = 0; i < cDevice::NumDevices(); i++) {
++           cDevice *d = cDevice::GetDevice(i);
++           if (d)
++              d->CheckIdle();
++           }
++
+         // Main thread hooks of plugins:
+         PluginManager.MainThreadHook();
+         }
diff --git a/debian/patches/series b/debian/patches/series
index ee12f60..864896a 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -28,3 +28,6 @@ opt-45_yaepg.patch
 
 # Patch required for the GraphTFT plugin
 opt-50_graphtft.patch
+
+# Power down idle dvb devices
+opt-60_power-saving.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr.git



More information about the pkg-vdr-dvb-changes mailing list