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
This commit is contained in:
Sam Lantinga 2019-05-19 11:56:26 -07:00
parent 510b01f5fc
commit c377de5440

View file

@ -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);
}
}