RDK Documentation (Open Sourced RDK Components)
deepSleep.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2021 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 
22 /**
23 * @defgroup iarmmgrs
24 * @{
25 * @defgroup deepsleepmgr
26 * @{
27 **/
28 
29 
30 #ifdef ENABLE_DEEP_SLEEP
31 
32 #include <stdio.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <stdint.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <stdlib.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 #include <sys/stat.h>
44 #include <pthread.h>
45 #include "iarmUtil.h"
46 #include "pwrMgr.h"
47 #include "libIBus.h"
48 //#include "plat_deepsleep.h"
49 #ifdef __cplusplus
50 }
51 #endif
52 #include "pwrlogger.h"
53 #include "plat_power.h"
54 #include "deepSleepMgr.h"
55 #include "libIBusDaemon.h"
56 #include "irMgr.h"
57 #include "comcastIrKeyCodes.h"
58 #include "manager.hpp"
59 
60 
61 /* For glib APIs*/
62 #include <glib.h>
63 /* Deep Sleep static Functions */
64 static IARM_Result_t _DeepSleepWakeup(void *arg);
65 static IARM_Result_t _SetDeepSleepTimer(void *arg);
66 static IARM_Result_t _GetDeepSleepStatus(void *arg);
67 static IARM_Result_t _GetLastWakeupReason(void *arg);
68 static IARM_Result_t _GetLastWakeupKeyCode(void *arg);
69 
70 IARM_Result_t GetPwrMgrDeepSleepStatus(int *status);
71 IARM_Result_t PwrMgrDeepSleepWakeup(IARM_Bus_CommonAPI_PowerPreChange_Param_t *arg);
72 
73 static gboolean heartbeatMsg(gpointer data);
74 static gboolean deep_sleep_delay_timer_fn(gpointer data);
75 
76 /* Variables for Deep Sleep */
77 static uint32_t deep_sleep_delay_timeout = 0;
78 static uint32_t deep_sleep_wakeup_timer = 0;
79 static bool nwStandbyMode_gs = false;
80 GMainLoop *deepSleepMgr_Loop = NULL;
81 static GMainLoop *mainloop = NULL;
82 static guint dsleep_delay_event_src = 0;
83 static DeepSleepStatus_t IsDeviceInDeepSleep = DeepSleepStatus_NotStarted;
84 static gboolean isLxcRestart = 0;
85 extern void _handleDeepsleepTimeoutWakeup ();
86 
87 
88 void IARM_Bus_PWRMGR_RegisterDeepSleepAPIs()
89 {
90  /* Register for IARM events */
91  IARM_Bus_RegisterCall(IARM_BUS_COMMON_API_DeepSleepWakeup,_DeepSleepWakeup);
92  IARM_Bus_RegisterCall(IARM_BUS_DEEPSLEEPMGR_API_SetDeepSleepTimer, _SetDeepSleepTimer);
93  IARM_Bus_RegisterCall("GetDeepSleepStatus", _GetDeepSleepStatus);
94  IARM_Bus_RegisterCall(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason, _GetLastWakeupReason);
95  IARM_Bus_RegisterCall(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupKeyCode, _GetLastWakeupKeyCode);
96 }
97 
98 
99 void PwrMgrDeepSleepTimeout()
100 {
101 #if !defined (_DISABLE_SCHD_REBOOT_AT_DEEPSLEEP)
102  /*Scheduled maintanace reboot is disabled for XiOne/Llama/Platco*/
103  system("echo 0 > /opt/.rebootFlag");
104  system(" echo `/bin/timestamp` ------------- Reboot timer expired while in Deep Sleep --------------- >> /opt/logs/receiver.log");
105  system("sleep 5; /rebootNow.sh -s DeepSleepMgr -o 'Rebooting the box due to reboot timer expired while in Deep Sleep...'");
106 #endif /*End of _DISABLE_SCHD_REBOOT_AT_DEEPSLEEP*/
107 }
108 
109 
110 
111 static void SetPwrMgrDeepSleepMode(void *data)
112 {
113  LOG("[%s:%d] Entering...\n",__FUNCTION__,__LINE__);
115 
116  if(IsDeviceInDeepSleep != DeepSleepStatus_InProgress)
117  {
118  LOG("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r\n",
119  param->data.state.curState, param->data.state.newState);
120 
121  if(IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP == param->data.state.newState)
122  {
123 
124  LOG("GOT EVENT TO GO TO DEEP SLEEP \r\n");
125 
126  /*Here we are changing the DeesSleep State assuming that the api would succeed.
127  This is because, once the deep sleep api is called, the CPU would be idle.*/
128  /*Call Deep Sleep API*/
129  deep_sleep_wakeup_timer = param->data.state.deep_sleep_timeout;
130  FILE *fpST = NULL;
131  uint32_t SleepTimeInSec = 0;
132  struct stat buf;
133  IsDeviceInDeepSleep = DeepSleepStatus_InProgress;
134 
135  /* Read the Delay Sleep Time */
136  fpST = fopen("/tmp/deepSleepTimer","r");
137 
138  if (NULL != fpST) {
139  if(0 > fscanf(fpST,"%d",&SleepTimeInSec)) {
140  __TIMESTAMP();
141  LOG("Error: fscanf on SleepTimeInSec failed");
142  } else {
143  deep_sleep_delay_timeout = SleepTimeInSec ;
144  __TIMESTAMP();
145  LOG(" /tmp/ override Deep Sleep Time is %d \r\n",deep_sleep_delay_timeout);
146  }
147  fclose (fpST);
148  }
149 
150  LOG("Deep Sleep wakeup time value is %d Secs.. \r\n",deep_sleep_wakeup_timer);
151  if (deep_sleep_delay_timeout) {
152  /* start a Deep sleep timer thread */
153  LOG("Schedule Deep SLeep After %d Sec.. \r\n",deep_sleep_delay_timeout);
154  dsleep_delay_event_src = g_timeout_add_seconds ((guint) deep_sleep_delay_timeout,deep_sleep_delay_timer_fn,deepSleepMgr_Loop);
155  } else {
156  LOG("Enter to Deep sleep Mode..stop Receiver with sleep 10 before DS \r\n");
157  system("sleep 5");
158  if ((stat("/lib/systemd/system/lxc.service", &buf) == 0) && (stat("/opt/lxc_service_disabled",&buf) !=0)) {
159  LOG("stopping lxc service\r\n");
160  system("systemctl stop lxc.service");
161  isLxcRestart = 1;
162  } else {
163 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
164  LOG("stopping xre-receiver service\r\n");
165  system("systemctl stop xre-receiver.service");
166  LOG("stopping wpeframework service\r\n");
167  system("systemctl stop wpeframework.service");
168 #else
169  LOG("Skipping Stopping service while entering DEEPSLEEP.\n");
170 #endif
171 #ifndef ENABLE_LLAMA_PLATCO
172  LOG("Unmounting SDcard partition\r\n");
173  system("sh /lib/rdk/disk_checkV2 deepsleep ON");
174 #else
175  LOG("Skipping Unmounting SDcard partition.\r\n");
176 #endif
177  }
178 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
179  LOG("Enter to Deep sleep Mode..stop fog service before DS \r\n");
180  system("systemctl stop fog.service");
181 #endif
182  int status = -1;
183  int retryCount = 0;
184  bool userWakeup = 0;
185  while(retryCount< 5) {
186  LOG("Device entering Deep sleep Mode.. \r\n");
187  userWakeup = 0;
188 #ifdef ENABLE_LLAMA_PLATCO_SKY_XIONE
189  nwStandbyMode_gs = param->data.state.nwStandbyMode;
190  LOG("\nCalling PLAT_DS_SetDeepSleep with nwStandbyMode: %s\n",
191  nwStandbyMode_gs?("Enabled"):("Disabled"));
192 #endif
193  LOG("Device entered to Deep sleep Mode.. \r\n");
194  status = PLAT_DS_SetDeepSleep(deep_sleep_wakeup_timer,&userWakeup, nwStandbyMode_gs);
195  LOG("Device resumed from Deep sleep Mode. \r\n");
196 
197  if(status != 0) {
198  sleep(5);
199  retryCount++;
200  if(retryCount >= 5) {
201  LOG("ERROR: Device failed to enter into Deep sleep Mode.. \r\n");
202  IsDeviceInDeepSleep = DeepSleepStatus_Failed;
203  break;
204  }
205  } else {
206  IsDeviceInDeepSleep = DeepSleepStatus_Completed;
207  break;
208  }
209  }
210 
211  if (userWakeup) {
212  /* Always send KED_DEEPSLEEP_WAKEUP when user action wakes the device from deep sleep. Previously this was sent
213  if we woke from a GPIO event, however there are cases where IR events aren't always passed when exiting
214  deep sleep resulting in the device not fully resuming. To resolve this we will ensure the WAKE event
215  is always sent here */
216  LOG("Resumed due to user action. Sending KED_DEEPSLEEP_WAKEUP. \r\n");
217  IARM_Bus_IRMgr_EventData_t eventData;
218  eventData.data.irkey.keyType = KET_KEYDOWN;
219  eventData.data.irkey.keyCode = KED_DEEPSLEEP_WAKEUP;
220  eventData.data.irkey.isFP = 0;
221  eventData.data.irkey.keySrc = IARM_BUS_IRMGR_KEYSRC_IR;
222 
223  IARM_Bus_BroadcastEvent(IARM_BUS_IRMGR_NAME, (IARM_EventId_t) IARM_BUS_IRMGR_EVENT_IRKEY, (void *)&eventData, sizeof(eventData));
224  eventData.data.irkey.keyType = KET_KEYUP;
225  IARM_Bus_BroadcastEvent(IARM_BUS_IRMGR_NAME, (IARM_EventId_t) IARM_BUS_IRMGR_EVENT_IRKEY, (void *)&eventData, sizeof(eventData));
226  } else {
227  LOG("Resumed without user action. Not sending KED_DEEPSLEEP_WAKEUP. \r\n");
228  }
229 
230  #ifdef USE_WAKEUP_TIMER_EVT
231  DeepSleep_WakeupReason_t wakeupReason = DEEPSLEEP_WAKEUPREASON_UNKNOWN;
232  int reasonStatus = PLAT_DS_GetLastWakeupReason(&wakeupReason);
233  if (DEEPSLEEP_WAKEUPREASON_TIMER == wakeupReason){
234  LOG("Calling IARM_BUS_PWRMGR_API_handleDeepsleepTimeoutWakeup on wakeupReason:%d \n", wakeupReason);
235  _handleDeepsleepTimeoutWakeup();
236  }
237  #endif
238  }
239  }
240  } else {
241  LOG("[%s]DeepSleepStatus InProgress. Failed to Update DeepSleep ModeChange \r\n", __FUNCTION__);
242  }
243 
244  if(data) {
245  free(data);
246  data = NULL;
247  }
248  LOG("[%s:%d] Exiting...\r\n",__FUNCTION__,__LINE__);
249 }
250 
251 static void* DeepsleepStateChangeThread(void* arg)
252 {
253  SetPwrMgrDeepSleepMode(arg);
254  pthread_exit(NULL);
255 }
256 
257 void HandleDeepSleepStateChange(void *data)
258 {
259 
260  pthread_t pwrMgrDSEventThreadId;
261 
263 
264  LOG("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r\n",
265  param->data.state.curState, param->data.state.newState);
266 
267  int err = pthread_create(&pwrMgrDSEventThreadId, NULL, DeepsleepStateChangeThread, data);
268  if(err != 0) {
269  LOG("DeepsleepStateChangeThread thread create failed \r\n");
270  } else {
271  err = pthread_detach(pwrMgrDSEventThreadId);
272  if(err != 0) {
273  LOG("DeepsleepStateChangeThread thread detach failed \r\n");
274  }
275  }
276 }
277 
278 static IARM_Result_t _DeepSleepWakeup(void *arg)
279 {
280  IARM_Bus_CommonAPI_PowerPreChange_Param_t *param = (IARM_Bus_CommonAPI_PowerPreChange_Param_t *) arg;
281 
282 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
283  const char* syscommand = "systemctl restart mocadriver.service &";
284 #endif
285 
286  LOG("RPC IARM_BUS_COMMON_API_DeepSleepWakeup : State Changed %d -- > %d\r", param->curState, param->newState);
287 
288  /* Support Deep sleep to Power ON, Light Sleep and Standby Transition. */
289  if( (IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP == param->curState) &&
290  (IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP != param->newState)) {
291  LOG("GOT EVENT TO EXIT FROM DEEP SLEEP \r\n");
292 
293  /*Call Wake up API */
294  PLAT_DS_DeepSleepWakeup();
295 
296  /* Remove the Event source */
297  if(dsleep_delay_event_src) {
298  g_source_remove(dsleep_delay_event_src);
299  dsleep_delay_event_src = 0;
300  }
301 
302  if(IsDeviceInDeepSleep) {
303  /*Restart Moca service when exit from Deep Sleep*/
304 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
305  LOG("Restarting Moca Service After Waking up from Deep Sleep.. \r\n");
306  system(syscommand);
307 #endif
308 #ifndef ENABLE_LLAMA_PLATCO
309  LOG("Mounting SDcard partition After Waking up from Deep Sleep..\r\n");
310  system("sh /lib/rdk/disk_checkV2 deepsleep OFF");
311 #endif
312 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
313  LOG("Restarting fog Service After Waking up from Deep Sleep.. \r\n");
314  system("systemctl restart fog.service &");
315 #endif
316  if (isLxcRestart) {
317  LOG("Restarting Lxc Service After Waking up from Deep Sleep\r\n");
318  system("systemctl restart lxc.service");
319  isLxcRestart = 0;
320  } else {
321 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
322  LOG("Restarting WPEFramework Service After Waking up from Deep Sleep\r\n");
323  system("systemctl restart wpeframework.service");
324  LOG("Restarting Receiver Service After Waking up from Deep Sleep\r\n");
325  system("systemctl restart xre-receiver.service");
326 #else
327  LOG("Skipping restart of Services in Sky Platform\n");
328 #endif
329 
330  }
331  }
332  IsDeviceInDeepSleep = DeepSleepStatus_NotStarted;
333 
334  LOG("Device woke up from Deep sleep Mode.. \r\n");
335  }
336  return IARM_RESULT_SUCCESS;
337 }
338 
339 
340 
341 IARM_Result_t PwrMgrDeepSleepWakeup(IARM_Bus_CommonAPI_PowerPreChange_Param_t *arg)
342 {
343  IARM_Bus_CommonAPI_PowerPreChange_Param_t *param = (IARM_Bus_CommonAPI_PowerPreChange_Param_t *) arg;
344 
345 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
346  const char* syscommand = "systemctl restart mocadriver.service &";
347 #endif
348 
349  LOG("RPC IARM_BUS_COMMON_API_DeepSleepWakeup : State Changed %d -- > %d\r", param->curState, param->newState);
350 
351  /* Support Deep sleep to Power ON, Light Sleep and Standby Transition. */
352  if( (IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP == param->curState) &&
353  (IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP != param->newState)) {
354  LOG("GOT EVENT TO EXIT FROM DEEP SLEEP \r\n");
355 
356  /*Call Wake up API */
357  PLAT_DS_DeepSleepWakeup();
358 
359  /* Remove the Event source */
360  if(dsleep_delay_event_src) {
361  g_source_remove(dsleep_delay_event_src);
362  dsleep_delay_event_src = 0;
363  }
364 
365  if(IsDeviceInDeepSleep) {
366  /*Restart Moca service when exit from Deep Sleep*/
367 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
368  LOG("Restarting Moca Service After Waking up from Deep Sleep.. \r\n");
369  system(syscommand);
370 #endif
371 #ifndef ENABLE_LLAMA_PLATCO
372  LOG("Mounting SDcard partition After Waking up from Deep Sleep..\r\n");
373  system("sh /lib/rdk/disk_checkV2 deepsleep OFF");
374 #endif
375 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
376  LOG("Restarting fog Service After Waking up from Deep Sleep.. \r\n");
377  system("systemctl restart fog.service &");
378 #endif
379  if (isLxcRestart) {
380  LOG("Restarting Lxc Service After Waking up from Deep Sleep\r\n");
381  system("systemctl restart lxc.service");
382  isLxcRestart = 0;
383  } else {
384 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
385  LOG("Restarting WPEFramework Service After Waking up from Deep Sleep\r\n");
386  system("systemctl restart wpeframework.service");
387  LOG("Restarting Receiver Service After Waking up from Deep Sleep\r\n");
388  system("systemctl restart xre-receiver.service");
389 #else
390  LOG("Skipping restart of Services in Sky Platform\n");
391 #endif
392 
393  }
394  }
395  IsDeviceInDeepSleep = DeepSleepStatus_NotStarted;
396 
397  LOG("Device woke up from Deep sleep Mode.. \r\n");
398  }
399  return IARM_RESULT_SUCCESS;
400 }
401 
402 static IARM_Result_t _GetDeepSleepStatus(void *arg)
403 {
404  int *status = (int *)arg;
405  *status = IsDeviceInDeepSleep;
406  return IARM_RESULT_SUCCESS;
407 }
408 
409 IARM_Result_t GetPwrMgrDeepSleepStatus(int *status)
410 {
411  *status = IsDeviceInDeepSleep;
412  return IARM_RESULT_SUCCESS;
413 }
414 
415 static IARM_Result_t _SetDeepSleepTimer(void *arg)
416 {
417  IARM_Bus_DeepSleepMgr_SetDeepSleepTimer_Param_t *param = (IARM_Bus_DeepSleepMgr_SetDeepSleepTimer_Param_t *)arg;
418 
419  if(param != NULL) {
420  LOG("Deep sleep timer set to : %d Seconds \r\n", param->timeout);
421  deep_sleep_delay_timeout = param->timeout;
422  return IARM_RESULT_SUCCESS;
423  }
424  return IARM_RESULT_IPCCORE_FAIL;
425 }
426 
427 static gboolean deep_sleep_delay_timer_fn(gpointer data)
428 {
429  struct stat buf;
430  int status = -1;
431 
432  LOG("Deep Sleep Timer Expires :Enter to Deep sleep Mode..stop Receiver with sleep 10 before DS \r\n");
433  system("sleep 10");
434 
435  if ((stat("/lib/systemd/system/lxc.service", &buf) == 0) && (stat("/opt/lxc_service_disabled",&buf) !=0)) {
436  system("systemctl stop lxc.service");
437  isLxcRestart = 1;
438  } else {
439 #ifndef ENABLE_LLAMA_PLATCO_SKY_XIONE
440  system("systemctl stop xre-receiver.service");
441  system("systemctl stop wpeframework.service");
442 #else
443  LOG("Skiping Stopping of services in Sky Llama Platform\n");
444 #endif
445  }
446  bool userWakeup = 0;
447  status = PLAT_DS_SetDeepSleep(deep_sleep_wakeup_timer,&userWakeup, nwStandbyMode_gs);
448  if(status != 0) {
449  LOG("deep_sleep_delay_timer_fn: Failed to enter deepsleep state \n");
450  }
451 
452  #ifdef USE_WAKEUP_TIMER_EVT
453  //Call pwrmgr InvokeDeepsleepTimeout here
454  DeepSleep_WakeupReason_t wakeupReason = DEEPSLEEP_WAKEUPREASON_UNKNOWN;
455  int reasonStatus = PLAT_DS_GetLastWakeupReason(&wakeupReason);
456  if (DEEPSLEEP_WAKEUPREASON_TIMER == wakeupReason){
457  LOG("Calling IARM_BUS_PWRMGR_API_handleDeepsleepTimeoutWakeup on wakeupReason:%d \n", wakeupReason);
458  _handleDeepsleepTimeoutWakeup();
459  }
460  #endif
461  return FALSE; // Send False so the handler should not be called again
462 }
463 
464 static IARM_Result_t _GetLastWakeupReason(void *arg)
465 {
466  DeepSleep_WakeupReason_t *wakeupReason = (DeepSleep_WakeupReason_t *)arg;
467  int status = PLAT_DS_GetLastWakeupReason(wakeupReason);
468  return (IARM_Result_t) status;
469 }
470 
471 static IARM_Result_t _GetLastWakeupKeyCode(void *arg)
472 {
473  IARM_Bus_DeepSleepMgr_WakeupKeyCode_Param_t *wakeupKeyCode = (IARM_Bus_DeepSleepMgr_WakeupKeyCode_Param_t *)arg;
474  int status = PLAT_DS_GetLastWakeupKeyCode(wakeupKeyCode);
475  return (IARM_Result_t) status;
476 
477 }
478 #endif
479 /** @} */
480 /** @} */
IARM_BUS_IRMGR_EVENT_IRKEY
@ IARM_BUS_IRMGR_EVENT_IRKEY
Definition: irMgr.h:220
DeepSleepStatus_Failed
@ DeepSleepStatus_Failed
Definition: deepSleepMgr.h:64
manager.hpp
It contains class referenced by manager.cpp file.
_PWRMgr_EventData_t
Structure which holds the event data.
Definition: pwrMgr.h:117
IARM_Bus_RegisterCall
IARM_Result_t IARM_Bus_RegisterCall(const char *methodName, IARM_BusCall_t handler)
This API is used to register an RPC method that can be invoked by other applications.
DeepSleepStatus_NotStarted
@ DeepSleepStatus_NotStarted
Definition: deepSleepMgr.h:65
DeepSleepStatus_Completed
@ DeepSleepStatus_Completed
Definition: deepSleepMgr.h:67
IARM_Bus_BroadcastEvent
IARM_Result_t IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *data, size_t len)
This API is used to publish an Asynchronous event to all IARM client registered for this perticular e...
libIBus.h
RDK IARM-Bus API Declarations.
IARM_BUS_IRMGR_NAME
#define IARM_BUS_IRMGR_NAME
Definition: irMgr.h:216
IARM_BUS_IRMGR_KEYSRC_IR
@ IARM_BUS_IRMGR_KEYSRC_IR
Definition: irMgr.h:229
pwrMgr.h
IARM-Bus Power Manager Public API.
irMgr.h
IARM-Bus IR Manager API.
_IRMgr_EventData_t
Definition: irMgr.h:235
DeepSleepStatus_InProgress
@ DeepSleepStatus_InProgress
Definition: deepSleepMgr.h:66