Tune xwiimote handling
[wiimote-pad] / wiimote-pad.c
1 /*
2  * Wiimote-Pad
3  *
4  * Copyright (C) 2013 Giuseppe Bilotta
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21
22 #include <libudev.h>
23 #include <linux/input.h>
24 #include <linux/uinput.h>
25
26 #include <sys/select.h>
27 #include <fcntl.h>
28 #include <glob.h>
29 #include <errno.h>
30 #include <signal.h>
31
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <unistd.h>
36
37 #include <xwiimote.h>
38
39 /* These definitions might be missing from older linux/input.h headers */
40 #ifndef BTN_DPAD_LEFT
41 #define BTN_DPAD_LEFT 0x222
42 #endif
43 #ifndef BTN_DPAD_RIGHT
44 #define BTN_DPAD_RIGHT 0x223
45 #endif
46 #ifndef BTN_DPAD_UP
47 #define BTN_DPAD_UP 0x220
48 #endif
49 #ifndef BTN_DPAD_DOWN
50 #define BTN_DPAD_DOWN 0x221
51 #endif
52
53 #define WIIMOTE_PADMODE_VENDOR_ID 0x6181 /* GIuseppe BIlotta */
54 #define WIIMOTE_PADMODE_DEVICE_ID 0x3169 /* WIimote GamePad */
55
56 /* Check if an error \code is negative during \str action */
57 void err_check(int code, char const *str) {
58         if (code < 0) {
59                 int err = errno;
60                 fprintf(stderr, "could not %s (%d): %s\n",
61                         str, err, strerror(err));
62                 exit(-err);
63         }
64 }
65
66 #define BUTTONS do { \
67         _BUTTON(XWII_KEY_LEFT, BTN_DPAD_LEFT); \
68         _BUTTON(XWII_KEY_RIGHT, BTN_DPAD_RIGHT); \
69         _BUTTON(XWII_KEY_UP, BTN_DPAD_UP); \
70         _BUTTON(XWII_KEY_DOWN, BTN_DPAD_DOWN); \
71         _BUTTON(XWII_KEY_A, BTN_A); \
72         _BUTTON(XWII_KEY_B, BTN_B); \
73         _BUTTON(XWII_KEY_PLUS, BTN_TL); \
74         _BUTTON(XWII_KEY_MINUS, BTN_TR); \
75         _BUTTON(XWII_KEY_HOME, BTN_MODE); \
76         _BUTTON(XWII_KEY_ONE, BTN_1); \
77         _BUTTON(XWII_KEY_TWO, BTN_2); \
78 } while (0)
79
80
81 struct uinput_user_dev padmode;
82 /* Room for controller keys and two axes, plus SYN */
83 struct input_event iev[XWII_KEY_TWO+2+1+1];
84
85 /* macros to set evbits and keybits */
86 #define set_ev(key) do { \
87         ret = ioctl(fd, UI_SET_EVBIT, key); \
88         err_check(ret, "set " #key); \
89 } while(0)
90
91 #define set_key(key) do { \
92         ret = ioctl(fd, UI_SET_KEYBIT, key); \
93         err_check(ret, "set " #key); \
94 } while(0)
95
96 #define set_abs(key, min, max, fuzz, flat) do { \
97         ret = ioctl(fd, UI_SET_ABSBIT, key); \
98         err_check(ret, "set " #key); \
99         padmode.absmin[key] = min; \
100         padmode.absmax[key] = max; \
101         padmode.absfuzz[key] = fuzz; \
102         padmode.absflat[key] = flat; \
103 } while(0)
104
105 #define AXIS_MAX 100
106
107 struct wiimote_dev {
108         const char *device;
109         char *root;
110
111         int dev_id;
112
113         int uinput;
114
115         struct xwii_iface *iface;
116         unsigned int ifs;
117         int fd;
118 };
119
120 #define MAX_WIIMOTES 1
121 struct wiimote_dev dev[MAX_WIIMOTES];
122
123 void dev_init(struct wiimote_dev const *dev) {
124         int ret;
125         int fd = dev->uinput;
126
127 #define _BUTTON(n, bt) do { \
128         set_key(bt); \
129         iev[n].type = EV_KEY; \
130         iev[n].code = bt; \
131 } while (0)
132         set_ev(EV_KEY);
133         BUTTONS;
134         set_ev(EV_SYN);
135 #undef _BUTTON
136
137         set_ev(EV_ABS);
138         set_abs(ABS_X, -AXIS_MAX, AXIS_MAX, 2, 4);
139         iev[11].type = EV_ABS;
140         iev[11].code = ABS_X;
141         set_abs(ABS_Y, -AXIS_MAX, AXIS_MAX, 2, 4);
142         iev[12].type = EV_ABS;
143         iev[12].code = ABS_Y;
144
145         iev[13].type = EV_SYN;
146         iev[13].code = iev[13].value = 0;
147
148         snprintf(padmode.name, UINPUT_MAX_NAME_SIZE, XWII_NAME_CORE " in gamepad mode");
149         padmode.id.bustype = BUS_VIRTUAL;
150         /*
151         padmode.id.vendor = 0;
152         padmode.id.product = 0;
153         padmode.id.version = 0;
154         */
155
156         ret = write(fd, &padmode, sizeof(padmode));
157         err_check(ret, "set dev properties");
158         ret = ioctl(fd, UI_DEV_CREATE);
159         err_check(ret, "create device");
160 }
161
162
163 static int wiimote_refresh(struct wiimote_dev *dev)
164 {
165         puts("Refreshing\n");
166         return xwii_iface_open(dev->iface, dev->ifs);
167 }
168
169 static void wiimote_key(struct wiimote_dev *dev, struct xwii_event const *ev)
170 {
171         unsigned int code;
172         unsigned int state;
173
174         code = ev->v.key.code;
175         state = ev->v.key.state;
176
177         if (code > XWII_KEY_TWO)
178                 return;
179         if (state > 1)
180                 return;
181         iev[code].value = state;
182
183         if (dev->uinput > 0) {
184                 int ret = write(dev->uinput, iev + code, sizeof(*iev));
185                 err_check(ret, "report button");
186                 ret = write(dev->uinput, iev + 13, sizeof(*iev));
187                 err_check(ret, "report btn SYN");
188         } else {
189                 fputs("nowhere to report butto presses to\n", stderr);
190         }
191 }
192
193 #define CLIP_AXIS(val) do { \
194         if (val < -AXIS_MAX) \
195                 val = -AXIS_MAX; \
196         if (val > AXIS_MAX) \
197                 val = AXIS_MAX; \
198 } while (0)
199
200
201 static void wiimote_accel(struct wiimote_dev *dev, struct xwii_event const *ev)
202 {
203         iev[11].value = -(ev->v.abs[0].y);
204         iev[12].value = -(ev->v.abs[0].x);
205
206         CLIP_AXIS(iev[11].value);
207         CLIP_AXIS(iev[12].value);
208
209         if (dev->uinput > 0) {
210                 int ret = write(dev->uinput, iev + 11, sizeof(*iev));
211                 err_check(ret, "report accel X");
212                 ret = write(dev->uinput, iev + 12, sizeof(*iev));
213                 err_check(ret, "report accel Y");
214                 ret = write(dev->uinput, iev + 13, sizeof(*iev));
215                 err_check(ret, "report accel SYN");
216 #if 0
217                 printf("reported J (%d, %d) from ev (%d, %d)\n",
218                         iev[11].value, iev[12].value,
219                         -(ev->v.abs[0].y), ev->v.abs[0].x);
220 #endif
221         } else {
222                 fputs("nowhere to report accel to\n", stderr);
223         }
224 }
225
226 static int wiimote_poll(struct wiimote_dev *dev)
227 {
228         struct xwii_event ev;
229         int ret;
230
231         do {
232                 memset(&ev, 0, sizeof(ev));
233                 ret = xwii_iface_dispatch(dev->iface, &ev, sizeof(ev));
234
235                 if (ret)
236                         break;
237
238                 switch (ev.type) {
239                 case XWII_EVENT_WATCH:
240                         ret = wiimote_refresh(dev);
241                         break;
242                 case XWII_EVENT_KEY:
243                         wiimote_key(dev, &ev);
244                         break;
245                 case XWII_EVENT_ACCEL:
246                         wiimote_accel(dev, &ev);
247                         break;
248                 default:
249                         printf("Unhandled Wiimote event type %d\n", ev.type);
250                 }
251         } while (!ret);
252
253         if (ret == -EAGAIN) {
254                 ret = 0;
255         }
256
257         return ret;
258 }
259
260 int dev_create(struct wiimote_dev *dev) {
261         int ret = 0;
262         struct udev *udev;
263         struct udev_device *d, *p;
264         struct stat st;
265         const char *root, *snum, *driver, *subs;
266         int num;
267
268         if (!dev->device) {
269                 ret = EINVAL;
270                 goto exit;
271         }
272
273         if (stat(dev->device, &st)) {
274                 ret = errno;
275                 goto exit;
276         }
277
278         udev = udev_new();
279         if (!udev) {
280                 fputs("could not connect to udev\n", stderr);
281                 ret = errno;
282                 goto exit;
283         }
284
285         d = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
286         if (!d) {
287                 fputs("could not find udev device\n", stderr);
288                 ret = errno;
289                 goto exit_udev;
290         }
291
292         p = udev_device_get_parent_with_subsystem_devtype(d, "hid", NULL);
293         if (!p) {
294                 fputs("could not find parent HID device\n", stderr);
295                 ret = errno;
296                 goto exit_dev;
297         }
298
299         driver = udev_device_get_driver(p);
300         subs = udev_device_get_subsystem(p);
301         if (!driver || strcmp(driver, "wiimote") || !subs || strcmp(subs, "hid")) {
302                 fputs("parent is not a HID Wiimote\n", stderr);
303                 ret = errno;
304                 goto exit_dev;
305         }
306
307         root = udev_device_get_syspath(p);
308         snum = udev_device_get_sysname(p);
309         snum = snum ? strchr(snum, '.') : NULL;
310         if (!root || !snum) {
311                 fputs("Could not get root path\n", stderr);
312                 ret = errno;
313                 goto exit_dev;
314         }
315
316         num = strtol(&snum[1], NULL, 16);
317         if (num < 0) {
318                 fputs("Negative device number!\n", stderr);
319                 ret = errno;
320                 goto exit_dev;
321         }
322         dev->dev_id = num;
323
324         dev->root = strdup(root);
325         if (!dev->root) {
326                 fputs("Could not set device root\n", stderr);
327                 ret = errno;
328                 goto exit_dev;
329         }
330
331         printf("using device %d from root %s for %s\n",
332                 dev->dev_id, dev->root, dev->device);
333
334         dev->ifs = XWII_IFACE_CORE | XWII_IFACE_ACCEL;
335         ret = xwii_iface_new(&dev->iface, dev->root);
336         if (ret) {
337                 fputs("Could not create xwiimote interface\n", stderr);
338                 ret = errno;
339                 goto exit_wii;
340         }
341
342         ret = xwii_iface_open(dev->iface, dev->ifs);
343         if (ret) {
344                 fputs("Could not open xwiimote interface\n", stderr);
345                 ret = errno;
346                 goto exit_wii;
347         }
348         if (xwii_iface_opened(dev->iface) != dev->ifs) {
349                 fputs("Some interfaces failed to open\n", stderr);
350                 ret = errno;
351                 goto exit_wii;
352         }
353
354         dev->fd = xwii_iface_get_fd(dev->iface);
355
356         goto exit_dev;
357
358 exit_wii:
359         free(dev->root);
360         dev->root = NULL;
361
362 exit_dev:
363         udev_device_unref(d);
364 exit_udev:
365         udev_unref(udev);
366 exit:
367         return ret;
368 }
369
370 static void dev_destroy(struct wiimote_dev *dev) {
371         if (dev->root) {
372                 xwii_iface_unref(dev->iface);
373                 free(dev->root);
374                 dev->root = NULL;
375         }
376         if (dev->uinput > 0) {
377                 ioctl(dev->uinput, UI_DEV_DESTROY);
378                 close(dev->uinput);
379         }
380         printf("deassociated from device %s\n", dev->device);
381 }
382
383 glob_t js_devs;
384
385 static void destroy_all_devs(void) {
386 #if MAX_WIIMOTES > 1
387 #error "destroy_all_devs only works for a single device"
388 #endif
389         dev_destroy(dev);
390         globfree(&js_devs);
391 }
392
393 static int last_signal;
394
395 static void sig_exit(int _signal) {
396         last_signal = _signal;
397         printf("Interrupted by signal %d\n", last_signal);
398 }
399
400 struct timeval no_wait;
401
402 const char uinput_path[] = "/dev/uinput";
403
404 const char js_glob[] = "/dev/input/js*";
405
406 int main(int argc, char *argv[]) {
407         int ret;
408         size_t j;
409         fd_set fds[1];
410
411         atexit(destroy_all_devs);
412         signal(SIGINT, sig_exit);
413
414         if (argc > 1) {
415                 dev->device = argv[1];
416                 ret = dev_create(dev);
417
418                 if (ret) {
419                         fprintf(stderr, "could not %s (%d): %s\n",
420                                 "associate", ret, strerror(ret));
421                         return ret;
422                 }
423         } else {
424                 /* No device specified. Since the Linux kernel exposes the
425                  * controller also as a joystick (without axes), we peek at
426                  * all available joysticks looking for one which is a Wiimote
427                  */
428
429                 switch (glob(js_glob, GLOB_NOSORT, NULL, &js_devs)) {
430                 case GLOB_ABORTED:
431                 case GLOB_NOMATCH:
432                 case GLOB_NOSPACE:
433                         fputs("no joysticks found\n", stderr);
434                         exit(ENODEV);
435                 }
436
437                 for (j = 0; j < js_devs.gl_pathc; ++j) {
438                         dev->device = js_devs.gl_pathv[j];
439                         ret = dev_create(dev);
440                         if (!ret)
441                                 break; /* found */
442                         printf("skipping %s (%d): %s\n",
443                                 dev->device, ret, strerror(ret));
444                         dev->device = NULL;
445                 }
446                 if (!dev->device) {
447                         fputs("no wiimote found\n", stderr);
448                         exit(ENODEV);
449                 }
450         }
451
452         dev->uinput = open(uinput_path, O_WRONLY | O_NONBLOCK);
453         err_check(dev->uinput, "open uinput");
454
455         dev_init(dev);
456
457         do {
458                 memset(&no_wait, 0, sizeof(no_wait));
459                 FD_ZERO(fds);
460                 FD_SET(dev->fd, fds);
461
462                 if (last_signal)
463                         break;
464                 ret = select(dev->fd + 1, fds, NULL, NULL, NULL);
465                 err_check(ret, "poll wiimote fd");
466                 if (ret > 0) {
467                         ret = wiimote_poll(dev);
468                         err_check(ret, "process wiimote data");
469                 }
470         } while (1);
471
472         return ret;
473 }
474