Commit | Line | Data |
---|---|---|
b7c7cd5d | 1 | /* |
c4334e00 | 2 | * (C) GraÅžvydas "notaz" Ignotas, 2008-2011 |
b7c7cd5d | 3 | * |
4 | * This work is licensed under the terms of any of these licenses | |
5 | * (at your option): | |
6 | * - GNU GPL, version 2 or later. | |
7 | * - GNU LGPL, version 2.1 or later. | |
f89d8471 | 8 | * - MAME license. |
b7c7cd5d | 9 | * See the COPYING file in the top-level directory. |
10 | */ | |
11 | ||
2258f158 | 12 | #include <stdio.h> |
13 | #include <stdlib.h> | |
14 | #include <string.h> | |
15 | ||
16 | #include "input.h" | |
4ab30ad4 | 17 | #include "plat.h" |
7ee5c389 | 18 | #include "lprintf.h" |
972151fc | 19 | |
2258f158 | 20 | typedef struct |
21 | { | |
22 | int drv_id; | |
7f022a8d | 23 | int drv_fd_hnd; |
2258f158 | 24 | void *drv_data; |
2258f158 | 25 | char *name; |
8e77275e | 26 | int key_count; |
27 | int *binds; /* total = key_count * bindtypes * 2 */ | |
4acbd7fe | 28 | int *kbd_binds; /* total = key_count */ |
e9b29264 | 29 | const char * const *key_names; |
30 | unsigned int probed:1; | |
31 | unsigned int does_combos:1; | |
2258f158 | 32 | } in_dev_t; |
33 | ||
c4334e00 | 34 | static in_drv_t *in_drivers; |
2258f158 | 35 | static in_dev_t in_devices[IN_MAX_DEVS]; |
c4334e00 | 36 | static int in_driver_count = 0; |
23fb16c8 | 37 | static int in_dev_count = 0; /* probed + bind devices */ |
13b692eb | 38 | static int in_have_async_devs = 0; |
c4334e00 | 39 | static int in_probe_dev_id; |
82abf46f | 40 | static int menu_key_state = 0; |
41 | static int menu_last_used_dev = 0; | |
e0bf7946 | 42 | static int menu_key_prev = 0; |
e0bf7946 | 43 | static int menu_key_repeat = 0; |
2258f158 | 44 | |
c4334e00 | 45 | #define DRV(id) in_drivers[id] |
da767bd5 | 46 | |
13b692eb | 47 | |
8e77275e | 48 | static int *in_alloc_binds(int drv_id, int key_count) |
2258f158 | 49 | { |
215aec76 | 50 | const struct in_default_bind *defbinds; |
9fec8a91 | 51 | int *binds, *binds_d; |
215aec76 | 52 | int i; |
2258f158 | 53 | |
8e77275e | 54 | binds = calloc(key_count * IN_BINDTYPE_COUNT * 2, sizeof(binds[0])); |
da767bd5 | 55 | if (binds == NULL) |
56 | return NULL; | |
57 | ||
9fec8a91 | 58 | binds_d = binds + key_count * IN_BINDTYPE_COUNT; |
59 | ||
60 | /* always have a copy of defbinds */ | |
215aec76 | 61 | defbinds = DRV(drv_id).defbinds; |
62 | if (defbinds != NULL) { | |
63 | for (i = 0; ; i++) { | |
21604a04 | 64 | if (defbinds[i].code == 0 && defbinds[i].btype == 0 |
7ceadd99 | 65 | && defbinds[i].bit == 0) |
215aec76 | 66 | break; |
9fec8a91 | 67 | |
c3031dbf | 68 | binds_d[IN_BIND_OFFS(defbinds[i].code, defbinds[i].btype)] |= |
69 | 1 << defbinds[i].bit; | |
215aec76 | 70 | } |
215aec76 | 71 | } |
da767bd5 | 72 | |
73 | return binds; | |
2258f158 | 74 | } |
75 | ||
4acbd7fe | 76 | static int *in_alloc_kbd_binds(int drv_id, int key_count) |
b047d2e2 | 77 | { |
78 | const struct in_default_bind *defbinds; | |
79 | int *binds; | |
80 | int i; | |
81 | ||
82 | binds = calloc(key_count * 2, sizeof(binds[0])); | |
83 | if (binds == NULL) | |
84 | return NULL; | |
85 | ||
86 | /* always have a copy of defbinds */ | |
4acbd7fe | 87 | defbinds = DRV(drv_id).kbd_binds; |
b047d2e2 | 88 | if (defbinds != NULL) { |
89 | for (i = 0; ; i++) { | |
90 | if (defbinds[i].code == 0 && defbinds[i].btype == 0 | |
91 | && defbinds[i].bit == 0) | |
92 | break; | |
93 | ||
94 | binds[defbinds[i].code] = defbinds[i].bit; | |
95 | } | |
96 | } | |
97 | ||
98 | return binds; | |
99 | } | |
100 | ||
23fb16c8 | 101 | static void in_unprobe(in_dev_t *dev) |
2258f158 | 102 | { |
da767bd5 | 103 | if (dev->probed) |
104 | DRV(dev->drv_id).free(dev->drv_data); | |
2258f158 | 105 | dev->probed = 0; |
106 | dev->drv_data = NULL; | |
23fb16c8 | 107 | } |
108 | ||
109 | static void in_free(in_dev_t *dev) | |
110 | { | |
111 | in_unprobe(dev); | |
2258f158 | 112 | free(dev->name); |
113 | dev->name = NULL; | |
114 | free(dev->binds); | |
115 | dev->binds = NULL; | |
116 | } | |
117 | ||
13b692eb | 118 | /* to be called by drivers |
119 | * async devices must set drv_fd_hnd to -1 */ | |
c4334e00 | 120 | void in_register(const char *nname, int drv_fd_hnd, void *drv_data, |
e9b29264 | 121 | int key_count, const char * const *key_names, int combos) |
2258f158 | 122 | { |
4acbd7fe | 123 | int i, ret, dupe_count = 0, *binds, *kbd_binds; |
2258f158 | 124 | char name[256], *name_end, *tmp; |
125 | ||
126 | strncpy(name, nname, sizeof(name)); | |
127 | name[sizeof(name)-12] = 0; | |
128 | name_end = name + strlen(name); | |
129 | ||
130 | for (i = 0; i < in_dev_count; i++) | |
131 | { | |
132 | if (in_devices[i].name == NULL) | |
133 | continue; | |
134 | if (strcmp(in_devices[i].name, name) == 0) | |
135 | { | |
136 | if (in_devices[i].probed) { | |
137 | dupe_count++; | |
138 | sprintf(name_end, " [%d]", dupe_count); | |
139 | continue; | |
140 | } | |
141 | goto update; | |
142 | } | |
143 | } | |
144 | ||
145 | if (i >= IN_MAX_DEVS) | |
146 | { | |
147 | /* try to find unused device */ | |
148 | for (i = 0; i < IN_MAX_DEVS; i++) | |
149 | if (!in_devices[i].probed) break; | |
150 | if (i >= IN_MAX_DEVS) { | |
7ee5c389 | 151 | lprintf("input: too many devices, can't add %s\n", name); |
2258f158 | 152 | return; |
153 | } | |
154 | in_free(&in_devices[i]); | |
155 | } | |
156 | ||
157 | tmp = strdup(name); | |
158 | if (tmp == NULL) | |
159 | return; | |
160 | ||
c4334e00 | 161 | binds = in_alloc_binds(in_probe_dev_id, key_count); |
2258f158 | 162 | if (binds == NULL) { |
163 | free(tmp); | |
164 | return; | |
165 | } | |
4acbd7fe | 166 | kbd_binds = in_alloc_kbd_binds(in_probe_dev_id, key_count); |
167 | if (kbd_binds == NULL) { | |
b047d2e2 | 168 | free(tmp); |
169 | return; | |
170 | } | |
2258f158 | 171 | |
9fec8a91 | 172 | memcpy(binds, binds + key_count * IN_BINDTYPE_COUNT, |
173 | sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT); | |
174 | ||
2258f158 | 175 | in_devices[i].name = tmp; |
176 | in_devices[i].binds = binds; | |
4acbd7fe | 177 | in_devices[i].kbd_binds = kbd_binds; |
8e77275e | 178 | in_devices[i].key_count = key_count; |
2258f158 | 179 | if (i + 1 > in_dev_count) |
180 | in_dev_count = i + 1; | |
181 | ||
7ee5c389 | 182 | lprintf("input: new device #%d \"%s\"\n", i, name); |
2258f158 | 183 | update: |
184 | in_devices[i].probed = 1; | |
2c600560 | 185 | in_devices[i].does_combos = combos; |
c4334e00 | 186 | in_devices[i].drv_id = in_probe_dev_id; |
7f022a8d | 187 | in_devices[i].drv_fd_hnd = drv_fd_hnd; |
e9b29264 | 188 | in_devices[i].key_names = key_names; |
2258f158 | 189 | in_devices[i].drv_data = drv_data; |
da767bd5 | 190 | |
191 | if (in_devices[i].binds != NULL) { | |
c4334e00 | 192 | ret = DRV(in_probe_dev_id).clean_binds(drv_data, in_devices[i].binds, |
8e77275e | 193 | in_devices[i].binds + key_count * IN_BINDTYPE_COUNT); |
da767bd5 | 194 | if (ret == 0) { |
195 | /* no useable binds */ | |
196 | free(in_devices[i].binds); | |
197 | in_devices[i].binds = NULL; | |
198 | } | |
199 | } | |
2258f158 | 200 | } |
201 | ||
8e77275e | 202 | /* key combo handling, to be called by drivers that support it. |
203 | * Only care about IN_BINDTYPE_EMU */ | |
204 | void in_combos_find(const int *binds, int last_key, int *combo_keys, int *combo_acts) | |
2c600560 | 205 | { |
206 | int act, u; | |
207 | ||
208 | *combo_keys = *combo_acts = 0; | |
209 | for (act = 0; act < sizeof(binds[0]) * 8; act++) | |
210 | { | |
211 | int keyc = 0; | |
212 | for (u = 0; u <= last_key; u++) | |
8e77275e | 213 | if (binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & (1 << act)) |
2c600560 | 214 | keyc++; |
215 | ||
216 | if (keyc > 1) | |
217 | { | |
218 | // loop again and mark those keys and actions as combo | |
219 | for (u = 0; u <= last_key; u++) | |
220 | { | |
8e77275e | 221 | if (binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & (1 << act)) { |
2c600560 | 222 | *combo_keys |= 1 << u; |
223 | *combo_acts |= 1 << act; | |
224 | } | |
225 | } | |
226 | } | |
227 | } | |
228 | } | |
229 | ||
8e77275e | 230 | int in_combos_do(int keys, const int *binds, int last_key, int combo_keys, int combo_acts) |
2c600560 | 231 | { |
232 | int i, ret = 0; | |
233 | ||
234 | for (i = 0; i <= last_key; i++) | |
235 | { | |
8e77275e | 236 | int acts, acts_c, u; |
237 | ||
2c600560 | 238 | if (!(keys & (1 << i))) |
239 | continue; | |
240 | ||
8e77275e | 241 | acts = binds[IN_BIND_OFFS(i, IN_BINDTYPE_EMU)]; |
2c600560 | 242 | if (!acts) |
243 | continue; | |
244 | ||
8e77275e | 245 | if (!(combo_keys & (1 << i))) { |
2c600560 | 246 | ret |= acts; |
8e77275e | 247 | continue; |
248 | } | |
249 | ||
250 | acts_c = acts & combo_acts; | |
251 | u = last_key; | |
252 | if (acts_c) { | |
253 | // let's try to find the other one | |
254 | for (u = i + 1; u <= last_key; u++) | |
255 | if ( (keys & (1 << u)) && (binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & acts_c) ) { | |
256 | ret |= acts_c & binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)]; | |
257 | keys &= ~((1 << i) | (1 << u)); | |
258 | break; | |
259 | } | |
260 | } | |
261 | // add non-combo actions if combo ones were not found | |
262 | if (u >= last_key) | |
263 | ret |= acts & ~combo_acts; | |
2c600560 | 264 | } |
265 | ||
266 | return ret; | |
267 | } | |
268 | ||
2258f158 | 269 | void in_probe(void) |
270 | { | |
271 | int i; | |
13b692eb | 272 | |
273 | in_have_async_devs = 0; | |
23fb16c8 | 274 | menu_key_state = 0; |
275 | menu_last_used_dev = 0; | |
276 | ||
277 | for (i = 0; i < in_dev_count; i++) | |
278 | in_unprobe(&in_devices[i]); | |
2258f158 | 279 | |
c4334e00 | 280 | for (i = 0; i < in_driver_count; i++) { |
281 | in_probe_dev_id = i; | |
c19e28f6 | 282 | in_drivers[i].probe(&DRV(i)); |
c4334e00 | 283 | } |
2258f158 | 284 | |
285 | /* get rid of devs without binds and probes */ | |
286 | for (i = 0; i < in_dev_count; i++) { | |
287 | if (!in_devices[i].probed && in_devices[i].binds == NULL) { | |
288 | in_dev_count--; | |
289 | if (i < in_dev_count) { | |
290 | free(in_devices[i].name); | |
291 | memmove(&in_devices[i], &in_devices[i+1], | |
292 | (in_dev_count - i) * sizeof(in_devices[0])); | |
293 | } | |
13b692eb | 294 | |
295 | continue; | |
2258f158 | 296 | } |
13b692eb | 297 | |
298 | if (in_devices[i].probed && in_devices[i].drv_fd_hnd == -1) | |
299 | in_have_async_devs = 1; | |
2258f158 | 300 | } |
13b692eb | 301 | |
302 | if (in_have_async_devs) | |
7ee5c389 | 303 | lprintf("input: async-only devices detected..\n"); |
e9b29264 | 304 | |
305 | in_debug_dump(); | |
2258f158 | 306 | } |
307 | ||
7f022a8d | 308 | /* async update */ |
8e77275e | 309 | int in_update(int *result) |
2258f158 | 310 | { |
8e77275e | 311 | int i, ret = 0; |
2258f158 | 312 | |
313 | for (i = 0; i < in_dev_count; i++) { | |
906bdc9f | 314 | in_dev_t *dev = &in_devices[i]; |
c4334e00 | 315 | if (dev->probed && dev->binds != NULL) |
316 | ret |= DRV(dev->drv_id).update(dev->drv_data, dev->binds, result); | |
2258f158 | 317 | } |
318 | ||
8e77275e | 319 | return ret; |
2258f158 | 320 | } |
321 | ||
4acbd7fe | 322 | int in_update_kbd(int *result) |
b047d2e2 | 323 | { |
324 | int i, ret = 0; | |
325 | ||
326 | for (i = 0; i < in_dev_count; i++) { | |
327 | in_dev_t *dev = &in_devices[i]; | |
328 | if (dev->probed && dev->binds != NULL) | |
842f0c7c | 329 | ret += DRV(dev->drv_id).update_kbd(dev->drv_data, dev->kbd_binds, result+ret); |
b047d2e2 | 330 | } |
331 | ||
332 | return ret; | |
333 | } | |
334 | ||
df77913a | 335 | static in_dev_t *get_dev(int dev_id) |
336 | { | |
337 | if (dev_id < 0 || dev_id >= IN_MAX_DEVS) | |
338 | return NULL; | |
339 | ||
340 | return &in_devices[dev_id]; | |
341 | } | |
342 | ||
343 | int in_update_analog(int dev_id, int axis_id, int *result) | |
344 | { | |
345 | in_dev_t *dev = get_dev(dev_id); | |
346 | ||
347 | if (dev == NULL || !dev->probed) | |
348 | return -1; | |
349 | ||
350 | return DRV(dev->drv_id).update_analog(dev->drv_data, axis_id, result); | |
351 | } | |
352 | ||
b020891a | 353 | int in_update_pointer(int dev_id, int id, int *result) |
354 | { | |
355 | in_dev_t *dev = get_dev(dev_id); | |
356 | ||
357 | if (dev == NULL || !dev->probed) | |
358 | return -1; | |
359 | ||
360 | return DRV(dev->drv_id).update_pointer(dev->drv_data, id, result); | |
361 | } | |
362 | ||
13b692eb | 363 | static int in_update_kc_async(int *dev_id_out, int *is_down_out, int timeout_ms) |
364 | { | |
13b692eb | 365 | int i, is_down, result; |
4ab30ad4 | 366 | unsigned int ticks; |
13b692eb | 367 | |
4ab30ad4 | 368 | ticks = plat_get_ticks_ms(); |
13b692eb | 369 | |
370 | while (1) | |
371 | { | |
372 | for (i = 0; i < in_dev_count; i++) { | |
373 | in_dev_t *d = &in_devices[i]; | |
374 | if (!d->probed) | |
375 | continue; | |
376 | ||
377 | result = DRV(d->drv_id).update_keycode(d->drv_data, &is_down); | |
378 | if (result == -1) | |
379 | continue; | |
380 | ||
381 | if (dev_id_out) | |
382 | *dev_id_out = i; | |
383 | if (is_down_out) | |
384 | *is_down_out = is_down; | |
385 | return result; | |
386 | } | |
387 | ||
4ab30ad4 | 388 | if (timeout_ms >= 0 && (int)(plat_get_ticks_ms() - ticks) > timeout_ms) |
389 | break; | |
13b692eb | 390 | |
4ab30ad4 | 391 | plat_sleep_ms(10); |
13b692eb | 392 | } |
393 | ||
394 | return -1; | |
395 | } | |
7f022a8d | 396 | |
34581c95 | 397 | /* |
13b692eb | 398 | * wait for a press, always return some keycode or -1 on timeout or error |
34581c95 | 399 | */ |
9934732a | 400 | int in_update_keycode(int *dev_id_out, int *is_down_out, char *charcode, int timeout_ms) |
34581c95 | 401 | { |
4ab30ad4 | 402 | int result = -1, dev_id = 0, is_down, result_menu; |
7f022a8d | 403 | int fds_hnds[IN_MAX_DEVS]; |
404 | int i, ret, count = 0; | |
7fd581f4 | 405 | in_drv_t *drv = NULL; |
4ab30ad4 | 406 | unsigned int ticks; |
7f022a8d | 407 | |
13b692eb | 408 | if (in_have_async_devs) { |
409 | result = in_update_kc_async(&dev_id, &is_down, timeout_ms); | |
65f8fc5e | 410 | if (result == -1) { |
65f8fc5e | 411 | // no key up event for RDRAW, clear to avoid key repeat |
412 | menu_key_state &= ~PBTN_RDRAW; | |
13b692eb | 413 | return -1; |
65f8fc5e | 414 | } |
13b692eb | 415 | drv = &DRV(in_devices[dev_id].drv_id); |
416 | goto finish; | |
417 | } | |
418 | ||
4ab30ad4 | 419 | ticks = plat_get_ticks_ms(); |
420 | ||
7f022a8d | 421 | for (i = 0; i < in_dev_count; i++) { |
422 | if (in_devices[i].probed) | |
423 | fds_hnds[count++] = in_devices[i].drv_fd_hnd; | |
424 | } | |
34581c95 | 425 | |
426 | if (count == 0) { | |
427 | /* don't deadlock, fail */ | |
7ee5c389 | 428 | lprintf("input: failed to find devices to read\n"); |
34581c95 | 429 | exit(1); |
430 | } | |
431 | ||
4ab30ad4 | 432 | while (1) |
7f022a8d | 433 | { |
4ab30ad4 | 434 | ret = plat_wait_event(fds_hnds, count, timeout_ms); |
435 | if (ret < 0) | |
436 | break; | |
7f022a8d | 437 | |
4ab30ad4 | 438 | for (i = 0; i < in_dev_count; i++) { |
439 | if (in_devices[i].drv_fd_hnd == ret) { | |
440 | dev_id = i; | |
441 | break; | |
442 | } | |
7f022a8d | 443 | } |
444 | ||
4ab30ad4 | 445 | drv = &DRV(in_devices[dev_id].drv_id); |
446 | result = drv->update_keycode(in_devices[dev_id].drv_data, &is_down); | |
4ab30ad4 | 447 | if (result >= 0) |
906bdc9f | 448 | break; |
4ab30ad4 | 449 | |
23fb16c8 | 450 | if (result == -2) { |
451 | lprintf("input: \"%s\" errored out, removing.\n", in_devices[dev_id].name); | |
452 | in_unprobe(&in_devices[dev_id]); | |
453 | break; | |
454 | } | |
455 | ||
4ab30ad4 | 456 | if (timeout_ms >= 0) { |
457 | unsigned int ticks2 = plat_get_ticks_ms(); | |
458 | timeout_ms -= ticks2 - ticks; | |
459 | ticks = ticks2; | |
460 | if (timeout_ms <= 0) | |
461 | break; | |
595491c4 | 462 | } |
463 | } | |
7f022a8d | 464 | |
74065be8 | 465 | if (result < 0) |
4ab30ad4 | 466 | return -1; |
13b692eb | 467 | finish: |
906bdc9f | 468 | /* keep track of menu key state, to allow mixing |
fce20e73 | 469 | * in_update_keycode() and in_menu_wait_any() calls */ |
9934732a | 470 | result_menu = drv->menu_translate(in_devices[dev_id].drv_data, result, charcode); |
906bdc9f | 471 | if (result_menu != 0) { |
472 | if (is_down) | |
473 | menu_key_state |= result_menu; | |
474 | else | |
475 | menu_key_state &= ~result_menu; | |
476 | } | |
477 | ||
478 | if (dev_id_out != NULL) | |
479 | *dev_id_out = dev_id; | |
480 | if (is_down_out != NULL) | |
481 | *is_down_out = is_down; | |
34581c95 | 482 | return result; |
483 | } | |
484 | ||
fce20e73 | 485 | /* same as above, only return bitfield of PBTN_* */ |
9934732a | 486 | int in_menu_wait_any(char *charcode, int timeout_ms) |
595491c4 | 487 | { |
906bdc9f | 488 | int keys_old = menu_key_state; |
9089665c | 489 | int ret; |
e0bf7946 | 490 | int dev_id = 0; |
595491c4 | 491 | |
e0bf7946 | 492 | menu_key_prev = menu_key_state; |
493 | ||
494 | in_update_keycode(&dev_id, NULL, charcode, timeout_ms); | |
595491c4 | 495 | |
1eb399bd | 496 | if (keys_old != menu_key_state) |
497 | menu_last_used_dev = dev_id; | |
595491c4 | 498 | |
9089665c | 499 | ret = menu_key_state; |
e0bf7946 | 500 | if (ret == 0) |
7b3f69a4 | 501 | menu_key_prev = 0; |
e0bf7946 | 502 | |
9089665c | 503 | return ret; |
595491c4 | 504 | } |
505 | ||
fce20e73 | 506 | /* wait for menu input, do autorepeat */ |
9934732a | 507 | int in_menu_wait(int interesting, char *charcode, int autorep_delay_ms) |
fce20e73 | 508 | { |
e0bf7946 | 509 | int ret, wait = 450; |
fce20e73 | 510 | |
e0bf7946 | 511 | if (menu_key_repeat) |
049a6b3e | 512 | wait = autorep_delay_ms; |
fce20e73 | 513 | |
e0bf7946 | 514 | /* wait until either key repeat or a new key has been pressed */ |
bededcb4 | 515 | interesting |= PBTN_RDRAW; |
e0bf7946 | 516 | do { |
517 | ret = in_menu_wait_any(charcode, wait); | |
518 | if (ret == 0 || ret != menu_key_prev) | |
519 | menu_key_repeat = 0; | |
520 | else | |
521 | menu_key_repeat++; | |
522 | wait = -1; | |
e0bf7946 | 523 | } while (!(ret & interesting)); |
fce20e73 | 524 | |
6c263f30 | 525 | /* we don't need diagonals in menus */ |
e0bf7946 | 526 | if (ret & (PBTN_UP|PBTN_DOWN)) ret &= ~(PBTN_LEFT|PBTN_RIGHT); |
fce20e73 | 527 | |
528 | return ret; | |
529 | } | |
530 | ||
da767bd5 | 531 | const int *in_get_dev_binds(int dev_id) |
532 | { | |
df77913a | 533 | in_dev_t *dev = get_dev(dev_id); |
da767bd5 | 534 | |
df77913a | 535 | return dev ? dev->binds : NULL; |
da767bd5 | 536 | } |
537 | ||
4acbd7fe | 538 | const int *in_get_dev_kbd_binds(int dev_id) |
e0d65e94 | 539 | { |
540 | in_dev_t *dev = get_dev(dev_id); | |
541 | ||
4acbd7fe | 542 | return dev ? dev->kbd_binds : NULL; |
e0d65e94 | 543 | } |
544 | ||
da767bd5 | 545 | const int *in_get_dev_def_binds(int dev_id) |
546 | { | |
df77913a | 547 | in_dev_t *dev = get_dev(dev_id); |
548 | if (dev == NULL) | |
da767bd5 | 549 | return NULL; |
9fec8a91 | 550 | if (dev->binds == NULL) |
551 | return NULL; | |
da767bd5 | 552 | |
df77913a | 553 | return dev->binds + dev->key_count * IN_BINDTYPE_COUNT; |
da767bd5 | 554 | } |
555 | ||
4acbd7fe | 556 | const int *in_get_dev_kbd_def_binds(int dev_id) |
e0d65e94 | 557 | { |
558 | in_dev_t *dev = get_dev(dev_id); | |
559 | if (dev == NULL) | |
560 | return NULL; | |
561 | if (dev->binds == NULL) | |
562 | return NULL; | |
563 | ||
4acbd7fe | 564 | return dev->kbd_binds; |
e0d65e94 | 565 | } |
566 | ||
3f4a964c | 567 | int in_get_config(int dev_id, enum in_cfg_opt what, void *val) |
da767bd5 | 568 | { |
e9b29264 | 569 | int *ival = val; |
570 | in_dev_t *dev; | |
da767bd5 | 571 | |
df77913a | 572 | dev = get_dev(dev_id); |
573 | if (dev == NULL || val == NULL) | |
e9b29264 | 574 | return -1; |
575 | ||
2c600560 | 576 | switch (what) { |
e9b29264 | 577 | case IN_CFG_BIND_COUNT: |
578 | *ival = dev->key_count; | |
579 | break; | |
580 | case IN_CFG_DOES_COMBOS: | |
581 | *ival = dev->does_combos; | |
582 | break; | |
583 | case IN_CFG_BLOCKING: | |
584 | case IN_CFG_KEY_NAMES: | |
585 | return -1; /* not implemented */ | |
586 | default: | |
a4025790 | 587 | if (!dev->probed) |
588 | return -1; | |
589 | ||
e9b29264 | 590 | return DRV(dev->drv_id).get_config(dev->drv_data, what, ival); |
591 | } | |
592 | ||
593 | return 0; | |
594 | } | |
595 | ||
596 | static int in_set_blocking(int is_blocking) | |
597 | { | |
598 | int i, ret; | |
599 | ||
600 | /* have_async_devs means we will have to do all reads async anyway.. */ | |
601 | if (!in_have_async_devs) { | |
602 | for (i = 0; i < in_dev_count; i++) { | |
a4025790 | 603 | if (!in_devices[i].probed) |
604 | continue; | |
605 | ||
606 | DRV(in_devices[i].drv_id).set_config( | |
607 | in_devices[i].drv_data, IN_CFG_BLOCKING, | |
608 | is_blocking); | |
e9b29264 | 609 | } |
2c600560 | 610 | } |
611 | ||
e9b29264 | 612 | /* flush events */ |
613 | do { | |
9934732a | 614 | ret = in_update_keycode(NULL, NULL, NULL, 0); |
e9b29264 | 615 | } while (ret >= 0); |
616 | ||
1eb399bd | 617 | menu_key_state = 0; |
618 | ||
2c600560 | 619 | return 0; |
da767bd5 | 620 | } |
621 | ||
3f4a964c | 622 | int in_set_config(int dev_id, enum in_cfg_opt what, const void *val, size_t size) |
e9b29264 | 623 | { |
215aec76 | 624 | const char * const *names; |
e9b29264 | 625 | const int *ival = val; |
626 | in_dev_t *dev; | |
215aec76 | 627 | int count; |
e9b29264 | 628 | |
629 | if (what == IN_CFG_BLOCKING) | |
630 | return in_set_blocking(*ival); | |
631 | ||
df77913a | 632 | dev = get_dev(dev_id); |
633 | if (dev == NULL) | |
e9b29264 | 634 | return -1; |
635 | ||
215aec76 | 636 | switch (what) { |
637 | case IN_CFG_KEY_NAMES: | |
638 | names = val; | |
639 | count = size / sizeof(names[0]); | |
e9b29264 | 640 | |
641 | if (count < dev->key_count) { | |
642 | lprintf("input: set_key_names: not enough keys\n"); | |
643 | return -1; | |
644 | } | |
645 | ||
646 | dev->key_names = names; | |
647 | return 0; | |
215aec76 | 648 | case IN_CFG_DEFAULT_DEV: |
649 | /* just set last used dev, for now */ | |
650 | menu_last_used_dev = dev_id; | |
651 | return 0; | |
652 | default: | |
653 | break; | |
e9b29264 | 654 | } |
655 | ||
8754b84c | 656 | if (dev->probed) |
657 | return DRV(dev->drv_id).set_config(dev->drv_data, what, *ival); | |
658 | ||
659 | return -1; | |
e9b29264 | 660 | } |
661 | ||
049a6b3e | 662 | const char *in_get_dev_name(int dev_id, int must_be_active, int skip_pfix) |
da767bd5 | 663 | { |
049a6b3e | 664 | const char *name, *tmp; |
df77913a | 665 | in_dev_t *dev; |
049a6b3e | 666 | |
df77913a | 667 | dev = get_dev(dev_id); |
668 | if (dev == NULL) | |
da767bd5 | 669 | return NULL; |
670 | ||
df77913a | 671 | if (must_be_active && !dev->probed) |
fce20e73 | 672 | return NULL; |
049a6b3e | 673 | |
df77913a | 674 | name = dev->name; |
bf3c44f4 | 675 | if (name == NULL || !skip_pfix) |
676 | return name; | |
f3b6f133 | 677 | |
bf3c44f4 | 678 | /* skip prefix */ |
049a6b3e | 679 | tmp = strchr(name, ':'); |
680 | if (tmp != NULL) | |
681 | name = tmp + 1; | |
682 | ||
683 | return name; | |
da767bd5 | 684 | } |
685 | ||
e9b29264 | 686 | int in_name_to_id(const char *dev_name) |
687 | { | |
688 | int i; | |
689 | ||
690 | for (i = 0; i < in_dev_count; i++) | |
691 | if (strcmp(dev_name, in_devices[i].name) == 0) | |
692 | break; | |
693 | ||
694 | if (i >= in_dev_count) { | |
695 | lprintf("input: in_name_to_id: no such device: %s\n", dev_name); | |
696 | return -1; | |
697 | } | |
698 | ||
699 | return i; | |
700 | } | |
701 | ||
906bdc9f | 702 | /* never returns NULL */ |
595491c4 | 703 | const char *in_get_key_name(int dev_id, int keycode) |
704 | { | |
e9b29264 | 705 | const char *name = NULL; |
906bdc9f | 706 | static char xname[16]; |
c4334e00 | 707 | in_drv_t *drv; |
e9b29264 | 708 | in_dev_t *dev; |
906bdc9f | 709 | |
82abf46f | 710 | if (dev_id < 0) /* want last used dev? */ |
711 | dev_id = menu_last_used_dev; | |
712 | ||
df77913a | 713 | dev = get_dev(dev_id); |
714 | if (dev == NULL) | |
595491c4 | 715 | return "Unkn0"; |
da767bd5 | 716 | |
c4334e00 | 717 | drv = &DRV(dev->drv_id); |
82abf46f | 718 | if (keycode < 0) /* want name for menu key? */ |
9934732a | 719 | keycode = drv->menu_translate(dev->drv_data, keycode, NULL); |
e9b29264 | 720 | |
721 | if (dev->key_names != NULL && 0 <= keycode && keycode < dev->key_count) | |
722 | name = dev->key_names[keycode]; | |
723 | if (name != NULL) | |
724 | return name; | |
82abf46f | 725 | |
c4334e00 | 726 | if (drv->get_key_name != NULL) |
727 | name = drv->get_key_name(keycode); | |
906bdc9f | 728 | if (name != NULL) |
729 | return name; | |
730 | ||
731 | /* assume scancode */ | |
732 | if ((keycode >= '0' && keycode <= '9') || (keycode >= 'a' && keycode <= 'z') | |
733 | || (keycode >= 'A' && keycode <= 'Z')) | |
734 | sprintf(xname, "%c", keycode); | |
735 | else | |
736 | sprintf(xname, "\\x%02X", keycode); | |
737 | return xname; | |
738 | } | |
739 | ||
d166ceb6 | 740 | int in_get_key_code(int dev_id, const char *key_name) |
741 | { | |
742 | in_dev_t *dev; | |
743 | int i; | |
744 | ||
745 | if (dev_id < 0) /* want last used dev? */ | |
746 | dev_id = menu_last_used_dev; | |
747 | ||
df77913a | 748 | dev = get_dev(dev_id); |
749 | if (dev == NULL) | |
d166ceb6 | 750 | return -1; |
751 | ||
d166ceb6 | 752 | if (dev->key_names == NULL) |
753 | return -1; | |
754 | ||
755 | for (i = 0; i < dev->key_count; i++) | |
756 | if (dev->key_names[i] && strcasecmp(dev->key_names[i], key_name) == 0) | |
757 | return i; | |
758 | ||
759 | return -1; | |
760 | } | |
761 | ||
92068389 | 762 | int in_bind_key(int dev_id, int keycode, int mask, int bind_type, int force_unbind) |
906bdc9f | 763 | { |
764 | int ret, count; | |
765 | in_dev_t *dev; | |
766 | ||
df77913a | 767 | dev = get_dev(dev_id); |
768 | if (dev == NULL || bind_type >= IN_BINDTYPE_COUNT) | |
906bdc9f | 769 | return -1; |
8e77275e | 770 | |
8e77275e | 771 | count = dev->key_count; |
906bdc9f | 772 | |
773 | if (dev->binds == NULL) { | |
774 | if (force_unbind) | |
775 | return 0; | |
8e77275e | 776 | dev->binds = in_alloc_binds(dev->drv_id, count); |
906bdc9f | 777 | if (dev->binds == NULL) |
778 | return -1; | |
779 | } | |
780 | ||
906bdc9f | 781 | if (keycode < 0 || keycode >= count) |
782 | return -1; | |
783 | ||
784 | if (force_unbind) | |
8e77275e | 785 | dev->binds[IN_BIND_OFFS(keycode, bind_type)] &= ~mask; |
906bdc9f | 786 | else |
8e77275e | 787 | dev->binds[IN_BIND_OFFS(keycode, bind_type)] ^= mask; |
906bdc9f | 788 | |
8e77275e | 789 | ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds, |
790 | dev->binds + count * IN_BINDTYPE_COUNT); | |
906bdc9f | 791 | if (ret == 0) { |
792 | free(dev->binds); | |
793 | dev->binds = NULL; | |
794 | } | |
795 | ||
796 | return 0; | |
da767bd5 | 797 | } |
798 | ||
4acbd7fe | 799 | int in_bind_kbd_key(int dev_id, int keycode, int kbd_key) |
e0d65e94 | 800 | { |
801 | int count; | |
802 | in_dev_t *dev; | |
803 | ||
804 | dev = get_dev(dev_id); | |
805 | if (dev == NULL) | |
806 | return -1; | |
807 | ||
808 | count = dev->key_count; | |
809 | ||
4acbd7fe | 810 | if (dev->kbd_binds == NULL) { |
811 | dev->kbd_binds = in_alloc_kbd_binds(dev->drv_id, count); | |
812 | if (dev->kbd_binds == NULL) | |
e0d65e94 | 813 | return -1; |
814 | } | |
815 | ||
816 | if (keycode < 0 || keycode >= count) | |
817 | return -1; | |
818 | ||
d4428e4e | 819 | dev->kbd_binds[keycode] = (kbd_key == -1 ? 0 : kbd_key); |
e0d65e94 | 820 | return 0; |
821 | } | |
822 | ||
2e307a07 | 823 | /* |
824 | * Unbind act_mask on binds with type bind_type | |
825 | * - if dev_id_ < 0, affects all devices | |
826 | * else only affects dev_id_ | |
827 | * - if act_mask == -1, unbind all keys | |
828 | * else only actions in mask | |
829 | */ | |
830 | void in_unbind_all(int dev_id_, int act_mask, int bind_type) | |
92068389 | 831 | { |
2e307a07 | 832 | int dev_id = 0, dev_last = IN_MAX_DEVS - 1; |
92068389 | 833 | int i, count; |
834 | in_dev_t *dev; | |
835 | ||
2e307a07 | 836 | if (dev_id_ >= 0) |
837 | dev_id = dev_last = dev_id_; | |
838 | ||
839 | if (bind_type >= IN_BINDTYPE_COUNT) | |
92068389 | 840 | return; |
841 | ||
2e307a07 | 842 | for (; dev_id <= dev_last; dev_id++) { |
843 | dev = &in_devices[dev_id]; | |
844 | count = dev->key_count; | |
92068389 | 845 | |
2e307a07 | 846 | if (dev->binds == NULL) |
847 | continue; | |
92068389 | 848 | |
2e307a07 | 849 | if (act_mask != -1) { |
850 | for (i = 0; i < count; i++) | |
851 | dev->binds[IN_BIND_OFFS(i, bind_type)] &= ~act_mask; | |
d4428e4e | 852 | } else { |
2e307a07 | 853 | memset(dev->binds, 0, sizeof(dev->binds[0]) * count * IN_BINDTYPE_COUNT); |
d4428e4e | 854 | if (dev->kbd_binds) |
855 | memset(dev->kbd_binds, 0, sizeof(dev->kbd_binds[0]) * count); | |
856 | } | |
2e307a07 | 857 | } |
92068389 | 858 | } |
859 | ||
da767bd5 | 860 | /* returns device id, or -1 on error */ |
861 | int in_config_parse_dev(const char *name) | |
862 | { | |
863 | int drv_id = -1, i; | |
864 | ||
c4334e00 | 865 | for (i = 0; i < in_driver_count; i++) { |
da767bd5 | 866 | int len = strlen(in_drivers[i].prefix); |
867 | if (strncmp(name, in_drivers[i].prefix, len) == 0) { | |
868 | drv_id = i; | |
869 | break; | |
870 | } | |
871 | } | |
872 | ||
873 | if (drv_id < 0) { | |
9fec8a91 | 874 | lprintf("input: missing driver for '%s'\n", name); |
da767bd5 | 875 | return -1; |
876 | } | |
877 | ||
878 | for (i = 0; i < in_dev_count; i++) | |
879 | { | |
880 | if (in_devices[i].name == NULL) | |
881 | continue; | |
882 | if (strcmp(in_devices[i].name, name) == 0) | |
883 | return i; | |
884 | } | |
885 | ||
886 | if (i >= IN_MAX_DEVS) | |
887 | { | |
888 | /* try to find unused device */ | |
889 | for (i = 0; i < IN_MAX_DEVS; i++) | |
890 | if (in_devices[i].name == NULL) break; | |
891 | if (i >= IN_MAX_DEVS) { | |
9fec8a91 | 892 | lprintf("input: too many devices, can't add '%s'\n", |
893 | name); | |
da767bd5 | 894 | return -1; |
895 | } | |
896 | } | |
897 | ||
898 | memset(&in_devices[i], 0, sizeof(in_devices[i])); | |
899 | ||
900 | in_devices[i].name = strdup(name); | |
901 | if (in_devices[i].name == NULL) | |
902 | return -1; | |
903 | ||
d685ce46 PC |
904 | in_devices[i].key_names = DRV(drv_id).get_key_names(&DRV(drv_id), |
905 | &in_devices[i].key_count); | |
8e77275e | 906 | in_devices[i].drv_id = drv_id; |
907 | ||
da767bd5 | 908 | if (i + 1 > in_dev_count) |
909 | in_dev_count = i + 1; | |
da767bd5 | 910 | |
911 | return i; | |
912 | } | |
913 | ||
e0d65e94 | 914 | static int parse_key(in_dev_t *dev, const char *key) |
da767bd5 | 915 | { |
e0d65e94 | 916 | int kc, i; |
da767bd5 | 917 | |
906bdc9f | 918 | /* maybe a raw code? */ |
919 | if (key[0] == '\\' && key[1] == 'x') { | |
920 | char *p = NULL; | |
921 | kc = (int)strtoul(key + 2, &p, 16); | |
922 | if (p == NULL || *p != 0) | |
923 | kc = -1; | |
924 | } | |
925 | else { | |
926 | /* device specific key name */ | |
927 | if (dev->binds == NULL) { | |
8e77275e | 928 | dev->binds = in_alloc_binds(dev->drv_id, dev->key_count); |
906bdc9f | 929 | if (dev->binds == NULL) |
930 | return -1; | |
906bdc9f | 931 | } |
932 | ||
e9b29264 | 933 | kc = -1; |
934 | if (dev->key_names != NULL) { | |
935 | for (i = 0; i < dev->key_count; i++) { | |
936 | const char *k = dev->key_names[i]; | |
937 | if (k != NULL && strcasecmp(k, key) == 0) { | |
938 | kc = i; | |
939 | break; | |
940 | } | |
941 | } | |
942 | } | |
943 | ||
944 | if (kc < 0) | |
945 | kc = DRV(dev->drv_id).get_key_code(key); | |
906bdc9f | 946 | if (kc < 0 && strlen(key) == 1) { |
947 | /* assume scancode */ | |
948 | kc = key[0]; | |
949 | } | |
da767bd5 | 950 | } |
951 | ||
e0d65e94 | 952 | return kc; |
953 | } | |
954 | ||
955 | int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type) | |
956 | { | |
957 | in_dev_t *dev; | |
958 | int i, offs, kc; | |
959 | ||
960 | dev = get_dev(dev_id); | |
961 | if (dev == NULL || bind_type >= IN_BINDTYPE_COUNT) | |
962 | return -1; | |
963 | ||
964 | kc = parse_key(dev, key); | |
965 | ||
8e77275e | 966 | if (kc < 0 || kc >= dev->key_count) { |
9fec8a91 | 967 | lprintf("input: bad key: '%s' for device '%s'\n", |
968 | key, dev->name); | |
da767bd5 | 969 | return -1; |
595491c4 | 970 | } |
971 | ||
8e77275e | 972 | if (bind_type == IN_BINDTYPE_NONE) { |
973 | for (i = 0; i < IN_BINDTYPE_COUNT; i++) | |
974 | dev->binds[IN_BIND_OFFS(kc, i)] = 0; | |
975 | return 0; | |
976 | } | |
da767bd5 | 977 | |
8e77275e | 978 | offs = IN_BIND_OFFS(kc, bind_type); |
979 | if (dev->binds[offs] == -1) | |
980 | dev->binds[offs] = 0; | |
981 | dev->binds[offs] |= acts; | |
da767bd5 | 982 | return 0; |
983 | } | |
984 | ||
4acbd7fe | 985 | int in_config_bind_kbd_key(int dev_id, const char *key, int kbd_key) |
e0d65e94 | 986 | { |
987 | in_dev_t *dev; | |
988 | int kc; | |
989 | ||
990 | dev = get_dev(dev_id); | |
991 | if (dev == NULL) | |
992 | return -1; | |
993 | ||
994 | kc = parse_key(dev, key); | |
995 | ||
996 | if (kc < 0 || kc >= dev->key_count) { | |
997 | lprintf("input: bad key: '%s' for device '%s'\n", | |
998 | key, dev->name); | |
999 | return -1; | |
1000 | } | |
1001 | ||
4acbd7fe | 1002 | dev->kbd_binds[kc] = kbd_key; |
e0d65e94 | 1003 | |
1004 | return 0; | |
1005 | } | |
1006 | ||
45a39652 | 1007 | void in_clean_binds(void) |
da767bd5 | 1008 | { |
1009 | int i; | |
1010 | ||
1011 | for (i = 0; i < IN_MAX_DEVS; i++) { | |
45a39652 | 1012 | int ret, count, *binds, *def_binds; |
906bdc9f | 1013 | in_dev_t *dev = &in_devices[i]; |
da767bd5 | 1014 | |
a4025790 | 1015 | if (dev->binds == NULL || !dev->probed) |
da767bd5 | 1016 | continue; |
1017 | ||
8e77275e | 1018 | count = dev->key_count; |
906bdc9f | 1019 | binds = dev->binds; |
8e77275e | 1020 | def_binds = binds + count * IN_BINDTYPE_COUNT; |
da767bd5 | 1021 | |
8e77275e | 1022 | ret = DRV(dev->drv_id).clean_binds(dev->drv_data, binds, def_binds); |
da767bd5 | 1023 | if (ret == 0) { |
1024 | /* no useable binds */ | |
906bdc9f | 1025 | free(dev->binds); |
1026 | dev->binds = NULL; | |
da767bd5 | 1027 | } |
1028 | } | |
595491c4 | 1029 | } |
1030 | ||
da767bd5 | 1031 | void in_debug_dump(void) |
1032 | { | |
1033 | int i; | |
1034 | ||
7ee5c389 | 1035 | lprintf("# drv probed binds name\n"); |
da767bd5 | 1036 | for (i = 0; i < IN_MAX_DEVS; i++) { |
1037 | in_dev_t *d = &in_devices[i]; | |
1038 | if (!d->probed && d->name == NULL && d->binds == NULL) | |
1039 | continue; | |
9fec8a91 | 1040 | lprintf("%d %3d %6c %5c %s\n", i, d->drv_id, |
1041 | d->probed ? 'y' : 'n', | |
da767bd5 | 1042 | d->binds ? 'y' : 'n', d->name); |
9fec8a91 | 1043 | #if 0 |
1044 | if (d->binds) { | |
1045 | int kc, o, t, h; | |
1046 | for (kc = 0; kc < d->key_count; kc++) { | |
1047 | o = IN_BIND_OFFS(kc, 0); | |
1048 | for (t = h = 0; t < IN_BINDTYPE_COUNT; t++) | |
1049 | h |= d->binds[o + t]; | |
1050 | if (h == 0) | |
1051 | continue; | |
1052 | lprintf(" [%3d] =", kc); | |
1053 | for (t = 0; t < IN_BINDTYPE_COUNT; t++) | |
1054 | printf(" %x", d->binds[o + t]); | |
1055 | printf("\n"); | |
1056 | } | |
1057 | } | |
1058 | #endif | |
da767bd5 | 1059 | } |
1060 | } | |
1061 | ||
c4334e00 | 1062 | /* stubs for drivers that choose not to implement something */ |
da767bd5 | 1063 | |
da767bd5 | 1064 | static void in_def_free(void *drv_data) {} |
c4334e00 | 1065 | static int in_def_clean_binds(void *drv_data, int *b, int *db) { return 1; } |
3f4a964c | 1066 | static int in_def_get_config(void *drv_data, enum in_cfg_opt what, int *val) { return -1; } |
1067 | static int in_def_set_config(void *drv_data, enum in_cfg_opt what, int val) { return -1; } | |
df77913a | 1068 | static int in_def_update_analog(void *drv_data, int axis_id, int *result) { return -1; } |
b020891a | 1069 | static int in_def_update_pointer(void *drv_data, int id, int *result) { return -1; } |
7f022a8d | 1070 | static int in_def_update_keycode(void *drv_data, int *is_down) { return 0; } |
9934732a | 1071 | static int in_def_menu_translate(void *drv_data, int keycode, char *ccode) { return 0; } |
e9b29264 | 1072 | static int in_def_get_key_code(const char *key_name) { return -1; } |
da767bd5 | 1073 | static const char *in_def_get_key_name(int keycode) { return NULL; } |
1074 | ||
c4334e00 | 1075 | #define CHECK_ADD_STUB(d, f) \ |
1076 | if (d.f == NULL) d.f = in_def_##f | |
da767bd5 | 1077 | |
c4334e00 | 1078 | /* to be called by drivers */ |
c19e28f6 | 1079 | int in_register_driver(const in_drv_t *drv, |
b047d2e2 | 1080 | const struct in_default_bind *defbinds, |
4acbd7fe | 1081 | const struct in_default_bind *kbd_map, |
b047d2e2 | 1082 | const void *pdata) |
c4334e00 | 1083 | { |
1084 | int count_new = in_driver_count + 1; | |
1085 | in_drv_t *new_drivers; | |
da767bd5 | 1086 | |
c4334e00 | 1087 | new_drivers = realloc(in_drivers, count_new * sizeof(in_drivers[0])); |
1088 | if (new_drivers == NULL) { | |
1089 | lprintf("input: in_register_driver OOM\n"); | |
1090 | return -1; | |
da767bd5 | 1091 | } |
1092 | ||
c4334e00 | 1093 | memcpy(&new_drivers[in_driver_count], drv, sizeof(new_drivers[0])); |
1094 | ||
1095 | CHECK_ADD_STUB(new_drivers[in_driver_count], free); | |
c4334e00 | 1096 | CHECK_ADD_STUB(new_drivers[in_driver_count], clean_binds); |
1097 | CHECK_ADD_STUB(new_drivers[in_driver_count], get_config); | |
1098 | CHECK_ADD_STUB(new_drivers[in_driver_count], set_config); | |
df77913a | 1099 | CHECK_ADD_STUB(new_drivers[in_driver_count], update_analog); |
b020891a | 1100 | CHECK_ADD_STUB(new_drivers[in_driver_count], update_pointer); |
c4334e00 | 1101 | CHECK_ADD_STUB(new_drivers[in_driver_count], update_keycode); |
1102 | CHECK_ADD_STUB(new_drivers[in_driver_count], menu_translate); | |
1103 | CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_code); | |
1104 | CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_name); | |
c19e28f6 PC |
1105 | if (pdata) |
1106 | new_drivers[in_driver_count].pdata = pdata; | |
1107 | if (defbinds) | |
215aec76 | 1108 | new_drivers[in_driver_count].defbinds = defbinds; |
4acbd7fe | 1109 | if (kbd_map) |
1110 | new_drivers[in_driver_count].kbd_binds = kbd_map; | |
c4334e00 | 1111 | in_drivers = new_drivers; |
1112 | in_driver_count = count_new; | |
1113 | ||
1114 | return 0; | |
1115 | } | |
1116 | ||
1117 | void in_init(void) | |
1118 | { | |
1119 | in_drivers = NULL; | |
1120 | memset(in_devices, 0, sizeof(in_devices)); | |
1121 | in_driver_count = 0; | |
1122 | in_dev_count = 0; | |
2258f158 | 1123 | } |
1124 | ||
da767bd5 | 1125 | #if 0 |
2258f158 | 1126 | int main(void) |
1127 | { | |
34581c95 | 1128 | int ret; |
1129 | ||
2258f158 | 1130 | in_init(); |
1131 | in_probe(); | |
1132 | ||
595491c4 | 1133 | in_set_blocking(1); |
1134 | ||
1135 | #if 1 | |
1136 | while (1) { | |
1137 | int dev = 0, down; | |
1138 | ret = in_update_keycode(&dev, &down); | |
7ee5c389 | 1139 | lprintf("#%i: %i %i (%s)\n", dev, down, ret, in_get_key_name(dev, ret)); |
595491c4 | 1140 | } |
1141 | #else | |
2258f158 | 1142 | while (1) { |
fce20e73 | 1143 | ret = in_menu_wait_any(); |
7ee5c389 | 1144 | lprintf("%08x\n", ret); |
2258f158 | 1145 | } |
595491c4 | 1146 | #endif |
2258f158 | 1147 | |
1148 | return 0; | |
1149 | } | |
da767bd5 | 1150 | #endif |