SDL: Fixed rare case of wireless Steam Controller not being detected at startup

From 2b10a040ff9b1dd62ed8027427608ce516d47c0c Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 16 Nov 2024 13:10:02 -0800
Subject: [PATCH] Fixed rare case of wireless Steam Controller not being
 detected at startup

---
 src/joystick/hidapi/SDL_hidapi_steam.c | 51 +++++++++++++++++---------
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c
index 796c709b3a5d0..ad41b9300323a 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam.c
@@ -1214,6 +1214,31 @@ static bool HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_
     return true;
 }
 
+static bool ControllerConnected(SDL_HIDAPI_Device *device, SDL_Joystick **joystick)
+{
+    SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
+
+    if (!HIDAPI_JoystickConnected(device, NULL)) {
+        return false;
+    }
+
+    // We'll automatically accept this controller if we're in pairing mode
+    HIDAPI_DriverSteam_CommitPairing(ctx);
+
+    *joystick = SDL_GetJoystickFromID(device->joysticks[0]);
+    ctx->connected = true;
+    return true;
+}
+
+static void ControllerDisconnected(SDL_HIDAPI_Device *device, SDL_Joystick **joystick)
+{
+    SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
+
+    HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
+    ctx->connected = false;
+    *joystick = NULL;
+}
+
 static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
 {
     SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
@@ -1232,10 +1257,7 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
         if (r <= 0) {
             if (r < 0) {
                 // Failed to read from controller
-                if (ctx->connected) {
-                    HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
-                    ctx->connected = false;
-                }
+                ControllerDisconnected(device, &joystick);
                 return false;
             }
             break;
@@ -1251,6 +1273,11 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
         if (nPacketLength > 0 && UpdateSteamControllerState(pPacket, nPacketLength, &ctx->m_state)) {
             Uint64 timestamp = SDL_GetTicksNS();
 
+            if (!ctx->connected) {
+                // Maybe we missed a wireless status packet?
+                ControllerConnected(device, &joystick);
+            }
+
             if (!joystick) {
                 continue;
             }
@@ -1336,21 +1363,9 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
 
             ctx->m_last_state = ctx->m_state;
         } else if (!ctx->connected && D0G_IS_WIRELESS_CONNECT(pPacket, nPacketLength)) {
-            // Controller has connected to the wireless dongle
-            if (!HIDAPI_JoystickConnected(device, NULL)) {
-                return false;
-            }
-
-            // We'll automatically accept this controller if we're in pairing mode
-            HIDAPI_DriverSteam_CommitPairing(ctx);
-
-            joystick = SDL_GetJoystickFromID(device->joysticks[0]);
-            ctx->connected = true;
+            ControllerConnected(device, &joystick);
         } else if (ctx->connected && D0G_IS_WIRELESS_DISCONNECT(pPacket, nPacketLength)) {
-            // Controller has disconnected from the wireless dongle
-            HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
-            joystick = NULL;
-            ctx->connected = false;
+            ControllerDisconnected(device, &joystick);
         }
     }
     return true;