more input wip
[libpicofe.git] / linux / in_evdev.c
CommitLineData
d92ea048 1#include <stdio.h>
2#include <string.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <sys/ioctl.h>
7#include <unistd.h>
8#include <linux/input.h>
9#include <errno.h>
10
34581c95 11#include "../common/common.h"
2258f158 12#include "../common/input.h"
34581c95 13#include "in_evdev.h"
d92ea048 14
d92ea048 15#define BIT(x) (keybits[(x)/sizeof(keybits[0])/8] & \
16 (1 << ((x) & (sizeof(keybits[0])*8-1))))
17
2258f158 18int in_evdev_probe(void)
d92ea048 19{
20 int i;
21
2258f158 22 for (i = 0;; i++)
d92ea048 23 {
24 int u, ret, fd, keybits[KEY_MAX/sizeof(int)];
25 int support = 0, count = 0;
26 char name[64];
27
28 snprintf(name, sizeof(name), "/dev/input/event%d", i);
29 fd = open(name, O_RDONLY|O_NONBLOCK);
30 if (fd == -1)
31 break;
32
33 /* check supported events */
34 ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support);
35 if (ret == -1) {
2258f158 36 printf("in_evdev: ioctl failed on %s\n", name);
d92ea048 37 goto skip;
38 }
39
40 if (!(support & (1 << EV_KEY)))
41 goto skip;
42
43 ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
44 if (ret == -1) {
2258f158 45 printf("in_evdev: ioctl failed on %s\n", name);
d92ea048 46 goto skip;
47 }
48
d92ea048 49 /* check for interesting keys */
50 for (u = 0; u < KEY_MAX; u++) {
2258f158 51 if (BIT(u) && u != KEY_POWER && u != KEY_SLEEP)
d92ea048 52 count++;
53 }
54
55 if (count == 0)
56 goto skip;
57
2258f158 58 strcpy(name, "evdev:");
59 ioctl(fd, EVIOCGNAME(sizeof(name)-6), name+6);
60 printf("in_evdev: found \"%s\" with %d events (type %08x)\n",
61 name+6, count, support);
62 in_register(name, IN_DRVID_EVDEV, (void *)fd);
d92ea048 63 continue;
64
65skip:
66 close(fd);
67 }
68
d92ea048 69 return 0;
70}
71
2258f158 72void in_evdev_free(void *drv_data)
73{
74 close((int)drv_data);
75}
76
77int in_evdev_bind_count(void)
d92ea048 78{
2258f158 79 return 512;
d92ea048 80}
81
2258f158 82int in_evdev_update(void *drv_data, int *binds)
d92ea048 83{
84 struct input_event ev[16];
2258f158 85 int keybits[KEY_MAX/sizeof(int)];
86 int fd = (int)drv_data;
87 int result = 0, changed = 0;
88 int rd, ret, u;
d92ea048 89
2258f158 90 while (1) {
91 rd = read(fd, ev, sizeof(ev));
92 if (rd < (int)sizeof(ev[0])) {
93 if (errno != EAGAIN)
94 perror("in_evdev: read failed");
95 break;
d92ea048 96 }
97
2258f158 98 changed = 1;
99 }
d92ea048 100
2258f158 101/*
102 if (!changed)
103 return 0;
104*/
105 ret = ioctl(fd, EVIOCGKEY(sizeof(keybits)), keybits);
106 if (ret == -1) {
107 perror("in_evdev: ioctl failed");
108 return 0;
109 }
d92ea048 110
2258f158 111 printf("#%d: ", fd);
112 for (u = 0; u < KEY_MAX; u++) {
113 if (BIT(u)) {
114 printf(" %d", u);
115 result |= binds[u];
d92ea048 116 }
d92ea048 117 }
2258f158 118 printf("\n");
d92ea048 119
120 return result;
121}
122
34581c95 123int in_evdev_update_menu(void **data, int count)
124{
125 const int *fds = (const int *)data;
126 static int result = 0;
127 int i, ret, fdmax = -1;
128 int oldresult = result;
129 long flags;
130
131 /* switch to blocking mode */
132 for (i = 0; i < count; i++) {
133 if (fds[i] > fdmax) fdmax = fds[i];
134
135 flags = (long)fcntl(fds[i], F_GETFL);
136 if ((int)flags == -1) {
137 perror("in_evdev: F_GETFL fcntl failed");
138 continue;
139 }
140 flags &= ~O_NONBLOCK;
141 ret = fcntl(fds[i], F_SETFL, flags);
142 if (ret == -1)
143 perror("in_evdev: F_SETFL fcntl failed");
144 }
145
146 while (1)
147 {
148 struct input_event ev[64];
149 int fd, rd;
150 fd_set fdset;
151
152 FD_ZERO(&fdset);
153 for (i = 0; i < count; i++)
154 FD_SET(fds[i], &fdset);
155
156 ret = select(fdmax + 1, &fdset, NULL, NULL, NULL);
157 if (ret == -1)
158 {
159 perror("in_evdev: select failed");
160 sleep(1);
161 return 0;
162 }
163
164 for (i = 0; i < count; i++)
165 if (FD_ISSET(fds[i], &fdset))
166 fd = fds[i];
167
168 rd = read(fd, ev, sizeof(ev[0]) * 64);
169 if (rd < (int) sizeof(ev[0])) {
170 perror("in_evdev: error reading");
171 sleep(1);
172 return 0;
173 }
174
175 #define mapkey(o,k) \
176 case o: \
177 if (ev[i].value) result |= k; \
178 else result &= ~k; \
179 break
180 for (i = 0; i < rd / sizeof(ev[0]); i++)
181 {
182 if (ev[i].type != EV_KEY || ev[i].value < 0 || ev[i].value > 1)
183 continue;
184
185 switch (ev[i].code) {
186 /* keyboards */
187 mapkey(KEY_UP, PBTN_UP);
188 mapkey(KEY_DOWN, PBTN_DOWN);
189 mapkey(KEY_LEFT, PBTN_LEFT);
190 mapkey(KEY_RIGHT, PBTN_RIGHT);
191 mapkey(KEY_ENTER, PBTN_EAST);
192 mapkey(KEY_ESC, PBTN_SOUTH);
193 }
194 }
195 #undef mapkey
196
197 if (oldresult != result) break;
198 }
199
200 /* switch back to non-blocking mode */
201 for (i = 0; i < count; i++) {
202 if (fds[i] > fdmax) fdmax = fds[i];
203
204 flags = (long)fcntl(fds[i], F_GETFL);
205 if ((int)flags == -1) {
206 perror("in_evdev: F_GETFL fcntl failed");
207 continue;
208 }
209 flags |= O_NONBLOCK;
210 ret = fcntl(fds[i], F_SETFL, flags);
211 if (ret == -1)
212 perror("in_evdev: F_SETFL fcntl failed");
213 }
214
215 return result;
216}
217