Do default action in RUI mode
[platform/core/system/initrd-recovery.git] / src / librui / input-events.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /*
4  * Copyright (c) 2007 The Android Open Source Project
5  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #define _POSIX_C_SOURCE 200809L
21
22 #include <time.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <dirent.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdbool.h>
32
33 #include <sys/poll.h>
34 #include <sys/signalfd.h>
35 #include <sys/timerfd.h>
36
37 #include <linux/input.h>
38
39 #include "input-events.h"
40
41 #define MAX_INPUTS      32
42
43 #define BITS_PER_LONG           (sizeof(unsigned long) * 8)
44 #define BITS_TO_LONGS(x)        (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
45
46 #define test_bit(bit, array)                                            \
47         ((array)[(bit) / BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
48
49 static struct pollfd ev_fds[MAX_INPUTS];
50
51 static unsigned ev_count = 0;
52
53 static unsigned signalfd_idx = -1;
54 static unsigned timerfd_idx = -1;
55
56 #define IS_SIGNAL_EVENT(x) (x == signalfd_idx)
57 #define IS_TIMER_EVENT(x) (x == timerfd_idx)
58
59 static bool ev_signal_init(void)
60 {
61         sigset_t mask;
62
63         if (ev_count >= MAX_INPUTS)
64                 return false;
65
66         sigemptyset(&mask);
67         sigaddset(&mask, SIGINT);
68         if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
69                 perror("sigprocmask");
70                 return false;
71         }
72
73         ev_fds[ev_count].fd = signalfd(-1, &mask, 0);
74         ev_fds[ev_count].events = POLLIN;
75         if (ev_fds[ev_count].fd == -1) {
76                 perror("signalfd");
77                 return false;
78         }
79         signalfd_idx = ev_count++;
80
81         return true;
82 }
83
84 static bool ev_timer_init(void)
85 {
86         int fd;
87         struct itimerspec timer_spec = {
88                 .it_interval = {TIMER_INTERVAL, 0},
89                 .it_value = {0, 1},
90         };
91
92         if (ev_count >= MAX_INPUTS)
93                 return false;
94
95         fd = timerfd_create(CLOCK_REALTIME, 0);
96         if (fd < 0) {
97                 perror("timerfd_create");
98                 return false;
99         }
100
101         timerfd_settime(fd, 0, &timer_spec, NULL);
102         ev_fds[ev_count].fd = fd;
103         ev_fds[ev_count].events = POLLIN;
104         timerfd_idx = ev_count++;
105
106         return true;
107 }
108
109 static bool ev_input_init(void)
110 {
111         DIR *dir;
112         struct dirent *de;
113         int fd;
114         int t = ev_count;
115
116         dir = opendir("/dev/input");
117         if (!dir) {
118                 printf("Can't open directory \"/dev/input\".\n");
119                 return false;
120         }
121
122         while ((de = readdir(dir))) {
123                 unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
124
125                 /*              fprintf(stderr,"/dev/input/%s\n", de->d_name);*/
126                 if (strncmp(de->d_name, "event", 5))
127                         continue;
128
129                 fd = openat(dirfd(dir), de->d_name, O_RDONLY);
130                 if (fd < 0)
131                         continue;
132
133                 /* read the evbits of the input device */
134                 if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
135                         close(fd);
136                         continue;
137                 }
138
139                 /* TODO: add ability to specify event masks. For now, just
140                  * assume that only EV_KEY and EV_REL event types are ever
141                  * needed. */
142                 if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
143                         close(fd);
144                         continue;
145                 }
146
147                 ev_fds[ev_count].fd = fd;
148                 ev_fds[ev_count].events = POLLIN;
149                 ev_count++;
150                 if (ev_count == MAX_INPUTS)
151                         break;
152         }
153
154         closedir(dir);
155         if (ev_count == t) {
156                 printf("No input devices found.\n");
157                 return false;
158         }
159
160         return true;
161 }
162
163 bool ev_init(void)
164 {
165         return ev_input_init() && ev_signal_init() && ev_timer_init();
166 }
167
168 void ev_exit(void)
169 {
170         while (ev_count > 0)
171                 close(ev_fds[--ev_count].fd);
172 }
173
174 static user_action last_action = ACTION_NONE;
175 static time_t event_start = 0;
176
177 static void ev_input_longpress_check(input_callback callback)
178 {
179         if (event_start && time(NULL) - event_start >= LONGPRESS_TIME) {
180                 callback(last_action, ACTION_TYPE_LONGPRESS);
181                 event_start = time(NULL); /* Restarting the event */
182         }
183 }
184
185 static bool ev_input_process(struct input_event *ev, input_callback callback)
186 {
187         user_action action = ACTION_NONE;
188
189         ev_input_longpress_check(callback);
190
191         if (!ev) { /* Timeout */
192                 callback(ACTION_NONE, ACTION_TYPE_IDLE);
193                 return true;
194         }
195
196         if (ev->type == EV_SYN)
197                 return true;
198         else if (ev->type == EV_KEY && ev->code <= KEY_MAX) {
199                 switch (ev->code) {
200                 case KEY_DOWN:
201                 case KEY_VOLUMEDOWN:
202                         action = ACTION_DOWN;
203                         break;
204                 case KEY_UP:
205                 case KEY_VOLUMEUP:
206                         action = ACTION_UP;
207                         break;
208                 case KEY_ENTER:
209                 case KEY_POWER:
210                         action = ACTION_CONFIRM;
211                         break;
212                 case KEY_MENU:
213                         action = ACTION_HOME;
214                         break;
215                 case KEY_PHONE:
216                         action = ACTION_MENU;
217                         break;
218                 case KEY_BACK:
219                         action = ACTION_BACK;
220                         break;
221                 default:
222                         /*                              printf("Unknown key %d.\n", ev->code);*/
223                         break;
224                 }
225
226                 if (action != ACTION_NONE) {
227                         if (ev->value == 1) {
228                                 last_action = action;
229                                 event_start = time(NULL);
230                         } else if (action == last_action) {
231                                 last_action = ACTION_NONE;
232                                 event_start = 0;
233                         }
234
235                         if (callback)
236                                 callback(action, ev->value == 1 ?
237                                                 ACTION_TYPE_BEGIN :
238                                                 ACTION_TYPE_END);
239                 }
240         } else if (ev->type == EV_REL) { /* Relative event */
241
242         } else if (ev->type == EV_ABS) { /* Absolute event */
243
244         }
245
246         return true;
247 }
248
249 static int ev_wait(int timeout)
250 {
251         int ret;
252
253         if ((ret = poll(ev_fds, ev_count, timeout)) < 0)
254                 perror("poll()");
255
256         return ret;
257 }
258
259 bool ev_dispatch(input_callback callback)
260 {
261         int r;
262         unsigned n;
263
264         r = ev_wait(DISPATCH_TIMEOUT);
265         if (r < 0)
266                 return false;
267         else if (r == 0) /* Timeout */
268                 return ev_input_process(NULL, callback);
269
270         for (n = 0; n < ev_count; n++)
271                 if (ev_fds[n].revents & POLLIN) {
272                         int r;
273                         struct input_event ev;
274
275                         if (IS_SIGNAL_EVENT(n)) {   /* signalfd */
276                                 struct signalfd_siginfo fdsi;
277                                 r = read(ev_fds[n].fd, &fdsi, sizeof(fdsi));
278                                 if (r != sizeof(fdsi)) {
279                                         perror("read");
280                                         return false;
281                                 }
282                                 if (fdsi.ssi_signo == SIGINT)
283                                         return false;
284                                 continue;
285                         }
286
287                         if (IS_TIMER_EVENT(n)) {
288                                 uint64_t exp;
289
290                                 r = read(ev_fds[n].fd, &exp, sizeof(exp));
291                                 if (r != sizeof(exp)) {
292                                         perror("read");
293                                         return false;
294                                 }
295
296                                 callback(ACTION_TIMEOUT, ACTION_TYPE_TIMER);
297                                 continue;
298                         }
299
300                         r = read(ev_fds[n].fd, &ev, sizeof(ev));
301                         if (r != sizeof(ev))
302                                 continue;
303
304                         if (!ev_input_process(&ev, callback))
305                                 return false;
306                 }
307
308         return true;
309 }