SDL: SDL: let through a SetLED command every 5sec to deall with situations where the controller loses power when a computer is...

From 2a20cc0f1d4f74c8f3cc0775faf081b70cb2e86d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 12 Apr 2021 11:25:42 -0700
Subject: [PATCH] SDL: let through a SetLED command every 5sec to deall with
 situations where the controller loses power when a computer is suspended

CR: SamL
---
 src/joystick/SDL_joystick.c    | 16 +++++++++++-----
 src/joystick/SDL_sysjoystick.h |  3 +++
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 7d7a12a31..8cf47c745 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -416,6 +416,7 @@ SDL_JoystickOpen(int device_index)
     joystick->instance_id = instance_id;
     joystick->attached = SDL_TRUE;
     joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
+    joystick->led_expiration = SDL_GetTicks();
 
     if (driver->Open(joystick, device_index) < 0) {
         SDL_free(joystick);
@@ -954,6 +955,7 @@ int
 SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
 {
     int result;
+    SDL_bool isfreshvalue;
 
     if (!SDL_PrivateJoystickValid(joystick)) {
         return -1;
@@ -961,13 +963,17 @@ SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
 
     SDL_LockJoysticks();
 
-    if (red == joystick->led_red &&
-        green == joystick->led_green &&
-        blue == joystick->led_blue) {
+    isfreshvalue = red != joystick->led_red ||
+        green != joystick->led_green ||
+        blue != joystick->led_blue;
+
+    if ( isfreshvalue || SDL_TICKS_PASSED( SDL_GetTicks(), joystick->led_expiration ) ) {
+        result = joystick->driver->SetLED(joystick, red, green, blue);
+        joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS;
+    }
+    else {
         /* Avoid spamming the driver */
         result = 0;
-    } else {
-        result = joystick->driver->SetLED(joystick, red, green, blue);
     }
 
     /* Save the LED value regardless of success, so we don't spam the driver */
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index b8af118df..749c6efd2 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -99,6 +99,7 @@ struct _SDL_Joystick
     Uint8 led_red;
     Uint8 led_green;
     Uint8 led_blue;
+    Uint32 led_expiration;
 
     SDL_bool attached;
     SDL_bool is_game_controller;
@@ -189,6 +190,8 @@ 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
 
+#define SDL_LED_MIN_REPEAT_MS  5000
+
 /* The available joystick drivers */
 extern SDL_JoystickDriver SDL_ANDROID_JoystickDriver;
 extern SDL_JoystickDriver SDL_BSD_JoystickDriver;