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