Browse Source

Generalized the idea of joystick driver priority

Joystick drivers are sorted by priority in the driver list, and higher priority drivers report whether they are handling a device when lower priority drivers want to add it to their device list.

This has been handled ad-hoc with the Windows and HIDAPI drivers, but this formalizes the idea and makes sure that GameInput has the highest priority of the Windows drivers.
Sam Lantinga 1 year ago
parent
commit
f35ede7281

+ 29 - 6
src/joystick/SDL_joystick.c

@@ -49,16 +49,16 @@
 #endif
 
 static SDL_JoystickDriver *SDL_joystick_drivers[] = {
-#ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
+#ifdef SDL_JOYSTICK_HIDAPI /* Highest priority driver for supported devices */
     &SDL_HIDAPI_JoystickDriver,
 #endif
-#ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
-    &SDL_RAWINPUT_JoystickDriver,
-#endif
-#ifdef SDL_JOYSTICK_GAMEINPUT /* Before WINDOWS_ driver, as GameInput takes priority over XInputOnGameInput for GDK platforms */
+#ifdef SDL_JOYSTICK_GAMEINPUT /* Higher priority than other Windows drivers */
     &SDL_GAMEINPUT_JoystickDriver,
 #endif
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT) /* Before WGI driver, as WGI wants to check if this driver is handling things */
+#ifdef SDL_JOYSTICK_RAWINPUT
+    &SDL_RAWINPUT_JoystickDriver,
+#endif
+#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
     &SDL_WINDOWS_JoystickDriver,
 #endif
 #ifdef SDL_JOYSTICK_WGI
@@ -659,6 +659,29 @@ SDL_bool SDL_JoysticksOpened(void)
     return opened;
 }
 
