Make it possible to turn on PS5 rumble effects at runtime using the hint
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
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index dfd94a9..4aa0f93 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -27,6 +27,7 @@
#include "SDL_timer.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
+#include "../../SDL_hints_c.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
@@ -150,6 +151,8 @@ typedef struct {
} IMUCalibrationData;
typedef struct {
+ SDL_HIDAPI_Device *device;
+ SDL_Joystick *joystick;
SDL_bool is_bluetooth;
SDL_bool effects_supported;
SDL_bool report_sensors;
@@ -509,14 +512,26 @@ HIDAPI_DriverPS5_SetEffectsSupported(SDL_HIDAPI_Device *device, SDL_Joystick *jo
{
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
- ctx->effects_supported = SDL_TRUE;
+ if (!ctx->effects_supported) {
+ ctx->effects_supported = SDL_TRUE;
- SDL_PrivateJoystickAddTouchpad(joystick, 2);
- SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
- SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
+ SDL_PrivateJoystickAddTouchpad(joystick, 2);
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
- HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectLED);
- HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectPadLights);
+ HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectLED);
+ HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectPadLights);
+ }
+}
+
+static void SDLCALL SDL_PS5RumbleHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)userdata;
+
+ /* This is a one-way trip, you can't switch the controller back to simple report mode */
+ if (SDL_GetStringBoolean(hint, SDL_FALSE)) {
+ HIDAPI_DriverPS5_SetEffectsSupported(ctx->device, ctx->joystick);
+ }
}
static void
@@ -548,6 +563,8 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
SDL_OutOfMemory();
return SDL_FALSE;
}
+ ctx->device = device;
+ ctx->joystick = joystick;
ctx->last_packet = SDL_GetTicks();
device->dev = hid_open_path(device->path, 0);
@@ -594,7 +611,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
}
}
- if (!joystick->serial && SDL_strlen(device->serial) == 12) {
+ if (!joystick->serial && device->serial && SDL_strlen(device->serial) == 12) {
int i, j;
char serial[18];
@@ -622,8 +639,10 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
if (effects_supported) {
HIDAPI_DriverPS5_SetEffectsSupported(device, joystick);
+ } else {
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
+ SDL_PS5RumbleHintChanged, ctx);
}
-
return SDL_TRUE;
}
@@ -985,6 +1004,11 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
static void
HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
+ SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
+
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
+ SDL_PS5RumbleHintChanged, ctx);
+
hid_close(device->dev);
device->dev = NULL;