# SDL: Use the default calibration if we can't load IMU calibration for Nintendo Switch controllers

**URL:** <https://discourse.libsdl.org/t/sdl-use-the-default-calibration-if-we-cant-load-imu-calibration-for-nintendo-switch-controllers/69750>\
**Category:** SDL Commits\
**Created:** [November 3, 2026, 5:27pm UTC](https://discourse.libsdl.org/t/sdl-use-the-default-calibration-if-we-cant-load-imu-calibration-for-nintendo-switch-controllers/69750 "2026-11-03T17:27:32Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [November 3, 2026, 5:27pm UTC](https://discourse.libsdl.org/t/sdl-use-the-default-calibration-if-we-cant-load-imu-calibration-for-nintendo-switch-controllers/69750/1 "2026-11-03T17:27:32Z")

</div>

> <https://github.com/libsdl-org/SDL/commit/3c9321be39de4250e6406c273e1e86fb286997e4>
>
> Fixes https://github.com/libsdl-org/SDL/issues/16237

```diff
From 3c9321be39de4250e6406c273e1e86fb286997e4 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 3 Nov 2026 09:00:04 -0800
Subject: [PATCH] Use the default calibration if we can't load IMU calibration
 for Nintendo Switch controllers

Fixes https://github.com/libsdl-org/SDL/issues/16237
---
 src/joystick/hidapi/SDL_hidapi_switch.c | 39 ++++++++++++++++---------
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index f272a37e0a74f..dff750fc48b5a 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -1093,6 +1093,7 @@ static void LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
 
 static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
 {
+ bool have_imu_cal = false;
     SwitchSubcommandInputPacket_t *reply = NULL;
 
     // Read Calibration Info
@@ -1144,22 +1145,32 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
             }
         }
 
- // Gyro zero-rate offset
- ctx->m_IMUScaleData.sGyroOffsetX = sGyroRawX;
- ctx->m_IMUScaleData.sGyroOffsetY = sGyroRawY;
- ctx->m_IMUScaleData.sGyroOffsetZ = sGyroRawZ;
+ if (sAccelSensCoeffX != sAccelRawX &&
+ sAccelSensCoeffY != sAccelRawY &&
+ sAccelSensCoeffZ != sAccelRawZ &&
+ sGyroSensCoeffX != sGyroRawX &&
+ sGyroSensCoeffY != sGyroRawY &&
+ sGyroSensCoeffZ != sGyroRawZ) {
+ // Gyro zero-rate offset
+ ctx->m_IMUScaleData.sGyroOffsetX = sGyroRawX;
+ ctx->m_IMUScaleData.sGyroOffsetY = sGyroRawY;
+ ctx->m_IMUScaleData.sGyroOffsetZ = sGyroRawZ;
 
- // Accelerometer scale
- ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
- ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
- ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
+ // Accelerometer scale
+ ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
+ ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
+ ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
 
- // Gyro scale
- ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * SDL_PI_F / 180.0f;
- ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * SDL_PI_F / 180.0f;
- ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
+ // Gyro scale
+ ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * SDL_PI_F / 180.0f;
+ ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * SDL_PI_F / 180.0f;
+ ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
 
- } else {
+ have_imu_cal = true;
+ }
+ }
+
+ if (!have_imu_cal) {
         // Use default values
         const float accelScale = SDL_STANDARD_GRAVITY / SWITCH_ACCEL_SCALE;
         const float gyroScale = SDL_PI_F / 180.0f / SWITCH_GYRO_SCALE;
@@ -1176,6 +1187,8 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
         ctx->m_IMUScaleData.sGyroOffsetY = 0;
         ctx->m_IMUScaleData.sGyroOffsetZ = 0;
     }
+
+ // FIXME: Should we read two reports and verify that gyro values are coming through?
     return true;
 }
 

```
