[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