+SDL_bool SDL_JoystickHandledByAnotherDriver(struct SDL_JoystickDriver *driver, Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    int i;
+    SDL_bool result = SDL_FALSE;
+
+    SDL_LockJoysticks();
+    {
+        for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
+            if (driver == SDL_joystick_drivers[i]) {
+                /* Higher priority drivers do not have this device */
+                break;
+            }
+            if (SDL_joystick_drivers[i]->IsDevicePresent(vendor_id, product_id, version, name)) {
+                result = SDL_TRUE;
+                break;
+            }
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return result;
+}
+
 SDL_JoystickID *SDL_GetJoysticks(int *count)
 {
     int i, num_joysticks, device_index;

+ 3 - 0
src/joystick/SDL_joystick_c.h

@@ -54,6 +54,9 @@ extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_l
 /* Function to return whether there are any joysticks opened by the application */
 extern SDL_bool SDL_JoysticksOpened(void);
 
+/* Function to determine whether a device is currently detected by this driver */
+extern SDL_bool SDL_JoystickHandledByAnotherDriver(struct SDL_JoystickDriver *driver, Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
+
 /* Function to standardize the name for a controller
    This should be freed with SDL_free() when no longer needed
  */

+ 3 - 0
src/joystick/SDL_sysjoystick.h

@@ -158,6 +158,9 @@ typedef struct SDL_JoystickDriver
     /* Function to cause any queued joystick insertions to be processed */
     void (*Detect)(void);
 
+    /* Function to determine whether a device is currently detected by this driver */
+    SDL_bool (*IsDevicePresent)(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
+
     /* Function to get the device-dependent name of a joystick */
     const char *(*GetDeviceName)(int device_index);
 

+ 8 - 4
src/joystick/android/SDL_sysjoystick.c

@@ -321,12 +321,9 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
         goto done;
     }
 
-#ifdef SDL_JOYSTICK_HIDAPI
-    if (HIDAPI_IsDevicePresent(vendor_id, product_id, 0, name)) {
-        /* The HIDAPI driver is taking care of this device */
+    if (SDL_JoystickHandledByAnotherDriver(&SDL_ANDROID_JoystickDriver, vendor_id, product_id, 0, name)) {
         goto done;
     }
-#endif
 
 #ifdef DEBUG_JOYSTICK
     SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats\n", name, desc, vendor_id, product_id, naxes, nhats);
@@ -482,6 +479,12 @@ static void ANDROID_JoystickDetect(void)
     }
 }
 
+static SDL_bool ANDROID_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 static SDL_joylist_item *GetJoystickByDevIndex(int device_index)
 {
     SDL_joylist_item *item = SDL_joylist;
@@ -646,6 +649,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = {
     ANDROID_JoystickInit,
     ANDROID_JoystickGetCount,
     ANDROID_JoystickDetect,
+    ANDROID_JoystickIsDevicePresent,
     ANDROID_JoystickGetDeviceName,
     ANDROID_JoystickGetDevicePath,
     ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 7 - 0
src/joystick/apple/SDL_mfijoystick.m

@@ -879,6 +879,12 @@ static void IOS_JoystickDetect(void)
 {
 }
 
+static SDL_bool IOS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers through this method */
+    return SDL_FALSE;
+}
+
 static const char *IOS_JoystickGetDeviceName(int device_index)
 {
     SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
@@ -2079,6 +2085,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = {
     IOS_JoystickInit,
     IOS_JoystickGetCount,
     IOS_JoystickDetect,
+    IOS_JoystickIsDevicePresent,
     IOS_JoystickGetDeviceName,
     IOS_JoystickGetDevicePath,
     IOS_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 9 - 9
src/joystick/bsd/SDL_bsdjoystick.c

@@ -427,15 +427,8 @@ static int MaybeAddDevice(const char *path)
             name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product);
             guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0);
 
-#ifdef SDL_JOYSTICK_HIDAPI
-            if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {
-                /* The HIDAPI driver is taking care of this device */
-                SDL_free(name);
-                FreeHwData(hw);
-                return -1;
-            }
-#endif
-            if (SDL_ShouldIgnoreJoystick(name, guid)) {
+            if (SDL_ShouldIgnoreJoystick(name, guid) ||
+                SDL_JoystickHandledByAnotherDriver(&SDL_BSD_JoystickDriver, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {
                 SDL_free(name);
                 FreeHwData(hw);
                 return -1;
@@ -516,6 +509,12 @@ static void BSD_JoystickDetect(void)
 {
 }
 
+static SDL_bool BSD_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 static SDL_joylist_item *GetJoystickByDevIndex(int device_index)
 {
     SDL_joylist_item *item = SDL_joylist;
@@ -848,6 +847,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = {
     BSD_JoystickInit,
     BSD_JoystickGetCount,
     BSD_JoystickDetect,
+    BSD_JoystickIsDevicePresent,
     BSD_JoystickGetDeviceName,
     BSD_JoystickGetDevicePath,
     BSD_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 10 - 6
src/joystick/darwin/SDL_iokitjoystick.c

@@ -490,12 +490,9 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
         SDL_free(name);
     }
 
-#ifdef SDL_JOYSTICK_HIDAPI
-    if (HIDAPI_IsDevicePresent(vendor, product, version, pDevice->product)) {
-        /* The HIDAPI driver is taking care of this device */
+    if (SDL_JoystickHandledByAnotherDriver(&SDL_DARWIN_JoystickDriver, vendor, product, version, pDevice->product)) {
         return SDL_FALSE;
     }
-#endif
 
     pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0);
     pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
@@ -714,13 +711,19 @@ static void DARWIN_JoystickDetect(void)
     }
 }
 
-const char *DARWIN_JoystickGetDeviceName(int device_index)
+static SDL_bool DARWIN_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
+static const char *DARWIN_JoystickGetDeviceName(int device_index)
 {
     recDevice *device = GetDeviceForIndex(device_index);
     return device ? device->product : "UNKNOWN";
 }
 
-const char *DARWIN_JoystickGetDevicePath(int device_index)
+static const char *DARWIN_JoystickGetDevicePath(int device_index)
 {
     return NULL;
 }
@@ -1063,6 +1066,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = {
     DARWIN_JoystickInit,
     DARWIN_JoystickGetCount,
     DARWIN_JoystickDetect,
+    DARWIN_JoystickIsDevicePresent,
     DARWIN_JoystickGetDeviceName,
     DARWIN_JoystickGetDevicePath,
     DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 6 - 0
src/joystick/dummy/SDL_sysjoystick.c

@@ -41,6 +41,11 @@ static void DUMMY_JoystickDetect(void)
 {
 }
 
+static SDL_bool DUMMY_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    return SDL_FALSE;
+}
+
 static const char *DUMMY_JoystickGetDeviceName(int device_index)
 {
     return NULL;
@@ -128,6 +133,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = {
     DUMMY_JoystickInit,
     DUMMY_JoystickGetCount,
     DUMMY_JoystickDetect,
+    DUMMY_JoystickIsDevicePresent,
     DUMMY_JoystickGetDeviceName,
     DUMMY_JoystickGetDevicePath,
     DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 7 - 0
src/joystick/emscripten/SDL_sysjoystick.c

@@ -259,6 +259,12 @@ static void EMSCRIPTEN_JoystickDetect(void)
 {
 }
 
+static SDL_bool EMSCRIPTEN_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 static const char *EMSCRIPTEN_JoystickGetDeviceName(int device_index)
 {
     return JoystickByDeviceIndex(device_index)->name;
@@ -414,6 +420,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = {
     EMSCRIPTEN_JoystickInit,
     EMSCRIPTEN_JoystickGetCount,
     EMSCRIPTEN_JoystickDetect,
+    EMSCRIPTEN_JoystickIsDevicePresent,
     EMSCRIPTEN_JoystickGetDeviceName,
     EMSCRIPTEN_JoystickGetDevicePath,
     EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 38 - 26
src/joystick/gdk/SDL_gameinputjoystick.c

@@ -24,11 +24,6 @@
 
 #if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT
 
-/* Set up for C function definitions, even when using C++ */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Public APIs: GAMEINPUT_Joystick... */
 /* Private APIs: GAMEINPUT_InternalJoystick... */
 
@@ -38,6 +33,8 @@ typedef struct GAMEINPUT_InternalDevice
 {
     IGameInputDevice *device;
     const char *deviceName;        /* this is a constant string literal */
+    Uint16 vendor;
+    Uint16 product;
     SDL_JoystickGUID joystickGuid; /* generated by SDL. */
     SDL_JoystickID instanceId;     /* generated by SDL. */
     int playerIndex;
@@ -71,6 +68,10 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
     GAMEINPUT_InternalDevice **devicelist = NULL;
     GAMEINPUT_InternalDevice *elem = NULL;
     const GameInputDeviceInfo *devinfo = NULL;
+    Uint16 bus = SDL_HARDWARE_BUS_USB;
+    Uint16 vendor = 0;
+    Uint16 product = 0;
+    Uint16 version = 0;
     char tmpbuff[4];
     int idx = 0;
 
@@ -96,33 +97,34 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
         return SDL_OutOfMemory();
     }
 
+    devicelist = (GAMEINPUT_InternalDevice **)SDL_realloc(g_GameInputList.devices, sizeof(elem) * (g_GameInputList.count + 1LL));
+    if (!devicelist) {
+        SDL_free(elem);
+        return SDL_OutOfMemory();
+    }
+
     /* generate a device name */
     for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) {
         SDL_snprintf(tmpbuff, SDL_arraysize(tmpbuff), "%02hhX", devinfo->deviceId.value[idx]);
         SDL_strlcat(elem->devicePath, tmpbuff, SDL_arraysize(tmpbuff));
     }
-
-    devicelist = (GAMEINPUT_InternalDevice **)SDL_realloc(g_GameInputList.devices, sizeof(elem) * (g_GameInputList.count + 1LL));
-    if (!devicelist) {
-        SDL_free(elem);
-        return SDL_OutOfMemory();
+    if (devinfo->capabilities & GameInputDeviceCapabilityWireless) {
+        bus = SDL_HARDWARE_BUS_BLUETOOTH;
+    } else {
+        bus = SDL_HARDWARE_BUS_USB;
     }
+    vendor = devinfo->vendorId;
+    product = devinfo->productId;
+    version = (devinfo->major << 8) | devinfo->minor;
 
     g_GameInputList.devices = devicelist;
     IGameInputDevice_AddRef(pDevice);
     elem->device = pDevice;
     elem->deviceName = "GameInput Gamepad";
+    elem->vendor = vendor;
+    elem->product = product;
     elem->supportedRumbleMotors = devinfo->supportedRumbleMotors;
-    elem->joystickGuid = SDL_CreateJoystickGUID(
-        SDL_HARDWARE_BUS_BLUETOOTH,
-        USB_VENDOR_MICROSOFT,
-        USB_PRODUCT_XBOX_SERIES_X_BLE,
-        1,
-        "GameInput",
-        "Gamepad",
-        'g',
-        0
-    );
+    elem->joystickGuid = SDL_CreateJoystickGUID(bus, vendor, product, version, "GameInput", "Gamepad", 'g', 0);
     elem->instanceId = SDL_GetNextObjectID();
     g_GameInputList.devices[g_GameInputList.count] = elem;
 
@@ -274,6 +276,20 @@ static void GAMEINPUT_JoystickDetect(void)
     }
 }
 
+static SDL_bool GAMEINPUT_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    int idx = 0;
+    GAMEINPUT_InternalDevice *elem = NULL;
+
+    for (idx = 0; idx < g_GameInputList.count; ++idx) {
+        elem = g_GameInputList.devices[idx];
+        if (elem && vendor_id == elem->vendor && product_id == elem->product) {
+            return SDL_TRUE;
+        }
+    }
+    return SDL_FALSE;
+}
+
 static const char *GAMEINPUT_JoystickGetDeviceName(int device_index)
 {
     GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
@@ -312,7 +328,7 @@ static int GAMEINPUT_JoystickGetDevicePlayerIndex(int device_index)
      * you're meant to assign some index to a player yourself.
      *
      * GameMaker, for example, seems to do this in the order of plugging in.
-     * 
+     *
      * Sorry for the trouble!
      */
     GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
@@ -566,6 +582,7 @@ SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver =
     GAMEINPUT_JoystickInit,
     GAMEINPUT_JoystickGetCount,
     GAMEINPUT_JoystickDetect,
+    GAMEINPUT_JoystickIsDevicePresent,
     GAMEINPUT_JoystickGetDeviceName,
     GAMEINPUT_JoystickGetDevicePath,
     GAMEINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,
@@ -586,9 +603,4 @@ SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver =
 };
 
 
-/* Ends C function definitions when using C++ */
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT */

+ 7 - 0
src/joystick/haiku/SDL_haikujoystick.cc

@@ -91,6 +91,12 @@ extern "C"
     {
     }
 
+    static SDL_bool HAIKU_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+    {
+        /* We don't override any other drivers */
+        return SDL_FALSE;
+    }
+
     static const char *HAIKU_JoystickGetDeviceName(int device_index)
     {
         return SDL_joyname[device_index];
@@ -293,6 +299,7 @@ extern "C"
         HAIKU_JoystickInit,
         HAIKU_JoystickGetCount,
         HAIKU_JoystickDetect,
+        HAIKU_JoystickIsDevicePresent,
         HAIKU_JoystickGetDeviceName,
         HAIKU_JoystickGetDevicePath,
         HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 1 - 0
src/joystick/hidapi/SDL_hidapijoystick.c

@@ -1699,6 +1699,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = {
     HIDAPI_JoystickInit,
     HIDAPI_JoystickGetCount,
     HIDAPI_JoystickDetect,
+    HIDAPI_IsDevicePresent,
     HIDAPI_JoystickGetDeviceName,
     HIDAPI_JoystickGetDevicePath,
     HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 8 - 4
src/joystick/linux/SDL_sysjoystick.c

@@ -310,14 +310,11 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend
         return 0;
     }
 
-#ifdef SDL_JOYSTICK_HIDAPI
     if (!IsVirtualJoystick(inpid.vendor, inpid.product, inpid.version, name) &&
-        HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version, name)) {
-        /* The HIDAPI driver is taking care of this device */
+        SDL_JoystickHandledByAnotherDriver(&SDL_LINUX_JoystickDriver, inpid.vendor, inpid.product, inpid.version, name)) {
         SDL_free(name);
         return 0;
     }
-#endif
 
     FixupDeviceInfoForMapping(fd, &inpid);
 
@@ -987,6 +984,12 @@ static void LINUX_JoystickDetect(void)
     SDL_UpdateSteamControllers();
 }
 
+static SDL_bool LINUX_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 static int LINUX_JoystickInit(void)
 {
     const char *devices = SDL_GetHint(SDL_HINT_JOYSTICK_DEVICE);
@@ -2686,6 +2689,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = {
     LINUX_JoystickInit,
     LINUX_JoystickGetCount,
     LINUX_JoystickDetect,
+    LINUX_JoystickIsDevicePresent,
     LINUX_JoystickGetDeviceName,
     LINUX_JoystickGetDevicePath,
     LINUX_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 27 - 20
src/joystick/n3ds/SDL_sysjoystick.c

@@ -226,6 +226,12 @@ static void N3DS_JoystickDetect(void)
 {
 }
 
+static SDL_bool N3DS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 static const char *N3DS_JoystickGetDevicePath(int device_index)
 {
     return NULL;
@@ -266,26 +272,27 @@ static int N3DS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int
 }
 
 SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
-    .Init = N3DS_JoystickInit,
-    .GetCount = N3DS_JoystickGetCount,
-    .Detect = N3DS_JoystickDetect,
-    .GetDeviceName = N3DS_JoystickGetDeviceName,
-    .GetDevicePath = N3DS_JoystickGetDevicePath,
-    .GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
-    .GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex,
-    .SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex,
-    .GetDeviceGUID = N3DS_JoystickGetDeviceGUID,
-    .GetDeviceInstanceID = N3DS_JoystickGetDeviceInstanceID,
-    .Open = N3DS_JoystickOpen,
-    .Rumble = N3DS_JoystickRumble,
-    .RumbleTriggers = N3DS_JoystickRumbleTriggers,
-    .SetLED = N3DS_JoystickSetLED,
-    .SendEffect = N3DS_JoystickSendEffect,
-    .SetSensorsEnabled = N3DS_JoystickSetSensorsEnabled,
-    .Update = N3DS_JoystickUpdate,
-    .Close = N3DS_JoystickClose,
-    .Quit = N3DS_JoystickQuit,
-    .GetGamepadMapping = N3DS_JoystickGetGamepadMapping
+    N3DS_JoystickInit,
+    N3DS_JoystickGetCount,
+    N3DS_JoystickDetect,
+    N3DS_JoystickIsDevicePresent,
+    N3DS_JoystickGetDeviceName,
+    N3DS_JoystickGetDevicePath,
+    N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
+    N3DS_JoystickGetDevicePlayerIndex,
+    N3DS_JoystickSetDevicePlayerIndex,
+    N3DS_JoystickGetDeviceGUID,
+    N3DS_JoystickGetDeviceInstanceID,
+    N3DS_JoystickOpen,
+    N3DS_JoystickRumble,
+    N3DS_JoystickRumbleTriggers,
+    N3DS_JoystickSetLED,
+    N3DS_JoystickSendEffect,
+    N3DS_JoystickSetSensorsEnabled,
+    N3DS_JoystickUpdate,
+    N3DS_JoystickClose,
+    N3DS_JoystickQuit,
+    N3DS_JoystickGetGamepadMapping
 };
 
 #endif /* SDL_JOYSTICK_N3DS */

+ 7 - 0
src/joystick/ps2/SDL_sysjoystick.c

@@ -140,6 +140,12 @@ static void PS2_JoystickDetect()
 {
 }
 
+static SDL_bool PS2_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 /* Function to get the device-dependent name of a joystick */
 static const char *PS2_JoystickGetDeviceName(int index)
 {
@@ -341,6 +347,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = {
     PS2_JoystickInit,
     PS2_JoystickGetCount,
     PS2_JoystickDetect,
+    PS2_JoystickIsDevicePresent,
     PS2_JoystickGetDeviceName,
     PS2_JoystickGetDevicePath,
     PS2_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 7 - 0
src/joystick/psp/SDL_sysjoystick.c

@@ -105,6 +105,12 @@ static void PSP_JoystickDetect(void)
 {
 }
 
+static SDL_bool PSP_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 /* Function to get the device-dependent name of a joystick */
 static const char *PSP_JoystickGetDeviceName(int device_index)
 {
@@ -251,6 +257,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = {
     PSP_JoystickInit,
     PSP_JoystickGetCount,
     PSP_JoystickDetect,
+    PSP_JoystickIsDevicePresent,
     PSP_JoystickGetDeviceName,
     PSP_JoystickGetDevicePath,
     PSP_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 7 - 0
src/joystick/virtual/SDL_virtualjoystick.c

@@ -353,6 +353,12 @@ static void VIRTUAL_JoystickDetect(void)
 {
 }
 
+static SDL_bool VIRTUAL_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers... or do we? */
+    return SDL_FALSE;
+}
+
 static const char *VIRTUAL_JoystickGetDeviceName(int device_index)
 {
     joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
@@ -749,6 +755,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = {
     VIRTUAL_JoystickInit,
     VIRTUAL_JoystickGetCount,
     VIRTUAL_JoystickDetect,
+    VIRTUAL_JoystickIsDevicePresent,
     VIRTUAL_JoystickGetDeviceName,
     VIRTUAL_JoystickGetDevicePath,
     VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 17 - 10
src/joystick/vita/SDL_sysjoystick.c

@@ -101,7 +101,7 @@ static int calc_bezier_y(float t)
  * Joystick 0 should be the system default joystick.
  * It should return number of joysticks, or -1 on an unrecoverable fatal error.
  */
-int VITA_JoystickInit(void)
+static int VITA_JoystickInit(void)
 {
     int i;
     SceCtrlPortInfo myPortInfo;
@@ -139,22 +139,28 @@ int VITA_JoystickInit(void)
     return SDL_numjoysticks;
 }
 
-int VITA_JoystickGetCount()
+static int VITA_JoystickGetCount()
 {
     return SDL_numjoysticks;
 }
 
-void VITA_JoystickDetect()
+static void VITA_JoystickDetect()
 {
 }
 
+static SDL_bool VITA_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 /* Function to perform the mapping from device index to the instance id for this index */
-SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index)
+static SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index)
 {
     return device_index + 1;
 }
 
-const char *VITA_JoystickGetDeviceName(int index)
+static const char *VITA_JoystickGetDeviceName(int index)
 {
     if (index == 0) {
         return "PSVita Controller";
@@ -176,7 +182,7 @@ const char *VITA_JoystickGetDeviceName(int index)
     return NULL;
 }
 
-const char *VITA_JoystickGetDevicePath(int index)
+static const char *VITA_JoystickGetDevicePath(int index)
 {
     return NULL;
 }
@@ -200,7 +206,7 @@ static void VITA_JoystickSetDevicePlayerIndex(int device_index, int player_index
    This should fill the nbuttons and naxes fields of the joystick structure.
    It returns 0, or -1 if there is an error.
  */
-int VITA_JoystickOpen(SDL_Joystick *joystick, int device_index)
+static int VITA_JoystickOpen(SDL_Joystick *joystick, int device_index)
 {
     joystick->nbuttons = SDL_arraysize(ext_button_map);
     joystick->naxes = 6;
@@ -309,16 +315,16 @@ static void VITA_JoystickUpdate(SDL_Joystick *joystick)
 }
 
 /* Function to close a joystick after use */
-void VITA_JoystickClose(SDL_Joystick *joystick)
+static void VITA_JoystickClose(SDL_Joystick *joystick)
 {
 }
 
 /* Function to perform any system-specific joystick related cleanup */
-void VITA_JoystickQuit(void)
+static void VITA_JoystickQuit(void)
 {
 }
 
-SDL_JoystickGUID VITA_JoystickGetDeviceGUID(int device_index)
+static SDL_JoystickGUID VITA_JoystickGetDeviceGUID(int device_index)
 {
     /* the GUID is just the name for now */
     const char *name = VITA_JoystickGetDeviceName(device_index);
@@ -378,6 +384,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = {
     VITA_JoystickInit,
     VITA_JoystickGetCount,
     VITA_JoystickDetect,
+    VITA_JoystickIsDevicePresent,
     VITA_JoystickGetDeviceName,
     VITA_JoystickGetDevicePath,
     VITA_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 1 - 7
src/joystick/windows/SDL_dinputjoystick.c

@@ -516,13 +516,7 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
 
     CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
 
-#ifdef SDL_JOYSTICK_HIDAPI
-    CHECK(!HIDAPI_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname));
-#endif
-
-#ifdef SDL_JOYSTICK_RAWINPUT
-    CHECK(!RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname));
-#endif
+    CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname));
 
     WINDOWS_AddJoystickDevice(pNewJoystick);
     pNewJoystick = NULL;

+ 38 - 40
src/joystick/windows/SDL_rawinputjoystick.c

@@ -886,10 +886,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
     CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1);
     /* Only take XInput-capable devices */
     CHECK(SDL_strstr(dev_name, "IG_") != NULL);
-#ifdef SDL_JOYSTICK_HIDAPI
-    /* Don't take devices handled by HIDAPI */
-    CHECK(!HIDAPI_IsDevicePresent((Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
-#endif
+    CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_RAWINPUT_JoystickDriver, (Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
     device = (SDL_RAWINPUT_Device *)SDL_calloc(1, sizeof(SDL_RAWINPUT_Device));
     CHECK(device);
     device->hDevice = hDevice;
@@ -1062,42 +1059,6 @@ SDL_bool RAWINPUT_IsEnabled()
     return SDL_RAWINPUT_inited && !SDL_RAWINPUT_remote_desktop;
 }
 
-SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
-{
-    SDL_RAWINPUT_Device *device;
-
-    /* If we're being asked about a device, that means another API just detected one, so rescan */
-#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
-    xinput_device_change = SDL_TRUE;
-#endif
-
-    device = SDL_RAWINPUT_devices;
-    while (device) {
-        if (vendor_id == device->vendor_id && product_id == device->product_id) {
-            return SDL_TRUE;
-        }
-
-        /* The Xbox 360 wireless controller shows up as product 0 in WGI.
-           Try to match it to a Raw Input device via name or known product ID. */
-        if (vendor_id == device->vendor_id && product_id == 0 &&
-            ((name && SDL_strstr(device->name, name) != NULL) ||
-             (device->vendor_id == USB_VENDOR_MICROSOFT &&
-              device->product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER))) {
-            return SDL_TRUE;
-        }
-
-        /* The Xbox One controller shows up as a hardcoded raw input VID/PID */
-        if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 &&
-            device->vendor_id == USB_VENDOR_MICROSOFT &&
-            device->product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) {
-            return SDL_TRUE;
-        }
-
-        device = device->next;
-    }
-    return SDL_FALSE;
-}
-
 static void RAWINPUT_PostUpdate(void)
 {
 #ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
@@ -1181,6 +1142,42 @@ static void RAWINPUT_JoystickDetect(void)
     RAWINPUT_PostUpdate();
 }
 
+static SDL_bool RAWINPUT_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    SDL_RAWINPUT_Device *device;
+
+    /* If we're being asked about a device, that means another API just detected one, so rescan */
+#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
+    xinput_device_change = SDL_TRUE;
+#endif
+
+    device = SDL_RAWINPUT_devices;
+    while (device) {
+        if (vendor_id == device->vendor_id && product_id == device->product_id) {
+            return SDL_TRUE;
+        }
+
+        /* The Xbox 360 wireless controller shows up as product 0 in WGI.
+           Try to match it to a Raw Input device via name or known product ID. */
+        if (vendor_id == device->vendor_id && product_id == 0 &&
+            ((name && SDL_strstr(device->name, name) != NULL) ||
+             (device->vendor_id == USB_VENDOR_MICROSOFT &&
+              device->product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER))) {
+            return SDL_TRUE;
+        }
+
+        /* The Xbox One controller shows up as a hardcoded raw input VID/PID */
+        if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 &&
+            device->vendor_id == USB_VENDOR_MICROSOFT &&
+            device->product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) {
+            return SDL_TRUE;
+        }
+
+        device = device->next;
+    }
+    return SDL_FALSE;
+}
+
 static SDL_RAWINPUT_Device *RAWINPUT_GetDeviceByIndex(int device_index)
 {
     SDL_RAWINPUT_Device *device = SDL_RAWINPUT_devices;
@@ -2206,6 +2203,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
     RAWINPUT_JoystickInit,
     RAWINPUT_JoystickGetCount,
     RAWINPUT_JoystickDetect,
+    RAWINPUT_JoystickIsDevicePresent,
     RAWINPUT_JoystickGetDeviceName,
     RAWINPUT_JoystickGetDevicePath,
     RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 0 - 3
src/joystick/windows/SDL_rawinputjoystick_c.h

@@ -24,9 +24,6 @@
 /* Return true if the RawInput driver is enabled */
 extern SDL_bool RAWINPUT_IsEnabled();
 
-/* Return true if a RawInput device is present and supported as a joystick */
-extern SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
-
 /* Registers for input events */
 extern int RAWINPUT_RegisterNotifications(HWND hWnd);
 extern int RAWINPUT_UnregisterNotifications();

+ 8 - 123
src/joystick/windows/SDL_windows_gaming_input.c

@@ -106,114 +106,8 @@ DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, 0x43c0c035
 DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, 0xeb8d0792, 0xe95a, 0x4b19, 0xaf, 0xc7, 0x0a, 0x59, 0xf8, 0xbf, 0x75, 0x9e);
 
 extern SDL_bool SDL_XINPUT_Enabled(void);
-extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
 
 
-static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
-{
-#if defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT)
-    PRAWINPUTDEVICELIST raw_devices = NULL;
-    UINT i, raw_device_count = 0;
-    LONG vidpid = MAKELONG(vendor, product);
-
-    /* XInput and RawInput backends will pick up XInput-compatible devices */
-    if (!SDL_XINPUT_Enabled()
-#ifdef SDL_JOYSTICK_RAWINPUT
-        && !RAWINPUT_IsEnabled()
-#endif
-    ) {
-        return SDL_FALSE;
-    }
-
-    /* Go through RAWINPUT (WinXP and later) to find HID devices. */
-    if ((GetRawInputDeviceList(NULL, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!raw_device_count)) {
-        return SDL_FALSE; /* oh well. */
-    }
-
-    raw_devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * raw_device_count);
-    if (!raw_devices) {
-        return SDL_FALSE;
-    }
-
-    raw_device_count = GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST));
-    if (raw_device_count == (UINT)-1) {
-        SDL_free(raw_devices);
-        raw_devices = NULL;
-        return SDL_FALSE; /* oh well. */
-    }
-
-    for (i = 0; i < raw_device_count; i++) {
-        RID_DEVICE_INFO rdi;
-        char devName[MAX_PATH] = { 0 };
-        UINT rdiSize = sizeof(rdi);
-        UINT nameSize = SDL_arraysize(devName);
-        DEVINST devNode;
-        char devVidPidString[32];
-        int j;
-
-        rdi.cbSize = sizeof(rdi);
-
-        if ((raw_devices[i].dwType != RIM_TYPEHID) ||
-            (GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == ((UINT)-1)) ||
-            (GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) == ((UINT)-1)) ||
-            (SDL_strstr(devName, "IG_") == NULL)) {
-            /* Skip non-XInput devices */
-            continue;
-        }
-
-        /* First check for a simple VID/PID match. This will work for Xbox 360 controllers. */
-        if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == vidpid) {
-            SDL_free(raw_devices);
-            return SDL_TRUE;
-        }
-
-        /* For Xbox One controllers, Microsoft doesn't propagate the VID/PID down to the HID stack.
-         * We'll have to walk the device tree upwards searching for a match for our VID/PID. */
-
-        /* Make sure the device interface string is something we know how to parse */
-        /* Example: \\?\HID#VID_045E&PID_02FF&IG_00#9&2c203035&2&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} */
-        if ((SDL_strstr(devName, "\\\\?\\") != devName) || (SDL_strstr(devName, "#{") == NULL)) {
-            continue;
-        }
-
-        /* Unescape the backslashes in the string and terminate before the GUID portion */
-        for (j = 0; devName[j] != '\0'; j++) {
-            if (devName[j] == '#') {
-                if (devName[j + 1] == '{') {
-                    devName[j] = '\0';
-                    break;
-                } else {
-                    devName[j] = '\\';
-                }
-            }
-        }
-
-        /* We'll be left with a string like this: \\?\HID\VID_045E&PID_02FF&IG_00\9&2c203035&2&0000
-         * Simply skip the \\?\ prefix and we'll have a properly formed device instance ID */
-        if (CM_Locate_DevNodeA(&devNode, &devName[4], CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) {
-            continue;
-        }
-
-        (void)SDL_snprintf(devVidPidString, sizeof(devVidPidString), "VID_%04X&PID_%04X", vendor, product);
-
-        while (CM_Get_Parent(&devNode, devNode, 0) == CR_SUCCESS) {
-            char deviceId[MAX_DEVICE_ID_LEN];
-
-            if ((CM_Get_Device_IDA(devNode, deviceId, SDL_arraysize(deviceId), 0) == CR_SUCCESS) &&
-                (SDL_strstr(deviceId, devVidPidString) != NULL)) {
-                /* The VID/PID matched a parent device */
-                SDL_free(raw_devices);
-                return SDL_TRUE;
-            }
-        }
-    }
-
-    SDL_free(raw_devices);
-#endif /* SDL_JOYSTICK_XINPUT || SDL_JOYSTICK_RAWINPUT */
-
-    return SDL_FALSE;
-}
-
 static void WGI_LoadRawGameControllerStatics()
 {
     HRESULT hr;
@@ -448,23 +342,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             name = SDL_strdup("");
         }
 
-#ifdef SDL_JOYSTICK_HIDAPI
-        if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) {
-            ignore_joystick = SDL_TRUE;
-        }
-#endif
-
-#ifdef SDL_JOYSTICK_RAWINPUT
-        if (!ignore_joystick && RAWINPUT_IsDevicePresent(vendor, product, version, name)) {
-            ignore_joystick = SDL_TRUE;
-        }
-#endif
-
-        if (!ignore_joystick && SDL_DINPUT_JoystickPresent(vendor, product, version)) {
-            ignore_joystick = SDL_TRUE;
-        }
-
-        if (!ignore_joystick && SDL_IsXInputDevice(vendor, product)) {
+        if (!ignore_joystick && SDL_JoystickHandledByAnotherDriver(&SDL_WGI_JoystickDriver, vendor, product, version, name)) {
             ignore_joystick = SDL_TRUE;
         }
 
@@ -684,6 +562,12 @@ static void WGI_JoystickDetect(void)
 {
 }
 
+static SDL_bool WGI_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    /* We don't override any other drivers */
+    return SDL_FALSE;
+}
+
 static const char *WGI_JoystickGetDeviceName(int device_index)
 {
     return wgi.controllers[device_index].name;
@@ -1009,6 +893,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = {
     WGI_JoystickInit,
     WGI_JoystickGetCount,
     WGI_JoystickDetect,
+    WGI_JoystickIsDevicePresent,
     WGI_JoystickGetDeviceName,
     WGI_JoystickGetDevicePath,
     WGI_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 12 - 0
src/joystick/windows/SDL_windowsjoystick.c

@@ -579,6 +579,17 @@ void WINDOWS_JoystickDetect(void)
     }
 }
 
+static SDL_bool WINDOWS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+{
+    if (SDL_DINPUT_JoystickPresent(vendor_id, product_id, version)) {
+        return SDL_TRUE;
+    }
+    if (SDL_XINPUT_JoystickPresent(vendor_id, product_id, version)) {
+        return SDL_TRUE;
+    }
+    return SDL_FALSE;
+}
+
 static const char *WINDOWS_JoystickGetDeviceName(int device_index)
 {
     JoyStick_DeviceData *device = SYS_Joystick;
@@ -788,6 +799,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
     WINDOWS_JoystickInit,
     WINDOWS_JoystickGetCount,
     WINDOWS_JoystickDetect,
+    WINDOWS_JoystickIsDevicePresent,
     WINDOWS_JoystickGetDeviceName,
     WINDOWS_JoystickGetDevicePath,
     WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,

+ 36 - 13
src/joystick/windows/SDL_xinputjoystick.c

@@ -97,6 +97,13 @@ static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Ui
     SDL_XINPUT_CAPABILITIES_EX capabilities;
 
     if (!XINPUTGETCAPABILITIESEX || XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) != ERROR_SUCCESS) {
+        /* Use a generic VID/PID representing an XInput controller */
+        if (pVID) {
+            *pVID = USB_VENDOR_MICROSOFT;
+        }
+        if (pPID) {
+            *pPID = USB_PRODUCT_XBOX360_XUSB_CONTROLLER;
+        }
         return SDL_FALSE;
     }
 
@@ -199,22 +206,10 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
         return;
     }
 
-#ifdef SDL_JOYSTICK_HIDAPI
-    /* Since we're guessing about the VID/PID, use a hard-coded VID/PID to represent XInput */
-    if (HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, USB_PRODUCT_XBOX360_XUSB_CONTROLLER, version, pNewJoystick->joystickname)) {
-        /* The HIDAPI driver is taking care of this device */
-        SDL_free(pNewJoystick);
-        return;
-    }
-#endif
-
-#ifdef SDL_JOYSTICK_RAWINPUT
-    if (RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)) {
-        /* The RAWINPUT driver is taking care of this device */
+    if (SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname)) {
         SDL_free(pNewJoystick);
         return;
     }
-#endif
 
     WINDOWS_AddJoystickDevice(pNewJoystick);
 }
@@ -237,6 +232,29 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
     }
 }
 
