From 3f9a85d997fb1518d1bb49f3d8746f9e88d9152d Mon Sep 17 00:00:00 2001 From: Carlo Refice Date: Mon, 1 May 2023 23:37:26 +0200 Subject: [PATCH] Fix rumble on PS4/PS5 controllers connected via bluetooth (#15244) --- input/drivers_joypad/sdl_joypad.c | 36 +++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/input/drivers_joypad/sdl_joypad.c b/input/drivers_joypad/sdl_joypad.c index 43d1d81c5d..fe3b6905c7 100644 --- a/input/drivers_joypad/sdl_joypad.c +++ b/input/drivers_joypad/sdl_joypad.c @@ -2,6 +2,7 @@ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2017 - Daniel De Matteis * Copyright (C) 2014-2017 - Higor Euripedes + * Copyright (C) 2023 - Carlo Refice * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -32,7 +33,7 @@ typedef struct _sdl_joypad #ifdef HAVE_SDL2 SDL_GameController *controller; SDL_Haptic *haptic; - int rumble_effect; /* -1 = not initialized, -2 = error/unsupported */ + int rumble_effect; /* -1 = not initialized, -2 = error/unsupported, -3 = use SDL_JoystickRumble instead of haptic */ #endif unsigned num_axes; unsigned num_buttons; @@ -212,9 +213,15 @@ static void sdl_pad_connect(unsigned id) if (SDL_HapticEffectSupported(pad->haptic, &efx) == SDL_FALSE) { pad->rumble_effect = -2; - RARCH_WARN("[SDL]: Device #%u does not support rumble.\n", id); + RARCH_WARN("[SDL]: Device #%u does not support leftright haptic effect.\n", id); } } +#if SDL_VERSION_ATLEAST(2, 0, 9) + if (!pad->haptic || pad->rumble_effect == -2) { + pad->rumble_effect = -3; + RARCH_LOG("[SDL]: Falling back to joystick rumble\n"); + } +#endif #else pad->num_axes = SDL_JoystickNumAxes(pad->joypad); pad->num_buttons = SDL_JoystickNumButtons(pad->joypad); @@ -289,6 +296,11 @@ static void *sdl_joypad_init(void *data) } else g_has_haptic = true; + +#if SDL_VERSION_ATLEAST(2, 0, 9) + /* enable extended hid reports to support ps4/ps5 rumble over bluetooth */ + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); +#endif #endif memset(sdl_pads, 0, sizeof(sdl_pads)); @@ -471,7 +483,7 @@ static bool sdl_joypad_set_rumble(unsigned pad, enum retro_rumble_effect effect, memset(&efx, 0, sizeof(efx)); - if (!joypad->joypad || !joypad->haptic) + if (!joypad->joypad) return false; efx.type = SDL_HAPTIC_LEFTRIGHT; @@ -490,9 +502,25 @@ static bool sdl_joypad_set_rumble(unsigned pad, enum retro_rumble_effect effect, return false; } +#if SDL_VERSION_ATLEAST(2, 0, 9) + if (joypad->rumble_effect == -3) + { + if (SDL_JoystickRumble(joypad->joypad, efx.leftright.large_magnitude, efx.leftright.small_magnitude, efx.leftright.length) == -1) + { + RARCH_WARN("[SDL]: Failed to rumble joypad %u: %s\n", + pad, SDL_GetError()); + joypad->rumble_effect = -2; + return false; + } + } +#endif + + if (!joypad->haptic) + return false; + if (joypad->rumble_effect == -1) { - joypad->rumble_effect = SDL_HapticNewEffect(sdl_pads[pad].haptic, &efx); + joypad->rumble_effect = SDL_HapticNewEffect(joypad->haptic, &efx); if (joypad->rumble_effect < 0) { RARCH_WARN("[SDL]: Failed to create rumble effect for joypad %u: %s\n",