Advertisement
Guest User

Untitled

a guest
May 26th, 2016
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 15.31 KB | None | 0 0
  1. From bba59fb0843ec58705c996462a5bea802a5ffecf Mon Sep 17 00:00:00 2001
  2. From: glenvt18 <glenvt18@gmail.com>
  3. Date: Tue, 24 May 2016 00:39:01 +0300
  4. Subject: [PATCH] Device power saving feature
  5.  
  6. ---
  7. config.c    |  9 ++++++
  8.  config.h    |  3 ++
  9.  device.c    | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
  10.  device.h    | 29 +++++++++++++++++++
  11.  dvbdevice.c | 39 +++++++++++++++++++++++++
  12.  dvbdevice.h |  7 +++++
  13.  eitscan.c   |  7 ++++-
  14.  menu.c      |  9 +++++-
  15.  vdr.c       |  6 ++++
  16.  9 files changed, 201 insertions(+), 4 deletions(-)
  17.  
  18. diff --git a/config.c b/config.c
  19. index e5f5463..794c9f8 100644
  20. --- a/config.c
  21. +++ b/config.c
  22. @@ -395,6 +395,9 @@ cSetup::cSetup(void)
  23.    PositionerSpeed = 15;
  24.    PositionerSwing = 650;
  25.    PositionerLastLon = 0;
  26. +  PowerdownEnabled = 0;
  27. +  PowerdownTimeoutM = 15;
  28. +  PowerdownWakeupH = 4;
  29.    SetSystemTime = 0;
  30.    TimeSource = 0;
  31.    TimeTransponder = 0;
  32. @@ -622,6 +625,9 @@ bool cSetup::Parse(const char *Name, const char *Value)
  33.    else if (!strcasecmp(Name, "PositionerSpeed"))     PositionerSpeed    = atoi(Value);
  34.    else if (!strcasecmp(Name, "PositionerSwing"))     PositionerSwing    = atoi(Value);
  35.    else if (!strcasecmp(Name, "PositionerLastLon"))   PositionerLastLon  = atoi(Value);
  36. +  else if (!strcasecmp(Name, "PowerdownEnabled"))    PowerdownEnabled   = atoi(Value);
  37. +  else if (!strcasecmp(Name, "PowerdownTimeoutM"))   PowerdownTimeoutM  = atoi(Value);
  38. +  else if (!strcasecmp(Name, "PowerdownWakeupH"))    PowerdownWakeupH   = atoi(Value);
  39.    else if (!strcasecmp(Name, "SetSystemTime"))       SetSystemTime      = atoi(Value);
  40.    else if (!strcasecmp(Name, "TimeSource"))          TimeSource         = cSource::FromString(Value);
  41.    else if (!strcasecmp(Name, "TimeTransponder"))     TimeTransponder    = atoi(Value);
  42. @@ -753,6 +759,9 @@ bool cSetup::Save(void)
  43.    Store("PositionerSpeed",    PositionerSpeed);
  44.    Store("PositionerSwing",    PositionerSwing);
  45.    Store("PositionerLastLon",  PositionerLastLon);
  46. +  Store("PowerdownEnabled",   PowerdownEnabled);
  47. +  Store("PowerdownTimeoutM",  PowerdownTimeoutM);
  48. +  Store("PowerdownWakeupH",   PowerdownWakeupH);
  49.    Store("SetSystemTime",      SetSystemTime);
  50.    Store("TimeSource",         cSource::ToString(TimeSource));
  51.    Store("TimeTransponder",    TimeTransponder);
  52. diff --git a/config.h b/config.h
  53. index e5565da..7a73d9d 100644
  54. --- a/config.h
  55. +++ b/config.h
  56. @@ -273,6 +273,9 @@ public:
  57.    int PositionerSpeed;
  58.    int PositionerSwing;
  59.    int PositionerLastLon;
  60. +  int PowerdownEnabled;
  61. +  int PowerdownTimeoutM;
  62. +  int PowerdownWakeupH;
  63.    int SetSystemTime;
  64.    int TimeSource;
  65.    int TimeTransponder;
  66. diff --git a/device.c b/device.c
  67. index 542d120..9306adb 100644
  68. --- a/device.c
  69. +++ b/device.c
  70. @@ -104,6 +104,9 @@ cDevice::cDevice(void)
  71.    dvbSubtitleConverter = NULL;
  72.    autoSelectPreferredSubtitleLanguage = true;
  73.  
  74. +  idleTimerExpires = time(NULL) + Setup.PowerdownTimeoutM * 60;
  75. +  wakeupTimerExpires = 0;
  76. +
  77.    for (int i = 0; i < MAXRECEIVERS; i++)
  78.        receiver[i] = NULL;
  79.  
  80. @@ -745,6 +748,11 @@ bool cDevice::SwitchChannel(int Direction)
  81.    return result;
  82.  }
  83.  
  84. +// While switching to a channel, the device will be kept powered up
  85. +// for at least this number of seconds before a receiver is attached.
  86. +// Must be less than cEITScanner::ScanTimeout.
  87. +#define CHANNEL_SWITCH_POWERUP_TIMEOUT  10
  88. +
  89.  eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
  90.  {
  91.    cStatus::MsgChannelSwitch(this, 0, LiveView);
  92. @@ -778,6 +786,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
  93.          Result = scrNotAvailable;
  94.       }
  95.    else {
  96. +     // Power up the device
  97. +     PowerUp(CHANNEL_SWITCH_POWERUP_TIMEOUT);
  98.       // Stop section handling:
  99.       if (sectionHandler) {
  100.          sectionHandler->SetStatus(false);
  101. @@ -843,8 +853,11 @@ int cDevice::Occupied(void) const
  102.  
  103.  void cDevice::SetOccupied(int Seconds)
  104.  {
  105. -  if (Seconds >= 0)
  106. +  if (Seconds >= 0) {
  107.       occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
  108. +     // avoid short power-down/power-up cycles
  109. +     SetIdleTimer(true, Seconds + 30);
  110. +     }
  111.  }
  112.  
  113.  bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
  114. @@ -1675,6 +1688,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
  115.              startScrambleDetection = time(NULL);
  116.              }
  117.           Start();
  118. +         SetIdleTimer(false);
  119.           return true;
  120.           }
  121.        }
  122. @@ -1708,8 +1722,10 @@ void cDevice::Detach(cReceiver *Receiver)
  123.             camSlot->Assign(NULL);
  124.          }
  125.       }
  126. -  if (!receiversLeft)
  127. +  if (!receiversLeft) {
  128.       Cancel(-1);
  129. +     SetIdleTimer(true);
  130. +     }
  131.  }
  132.  
  133.  void cDevice::DetachAll(int Pid)
  134. @@ -1731,6 +1747,82 @@ void cDevice::DetachAllReceivers(void)
  135.        Detach(receiver[i]);
  136.  }
  137.  
  138. +void cDevice::CheckIdle(void)
  139. +{
  140. +  if (!SupportsPowerDown() || !Setup.PowerdownEnabled)
  141. +     return;
  142. +  cMutexLock MutexLock(&mutexPowerSaving);
  143. +  if (idleTimerExpires != 0 && time(NULL) > idleTimerExpires) {
  144. +     // idle, powered up
  145. +     dsyslog("power saving: device %d idle timer expired", CardIndex() + 1);
  146. +     SetIdleTimer(false);
  147. +     if (Setup.PowerdownWakeupH != 0)
  148. +        wakeupTimerExpires = time(NULL) + Setup.PowerdownWakeupH * 3600;
  149. +     else
  150. +        dsyslog("power saving: waking up is disabled");
  151. +     if (!IsPoweredDown()) {
  152. +        dsyslog("power saving: powering device %d down", CardIndex() + 1);
  153. +        if (sectionHandler) {
  154. +           sectionHandler->SetStatus(false);
  155. +           sectionHandler->SetChannel(NULL);
  156. +           }
  157. +        PowerDown(true);
  158. +        }
  159. +     }
  160. +  if (wakeupTimerExpires != 0 && time(NULL) > wakeupTimerExpires) {
  161. +     // idle, powered down
  162. +     dsyslog("power saving: device %d wakeup timer expired", CardIndex() + 1);
  163. +     SetIdleTimer(true);
  164. +     if (IsPoweredDown()) {
  165. +        dsyslog("power saving: waking up device %d", CardIndex() + 1);
  166. +        PowerDown(false);
  167. +        }
  168. +     }
  169. +}
  170. +
  171. +void cDevice::SetIdleTimer(bool On, int ExtraTimeoutS)
  172. +{
  173. +  if (!SupportsPowerDown())
  174. +     return;
  175. +  cMutexLock MutexLock(&mutexPowerSaving);
  176. +  if (On) {
  177. +     int Tout = Setup.PowerdownTimeoutM * 60;
  178. +     time_t Now = time(NULL);
  179. +     if (ExtraTimeoutS > 0) {
  180. +        if (idleTimerExpires >= Now + ExtraTimeoutS)
  181. +           return;
  182. +        Tout = ExtraTimeoutS;
  183. +        }
  184. +     idleTimerExpires = Now + Tout;
  185. +     if (Setup.PowerdownEnabled)
  186. +        dsyslog("power saving: set device %d idle timer to %d sec", CardIndex() + 1, Tout);
  187. +     }
  188. +  else {
  189. +     idleTimerExpires = 0;
  190. +     if (Setup.PowerdownEnabled)
  191. +        dsyslog("power saving: disable device %d idle timer", CardIndex() + 1);
  192. +     }
  193. +  wakeupTimerExpires = 0;
  194. +}
  195. +
  196. +bool cDevice::PoweredDown(void)
  197. +{
  198. +  if (SupportsPowerDown() && Setup.PowerdownEnabled) {
  199. +     cMutexLock MutexLock(&mutexPowerSaving);
  200. +     return IsPoweredDown();
  201. +     }
  202. +  else
  203. +     return false;
  204. +}
  205. +
  206. +void cDevice::PowerUp(int ExtraTimeoutS)
  207. +{
  208. +  cMutexLock MutexLock(&mutexPowerSaving);
  209. +  SetIdleTimer(true, ExtraTimeoutS);
  210. +  if (SupportsPowerDown() && IsPoweredDown())
  211. +     PowerDown(false);
  212. +}
  213. +
  214.  // --- cTSBuffer -------------------------------------------------------------
  215.  
  216.  cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
  217. diff --git a/device.h b/device.h
  218. index 31ee303..6c1fdfb 100644
  219. --- a/device.h
  220. +++ b/device.h
  221. @@ -821,6 +821,35 @@ public:
  222.         ///< Detaches all receivers from this device for this pid.
  223.    virtual void DetachAllReceivers(void);
  224.         ///< Detaches all receivers from this device.
  225. +
  226. +// Power saving facilities
  227. +
  228. +private:
  229. +  cMutex mutexPowerSaving;
  230. +  time_t idleTimerExpires, wakeupTimerExpires;
  231. +  void PowerUp(int ExtraTimeoutS);
  232. +       ///< If the device is powered down, powers it up and keeps it
  233. +       ///< powered up for at least ExtraTimeoutS seconds (see
  234. +       ///< cDevice::SetIdleTimer()).
  235. +public:
  236. +  void CheckIdle(void);
  237. +       ///< Should be called periodically in the main loop.
  238. +  bool PoweredDown(void);
  239. +       ///< Returns true if the device is powered down "logically", that is,
  240. +       ///< idle tasks like EPG scanning are disabled.
  241. +  void SetIdleTimer(bool On, int ExtraTimeoutS = 0);
  242. +       ///< Starts/disables the idle timer. This timer must be started when
  243. +       ///< a device gets idle and must be disabled when it is receiving.
  244. +       ///< If ExtraTimeoutS is greater than zero and On is true, a new timer
  245. +       ///< won't be set, but the device will be kept powered up for at least
  246. +       ///< ExtraTimeoutS seconds.
  247. +protected:
  248. +  virtual bool IsPoweredDown(void) {return false;}
  249. +       ///< Returns true if the device is powered down "physically".
  250. +  virtual void PowerDown(bool On) {};
  251. +       ///< Actually powers the device down/up.
  252. +  virtual bool SupportsPowerDown() {return false;}
  253. +       ///< Returns true if a derived device supports power saving.
  254.    };
  255.  
  256.  /// Derived cDevice classes that can receive channels will have to provide
  257. diff --git a/dvbdevice.c b/dvbdevice.c
  258. index 63af52e..cdadbff 100644
  259. --- a/dvbdevice.c
  260. +++ b/dvbdevice.c
  261. @@ -348,6 +348,8 @@ public:
  262.    const cPositioner *Positioner(void) const { return positioner; }
  263.    int GetSignalStrength(void) const;
  264.    int GetSignalQuality(void) const;
  265. +  bool IsPoweredDown(void) {return fd_frontend < 0;}
  266. +  void PowerDown(bool On);
  267.    };
  268.  
  269.  cMutex cDvbTuner::bondMutex;
  270. @@ -544,6 +546,8 @@ void cDvbTuner::ClearEventQueue(void) const
  271.  
  272.  bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
  273.  {
  274. +  if (fd_frontend < 0)
  275. +     return false;
  276.    ClearEventQueue();
  277.    while (1) {
  278.          if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1)
  279. @@ -559,6 +563,8 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
  280.  
  281.  int cDvbTuner::GetSignalStrength(void) const
  282.  {
  283. +  if (fd_frontend < 0)
  284. +     return -1;
  285.    ClearEventQueue();
  286.    uint16_t Signal;
  287.    while (1) {
  288. @@ -1001,6 +1007,26 @@ void cDvbTuner::Action(void)
  289.          }
  290.  }
  291.  
  292. +void cDvbTuner::PowerDown(bool On)
  293. +{
  294. +  cMutexLock MutexLock(&mutex);
  295. +  if (On && fd_frontend >= 0) {
  296. +     isyslog("dvb tuner: power-down - closing frontend %d/%d", adapter, frontend);
  297. +     tunerStatus = tsIdle;
  298. +     close(fd_frontend);
  299. +     fd_frontend = -1;
  300. +     }
  301. +  if (!On && fd_frontend < 0) {
  302. +     cString Filename = cString::sprintf("%s/%s%d/%s%d",
  303. +        DEV_DVB_BASE, DEV_DVB_ADAPTER, adapter, DEV_DVB_FRONTEND, frontend);
  304. +     isyslog("dvb tuner: power-up - opening frontend %d/%d", adapter, frontend);
  305. +     fd_frontend = open(Filename, O_RDWR | O_NONBLOCK);
  306. +     if (fd_frontend < 0)
  307. +        esyslog("ERROR: can't open DVB device frontend %d/%d", adapter, frontend);
  308. +     tunerStatus = tsIdle;
  309. +     }
  310. +}
  311. +
  312.  // --- cDvbSourceParam -------------------------------------------------------
  313.  
  314.  class cDvbSourceParam : public cSourceParam {
  315. @@ -1712,6 +1738,19 @@ void cDvbDevice::DetachAllReceivers(void)
  316.    needsDetachBondedReceivers = false;
  317.  }
  318.  
  319. +bool cDvbDevice::IsPoweredDown(void)
  320. +{
  321. +  if (dvbTuner)
  322. +     return dvbTuner->IsPoweredDown();
  323. +  return false;
  324. +}
  325. +
  326. +void cDvbDevice::PowerDown(bool On)
  327. +{
  328. +  if (dvbTuner)
  329. +     dvbTuner->PowerDown(On);
  330. +}
  331. +
  332.  // --- cDvbDeviceProbe -------------------------------------------------------
  333.  
  334.  cList<cDvbDeviceProbe> DvbDeviceProbes;
  335. diff --git a/dvbdevice.h b/dvbdevice.h
  336. index 5ae4952..15d1ff8 100644
  337. --- a/dvbdevice.h
  338. +++ b/dvbdevice.h
  339. @@ -290,6 +290,13 @@ protected:
  340.    virtual void CloseDvr(void);
  341.    virtual bool GetTSPacket(uchar *&Data);
  342.    virtual void DetachAllReceivers(void);
  343. +
  344. +// Power saving facilities
  345. +
  346. +protected:
  347. +  virtual bool IsPoweredDown(void);
  348. +  virtual void PowerDown(bool On);
  349. +  virtual bool SupportsPowerDown() {return true;}
  350.    };
  351.  
  352.  // A plugin that implements a DVB device derived from cDvbDevice needs to create
  353. diff --git a/eitscan.c b/eitscan.c
  354. index 41ac25e..765055c 100644
  355. --- a/eitscan.c
  356. +++ b/eitscan.c
  357. @@ -144,7 +144,8 @@ void cEITScanner::Process(void)
  358.             bool AnyDeviceSwitched = false;
  359.             for (int i = 0; i < cDevice::NumDevices(); i++) {
  360.                 cDevice *Device = cDevice::GetDevice(i);
  361. -               if (Device && Device->ProvidesEIT()) {
  362. +               if (Device && Device->ProvidesEIT()
  363. +                     && (!Device->PoweredDown() || lastActivity == 0)) { // powered up or forced scan
  364.                    for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) {
  365.                        const cChannel *Channel = ScanData->GetChannel();
  366.                        if (Channel) {
  367. @@ -165,6 +166,10 @@ void cEITScanner::Process(void)
  368.                                             }
  369.                                          }
  370.                                       //dsyslog("EIT scan: device %d  source  %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
  371. +                                     if (lastActivity == 0)
  372. +                                        // forced scan - set idle timer for each channel switch;
  373. +                                        // this prevents powering down while scanning a transponder
  374. +                                        Device->SetIdleTimer(true, ScanTimeout + 5);
  375.                                       Device->SwitchChannel(Channel, false);
  376.                                       scanList->Del(ScanData);
  377.                                       AnyDeviceSwitched = true;
  378. diff --git a/menu.c b/menu.c
  379. index 569900c..5a89771 100644
  380. --- a/menu.c
  381. +++ b/menu.c
  382. @@ -3715,6 +3715,12 @@ void cMenuSetupLNB::Setup(void)
  383.       Add(new cMenuEditIntxItem(tr("Setup.LNB$Positioner speed (degrees/s)"), &data.PositionerSpeed, 1, 1800, 10));
  384.       }
  385.  
  386. +  Add(new cMenuEditBoolItem(tr("Setup.LNB$Enable power saving"), &data.PowerdownEnabled));
  387. +  if (data.PowerdownEnabled) {
  388. +     Add(new cMenuEditIntItem(tr("Setup.LNB$Power down an idle device after (min)"), &data.PowerdownTimeoutM));
  389. +     Add(new cMenuEditIntItem(tr("Setup.LNB$Wake up from power-down after (h)"), &data.PowerdownWakeupH));
  390. +     }
  391. +
  392.    SetCurrent(Get(current));
  393.    Display();
  394.  }
  395. @@ -3723,6 +3729,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
  396.  {
  397.    int oldDiSEqC = data.DiSEqC;
  398.    int oldUsePositioner = data.UsePositioner;
  399. +  int oldPowerdownEnabled = data.PowerdownEnabled;
  400.    bool DeviceBondingsChanged = false;
  401.    if (Key == kOk) {
  402.       cString NewDeviceBondings = satCableNumbers.ToString();
  403. @@ -3731,7 +3738,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
  404.       }
  405.    eOSState state = cMenuSetupBase::ProcessKey(Key);
  406.  
  407. -  if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner))
  408. +  if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner || data.PowerdownEnabled != oldPowerdownEnabled))
  409.       Setup();
  410.    else if (DeviceBondingsChanged)
  411.       cDvbDevice::BondDevices(data.DeviceBondings);
  412. diff --git a/vdr.c b/vdr.c
  413. index 6b0bf2b..c8de702 100644
  414. --- a/vdr.c
  415. +++ b/vdr.c
  416. @@ -1515,6 +1515,12 @@ int main(int argc, char *argv[])
  417.  
  418.          ReportEpgBugFixStats();
  419.  
  420. +        for (int i = 0; i < cDevice::NumDevices(); i++) {
  421. +           cDevice *d = cDevice::GetDevice(i);
  422. +           if (d)
  423. +              d->CheckIdle();
  424. +           }
  425. +
  426.          // Main thread hooks of plugins:
  427.          PluginManager.MainThreadHook();
  428.          }
  429. --
  430. 1.9.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement