Commit 33050fea3997c7d0c1cf709fa5a70f5462e35ad9

Sam Lantinga 2022-10-07T11:29:49

Only open HID devices that might have a HIDAPI driver available This prevents an OS prompt for every connected device when running on Android

diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index 40884da..7bccd5f 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps4.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps4.c
@@ -194,7 +194,7 @@ HIDAPI_DriverPS4_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, 
     }
 
     if (SONY_THIRDPARTY_VENDOR(vendor_id)) {
-        if (device) {
+        if (device && device->dev) {
             if ((size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data))) == 48 &&
                 data[2] == 0x27) {
                 /* Supported third party controller */
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index 0e41d2e..4b2255d 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -277,7 +277,7 @@ HIDAPI_DriverPS5_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, 
     }
 
     if (SONY_THIRDPARTY_VENDOR(vendor_id)) {
-        if (device) {
+        if (device && device->dev) {
             if ((size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data))) == 48 &&
                 data[2] == 0x28) {
                 /* Supported third party controller */
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 8eaadb3..0bf66d8 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -1106,7 +1106,7 @@ static SDL_bool
 HIDAPI_DriverJoyCons_IsSupportedDevice(SDL_HIDAPI_Device *device, 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)
 {
     if (vendor_id == USB_VENDOR_NINTENDO) {
-        if (product_id == USB_PRODUCT_NINTENDO_SWITCH_PRO && device) {
+        if (product_id == USB_PRODUCT_NINTENDO_SWITCH_PRO && device && device->dev) {
             /* This might be a Kinvoca Joy-Con that reports VID/PID as a Switch Pro controller */
             ESwitchDeviceInfoControllerType eControllerType = ReadJoyConControllerType(device);
             if (eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index ee56e56..8cf9596 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -359,59 +359,61 @@ HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *removed)
         return; /* Already setup */
     }
 
-    /* Make sure we can open the device and leave it open for the driver */
-    if (device->num_children == 0) {
-        /* On Android we need to leave joysticks unlocked because it calls
-         * out to the main thread for permissions and the main thread can
-         * be in the process of handling controller input.
-         *
-         * See https://github.com/libsdl-org/SDL/issues/6347 for details
-         */
-        SDL_HIDAPI_Device *curr;
-        SDL_hid_device *dev;
-        char *path;
-
-        SDL_AssertJoysticksLocked();
-        path = SDL_strdup(device->path);
-        SDL_UnlockJoysticks();
-        dev = SDL_hid_open_path(path, 0);
-        SDL_LockJoysticks();
-        SDL_free(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) {
-            continue;
-        }
-        if (!curr) {
-            *removed = SDL_TRUE;
-            if (dev) {
-                SDL_hid_close(dev);
+    if (HIDAPI_GetDeviceDriver(device)) {
+        /* We might have a device driver for this device, try opening it and see */
+        if (device->num_children == 0) {
+            /* On Android we need to leave joysticks unlocked because it calls
+             * out to the main thread for permissions and the main thread can
+             * be in the process of handling controller input.
+             *
+             * See https://github.com/libsdl-org/SDL/issues/6347 for details
+             */
+            SDL_HIDAPI_Device *curr;
+            SDL_hid_device *dev;
+            char *path;
+
+            SDL_AssertJoysticksLocked();
+            path = SDL_strdup(device->path);
+            SDL_UnlockJoysticks();
+            dev = SDL_hid_open_path(path, 0);
+            SDL_LockJoysticks();
+            SDL_free(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) {
+                continue;
+            }
+            if (!curr) {
+                *removed = SDL_TRUE;
+                if (dev) {
+                    SDL_hid_close(dev);
+                }
+                return;
             }
-            return;
-        }
 
-        if (!dev) {
-            SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
-                         "HIDAPI_SetupDeviceDriver() couldn't open %s: %s\n",
-                         device->path, SDL_GetError());
-            return;
-        }
-        SDL_hid_set_nonblocking(dev, 1);
+            if (!dev) {
+                SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
+                             "HIDAPI_SetupDeviceDriver() couldn't open %s: %s\n",
+                             device->path, SDL_GetError());
+                return;
+            }
+            SDL_hid_set_nonblocking(dev, 1);
 
-        device->dev = dev;
-    }
+            device->dev = dev;
+        }
 
-    device->driver = HIDAPI_GetDeviceDriver(device);
+        device->driver = HIDAPI_GetDeviceDriver(device);
 
-    /* Initialize the device, which may cause a connected event */
-    if (device->driver && !device->driver->InitDevice(device)) {
-        HIDAPI_CleanupDeviceDriver(device);
-    }
+        /* Initialize the device, which may cause a connected event */
+        if (device->driver && !device->driver->InitDevice(device)) {
+            HIDAPI_CleanupDeviceDriver(device);
+        }
 
-    if (!device->driver && device->dev) {
-        /* No driver claimed this device, go ahead and close it */
-        SDL_hid_close(device->dev);
-        device->dev = NULL;
+        if (!device->driver && device->dev) {
+            /* No driver claimed this device, go ahead and close it */
+            SDL_hid_close(device->dev);
+            device->dev = NULL;
+        }
     }
 }