4 * Copyright (c) 2012 - 2013 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.
27 #include <sys/reboot.h>
30 #include <sys/mount.h>
31 #include <device-node.h>
32 #include "core/common.h"
33 #include "core/data.h"
34 #include "core/device-handler.h"
35 #include "core/device-notifier.h"
36 #include "core/devices.h"
37 #include "core/edbus-handler.h"
38 #include "core/launch.h"
40 #include "core/predefine.h"
41 #include "core/queue.h"
42 #include "dd-deviced.h"
43 #include "display/poll.h"
44 #include "display/setting.h"
45 #include "hall/hall-handler.h"
46 #include "power-handler.h"
47 #include "proc/proc-handler.h"
49 #define SIGNAL_BOOTING_DONE "BootingDone"
50 #define PREDEF_PWROFF_POPUP "pwroff-popup"
51 #define POWEROFF_POPUP_NAME "poweroff-syspopup"
52 #define RECOVERY_POWER_OFF "reboot recovery"
54 #define SYSTEMD_STOP_POWER_OFF 4
55 #define SYSTEMD_STOP_POWER_RESTART 5
56 #define SYSTEMD_STOP_POWER_RESTART_RECOVERY 6
57 #define SYSTEMD_CHECK_POWER_OFF 15
64 static const struct device_ops *hall_ic = NULL;
65 static Ecore_Timer *systemd_poweroff_timer = NULL;
67 static Eina_Bool systemd_force_shutdown_cb(void *arg)
70 if (systemd_poweroff_timer) {
71 ecore_timer_del(systemd_poweroff_timer);
72 systemd_poweroff_timer = NULL;
74 snprintf(params, sizeof(params), "%s -f", (char*)arg);
75 launch_evenif_exist("/usr/bin/systemctl", params);
79 static void start_boot_animation(void)
82 snprintf(params, sizeof(params), "--stop --clear");
83 launch_evenif_exist("/usr/bin/boot-animation", params);
86 static int systemd_shutdown(const char *arg)
89 systemd_poweroff_timer = ecore_timer_add(SYSTEMD_CHECK_POWER_OFF,
90 systemd_force_shutdown_cb, (void *)arg);
91 start_boot_animation();
92 device_notify(DEVICE_NOTIFIER_POWEROFF_HAPTIC, NULL);
93 return launch_evenif_exist("/usr/bin/systemctl", arg);
96 int do_poweroff(int argc, char **argv)
98 return vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS,
99 VCONFKEY_SYSMAN_POWER_OFF_DIRECT);
102 static void poweroff_control_cb(keynode_t *in_key, struct main_data *ad)
107 if (vconf_get_int(in_key->keyname, &val) != 0)
110 if (val == SYSTEMD_STOP_POWER_OFF
111 || val == SYSTEMD_STOP_POWER_RESTART
112 || val == SYSTEMD_STOP_POWER_RESTART_RECOVERY) {
113 vconf_ignore_key_changed(in_key->keyname,
114 (void*)poweroff_control_cb);
115 vconf_set_int(in_key->keyname, val);
118 device_notify(DEVICE_NOTIFIER_PMQOS_POWEROFF, (void*)1);
121 case SYSTEMD_STOP_POWER_OFF:
122 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
123 device_notify(DEVICE_NOTIFIER_POWEROFF,
124 (void *)VCONFKEY_SYSMAN_POWER_OFF_DIRECT);
125 ret = systemd_shutdown(PREDEF_POWEROFF);
127 _E("fail to do (%s)", PREDEF_POWEROFF);
129 case SYSTEMD_STOP_POWER_RESTART:
130 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
131 device_notify(DEVICE_NOTIFIER_POWEROFF,
132 (void *)VCONFKEY_SYSMAN_POWER_OFF_RESTART);
133 ret = systemd_shutdown(PREDEF_REBOOT);
135 _E("fail to do (%s)", PREDEF_REBOOT);
137 case SYSTEMD_STOP_POWER_RESTART_RECOVERY:
138 device_notify(DEVICE_NOTIFIER_POWEROFF,
139 (void *)VCONFKEY_SYSMAN_POWER_OFF_RESTART);
140 ret = systemd_shutdown(RECOVERY_POWER_OFF);
142 _E("fail to do (%s)", RECOVERY_POWER_OFF);
144 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
145 notify_action(PREDEF_PWROFF_POPUP, 0);
149 if (update_pm_setting)
150 update_pm_setting(SETTING_POWEROFF, val);
153 static void booting_done_edbus_signal_handler(void *data, DBusMessage *msg)
155 if (!dbus_message_is_signal(msg,
156 DEVICED_INTERFACE_CORE,
157 SIGNAL_BOOTING_DONE)) {
158 _E("there is no bootingdone signal");
162 device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE);
165 static int hall_ic_status(void)
168 return HALL_IC_OPENED;
169 return hall_ic->status();
172 int reset_resetkey_disable(char *name, enum watch_id id)
174 _D("force reset power resetkey disable to zero");
175 return device_set_property(DEVICE_TYPE_POWER,
176 PROP_POWER_RESETKEY_DISABLE,
180 static DBusMessage *edbus_resetkeydisable(E_DBus_Object *obj, DBusMessage *msg)
182 DBusMessageIter iter;
186 ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &val,
189 _E("there is no message");
194 ret = device_set_property(DEVICE_TYPE_POWER,
195 PROP_POWER_RESETKEY_DISABLE,
201 register_edbus_watch(msg,
202 WATCH_POWER_RESETKEY_DISABLE,
203 reset_resetkey_disable);
205 unregister_edbus_watch(msg,
206 WATCH_POWER_RESETKEY_DISABLE);
208 _D("get power resetkey disable %d, %d", val, ret);
211 reply = dbus_message_new_method_return(msg);
212 dbus_message_iter_init_append(reply, &iter);
213 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
217 static int reset_wakeupkey(char *name, enum watch_id id)
219 _D("force reset wakeupkey to zero");
220 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, 0);
223 static DBusMessage *edbus_set_wakeup_key(E_DBus_Object *obj, DBusMessage *msg)
225 DBusMessageIter iter;
229 ret = dbus_message_get_args(msg, NULL,
230 DBUS_TYPE_INT32, &val,
233 _E("there is no message");
238 ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, val);
243 register_edbus_watch(msg, WATCH_POWER_WAKEUPKEY, reset_wakeupkey);
245 unregister_edbus_watch(msg, WATCH_POWER_WAKEUPKEY);
247 _D("set power wakeup key %d %d", val, ret);
250 reply = dbus_message_new_method_return(msg);
251 dbus_message_iter_init_append(reply, &iter);
252 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
256 static const struct edbus_method edbus_methods[] = {
257 { "setresetkeydisable", "i", "i", edbus_resetkeydisable },
258 { "SetWakeupKey", "i", "i", edbus_set_wakeup_key },
259 /* Add methods here */
262 int launching_predefine_action(int argc, char **argv)
264 struct popup_data *params;
265 static const struct device_ops *apps = NULL;
268 val = hall_ic_status();
269 if (val == HALL_IC_CLOSED) {
270 _I("cover is closed");
274 apps = find_device("apps");
278 params = malloc(sizeof(struct popup_data));
279 if (params == NULL) {
283 params->name = POWEROFF_POPUP_NAME;
284 apps->init((void *)params);
289 static void power_init(void *data)
294 /* init dbus interface */
295 ret = register_edbus_method(DEVICED_PATH_POWER,
297 ARRAY_SIZE(edbus_methods));
299 _E("fail to init edbus method(%d)", ret);
301 ret = register_edbus_signal_handler(DEVICED_PATH_CORE,
302 DEVICED_INTERFACE_CORE,
304 booting_done_edbus_signal_handler);
306 _E("fail to register handler for signal: %s",
307 SIGNAL_BOOTING_DONE);
309 register_action(PREDEF_POWEROFF,
310 do_poweroff, NULL, NULL);
311 register_action(PREDEF_PWROFF_POPUP,
312 launching_predefine_action, NULL, NULL);
314 ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS,
315 (void *)poweroff_control_cb,
318 _E("Vconf notify key chaneged failed: KEY(%s)",
319 VCONFKEY_SYSMAN_POWER_OFF_STATUS);
320 hall_ic = find_device(HALL_IC_NAME);
323 static const struct device_ops power_device_ops = {
324 .priority = DEVICE_PRIORITY_NORMAL,
325 .name = "systemd-power",
329 DEVICE_OPS_REGISTER(&power_device_ops)