3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
32 #include <linux/input.h>
33 #ifndef KEY_SCREENLOCK
34 #define KEY_SCREENLOCK 0x98
37 #define PREDEF_PWROFF_POPUP "pwroff-popup"
38 #define PREDEF_LEAVESLEEP "leavesleep"
39 #define PREDEF_POWEROFF "poweroff"
41 #define USEC_PER_SEC 1000000
42 #define LONG_PRESS_INTERVAL 1000000 /* 1000 ms */
43 #define COMBINATION_INTERVAL 300000 /* 300 ms */
44 #define POWER_KEY_PRESS_IGNORE_TIME 700000 /* 700 ms */
46 #define KEY_RELEASED 0
48 #define KEY_BEING_PRESSED 2
50 #define KEY_COMBINATION_STOP 0
51 #define KEY_COMBINATION_START 1
52 #define KEY_COMBINATION_SCREENCAPTURE 2
54 static struct timeval pressed_time;
55 static guint longkey_timeout_id = 0;
56 static guint combination_timeout_id = 0;
57 static int cancel_lcdoff;
58 static int key_combination = KEY_COMBINATION_STOP;
59 static int powerkey_ignored = false;
63 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
66 static inline int current_state_in_on()
68 return (cur_state == S_LCDDIM || cur_state == S_NORMAL);
71 static void longkey_pressed()
74 LOGINFO("Power key long pressed!");
77 rc = vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val);
79 if (rc < 0 || val != 1) {
80 if (sysman_call_predef_action(PREDEF_PWROFF_POPUP, 0) <
82 LOGERR("poweroff popup exec failed");
84 if (sysman_call_predef_action(PREDEF_POWEROFF, 0) < 0) {
85 LOGERR("poweroff exec failed");
90 (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
93 static gboolean longkey_pressed_cb(gpointer data)
96 longkey_timeout_id = 0;
101 static gboolean combination_failed_cb(gpointer data)
103 key_combination = KEY_COMBINATION_STOP;
104 combination_timeout_id = 0;
109 static unsigned long timediff_usec(struct timeval t1, struct timeval t2)
113 udiff = (t2.tv_sec - t1.tv_sec) * USEC_PER_SEC;
114 udiff += (t2.tv_usec - t1.tv_usec);
119 static void stop_key_combination()
121 key_combination = KEY_COMBINATION_STOP;
122 if (combination_timeout_id > 0) {
123 g_source_remove(combination_timeout_id);
124 combination_timeout_id = 0;
128 static int process_power_key(struct input_event *pinput)
132 switch (pinput->value) {
134 if (current_state_in_on() && !cancel_lcdoff &&
135 !(key_combination == KEY_COMBINATION_SCREENCAPTURE)) {
136 check_processes(S_LCDOFF);
137 check_processes(S_LCDDIM);
139 if (!check_holdkey_block(S_LCDOFF) &&
140 !check_holdkey_block(S_LCDDIM)) {
141 delete_condition(S_LCDOFF);
142 delete_condition(S_LCDDIM);
145 recv_data.cond = 0x400;
146 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
149 if (!powerkey_ignored)
153 stop_key_combination();
155 if (longkey_timeout_id > 0) {
156 g_source_remove(longkey_timeout_id);
157 longkey_timeout_id = 0;
161 if (timediff_usec(pressed_time, pinput->time) <
162 POWER_KEY_PRESS_IGNORE_TIME) {
163 LOGINFO("power key double pressed ignored");
164 powerkey_ignored = true;
167 powerkey_ignored = false;
169 LOGINFO("power key pressed");
170 pressed_time.tv_sec = (pinput->time).tv_sec;
171 pressed_time.tv_usec = (pinput->time).tv_usec;
172 if (key_combination == KEY_COMBINATION_STOP) {
173 /* add long key timer */
174 longkey_timeout_id = g_timeout_add_full(
176 LONG_PRESS_INTERVAL / 1000,
177 (GSourceFunc)longkey_pressed_cb,
179 key_combination = KEY_COMBINATION_START;
180 combination_timeout_id = g_timeout_add_full(
182 COMBINATION_INTERVAL / 1000,
183 (GSourceFunc)combination_failed_cb,
185 } else if (key_combination == KEY_COMBINATION_START) {
186 if (combination_timeout_id > 0) {
187 g_source_remove(combination_timeout_id);
188 combination_timeout_id = 0;
190 LOGINFO("capture mode");
191 key_combination = KEY_COMBINATION_SCREENCAPTURE;
195 case KEY_BEING_PRESSED:
196 if (timediff_usec(pressed_time, pinput->time) >
205 static int process_volumedown_key(struct input_event *pinput)
209 if (pinput->value == KEY_PRESSED) {
210 if (key_combination == KEY_COMBINATION_STOP) {
211 key_combination = KEY_COMBINATION_START;
212 combination_timeout_id = g_timeout_add_full(
214 COMBINATION_INTERVAL / 1000,
215 (GSourceFunc)combination_failed_cb,
217 } else if (key_combination == KEY_COMBINATION_START) {
218 if (combination_timeout_id > 0) {
219 g_source_remove(combination_timeout_id);
220 combination_timeout_id = 0;
222 LOGINFO("capture mode");
223 key_combination = KEY_COMBINATION_SCREENCAPTURE;
226 } else if (pinput->value == KEY_RELEASED) {
227 if (key_combination != KEY_COMBINATION_SCREENCAPTURE) {
228 stop_key_combination();
229 if (current_state_in_on())
237 static int check_key(struct input_event *pinput)
241 switch (pinput->code) {
243 ignore = process_power_key(pinput);
246 ignore = process_volumedown_key(pinput);
254 stop_key_combination();
255 if (current_state_in_on())
263 stop_key_combination();
266 stop_key_combination();
273 int check_key_filter(int length, char buf[])
275 struct input_event *pinput;
280 pinput = (struct input_event *)&buf[idx];
281 switch (pinput->type) {
283 ignore = check_key(pinput);
289 if (current_state_in_on())
294 idx += sizeof(struct input_event);
295 if (ignore == true && length <= idx)
297 } while (length > idx);