1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2007 The Android Open Source Project
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun * You may obtain a copy of the License at
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun * limitations under the License.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <stdio.h>
18*4882a593Smuzhiyun #include <stdlib.h>
19*4882a593Smuzhiyun #include <fcntl.h>
20*4882a593Smuzhiyun #include <dirent.h>
21*4882a593Smuzhiyun #include <sys/epoll.h>
22*4882a593Smuzhiyun #include <unistd.h>
23*4882a593Smuzhiyun #include <string.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <linux/input.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include "minui.h"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define MAX_DEVICES 16
30*4882a593Smuzhiyun #define MAX_MISC_FDS 16
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define BITS_PER_LONG (sizeof(unsigned long) * 8)
33*4882a593Smuzhiyun #define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define test_bit(bit, array) \
36*4882a593Smuzhiyun ((array)[(bit)/BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun struct fd_info {
39*4882a593Smuzhiyun int fd;
40*4882a593Smuzhiyun ev_callback cb;
41*4882a593Smuzhiyun void *data;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static int epollfd;
45*4882a593Smuzhiyun static struct epoll_event polledevents[MAX_DEVICES + MAX_MISC_FDS];
46*4882a593Smuzhiyun static int npolledevents;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static struct fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS];
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun static unsigned ev_count = 0;
51*4882a593Smuzhiyun static unsigned ev_dev_count = 0;
52*4882a593Smuzhiyun static unsigned ev_misc_count = 0;
53*4882a593Smuzhiyun
ev_init(ev_callback input_cb,void * data)54*4882a593Smuzhiyun int ev_init(ev_callback input_cb, void *data)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun DIR *dir;
57*4882a593Smuzhiyun struct dirent *de;
58*4882a593Smuzhiyun int fd;
59*4882a593Smuzhiyun struct epoll_event ev;
60*4882a593Smuzhiyun bool epollctlfail = false;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun epollfd = epoll_create(MAX_DEVICES + MAX_MISC_FDS);
63*4882a593Smuzhiyun if (epollfd == -1)
64*4882a593Smuzhiyun return -1;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun dir = opendir("/dev/input");
67*4882a593Smuzhiyun if (dir != 0) {
68*4882a593Smuzhiyun while ((de = readdir(dir))) {
69*4882a593Smuzhiyun unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun // fprintf(stderr,"/dev/input/%s\n", de->d_name);
72*4882a593Smuzhiyun if (strncmp(de->d_name, "event", 5)) continue;
73*4882a593Smuzhiyun fd = openat(dirfd(dir), de->d_name, O_RDONLY);
74*4882a593Smuzhiyun if (fd < 0) continue;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* read the evbits of the input device */
77*4882a593Smuzhiyun if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
78*4882a593Smuzhiyun close(fd);
79*4882a593Smuzhiyun continue;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* TODO: add ability to specify event masks. For now, just assume
83*4882a593Smuzhiyun * that only EV_KEY and EV_REL event types are ever needed. */
84*4882a593Smuzhiyun if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
85*4882a593Smuzhiyun close(fd);
86*4882a593Smuzhiyun continue;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun ev.events = EPOLLIN | EPOLLWAKEUP;
90*4882a593Smuzhiyun ev.data.ptr = (void *)&ev_fdinfo[ev_count];
91*4882a593Smuzhiyun if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev)) {
92*4882a593Smuzhiyun close(fd);
93*4882a593Smuzhiyun epollctlfail = true;
94*4882a593Smuzhiyun continue;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun ev_fdinfo[ev_count].fd = fd;
98*4882a593Smuzhiyun ev_fdinfo[ev_count].cb = input_cb;
99*4882a593Smuzhiyun ev_fdinfo[ev_count].data = data;
100*4882a593Smuzhiyun ev_count++;
101*4882a593Smuzhiyun ev_dev_count++;
102*4882a593Smuzhiyun if (ev_dev_count == MAX_DEVICES) break;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun if (epollctlfail && !ev_count) {
107*4882a593Smuzhiyun close(epollfd);
108*4882a593Smuzhiyun epollfd = -1;
109*4882a593Smuzhiyun return -1;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun return 0;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
ev_add_fd(int fd,ev_callback cb,void * data)115*4882a593Smuzhiyun int ev_add_fd(int fd, ev_callback cb, void *data)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun struct epoll_event ev;
118*4882a593Smuzhiyun int ret;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (ev_misc_count == MAX_MISC_FDS || cb == NULL)
121*4882a593Smuzhiyun return -1;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun ev.events = EPOLLIN | EPOLLWAKEUP;
124*4882a593Smuzhiyun ev.data.ptr = (void *)&ev_fdinfo[ev_count];
125*4882a593Smuzhiyun ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
126*4882a593Smuzhiyun if (!ret) {
127*4882a593Smuzhiyun ev_fdinfo[ev_count].fd = fd;
128*4882a593Smuzhiyun ev_fdinfo[ev_count].cb = cb;
129*4882a593Smuzhiyun ev_fdinfo[ev_count].data = data;
130*4882a593Smuzhiyun ev_count++;
131*4882a593Smuzhiyun ev_misc_count++;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun return ret;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
ev_get_epollfd(void)137*4882a593Smuzhiyun int ev_get_epollfd(void)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun return epollfd;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
ev_exit(void)142*4882a593Smuzhiyun void ev_exit(void)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun while (ev_count > 0) {
145*4882a593Smuzhiyun close(ev_fdinfo[--ev_count].fd);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun ev_misc_count = 0;
148*4882a593Smuzhiyun ev_dev_count = 0;
149*4882a593Smuzhiyun close(epollfd);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
ev_wait(int timeout)152*4882a593Smuzhiyun int ev_wait(int timeout)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun npolledevents = epoll_wait(epollfd, polledevents, ev_count, timeout);
155*4882a593Smuzhiyun if (npolledevents <= 0)
156*4882a593Smuzhiyun return -1;
157*4882a593Smuzhiyun return 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
ev_dispatch(void)160*4882a593Smuzhiyun void ev_dispatch(void)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun int n;
163*4882a593Smuzhiyun int ret;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun for (n = 0; n < npolledevents; n++) {
166*4882a593Smuzhiyun struct fd_info *fdi = polledevents[n].data.ptr;
167*4882a593Smuzhiyun ev_callback cb = fdi->cb;
168*4882a593Smuzhiyun if (cb)
169*4882a593Smuzhiyun cb(fdi->fd, polledevents[n].events, fdi->data);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
ev_get_input(int fd,uint32_t epevents,struct input_event * ev)173*4882a593Smuzhiyun int ev_get_input(int fd, uint32_t epevents, struct input_event *ev)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun int r;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (epevents & EPOLLIN) {
178*4882a593Smuzhiyun r = read(fd, ev, sizeof(*ev));
179*4882a593Smuzhiyun if (r == sizeof(*ev))
180*4882a593Smuzhiyun return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun return -1;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
ev_sync_key_state(ev_set_key_callback set_key_cb,void * data)185*4882a593Smuzhiyun int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)];
188*4882a593Smuzhiyun unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
189*4882a593Smuzhiyun unsigned i;
190*4882a593Smuzhiyun int ret;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun for (i = 0; i < ev_dev_count; i++) {
193*4882a593Smuzhiyun int code;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun memset(key_bits, 0, sizeof(key_bits));
196*4882a593Smuzhiyun memset(ev_bits, 0, sizeof(ev_bits));
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun ret = ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
199*4882a593Smuzhiyun if (ret < 0 || !test_bit(EV_KEY, ev_bits))
200*4882a593Smuzhiyun continue;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun ret = ioctl(ev_fdinfo[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits);
203*4882a593Smuzhiyun if (ret < 0)
204*4882a593Smuzhiyun continue;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun for (code = 0; code <= KEY_MAX; code++) {
207*4882a593Smuzhiyun if (test_bit(code, key_bits))
208*4882a593Smuzhiyun set_key_cb(code, 1, data);
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun return 0;
213*4882a593Smuzhiyun }
214