Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 656cce97750882fd945d9ba76c47cb93a74c3059 Mon Sep 17 00:00:00 2001
- From: glenvt18 <glenvt18@gmail.com>
- Date: Tue, 24 May 2016 00:39:01 +0300
- Subject: [PATCH] Device power saving feature
- ---
- config.c | 9 ++++++
- config.h | 3 ++
- device.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
- device.h | 29 +++++++++++++++++++
- dvbdevice.c | 39 +++++++++++++++++++++++++
- dvbdevice.h | 7 +++++
- eitscan.c | 7 ++++-
- menu.c | 9 +++++-
- vdr.c | 6 ++++
- 9 files changed, 201 insertions(+), 4 deletions(-)
- diff --git a/config.c b/config.c
- index 9c6b71e..e196353 100644
- --- a/config.c
- +++ b/config.c
- @@ -395,6 +395,9 @@ cSetup::cSetup(void)
- PositionerSpeed = 15;
- PositionerSwing = 650;
- PositionerLastLon = 0;
- + PowerdownEnabled = 0;
- + PowerdownTimeoutM = 15;
- + PowerdownWakeupH = 4;
- SetSystemTime = 0;
- TimeSource = 0;
- TimeTransponder = 0;
- @@ -617,6 +620,9 @@ bool cSetup::Parse(const char *Name, const char *Value)
- 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);
- @@ -743,6 +749,9 @@ bool cSetup::Save(void)
- 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);
- diff --git a/config.h b/config.h
- index d1bae04..dbe84bb 100644
- --- a/config.h
- +++ b/config.h
- @@ -273,6 +273,9 @@ public:
- int PositionerSpeed;
- int PositionerSwing;
- int PositionerLastLon;
- + int PowerdownEnabled;
- + int PowerdownTimeoutM;
- + int PowerdownWakeupH;
- int SetSystemTime;
- int TimeSource;
- int TimeTransponder;
- diff --git a/device.c b/device.c
- index 4db7cc2..1c29677 100644
- --- a/device.c
- +++ b/device.c
- @@ -104,6 +104,9 @@ cDevice::cDevice(void)
- dvbSubtitleConverter = NULL;
- autoSelectPreferredSubtitleLanguage = true;
- + idleTimerExpires = time(NULL) + Setup.PowerdownTimeoutM * 60;
- + wakeupTimerExpires = 0;
- +
- for (int i = 0; i < MAXRECEIVERS; i++)
- receiver[i] = NULL;
- @@ -744,6 +747,11 @@ bool cDevice::SwitchChannel(int Direction)
- 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);
- @@ -778,6 +786,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
- }
- else {
- Channels.Lock(false);
- + // Power up the device
- + PowerUp(CHANNEL_SWITCH_POWERUP_TIMEOUT);
- // Stop section handling:
- if (sectionHandler) {
- sectionHandler->SetStatus(false);
- @@ -843,8 +853,11 @@ int cDevice::Occupied(void) const
- 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)
- @@ -1675,6 +1688,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
- startScrambleDetection = time(NULL);
- }
- Start();
- + SetIdleTimer(false);
- return true;
- }
- }
- @@ -1708,8 +1722,10 @@ void cDevice::Detach(cReceiver *Receiver)
- camSlot->Assign(NULL);
- }
- }
- - if (!receiversLeft)
- + if (!receiversLeft) {
- Cancel(-1);
- + SetIdleTimer(true);
- + }
- }
- void cDevice::DetachAll(int Pid)
- @@ -1731,6 +1747,82 @@ void cDevice::DetachAllReceivers(void)
- 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)
- diff --git a/device.h b/device.h
- index b06d977..56c4878 100644
- --- a/device.h
- +++ b/device.h
- @@ -821,6 +821,35 @@ public:
- ///< 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
- diff --git a/dvbdevice.c b/dvbdevice.c
- index 9321f16..2a0dad1 100644
- --- a/dvbdevice.c
- +++ b/dvbdevice.c
- @@ -348,6 +348,8 @@ public:
- 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 @@ void cDvbTuner::ClearEventQueue(void) const
- 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 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
- int cDvbTuner::GetSignalStrength(void) const
- {
- + if (fd_frontend < 0)
- + return -1;
- ClearEventQueue();
- uint16_t Signal;
- while (1) {
- @@ -1001,6 +1007,26 @@ void cDvbTuner::Action(void)
- }
- }
- +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 @@ void cDvbDevice::DetachAllReceivers(void)
- 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;
- diff --git a/dvbdevice.h b/dvbdevice.h
- index 0a148ce..a156de6 100644
- --- a/dvbdevice.h
- +++ b/dvbdevice.h
- @@ -289,6 +289,13 @@ protected:
- 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
- diff --git a/eitscan.c b/eitscan.c
- index 77f15c6..3899e00 100644
- --- a/eitscan.c
- +++ b/eitscan.c
- @@ -142,7 +142,8 @@ void cEITScanner::Process(void)
- 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 @@ void cEITScanner::Process(void)
- }
- }
- //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;
- diff --git a/menu.c b/menu.c
- index ae61c64..c469ab0 100644
- --- a/menu.c
- +++ b/menu.c
- @@ -3464,6 +3464,12 @@ void cMenuSetupLNB::Setup(void)
- 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();
- }
- @@ -3472,6 +3478,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
- {
- int oldDiSEqC = data.DiSEqC;
- int oldUsePositioner = data.UsePositioner;
- + int oldPowerdownEnabled = data.PowerdownEnabled;
- bool DeviceBondingsChanged = false;
- if (Key == kOk) {
- cString NewDeviceBondings = satCableNumbers.ToString();
- @@ -3480,7 +3487,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
- }
- 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);
- diff --git a/vdr.c b/vdr.c
- index 71a72f2..c12ad2c 100644
- --- a/vdr.c
- +++ b/vdr.c
- @@ -1444,6 +1444,12 @@ int main(int argc, char *argv[])
- 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();
- }
- --
- 1.9.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement