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
open_device(const char * device)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
close_device(const char * device)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
read_notify(const char * dirname,int nfd)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
scan_dir(const char * dirname)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
init_getevent()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
uninit_getevent()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
get_event(struct input_event * event,int timeout)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