more input wip
[libpicofe.git] / common / input.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "input.h"
6 #include "../linux/in_evdev.h"
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;
26         if (drv_id == IN_DRVID_EVDEV)
27                 count = in_evdev_bind_count();
28         if (count <= 0)
29                 printf("input: failed to get bind count for drv %d\n", drv_id);
30
31         return count;
32 }
33
34 static 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
48 static void in_free(in_dev_t *dev)
49 {
50         if (dev->probed) {
51                 if (dev->drv_id == IN_DRVID_EVDEV)
52                         in_evdev_free(dev->drv_data);
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 */
63 void 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);
115 update:
116         in_devices[i].probed = 1;
117         in_devices[i].drv_id = drv_id;
118         in_devices[i].drv_data = drv_data;
119 }
120
121 void in_probe(void)
122 {
123         int i;
124         for (i = 0; i < in_dev_count; i++)
125                 in_devices[i].probed = 0;
126
127         in_evdev_probe();
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
142 void 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
154 int 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) {
160                         if (in_devices[i].drv_id == IN_DRVID_EVDEV)
161                                 result |= in_evdev_update(in_devices[i].drv_data, in_devices[i].binds);
162                 }
163         }
164
165         return result;
166 }
167
168 /* 
169  * update with wait for a press, return bitfield of BTN_*
170  * only can use 1 drv here..
171  */
172 int 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
198 void in_init(void)
199 {
200         memset(in_devices, 0, sizeof(in_devices));
201         in_dev_count = 0;
202 }
203
204 int main(void)
205 {
206         int ret;
207
208         in_init();
209         in_probe();
210
211         while (1) {
212                 ret = in_update_menu();
213                 printf("%08x\n", ret);
214                 sleep(1);
215         }
216
217         return 0;
218 }
219