SDL: Try up to 20 times to read the controller type

From 62f2379e4cb0237dbc8c699dcac1eef0ad896fe9 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 31 Aug 2022 13:24:23 -0700
Subject: [PATCH] Try up to 20 times to read the controller type

It takes a while for Joy-Cons to initialize when plugged in via the Nintendo Joy-Con Charging Grip.
---
 src/joystick/hidapi/SDL_hidapi_switch.c | 51 ++++++++++++++++---------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 60d5bf6b135..5c1bea6d3c8 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -208,12 +208,12 @@ typedef struct
 
 typedef struct
 {
-	Uint8 ucPacketType;
-	Uint8 ucCommandID;
-	Uint8 ucFiller;
+    Uint8 ucPacketType;
+    Uint8 ucCommandID;
+    Uint8 ucFiller;
 
-	Uint8 ucDeviceType;
-	Uint8 rgucMACAddress[6];
+    Uint8 ucDeviceType;
+    Uint8 rgucMACAddress[6];
 } SwitchProprietaryStatusPacket_t;
 
 typedef struct
@@ -931,29 +931,42 @@ ReadJoyConControllerType(SDL_HIDAPI_Device *device)
 
         device->dev = SDL_hid_open_path(device->path, 0);
         if (device->dev) {
-            if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) {
-                SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
-
-                eControllerType = (ESwitchDeviceInfoControllerType) status->ucDeviceType;
+            const int MAX_ATTEMPTS = 20;
+            int attempts = 0;
+            for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) {
+                if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) {
+                    SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
+
+                    eControllerType = (ESwitchDeviceInfoControllerType) status->ucDeviceType;
+
+                    /* The N64 controller reports as a Pro controller over USB */
+                    if (eControllerType == k_eSwitchDeviceInfoControllerType_ProController &&
+                        device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
+                        eControllerType = k_eSwitchDeviceInfoControllerType_N64;
+                    }
+                } else {
+                    SwitchSubcommandInputPacket_t *reply = NULL;
 
-                /* The N64 controller reports as a Pro controller over USB */
-                if (eControllerType == k_eSwitchDeviceInfoControllerType_ProController &&
-                    device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
-                    eControllerType = k_eSwitchDeviceInfoControllerType_N64;
+                    ctx->m_bUsingBluetooth = SDL_TRUE;
+                    if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
+                        eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType;
+                    }
                 }
-            } else {
-                SwitchSubcommandInputPacket_t *reply = NULL;
-
-                ctx->m_bUsingBluetooth = SDL_TRUE;
-                if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
-                    eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType;
+                if (eControllerType == k_eSwitchDeviceInfoControllerType_Unknown) {
+                    /* Wait a bit and try again */
+                    SDL_Delay(100);
+                    continue;
+                } else {
+                    break;
                 }
             }
+printf("Attempts: %d\n", attempts);
             SDL_hid_close(device->dev);
             device->dev = NULL;
         }
         SDL_free(ctx);
     }
+printf("Controller type %d\n", eControllerType);
     return eControllerType;
 }