4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
23 #include <sys/types.h>
33 #include <libsyscommon/dbus-system.h>
36 #include "core/devices.h"
37 #include "core/common.h"
38 #include "core/device-notifier.h"
40 #include "display/display-dpms.h"
41 #include "display/display.h"
42 #include "power/boot.h"
43 #include "power-control.h"
45 static int mainlock_status = POWER_UNLOCK;
46 static int vital_service;
47 static bool vital_sleep;
48 static int vital_support = -2;
52 typedef struct _pm_history {
54 enum pm_log_type log_type;
58 static int max_history_count = MAX_LOG_COUNT;
59 static pm_history pm_history_log[MAX_LOG_COUNT] = {{0, }, };
60 static int history_count = 0;
62 static const char history_string[PM_LOG_MAX][15] = {
63 "PRESS", "LONG PRESS", "RELEASE", "LCD ON", "LCD ON COMPL", "LCD ON FAIL",
64 "LCD DIM", "LCD DIM FAIL", "LCD OFF", "LCD OFF COMPL", "LCD OFF FAIL",
67 void pm_history_init()
69 memset(pm_history_log, 0x0, sizeof(pm_history_log));
71 max_history_count = MAX_LOG_COUNT;
74 void pm_history_save(enum pm_log_type log_type, int code)
79 pm_history_log[history_count].time = now;
80 pm_history_log[history_count].log_type = log_type;
81 pm_history_log[history_count].keycode = code;
84 if (history_count >= max_history_count)
88 void pm_history_print(int fd, int count)
90 int start_index, index, i;
95 if (count <= 0 || count > max_history_count)
98 start_index = (history_count - count + max_history_count)
101 for (i = 0; i < count; i++) {
102 index = (start_index + i) % max_history_count;
104 if (pm_history_log[index].time == 0)
107 if (pm_history_log[index].log_type >= PM_LOG_MAX)
109 ctime_r(&pm_history_log[index].time, time_buf);
110 time_buf[strlen(time_buf) - 1] = 0;
111 snprintf(buf, sizeof(buf), "[%3d] %15s %3d %s\n",
113 history_string[pm_history_log[index].log_type],
114 pm_history_log[index].keycode,
116 ret = write(fd, buf, strlen(buf));
118 _E("Write() failed: %d", errno);
123 bool vital_mode(void)
128 static int vital_mode_support(void)
130 if (vital_support < 0) {
133 fp = fopen(FREEZER_VITAL_WAKEUP_CGROUP, "r");
135 _E("%s open failed", FREEZER_VITAL_WAKEUP_CGROUP);
136 /* read max 2 times to check if this file exist */
143 return vital_support;
146 int suspend_other_process(int type)
150 if (vital_service == type)
153 if (type == VITAL_WAKEUP && vital_service > VITAL_SLEEP)
156 vital_service = type;
158 if (!vital_mode_support())
161 if (type == VITAL_SLEEP) {
162 dbus_handle_method_sync_with_reply_var_timeout(RESOURCED_BUS_NAME,
163 RESOURCED_PATH_FREEZER,
164 RESOURCED_INTERFACE_FREEZER,
166 g_variant_new("(s)", "sleep"),
168 SET_SUSPEND_TIME*1000);
170 } else if (type == VITAL_WAKEUP) {
171 ret = dbus_handle_method_async_var(RESOURCED_BUS_NAME,
172 RESOURCED_PATH_FREEZER,
173 RESOURCED_INTERFACE_FREEZER,
175 g_variant_new("(s)", "wakeup"));
176 } else if (type == VITAL_EXIT) {
177 ret = dbus_handle_method_async_var(RESOURCED_BUS_NAME,
178 RESOURCED_PATH_FREEZER,
179 RESOURCED_INTERFACE_FREEZER,
181 g_variant_new("(s)", "exit"));
187 int vital_state_changed(void *data)
194 if (type == VITAL_EXIT)
195 suspend_other_process(VITAL_EXIT);
204 _I("system suspend");
205 ret = sys_set_str(POWER_STATE_PATH, "mem");
206 _I("System resume: %d", ret);
210 int pm_enable_autosleep(void)
212 _I("System autosleep enabled.");
213 return sys_set_str(POWER_AUTOSLEEP_PATH, "mem");
216 int pm_power_lock(void)
218 _I("system power lock");
219 suspend_other_process(VITAL_WAKEUP);
220 mainlock_status = POWER_LOCK;
222 return sys_set_str(POWER_LOCK_PATH, "mainlock");
225 int pm_get_power_lock(void)
227 return mainlock_status;
230 int pm_get_power_lock_support(void)
232 static int power_lock_support = -1;
235 if (power_lock_support >= 0)
238 ret = sys_check_node(POWER_LOCK_PATH);
240 power_lock_support = false;
242 power_lock_support = true;
244 _I("System power lock: %s",
245 (power_lock_support ? "support" : "not support"));
248 return power_lock_support;
251 int pm_power_unlock(void)
253 _I("system power unlock");
254 suspend_other_process(VITAL_SLEEP);
255 mainlock_status = POWER_UNLOCK;
257 return sys_set_str(POWER_UNLOCK_PATH, "mainlock");
260 int check_wakeup_src(void)
263 * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT)
268 int get_wakeup_count(int *cnt)
276 ret = sys_get_int(POWER_WAKEUP_PATH, &wakeup_count);
284 int set_wakeup_count(int cnt)
288 ret = sys_set_int(POWER_WAKEUP_PATH, cnt);