81f6e169af33d1aeb2d9112fe3f887e64b7f388a
[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         in_drv_t *drv = NULL;
261         unsigned int ticks;
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 || !skip_pfix)
430                 return name;
431
432         /* skip prefix */
433         tmp = strchr(name, ':');
434         if (tmp != NULL)
435                 name = tmp + 1;
436
437         return name;
438 }
439
440 /* never returns NULL */
441 const char *in_get_key_name(int dev_id, int keycode)
442 {
443         static char xname[16];
444         const char *name;
445
446         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
447                 return "Unkn0";
448
449         name = DRV(in_devices[dev_id].drv_id).get_key_name(keycode);
450         if (name != NULL)
451                 return name;
452
453         /* assume scancode */
454         if ((keycode >= '0' && keycode <= '9') || (keycode >= 'a' && keycode <= 'z')
455                         || (keycode >= 'A' && keycode <= 'Z'))
456                 sprintf(xname, "%c", keycode);
457         else
458                 sprintf(xname, "\\x%02X", keycode);
459         return xname;
460 }
461
462 int in_bind_key(int dev_id, int keycode, int mask, int force_unbind)
463 {
464         int ret, count;
465         in_dev_t *dev;
466
467         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
468                 return -1;
469         dev = &in_devices[dev_id];
470
471         if (dev->binds == NULL) {
472                 if (force_unbind)
473                         return 0;
474                 dev->binds = in_alloc_binds(dev->drv_id);
475                 if (dev->binds == NULL)
476                         return -1;
477         }
478
479         count = in_bind_count(dev->drv_id);
480         if (keycode < 0 || keycode >= count)
481                 return -1;
482         
483         if (force_unbind)
484                 dev->binds[keycode] &= ~mask;
485         else
486                 dev->binds[keycode] ^=  mask;
487         
488         ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds);
489         if (ret == 0) {
490                 free(dev->binds);
491                 dev->binds = NULL;
492         }
493
494         return 0;
495 }
496
497 /* returns device id, or -1 on error */
498 int in_config_parse_dev(const char *name)
499 {
500         int drv_id = -1, i;
501
502         for (i = 0; i < IN_DRVID_COUNT; i++) {
503                 int len = strlen(in_drivers[i].prefix);
504                 if (strncmp(name, in_drivers[i].prefix, len) == 0) {
505                         drv_id = i;
506                         break;
507                 }
508         }
509
510         if (drv_id < 0) {
511                 printf("input: missing driver for %s\n", name);
512                 return -1;
513         }
514
515         for (i = 0; i < in_dev_count; i++)
516         {
517                 if (in_devices[i].name == NULL)
518                         continue;
519                 if (strcmp(in_devices[i].name, name) == 0)
520                         return i;
521         }
522
523         if (i >= IN_MAX_DEVS)
524         {
525                 /* try to find unused device */
526                 for (i = 0; i < IN_MAX_DEVS; i++)
527                         if (in_devices[i].name == NULL) break;
528                 if (i >= IN_MAX_DEVS) {
529                         printf("input: too many devices, can't add %s\n", name);
530                         return -1;
531                 }
532         }
533
534         memset(&in_devices[i], 0, sizeof(in_devices[i]));
535
536         in_devices[i].name = strdup(name);
537         if (in_devices[i].name == NULL)
538                 return -1;
539
540         if (i + 1 > in_dev_count)
541                 in_dev_count = i + 1;
542         in_devices[i].drv_id = drv_id;
543
544         return i;
545 }
546
547 /*
548  * To reduce size of game specific configs, default binds are not saved.
549  * So we mark default binds in in_config_start(), override them in in_config_bind_key(),
550  * and restore whatever default binds are left in in_config_end().
551  */
552 void in_config_start(void)
553 {
554         int i;
555
556         /* mark all default binds, so they get overwritten by func below */
557         for (i = 0; i < IN_MAX_DEVS; i++) {
558                 int n, count, *binds, *def_binds;
559
560                 binds = in_devices[i].binds;
561                 if (binds == NULL)
562                         continue;
563
564                 count = in_bind_count(in_devices[i].drv_id);
565                 def_binds = binds + count;
566
567                 for (n = 0; n < count; n++)
568                         if (binds[n] == def_binds[n])
569                                 binds[n] = -1;
570         }
571 }
572
573 int in_config_bind_key(int dev_id, const char *key, int binds)
574 {
575         int count, kc;
576         in_dev_t *dev;
577
578         if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
579                 return -1;
580         dev = &in_devices[dev_id];
581
582         count = in_bind_count(dev->drv_id);
583
584         /* maybe a raw code? */
585         if (key[0] == '\\' && key[1] == 'x') {
586                 char *p = NULL;
587                 kc = (int)strtoul(key + 2, &p, 16);
588                 if (p == NULL || *p != 0)
589                         kc = -1;
590         }
591         else {
592                 /* device specific key name */
593                 if (dev->binds == NULL) {
594                         dev->binds = in_alloc_binds(dev->drv_id);
595                         if (dev->binds == NULL)
596                                 return -1;
597                         in_config_start();
598                 }
599
600                 kc = DRV(dev->drv_id).get_key_code(key);
601                 if (kc < 0 && strlen(key) == 1) {
602                         /* assume scancode */
603                         kc = key[0];
604                 }
605         }
606
607         if (kc < 0 || kc >= count) {
608                 printf("input: bad key: %s\n", key);
609                 return -1;
610         }
611
612         if (dev->binds[kc] == -1)
613                 dev->binds[kc] = 0;
614         dev->binds[kc] |= binds;
615
616         return 0;
617 }
618
619 void in_config_end(void)
620 {
621         int i;
622
623         for (i = 0; i < IN_MAX_DEVS; i++) {
624                 int n, ret, count, *binds, *def_binds;
625                 in_dev_t *dev = &in_devices[i];
626
627                 if (dev->binds == NULL)
628                         continue;
629
630                 count = in_bind_count(dev->drv_id);
631                 binds = dev->binds;
632                 def_binds = binds + count;
633
634                 for (n = 0; n < count; n++)
635                         if (binds[n] == -1)
636                                 binds[n] = def_binds[n];
637
638                 if (dev->drv_data == NULL)
639                         continue;
640
641                 ret = DRV(dev->drv_id).clean_binds(dev->drv_data, binds);
642                 if (ret == 0) {
643                         /* no useable binds */
644                         free(dev->binds);
645                         dev->binds = NULL;
646                 }
647         }
648 }
649
650 void in_debug_dump(void)
651 {
652         int i;
653
654         printf("# drv probed binds name\n");
655         for (i = 0; i < IN_MAX_DEVS; i++) {
656                 in_dev_t *d = &in_devices[i];
657                 if (!d->probed && d->name == NULL && d->binds == NULL)
658                         continue;
659                 printf("%d %3d %6c %5c %s\n", i, d->drv_id, d->probed ? 'y' : 'n',
660                         d->binds ? 'y' : 'n', d->name);
661         }
662 }
663
664 /* handlers for unknown/not_preset drivers */
665
666 static void in_def_probe(void) {}
667 static void in_def_free(void *drv_data) {}
668 static int  in_def_get_bind_count(void) { return 0; }
669 static void in_def_get_def_binds(int *binds) {}
670 static int  in_def_clean_binds(void *drv_data, int *binds) { return 0; }
671 static void in_def_set_blocking(void *data, int y) {}
672 static int  in_def_update_keycode(void *drv_data, int *is_down) { return 0; }
673 static int  in_def_menu_translate(int keycode) { return keycode; }
674 static int  in_def_get_key_code(const char *key_name) { return 0; }
675 static const char *in_def_get_key_name(int keycode) { return NULL; }
676
677 void in_init(void)
678 {
679         int i;
680
681         memset(in_drivers, 0, sizeof(in_drivers));
682         memset(in_devices, 0, sizeof(in_devices));
683         in_dev_count = 0;
684
685         for (i = 0; i < IN_DRVID_COUNT; i++) {
686                 in_drivers[i].prefix = "none:";
687                 in_drivers[i].probe = in_def_probe;
688                 in_drivers[i].free = in_def_free;
689                 in_drivers[i].get_bind_count = in_def_get_bind_count;
690                 in_drivers[i].get_def_binds = in_def_get_def_binds;
691                 in_drivers[i].clean_binds = in_def_clean_binds;
692                 in_drivers[i].set_blocking = in_def_set_blocking;
693                 in_drivers[i].update_keycode = in_def_update_keycode;
694                 in_drivers[i].menu_translate = in_def_menu_translate;
695                 in_drivers[i].get_key_code = in_def_get_key_code;
696                 in_drivers[i].get_key_name = in_def_get_key_name;
697         }
698
699 #ifdef IN_GP2X
700         in_gp2x_init(&in_drivers[IN_DRVID_GP2X]);
701 #endif
702 #ifdef IN_EVDEV
703         in_evdev_init(&in_drivers[IN_DRVID_EVDEV]);
704 #endif
705 }
706
707 #if 0
708 int main(void)
709 {
710         int ret;
711
712         in_init();
713         in_probe();
714
715         in_set_blocking(1);
716
717 #if 1
718         while (1) {
719                 int dev = 0, down;
720                 ret = in_update_keycode(&dev, &down);
721                 printf("#%i: %i %i (%s)\n", dev, down, ret, in_get_key_name(dev, ret));
722         }
723 #else
724         while (1) {
725                 ret = in_menu_wait_any();
726                 printf("%08x\n", ret);
727         }
728 #endif
729
730         return 0;
731 }
732 #endif