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.
32 #include "brightness.h"
33 #include "device-node.h"
34 #include "core/common.h"
35 #include "core/devices.h"
36 #include "core/device-notifier.h"
37 #include "core/edbus-handler.h"
38 #include "core/device-handler.h"
39 #include "power/power-handler.h"
41 #include <linux/input.h>
43 #define POWEROFF_ACT "poweroff"
45 #define KEY_RELEASED 0
48 #define NORMAL_POWER(val) (val == 0)
49 #define KEY_TEST_MODE_POWER(val) (val == 2)
51 #define SIGNAL_LCDON_BY_POWERKEY "LCDOnByPowerkey"
53 static Ecore_Timer *longkey_timeout_id;
54 static bool ignore_powerkey = false;
56 static inline int current_state_in_on(void)
58 return (pm_cur_state == S_LCDDIM || pm_cur_state == S_NORMAL);
61 static int power_execute(void *data)
63 static const struct device_ops *ops = NULL;
65 FIND_DEVICE_INT(ops, POWER_OPS_NAME);
67 return ops->execute(data);
70 static void longkey_pressed()
74 _I("Power key long pressed!");
76 ret = vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val);
80 if (NORMAL_POWER(val) || KEY_TEST_MODE_POWER(val))
84 * Poweroff-popup has been launched by app.
85 * deviced only turns off the phone by power key
86 * when power-off popup is disabled for testmode.
88 _I("power off action!");
90 power_execute(POWEROFF_ACT);
93 static Eina_Bool longkey_pressed_cb(void *data)
96 longkey_timeout_id = NULL;
101 static inline void check_key_pair(int code, int new, int *old)
104 _E("key pair is not matched! (%d, %d)", code, new);
109 static inline void broadcast_lcdon_by_powerkey(void)
111 broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
112 SIGNAL_LCDON_BY_POWERKEY, NULL, NULL);
115 static inline bool switch_on_lcd(void)
117 if (current_state_in_on())
120 if (backlight_ops.get_lcd_power() == PM_LCD_POWER_ON)
121 if (alpm_get_state == NULL ||
122 alpm_get_state() == false)
125 broadcast_lcdon_by_powerkey();
127 lcd_on_direct(LCD_ON_BY_POWER_KEY);
132 static inline void switch_off_lcd(void)
134 if (!current_state_in_on())
137 if (backlight_ops.get_lcd_power() == PM_LCD_POWER_OFF)
143 static int process_power_key(struct input_event *pinput)
146 static int value = KEY_RELEASED;
148 switch (pinput->value) {
150 check_key_pair(pinput->code, pinput->value, &value);
153 if (longkey_timeout_id > 0) {
154 ecore_timer_del(longkey_timeout_id);
155 longkey_timeout_id = NULL;
160 check_key_pair(pinput->code, pinput->value, &value);
161 _I("power key pressed");
163 /* add long key timer */
164 longkey_timeout_id = ecore_timer_add(
165 display_conf.longpress_interval,
166 longkey_pressed_cb, NULL);
173 static int check_key(struct input_event *pinput, int fd)
177 switch (pinput->code) {
179 ignore = process_power_key(pinput);
181 case KEY_PHONE: /* Flick up key */
182 case KEY_BACK: /* Flick down key */
195 case KEY_PREVIOUSSONG:
197 case KEY_FASTFORWARD:
198 /* These case do not turn on the lcd */
199 if (current_state_in_on())
206 if (pinput->value == KEY_PRESSED)
207 pm_history_save(PM_LOG_KEY_PRESS, pinput->code);
208 else if (pinput->value == KEY_RELEASED)
209 pm_history_save(PM_LOG_KEY_RELEASE, pinput->code);
214 static int check_key_filter(int length, char buf[], int fd)
216 struct input_event *pinput;
219 static int old_fd, code, value;
222 pinput = (struct input_event *)&buf[idx];
223 switch (pinput->type) {
225 if (pinput->code == code && pinput->value == value) {
226 _E("Same key(%d, %d) is polled [%d,%d]",
227 code, value, old_fd, fd);
231 value = pinput->value;
233 ignore = check_key(pinput, fd);
239 if (current_state_in_on())
241 if (get_ambient_mode != NULL &&
242 get_ambient_mode() == true) {
246 if (pm_cur_state == S_LCDDIM &&
247 backlight_ops.get_custom_status())
248 backlight_ops.custom_update();
252 idx += sizeof(struct input_event);
253 if (ignore == true && length <= idx)
255 } while (length > idx);
260 static void set_powerkey_ignore(int on)
262 _D("ignore powerkey %d", on);
263 ignore_powerkey = on;
266 static int powerkey_lcdoff(void)
268 /* Remove non est processes */
269 check_processes(S_LCDOFF);
270 check_processes(S_LCDDIM);
272 /* check holdkey block flag in lock node */
273 if (check_holdkey_block(S_LCDOFF) ||
274 check_holdkey_block(S_LCDDIM)) {
278 _I("power key lcdoff");
280 if (display_info.update_auto_brightness)
281 display_info.update_auto_brightness(false);
283 delete_condition(S_LCDOFF);
284 delete_condition(S_LCDDIM);
285 update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
286 recv_data.pid = getpid();
287 recv_data.cond = 0x400;
288 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
293 static const struct display_keyfilter_ops micro_keyfilter_ops = {
296 .check = check_key_filter,
297 .set_powerkey_ignore = set_powerkey_ignore,
298 .powerkey_lcdoff = powerkey_lcdoff,
299 .backlight_enable = NULL,
301 const struct display_keyfilter_ops *keyfilter_ops = µ_keyfilter_ops;