Browse Source

Make sure we completely unlock joysticks when opening HIDAPI devices

Also lock the joysticks when adding and removing Android joysticks
Sam Lantinga 2 years ago
parent
commit
333935ff3f

+ 7 - 1
src/joystick/SDL_joystick.c

@@ -168,10 +168,16 @@ SDL_UnlockJoysticks(void)
     }
     }
 }
 }
 
 
+SDL_bool
+SDL_JoysticksLocked(void)
+{
+    return (SDL_joysticks_locked > 0) ? SDL_TRUE : SDL_FALSE;
+}
+
 void
 void
 SDL_AssertJoysticksLocked(void)
 SDL_AssertJoysticksLocked(void)
 {
 {
-    SDL_assert(SDL_joysticks_locked > 0);
+    SDL_assert(SDL_JoysticksLocked());
 }
 }
 
 
 /*
 /*

+ 3 - 0
src/joystick/SDL_joystick_c.h

@@ -45,6 +45,9 @@ extern SDL_bool SDL_JoysticksInitialized(void);
 /* Return whether the joystick system is shutting down */
 /* Return whether the joystick system is shutting down */
 extern SDL_bool SDL_JoysticksQuitting(void);
 extern SDL_bool SDL_JoysticksQuitting(void);
 
 
+/* Return whether the joysticks are currently locked */
+extern SDL_bool SDL_JoysticksLocked(void);
+
 /* Make sure we currently have the joysticks locked */
 /* Make sure we currently have the joysticks locked */
 extern void SDL_AssertJoysticksLocked(void);
 extern void SDL_AssertJoysticksLocked(void);
 
 

+ 27 - 11
src/joystick/android/SDL_sysjoystick.c

@@ -317,23 +317,25 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo
     SDL_JoystickGUID guid;
     SDL_JoystickGUID guid;
     int i;
     int i;
     int axis_mask;
     int axis_mask;
+    int result = -1;
 
 
+    SDL_LockJoysticks();
 
 
     if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) {
     if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) {
         /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */
         /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */
         if (naxes < 2 && nhats < 1) {
         if (naxes < 2 && nhats < 1) {
-            return -1;
+            goto done;
         }
         }
     }
     }
-    
+
     if (JoystickByDeviceId(device_id) != NULL || name == NULL) {
     if (JoystickByDeviceId(device_id) != NULL || name == NULL) {
-        return -1;
+        goto done;
     }
     }
 
 
 #ifdef SDL_JOYSTICK_HIDAPI
 #ifdef SDL_JOYSTICK_HIDAPI
     if (HIDAPI_IsDevicePresent(vendor_id, product_id, 0, name)) {
     if (HIDAPI_IsDevicePresent(vendor_id, product_id, 0, name)) {
         /* The HIDAPI driver is taking care of this device */
         /* The HIDAPI driver is taking care of this device */
-        return -1;
+        goto done;
     }
     }
 #endif
 #endif
 
 
@@ -377,7 +379,7 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo
 
 
     item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
     item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
     if (item == NULL) {
     if (item == NULL) {
-        return -1;
+        goto done;
     }
     }
 
 
     SDL_zerop(item);
     SDL_zerop(item);
@@ -385,8 +387,8 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo
     item->device_id = device_id;
     item->device_id = device_id;
     item->name = SDL_CreateJoystickName(vendor_id, product_id, NULL, name);
     item->name = SDL_CreateJoystickName(vendor_id, product_id, NULL, name);
     if (item->name == NULL) {
     if (item->name == NULL) {
-         SDL_free(item);
-         return -1;
+        SDL_free(item);
+        goto done;
     }
     }
     
     
     item->is_accelerometer = is_accelerometer;
     item->is_accelerometer = is_accelerometer;
@@ -415,11 +417,16 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo
 
 
     SDL_PrivateJoystickAdded(item->device_instance);
     SDL_PrivateJoystickAdded(item->device_instance);
 
 
+    result = numjoysticks;
+
 #ifdef DEBUG_JOYSTICK
 #ifdef DEBUG_JOYSTICK
     SDL_Log("Added joystick %s with device_id %d", item->name, device_id);
     SDL_Log("Added joystick %s with device_id %d", item->name, device_id);
 #endif
 #endif
 
 
-    return numjoysticks;
+done:
+    SDL_UnlockJoysticks();
+
+    return result;
 }
 }
 
 
 int 
 int 
@@ -427,7 +434,10 @@ Android_RemoveJoystick(int device_id)
 {
 {
     SDL_joylist_item *item = SDL_joylist;
     SDL_joylist_item *item = SDL_joylist;
     SDL_joylist_item *prev = NULL;
     SDL_joylist_item *prev = NULL;
+    int result = -1;
     
     
+    SDL_LockJoysticks();
+
     /* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
     /* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
     while (item != NULL) {
     while (item != NULL) {
         if (item->device_id == device_id) {
         if (item->device_id == device_id) {
@@ -438,7 +448,7 @@ Android_RemoveJoystick(int device_id)
     }
     }
     
     
     if (item == NULL) {
     if (item == NULL) {
-        return -1;
+        goto done;
     }
     }
 
 
     if (item->joystick) {
     if (item->joystick) {
@@ -460,13 +470,19 @@ Android_RemoveJoystick(int device_id)
 
 
     SDL_PrivateJoystickRemoved(item->device_instance);
     SDL_PrivateJoystickRemoved(item->device_instance);
 
 
+    result = numjoysticks;
+
 #ifdef DEBUG_JOYSTICK
 #ifdef DEBUG_JOYSTICK
     SDL_Log("Removed joystick with device_id %d", device_id);
     SDL_Log("Removed joystick with device_id %d", device_id);
 #endif
 #endif
-    
+
     SDL_free(item->name);
     SDL_free(item->name);
     SDL_free(item);
     SDL_free(item);
-    return numjoysticks;
+
+done:
+    SDL_UnlockJoysticks();
+
+    return result;
 }
 }
 
 
 
 

+ 10 - 4
src/joystick/hidapi/SDL_hidapijoystick.c

@@ -368,15 +368,21 @@ HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *removed)
              *
              *
              * 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;
             SDL_hid_device *dev;
-            char *path;
+            char *path = SDL_strdup(device->path);
 
 
             SDL_AssertJoysticksLocked();
             SDL_AssertJoysticksLocked();
-            path = SDL_strdup(device->path);
-            SDL_UnlockJoysticks();
+            while (SDL_JoysticksLocked()) {
+                ++lock_count;
+                SDL_UnlockJoysticks();
+            }
             dev = SDL_hid_open_path(path, 0);
             dev = SDL_hid_open_path(path, 0);
-            SDL_LockJoysticks();
+            while (lock_count > 0) {
+                --lock_count;
+                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 */