2258f158 |
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | |
5 | #include "input.h" |
34581c95 |
6 | #include "../linux/in_evdev.h" |
2258f158 |
7 | |
8 | typedef struct |
9 | { |
10 | int drv_id; |
11 | void *drv_data; |
12 | int *binds; |
13 | char *name; |
14 | int probed:1; |
15 | int ignore:1; |
16 | } in_dev_t; |
17 | |
18 | #define IN_MAX_DEVS 10 |
19 | |
20 | static in_dev_t in_devices[IN_MAX_DEVS]; |
21 | static int in_dev_count = 0; |
22 | |
23 | static int in_bind_count(int drv_id) |
24 | { |
25 | int count = 0; |
595491c4 |
26 | switch (drv_id) { |
27 | case IN_DRVID_EVDEV: |
2258f158 |
28 | count = in_evdev_bind_count(); |
595491c4 |
29 | break; |
30 | } |
2258f158 |
31 | if (count <= 0) |
32 | printf("input: failed to get bind count for drv %d\n", drv_id); |
33 | |
34 | return count; |
35 | } |
36 | |
37 | static int *in_alloc_binds(int drv_id) |
38 | { |
39 | int count, *ret; |
40 | |
41 | count = in_bind_count(drv_id); |
42 | if (count <= 0) { |
43 | printf("input: failed to get bind count for drv %d\n", drv_id); |
44 | return NULL; |
45 | } |
46 | |
47 | ret = malloc(count * sizeof(*ret)); |
48 | return ret; |
49 | } |
50 | |
51 | static void in_free(in_dev_t *dev) |
52 | { |
53 | if (dev->probed) { |
595491c4 |
54 | switch (dev->drv_id) { |
55 | case IN_DRVID_EVDEV: |
2258f158 |
56 | in_evdev_free(dev->drv_data); |
595491c4 |
57 | break; |
58 | } |
2258f158 |
59 | } |
60 | dev->probed = 0; |
61 | dev->drv_data = NULL; |
62 | free(dev->name); |
63 | dev->name = NULL; |
64 | free(dev->binds); |
65 | dev->binds = NULL; |
66 | } |
67 | |
68 | /* to be called by drivers */ |
69 | void in_register(const char *nname, int drv_id, void *drv_data) |
70 | { |
71 | int i, dupe_count = 0, *binds; |
72 | char name[256], *name_end, *tmp; |
73 | |
74 | strncpy(name, nname, sizeof(name)); |
75 | name[sizeof(name)-12] = 0; |
76 | name_end = name + strlen(name); |
77 | |
78 | for (i = 0; i < in_dev_count; i++) |
79 | { |
80 | if (in_devices[i].name == NULL) |
81 | continue; |
82 | if (strcmp(in_devices[i].name, name) == 0) |
83 | { |
84 | if (in_devices[i].probed) { |
85 | dupe_count++; |
86 | sprintf(name_end, " [%d]", dupe_count); |
87 | continue; |
88 | } |
89 | goto update; |
90 | } |
91 | } |
92 | |
93 | if (i >= IN_MAX_DEVS) |
94 | { |
95 | /* try to find unused device */ |
96 | for (i = 0; i < IN_MAX_DEVS; i++) |
97 | if (!in_devices[i].probed) break; |
98 | if (i >= IN_MAX_DEVS) { |
99 | printf("input: too many devices, can't add %s\n", name); |
100 | return; |
101 | } |
102 | in_free(&in_devices[i]); |
103 | } |
104 | |
105 | tmp = strdup(name); |
106 | if (tmp == NULL) |
107 | return; |
108 | |
109 | binds = in_alloc_binds(drv_id); |
110 | if (binds == NULL) { |
111 | free(tmp); |
112 | return; |
113 | } |
114 | |
115 | in_devices[i].name = tmp; |
116 | in_devices[i].binds = binds; |
117 | if (i + 1 > in_dev_count) |
118 | in_dev_count = i + 1; |
119 | |
120 | printf("input: new device #%d \"%s\"\n", i, name); |
121 | update: |
122 | in_devices[i].probed = 1; |
123 | in_devices[i].drv_id = drv_id; |
124 | in_devices[i].drv_data = drv_data; |
125 | } |
126 | |
127 | void in_probe(void) |
128 | { |
129 | int i; |
130 | for (i = 0; i < in_dev_count; i++) |
131 | in_devices[i].probed = 0; |
132 | |
2258f158 |
133 | in_evdev_probe(); |
2258f158 |
134 | |
135 | /* get rid of devs without binds and probes */ |
136 | for (i = 0; i < in_dev_count; i++) { |
137 | if (!in_devices[i].probed && in_devices[i].binds == NULL) { |
138 | in_dev_count--; |
139 | if (i < in_dev_count) { |
140 | free(in_devices[i].name); |
141 | memmove(&in_devices[i], &in_devices[i+1], |
142 | (in_dev_count - i) * sizeof(in_devices[0])); |
143 | } |
144 | } |
145 | } |
146 | } |
147 | |
148 | void in_clear_binds(const char *devname) |
149 | { |
150 | /* int count; |
151 | |
152 | count = in_bind_count(drv_id); |
153 | if (count <= 0) { |
154 | printf("input: failed to get bind count for drv %d\n", dev->drv_id); |
155 | return NULL; |
156 | } |
157 | */ |
158 | } |
159 | |
160 | int in_update(void) |
161 | { |
162 | int i, result = 0; |
163 | |
164 | for (i = 0; i < in_dev_count; i++) { |
165 | if (in_devices[i].probed && in_devices[i].binds != NULL) { |
595491c4 |
166 | switch (in_devices[i].drv_id) { |
167 | case IN_DRVID_EVDEV: |
34581c95 |
168 | result |= in_evdev_update(in_devices[i].drv_data, in_devices[i].binds); |
595491c4 |
169 | break; |
170 | } |
2258f158 |
171 | } |
172 | } |
173 | |
174 | return result; |
175 | } |
176 | |
595491c4 |
177 | static void **in_collect_drvdata(int drv_id, int *count) |
178 | { |
179 | static void *data[IN_MAX_DEVS]; |
180 | int i; |
181 | |
182 | for (*count = i = 0; i < in_dev_count; i++) { |
183 | if (in_devices[i].drv_id == drv_id && in_devices[i].probed) |
184 | data[(*count)++] = in_devices[i].drv_data; |
185 | } |
186 | |
187 | return data; |
188 | } |
189 | |
190 | void in_set_blocking(int is_blocking) |
191 | { |
192 | int i; |
193 | |
194 | for (i = 0; i < in_dev_count; i++) { |
195 | if (in_devices[i].probed) { |
196 | switch (in_devices[i].drv_id) { |
197 | case IN_DRVID_EVDEV: |
198 | in_evdev_set_blocking(in_devices[i].drv_data, is_blocking); |
199 | break; |
200 | } |
201 | } |
202 | } |
203 | } |
204 | |
34581c95 |
205 | /* |
595491c4 |
206 | * update with wait for a press, return keycode |
34581c95 |
207 | * only can use 1 drv here.. |
208 | */ |
595491c4 |
209 | int in_update_keycode(int *dev_id, int *is_down) |
34581c95 |
210 | { |
211 | int result = 0; |
212 | #ifdef IN_EVDEV |
595491c4 |
213 | void **data; |
214 | int i, id = 0, count = 0; |
34581c95 |
215 | |
595491c4 |
216 | data = in_collect_drvdata(IN_DRVID_EVDEV, &count); |
34581c95 |
217 | if (count == 0) { |
218 | /* don't deadlock, fail */ |
219 | printf("input: failed to find devices to read\n"); |
220 | exit(1); |
221 | } |
222 | |
595491c4 |
223 | result = in_evdev_update_keycode(data, count, &id, is_down); |
224 | |
225 | if (dev_id != NULL) { |
226 | for (i = id; i < in_dev_count; i++) { |
227 | if (in_devices[i].drv_data == data[id]) { |
228 | *dev_id = i; |
229 | break; |
230 | } |
231 | } |
232 | } |
34581c95 |
233 | #else |
234 | #error no menu read handlers |
235 | #endif |
236 | |
237 | return result; |
238 | } |
239 | |
595491c4 |
240 | /* |
241 | * same as above, only return bitfield of BTN_* |
242 | */ |
243 | int in_update_menu(void) |
244 | { |
245 | static int keys_active = 0; |
246 | int keys_old = keys_active; |
247 | |
248 | while (1) |
249 | { |
250 | int code, is_down = 0; |
251 | code = in_update_keycode(NULL, &is_down); |
252 | #ifdef IN_EVDEV |
253 | code = in_evdev_menu_translate(code); |
254 | #endif |
255 | if (code == 0) continue; |
256 | |
257 | if (is_down) |
258 | keys_active |= code; |
259 | else |
260 | keys_active &= ~code; |
261 | |
262 | if (keys_old != keys_active) |
263 | break; |
264 | } |
265 | |
266 | return keys_active; |
267 | } |
268 | |
269 | const char *in_get_key_name(int dev_id, int keycode) |
270 | { |
271 | if (dev_id < 0 || dev_id >= IN_MAX_DEVS) |
272 | return "Unkn0"; |
273 | switch (in_devices[dev_id].drv_id) { |
274 | case IN_DRVID_EVDEV: |
275 | return in_evdev_get_key_name(keycode); |
276 | } |
277 | |
278 | return "Unkn1"; |
279 | } |
280 | |
2258f158 |
281 | void in_init(void) |
282 | { |
283 | memset(in_devices, 0, sizeof(in_devices)); |
284 | in_dev_count = 0; |
285 | } |
286 | |
287 | int main(void) |
288 | { |
34581c95 |
289 | int ret; |
290 | |
2258f158 |
291 | in_init(); |
292 | in_probe(); |
293 | |
595491c4 |
294 | in_set_blocking(1); |
295 | |
296 | #if 1 |
297 | while (1) { |
298 | int dev = 0, down; |
299 | ret = in_update_keycode(&dev, &down); |
300 | printf("#%i: %i %i (%s)\n", dev, down, ret, in_get_key_name(dev, ret)); |
301 | } |
302 | #else |
2258f158 |
303 | while (1) { |
34581c95 |
304 | ret = in_update_menu(); |
305 | printf("%08x\n", ret); |
2258f158 |
306 | } |
595491c4 |
307 | #endif |
2258f158 |
308 | |
309 | return 0; |
310 | } |
311 | |