From caecff650d4ec4b550e2c8b91052e654b2535435 Mon Sep 17 00:00:00 2001
From: mitchellcairns <[EMAIL REDACTED]>
Date: Sun, 22 Jun 2025 20:59:15 -0700
Subject: [PATCH] Resolve bug for calibration Nintendo Switch Pro Controller
(#13260)
Resolves a bug which prevents the stored calibration data from loading, only allowing loading of factory-installed calibration data
(cherry picked from commit 796961acecdd450a868f86c9bea370be0ceb17df)
---
src/joystick/hidapi/SDL_hidapi_switch.c | 58 +++++++++++++++----------
1 file changed, 36 insertions(+), 22 deletions(-)
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 667bc6be8979e..8f9b1bf520965 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -928,13 +928,14 @@ static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled)
static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
{
- Uint8 *pLeftStickCal;
- Uint8 *pRightStickCal;
+ Uint8 *pLeftStickCal = NULL;
+ Uint8 *pRightStickCal = NULL;
size_t stick, axis;
SwitchSubcommandInputPacket_t *user_reply = NULL;
SwitchSubcommandInputPacket_t *factory_reply = NULL;
SwitchSPIOpData_t readUserParams;
SwitchSPIOpData_t readFactoryParams;
+ Uint8 userParamsReadSuccessCount = 0;
// Read User Calibration Info
readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset;
@@ -947,33 +948,46 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
- 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
if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) {
+ userParamsReadSuccessCount += 1;
pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration;
- } else {
- pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
}
if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) {
+ userParamsReadSuccessCount += 1;
pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
- } else {
- pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
+ }
+
+ // Only read the factory calibration info if we failed to receive the correct magic bytes
+ if (userParamsReadSuccessCount < 2) {
+ // Read Factory Calibration Info
+ readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
+ readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
+
+ 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
+ pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
+ pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
+ break;
+ }
+
+ if (attempt == MAX_ATTEMPTS) {
+ return false;
+ }
+ }
+ }
+
+ // If we still don't have calibration data, return false
+ if (pLeftStickCal == NULL || pRightStickCal == NULL)
+ {
+ return false;
}
/* Stick calibration values are 12-bits each and are packed by bit