more input wip
[libpicofe.git] / common / input.c
CommitLineData
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
8typedef 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
20static in_dev_t in_devices[IN_MAX_DEVS];
21static int in_dev_count = 0;
22
23static int in_bind_count(int drv_id)
24{
25 int count = 0;
2258f158 26 if (drv_id == IN_DRVID_EVDEV)
27 count = in_evdev_bind_count();
2258f158 28 if (count <= 0)
29 printf("input: failed to get bind count for drv %d\n", drv_id);
30
31 return count;
32}
33
34static int *in_alloc_binds(int drv_id)
35{
36 int count, *ret;
37
38 count = in_bind_count(drv_id);
39 if (count <= 0) {
40 printf("input: failed to get bind count for drv %d\n", drv_id);
41 return NULL;
42 }
43
44 ret = malloc(count * sizeof(*ret));
45 return ret;
46}
47
48static void in_free(in_dev_t *dev)
49{
50 if (dev->probed) {
2258f158 51 if (dev->drv_id == IN_DRVID_EVDEV)
52 in_evdev_free(dev->drv_data);
2258f158 53 }
54 dev->probed = 0;
55 dev->drv_data = NULL;
56 free(dev->name);
57 dev->name = NULL;
58 free(dev->binds);
59 dev->binds = NULL;
60}
61
62/* to be called by drivers */
63void in_register(const char *nname, int drv_id, void *drv_data)
64{
65 int i, dupe_count = 0, *binds;
66 char name[256], *name_end, *tmp;
67
68 strncpy(name, nname, sizeof(name));
69 name[sizeof(name)-12] = 0;
70 name_end = name + strlen(name);
71
72 for (i = 0; i < in_dev_count; i++)
73 {
74 if (in_devices[i].name == NULL)
75 continue;
76 if (strcmp(in_devices[i].name, name) == 0)
77 {
78 if (in_devices[i].probed) {
79 dupe_count++;
80 sprintf(name_end, " [%d]", dupe_count);
81 continue;
82 }
83 goto update;
84 }
85 }
86
87 if (i >= IN_MAX_DEVS)
88 {
89 /* try to find unused device */
90 for (i = 0; i < IN_MAX_DEVS; i++)
91 if (!in_devices[i].probed) break;
92 if (i >= IN_MAX_DEVS) {
93 printf("input: too many devices, can't add %s\n", name);
94 return;
95 }
96 in_free(&in_devices[i]);
97 }
98
99 tmp = strdup(name);
100 if (tmp == NULL)
101 return;
102
103 binds = in_alloc_binds(drv_id);
104 if (binds == NULL) {
105 free(tmp);
106 return;
107 }
108
109 in_devices[i].name = tmp;
110 in_devices[i].binds = binds;
111 if (i + 1 > in_dev_count)
112 in_dev_count = i + 1;
113
114 printf("input: new device #%d \"%s\"\n", i, name);
115update:
116 in_devices[i].probed = 1;
117 in_devices[i].drv_id = drv_id;
118 in_devices[i].drv_data = drv_data;
119}
120
121void in_probe(void)
122{
123 int i;
124 for (i = 0; i < in_dev_count; i++)
125 in_devices[i].probed = 0;
126
2258f158 127 in_evdev_probe();
2258f158 128
129 /* get rid of devs without binds and probes */
130 for (i = 0; i < in_dev_count; i++) {
131 if (!in_devices[i].probed && in_devices[i].binds == NULL) {
132 in_dev_count--;
133 if (i < in_dev_count) {
134 free(in_devices[i].name);
135 memmove(&in_devices[i], &in_devices[i+1],
136 (in_dev_count - i) * sizeof(in_devices[0]));
137 }
138 }
139 }
140}
141
142void in_clear_binds(const char *devname)
143{
144/* int count;
145
146 count = in_bind_count(drv_id);
147 if (count <= 0) {
148 printf("input: failed to get bind count for drv %d\n", dev->drv_id);
149 return NULL;
150 }
151*/
152}
153
154int in_update(void)
155{
156 int i, result = 0;
157
158 for (i = 0; i < in_dev_count; i++) {
159 if (in_devices[i].probed && in_devices[i].binds != NULL) {
34581c95 160 if (in_devices[i].drv_id == IN_DRVID_EVDEV)
161 result |= in_evdev_update(in_devices[i].drv_data, in_devices[i].binds);
2258f158 162 }
163 }
164
165 return result;
166}
167
34581c95 168/*
169 * update with wait for a press, return bitfield of BTN_*
170 * only can use 1 drv here..
171 */
172int in_update_menu(void)
173{
174 int result = 0;
175#ifdef IN_EVDEV
176 void *data[IN_MAX_DEVS];
177 int i, count = 0;
178
179 for (i = 0; i < in_dev_count; i++) {
180 if (in_devices[i].probed)
181 data[count++] = in_devices[i].drv_data;
182 }
183
184 if (count == 0) {
185 /* don't deadlock, fail */
186 printf("input: failed to find devices to read\n");
187 exit(1);
188 }
189
190 result = in_evdev_update_menu(data, count);
191#else
192#error no menu read handlers
193#endif
194
195 return result;
196}
197
2258f158 198void in_init(void)
199{
200 memset(in_devices, 0, sizeof(in_devices));
201 in_dev_count = 0;
202}
203
204int main(void)
205{
34581c95 206 int ret;
207
2258f158 208 in_init();
209 in_probe();
210
211 while (1) {
34581c95 212 ret = in_update_menu();
213 printf("%08x\n", ret);
2258f158 214 sleep(1);
215 }
216
217 return 0;
218}
219