68cd5704811d3e3fd8c65719560331b926b0b6f8
[platform/core/system/deviced.git] / plugins / tv / display / key-filter.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include <assert.h>
25 #include <vconf.h>
26 #include <sys/types.h>
27 #include <libsyscommon/libgdbus.h>
28 #include <libsyscommon/resource-manager.h>
29 #include <libsyscommon/log.h>
30 #include <system/syscommon-plugin-deviced-common-interface.h>
31 #include <system/syscommon-plugin-deviced-display-interface.h>
32 #include <linux/input.h>
33
34 #include "ambient-mode.h"
35 #include "core.h"
36 #include "poll.h"
37 #include "device-interface.h"
38 #include "display-actor.h"
39 #include "display-panel.h"
40 #include "display-backlight.h"
41 #include "display-ops.h"
42 #include "display-config.h"
43 #include "display-misc.h"
44 #include "display-state-transition.h"
45 #include "display-util.h"
46 #include "shared/common.h"
47 #include "shared/devices.h"
48 #include "shared/device-notifier.h"
49 #include "shared/common.h"
50 #include "shared/plugin.h"
51 #include "shared/apps.h"
52 #include "power/power-off.h"
53 #include "power/power-suspend.h"
54 #include "led/touch-key.h"
55 #include "display-lock.h"
56 #include "input/input.h"
57
58 #ifndef KEY_SCREENLOCK
59 #define KEY_SCREENLOCK          0x98
60 #endif
61 #ifndef SW_GLOVE
62 #define SW_GLOVE                0x16
63 #endif
64
65 #define USEC_PER_SEC                    1000000
66
67 #define CAPTURE_COMBINATION_INTERVAL            0.5     /* 0.5 second */
68 #define TORCH_COMBINATION_INTERVAL                      0.1 /* 0.1 second */
69 #define DEFAULT_COMBINATION_INTERVAL            0.1 /* 0.1 second */
70
71 #define LONGKEY_PRESSED_TIME    4       /* 4 second */
72
73 #define SIGNAL_CHANGE_HARDKEY           "ChangeHardkey"
74 #define SIGNAL_LCDON_BY_POWERKEY        "LCDOnByPowerkey"
75 #define SIGNAL_LCDOFF_BY_POWERKEY       "LCDOffByPowerkey"
76
77 enum key_combination_flags {
78         KEY_COMBINATION_STOP            = 0,
79         KEY_COMBINATION_POWERKEY        = BIT(0),
80         KEY_COMBINATION_MENUKEY         = BIT(1),
81         KEY_COMBINATION_VOLUMEUP        = BIT(2),
82         KEY_COMBINATION_VOLUMEDOWN      = BIT(3),
83 };
84
85 enum combination_process {
86         COMBINATION_STOP        = KEY_COMBINATION_STOP,
87         COMBINATION_SCREENCAPTURE       = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_MENUKEY,
88         COMBINATION_TORCH       = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_VOLUMEUP,
89         COMBINATION_QUICKTALK   = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_VOLUMEDOWN,
90 };
91
92 static struct display_plugin *disp_plgn;
93 static struct display_backlight_ops *backlight_ops;
94 static struct timeval pressed_time;
95 static guint longkey_timeout_id = 0;
96 static guint longkey_restore_id = 0;
97 static guint displayon_by_powerkey_timeout_id = 0;
98 static int cancel_lcdoff;
99 static int key_combination = KEY_COMBINATION_STOP;
100 static double combination_pressed_time;
101 static bool touch_pressed = false;
102 static int skip_lcd_off = false;
103 static int skip_combination = false;
104 static int bezel_wakeup = true;
105 static int booting_check = true;
106
107 static inline int current_state_in_on(void)
108 {
109         int ret;
110         enum syscommon_deviced_display_state current;
111
112         ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
113                 DEVICED_DISPLAY_ATTR_INT_CURRENT_STATE, (int32_t *) &current);
114         if (ret < 0)
115                 return 0;
116
117         return ((current == SYSCOMMON_DEVICED_DISPLAY_STATE_DIM) || (current == SYSCOMMON_DEVICED_DISPLAY_STATE_ON));
118 }
119
120 static inline void restore_custom_brightness(void)
121 {
122         bool custom_status;
123         int ret;
124         enum syscommon_deviced_display_state current;
125
126         ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
127                 DEVICED_DISPLAY_ATTR_INT_CURRENT_STATE, (int32_t *) &current);
128         if (ret < 0)
129                 return;
130
131         display_backlight_get_custom_status(&custom_status);
132         if (current == SYSCOMMON_DEVICED_DISPLAY_STATE_DIM && custom_status)
133                 display_backlight_update_by_custom_brightness();
134 }
135
136 static void pwroff_popup(void)
137 {
138         int ret;
139
140         ret = launch_system_app(APP_POWERKEY, 2, APP_KEY_TYPE, APP_POWERKEY);
141         if (ret < 0)
142                 _E("Failed to launch power off popup.");
143 }
144
145 static void longkey_pressed(void)
146 {
147         unsigned int caps;
148
149         _I("Power key long pressed!");
150         cancel_lcdoff = 1;
151
152         caps = display_get_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY);
153
154         if (display_has_caps(caps, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON)) {
155                 /* change state - LCD on */
156                 syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
157                         DEVICED_DISPLAY_ATTR_TUPLE2_CURRENT_STATE,
158                         SYSCOMMON_DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT_POWERKEY);
159         }
160
161         if (!display_has_caps(caps, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF)) {
162                 _D("No poweroff capability!");
163                 return;
164         }
165
166         pwroff_popup();
167 }
168
169 static gboolean longkey_restore_cb(void *data)
170 {
171         syscommon_notifier_emit_notify(DEVICED_NOTIFIER_LONGKEY_RESTORE, (void *)NULL);
172         longkey_restore_id = 0;
173
174         return G_SOURCE_REMOVE;
175 }
176
177 static gboolean longkey_pressed_cb(void *data)
178 {
179         longkey_pressed();
180         longkey_timeout_id = 0;
181
182         return G_SOURCE_REMOVE;
183 }
184
185 static unsigned long timediff_usec(struct timeval t1, struct timeval t2)
186 {
187         unsigned long udiff;
188
189         udiff = (t2.tv_sec - t1.tv_sec) * USEC_PER_SEC;
190         udiff += (t2.tv_usec - t1.tv_usec);
191
192         return udiff;
193 }
194
195 static inline void check_key_pair(int code, int new, int *old)
196 {
197         if (new == *old)
198                 _E("key pair is not matched! (%d, %d)", code, new);
199         else
200                 *old = new;
201 }
202
203 static inline void broadcast_lcdon_by_powerkey(void)
204 {
205         gdbus_signal_emit(NULL,
206                                         DEVICED_PATH_DISPLAY,
207                                         DEVICED_INTERFACE_DISPLAY,
208                                         SIGNAL_LCDON_BY_POWERKEY,
209                                         NULL);
210 }
211
212 static inline void broadcast_lcdoff_by_powerkey(void)
213 {
214         gdbus_signal_emit(NULL,
215                                         DEVICED_PATH_DISPLAY,
216                                         DEVICED_INTERFACE_DISPLAY,
217                                         SIGNAL_LCDOFF_BY_POWERKEY,
218                                         NULL);
219 }
220
221 static inline bool switch_on_lcd(enum device_flags flags)
222 {
223         if (current_state_in_on())
224                 return false;
225
226         if (display_panel_get_dpms_cached_state() == SYSCOMMON_DEVICED_DPMS_ON) {
227                 if (ambient_get_state() == false)
228                         return false;
229         }
230
231         if (flags & LCD_ON_BY_POWER_KEY)
232                 broadcast_lcdon_by_powerkey();
233         else if (flags & LCD_ON_BY_TOUCH)
234                 _I("Display on by Touch_wakeup event");
235
236         display_panel_lcd_on_direct(flags);
237
238         return true;
239 }
240
241 static inline void switch_off_lcd(void)
242 {
243         if (!current_state_in_on())
244                 return;
245
246         if (display_panel_get_dpms_cached_state() == SYSCOMMON_DEVICED_DPMS_OFF)
247                 return;
248
249         broadcast_lcdoff_by_powerkey();
250
251         display_panel_lcd_off_procedure(LCD_OFF_BY_POWER_KEY);
252 }
253
254 static void check_key_combination(struct input_event *pinput)
255 {
256         double press_time, diff_time;
257         press_time = (pinput->time).tv_sec + USEC_TO_SEC((pinput->time).tv_usec);
258         diff_time = press_time - combination_pressed_time;
259
260         switch (key_combination) {
261         case COMBINATION_SCREENCAPTURE:
262                 if (diff_time <= CAPTURE_COMBINATION_INTERVAL) {
263                         _I("Combination key : SCREENCAPTURE mode");
264                         skip_combination = true;
265                 }
266                 break;
267         case COMBINATION_TORCH:
268                 if (diff_time <= TORCH_COMBINATION_INTERVAL) {
269                         /* When torch combination, display control should be not change. */
270                         if (displayon_by_powerkey_timeout_id) {
271                                 g_source_remove(displayon_by_powerkey_timeout_id);
272                                 displayon_by_powerkey_timeout_id = 0;
273                         }
274                         _I("Combination key : TORCH mode");
275                         skip_combination = true;
276                 } else
277                         key_combination = COMBINATION_STOP;
278                 break;
279         case COMBINATION_QUICKTALK:
280                 if (diff_time <= DEFAULT_COMBINATION_INTERVAL) {
281                         _I("Combination key : QUICK-TALK mode");
282                         skip_combination = true;
283                         if (longkey_timeout_id) {
284                                 g_source_remove(longkey_timeout_id);
285                                 longkey_timeout_id = 0;
286                         }
287                 }
288                 break;
289         default:
290                 combination_pressed_time = press_time;
291                 return;
292         }
293
294 }
295
296 static void start_key_combination(struct input_event *pinput)
297 {
298         switch (pinput->code) {
299         case KEY_POWER:
300                 key_combination |= KEY_COMBINATION_POWERKEY;
301                 break;
302         case KEY_MENU:
303                 key_combination |= KEY_COMBINATION_MENUKEY;
304                 break;
305         case KEY_VOLUMEUP:
306                 key_combination |= KEY_COMBINATION_VOLUMEUP;
307                 break;
308         case KEY_VOLUMEDOWN:
309                 key_combination |= KEY_COMBINATION_VOLUMEDOWN;
310                 break;
311         default:
312                 return;
313         }
314
315         check_key_combination(pinput);
316 }
317
318 static void stop_key_combination(struct input_event *pinput)
319 {
320         if (pinput == NULL) {
321                 key_combination = KEY_COMBINATION_STOP;
322                 return;
323         }
324
325         switch (pinput->code) {
326         case KEY_POWER:
327                 key_combination &= ~KEY_COMBINATION_POWERKEY;
328                 break;
329         case KEY_MENU:
330                 key_combination &= ~KEY_COMBINATION_MENUKEY;
331                 break;
332         case KEY_VOLUMEUP:
333                 key_combination &= ~KEY_COMBINATION_VOLUMEUP;
334                 break;
335         case KEY_VOLUMEDOWN:
336                 key_combination &= ~KEY_COMBINATION_VOLUMEDOWN;
337                 break;
338         default:
339                 _E("This code(%d) is not combination type.", pinput->code);
340                 break;
341         }
342 }
343
344 static void process_combination_key(struct input_event *pinput)
345 {
346         if (pinput->value == KEY_PRESSED)
347                 start_key_combination(pinput);
348         else if (pinput->value == KEY_RELEASED)
349                 stop_key_combination(pinput);
350 }
351
352 static int process_menu_key(struct input_event *pinput)
353 {
354         int caps;
355
356         caps = display_get_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_MENU_KEY);
357
358         if (!display_has_caps(caps, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON)) {
359                 if (current_state_in_on())
360                         return false;
361                 _D("No lcd-on capability!");
362                 return true;
363         } else if (pinput->value == KEY_PRESSED)
364                 switch_on_lcd(LCD_ON_BY_POWER_KEY);
365
366         return false;
367 }
368
369 static int decide_lcdoff(void)
370 {
371         /* It's not needed if it's already LCD off state */
372         if (!current_state_in_on() &&
373             display_panel_get_dpms_cached_state() != SYSCOMMON_DEVICED_DPMS_ON)
374                 return false;
375
376         /*
377          * This flag is set at the moment
378          * that LCD is turned on by power key
379          * LCD has not to turned off in the situation.
380          */
381         if (skip_lcd_off)
382                 return false;
383
384         /* LCD is not turned off when powerkey is pressed,not released */
385         if (key_combination == KEY_COMBINATION_POWERKEY)
386                 return false;
387
388         /* LCD-off is blocked at the moment poweroff popup shows */
389         if (cancel_lcdoff)
390                 return false;
391
392         /* LCD-off is blocked when powerkey and volmedown key are pressed */
393         if (skip_combination)
394                 return false;
395
396         /* At booting time, display must do not turn off */
397         if (booting_check)
398                 return false;
399
400         return true;
401 }
402
403 static int lcdoff_powerkey(void)
404 {
405         int ignore = true;
406
407         if (decide_lcdoff() == true) {
408                 switch_off_lcd();
409                 display_lock_release_lock_all(SYSCOMMON_DEVICED_DISPLAY_STATE_ON);
410                 display_lock_release_lock_all(SYSCOMMON_DEVICED_DISPLAY_STATE_DIM);
411                 display_state_transition_update_lcdoff_reason(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
412                 syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
413                         DEVICED_DISPLAY_ATTR_TUPLE2_CURRENT_STATE,
414                         SYSCOMMON_DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT_POWERKEY);
415         } else {
416                 ignore = false;
417                 skip_combination = false;
418         }
419         cancel_lcdoff = 0;
420
421         return ignore;
422 }
423
424 static int process_back_key(struct input_event *pinput)
425 {
426         int ignore = true;
427
428         if (pinput->value == KEY_PRESSED) {
429                 switch_on_lcd(LCD_ON_BY_BACK_KEY);
430                 _I("back key pressed");
431                 ignore = false;
432         }
433
434         return ignore;
435 }
436
437 static int process_power_key(struct input_event *pinput)
438 {
439         int ignore = true;
440         static int value = KEY_RELEASED;
441         unsigned int caps;
442         const struct syscommon_deviced_display_config *display_conf = get_var_display_config();
443         if(!display_conf) {
444                 _E("Failed to get display configuration variable.");
445                 return ignore;
446         }
447
448         caps = display_get_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY);
449
450         switch (pinput->value) {
451         case KEY_RELEASED:
452                 check_key_pair(pinput->code, pinput->value, &value);
453
454                 if (!display_conf->powerkey_doublepress) {
455                         if (display_has_caps(caps, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF))
456                                 lcdoff_powerkey();
457                         else
458                                 _D("No lcdoff capability!");
459                 } else if (skip_lcd_off)
460                         ignore = false;
461
462                 if (!display_has_caps(caps, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON))
463                         ignore = true;
464
465                 if (longkey_timeout_id > 0) {
466                         g_source_remove(longkey_timeout_id);
467                         longkey_timeout_id = 0;
468                 }
469
470                 if (longkey_restore_id > 0) {
471                         g_source_remove(longkey_restore_id);
472                         longkey_restore_id = 0;
473                 }
474
475                 break;
476         case KEY_PRESSED:
477                 if (display_has_caps(caps, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON)) {
478                         skip_lcd_off = switch_on_lcd(LCD_ON_BY_POWER_KEY);
479                 } else {
480                         _D("No lcdon capability!");
481                         skip_lcd_off = false;
482                 }
483                 check_key_pair(pinput->code, pinput->value, &value);
484                 _I("power key pressed");
485                 pressed_time.tv_sec = (pinput->time).tv_sec;
486                 pressed_time.tv_usec = (pinput->time).tv_usec;
487                 if (key_combination == KEY_COMBINATION_POWERKEY) {
488                         /* add long key timer */
489                         longkey_timeout_id = g_timeout_add_seconds(
490                                     display_conf->longpress_interval,
491                                     longkey_pressed_cb, NULL);
492                         /* add long key restore timer */
493                         longkey_restore_id = g_timeout_add_seconds(
494                                     LONGKEY_PRESSED_TIME,
495                                     longkey_restore_cb, NULL);
496                 }
497                 cancel_lcdoff = 0;
498
499                 break;
500         case KEY_BEING_PRESSED:
501                 if (timediff_usec(pressed_time, pinput->time) >
502                     (display_conf->longpress_interval * USEC_PER_SEC))
503                         longkey_pressed();
504                 break;
505         }
506         return ignore;
507 }
508
509 static int process_screenlock_key(struct input_event *pinput)
510 {
511         if (pinput->value != KEY_RELEASED) {
512                 stop_key_combination(NULL);
513                 return true;
514         }
515
516         if (!current_state_in_on())
517                 return false;
518
519         display_lock_release_lock_all(SYSCOMMON_DEVICED_DISPLAY_STATE_ON);
520         display_lock_release_lock_all(SYSCOMMON_DEVICED_DISPLAY_STATE_DIM);
521         display_state_transition_update_lcdoff_reason(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
522
523         /* LCD off forcly */
524         syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
525                 DEVICED_DISPLAY_ATTR_TUPLE2_CURRENT_STATE,
526                 SYSCOMMON_DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT_POWERKEY);
527
528         return true;
529 }
530
531 static void sound_vibrate_hardkey(void)
532 {
533         /* device notify(vibrator) */
534         /* sound(dbus) */
535         /* Need to notify to deviced-vibrator. deviced-vibrator receives ChangedHardKey signal */
536         gdbus_signal_emit(NULL,
537                                         DEVICED_PATH_KEY,
538                                         DEVICED_INTERFACE_KEY,
539                                         SIGNAL_CHANGE_HARDKEY,
540                                         NULL);
541 }
542
543 static void process_hardkey_backlight(struct input_event *pinput)
544 {
545         _E("pinput->value : %d", pinput->value);
546         if (pinput->value == KEY_PRESSED) {
547                 /* Sound & Vibrate only in unlock state */
548                 if (__get_lock_screen_state() == VCONFKEY_IDLE_UNLOCK
549                     || get_lock_screen_bg_state())
550                         sound_vibrate_hardkey();
551
552                 touchled_control_backlight(TOUCHLED_PRESS);
553         } else if (pinput->value == KEY_RELEASED) {
554                 /* if lockscreen is idle lock */
555                 if (__get_lock_screen_state() == VCONFKEY_IDLE_LOCK) {
556                         _D("Lock state, key backlight is off when phone is unlocked!");
557                         return;
558                 }
559
560                 touchled_control_backlight(TOUCHLED_RELEASE);
561         }
562 }
563
564 static void update_vital_state(struct input_event *pinput)
565 {
566         int type;
567
568         /* Change vital state to  SYSCOMMON_DEVICED_VITAL_EXIT only if vital mode is active */
569         if (!vital_mode())
570                 return;
571
572         /* Touch or Menu Key Release Event */
573         if (pinput->type == EV_ABS || (pinput->type == EV_KEY &&
574             pinput->value == KEY_RELEASED && pinput->code == KEY_MENU)) {
575                 /* Enable all services upon receiving user input, else maintain same state */
576                 type = SYSCOMMON_DEVICED_VITAL_EXIT;
577                 syscommon_notifier_emit_notify(DEVICED_NOTIFIER_VITAL_STATE, &type);
578         }
579 }
580
581 static int check_key(struct input_event *pinput)
582 {
583         int ignore = true;
584
585         process_combination_key(pinput);
586         switch (pinput->code) {
587         case KEY_MENU:
588                 ignore = process_menu_key(pinput);
589                 break;
590         case KEY_POWER:
591                 ignore = process_power_key(pinput);
592                 if (current_state_in_on())
593                         ignore = false;
594                 break;
595         case KEY_SCREENLOCK:
596                 ignore = process_screenlock_key(pinput);
597                 break;
598         case KEY_BACK:
599                 ignore = process_back_key(pinput);
600                 stop_key_combination(NULL);
601                 if (current_state_in_on()) {
602                         process_hardkey_backlight(pinput);
603                         ignore = false;
604                 }
605                 break;
606         case KEY_PHONE:
607                 stop_key_combination(NULL);
608                 if (current_state_in_on()) {
609                         process_hardkey_backlight(pinput);
610                         ignore = false;
611                 }
612                 break;
613         case KEY_VOLUMEUP:
614         case KEY_VOLUMEDOWN:
615                 if (current_state_in_on())
616                         ignore = false;
617                 break;
618         case KEY_CAMERA:
619         case KEY_EXIT:
620         case KEY_CONFIG:
621         case KEY_MEDIA:
622         case KEY_MUTE:
623         case KEY_PLAYPAUSE:
624         case KEY_PLAYCD:
625         case KEY_PAUSECD:
626         case KEY_STOPCD:
627         case KEY_NEXTSONG:
628         case KEY_PREVIOUSSONG:
629         case KEY_REWIND:
630         case KEY_FASTFORWARD:
631                 stop_key_combination(NULL);
632                 if (current_state_in_on())
633                         ignore = false;
634                 break;
635         case 0x1DB:
636         case 0x1DC:
637         case 0x1DD:
638         case 0x1DE:
639                 stop_key_combination(NULL);
640                 break;
641         default:
642                 stop_key_combination(NULL);
643                 ignore = false;
644         }
645 #ifdef ENABLE_PM_LOG
646         if (pinput->value == KEY_PRESSED)
647                 pm_history_save(SYSCOMMON_DEVICED_POWER_LOG_TYPE_KEY_PRESS, pinput->code);
648         else if (pinput->value == KEY_RELEASED)
649                 pm_history_save(SYSCOMMON_DEVICED_POWER_LOG_TYPE_KEY_RELEASE, pinput->code);
650 #endif
651         return ignore;
652 }
653
654 static void check_key_filter(struct timeval time, unsigned short type, unsigned short keycode, unsigned int keyvalue)
655 {
656         struct input_event *pinput = &(struct input_event) {
657                 .time = time,
658                 .type = type,
659                 .code = keycode,
660                 .value = keyvalue
661         };
662         int ignore = true;
663         static int code, value;
664         int ret;
665         enum syscommon_deviced_display_state current;
666
667         assert(pinput);
668
669         switch (pinput->type) {
670         case EV_KEY:
671                 if (pinput->code == BTN_TOUCH &&
672                         pinput->value == KEY_RELEASED)
673                         touch_pressed = false;
674                 /*
675                  * Normally, touch press/release events don't occur
676                  * in lcd off state. But touch release events can occur
677                  * in the state abnormally. Then touch events are ignored
678                  * when lcd is off state.
679                  */
680                 if (pinput->code == BTN_TOUCH && !current_state_in_on())
681                         break;
682                 if (pinput->code == code && pinput->value == value) {
683                         _E("Same key(%d, %d) is polled", code, value);
684                 }
685                 code = pinput->code;
686                 value = pinput->value;
687
688                 update_vital_state(pinput);
689                 ignore = check_key(pinput);
690                 restore_custom_brightness();
691
692                 break;
693         case EV_REL:
694                 ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
695                         DEVICED_DISPLAY_ATTR_INT_CURRENT_STATE, (int32_t *) &current);
696                 if (ret < 0)
697                         break;
698
699                 if (current == SYSCOMMON_DEVICED_DISPLAY_STATE_OFF && bezel_wakeup) {
700                         switch_on_lcd(LCD_ON_BY_BEZEL);
701                         ignore = false;
702                 } else if (current != SYSCOMMON_DEVICED_DISPLAY_STATE_OFF)
703                         ignore = false;
704                 break;
705         case EV_ABS:
706                 if (display_misc_is_touch_event_blocked()
707                         && !g_display_plugin.config->touch_wakeup
708                         && pinput->value == KEY_BEING_PRESSED)
709                         return;
710
711                 update_vital_state(pinput);
712                 if (pinput->value == KEY_PRESSED) {
713                         switch_on_lcd(LCD_ON_BY_TOUCH);
714                         ignore = false;
715                 }
716
717                 if (current_state_in_on())
718                         ignore = false;
719
720                 restore_custom_brightness();
721
722                 if (pinput->value == KEY_PRESSED)
723                         touch_pressed = true;
724                 else if (pinput->value == KEY_RELEASED)
725                         touch_pressed = false;
726                 break;
727         case EV_SW:
728                 break;
729         }
730
731         if (ignore)
732                 return;
733
734         /* lcd on or update lcd timeout */
735         display_state_transition_do_state_transition_by_input_poll_event();
736 }
737
738 static int delayed_init_done(void *data)
739 {
740         booting_check = 0;
741
742         return 0;
743 }
744
745 static int bezel_wakeup_cb(void *data)
746 {
747         bezel_wakeup = (int)((intptr_t)data);
748
749         return 0;
750 }
751
752 /*
753  * Default capability
754  * powerkey := LCDON | LCDOFF | POWEROFF
755  * homekey  := LCDON
756  */
757 static struct syscommon_deviced_display_actor_ops display_powerkey_actor = {
758         .id     = SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY,
759         .caps   = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON |
760                   SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF |
761                   SYSCOMMON_DEVICED_DISPLAY_CAPA_POWEROFF,
762 };
763
764 static struct syscommon_deviced_display_actor_ops display_menukey_actor = {
765         .id     = SYSCOMMON_DEVICED_DISPLAY_ACTOR_MENU_KEY,
766         .caps   = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON,
767 };
768
769 static void __CONSTRUCTOR__ initialize(void)
770 {
771         disp_plgn = get_var_display_plugin();
772         if (!disp_plgn)
773                 _E("Failed to get display plugin variable.");
774
775         backlight_ops = get_var_backlight_ops();
776         if (!backlight_ops)
777                 _E("Failed to get backlight operator variable.");
778
779         display_add_actor(&display_powerkey_actor);
780         display_add_actor(&display_menukey_actor);
781
782         syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_DELAYED_INIT, delayed_init_done);
783         syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_BEZEL_WAKEUP, bezel_wakeup_cb);
784
785         input_register_event_callback(check_key_filter, NULL, NULL, NULL);
786 }