1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdint.h> 5 #include <dirent.h> 6 #include <fcntl.h> 7 #include <sys/ioctl.h> 8 #include <sys/inotify.h> 9 #include <sys/limits.h> 10 #include <sys/poll.h> 11 #include <linux/input.h> 12 #include <errno.h> 13 #include <cutils/log.h> 14 15 static struct pollfd *ufds; 16 static char **device_names; 17 static int nfds; 18 19 static int open_device(const char *device) 20 { 21 int version; 22 int fd; 23 struct pollfd *new_ufds; 24 char **new_device_names; 25 char name[80]; 26 char location[80]; 27 char idstr[80]; 28 struct input_id id; 29 30 fd = open(device, O_RDWR); 31 if(fd < 0) { 32 return -1; 33 } 34 35 if(ioctl(fd, EVIOCGVERSION, &version)) { 36 return -1; 37 } 38 if(ioctl(fd, EVIOCGID, &id)) { 39 return -1; 40 } 41 name[sizeof(name) - 1] = '\0'; 42 location[sizeof(location) - 1] = '\0'; 43 idstr[sizeof(idstr) - 1] = '\0'; 44 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { 45 //fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno)); 46 name[0] = '\0'; 47 } 48 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) { 49 //fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno)); 50 location[0] = '\0'; 51 } 52 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) { 53 //fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno)); 54 idstr[0] = '\0'; 55 } 56 57 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1)); 58 if(new_ufds == NULL) { 59 fprintf(stderr, "out of memory\n"); 60 return -1; 61 } 62 ufds = new_ufds; 63 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1)); 64 if(new_device_names == NULL) { 65 fprintf(stderr, "out of memory\n"); 66 return -1; 67 } 68 device_names = new_device_names; 69 ufds[nfds].fd = fd; 70 ufds[nfds].events = POLLIN; 71 device_names[nfds] = strdup(device); 72 nfds++; 73 74 return 0; 75 } 76 77 int close_device(const char *device) 78 { 79 int i; 80 for(i = 1; i < nfds; i++) { 81 if(strcmp(device_names[i], device) == 0) { 82 int count = nfds - i - 1; 83 free(device_names[i]); 84 memmove(device_names + i, device_names + i + 1, sizeof(device_names[0]) * count); 85 memmove(ufds + i, ufds + i + 1, sizeof(ufds[0]) * count); 86 nfds--; 87 return 0; 88 } 89 } 90 return -1; 91 } 92 93 static int read_notify(const char *dirname, int nfd) 94 { 95 int res; 96 char devname[PATH_MAX]; 97 char *filename; 98 char event_buf[512]; 99 int event_size; 100 int event_pos = 0; 101 struct inotify_event *event; 102 103 res = read(nfd, event_buf, sizeof(event_buf)); 104 if(res < (int)sizeof(*event)) { 105 if(errno == EINTR) 106 return 0; 107 fprintf(stderr, "could not get event, %s\n", strerror(errno)); 108 return 1; 109 } 110 //printf("got %d bytes of event information\n", res); 111 112 strcpy(devname, dirname); 113 filename = devname + strlen(devname); 114 *filename++ = '/'; 115 116 while(res >= (int)sizeof(*event)) { 117 event = (struct inotify_event *)(event_buf + event_pos); 118 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : ""); 119 if(event->len) { 120 strcpy(filename, event->name); 121 if(event->mask & IN_CREATE) { 122 open_device(devname); 123 } 124 else { 125 close_device(devname); 126 } 127 } 128 event_size = sizeof(*event) + event->len; 129 res -= event_size; 130 event_pos += event_size; 131 } 132 return 0; 133 } 134 135 static int scan_dir(const char *dirname) 136 { 137 char devname[PATH_MAX]; 138 char *filename; 139 DIR *dir; 140 struct dirent *de; 141 dir = opendir(dirname); 142 if(dir == NULL) 143 return -1; 144 strcpy(devname, dirname); 145 filename = devname + strlen(devname); 146 *filename++ = '/'; 147 while((de = readdir(dir))) { 148 if(de->d_name[0] == '.' && 149 (de->d_name[1] == '\0' || 150 (de->d_name[1] == '.' && de->d_name[2] == '\0'))) 151 continue; 152 strcpy(filename, de->d_name); 153 open_device(devname); 154 } 155 closedir(dir); 156 return 0; 157 } 158 159 int init_getevent() 160 { 161 int res; 162 const char *device_path = "/dev/input"; 163 164 nfds = 1; 165 ufds = calloc(1, sizeof(ufds[0])); 166 ufds[0].fd = inotify_init(); 167 ufds[0].events = POLLIN; 168 169 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); 170 if(res < 0) { 171 return 1; 172 } 173 res = scan_dir(device_path); 174 if(res < 0) { 175 return 1; 176 } 177 return 0; 178 } 179 180 void uninit_getevent() 181 { 182 int i; 183 for(i = 0; i < nfds; i++) { 184 close(ufds[i].fd); 185 } 186 free(ufds); 187 ufds = 0; 188 nfds = 0; 189 } 190 191 int get_event(struct input_event* event, int timeout) 192 { 193 int res; 194 int i; 195 int pollres; 196 const char *device_path = "/dev/input"; 197 while(1) { 198 pollres = poll(ufds, nfds, timeout); 199 if (pollres == 0) { 200 return 1; 201 } 202 if(ufds[0].revents & POLLIN) { 203 read_notify(device_path, ufds[0].fd); 204 } 205 for(i = 1; i < nfds; i++) { 206 if(ufds[i].revents) { 207 if(ufds[i].revents & POLLIN) { 208 res = read(ufds[i].fd, event, sizeof(*event)); 209 if(res < (int)sizeof(event)) { 210 fprintf(stderr, "could not get event\n"); 211 return -1; 212 } 213 return 0; 214 } 215 } 216 } 217 } 218 return 0; 219 } 220