bugfix
[libpicofe.git] / common / input.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "common.h"
6 #include "input.h"
7 #include "plat.h"
8 #include "../linux/in_evdev.h"
9 #include "../gp2x/in_gp2x.h"
10
11 typedef struct
12 {
13         int drv_id;
14         int drv_fd_hnd;
15         void *drv_data;
16         char *name;
17         int *binds;
18         int probed:1;
19 } in_dev_t;
20
21 static in_drv_t in_drivers[IN_DRVID_COUNT];
22 static in_dev_t in_devices[IN_MAX_DEVS];
23 static int in_dev_count = 0;
24 static int in_have_async_devs = 0;
25
26 #define DRV(id) in_drivers[(unsigned)(id) < IN_DRVID_COUNT ? (id) : 0]
27
28
29 static int in_bind_count(int drv_id)
30 {
31         int count = DRV(drv_id).get_bind_count();
32         if (count <= 0)
33                 printf("input: failed to get bind count for drv %d\n", drv_id);
34
35         return count;
36 }
37
38 static int *in_alloc_binds(int drv_id)
39 {
40         int count, *binds;
41
42         count = in_bind_count(drv_id);
43         if (count <= 0)
44                 return NULL;
45
46         binds = calloc(count * 2, sizeof(binds[0]));
47         if (binds == NULL)
48                 return NULL;
49
50         DRV(drv_id).get_def_binds(binds + count);
51         memcpy(binds, binds + count, count * sizeof(binds[0]));
52
53         return binds;
54 }
55
56 static void in_free(in_dev_t *dev)
57 {
58         if (dev->probed)
59                 DRV(dev->drv_id).free(dev->drv_data);
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  * async devices must set drv_fd_hnd to -1 */
70 void in_register(const char *nname, int drv_id, int drv_fd_hnd, void *drv_data)
71 {
72         int i, ret, dupe_count = 0, *binds;
73         char name[256], *name_end, *tmp;
74
75         strncpy(name, nname, sizeof(name));
76         name[sizeof(name)-12] = 0;
77         name_end = name + strlen(name);
78
79         for (i = 0; i < in_dev_count; i++)
80         {
81                 if (in_devices[i].name == NULL)
82                         continue;
83                 if (strcmp(in_devices[i].name, name) == 0)
84                 {
85                         if (in_devices[i].probed) {
86                                 dupe_count++;
87                                 sprintf(name_end, " [%d]", dupe_count);
88                                 continue;
89                         }
90                         goto update;
91                 }
92         }
93
94         if (i >= IN_MAX_DEVS)
95         {
96                 /* try to find unused device */
97                 for (i = 0; i < IN_MAX_DEVS; i++)
98                         if (!in_devices[i].probed) break;
99                 if (i >= IN_MAX_DEVS) {
100                         printf("input: too many devices, can't add %s\n", name);
101                         return;
102                 }
103                 in_free(&in_devices[i]);
104         }
105
106         tmp = strdup(name);
107         if (tmp == NULL)
108                 return;
109
110         binds = in_alloc_binds(drv_id);
111         if (binds == NULL) {
112                 free(tmp);
113                 return;
114         }
115
116         in_devices[i].name = tmp;
117         in_devices[i].binds = binds;
118         if (i + 1 > in_dev_count)
119                 in_dev_count = i + 1;
120
121         printf("input: new device #%d \"%s\"\n", i, name);
122 update:
123         in_devices[i].probed = 1;
124         in_devices[i].drv_id = drv_id;
125         in_devices[i].drv_fd_hnd = drv_fd_hnd;
126         in_devices[i].drv_data = drv_data;
127
128         if (in_devices[i].binds != NULL) {
129                 ret = DRV(drv_id).clean_binds(drv_data, in_devices[i].binds);
130                 if (ret == 0) {
131                         /* no useable binds */
132                         free(in_devices[i].binds);
133                         in_devices[i].binds = NULL;
134                 }
135         }
136 }
137
138 void in_probe(void)
139 {
140         int i;
141
142         in_have_async_devs = 0;
143         for (i = 0; i < in_dev_count; i++)
144                 in_devices[i].probed = 0;
145
146         for (i = 1; i < IN_DRVID_COUNT; i++)
147                 in_drivers[i].probe();
148
149         /* get rid of devs without binds and probes */
150         for (i = 0; i < in_dev_count; i++) {
151                 if (!in_devices[i].probed && in_devices[i].binds == NULL) {
152                         in_dev_count--;
153                         if (i < in_dev_count) {
154                                 free(in_devices[i].name);
155                                 memmove(&in_devices[i], &in_devices[i+1],
156                                         (in_dev_count - i) * sizeof(in_devices[0]));
157                         }
158
159                         continue;
160                 }
161
162                 if (in_devices[i].probed && in_devices[i].drv_fd_hnd == -1)
163                         in_have_async_devs = 1;
164         }
165
166         if (in_have_async_devs)
167                 printf("input: async-only devices detected..\n");
168 }
169
170 /* async update */
171 int in_update(void)
172 {
173         int i, result = 0;
174
175         for (i = 0; i < in_dev_count; i++) {
176                 in_dev_t *dev = &in_devices[i];
177                 if (dev->probed && dev->binds != NULL) {
178                         switch (dev->drv_id) {
179 #ifdef IN_EVDEV
180                         case IN_DRVID_EVDEV:
181                                 result |= in_evdev_update(dev->drv_data, dev->binds);
182                                 break;
183 #endif
184 #ifdef IN_GP2X
185                         case IN_DRVID_GP2X:
186                                 result |= in_gp2x_update(dev->drv_data, dev->binds);
187                                 break;
188 #endif
189                         }
190                 }
191         }
192
193         return result;
194 }
195
196 static int menu_key_state = 0;
197
198 void in_set_blocking(int is_blocking)
199 {
200         int i, ret;
201
202         /* have_async_devs means we will have to do all reads async anyway.. */
203         if (!in_have_async_devs) {
204                 for (i = 0; i < in_dev_count; i++) {
205                         if (in_devices[i].probed)
206                                 DRV(in_devices[i].drv_id).set_blocking(in_devices[i].drv_data, is_blocking);
207                 }
208         }
209
210         menu_key_state = 0;
211
212         /* flush events */
213         do {
214                 ret = in_update_keycode(NULL, NULL, 0);
215         } while (ret >= 0);
216 }
217
218 static int in_update_kc_async(int *dev_id_out, int *is_down_out, int timeout_ms)
219 {
220         int i, is_down, result;
221         unsigned int ticks;
222
223         ticks = plat_get_ticks_ms();
224
225         while (1)
226         {
227                 for (i = 0; i < in_dev_count; i++) {
228                         in_dev_t *d = &in_devices[i];
229                         if (!d->probed)
230                                 continue;
231
232                         result = DRV(d->drv_id).update_keycode(d->drv_data, &is_down);
233                         if (result == -1)
234                                 continue;
235
236                         if (dev_id_out)
237                                 *dev_id_out = i;
238                         if (is_down_out)
239                                 *is_down_out = is_down;
240                         return result;
241                 }
242
243                 if (timeout_ms >= 0 && (int)(plat_get_ticks_ms() - ticks) > timeout_ms)
244                         break;
245
246                 plat_sleep_ms(10);
247         }
248
249         return -1;
250 }
251
252 /* 
253  * wait for a press, always return some keycode or -1 on timeout or error
254  */
255 int in_update_keycode(int *dev_id_out, int *is_down_out, int timeout_ms)
256 {
257         int result = -1, dev_id = 0, is_down, result_menu;
258         int fds_hnds[IN_MAX_DEVS];
259         int i, ret, count = 0;
260         unsigned int ticks;
261         in_drv_t *drv;
262
263         if (in_have_async_devs) {
264                 result = in_update_kc_async(&dev_id, &is_down, timeout_ms);
265                 if (result == -1)
266                         return -1;
267                 drv = &DRV(in_devices[dev_id].drv_id);
268                 goto finish;
269         }
270
271         ticks = plat_get_ticks_ms();
272
273         for (i = 0; i < in_dev_count; i++) {
274                 if (in_devices[i].probed)
275                         fds_hnds[count++] = in_devices[i].drv_fd_hnd;
276         }
277
278         if (count == 0) {
279                 /* don't deadlock, fail */
280                 printf("input: failed to find devices to read\n");
281                 exit(1);
282         }
283
284         while (1)
285         {
286                 ret = plat_wait_event(fds_hnds, count, timeout_ms);
287                 if (ret < 0)
288                         break;
289
290                 for (i = 0; i < in_dev_count; i++) {
291                         if (in_devices[i].drv_fd_hnd == ret) {
292                                 dev_id = i;
293                                 break;
294                         }
295                 }
296
297                 drv = &DRV(in_devices[dev_id].drv_id);
298                 result = drv->update_keycode(in_devices[dev_id].drv_data, &is_down);
299
300                 /* update_keycode() might return -1 when some not interesting
301                  * event happened, like sync event for evdev. */
302                 if (result >= 0)
303                         break;
304
305                 if (timeout_ms >= 0) {
306                         unsigned int ticks2 = plat_get_ticks_ms();
307                         timeout_ms -= ticks2 - ticks;
308                         ticks = ticks2;
309                         if (timeout_ms <= 0)
310                                 break;
311                 }
312         }
313
314         if (result == -1)
315                 return -1;
316 finish:
317         /* keep track of menu key state, to allow mixing
318          * in_update_keycode() and in_menu_wait_any() calls */
319         result_menu = drv->menu_translate(result);
320         if (result_menu != 0) {
321                 if (is_down)
322                         menu_key_state |=  result_menu;
323                 else
324                         menu_key_state &= ~result_menu;
325         }
326
327         if (dev_id_out != NULL)
328                 *dev_id_out = dev_id;
329         if (is_down_out != NULL)
330                 *is_down_out = is_down;
331         return result;
332 }
333
334 /* same as above, only return bitfield of PBTN_*  */
335 int in_menu_wait_any(int timeout_ms)
336 {
337         int keys_old = menu_key_state;
338
339         while (1)
340         {
341                 int code, is_down = 0, dev_id = 0;
342
343                 code = in_update_keycode(&dev_id, &is_down, timeout_ms);
344                 if (code >= 0)
345                         code = DRV(in_devices[dev_id].drv_id).menu_translate(code);
346
347                 if (timeout_ms >= 0)
348                         break;
349                 if (code < 0)
350                         continue;
351                 if (keys_old != menu_key_state)
352                         break;
353         }
354
355         return menu_key_state;
356 }
357
358 /* wait for menu input, do autorepeat */
359 int in_menu_wait(int interesting, int autorep_delay_ms)
360 {
361         static int inp_prev = 0;
362         static int repeats = 0;
363         int ret, release = 0, wait = 666;
364
365         if (repeats)
366                 wait = autorep_delay_ms;
367
368         ret = in_menu_wait_any(wait);
369         if (ret == inp_prev)
370                 repeats++;
371
372         while (!(ret & interesting)) {
373                 ret = in_menu_wait_any(-1);
374                 release = 1;
375         }
376
377         if (release || ret != inp_prev)
378                 repeats = 0;
379
380         inp_prev = ret;
381
382         /* we don't need diagonals in menus */
383         if ((ret & PBTN_UP)   && (ret & PBTN_LEFT))  ret &= ~PBTN_LEFT;
384         if ((ret & PBTN_UP)   && (ret & PBTN_RIGHT)) ret &= ~PBTN_RIGHT;
385         if ((ret & PBTN_DOWN) && (ret & PBTN_LEFT))  ret &= ~PBTN_LEFT;
386         if ((ret & PBTN_DOWN) && (ret & PBTN_RIGHT)) ret &= ~PBTN_RIGHT;
387
388         return ret;
389 }
390
391 const int *in_get_dev_binds(int dev_id)
392 {
393         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
394                 return NULL;
395
396         return in_devices[dev_id].binds;
397 }
398
399 const int *in_get_dev_def_binds(int dev_id)
400 {
401         int count;
402
403         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
404                 return NULL;
405
406         count = in_bind_count(in_devices[dev_id].drv_id);
407         return in_devices[dev_id].binds + count;
408 }
409
410 int in_get_dev_bind_count(int dev_id)
411 {
412         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
413                 return 0;
414
415         return in_bind_count(in_devices[dev_id].drv_id);
416 }
417
418 const char *in_get_dev_name(int dev_id, int must_be_active, int skip_pfix)
419 {
420         const char *name, *tmp;
421
422         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
423                 return NULL;
424
425         if (must_be_active && !in_devices[dev_id].probed)
426                 return NULL;
427
428         name = in_devices[dev_id].name;
429         if (name == NULL)
430                 return NULL;
431
432         tmp = strchr(name, ':');
433         if (tmp != NULL)
434                 name = tmp + 1;
435
436         return name;
437 }
438
439 /* never returns NULL */
440 const char *in_get_key_name(int dev_id, int keycode)
441 {
442         static char xname[16];
443         const char *name;
444
445         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
446                 return "Unkn0";
447
448         name = DRV(in_devices[dev_id].drv_id).get_key_name(keycode);
449         if (name != NULL)
450                 return name;
451
452         /* assume scancode */
453         if ((keycode >= '0' && keycode <= '9') || (keycode >= 'a' && keycode <= 'z')
454                         || (keycode >= 'A' && keycode <= 'Z'))
455                 sprintf(xname, "%c", keycode);
456         else
457                 sprintf(xname, "\\x%02X", keycode);
458         return xname;
459 }
460
461 int in_bind_key(int dev_id, int keycode, int mask, int force_unbind)
462 {
463         int ret, count;
464         in_dev_t *dev;
465
466         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
467                 return -1;
468         dev = &in_devices[dev_id];
469
470         if (dev->binds == NULL) {
471                 if (force_unbind)
472                         return 0;
473                 dev->binds = in_alloc_binds(dev->drv_id);
474                 if (dev->binds == NULL)
475                         return -1;
476         }
477
478         count = in_bind_count(dev->drv_id);
479         if (keycode < 0 || keycode >= count)
480                 return -1;
481         
482         if (force_unbind)
483                 dev->binds[keycode] &= ~mask;
484         else
485                 dev->binds[keycode] ^=  mask;
486         
487         ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds);
488         if (ret == 0) {
489                 free(dev->binds);
490                 dev->binds = NULL;
491         }
492
493         return 0;
494 }
495
496 /* returns device id, or -1 on error */
497 int in_config_parse_dev(const char *name)
498 {
499         int drv_id = -1, i;
500
501         for (i = 0; i < IN_DRVID_COUNT; i++) {
502                 int len = strlen(in_drivers[i].prefix);
503                 if (strncmp(name, in_drivers[i].prefix, len) == 0) {
504                         drv_id = i;
505                         break;
506                 }
507         }
508
509         if (drv_id < 0) {
510                 printf("input: missing driver for %s\n", name);
511                 return -1;
512         }
513
514         for (i = 0; i < in_dev_count; i++)
515         {
516                 if (in_devices[i].name == NULL)
517                         continue;
518                 if (strcmp(in_devices[i].name, name) == 0)
519                         return i;
520         }
521
522         if (i >= IN_MAX_DEVS)
523         {
524                 /* try to find unused device */
525                 for (i = 0; i < IN_MAX_DEVS; i++)
526                         if (in_devices[i].name == NULL) break;
527                 if (i >= IN_MAX_DEVS) {
528                         printf("input: too many devices, can't add %s\n", name);
529                         return -1;
530                 }
531         }
532
533         memset(&in_devices[i], 0, sizeof(in_devices[i]));
534
535         in_devices[i].name = strdup(name);
536         if (in_devices[i].name == NULL)
537                 return -1;
538
539         if (i + 1 > in_dev_count)
540                 in_dev_count = i + 1;
541         in_devices[i].drv_id = drv_id;
542
543         return i;
544 }
545
546 /*
547  * To reduce size of game specific configs, default binds are not saved.
548  * So we mark default binds in in_config_start(), override them in in_config_bind_key(),
549  * and restore whatever default binds are left in in_config_end().
550  */
551 void in_config_start(void)
552 {
553         int i;
554
555         /* mark all default binds, so they get overwritten by func below */
556         for (i = 0; i < IN_MAX_DEVS; i++) {
557                 int n, count, *binds, *def_binds;
558
559                 binds = in_devices[i].binds;
560                 if (binds == NULL)
561                         continue;
562
563                 count = in_bind_count(in_devices[i].drv_id);
564                 def_binds = binds + count;
565
566                 for (n = 0; n < count; n++)
567                         if (binds[n] == def_binds[n])
568                                 binds[n] = -1;
569         }
570 }
571
572 int in_config_bind_key(int dev_id, const char *key, int binds)
573 {
574         int count, kc;
575         in_dev_t *dev;
576
577         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
578                 return -1;
579         dev = &in_devices[dev_id];
580
581         count = in_bind_count(dev->drv_id);
582
583         /* maybe a raw code? */
584         if (key[0] == '\\' && key[1] == 'x') {
585                 char *p = NULL;
586                 kc = (int)strtoul(key + 2, &p, 16);
587                 if (p == NULL || *p != 0)
588                         kc = -1;
589         }
590         else {
591                 /* device specific key name */
592                 if (dev->binds == NULL) {
593                         dev->binds = in_alloc_binds(dev->drv_id);
594                         if (dev->binds == NULL)
595                                 return -1;
596                         in_config_start();
597                 }
598
599                 kc = DRV(dev->drv_id).get_key_code(key);
600                 if (kc < 0 && strlen(key) == 1) {
601                         /* assume scancode */
602                         kc = key[0];
603                 }
604         }
605
606         if (kc < 0 || kc >= count) {
607                 printf("input: bad key: %s\n", key);
608                 return -1;
609         }
610
611         if (dev->binds[kc] == -1)
612                 dev->binds[kc] = 0;
613         dev->binds[kc] |= binds;
614
615         return 0;
616 }
617
618 void in_config_end(void)
619 {
620         int i;
621
622         for (i = 0; i < IN_MAX_DEVS; i++) {
623                 int n, ret, count, *binds, *def_binds;
624                 in_dev_t *dev = &in_devices[i];
625
626                 if (dev->binds == NULL)
627                         continue;
628
629                 count = in_bind_count(dev->drv_id);
630                 binds = dev->binds;
631                 def_binds = binds + count;
632
633                 for (n = 0; n < count; n++)
634                         if (binds[n] == -1)
635                                 binds[n] = def_binds[n];
636
637                 if (dev->drv_data == NULL)
638                         continue;
639
640                 ret = DRV(dev->drv_id).clean_binds(dev->drv_data, binds);
641                 if (ret == 0) {
642                         /* no useable binds */
643                         free(dev->binds);
644                         dev->binds = NULL;
645                 }
646         }
647 }
648
649 void in_debug_dump(void)
650 {
651         int i;
652
653         printf("# drv probed binds name\n");
654         for (i = 0; i < IN_MAX_DEVS; i++) {
655                 in_dev_t *d = &in_devices[i];
656                 if (!d->probed && d->name == NULL && d->binds == NULL)
657                         continue;
658                 printf("%d %3d %6c %5c %s\n", i, d->drv_id, d->probed ? 'y' : 'n',
659                         d->binds ? 'y' : 'n', d->name);
660         }
661 }
662
663 /* handlers for unknown/not_preset drivers */
664
665 static void in_def_probe(void) {}
666 static void in_def_free(void *drv_data) {}
667 static int  in_def_get_bind_count(void) { return 0; }
668 static void in_def_get_def_binds(int *binds) {}
669 static int  in_def_clean_binds(void *drv_data, int *binds) { return 0; }
670 static void in_def_set_blocking(void *data, int y) {}
671 static int  in_def_update_keycode(void *drv_data, int *is_down) { return 0; }
672 static int  in_def_menu_translate(int keycode) { return keycode; }
673 static int  in_def_get_key_code(const char *key_name) { return 0; }
674 static const char *in_def_get_key_name(int keycode) { return NULL; }
675
676 void in_init(void)
677 {
678         int i;
679
680         memset(in_drivers, 0, sizeof(in_drivers));
681         memset(in_devices, 0, sizeof(in_devices));
682         in_dev_count = 0;
683
684         for (i = 0; i < IN_DRVID_COUNT; i++) {
685                 in_drivers[i].prefix = "none:";
686                 in_drivers[i].probe = in_def_probe;
687                 in_drivers[i].free = in_def_free;
688                 in_drivers[i].get_bind_count = in_def_get_bind_count;
689                 in_drivers[i].get_def_binds = in_def_get_def_binds;
690                 in_drivers[i].clean_binds = in_def_clean_binds;
691                 in_drivers[i].set_blocking = in_def_set_blocking;
692                 in_drivers[i].update_keycode = in_def_update_keycode;
693                 in_drivers[i].menu_translate = in_def_menu_translate;
694                 in_drivers[i].get_key_code = in_def_get_key_code;
695                 in_drivers[i].get_key_name = in_def_get_key_name;
696         }
697
698 #ifdef IN_GP2X
699         in_gp2x_init(&in_drivers[IN_DRVID_GP2X]);
700 #endif
701 #ifdef IN_EVDEV
702         in_evdev_init(&in_drivers[IN_DRVID_EVDEV]);
703 #endif
704 }
705
706 #if 0
707 int main(void)
708 {
709         int ret;
710
711         in_init();
712         in_probe();
713
714         in_set_blocking(1);
715
716 #if 1
717         while (1) {
718                 int dev = 0, down;
719                 ret = in_update_keycode(&dev, &down);
720                 printf("#%i: %i %i (%s)\n", dev, down, ret, in_get_key_name(dev, ret));
721         }
722 #else
723         while (1) {
724                 ret = in_menu_wait_any();
725                 printf("%08x\n", ret);
726         }
727 #endif
728
729         return 0;
730 }
731 #endif