xref: /OK3568_Linux_fs/external/recovery/minui/events.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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