1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 * Copyright (c) 2007 The Android Open Source Project
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #define _POSIX_C_SOURCE 200809L
34 #include <sys/signalfd.h>
35 #include <sys/timerfd.h>
37 #include <linux/input.h>
39 #include "input-events.h"
43 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
44 #define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
46 #define test_bit(bit, array) \
47 ((array)[(bit) / BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
49 static struct pollfd ev_fds[MAX_INPUTS];
51 static unsigned ev_count = 0;
53 static unsigned signalfd_idx = -1;
54 static unsigned timerfd_idx = -1;
56 #define IS_SIGNAL_EVENT(x) (x == signalfd_idx)
57 #define IS_TIMER_EVENT(x) (x == timerfd_idx)
59 static bool ev_signal_init(void)
63 if (ev_count >= MAX_INPUTS)
67 sigaddset(&mask, SIGINT);
68 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
69 perror("sigprocmask");
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) {
79 signalfd_idx = ev_count++;
84 static bool ev_timer_init(void)
87 struct itimerspec timer_spec = {
88 .it_interval = {TIMER_INTERVAL, 0},
92 if (ev_count >= MAX_INPUTS)
95 fd = timerfd_create(CLOCK_REALTIME, 0);
97 perror("timerfd_create");
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++;
109 static bool ev_input_init(void)
116 dir = opendir("/dev/input");
118 printf("Can't open directory \"/dev/input\".\n");
122 while ((de = readdir(dir))) {
123 unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
125 /* fprintf(stderr,"/dev/input/%s\n", de->d_name);*/
126 if (strncmp(de->d_name, "event", 5))
129 fd = openat(dirfd(dir), de->d_name, O_RDONLY);
133 /* read the evbits of the input device */
134 if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
139 /* TODO: add ability to specify event masks. For now, just
140 * assume that only EV_KEY and EV_REL event types are ever
142 if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
147 ev_fds[ev_count].fd = fd;
148 ev_fds[ev_count].events = POLLIN;
150 if (ev_count == MAX_INPUTS)
156 printf("No input devices found.\n");
165 return ev_input_init() && ev_signal_init() && ev_timer_init();
171 close(ev_fds[--ev_count].fd);
174 static user_action last_action = ACTION_NONE;
175 static time_t event_start = 0;
177 static void ev_input_longpress_check(input_callback callback)
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 */
185 static bool ev_input_process(struct input_event *ev, input_callback callback)
187 user_action action = ACTION_NONE;
189 ev_input_longpress_check(callback);
191 if (!ev) { /* Timeout */
192 callback(ACTION_NONE, ACTION_TYPE_IDLE);
196 if (ev->type == EV_SYN)
198 else if (ev->type == EV_KEY && ev->code <= KEY_MAX) {
202 action = ACTION_DOWN;
210 action = ACTION_CONFIRM;
213 action = ACTION_HOME;
216 action = ACTION_MENU;
219 action = ACTION_BACK;
222 /* printf("Unknown key %d.\n", ev->code);*/
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;
236 callback(action, ev->value == 1 ?
240 } else if (ev->type == EV_REL) { /* Relative event */
242 } else if (ev->type == EV_ABS) { /* Absolute event */
249 static int ev_wait(int timeout)
253 if ((ret = poll(ev_fds, ev_count, timeout)) < 0)
259 bool ev_dispatch(input_callback callback)
264 r = ev_wait(DISPATCH_TIMEOUT);
267 else if (r == 0) /* Timeout */
268 return ev_input_process(NULL, callback);
270 for (n = 0; n < ev_count; n++)
271 if (ev_fds[n].revents & POLLIN) {
273 struct input_event ev;
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)) {
282 if (fdsi.ssi_signo == SIGINT)
287 if (IS_TIMER_EVENT(n)) {
290 r = read(ev_fds[n].fd, &exp, sizeof(exp));
291 if (r != sizeof(exp)) {
296 callback(ACTION_TIMEOUT, ACTION_TYPE_TIMER);
300 r = read(ev_fds[n].fd, &ev, sizeof(ev));
304 if (!ev_input_process(&ev, callback))