d92ea048 |
1 | #include <stdio.h> |
2 | #include <string.h> |
3 | #include <sys/types.h> |
4 | #include <sys/stat.h> |
5 | #include <fcntl.h> |
6 | #include <sys/ioctl.h> |
7 | #include <unistd.h> |
8 | #include <linux/input.h> |
9 | #include <errno.h> |
10 | |
34581c95 |
11 | #include "../common/common.h" |
2258f158 |
12 | #include "../common/input.h" |
34581c95 |
13 | #include "in_evdev.h" |
d92ea048 |
14 | |
d92ea048 |
15 | #define BIT(x) (keybits[(x)/sizeof(keybits[0])/8] & \ |
16 | (1 << ((x) & (sizeof(keybits[0])*8-1)))) |
17 | |
2258f158 |
18 | int in_evdev_probe(void) |
d92ea048 |
19 | { |
20 | int i; |
21 | |
2258f158 |
22 | for (i = 0;; i++) |
d92ea048 |
23 | { |
24 | int u, ret, fd, keybits[KEY_MAX/sizeof(int)]; |
25 | int support = 0, count = 0; |
26 | char name[64]; |
27 | |
28 | snprintf(name, sizeof(name), "/dev/input/event%d", i); |
29 | fd = open(name, O_RDONLY|O_NONBLOCK); |
30 | if (fd == -1) |
31 | break; |
32 | |
33 | /* check supported events */ |
34 | ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support); |
35 | if (ret == -1) { |
2258f158 |
36 | printf("in_evdev: ioctl failed on %s\n", name); |
d92ea048 |
37 | goto skip; |
38 | } |
39 | |
40 | if (!(support & (1 << EV_KEY))) |
41 | goto skip; |
42 | |
43 | ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits); |
44 | if (ret == -1) { |
2258f158 |
45 | printf("in_evdev: ioctl failed on %s\n", name); |
d92ea048 |
46 | goto skip; |
47 | } |
48 | |
d92ea048 |
49 | /* check for interesting keys */ |
50 | for (u = 0; u < KEY_MAX; u++) { |
2258f158 |
51 | if (BIT(u) && u != KEY_POWER && u != KEY_SLEEP) |
d92ea048 |
52 | count++; |
53 | } |
54 | |
55 | if (count == 0) |
56 | goto skip; |
57 | |
2258f158 |
58 | strcpy(name, "evdev:"); |
59 | ioctl(fd, EVIOCGNAME(sizeof(name)-6), name+6); |
60 | printf("in_evdev: found \"%s\" with %d events (type %08x)\n", |
61 | name+6, count, support); |
62 | in_register(name, IN_DRVID_EVDEV, (void *)fd); |
d92ea048 |
63 | continue; |
64 | |
65 | skip: |
66 | close(fd); |
67 | } |
68 | |
d92ea048 |
69 | return 0; |
70 | } |
71 | |
2258f158 |
72 | void in_evdev_free(void *drv_data) |
73 | { |
74 | close((int)drv_data); |
75 | } |
76 | |
77 | int in_evdev_bind_count(void) |
d92ea048 |
78 | { |
2258f158 |
79 | return 512; |
d92ea048 |
80 | } |
81 | |
2258f158 |
82 | int in_evdev_update(void *drv_data, int *binds) |
d92ea048 |
83 | { |
84 | struct input_event ev[16]; |
2258f158 |
85 | int keybits[KEY_MAX/sizeof(int)]; |
86 | int fd = (int)drv_data; |
87 | int result = 0, changed = 0; |
88 | int rd, ret, u; |
d92ea048 |
89 | |
2258f158 |
90 | while (1) { |
91 | rd = read(fd, ev, sizeof(ev)); |
92 | if (rd < (int)sizeof(ev[0])) { |
93 | if (errno != EAGAIN) |
94 | perror("in_evdev: read failed"); |
95 | break; |
d92ea048 |
96 | } |
97 | |
2258f158 |
98 | changed = 1; |
99 | } |
d92ea048 |
100 | |
2258f158 |
101 | /* |
102 | if (!changed) |
103 | return 0; |
104 | */ |
105 | ret = ioctl(fd, EVIOCGKEY(sizeof(keybits)), keybits); |
106 | if (ret == -1) { |
107 | perror("in_evdev: ioctl failed"); |
108 | return 0; |
109 | } |
d92ea048 |
110 | |
2258f158 |
111 | printf("#%d: ", fd); |
112 | for (u = 0; u < KEY_MAX; u++) { |
113 | if (BIT(u)) { |
114 | printf(" %d", u); |
115 | result |= binds[u]; |
d92ea048 |
116 | } |
d92ea048 |
117 | } |
2258f158 |
118 | printf("\n"); |
d92ea048 |
119 | |
120 | return result; |
121 | } |
122 | |
34581c95 |
123 | int in_evdev_update_menu(void **data, int count) |
124 | { |
125 | const int *fds = (const int *)data; |
126 | static int result = 0; |
127 | int i, ret, fdmax = -1; |
128 | int oldresult = result; |
129 | long flags; |
130 | |
131 | /* switch to blocking mode */ |
132 | for (i = 0; i < count; i++) { |
133 | if (fds[i] > fdmax) fdmax = fds[i]; |
134 | |
135 | flags = (long)fcntl(fds[i], F_GETFL); |
136 | if ((int)flags == -1) { |
137 | perror("in_evdev: F_GETFL fcntl failed"); |
138 | continue; |
139 | } |
140 | flags &= ~O_NONBLOCK; |
141 | ret = fcntl(fds[i], F_SETFL, flags); |
142 | if (ret == -1) |
143 | perror("in_evdev: F_SETFL fcntl failed"); |
144 | } |
145 | |
146 | while (1) |
147 | { |
148 | struct input_event ev[64]; |
149 | int fd, rd; |
150 | fd_set fdset; |
151 | |
152 | FD_ZERO(&fdset); |
153 | for (i = 0; i < count; i++) |
154 | FD_SET(fds[i], &fdset); |
155 | |
156 | ret = select(fdmax + 1, &fdset, NULL, NULL, NULL); |
157 | if (ret == -1) |
158 | { |
159 | perror("in_evdev: select failed"); |
160 | sleep(1); |
161 | return 0; |
162 | } |
163 | |
164 | for (i = 0; i < count; i++) |
165 | if (FD_ISSET(fds[i], &fdset)) |
166 | fd = fds[i]; |
167 | |
168 | rd = read(fd, ev, sizeof(ev[0]) * 64); |
169 | if (rd < (int) sizeof(ev[0])) { |
170 | perror("in_evdev: error reading"); |
171 | sleep(1); |
172 | return 0; |
173 | } |
174 | |
175 | #define mapkey(o,k) \ |
176 | case o: \ |
177 | if (ev[i].value) result |= k; \ |
178 | else result &= ~k; \ |
179 | break |
180 | for (i = 0; i < rd / sizeof(ev[0]); i++) |
181 | { |
182 | if (ev[i].type != EV_KEY || ev[i].value < 0 || ev[i].value > 1) |
183 | continue; |
184 | |
185 | switch (ev[i].code) { |
186 | /* keyboards */ |
187 | mapkey(KEY_UP, PBTN_UP); |
188 | mapkey(KEY_DOWN, PBTN_DOWN); |
189 | mapkey(KEY_LEFT, PBTN_LEFT); |
190 | mapkey(KEY_RIGHT, PBTN_RIGHT); |
191 | mapkey(KEY_ENTER, PBTN_EAST); |
192 | mapkey(KEY_ESC, PBTN_SOUTH); |
193 | } |
194 | } |
195 | #undef mapkey |
196 | |
197 | if (oldresult != result) break; |
198 | } |
199 | |
200 | /* switch back to non-blocking mode */ |
201 | for (i = 0; i < count; i++) { |
202 | if (fds[i] > fdmax) fdmax = fds[i]; |
203 | |
204 | flags = (long)fcntl(fds[i], F_GETFL); |
205 | if ((int)flags == -1) { |
206 | perror("in_evdev: F_GETFL fcntl failed"); |
207 | continue; |
208 | } |
209 | flags |= O_NONBLOCK; |
210 | ret = fcntl(fds[i], F_SETFL, flags); |
211 | if (ret == -1) |
212 | perror("in_evdev: F_SETFL fcntl failed"); |
213 | } |
214 | |
215 | return result; |
216 | } |
217 | |