diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c index abfce17eea..5426edbd71 100644 --- a/src/joystick/hidapi/SDL_hidapi_combined.c +++ b/src/joystick/hidapi/SDL_hidapi_combined.c @@ -70,6 +70,8 @@ static bool HIDAPI_DriverCombined_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Jo for (i = 0; i < device->num_children; ++i) { SDL_HIDAPI_Device *child = device->children[i]; if (!child->driver->OpenJoystick(child, joystick)) { + child->broken = true; + while (i-- > 0) { child = device->children[i]; child->driver->CloseJoystick(child, joystick); diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 85f551a480..6e09865df5 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -2727,6 +2727,7 @@ static bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) // Reconnect the Bluetooth device once the USB device is gone if (device->num_joysticks == 0 && device->is_bluetooth && packet_count > 0 && + !device->parent && !HIDAPI_HasConnectedUSBDevice(device->serial)) { HIDAPI_JoystickConnected(device, NULL); } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 566eae4a9d..bec9c90714 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -363,7 +363,7 @@ static SDL_HIDAPI_Device *HIDAPI_GetDeviceByIndex(int device_index, SDL_Joystick SDL_AssertJoysticksLocked(); for (device = SDL_HIDAPI_devices; device; device = device->next) { - if (device->parent) { + if (device->parent || device->broken) { continue; } if (device->driver) { @@ -685,7 +685,7 @@ bool HIDAPI_HasConnectedUSBDevice(const char *serial) } for (device = SDL_HIDAPI_devices; device; device = device->next) { - if (!device->driver) { + if (!device->driver || device->broken) { continue; } @@ -711,7 +711,7 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial) } for (device = SDL_HIDAPI_devices; device; device = device->next) { - if (!device->driver) { + if (!device->driver || device->broken) { continue; } @@ -1016,6 +1016,10 @@ static bool HIDAPI_CreateCombinedJoyCons(void) // This device is already part of a combined device continue; } + if (device->broken) { + // This device can't be used + continue; + } SDL_GetJoystickGUIDInfo(device->guid, &vendor, &product, NULL, NULL); @@ -1136,6 +1140,12 @@ check_removed: SDL_HIDAPI_change_count = 0; } } + if (device->broken && device->parent) { + HIDAPI_DelDevice(device->parent); + + // We deleted a different device here, restart the loop + goto check_removed; + } device = next; } @@ -1478,7 +1488,7 @@ static bool HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_AssertJoysticksLocked(); - if (!device || !device->driver) { + if (!device || !device->driver || device->broken) { // This should never happen - validated before being called return SDL_SetError("Couldn't find HIDAPI device at index %d", device_index); } diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index f8d7709392..9cd9f40065 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -101,6 +101,10 @@ typedef struct SDL_HIDAPI_Device // Used to flag that the device is being updated bool updating; + // Used to flag devices that failed open + // This can happen on Windows with Bluetooth devices that have turned off + bool broken; + struct SDL_HIDAPI_Device *parent; int num_children; struct SDL_HIDAPI_Device **children;