Commit ce0f90ffb9c845d70ce833e75b3764a8246213cb

Ryan C. Gordon 2015-12-29T02:29:56

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.

diff --git a/src/joystick/bsd/SDL_sysjoystick.c b/src/joystick/bsd/SDL_sysjoystick.c
index a6fe2f7..b43e13b 100644
--- a/src/joystick/bsd/SDL_sysjoystick.c
+++ b/src/joystick/bsd/SDL_sysjoystick.c
@@ -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 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
     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 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
 #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 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
         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: