From 3dc88da0222c9ee3156b87c5213a4a9e400e6883 Mon Sep 17 00:00:00 2001
From: meyraud705 <[EMAIL REDACTED]>
Date: Tue, 8 Nov 2022 13:27:56 +0100
Subject: [PATCH] Fix Dualshock 4 rumble stopping too early
Dualshock 4 controller only rumbles for 5 seconds maximum. Resend
rumble command every 2 seconds to make long rumble work.
---
src/joystick/SDL_joystick.c | 21 +++++++++++++++++++--
src/joystick/SDL_sysjoystick.h | 5 +++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 60a82c967886..c1e47beb0800 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1005,6 +1005,10 @@ SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h
result = 0;
} else {
result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble);
+ joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS;
+ if (!joystick->rumble_resend) {
+ joystick->rumble_resend = 1;
+ }
}
if (result == 0) {
@@ -1018,6 +1022,7 @@ SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h
}
} else {
joystick->rumble_expiration = 0;
+ joystick->rumble_resend = 0;
}
}
SDL_UnlockJoysticks();
@@ -1713,6 +1718,7 @@ void
SDL_JoystickUpdate(void)
{
int i;
+ Uint32 now;
SDL_Joystick *joystick;
if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
@@ -1735,13 +1741,24 @@ SDL_JoystickUpdate(void)
}
}
+ now = SDL_GetTicks();
if (joystick->rumble_expiration &&
- SDL_TICKS_PASSED(SDL_GetTicks(), joystick->rumble_expiration)) {
+ SDL_TICKS_PASSED(now, joystick->rumble_expiration)) {
SDL_JoystickRumble(joystick, 0, 0, 0);
+ joystick->rumble_resend = 0;
+ }
+
+ if (joystick->rumble_resend &&
+ SDL_TICKS_PASSED(now, joystick->rumble_resend)) {
+ joystick->driver->Rumble(joystick, joystick->low_frequency_rumble, joystick->high_frequency_rumble);
+ joystick->rumble_resend = now + SDL_RUMBLE_RESEND_MS;
+ if (joystick->rumble_resend == 0) {
+ joystick->rumble_resend = 1;
+ }
}
if (joystick->trigger_rumble_expiration &&
- SDL_TICKS_PASSED(SDL_GetTicks(), joystick->trigger_rumble_expiration)) {
+ SDL_TICKS_PASSED(now, joystick->trigger_rumble_expiration)) {
SDL_JoystickRumbleTriggers(joystick, 0, 0, 0);
}
}
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index 707ab4ae3234..015007c59e91 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -103,6 +103,7 @@ struct _SDL_Joystick
Uint16 low_frequency_rumble;
Uint16 high_frequency_rumble;
Uint32 rumble_expiration;
+ Uint32 rumble_resend;
Uint16 left_trigger_rumble;
Uint16 right_trigger_rumble;
@@ -217,6 +218,10 @@ typedef struct _SDL_JoystickDriver
/* Windows and Mac OSX has a limit of MAX_DWORD / 1000, Linux kernel has a limit of 0xFFFF */
#define SDL_MAX_RUMBLE_DURATION_MS 0xFFFF
+/* Dualshock4 only rumbles for about 5 seconds max, resend rumble command every 2 seconds
+ * to make long rumble work. */
+#define SDL_RUMBLE_RESEND_MS 2000
+
#define SDL_LED_MIN_REPEAT_MS 5000
/* The available joystick drivers */