tizen 2.3 release
[framework/system/deviced.git] / src / 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
25 #include <vconf.h>
26 #include <Ecore.h>
27
28 #include "util.h"
29 #include "core.h"
30 #include "poll.h"
31 #include "brightness.h"
32 #include "device-node.h"
33 #include "display-actor.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"
40
41 #include <linux/input.h>
42 #ifndef KEY_SCREENLOCK
43 #define KEY_SCREENLOCK          0x98
44 #endif
45 #ifndef SW_GLOVE
46 #define SW_GLOVE                0x16
47 #endif
48
49 #define PREDEF_LEAVESLEEP       "leavesleep"
50 #define POWEROFF_ACT                    "poweroff"
51 #define PWROFF_POPUP_ACT                "pwroff-popup"
52 #define USEC_PER_SEC                    1000000
53 #define COMBINATION_INTERVAL            0.5     /* 0.5 second */
54 #define KEYBACKLIGHT_TIME_90            90      /* 1.5 second */
55 #define KEYBACKLIGHT_TIME_360           360     /* 6 second */
56 #define KEYBACKLIGHT_TIME_ALWAYS_ON             -1      /* always on */
57 #define KEYBACKLIGHT_TIME_ALWAYS_OFF    0       /* always off */
58 #define KEYBACKLIGHT_BASE_TIME          60      /* 1min = 60sec */
59 #define KEYBACKLIGHT_PRESSED_TIME       15      /*  15 second */
60 #define KEY_MAX_DELAY_TIME              700     /* ms */
61
62 #define KEY_RELEASED            0
63 #define KEY_PRESSED             1
64 #define KEY_BEING_PRESSED       2
65
66 #define KEY_COMBINATION_STOP            0
67 #define KEY_COMBINATION_START           1
68 #define KEY_COMBINATION_SCREENCAPTURE   2
69
70 #define SIGNAL_CHANGE_HARDKEY           "ChangeHardkey"
71 #define SIGNAL_LCDON_BY_POWERKEY        "LCDOnByPowerkey"
72 #define SIGNAL_LCDOFF_BY_POWERKEY       "LCDOffByPowerkey"
73
74 #define NORMAL_POWER(val)               (val == 0)
75 #define KEY_TEST_MODE_POWER(val)        (val == 2)
76
77 #define TOUCH_RELEASE           (-1)
78
79 #ifndef VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION
80 #define VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION VCONFKEY_SETAPPL_PREFIX"/display/touchkey_light_duration"
81 #endif
82
83 #define GLOVE_MODE      1
84
85 int __WEAK__ get_glove_state(void);
86 void __WEAK__ switch_glove_key(int val);
87
88 static struct timeval pressed_time;
89 static Ecore_Timer *longkey_timeout_id = NULL;
90 static Ecore_Timer *combination_timeout_id = NULL;
91 static Ecore_Timer *hardkey_timeout_id = NULL;
92 static int cancel_lcdoff;
93 static int key_combination = KEY_COMBINATION_STOP;
94 static int menu_pressed = false;
95 static int hardkey_duration;
96 static bool touch_pressed = false;
97 static int skip_lcd_off = false;
98 static bool powerkey_pressed = false;
99
100 static inline int current_state_in_on(void)
101 {
102         return (pm_cur_state == S_LCDDIM || pm_cur_state == S_NORMAL);
103 }
104
105 static inline void restore_custom_brightness(void)
106 {
107         if (pm_cur_state == S_LCDDIM &&
108             backlight_ops.get_custom_status())
109                 backlight_ops.custom_update();
110 }
111
112 static int power_execute(void *data)
113 {
114         static const struct device_ops *ops = NULL;
115
116         FIND_DEVICE_INT(ops, POWER_OPS_NAME);
117
118         return ops->execute(data);
119 }
120
121 static void longkey_pressed()
122 {
123         int val = 0;
124         int ret;
125         int csc_mode;
126         char *opt;
127         unsigned int caps;
128
129         _I("Power key long pressed!");
130         cancel_lcdoff = 1;
131
132         caps = display_get_caps(DISPLAY_ACTOR_POWER_KEY);
133
134         if (display_has_caps(caps, DISPLAY_CAPA_LCDON)) {
135                 /* change state - LCD on */
136                 recv_data.pid = getpid();
137                 recv_data.cond = 0x100;
138                 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
139                 (*g_pm_callback)(INPUT_POLL_EVENT, NULL);
140         }
141
142         if (!display_has_caps(caps, DISPLAY_CAPA_LCDOFF)) {
143                 _D("No poweroff capability!");
144                 return;
145         }
146
147         ret = vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val);
148         if (ret != 0 || NORMAL_POWER(val)) {
149                 ret = vconf_get_int(VCONFKEY_CSC_CONFIG_MODE_RUNNING,
150                         &csc_mode);
151                 if (ret >= 0 && csc_mode) {
152                         _I("csc config mode! No poweroff-popup!");
153                         return;
154                 }
155                 opt = PWROFF_POPUP_ACT;
156                 goto entry_call;
157         }
158         if (KEY_TEST_MODE_POWER(val)) {
159                 _I("skip power off control during factory key test mode");
160                 return;
161         }
162         opt = POWEROFF_ACT;
163 entry_call:
164         power_execute(opt);
165 }
166
167 static Eina_Bool longkey_pressed_cb(void *data)
168 {
169         longkey_pressed();
170         longkey_timeout_id = NULL;
171
172         return EINA_FALSE;
173 }
174
175 static Eina_Bool combination_failed_cb(void *data)
176 {
177         key_combination = KEY_COMBINATION_STOP;
178         combination_timeout_id = NULL;
179
180         return EINA_FALSE;
181 }
182
183 static unsigned long timediff_usec(struct timeval t1, struct timeval t2)
184 {
185         unsigned long udiff;
186
187         udiff = (t2.tv_sec - t1.tv_sec) * USEC_PER_SEC;
188         udiff += (t2.tv_usec - t1.tv_usec);
189
190         return udiff;
191 }
192
193 static void stop_key_combination(void)
194 {
195         key_combination = KEY_COMBINATION_STOP;
196         if (combination_timeout_id > 0) {
197                 g_source_remove(combination_timeout_id);
198                 combination_timeout_id = NULL;
199         }
200 }
201
202 static inline void check_key_pair(int code, int new, int *old)
203 {
204         if (new == *old)
205                 _E("key pair is not matched! (%d, %d)", code, new);
206         else
207                 *old = new;
208 }
209
210 static inline void broadcast_lcdon_by_powerkey(void)
211 {
212         broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
213             SIGNAL_LCDON_BY_POWERKEY, NULL, NULL);
214 }
215
216 static inline void broadcast_lcdoff_by_powerkey(void)
217 {
218         broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
219             SIGNAL_LCDOFF_BY_POWERKEY, NULL, NULL);
220 }
221
222 static inline bool switch_on_lcd(void)
223 {
224         if (current_state_in_on())
225                 return false;
226
227         if (backlight_ops.get_lcd_power() == PM_LCD_POWER_ON)
228                 return false;
229
230         broadcast_lcdon_by_powerkey();
231
232         lcd_on_direct(LCD_ON_BY_POWER_KEY);
233
234         return true;
235 }
236
237 static inline void switch_off_lcd(void)
238 {
239         if (!current_state_in_on())
240                 return;
241
242         if (backlight_ops.get_lcd_power() == PM_LCD_POWER_OFF)
243                 return;
244
245         broadcast_lcdoff_by_powerkey();
246
247         lcd_off_procedure();
248 }
249
250 static void process_combination_key(struct input_event *pinput)
251 {
252         if (pinput->value == KEY_PRESSED) {
253                 if (key_combination == KEY_COMBINATION_STOP) {
254                         key_combination = KEY_COMBINATION_START;
255                         combination_timeout_id = ecore_timer_add(
256                             COMBINATION_INTERVAL,
257                             (Ecore_Task_Cb)combination_failed_cb, NULL);
258                 } else if (key_combination == KEY_COMBINATION_START) {
259                         if (combination_timeout_id > 0) {
260                                 ecore_timer_del(combination_timeout_id);
261                                 combination_timeout_id = NULL;
262                         }
263                         if (longkey_timeout_id > 0) {
264                                 ecore_timer_del(longkey_timeout_id);
265                                 longkey_timeout_id = NULL;
266                         }
267                         _I("capture mode");
268                         key_combination = KEY_COMBINATION_SCREENCAPTURE;
269                         skip_lcd_off = true;
270                 }
271                 menu_pressed = true;
272         } else if (pinput->value == KEY_RELEASED) {
273                 if (key_combination != KEY_COMBINATION_SCREENCAPTURE)
274                         stop_key_combination();
275                 menu_pressed = false;
276         }
277 }
278
279
280 static int process_menu_key(struct input_event *pinput)
281 {
282         int caps;
283
284         caps = display_get_caps(DISPLAY_ACTOR_MENU_KEY);
285
286         if (!display_has_caps(caps, DISPLAY_CAPA_LCDON)) {
287                 if (current_state_in_on()) {
288                         process_combination_key(pinput);
289                         return false;
290                 }
291                 _D("No lcd-on capability!");
292                 return true;
293         } else if (pinput->value == KEY_PRESSED) {
294                 switch_on_lcd();
295         }
296
297         process_combination_key(pinput);
298
299         return false;
300 }
301
302 static int decide_lcdoff(void)
303 {
304         /* It's not needed if it's already LCD off state */
305         if (!current_state_in_on() &&
306             backlight_ops.get_lcd_power() != PM_LCD_POWER_ON)
307                 return false;
308
309         /*
310          * This flag is set at the moment
311          * that LCD is turned on by power key
312          * LCD has not to turned off in the situation.
313          */
314         if (skip_lcd_off)
315                 return false;
316
317         /* LCD is not turned off when powerkey is pressed,not released */
318         if (powerkey_pressed)
319                 return false;
320
321         /* LCD-off is blocked at the moment poweroff popup shows */
322         if (cancel_lcdoff)
323                 return false;
324
325         /* LCD-off is blocked at the moment volumedown key is pressed */
326         if (menu_pressed)
327                 return false;
328
329         /* LCD-off is blocked when powerkey and volmedown key are pressed */
330         if (key_combination == KEY_COMBINATION_SCREENCAPTURE)
331                 return false;
332
333         return true;
334 }
335
336 static int lcdoff_powerkey(void)
337 {
338         int ignore = true;
339
340         if (decide_lcdoff() == true) {
341                 check_processes(S_LCDOFF);
342                 check_processes(S_LCDDIM);
343
344                 if (!check_holdkey_block(S_LCDOFF) &&
345                     !check_holdkey_block(S_LCDDIM)) {
346                         if (display_info.update_auto_brightness)
347                                 display_info.update_auto_brightness(false);
348                         switch_off_lcd();
349                         delete_condition(S_LCDOFF);
350                         delete_condition(S_LCDDIM);
351                         update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
352                         recv_data.pid = getpid();
353                         recv_data.cond = 0x400;
354                         (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
355                 }
356         } else {
357                 ignore = false;
358         }
359         cancel_lcdoff = 0;
360
361         return ignore;
362 }
363
364 static int process_power_key(struct input_event *pinput)
365 {
366         int ignore = true;
367         static int value = KEY_RELEASED;
368         unsigned int caps;
369
370         caps = display_get_caps(DISPLAY_ACTOR_POWER_KEY);
371
372         switch (pinput->value) {
373         case KEY_RELEASED:
374                 powerkey_pressed = false;
375                 check_key_pair(pinput->code, pinput->value, &value);
376
377                 if (!display_conf.powerkey_doublepress) {
378                         if (display_has_caps(caps, DISPLAY_CAPA_LCDOFF))
379                                 ignore = lcdoff_powerkey();
380                         else
381                                 _D("No lcdoff capability!");
382                 } else if (skip_lcd_off) {
383                         ignore = false;
384                 }
385
386                 if (!display_has_caps(caps, DISPLAY_CAPA_LCDON))
387                         ignore = true;
388
389                 stop_key_combination();
390                 if (longkey_timeout_id > 0) {
391                         ecore_timer_del(longkey_timeout_id);
392                         longkey_timeout_id = NULL;
393                 }
394
395                 break;
396         case KEY_PRESSED:
397                 powerkey_pressed = true;
398                 if (display_has_caps(caps, DISPLAY_CAPA_LCDON)) {
399                         skip_lcd_off = switch_on_lcd();
400                 } else {
401                         _D("No lcdon capability!");
402                         skip_lcd_off = false;
403                 }
404                 check_key_pair(pinput->code, pinput->value, &value);
405                 _I("power key pressed");
406                 pressed_time.tv_sec = (pinput->time).tv_sec;
407                 pressed_time.tv_usec = (pinput->time).tv_usec;
408                 if (key_combination == KEY_COMBINATION_STOP) {
409                         /* add long key timer */
410                         longkey_timeout_id = ecore_timer_add(
411                                     display_conf.longpress_interval,
412                                     (Ecore_Task_Cb)longkey_pressed_cb, NULL);
413                         key_combination = KEY_COMBINATION_START;
414                         combination_timeout_id = ecore_timer_add(
415                                     COMBINATION_INTERVAL,
416                                     (Ecore_Task_Cb)combination_failed_cb, NULL);
417                 } else if (key_combination == KEY_COMBINATION_START) {
418                         if (combination_timeout_id > 0) {
419                                 ecore_timer_del(combination_timeout_id);
420                                 combination_timeout_id = NULL;
421                         }
422                         _I("capture mode");
423                         key_combination = KEY_COMBINATION_SCREENCAPTURE;
424                         skip_lcd_off = true;
425                         ignore = false;
426                 }
427                 if (skip_lcd_off)
428                         ignore = false;
429                 cancel_lcdoff = 0;
430
431                 break;
432         case KEY_BEING_PRESSED:
433                 if (timediff_usec(pressed_time, pinput->time) >
434                     (display_conf.longpress_interval * USEC_PER_SEC))
435                         longkey_pressed();
436                 break;
437         }
438         return ignore;
439 }
440
441 static int process_brightness_key(struct input_event *pinput, int action)
442 {
443         if (pinput->value == KEY_RELEASED) {
444                 stop_key_combination();
445                 return true;
446         }
447
448         if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK)
449                 return false;
450
451         /* check weak function symbol */
452         if (!control_brightness_key)
453                 return true;
454
455         return control_brightness_key(action);
456 }
457
458 static int process_screenlock_key(struct input_event *pinput)
459 {
460         if (pinput->value != KEY_RELEASED) {
461                 stop_key_combination();
462                 return true;
463         }
464
465         if (!current_state_in_on())
466                 return false;
467
468         check_processes(S_LCDOFF);
469         check_processes(S_LCDDIM);
470
471         if (!check_holdkey_block(S_LCDOFF) && !check_holdkey_block(S_LCDDIM)) {
472                 delete_condition(S_LCDOFF);
473                 delete_condition(S_LCDDIM);
474                 update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
475
476                 /* LCD off forcly */
477                 recv_data.pid = -1;
478                 recv_data.cond = 0x400;
479                 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
480         }
481
482         return true;
483 }
484
485 static void turnon_hardkey_backlight(void)
486 {
487         int val, ret;
488
489         ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_HARDKEY, &val);
490         if (ret < 0 || !val) {
491                 /* key backlight on */
492                 ret = device_set_property(DEVICE_TYPE_LED,
493                     PROP_LED_HARDKEY, STATUS_ON);
494                 if (ret < 0)
495                         _E("Fail to turn off key backlight!");
496         }
497 }
498
499 static void turnoff_hardkey_backlight(void)
500 {
501         int val, ret;
502
503         ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_HARDKEY, &val);
504         /* check key backlight is already off */
505         if (!ret && !val)
506                 return;
507
508         /* key backlight off */
509         ret = device_set_property(DEVICE_TYPE_LED, PROP_LED_HARDKEY, STATUS_OFF);
510         if (ret < 0)
511                 _E("Fail to turn off key backlight!");
512 }
513
514 static Eina_Bool key_backlight_expired(void *data)
515 {
516         hardkey_timeout_id = NULL;
517
518         turnoff_hardkey_backlight();
519
520         return ECORE_CALLBACK_CANCEL;
521 }
522
523 static void sound_vibrate_hardkey(void)
524 {
525         /* device notify(vibrator) */
526         device_notify(DEVICE_NOTIFIER_TOUCH_HARDKEY, NULL);
527         /* sound(dbus) */
528         broadcast_edbus_signal(DEVICED_PATH_KEY, DEVICED_INTERFACE_KEY,
529                         SIGNAL_CHANGE_HARDKEY, NULL, NULL);
530 }
531
532 static void process_hardkey_backlight(struct input_event *pinput)
533 {
534         float fduration;
535
536         if (pinput->value == KEY_PRESSED) {
537                 if (touch_pressed) {
538                         _I("Touch is pressed, then hard key is not working!");
539                         return;
540                 }
541                 /* Sound & Vibrate only in unlock state */
542                 if (get_lock_screen_state() == VCONFKEY_IDLE_UNLOCK
543                     || get_lock_screen_bg_state())
544                         sound_vibrate_hardkey();
545                 /* release existing timer */
546                 if (hardkey_timeout_id > 0) {
547                         ecore_timer_del(hardkey_timeout_id);
548                         hardkey_timeout_id = NULL;
549                 }
550                 /* if hardkey option is always off */
551                 if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF)
552                         return;
553                 /* turn on hardkey backlight */
554                 turnon_hardkey_backlight();
555                 /* start timer */
556                 hardkey_timeout_id = ecore_timer_add(
557                             KEYBACKLIGHT_PRESSED_TIME,
558                             key_backlight_expired, NULL);
559
560         } else if (pinput->value == KEY_RELEASED) {
561                 /* if lockscreen is idle lock */
562                 if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK) {
563                         _D("Lock state, key backlight is off when phone is unlocked!");
564                         return;
565                 }
566                 /* release existing timer */
567                 if (hardkey_timeout_id > 0) {
568                         ecore_timer_del(hardkey_timeout_id);
569                         hardkey_timeout_id = NULL;
570                 }
571                 /* if hardkey option is always on or off */
572                 if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON ||
573                         hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF)
574                         return;
575                 /* start timer */
576                 fduration = (float)hardkey_duration / KEYBACKLIGHT_BASE_TIME;
577                 hardkey_timeout_id = ecore_timer_add(
578                             fduration,
579                             key_backlight_expired, NULL);
580         }
581 }
582
583 static int check_key(struct input_event *pinput, int fd)
584 {
585         int ignore = true;
586
587         switch (pinput->code) {
588         case KEY_MENU:
589                 ignore = process_menu_key(pinput);
590                 break;
591         case KEY_POWER:
592                 ignore = process_power_key(pinput);
593                 break;
594         case KEY_BRIGHTNESSDOWN:
595                 ignore = process_brightness_key(pinput, BRIGHTNESS_DOWN);
596                 break;
597         case KEY_BRIGHTNESSUP:
598                 ignore = process_brightness_key(pinput, BRIGHTNESS_UP);
599                 break;
600         case KEY_SCREENLOCK:
601                 ignore = process_screenlock_key(pinput);
602                 break;
603         case KEY_BACK:
604         case KEY_PHONE:
605                 stop_key_combination();
606                 if (current_state_in_on()) {
607                         process_hardkey_backlight(pinput);
608                         ignore = false;
609                 } else if (!check_pre_install(fd)) {
610                         ignore = false;
611                 }
612                 break;
613         case KEY_VOLUMEUP:
614         case KEY_VOLUMEDOWN:
615         case KEY_CAMERA:
616         case KEY_EXIT:
617         case KEY_CONFIG:
618         case KEY_MEDIA:
619         case KEY_MUTE:
620         case KEY_PLAYPAUSE:
621         case KEY_PLAYCD:
622         case KEY_PAUSECD:
623         case KEY_STOPCD:
624         case KEY_NEXTSONG:
625         case KEY_PREVIOUSSONG:
626         case KEY_REWIND:
627         case KEY_FASTFORWARD:
628                 stop_key_combination();
629                 if (current_state_in_on())
630                         ignore = false;
631                 break;
632         case 0x1DB:
633         case 0x1DC:
634         case 0x1DD:
635         case 0x1DE:
636                 stop_key_combination();
637                 break;
638         default:
639                 stop_key_combination();
640                 ignore = false;
641         }
642 #ifdef ENABLE_PM_LOG
643         if (pinput->value == KEY_PRESSED)
644                 pm_history_save(PM_LOG_KEY_PRESS, pinput->code);
645         else if (pinput->value == KEY_RELEASED)
646                 pm_history_save(PM_LOG_KEY_RELEASE, pinput->code);
647 #endif
648         return ignore;
649 }
650
651 static int check_key_filter(int length, char buf[], int fd)
652 {
653         struct input_event *pinput;
654         int ignore = true;
655         int idx = 0;
656         static int old_fd, code, value;
657
658         do {
659                 pinput = (struct input_event *)&buf[idx];
660                 switch (pinput->type) {
661                 case EV_KEY:
662                         if (pinput->code == BTN_TOUCH &&
663                             pinput->value == KEY_RELEASED)
664                                 touch_pressed = false;
665                         /*
666                          * Normally, touch press/release events don't occur
667                          * in lcd off state. But touch release events can occur
668                          * in the state abnormally. Then touch events are ignored
669                          * when lcd is off state.
670                          */
671                         if (pinput->code == BTN_TOUCH && !current_state_in_on())
672                                 break;
673                         if (get_standby_state() && pinput->code != KEY_POWER) {
674                                 _D("standby mode,key ignored except powerkey");
675                                 break;
676                         }
677                         if (pinput->code == code && pinput->value == value) {
678                                 _E("Same key(%d, %d) is polled [%d,%d]",
679                                     code, value, old_fd, fd);
680                         }
681                         old_fd = fd;
682                         code = pinput->code;
683                         value = pinput->value;
684
685                         ignore = check_key(pinput, fd);
686                         restore_custom_brightness();
687
688                         break;
689                 case EV_REL:
690                         if (get_standby_state())
691                                 break;
692                         ignore = false;
693                         break;
694                 case EV_ABS:
695                         if (get_standby_state())
696                                 break;
697                         if (current_state_in_on())
698                                 ignore = false;
699                         restore_custom_brightness();
700
701                         touch_pressed =
702                             (pinput->value == TOUCH_RELEASE ? false : true);
703                         break;
704                 case EV_SW:
705                         if (!get_glove_state || !switch_glove_key)
706                                 break;
707                         if (pinput->code == SW_GLOVE &&
708                             get_glove_state() == GLOVE_MODE) {
709                                 switch_glove_key(pinput->value);
710                         }
711                         break;
712                 }
713                 idx += sizeof(struct input_event);
714                 if (ignore == true && length <= idx)
715                         return 1;
716         } while (length > idx);
717
718         return 0;
719 }
720
721 void key_backlight_enable(bool enable)
722 {
723         /* release existing timer */
724         if (hardkey_timeout_id > 0) {
725                 ecore_timer_del(hardkey_timeout_id);
726                 hardkey_timeout_id = NULL;
727         }
728
729         /* start timer in case of backlight enabled */
730         if (enable) {
731                 /* if hardkey option is always off */
732                 if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF)
733                         return;
734
735                 /* turn on hardkey backlight */
736                 turnon_hardkey_backlight();
737
738                 /* do not create turnoff timer in case of idle lock state */
739                 if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK)
740                         return;
741
742                 /* start timer */
743                 hardkey_timeout_id = ecore_timer_add(
744                             KEYBACKLIGHT_PRESSED_TIME,
745                                 key_backlight_expired, NULL);
746         } else {
747                 /* if hardkey option is always on */
748                 if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON)
749                         return;
750
751                 /* turn off hardkey backlight */
752                 turnoff_hardkey_backlight();
753         }
754 }
755
756 static void hardkey_duration_cb(keynode_t *key, void *data)
757 {
758         float duration;
759
760         hardkey_duration = vconf_keynode_get_int(key);
761
762         /* release existing timer */
763         if (hardkey_timeout_id > 0) {
764                 ecore_timer_del(hardkey_timeout_id);
765                 hardkey_timeout_id = NULL;
766         }
767
768         /* if hardkey option is always off */
769         if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF) {
770                 /* turn off hardkey backlight */
771                 turnoff_hardkey_backlight();
772                 return;
773         }
774
775         /* turn on hardkey backlight */
776         turnon_hardkey_backlight();
777
778         /* if hardkey option is always on */
779         if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON)
780                 return;
781
782         /* start timer */
783         duration = (float)hardkey_duration / KEYBACKLIGHT_BASE_TIME;
784         hardkey_timeout_id = ecore_timer_add(
785                     duration,
786                     key_backlight_expired, NULL);
787 }
788
789 static int hardkey_lcd_changed_cb(void *data)
790 {
791         int lcd_state = (int)data;
792
793         if (lcd_state == S_NORMAL
794             && battery.temp == TEMP_HIGH
795             && hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON) {
796                 turnon_hardkey_backlight();
797                 return 0;
798         }
799
800         /* when lcd state is dim and battery is over temp,
801            hardkey led should turn off */
802         if (lcd_state == S_LCDDIM && battery.health == HEALTH_BAD) {
803                 /* release existing timer */
804                 if (hardkey_timeout_id > 0) {
805                         ecore_timer_del(hardkey_timeout_id);
806                         hardkey_timeout_id = NULL;
807                 }
808
809                 /* turn off hardkey backlight */
810                 turnoff_hardkey_backlight();
811         }
812         return 0;
813 }
814
815 /*
816  * Default capability
817  * powerkey := LCDON | LCDOFF | POWEROFF
818  * homekey  := LCDON
819  */
820 static struct display_actor_ops display_powerkey_actor = {
821         .id     = DISPLAY_ACTOR_POWER_KEY,
822         .caps   = DISPLAY_CAPA_LCDON |
823                   DISPLAY_CAPA_LCDOFF |
824                   DISPLAY_CAPA_POWEROFF,
825 };
826
827 static struct display_actor_ops display_menukey_actor = {
828         .id     = DISPLAY_ACTOR_MENU_KEY,
829         .caps   = DISPLAY_CAPA_LCDON,
830 };
831
832 static void keyfilter_init(void)
833 {
834         display_add_actor(&display_powerkey_actor);
835         display_add_actor(&display_menukey_actor);
836
837         /* get touchkey light duration setting */
838         if (vconf_get_int(VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION, &hardkey_duration) < 0) {
839                 _W("Fail to get VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION!!");
840                 hardkey_duration = KEYBACKLIGHT_TIME_90;
841         }
842
843         vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION, hardkey_duration_cb, NULL);
844
845         /* register notifier */
846         register_notifier(DEVICE_NOTIFIER_LCD, hardkey_lcd_changed_cb);
847
848         /* update touchkey light duration right now */
849         if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON)
850                 turnon_hardkey_backlight();
851 }
852
853 static void keyfilter_exit(void)
854 {
855         /* unregister notifier */
856         unregister_notifier(DEVICE_NOTIFIER_LCD, hardkey_lcd_changed_cb);
857
858         vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION, hardkey_duration_cb);
859 }
860
861 static const struct display_keyfilter_ops normal_keyfilter_ops = {
862         .init                   = keyfilter_init,
863         .exit                   = keyfilter_exit,
864         .check                  = check_key_filter,
865         .set_powerkey_ignore    = NULL,
866         .powerkey_lcdoff        = NULL,
867         .backlight_enable       = key_backlight_enable,
868 };
869 const struct display_keyfilter_ops *keyfilter_ops = &normal_keyfilter_ops;
870