teensytp: configurable gamepads
[megadrive.git] / teensytp / host / main.c
1 /*
2  * TeensyTP, Team Player/4-Player Adaptor implementation for Teensy3
3  * host part
4  * Copyright (c) 2015 notaz
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdint.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <sys/ioctl.h>
35 #include <sys/select.h>
36 #include <unistd.h>
37 #include <dirent.h>
38 #include <signal.h>
39 #include <termios.h>
40 #include <errno.h>
41 #include <linux/usbdevice_fs.h>
42 #include <linux/usb/ch9.h>
43 #include <linux/input.h>
44 #include "../pkts.h"
45
46 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
47
48 struct teensy_dev {
49   int fd;
50   struct {
51     int ep_in;
52     int ep_out;
53   } ifaces[2];
54 };
55
56 /* return 1 if found, 0 if not, < 0 on error */
57 static int find_device(struct teensy_dev *dev,
58   uint16_t vendor, uint16_t product)
59 {
60   const char path_root[] = "/dev/bus/usb";
61   union {
62     struct usb_descriptor_header hdr;
63     struct usb_device_descriptor d;
64     struct usb_config_descriptor c;
65     struct usb_interface_descriptor i;
66     struct usb_endpoint_descriptor e;
67     char space[0x100]; /* enough? */
68   } desc;
69   char path_bus[256], path_dev[256];
70   struct dirent *ent, *ent_bus;
71   DIR *dir = NULL, *dir_bus = NULL;
72   int num, fd = -1;
73   int iface = -1;
74   int retval = -1;
75   int ret;
76
77   memset(dev, 0xff, sizeof(*dev));
78
79   dir = opendir(path_root);
80   if (dir == NULL) {
81     perror("opendir");
82     return -1;
83   }
84
85   for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
86     /* should be a number like 000 */
87     if (sscanf(ent->d_name, "%03d", &num) != 1)
88       continue;
89
90     snprintf(path_bus, sizeof(path_bus), "%s/%s",
91         path_root, ent->d_name);
92
93     dir_bus = opendir(path_bus);
94     if (dir_bus == NULL)
95       continue;
96
97     ent_bus = readdir(dir_bus);
98     for (; ent_bus != NULL; ent_bus = readdir(dir_bus)) {
99       if (sscanf(ent->d_name, "%03d", &num) != 1)
100         continue;
101
102       snprintf(path_dev, sizeof(path_dev), "%s/%s/%s",
103           path_root, ent->d_name, ent_bus->d_name);
104
105       fd = open(path_dev, O_RDWR);
106       if (fd == -1)
107         continue;
108
109       ret = read(fd, &desc.d, sizeof(desc.d));
110       if (ret != sizeof(desc.d)) {
111         fprintf(stderr, "desc read: %d/%zd: ", ret, sizeof(desc.d));
112         perror("");
113         goto next;
114       }
115
116       if (desc.d.bDescriptorType != USB_DT_DEVICE) {
117         fprintf(stderr, "%s: bad DT: 0x%02x\n",
118             path_dev, desc.d.bDescriptorType);
119         goto next;
120       }
121
122       if (desc.d.idVendor == vendor && desc.d.idProduct == product)
123         goto found;
124
125 next:
126       close(fd);
127       fd = -1;
128     }
129
130     closedir(dir_bus);
131     dir_bus = NULL;
132   }
133
134   /* not found */
135   retval = 0;
136   goto out;
137
138 found:
139   if (desc.d.bNumConfigurations != 1) {
140     fprintf(stderr, "unexpected bNumConfigurations: %u\n",
141         desc.d.bNumConfigurations);
142     goto out;
143   }
144
145   /* walk through all descriptors */
146   while (1)
147   {
148     ret = read(fd, &desc.hdr, sizeof(desc.hdr));
149     if (ret == 0)
150       break;
151     if (ret != sizeof(desc.hdr)) {
152       fprintf(stderr, "desc.hdr read: %d/%zd: ", ret, sizeof(desc.hdr));
153       perror("");
154       break;
155     }
156
157     ret = (int)lseek(fd, -sizeof(desc.hdr), SEEK_CUR);
158     if (ret == -1) {
159       perror("lseek");
160       break;
161     }
162
163     ret = read(fd, &desc, desc.hdr.bLength);
164     if (ret != desc.hdr.bLength) {
165       fprintf(stderr, "desc read: %d/%u: ", ret, desc.hdr.bLength);
166       perror("");
167       break;
168     }
169
170     switch (desc.hdr.bDescriptorType) {
171       case USB_DT_CONFIG:
172         if (desc.c.bNumInterfaces != 2) {
173           fprintf(stderr, "unexpected bNumInterfaces: %u\n",
174               desc.c.bNumInterfaces);
175           goto out;
176         }
177         break;
178
179       case USB_DT_INTERFACE:
180         if (desc.i.bInterfaceClass != USB_CLASS_HID
181             || desc.i.bInterfaceSubClass != 0
182             || desc.i.bInterfaceProtocol != 0) {
183           fprintf(stderr, "unexpected interface %x:%x:%x\n",
184             desc.i.bInterfaceClass, desc.i.bInterfaceSubClass,
185             desc.i.bInterfaceProtocol);
186           goto out;
187         }
188         if (desc.i.bNumEndpoints != 2) {
189           fprintf(stderr, "unexpected bNumEndpoints: %u\n",
190             desc.i.bNumEndpoints);
191           goto out;
192         }
193         iface++;
194         break;
195
196       case USB_DT_ENDPOINT:
197         if (iface < 0 || iface >= ARRAY_SIZE(dev->ifaces)) {
198           fprintf(stderr, "bad iface: %d\n", iface);
199           goto out;
200         }
201         if (desc.e.wMaxPacketSize != 64 && desc.e.wMaxPacketSize != 32) {
202           fprintf(stderr, "iface %d, EP %02x: "
203             "unexpected wMaxPacketSize: %u\n",
204             iface, desc.e.bEndpointAddress, desc.e.wMaxPacketSize);
205           goto out;
206         }
207         if (desc.e.bEndpointAddress & 0x80)
208           dev->ifaces[iface].ep_in = desc.e.bEndpointAddress; // & 0x7F;
209         else
210           dev->ifaces[iface].ep_out = desc.e.bEndpointAddress;
211         break;
212
213       case 0x21:
214         /* ignore */
215         break;
216
217       default:
218         fprintf(stderr, "skipping desc 0x%02x\n",
219           desc.hdr.bDescriptorType);
220         break;
221     }
222   }
223
224   /* claim interfaces */
225   for (iface = 0; iface < ARRAY_SIZE(dev->ifaces); iface++) {
226     struct usbdevfs_ioctl usbio;
227
228     if (dev->ifaces[iface].ep_in == -1) {
229       fprintf(stderr, "missing ep_in, iface: %d\n", iface);
230       goto out;
231     }
232     if (dev->ifaces[iface].ep_out == -1) {
233       fprintf(stderr, "missing ep_out, iface: %d\n", iface);
234       goto out;
235     }
236
237     /* disconnect default driver */
238     memset(&usbio, 0, sizeof(usbio));
239     usbio.ifno = iface;
240     usbio.ioctl_code = USBDEVFS_DISCONNECT;
241     ret = ioctl(fd, USBDEVFS_IOCTL, &usbio);
242     if (ret != 0 && errno != ENODATA)
243       perror("USBDEVFS_DISCONNECT");
244
245     ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &iface);
246     if (ret != 0)
247       perror("USBDEVFS_CLAIMINTERFACE");
248   }
249
250   dev->fd = fd;
251   fd = -1;
252   retval = 1;
253
254 out:
255   if (fd != -1)
256     close(fd);
257   if (dir_bus != NULL)
258     closedir(dir_bus);
259   if (dir != NULL)
260     closedir(dir);
261
262   return retval;
263 }
264
265 static int enable_echo(int enable)
266 {
267   const char *portname = "/dev/tty";
268   struct termios tty;
269   int retval = -1;
270   int ret;
271   int fd;
272
273   memset(&tty, 0, sizeof(tty));
274
275   fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
276   if (fd < 0) {
277     fprintf(stderr, "open %s: ", portname);
278     perror("");
279     return 1;
280   }
281
282   ret = tcgetattr(fd, &tty);
283   if (ret != 0) {
284     perror("tcgetattr");
285     goto out;
286   }
287
288   // printf("lflag: 0%o\n", tty.c_lflag);
289   if (enable)
290     tty.c_lflag |= ECHO | ICANON;
291   else {
292     tty.c_lflag &= ~(ECHO | ICANON);
293     tty.c_cc[VMIN] = tty.c_cc[VTIME] = 0;
294   }
295
296   ret = tcsetattr(fd, TCSANOW, &tty);
297   if (ret != 0) {
298     perror("tcsetattr");
299     goto out;
300   }
301
302   retval = 0;
303 out:
304   close(fd);
305
306   return retval;
307 }
308
309 static int g_exit;
310
311 static void signal_handler(int sig)
312 {
313   g_exit = 1;
314   signal(sig, SIG_DFL);
315 }
316
317 /* MXYZ SACB RLDU */
318 enum mdbtn {
319   MDBTN_UP    = (1 <<  0),
320   MDBTN_DOWN  = (1 <<  1),
321   MDBTN_LEFT  = (1 <<  2),
322   MDBTN_RIGHT = (1 <<  3),
323   MDBTN_A     = (1 <<  6),
324   MDBTN_B     = (1 <<  4),
325   MDBTN_C     = (1 <<  5),
326   MDBTN_START = (1 <<  7),
327   MDBTN_X     = (1 << 10),
328   MDBTN_Y     = (1 <<  9),
329   MDBTN_Z     = (1 <<  8),
330   MDBTN_MODE  = (1 << 11),
331 };
332
333 #define BTN_JOY BTN_JOYSTICK
334 #define BTN_GP  BTN_GAMEPAD
335
336 static const uint32_t evdev_md_default_map[KEY_CNT] = {
337   [KEY_UP]       = MDBTN_UP,
338   [KEY_DOWN]     = MDBTN_DOWN,
339   [KEY_LEFT]     = MDBTN_LEFT,
340   [KEY_RIGHT]    = MDBTN_RIGHT,
341   [KEY_Z]        = MDBTN_A,
342   [KEY_X]        = MDBTN_B,
343   [KEY_C]        = MDBTN_C,
344   [KEY_A]        = MDBTN_X,
345   [KEY_S]        = MDBTN_Y,
346   [KEY_D]        = MDBTN_Z,
347   [KEY_F]        = MDBTN_MODE,
348   [KEY_ENTER]    = MDBTN_START,
349   // joystick, assume diamond face button layout   1
350   //                                             4   2
351   //                                               3
352   [BTN_JOY + 0]  = MDBTN_X,
353   [BTN_JOY + 1]  = MDBTN_C,
354   [BTN_JOY + 2]  = MDBTN_B,
355   [BTN_JOY + 3]  = MDBTN_A,
356   [BTN_JOY + 4]  = MDBTN_Y,
357   [BTN_JOY + 5]  = MDBTN_Z,
358   [BTN_JOY + 6]  = MDBTN_START,
359   [BTN_JOY + 7]  = MDBTN_MODE,
360   [BTN_JOY + 9]  = MDBTN_START,
361   // gamepad
362   [BTN_GP + 0]   = MDBTN_A,
363   [BTN_GP + 1]   = MDBTN_B,
364   [BTN_GP + 2]   = MDBTN_C,
365   [BTN_GP + 3]   = MDBTN_X,
366   [BTN_GP + 4]   = MDBTN_Y,
367   [BTN_GP + 5]   = MDBTN_Z,
368   [BTN_GP + 6]   = MDBTN_START,
369   [BTN_GP + 7]   = MDBTN_MODE,
370   [BTN_GP + 9]   = MDBTN_START,
371   // pandora
372   [KEY_HOME]     = MDBTN_A,
373   [KEY_PAGEDOWN] = MDBTN_B,
374   [KEY_END]      = MDBTN_C,
375   [KEY_LEFTALT]  = MDBTN_START,
376 };
377
378 static const uint16_t bind_to_mask[256] = {
379   ['u'] = MDBTN_UP,
380   ['d'] = MDBTN_DOWN,
381   ['l'] = MDBTN_LEFT,
382   ['r'] = MDBTN_RIGHT,
383   ['a'] = MDBTN_A,
384   ['b'] = MDBTN_B,
385   ['c'] = MDBTN_C,
386   ['s'] = MDBTN_START,
387   ['x'] = MDBTN_X,
388   ['y'] = MDBTN_Y,
389   ['z'] = MDBTN_Z,
390   ['m'] = MDBTN_MODE,
391   ['0'] = 0,          // to unbind a key
392 };
393
394 static struct player_state {
395   uint32_t state;
396   int dirty;
397 } players[4];
398
399 struct evdev_dev {
400   uint32_t kc_map[KEY_CNT];
401   uint32_t player;
402   int fd;
403   struct {
404     int min, max, zone;
405   } abs[2]; // more abs on TODO (problems like noisy analogs)
406 } devs[16];
407
408 static int verbose;
409
410 #define printf_v(l_, fmt_, ...) do { \
411   if (verbose >= (l_)) \
412     fprintf(stderr, fmt_, ##__VA_ARGS__); \
413 } while (0)
414
415 static int do_evdev_input(struct evdev_dev *dev)
416 {
417   struct player_state *player;
418   struct input_event ev;
419   uint32_t mask_clear = 0;
420   uint32_t mask_set = 0;
421   uint32_t old_state;
422   int ret;
423
424   ret = read(dev->fd, &ev, sizeof(ev));
425   if (ret != sizeof(ev)) {
426     fprintf(stderr, "%tu, p%u: evdev read %d/%zd: ",
427       dev - devs, dev->player, ret, sizeof(ev));
428     perror("");
429     if (ret < 0) {
430       close(dev->fd);
431       dev->fd = -1;
432     }
433     return 0;
434   }
435
436   if (dev->player >= ARRAY_SIZE(players)) {
437     fprintf(stderr, "bad player: %u\n", dev->player);
438     return 0;
439   }
440   player = &players[dev->player];
441   old_state = player->state;
442
443   if (ev.type == EV_ABS) {
444     uint32_t l, h;
445
446     if (ev.code >= ARRAY_SIZE(dev->abs)) {
447       printf_v(2, "abs id %u is too large\n", ev.code);
448       return 0;
449     }
450     printf_v(1, "%tu p%u: abs %u: %4d %4d %4d (%d)\n",
451       dev - devs, dev->player, ev.code,
452       dev->abs[ev.code].min, ev.value,
453       dev->abs[ev.code].max, dev->abs[ev.code].zone);
454
455     l = (ev.code & 1) ? MDBTN_UP   : MDBTN_LEFT;
456     h = (ev.code & 1) ? MDBTN_DOWN : MDBTN_RIGHT;
457     mask_clear = l | h;
458     if (ev.value < dev->abs[ev.code].min + dev->abs[ev.code].zone)
459       mask_set = l;
460     else if (ev.value > dev->abs[ev.code].max - dev->abs[ev.code].zone)
461       mask_set = h;
462   }
463   else if (ev.type == EV_KEY) {
464     if (ev.value != 0 && ev.value != 1)
465       return 0;
466
467     if ((uint32_t)ev.code >= ARRAY_SIZE(dev->kc_map)) {
468       fprintf(stderr, "evdev read bad key: %u\n", ev.code);
469       return 0;
470     }
471
472     if (ev.value) // press?
473       mask_set   = dev->kc_map[ev.code];
474     else
475       mask_clear = dev->kc_map[ev.code];
476   }
477   else {
478     return 0;
479   }
480
481   printf_v(1, "%tu p%u: c %03x, s %03x\n",
482       dev - devs, dev->player, mask_clear, mask_set);
483
484   player->state &= ~mask_clear;
485   player->state |=  mask_set;
486
487   player->dirty |= old_state != player->state;
488   return player->dirty;
489 }
490
491 static int open_evdev(struct evdev_dev *dev, char *str_in)
492 {
493   uint32_t event_support = 0;
494   uint32_t abs_support = 0;
495   struct input_absinfo absi;
496   const char *name = str_in;
497   char *p, *s, *binds = NULL;
498   int i, fd, ret;
499   char buf[64];
500
501   p = strchr(str_in, ',');
502   if (p != NULL) {
503     *p++ = 0;
504     binds = p;
505   }
506
507   p = NULL;
508   i = strtol(name, &p, 0);
509   if (p != NULL && *p == 0) {
510     snprintf(buf, sizeof(buf), "/dev/input/event%d", i);
511     name = buf;
512   }
513
514   fd = open(name, O_RDONLY);
515   if (fd == -1) {
516     fprintf(stderr, "open %s: ", name);
517     perror("");
518     return -1;
519   }
520   ret = ioctl(fd, EVIOCGBIT(0, sizeof(event_support)),
521               &event_support);
522   if (ret < 0)
523     perror("EVIOCGBIT");
524   if (!(event_support & ((1 << EV_KEY) | (1 << EV_ABS)))) {
525     fprintf(stderr, "%s doesn't have keys or abs\n", name);
526     close(fd);
527     return -1;
528   }
529
530   dev->fd = fd;
531
532   if (event_support & (1 << EV_ABS)) {
533     ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_support)),
534                 &abs_support);
535     if (ret < 0)
536       perror("EVIOCGBIT");
537     for (i = 0; i < ARRAY_SIZE(dev->abs); i++) {
538       if (!(abs_support & (1 << i)))
539         continue;
540       ret = ioctl(fd, EVIOCGABS(i), &absi);
541       if (ret != 0) {
542         perror("EVIOCGABS");
543         continue;
544       }
545       dev->abs[i].min = absi.minimum;
546       dev->abs[i].max = absi.maximum;
547       dev->abs[i].zone = (absi.maximum - absi.minimum) / 3;
548     }
549   }
550
551   memcpy(dev->kc_map, evdev_md_default_map, sizeof(dev->kc_map));
552   if (binds != NULL) {
553     unsigned int kc, end = 0;
554
555     p = binds;
556     do {
557       s = p;
558       for (; *p != 0 && *p != ','; p++)
559         ;
560       if (*p == 0)
561         end = 1;
562       else
563         *p++ = 0;
564       if (strncmp(s, "j=", 2) == 0) {
565         kc = BTN_JOYSTICK;
566         s += 2;
567       }
568       else if (strncmp(s, "g=", 2) == 0) {
569         kc = BTN_GAMEPAD;
570         s += 2;
571       }
572       else {
573         ret = sscanf(s, "%u=", &kc);
574         if (ret != 1 || (s = strchr(s, '=')) == NULL) {
575           fprintf(stderr, "parse failed: '%s'\n", s);
576           break;
577         }
578         s++;
579       }
580       // bind
581       for (; *s != 0 && kc < sizeof(dev->kc_map); s++, kc++) {
582         uint32_t mask = bind_to_mask[(uint8_t)*s];
583         if (mask == 0 && *s != '0') {
584           fprintf(stderr, "%s: '%c' is not a valid MD btn\n", name, *s);
585           continue;
586         }
587         dev->kc_map[kc] = mask;
588       }
589     }
590     while (!end);
591   }
592
593   return 0;
594 }
595
596 static void do_stdin_input(uint32_t *mode, int *changed)
597 {
598   char c = 0;
599   int ret;
600
601   ret = read(STDIN_FILENO, &c, 1);
602   if (ret <= 0) {
603     perror("read stdin");
604     return;
605   }
606
607   switch (c) {
608   case '1':
609     printf("3btn mode\n");
610     *mode = OP_MODE_3BTN;
611     *changed = 1;
612     break;
613   case '2':
614     printf("6btn mode\n");
615     *mode = OP_MODE_6BTN;
616     *changed = 1;
617     break;
618   case '3':
619     printf("teamplayer mode\n");
620     *mode = OP_MODE_TEAMPLAYER;
621     *changed = 1;
622     break;
623   }
624 }
625
626 static int submit_urb(int fd, struct usbdevfs_urb *urb, int ep,
627   void *buf, size_t buf_size)
628 {
629   memset(urb, 0, sizeof(*urb));
630   urb->type = USBDEVFS_URB_TYPE_INTERRUPT;
631   urb->endpoint = ep;
632   urb->buffer = buf;
633   urb->buffer_length = buf_size;
634
635   return ioctl(fd, USBDEVFS_SUBMITURB, urb);
636 }
637
638 enum my_urbs {
639   URB_DATA_IN,
640   URB_DATA_OUT,
641   URB_DBG_IN,
642   URB_CNT
643 };
644
645 static void usage(const char *argv0)
646 {
647   fprintf(stderr, "usage:\n%s <-e player /dev/input/node[,binds]>*\n"
648     "  [-m <mode>] [-v]\n\n"
649     "  binds:   <keycode=mdbtns>[,keycode=mdbtns]*\n"
650     "  keycode: first keycode (int), can be j,g for joy,gamepad btn0\n"
651     "  mdbtns:  sequence of chars from: udlrabcsxyzm0\n"
652     "           (u=up, d=down, ..., 0=unbind)\n"
653     "  mode:    int 0-2: 3btn 6btn teamplayer\n", argv0);
654   exit(1);
655 }
656
657 static void bad_arg(char *argv[], int a)
658 {
659   fprintf(stderr, "bad arg %d: '%s'\n", a, argv[a]);
660   usage(argv[0]);
661 }
662
663 int main(int argc, char *argv[])
664 {
665   struct teensy_dev dev;
666   struct usbdevfs_urb urb[URB_CNT];
667   struct usbdevfs_urb *reaped_urb;
668   int dev_cnt = 0;
669   int wait_device = 0;
670   int pending_urbs = 0;
671   int had_input = 0;
672   fd_set rfds, wfds;
673   int mode_changed = 0;
674   char buf_dbg[64 + 1];
675   struct tp_pkt pkt_in;
676   struct tp_pkt pkt_out;
677   struct timeval *timeout = NULL;
678   struct timeval tout;
679   uint32_t mode = OP_MODE_3BTN;
680   uint32_t player;
681   int i, ret = -1;
682
683   for (i = 1; i < argc; i++) {
684     if (argv[i][0] == '-') {
685       switch (argv[i][1] | (argv[i][2] << 8)) {
686       case 'e':
687         if (argv[++i] == NULL)
688           bad_arg(argv, i);
689         player = strtoul(argv[i], NULL, 0);
690         if (player >= ARRAY_SIZE(players))
691           bad_arg(argv, i);
692
693         if (argv[++i] == NULL)
694           bad_arg(argv, i);
695         if (dev_cnt >= ARRAY_SIZE(devs)) {
696           fprintf(stderr, "too many evdevs\n");
697           break;
698         }
699         ret = open_evdev(&devs[dev_cnt], argv[i]);
700         if (ret != 0)
701           bad_arg(argv, i);
702         devs[dev_cnt].player = player;
703         dev_cnt++;
704         continue;
705       case 'm':
706         if (argv[++i] == NULL)
707           bad_arg(argv, i);
708         mode = strtoul(argv[i], NULL, 0);
709         mode_changed = 1;
710         continue;
711       case 'v':
712         verbose++;
713         continue;
714       }
715     }
716     bad_arg(argv, i);
717   }
718
719   if (dev_cnt == 0)
720     usage(argv[0]);
721
722   enable_echo(0);
723   signal(SIGINT, signal_handler);
724
725   dev.fd = -1;
726
727   while (!g_exit || (pending_urbs & (1 << URB_DATA_OUT)))
728   {
729     if (dev.fd == -1) {
730       ret = find_device(&dev, 0x16C0, 0x0486);
731       if (ret < 0)
732         break;
733
734       if (ret == 0) {
735         if (!wait_device) {
736           printf("waiting for device...\n");
737           wait_device = 1;
738         }
739         usleep(250000);
740         continue;
741       }
742
743       wait_device = 0;
744       pending_urbs = 0;
745
746       /* we wait first, then send commands, but if teensy
747        * is started already, it won't send anything back */
748       tout.tv_sec = 1;
749       tout.tv_usec = 0;
750       timeout = &tout;
751     }
752
753     if (!(pending_urbs & (1 << URB_DATA_IN))) {
754       memset(&pkt_in, 0, sizeof(pkt_in));
755       ret = submit_urb(dev.fd, &urb[URB_DATA_IN], dev.ifaces[0].ep_in,
756                        &pkt_in, sizeof(pkt_in));
757       if (ret != 0) {
758         perror("USBDEVFS_SUBMITURB URB_DATA_IN");
759         break;
760       }
761
762       pending_urbs |= 1 << URB_DATA_IN;
763     }
764     if (!(pending_urbs & (1 << URB_DBG_IN))) {
765       ret = submit_urb(dev.fd, &urb[URB_DBG_IN], dev.ifaces[1].ep_in,
766                        buf_dbg, sizeof(buf_dbg) - 1);
767       if (ret != 0) {
768         perror("USBDEVFS_SUBMITURB URB_DBG_IN");
769         break;
770       }
771
772       pending_urbs |= 1 << URB_DBG_IN;
773     }
774
775     FD_ZERO(&rfds);
776     FD_SET(STDIN_FILENO, &rfds);
777     for (i = 0; i < dev_cnt; i++)
778       if (devs[i].fd != -1)
779         FD_SET(devs[i].fd, &rfds);
780
781     FD_ZERO(&wfds);
782     FD_SET(dev.fd, &wfds);
783
784     ret = select(dev.fd + 1, &rfds, &wfds, NULL, timeout);
785     if (ret < 0) {
786       perror("select");
787       break;
788     }
789     timeout = NULL;
790
791     /* something form stdin? */
792     if (FD_ISSET(STDIN_FILENO, &rfds))
793       do_stdin_input(&mode, &mode_changed);
794
795     /* something from input devices? */
796     had_input = 0;
797     for (i = 0; i < dev_cnt; i++) {
798       if (devs[i].fd != -1 && FD_ISSET(devs[i].fd, &rfds)) {
799         do_evdev_input(&devs[i]);
800         had_input = 1;
801       }
802     }
803     if (had_input) {
804       /* collect any other input changes before starting
805        * the slow USB transfer to teensy */
806       tout.tv_sec = tout.tv_usec = 0;
807       timeout = &tout;
808       continue;
809     }
810
811     /* something from USB? */
812     if (FD_ISSET(dev.fd, &wfds))
813     {
814       unsigned int which_urb;
815
816       reaped_urb = NULL;
817       ret = ioctl(dev.fd, USBDEVFS_REAPURB, &reaped_urb);
818       if (ret != 0) {
819         if (errno == ENODEV)
820           goto dev_close;
821         perror("USBDEVFS_REAPURB");
822         break;
823       }
824       which_urb = reaped_urb - urb;
825       if (which_urb < ARRAY_SIZE(urb))
826         pending_urbs &= ~(1 << which_urb);
827       else {
828         fprintf(stderr, "reaped unknown urb: %p #%u",
829                 reaped_urb, which_urb);
830       }
831
832       if (reaped_urb != NULL && reaped_urb->status != 0) {
833         errno = -reaped_urb->status;
834         fprintf(stderr, "urb #%u: ", which_urb);
835         perror("");
836         if (reaped_urb->status == -EILSEQ) {
837           /* this is usually a sign of disconnect.. */
838           usleep(250000);
839           goto dev_close;
840         }
841       }
842       else if (reaped_urb == &urb[URB_DATA_IN])
843       {
844         /* some request from teensy */
845         printf("rx data?\n");
846       }
847       else if (reaped_urb == &urb[URB_DATA_OUT])
848       {
849       }
850       else if (reaped_urb == &urb[URB_DBG_IN])
851       {
852         /* debug text */
853         buf_dbg[reaped_urb->actual_length] = 0;
854         printf("%s", buf_dbg);
855
856         // continue receiving debug before sending out stuff
857         tout.tv_sec = 0;
858         tout.tv_usec = 1000;
859         timeout = &tout;
860         continue;
861       }
862       else {
863         fprintf(stderr, "reaped unknown urb? %p #%zu\n",
864           reaped_urb, reaped_urb - urb);
865       }
866     }
867
868     /* something to send? */
869     if (pending_urbs & (1 << URB_DATA_OUT))
870       // can't do that yet - out urb still busy
871       continue;
872
873     if (mode_changed) {
874       memset(&pkt_out, 0, sizeof(pkt_out));
875       pkt_out.type = PKT_UPD_MODE;
876       pkt_out.mode = mode;
877
878       ret = submit_urb(dev.fd, &urb[URB_DATA_OUT], dev.ifaces[0].ep_out,
879                        &pkt_out, sizeof(pkt_out));
880       if (ret != 0) {
881         perror("USBDEVFS_SUBMITURB PKT_STREAM_ENABLE");
882         continue;
883       }
884       pending_urbs |= 1 << URB_DATA_OUT;
885       mode_changed = 0;
886       continue;
887     }
888
889     /* send buttons if there were any changes */
890     memset(&pkt_out, 0, sizeof(pkt_out));
891     for (i = 0; i < ARRAY_SIZE(players); i++) {
892       if (players[i].dirty)
893         pkt_out.changed_players |= 1 << i;
894       players[i].dirty = 0;
895
896       pkt_out.bnts[i] = players[i].state;
897     }
898     if (pkt_out.changed_players != 0) {
899       pkt_out.type = PKT_UPD_BTNS;
900
901       ret = submit_urb(dev.fd, &urb[URB_DATA_OUT], dev.ifaces[0].ep_out,
902                        &pkt_out, sizeof(pkt_out));
903       if (ret != 0) {
904         perror("USBDEVFS_SUBMITURB PKT_FIXED_STATE");
905         break;
906       }
907       pending_urbs |= 1 << URB_DATA_OUT;
908       continue;
909     }
910
911     continue;
912
913 dev_close:
914     close(dev.fd);
915     dev.fd = -1;
916   }
917
918   enable_echo(1);
919
920   if (dev.fd != -1) {
921     /* deal with pending URBs */
922     if (pending_urbs & (1 << URB_DATA_IN))
923       ioctl(dev.fd, USBDEVFS_DISCARDURB, &urb[URB_DATA_IN]);
924     if (pending_urbs & (1 << URB_DBG_IN))
925       ioctl(dev.fd, USBDEVFS_DISCARDURB, &urb[URB_DBG_IN]);
926     for (i = 0; i < URB_CNT; i++) {
927       if (pending_urbs & (1 << i)) {
928         ret = ioctl(dev.fd, USBDEVFS_REAPURB, &reaped_urb);
929         if (ret != 0)
930           perror("USBDEVFS_REAPURB");
931       }
932     }
933
934     close(dev.fd);
935   }
936
937   return ret;
938 }
939
940 // vim: ts=2:sw=2:expandtab