From ba88b6aa06f78ca7b5811efb1a50e76503deec10 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 26 Feb 2025 11:21:34 -0800
Subject: [PATCH] Fixed reliability of initializing Switch controllers on macOS
It looks like both macOS (15.1.1) and SDL are trying to talk to the controller at the same time, which can cause interleaved replies or even locking up the controller. Waiting a bit before talking to the controller seems to take care of this.
---
src/joystick/hidapi/SDL_hidapi_switch.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index c1bc6d0abfbd3..2830aee9160b3 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -943,8 +943,20 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
- if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
- return false;
+ const int MAX_ATTEMPTS = 3;
+ for (int attempt = 0; ; ++attempt) {
+ if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
+ return false;
+ }
+
+ if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
+ // We successfully read the calibration data
+ break;
+ }
+
+ if (attempt == MAX_ATTEMPTS) {
+ return false;
+ }
}
// Automatically select the user calibration if magic bytes are set
@@ -1508,6 +1520,10 @@ static bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joys
ctx->m_bSyncWrite = true;
if (!ctx->m_bInputOnly) {
+#ifdef SDL_PLATFORM_MACOS
+ // Wait for the OS to finish its handshake with the controller
+ SDL_Delay(250);
+#endif
GetInitialInputMode(ctx);
ctx->m_nCurrentInputMode = ctx->m_nInitialInputMode;