mirror of
https://github.com/Ryujinx/SDL.git
synced 2025-06-08 19:26:14 +00:00
Hold the joystick lock while opening the HID device on non-Android platforms
On Windows the main thread can be enumerating DirectInput devices while the Windows.Gaming.Input thread is calling back with a new controller available, and in this case HIDAPI_IsDevicePresent() returned false since the controller initialization hadn't completed yet, creating a duplicate controller. Fixes https://github.com/libsdl-org/SDL/issues/7304 (cherry picked from commit ece8a7bb8e2dae9cb53115980cea9ef1213a0160)
This commit is contained in:
parent
d948e6c3c5
commit
e86f494317
|
@ -380,44 +380,65 @@ static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *remove
|
||||||
if (HIDAPI_GetDeviceDriver(device)) {
|
if (HIDAPI_GetDeviceDriver(device)) {
|
||||||
/* We might have a device driver for this device, try opening it and see */
|
/* We might have a device driver for this device, try opening it and see */
|
||||||
if (device->num_children == 0) {
|
if (device->num_children == 0) {
|
||||||
|
SDL_hid_device *dev;
|
||||||
|
|
||||||
|
/* Wait a little bit for the device to initialize */
|
||||||
|
SDL_Delay(10);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
/* On Android we need to leave joysticks unlocked because it calls
|
/* On Android we need to leave joysticks unlocked because it calls
|
||||||
* out to the main thread for permissions and the main thread can
|
* out to the main thread for permissions and the main thread can
|
||||||
* be in the process of handling controller input.
|
* be in the process of handling controller input.
|
||||||
*
|
*
|
||||||
* See https://github.com/libsdl-org/SDL/issues/6347 for details
|
* See https://github.com/libsdl-org/SDL/issues/6347 for details
|
||||||
*/
|
*/
|
||||||
int lock_count = 0;
|
{
|
||||||
SDL_HIDAPI_Device *curr;
|
SDL_HIDAPI_Device *curr;
|
||||||
SDL_hid_device *dev;
|
int lock_count = 0;
|
||||||
char *path = SDL_strdup(device->path);
|
char *path = SDL_strdup(device->path);
|
||||||
|
|
||||||
/* Wait a little bit for the device to initialize */
|
/* Wait a little bit for the device to initialize */
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
|
|
||||||
SDL_AssertJoysticksLocked();
|
SDL_AssertJoysticksLocked();
|
||||||
while (SDL_JoysticksLocked()) {
|
while (SDL_JoysticksLocked()) {
|
||||||
++lock_count;
|
++lock_count;
|
||||||
SDL_UnlockJoysticks();
|
SDL_UnlockJoysticks();
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = SDL_hid_open_path(path, 0);
|
dev = SDL_hid_open_path(path, 0);
|
||||||
|
|
||||||
while (lock_count > 0) {
|
while (lock_count > 0) {
|
||||||
--lock_count;
|
--lock_count;
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
}
|
}
|
||||||
SDL_free(path);
|
SDL_free(path);
|
||||||
|
|
||||||
/* Make sure the device didn't get removed while opening the HID path */
|
/* Make sure the device didn't get removed while opening the HID path */
|
||||||
for (curr = SDL_HIDAPI_devices; curr && curr != device; curr = curr->next) {
|
for (curr = SDL_HIDAPI_devices; curr && curr != device; curr = curr->next) {
|
||||||
}
|
continue;
|
||||||
if (curr == NULL) {
|
}
|
||||||
*removed = SDL_TRUE;
|
if (curr == NULL) {
|
||||||
if (dev) {
|
*removed = SDL_TRUE;
|
||||||
SDL_hid_close(dev);
|
if (dev) {
|
||||||
|
SDL_hid_close(dev);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/* On other platforms we want to keep the lock so other threads wait for
|
||||||
|
* us to finish opening the controller before checking to see whether the
|
||||||
|
* HIDAPI driver is handling the device.
|
||||||
|
*
|
||||||
|
* On Windows, for example, the main thread can be enumerating DirectInput
|
||||||
|
* devices while the Windows.Gaming.Input thread is calling back with a new
|
||||||
|
* controller available.
|
||||||
|
*
|
||||||
|
* See https://github.com/libsdl-org/SDL/issues/7304 for details.
|
||||||
|
*/
|
||||||
|
dev = SDL_hid_open_path(device->path, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||||
|
|
Loading…
Reference in a new issue