Commit 5b8fc907df5866cc7e30c523c6ea499eb6f8a4d4

Sam Lantinga 2023-06-17T12:42:55

Added support for the GameSir G4 Pro We can't read device info or IMU calibration from this controller, and it has no gyro or accelerometer, but is otherwise perfectly functional. (cherry picked from commit f168f9c81326ad374aade49d1dc46f245b20d07a)

diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 8b9d5e8..4a11719 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -592,35 +592,30 @@ static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx)
 {
     SwitchSubcommandInputPacket_t *reply = NULL;
 
-    ctx->device->is_bluetooth = SDL_FALSE;
-
-    if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) {
-        SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
-        size_t i;
+    if (ctx->device->is_bluetooth) {
+        if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
+            // Byte 2: Controller ID (1=LJC, 2=RJC, 3=Pro)
+            ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType);
 
-        ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)status->ucDeviceType);
+            // Bytes 4-9: MAC address (big-endian)
+            SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
 
-        for (i = 0; i < sizeof(ctx->m_rgucMACAddress); ++i) {
-            ctx->m_rgucMACAddress[i] = status->rgucMACAddress[sizeof(ctx->m_rgucMACAddress) - i - 1];
+            return SDL_TRUE;
         }
+    } else {
+        if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) {
+            SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
+            size_t i;
 
-        return SDL_TRUE;
-    }
-
-    ctx->device->is_bluetooth = SDL_TRUE;
-
-    if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
-        // Byte 2: Controller ID (1=LJC, 2=RJC, 3=Pro)
-        ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType);
+            ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)status->ucDeviceType);
 
-        // Bytes 4-9: MAC address (big-endian)
-        SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
+            for (i = 0; i < sizeof(ctx->m_rgucMACAddress); ++i) {
+                ctx->m_rgucMACAddress[i] = status->rgucMACAddress[sizeof(ctx->m_rgucMACAddress) - i - 1];
+            }
 
-        return SDL_TRUE;
+            return SDL_TRUE;
+        }
     }
-
-    ctx->device->is_bluetooth = SDL_FALSE;
-
     return SDL_FALSE;
 }
 
@@ -1042,7 +1037,8 @@ static SDL_bool HasHomeLED(SDL_DriverSwitch_Context *ctx)
     }
 
     /* Third party controllers don't have a home LED and will shut off if we try to set it */
-    if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_LicProController) {
+    if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_Unknown ||
+        ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_LicProController) {
         return SDL_FALSE;
     }
 
@@ -1243,6 +1239,9 @@ static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
         HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
         device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
         break;
+    case k_eSwitchDeviceInfoControllerType_Unknown:
+        /* We couldn't read the device info for this controller, might not be fully compliant */
+        return;
     default:
         break;
     }
@@ -1285,12 +1284,7 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
         SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
         SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
 
-        if (!BReadDeviceInfo(ctx)) {
-            SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
-                         "HIDAPI_DriverSwitch_InitDevice(): Couldn't read device info");
-            return SDL_FALSE;
-        }
-
+        BReadDeviceInfo(ctx);
         UpdateDeviceIdentity(device);
     }
 
@@ -1345,39 +1339,36 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
             }
         }
 
+        if (!LoadStickCalibration(ctx)) {
+            SDL_SetError("Couldn't load stick calibration");
+            return SDL_FALSE;
+        }
+
         if (ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_NESLeft &&
             ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_NESRight &&
             ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_SNES &&
             ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_N64 &&
             ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_SEGA_Genesis) {
-            /* Use the right sensor in the combined Joy-Con pair */
-            if (!device->parent ||
-                ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
-                SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 200.0f);
-                SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 200.0f);
-            }
-            if (device->parent &&
-                ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
-                SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_L, 200.0f);
-                SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 200.0f);
-            }
-            if (device->parent &&
-                ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
-                SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_R, 200.0f);
-                SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_R, 200.0f);
+            if (LoadIMUCalibration(ctx)) {
+                /* Use the right sensor in the combined Joy-Con pair */
+                if (!device->parent ||
+                    ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
+                    SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 200.0f);
+                    SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 200.0f);
+                }
+                if (device->parent &&
+                    ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
+                    SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_L, 200.0f);
+                    SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 200.0f);
+                }
+                if (device->parent &&
+                    ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
+                    SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_R, 200.0f);
+                    SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_R, 200.0f);
+                }
             }
         }
 
-        if (!LoadStickCalibration(ctx)) {
-            SDL_SetError("Couldn't load stick calibration");
-            return SDL_FALSE;
-        }
-
-        if (!LoadIMUCalibration(ctx)) {
-            SDL_SetError("Couldn't load sensor calibration");
-            return SDL_FALSE;
-        }
-
         if (!SetVibrationEnabled(ctx, 1)) {
             SDL_SetError("Couldn't enable vibration");
             return SDL_FALSE;