Fixed bug 4436 - [OpenBSD] fix D-pad Thomas Frohwein Hi, If a gamepad lists the Dpad as 4 buttons (Dpad Up,Down, Left, Right) like with the Xbox 360 gamepad / XInput report descriptor used by OpenBSD (https://github.com/openbsd/src/blob/master/sys/dev/usb/uhid_rdesc.h#L184), this is not recognized by the SDL BSD backend and no hat or any other listing for the D-pad exists, e.g. in sdl2-jstest (https://gitlab.com/sdl-jstest/sdl-jstest). The attached diff fixes this and makes the D-pad on my Xbox 360 and Logitech F310 controllers usable. It adds a hat to nhats when usage HUG_DPAD_UP is found, reads the state of the D-pad buttons into array dpad[], and turns the value of dpad[] into an SDL hat direction (dpad_to_sdl()). Tested and works with Xbox 360 controller and Logitech F310 in XInput mode. Software-side tested with sdl2-jstest and Owlboy where this worked without problems or regressions. I don't know if this would be applicable to other *BSDs and don't have an install to test it with, therefore wrapped it in __OpenBSD__ ifdefs. Thanks, thfr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
diff --git a/src/joystick/bsd/SDL_sysjoystick.c b/src/joystick/bsd/SDL_sysjoystick.c
index 2f699a7..fb63263 100644
--- a/src/joystick/bsd/SDL_sysjoystick.c
+++ b/src/joystick/bsd/SDL_sysjoystick.c
@@ -80,6 +80,49 @@
#define MAX_JOY_JOYS 2
#define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS)
+#ifdef __OpenBSD__
+
+#define HUG_DPAD_UP 0x90
+#define HUG_DPAD_DOWN 0x91
+#define HUG_DPAD_RIGHT 0x92
+#define HUG_DPAD_LEFT 0x93
+
+#define HAT_CENTERED 0x00
+#define HAT_UP 0x01
+#define HAT_RIGHT 0x02
+#define HAT_DOWN 0x04
+#define HAT_LEFT 0x08
+#define HAT_RIGHTUP (HAT_RIGHT|HAT_UP)
+#define HAT_RIGHTDOWN (HAT_RIGHT|HAT_DOWN)
+#define HAT_LEFTUP (HAT_LEFT|HAT_UP)
+#define HAT_LEFTDOWN (HAT_LEFT|HAT_DOWN)
+
+/* calculate the value from the state of the dpad */
+int
+dpad_to_sdl(Sint32 *dpad)
+{
+ if (dpad[2]) {
+ if (dpad[0])
+ return HAT_RIGHTUP;
+ else if (dpad[1])
+ return HAT_RIGHTDOWN;
+ else
+ return HAT_RIGHT;
+ } else if (dpad[3]) {
+ if (dpad[0])
+ return HAT_LEFTUP;
+ else if (dpad[1])
+ return HAT_LEFTDOWN;
+ else
+ return HAT_LEFT;
+ } else if (dpad[0]) {
+ return HAT_UP;
+ } else if (dpad[1]) {
+ return HAT_DOWN;
+ }
+ return HAT_CENTERED;
+}
+#endif
struct report
{
@@ -434,7 +477,11 @@ desc_failed:
int joyaxe = usage_to_joyaxe(usage);
if (joyaxe >= 0) {
hw->axis_map[joyaxe] = 1;
- } else if (usage == HUG_HAT_SWITCH) {
+ } else if (usage == HUG_HAT_SWITCH
+#ifdef __OpenBSD__
+ || usage == HUG_DPAD_UP
+#endif
+ ) {
joy->nhats++;
}
break;
@@ -487,6 +534,9 @@ BSD_JoystickUpdate(SDL_Joystick * joy)
struct report *rep;
int nbutton, naxe = -1;
Sint32 v;
+#ifdef __OpenBSD__
+ Sint32 dpad[4] = {0, 0, 0, 0};
+#endif
#if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
struct joystick gameport;
@@ -572,6 +622,16 @@ BSD_JoystickUpdate(SDL_Joystick * joy)
hatval_to_sdl(v) -
hitem.logical_minimum);
}
+#ifdef __OpenBSD__
+ else if (usage == HUG_DPAD_UP)
+ dpad[0] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
+ else if (usage == HUG_DPAD_DOWN)
+ dpad[1] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
+ else if (usage == HUG_DPAD_RIGHT)
+ dpad[2] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
+ else if (usage == HUG_DPAD_LEFT)
+ dpad[3] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
+#endif
break;
}
case HUP_BUTTON:
@@ -587,6 +647,9 @@ BSD_JoystickUpdate(SDL_Joystick * joy)
break;
}
}
+#ifdef __OpenBSD__
+ SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
+#endif
hid_end_parse(hdata);
}
}