Fix Xbox Series X controller on macOS There were two different implementations of IsBluetoothXboxOneController(), one in SDL_hidapi_xbox360.c and one in SDL_hidapi_xboxone.c. The latter had been updated to include USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH while the former had not. This mismatch led to the Xbox Series X failing on macOS only. We have special code for handling the 360Controller driver for macOS which requires us to use the Xbox 360 driver for wired Xbox One controllers, and the SDL_hidapi_xbox360 version of IsBluetoothXboxOneController() was used to determine which devices were wired. In addition to adding the missing USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH, this change moves IsBluetoothXboxOneController() into a single shared function which will ensure this bug won't happen again.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index a9177f3..d532e52 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1927,6 +1927,20 @@ SDL_IsJoystickXboxOneSeriesX(Uint16 vendor_id, Uint16 product_id)
}
SDL_bool
+SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id)
+{
+ if (vendor_id == USB_VENDOR_MICROSOFT) {
+ if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
+ product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
+ product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ||
+ product_id == USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+SDL_bool
SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index 7459c2d..8e634ac 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -68,6 +68,9 @@ extern SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick is an Xbox One Series X controller */
extern SDL_bool SDL_IsJoystickXboxOneSeriesX(Uint16 vendor_id, Uint16 product_id);
+/* Function to return whether a joystick is an Xbox One controller connected via Bluetooth */
+extern SDL_bool SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id);
+
/* Function to return whether a joystick is a PS4 controller */
extern SDL_bool SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id);
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c
index 6702937..08f23eb 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c
@@ -42,22 +42,6 @@ typedef struct {
Uint8 last_state[USB_PACKET_LENGTH];
} SDL_DriverXbox360_Context;
-#if defined(__MACOSX__)
-static SDL_bool
-IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
-{
- /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
- if (vendor_id == USB_VENDOR_MICROSOFT) {
- if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
- product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
- product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
-}
-#endif
-
static SDL_bool
HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
@@ -89,7 +73,7 @@ HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType
Bluetooth Xbox One controllers are handled by the SDL Xbox One driver
*/
- if (IsBluetoothXboxOneController(vendor_id, product_id)) {
+ if (SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) {
return SDL_FALSE;
}
return (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE;
@@ -177,7 +161,7 @@ static int
HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
#ifdef __MACOSX__
- if (IsBluetoothXboxOneController(device->vendor_id, device->product_id)) {
+ if (SDL_IsJoystickBluetoothXboxOne(device->vendor_id, device->product_id)) {
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
rumble_packet[4] = (low_frequency_rumble >> 8);
diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c
index fe9f305..bcc05d7 100644
--- a/src/joystick/hidapi/SDL_hidapi_xboxone.c
+++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c
@@ -129,22 +129,6 @@ typedef struct {
Uint8 right_trigger_rumble;
} SDL_DriverXboxOne_Context;
-
-static SDL_bool
-IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
-{
- /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
- if (vendor_id == USB_VENDOR_MICROSOFT) {
- if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
- product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
- product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ||
- product_id == USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH) {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
-}
-
static SDL_bool
ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
{
@@ -289,7 +273,7 @@ HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, SDL_GameControllerType
#endif
#ifdef __MACOSX__
/* Wired Xbox One controllers are handled by the 360Controller driver */
- if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
+ if (!SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) {
return SDL_FALSE;
}
#endif
@@ -343,7 +327,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
ctx->vendor_id = device->vendor_id;
ctx->product_id = device->product_id;
- ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
+ ctx->bluetooth = SDL_IsJoystickBluetoothXboxOne(device->vendor_id, device->product_id);
ctx->start_time = SDL_GetTicks();
ctx->sequence = 1;
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);