some input framework attempt
[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/event.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 #ifdef IN_EVDEV
27         if (drv_id == IN_DRVID_EVDEV)
28                 count = in_evdev_bind_count();
29 #endif
30         if (count <= 0)
31                 printf("input: failed to get bind count for drv %d\n", drv_id);
32
33         return count;
34 }
35
36 static int *in_alloc_binds(int drv_id)
37 {
38         int count, *ret;
39
40         count = in_bind_count(drv_id);
41         if (count <= 0) {
42                 printf("input: failed to get bind count for drv %d\n", drv_id);
43                 return NULL;
44         }
45
46         ret = malloc(count * sizeof(*ret));
47         return ret;
48 }
49
50 static void in_free(in_dev_t *dev)
51 {
52         if (dev->probed) {
53 #ifdef IN_EVDEV
54                 if (dev->drv_id == IN_DRVID_EVDEV)
55                         in_evdev_free(dev->drv_data);
56 #endif
57         }
58         dev->probed = 0;
59         dev->drv_data = NULL;
60         free(dev->name);
61         dev->name = NULL;
62         free(dev->binds);
63         dev->binds = NULL;
64 }
65
66 /* to be called by drivers */
67 void in_register(const char *nname, int drv_id, void *drv_data)
68 {
69         int i, dupe_count = 0, *binds;
70         char name[256], *name_end, *tmp;
71
72         strncpy(name, nname, sizeof(name));
73         name[sizeof(name)-12] = 0;
74         name_end = name + strlen(name);
75
76         for (i = 0; i < in_dev_count; i++)
77         {
78                 if (in_devices[i].name == NULL)
79                         continue;
80                 if (strcmp(in_devices[i].name, name) == 0)
81                 {
82                         if (in_devices[i].probed) {
83                                 dupe_count++;
84                                 sprintf(name_end, " [%d]", dupe_count);
85                                 continue;
86                         }
87                         goto update;
88                 }
89         }
90
91         if (i >= IN_MAX_DEVS)
92         {
93                 /* try to find unused device */
94                 for (i = 0; i < IN_MAX_DEVS; i++)
95                         if (!in_devices[i].probed) break;
96                 if (i >= IN_MAX_DEVS) {
97                         printf("input: too many devices, can't add %s\n", name);
98                         return;
99                 }
100                 in_free(&in_devices[i]);
101         }
102
103         tmp = strdup(name);
104         if (tmp == NULL)
105                 return;
106
107         binds = in_alloc_binds(drv_id);
108         if (binds == NULL) {
109                 free(tmp);
110                 return;
111         }
112
113         in_devices[i].name = tmp;
114         in_devices[i].binds = binds;
115         if (i + 1 > in_dev_count)
116                 in_dev_count = i + 1;
117
118         printf("input: new device #%d \"%s\"\n", i, name);
119 update:
120         in_devices[i].probed = 1;
121         in_devices[i].drv_id = drv_id;
122         in_devices[i].drv_data = drv_data;
123 }
124
125 void in_probe(void)
126 {
127         int i;
128         for (i = 0; i < in_dev_count; i++)
129                 in_devices[i].probed = 0;
130
131 #ifdef IN_EVDEV
132         in_evdev_probe();
133 #endif
134
135         /* get rid of devs without binds and probes */
136         for (i = 0; i < in_dev_count; i++) {
137                 if (!in_devices[i].probed && in_devices[i].binds == NULL) {
138                         in_dev_count--;
139                         if (i < in_dev_count) {
140                                 free(in_devices[i].name);
141                                 memmove(&in_devices[i], &in_devices[i+1],
142                                         (in_dev_count - i) * sizeof(in_devices[0]));
143                         }
144                 }
145         }
146 }
147
148 void in_clear_binds(const char *devname)
149 {
150 /*      int count;
151
152         count = in_bind_count(drv_id);
153         if (count <= 0) {
154                 printf("input: failed to get bind count for drv %d\n", dev->drv_id);
155                 return NULL;
156         }
157 */
158 }
159
160 int in_update(void)
161 {
162         int i, result = 0;
163
164         for (i = 0; i < in_dev_count; i++) {
165                 if (in_devices[i].probed && in_devices[i].binds != NULL) {
166 #ifdef IN_EVDEV
167                         result |= in_evdev_update(in_devices[i].drv_data, in_devices[i].binds);
168 #endif
169                 }
170         }
171
172         return result;
173 }
174
175 void in_init(void)
176 {
177         memset(in_devices, 0, sizeof(in_devices));
178         in_dev_count = 0;
179 }
180
181 int main(void)
182 {
183         in_init();
184         in_probe();
185
186         while (1) {
187                 in_update();
188                 sleep(1);
189         }
190
191         return 0;
192 }
193