+SDL_bool SDL_XINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
+{
+    int iuserid;
+
+    if (!s_bXInputEnabled) {
+        return SDL_FALSE;
+    }
+
+    /* iterate in reverse, so these are in the final list in ascending numeric order. */
+    for (iuserid = 0; iuserid < XUSER_MAX_COUNT; ++iuserid) {
+        const Uint8 userid = (Uint8)iuserid;
+        Uint16 slot_vendor;
+        Uint16 slot_product;
+        Uint16 slot_version;
+        if (GetXInputDeviceInfo(userid, &slot_vendor, &slot_product, &slot_version)) {
+            if (vendor == slot_vendor && product == slot_product && version == slot_version) {
+                return SDL_TRUE;
+            }
+        }
+    }
+    return SDL_FALSE;
+}
+
 int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
 {
     const Uint8 userId = joystickdevice->XInputUserId;
@@ -420,6 +438,11 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
 {
 }
 
+SDL_bool SDL_XINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
+{
+    return SDL_FALSE;
+}
+
 int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
 {
     return SDL_Unsupported();

+ 1 - 0
src/joystick/windows/SDL_xinputjoystick_c.h

@@ -30,6 +30,7 @@ extern "C" {
 extern SDL_bool SDL_XINPUT_Enabled(void);
 extern int SDL_XINPUT_JoystickInit(void);
 extern void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
+extern SDL_bool SDL_XINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
 extern int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice);
 extern int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
 extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick);