NetBSD: improved joystick support (thanks, Thomas!).
authorRyan C. Gordon <icculus@icculus.org>
Tue, 29 Dec 2015 02:29:56 -0500
changeset 9986 081fbd89a347
parent 9985 091503bd5054
child 9987 d64783aac765
NetBSD: improved joystick support (thanks, Thomas!). This patch skips non-joystick HID devices and gives joysticks on NetBSD a human readable name. Fixes Bugzilla #3178.
src/joystick/bsd/SDL_sysjoystick.c
--- a/src/joystick/bsd/SDL_sysjoystick.c	Tue Dec 29 02:27:02 2015 -0500
+++ b/src/joystick/bsd/SDL_sysjoystick.c	Tue Dec 29 02:29:56 2015 -0500
@@ -76,7 +76,7 @@
 #include "../SDL_sysjoystick.h"
 #include "../SDL_joystick_c.h"
 
-#define MAX_UHID_JOYS   16
+#define MAX_UHID_JOYS   64
 #define MAX_JOY_JOYS    2
 #define MAX_JOYS    (MAX_UHID_JOYS + MAX_JOY_JOYS)
 
@@ -286,7 +286,7 @@
     struct joystick_hwdata *hw;
     struct hid_item hitem;
     struct hid_data *hdata;
-    struct report *rep;
+    struct report *rep = NULL;
     int fd;
     int i;
 
@@ -337,6 +337,38 @@
 #endif
         rep->rid = -1;          /* XXX */
     }
+#if defined(__NetBSD__)
+    usb_device_descriptor_t udd;
+    struct usb_string_desc usd;
+    if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
+        goto desc_failed;
+
+    /* Get default language */
+    usd.usd_string_index = USB_LANGUAGE_TABLE;
+    usd.usd_language_id = 0;
+    if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
+        usd.usd_language_id = 0;
+    } else {
+        usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
+    }
+
+    usd.usd_string_index = udd.iProduct;
+    if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
+        char str[128];
+        char *new_name = NULL;
+        int i;
+        for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) {
+            str[i] = UGETW(usd.usd_desc.bString[i]);
+        }
+        str[i] = '\0';
+        asprintf(&new_name, "%s @ %s", str, path);
+        if (new_name != NULL) {
+            free(joydevnames[SDL_SYS_numjoysticks]);
+            joydevnames[SDL_SYS_numjoysticks] = new_name;
+        }
+    }
+desc_failed:
+#endif
     if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
         goto usberr;
     }
@@ -409,9 +441,21 @@
         if (hw->axis_map[i] > 0)
             hw->axis_map[i] = joy->naxes++;
 
+    if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
+        SDL_SetError("%s: Not a joystick, ignoring", hw->path);
+        goto usberr;
+    }
+
   usbend:
     /* The poll blocks the event thread. */
     fcntl(fd, F_SETFL, O_NONBLOCK);
+#ifdef __NetBSD__
+    /* Flush pending events */
+    if (rep) {
+        while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
+            ;
+    }
+#endif
 
     return (0);
   usberr: