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