Commit 9be85b846b3aa681567683768c2975443bad41c3

Sam Lantinga 2023-02-21T15:05:57

Rumbling the Google Stadia Controller over Bluetooth works on Linux and macOS (cherry picked from commit 4aeec9d8c2ad2fa0465999ecb4fd5c20734f1b27)

diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c
index 1ff00af..0cdb4f4 100644
--- a/src/joystick/hidapi/SDL_hidapi_stadia.c
+++ b/src/joystick/hidapi/SDL_hidapi_stadia.c
@@ -43,6 +43,7 @@ enum
 
 typedef struct
 {
+    SDL_bool rumble_supported;
     Uint8 last_state[USB_PACKET_LENGTH];
 } SDL_DriverStadia_Context;
 
@@ -77,12 +78,12 @@ static SDL_bool HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device)
     }
     device->context = ctx;
 
-    /* Check whether this is connected via USB or Bluetooth */
+    /* Check whether rumble is supported */
     {
         Uint8 rumble_packet[] = { 0x05, 0x00, 0x00, 0x00, 0x00 };
 
-        if (SDL_hid_write(device->dev, rumble_packet, sizeof(rumble_packet)) < 0) {
-            device->is_bluetooth = SDL_TRUE;
+        if (SDL_hid_write(device->dev, rumble_packet, sizeof(rumble_packet)) >= 0) {
+            ctx->rumble_supported = SDL_TRUE;
         }
     }
 
@@ -119,21 +120,24 @@ static SDL_bool HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
 
 static int HIDAPI_DriverStadia_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
 {
-    Uint8 rumble_packet[] = { 0x05, 0x00, 0x00, 0x00, 0x00 };
+    SDL_DriverStadia_Context *ctx = (SDL_DriverStadia_Context *)device->context;
+
+    if (ctx->rumble_supported) {
+        Uint8 rumble_packet[] = { 0x05, 0x00, 0x00, 0x00, 0x00 };
 
-    if (device->is_bluetooth) {
-        return SDL_Unsupported();
-    }
 
-    rumble_packet[1] = (low_frequency_rumble & 0xFF);
-    rumble_packet[2] = (low_frequency_rumble >> 8);
-    rumble_packet[3] = (high_frequency_rumble & 0xFF);
-    rumble_packet[4] = (high_frequency_rumble >> 8);
+        rumble_packet[1] = (low_frequency_rumble & 0xFF);
+        rumble_packet[2] = (low_frequency_rumble >> 8);
+        rumble_packet[3] = (high_frequency_rumble & 0xFF);
+        rumble_packet[4] = (high_frequency_rumble >> 8);
 
-    if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
-        return SDL_SetError("Couldn't send rumble packet");
+        if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
+            return SDL_SetError("Couldn't send rumble packet");
+        }
+        return 0;
+    } else {
+        return SDL_Unsupported();
     }
-    return 0;
 }
 
 static int HIDAPI_DriverStadia_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
@@ -143,9 +147,10 @@ static int HIDAPI_DriverStadia_RumbleJoystickTriggers(SDL_HIDAPI_Device *device,
 
 static Uint32 HIDAPI_DriverStadia_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
 {
+    SDL_DriverStadia_Context *ctx = (SDL_DriverStadia_Context *)device->context;
     Uint32 caps = 0;
 
-    if (!device->is_bluetooth) {
+    if (ctx->rumble_supported) {
         caps |= SDL_JOYCAP_RUMBLE;
     }
     return caps;