From c377de54409933b19ae5eb3855fdf203448d1f98 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 19 May 2019 11:56:26 -0700 Subject: [PATCH] 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 --- src/joystick/bsd/SDL_sysjoystick.c | 65 +++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/joystick/bsd/SDL_sysjoystick.c b/src/joystick/bsd/SDL_sysjoystick.c index 2f699a73c0bee..fb632635468cf 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 @@ BSD_JoystickOpen(SDL_Joystick * joy, int device_index) 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); } }