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