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.
This commit is contained in:
Sam Lantinga 2024-02-17 15:41:18 -08:00
parent 7f33464bed
commit f35ede7281
25 changed files with 298 additions and 272 deletions

View File

@ -49,16 +49,16 @@
#endif #endif
static SDL_JoystickDriver *SDL_joystick_drivers[] = { 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, &SDL_HIDAPI_JoystickDriver,
#endif #endif
#ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */ #ifdef SDL_JOYSTICK_GAMEINPUT /* Higher priority than other Windows drivers */
&SDL_RAWINPUT_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_GAMEINPUT /* Before WINDOWS_ driver, as GameInput takes priority over XInputOnGameInput for GDK platforms */
&SDL_GAMEINPUT_JoystickDriver, &SDL_GAMEINPUT_JoystickDriver,
#endif #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, &SDL_WINDOWS_JoystickDriver,
#endif #endif
#ifdef SDL_JOYSTICK_WGI #ifdef SDL_JOYSTICK_WGI
@ -659,6 +659,29 @@ SDL_bool SDL_JoysticksOpened(void)
return opened; 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) SDL_JoystickID *SDL_GetJoysticks(int *count)
{ {
int i, num_joysticks, device_index; int i, num_joysticks, device_index;

View File

@ -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 */ /* Function to return whether there are any joysticks opened by the application */
extern SDL_bool SDL_JoysticksOpened(void); 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 /* Function to standardize the name for a controller
This should be freed with SDL_free() when no longer needed This should be freed with SDL_free() when no longer needed
*/ */

View File

@ -158,6 +158,9 @@ typedef struct SDL_JoystickDriver
/* Function to cause any queued joystick insertions to be processed */ /* Function to cause any queued joystick insertions to be processed */
void (*Detect)(void); 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 */ /* Function to get the device-dependent name of a joystick */
const char *(*GetDeviceName)(int device_index); const char *(*GetDeviceName)(int device_index);

View File

@ -321,12 +321,9 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
goto done; goto done;
} }
#ifdef SDL_JOYSTICK_HIDAPI if (SDL_JoystickHandledByAnotherDriver(&SDL_ANDROID_JoystickDriver, vendor_id, product_id, 0, name)) {
if (HIDAPI_IsDevicePresent(vendor_id, product_id, 0, name)) {
/* The HIDAPI driver is taking care of this device */
goto done; goto done;
} }
#endif
#ifdef DEBUG_JOYSTICK #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); 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) static SDL_joylist_item *GetJoystickByDevIndex(int device_index)
{ {
SDL_joylist_item *item = SDL_joylist; SDL_joylist_item *item = SDL_joylist;
@ -646,6 +649,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = {
ANDROID_JoystickInit, ANDROID_JoystickInit,
ANDROID_JoystickGetCount, ANDROID_JoystickGetCount,
ANDROID_JoystickDetect, ANDROID_JoystickDetect,
ANDROID_JoystickIsDevicePresent,
ANDROID_JoystickGetDeviceName, ANDROID_JoystickGetDeviceName,
ANDROID_JoystickGetDevicePath, ANDROID_JoystickGetDevicePath,
ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot, ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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) static const char *IOS_JoystickGetDeviceName(int device_index)
{ {
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index); SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
@ -2079,6 +2085,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = {
IOS_JoystickInit, IOS_JoystickInit,
IOS_JoystickGetCount, IOS_JoystickGetCount,
IOS_JoystickDetect, IOS_JoystickDetect,
IOS_JoystickIsDevicePresent,
IOS_JoystickGetDeviceName, IOS_JoystickGetDeviceName,
IOS_JoystickGetDevicePath, IOS_JoystickGetDevicePath,
IOS_JoystickGetDeviceSteamVirtualGamepadSlot, IOS_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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); 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); 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 (SDL_ShouldIgnoreJoystick(name, guid) ||
if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) { SDL_JoystickHandledByAnotherDriver(&SDL_BSD_JoystickDriver, 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)) {
SDL_free(name); SDL_free(name);
FreeHwData(hw); FreeHwData(hw);
return -1; 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) static SDL_joylist_item *GetJoystickByDevIndex(int device_index)
{ {
SDL_joylist_item *item = SDL_joylist; SDL_joylist_item *item = SDL_joylist;
@ -848,6 +847,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = {
BSD_JoystickInit, BSD_JoystickInit,
BSD_JoystickGetCount, BSD_JoystickGetCount,
BSD_JoystickDetect, BSD_JoystickDetect,
BSD_JoystickIsDevicePresent,
BSD_JoystickGetDeviceName, BSD_JoystickGetDeviceName,
BSD_JoystickGetDevicePath, BSD_JoystickGetDevicePath,
BSD_JoystickGetDeviceSteamVirtualGamepadSlot, BSD_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -490,12 +490,9 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
SDL_free(name); SDL_free(name);
} }
#ifdef SDL_JOYSTICK_HIDAPI if (SDL_JoystickHandledByAnotherDriver(&SDL_DARWIN_JoystickDriver, vendor, product, version, pDevice->product)) {
if (HIDAPI_IsDevicePresent(vendor, product, version, pDevice->product)) {
/* The HIDAPI driver is taking care of this device */
return SDL_FALSE; 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->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); 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); recDevice *device = GetDeviceForIndex(device_index);
return device ? device->product : "UNKNOWN"; return device ? device->product : "UNKNOWN";
} }
const char *DARWIN_JoystickGetDevicePath(int device_index) static const char *DARWIN_JoystickGetDevicePath(int device_index)
{ {
return NULL; return NULL;
} }
@ -1063,6 +1066,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = {
DARWIN_JoystickInit, DARWIN_JoystickInit,
DARWIN_JoystickGetCount, DARWIN_JoystickGetCount,
DARWIN_JoystickDetect, DARWIN_JoystickDetect,
DARWIN_JoystickIsDevicePresent,
DARWIN_JoystickGetDeviceName, DARWIN_JoystickGetDeviceName,
DARWIN_JoystickGetDevicePath, DARWIN_JoystickGetDevicePath,
DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot, DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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) static const char *DUMMY_JoystickGetDeviceName(int device_index)
{ {
return NULL; return NULL;
@ -128,6 +133,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = {
DUMMY_JoystickInit, DUMMY_JoystickInit,
DUMMY_JoystickGetCount, DUMMY_JoystickGetCount,
DUMMY_JoystickDetect, DUMMY_JoystickDetect,
DUMMY_JoystickIsDevicePresent,
DUMMY_JoystickGetDeviceName, DUMMY_JoystickGetDeviceName,
DUMMY_JoystickGetDevicePath, DUMMY_JoystickGetDevicePath,
DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot, DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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) static const char *EMSCRIPTEN_JoystickGetDeviceName(int device_index)
{ {
return JoystickByDeviceIndex(device_index)->name; return JoystickByDeviceIndex(device_index)->name;
@ -414,6 +420,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = {
EMSCRIPTEN_JoystickInit, EMSCRIPTEN_JoystickInit,
EMSCRIPTEN_JoystickGetCount, EMSCRIPTEN_JoystickGetCount,
EMSCRIPTEN_JoystickDetect, EMSCRIPTEN_JoystickDetect,
EMSCRIPTEN_JoystickIsDevicePresent,
EMSCRIPTEN_JoystickGetDeviceName, EMSCRIPTEN_JoystickGetDeviceName,
EMSCRIPTEN_JoystickGetDevicePath, EMSCRIPTEN_JoystickGetDevicePath,
EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot, EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -24,11 +24,6 @@
#if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT #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... */ /* Public APIs: GAMEINPUT_Joystick... */
/* Private APIs: GAMEINPUT_InternalJoystick... */ /* Private APIs: GAMEINPUT_InternalJoystick... */
@ -38,6 +33,8 @@ typedef struct GAMEINPUT_InternalDevice
{ {
IGameInputDevice *device; IGameInputDevice *device;
const char *deviceName; /* this is a constant string literal */ const char *deviceName; /* this is a constant string literal */
Uint16 vendor;
Uint16 product;
SDL_JoystickGUID joystickGuid; /* generated by SDL. */ SDL_JoystickGUID joystickGuid; /* generated by SDL. */
SDL_JoystickID instanceId; /* generated by SDL. */ SDL_JoystickID instanceId; /* generated by SDL. */
int playerIndex; int playerIndex;
@ -71,6 +68,10 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
GAMEINPUT_InternalDevice **devicelist = NULL; GAMEINPUT_InternalDevice **devicelist = NULL;
GAMEINPUT_InternalDevice *elem = NULL; GAMEINPUT_InternalDevice *elem = NULL;
const GameInputDeviceInfo *devinfo = NULL; const GameInputDeviceInfo *devinfo = NULL;
Uint16 bus = SDL_HARDWARE_BUS_USB;
Uint16 vendor = 0;
Uint16 product = 0;
Uint16 version = 0;
char tmpbuff[4]; char tmpbuff[4];
int idx = 0; int idx = 0;
@ -96,33 +97,34 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
return SDL_OutOfMemory(); 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)); devicelist = (GAMEINPUT_InternalDevice **)SDL_realloc(g_GameInputList.devices, sizeof(elem) * (g_GameInputList.count + 1LL));
if (!devicelist) { if (!devicelist) {
SDL_free(elem); SDL_free(elem);
return SDL_OutOfMemory(); 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));
}
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; g_GameInputList.devices = devicelist;
IGameInputDevice_AddRef(pDevice); IGameInputDevice_AddRef(pDevice);
elem->device = pDevice; elem->device = pDevice;
elem->deviceName = "GameInput Gamepad"; elem->deviceName = "GameInput Gamepad";
elem->vendor = vendor;
elem->product = product;
elem->supportedRumbleMotors = devinfo->supportedRumbleMotors; elem->supportedRumbleMotors = devinfo->supportedRumbleMotors;
elem->joystickGuid = SDL_CreateJoystickGUID( elem->joystickGuid = SDL_CreateJoystickGUID(bus, vendor, product, version, "GameInput", "Gamepad", 'g', 0);
SDL_HARDWARE_BUS_BLUETOOTH,
USB_VENDOR_MICROSOFT,
USB_PRODUCT_XBOX_SERIES_X_BLE,
1,
"GameInput",
"Gamepad",
'g',
0
);
elem->instanceId = SDL_GetNextObjectID(); elem->instanceId = SDL_GetNextObjectID();
g_GameInputList.devices[g_GameInputList.count] = elem; 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) static const char *GAMEINPUT_JoystickGetDeviceName(int device_index)
{ {
GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index); GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
@ -566,6 +582,7 @@ SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver =
GAMEINPUT_JoystickInit, GAMEINPUT_JoystickInit,
GAMEINPUT_JoystickGetCount, GAMEINPUT_JoystickGetCount,
GAMEINPUT_JoystickDetect, GAMEINPUT_JoystickDetect,
GAMEINPUT_JoystickIsDevicePresent,
GAMEINPUT_JoystickGetDeviceName, GAMEINPUT_JoystickGetDeviceName,
GAMEINPUT_JoystickGetDevicePath, GAMEINPUT_JoystickGetDevicePath,
GAMEINPUT_JoystickGetDeviceSteamVirtualGamepadSlot, 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 */ #endif /* defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT */

View File

@ -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) static const char *HAIKU_JoystickGetDeviceName(int device_index)
{ {
return SDL_joyname[device_index]; return SDL_joyname[device_index];
@ -293,6 +299,7 @@ extern "C"
HAIKU_JoystickInit, HAIKU_JoystickInit,
HAIKU_JoystickGetCount, HAIKU_JoystickGetCount,
HAIKU_JoystickDetect, HAIKU_JoystickDetect,
HAIKU_JoystickIsDevicePresent,
HAIKU_JoystickGetDeviceName, HAIKU_JoystickGetDeviceName,
HAIKU_JoystickGetDevicePath, HAIKU_JoystickGetDevicePath,
HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot, HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

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

View File

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

View File

@ -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) static const char *N3DS_JoystickGetDevicePath(int device_index)
{ {
return NULL; return NULL;
@ -266,26 +272,27 @@ static int N3DS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int
} }
SDL_JoystickDriver SDL_N3DS_JoystickDriver = { SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
.Init = N3DS_JoystickInit, N3DS_JoystickInit,
.GetCount = N3DS_JoystickGetCount, N3DS_JoystickGetCount,
.Detect = N3DS_JoystickDetect, N3DS_JoystickDetect,
.GetDeviceName = N3DS_JoystickGetDeviceName, N3DS_JoystickIsDevicePresent,
.GetDevicePath = N3DS_JoystickGetDevicePath, N3DS_JoystickGetDeviceName,
.GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot, N3DS_JoystickGetDevicePath,
.GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex, N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
.SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex, N3DS_JoystickGetDevicePlayerIndex,
.GetDeviceGUID = N3DS_JoystickGetDeviceGUID, N3DS_JoystickSetDevicePlayerIndex,
.GetDeviceInstanceID = N3DS_JoystickGetDeviceInstanceID, N3DS_JoystickGetDeviceGUID,
.Open = N3DS_JoystickOpen, N3DS_JoystickGetDeviceInstanceID,
.Rumble = N3DS_JoystickRumble, N3DS_JoystickOpen,
.RumbleTriggers = N3DS_JoystickRumbleTriggers, N3DS_JoystickRumble,
.SetLED = N3DS_JoystickSetLED, N3DS_JoystickRumbleTriggers,
.SendEffect = N3DS_JoystickSendEffect, N3DS_JoystickSetLED,
.SetSensorsEnabled = N3DS_JoystickSetSensorsEnabled, N3DS_JoystickSendEffect,
.Update = N3DS_JoystickUpdate, N3DS_JoystickSetSensorsEnabled,
.Close = N3DS_JoystickClose, N3DS_JoystickUpdate,
.Quit = N3DS_JoystickQuit, N3DS_JoystickClose,
.GetGamepadMapping = N3DS_JoystickGetGamepadMapping N3DS_JoystickQuit,
N3DS_JoystickGetGamepadMapping
}; };
#endif /* SDL_JOYSTICK_N3DS */ #endif /* SDL_JOYSTICK_N3DS */

View File

@ -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 */ /* Function to get the device-dependent name of a joystick */
static const char *PS2_JoystickGetDeviceName(int index) static const char *PS2_JoystickGetDeviceName(int index)
{ {
@ -341,6 +347,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = {
PS2_JoystickInit, PS2_JoystickInit,
PS2_JoystickGetCount, PS2_JoystickGetCount,
PS2_JoystickDetect, PS2_JoystickDetect,
PS2_JoystickIsDevicePresent,
PS2_JoystickGetDeviceName, PS2_JoystickGetDeviceName,
PS2_JoystickGetDevicePath, PS2_JoystickGetDevicePath,
PS2_JoystickGetDeviceSteamVirtualGamepadSlot, PS2_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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 */ /* Function to get the device-dependent name of a joystick */
static const char *PSP_JoystickGetDeviceName(int device_index) static const char *PSP_JoystickGetDeviceName(int device_index)
{ {
@ -251,6 +257,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = {
PSP_JoystickInit, PSP_JoystickInit,
PSP_JoystickGetCount, PSP_JoystickGetCount,
PSP_JoystickDetect, PSP_JoystickDetect,
PSP_JoystickIsDevicePresent,
PSP_JoystickGetDeviceName, PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath, PSP_JoystickGetDevicePath,
PSP_JoystickGetDeviceSteamVirtualGamepadSlot, PSP_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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) static const char *VIRTUAL_JoystickGetDeviceName(int device_index)
{ {
joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
@ -749,6 +755,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = {
VIRTUAL_JoystickInit, VIRTUAL_JoystickInit,
VIRTUAL_JoystickGetCount, VIRTUAL_JoystickGetCount,
VIRTUAL_JoystickDetect, VIRTUAL_JoystickDetect,
VIRTUAL_JoystickIsDevicePresent,
VIRTUAL_JoystickGetDeviceName, VIRTUAL_JoystickGetDeviceName,
VIRTUAL_JoystickGetDevicePath, VIRTUAL_JoystickGetDevicePath,
VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot, VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -101,7 +101,7 @@ static int calc_bezier_y(float t)
* Joystick 0 should be the system default joystick. * Joystick 0 should be the system default joystick.
* It should return number of joysticks, or -1 on an unrecoverable fatal error. * It should return number of joysticks, or -1 on an unrecoverable fatal error.
*/ */
int VITA_JoystickInit(void) static int VITA_JoystickInit(void)
{ {
int i; int i;
SceCtrlPortInfo myPortInfo; SceCtrlPortInfo myPortInfo;
@ -139,22 +139,28 @@ int VITA_JoystickInit(void)
return SDL_numjoysticks; return SDL_numjoysticks;
} }
int VITA_JoystickGetCount() static int VITA_JoystickGetCount()
{ {
return SDL_numjoysticks; 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 */ /* 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; return device_index + 1;
} }
const char *VITA_JoystickGetDeviceName(int index) static const char *VITA_JoystickGetDeviceName(int index)
{ {
if (index == 0) { if (index == 0) {
return "PSVita Controller"; return "PSVita Controller";
@ -176,7 +182,7 @@ const char *VITA_JoystickGetDeviceName(int index)
return NULL; return NULL;
} }
const char *VITA_JoystickGetDevicePath(int index) static const char *VITA_JoystickGetDevicePath(int index)
{ {
return NULL; 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. This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error. 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->nbuttons = SDL_arraysize(ext_button_map);
joystick->naxes = 6; joystick->naxes = 6;
@ -309,16 +315,16 @@ static void VITA_JoystickUpdate(SDL_Joystick *joystick)
} }
/* Function to close a joystick after use */ /* 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 */ /* 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 */ /* the GUID is just the name for now */
const char *name = VITA_JoystickGetDeviceName(device_index); const char *name = VITA_JoystickGetDeviceName(device_index);
@ -378,6 +384,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = {
VITA_JoystickInit, VITA_JoystickInit,
VITA_JoystickGetCount, VITA_JoystickGetCount,
VITA_JoystickDetect, VITA_JoystickDetect,
VITA_JoystickIsDevicePresent,
VITA_JoystickGetDeviceName, VITA_JoystickGetDeviceName,
VITA_JoystickGetDevicePath, VITA_JoystickGetDevicePath,
VITA_JoystickGetDeviceSteamVirtualGamepadSlot, VITA_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

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

View File

@ -886,10 +886,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1); CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1);
/* Only take XInput-capable devices */ /* Only take XInput-capable devices */
CHECK(SDL_strstr(dev_name, "IG_") != NULL); CHECK(SDL_strstr(dev_name, "IG_") != NULL);
#ifdef SDL_JOYSTICK_HIDAPI CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_RAWINPUT_JoystickDriver, (Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
/* Don't take devices handled by HIDAPI */
CHECK(!HIDAPI_IsDevicePresent((Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
#endif
device = (SDL_RAWINPUT_Device *)SDL_calloc(1, sizeof(SDL_RAWINPUT_Device)); device = (SDL_RAWINPUT_Device *)SDL_calloc(1, sizeof(SDL_RAWINPUT_Device));
CHECK(device); CHECK(device);
device->hDevice = hDevice; device->hDevice = hDevice;
@ -1062,42 +1059,6 @@ SDL_bool RAWINPUT_IsEnabled()
return SDL_RAWINPUT_inited && !SDL_RAWINPUT_remote_desktop; 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) static void RAWINPUT_PostUpdate(void)
{ {
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING #ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
@ -1181,6 +1142,42 @@ static void RAWINPUT_JoystickDetect(void)
RAWINPUT_PostUpdate(); 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) static SDL_RAWINPUT_Device *RAWINPUT_GetDeviceByIndex(int device_index)
{ {
SDL_RAWINPUT_Device *device = SDL_RAWINPUT_devices; SDL_RAWINPUT_Device *device = SDL_RAWINPUT_devices;
@ -2206,6 +2203,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
RAWINPUT_JoystickInit, RAWINPUT_JoystickInit,
RAWINPUT_JoystickGetCount, RAWINPUT_JoystickGetCount,
RAWINPUT_JoystickDetect, RAWINPUT_JoystickDetect,
RAWINPUT_JoystickIsDevicePresent,
RAWINPUT_JoystickGetDeviceName, RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath, RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot, RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -24,9 +24,6 @@
/* Return true if the RawInput driver is enabled */ /* Return true if the RawInput driver is enabled */
extern SDL_bool RAWINPUT_IsEnabled(); 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 */ /* Registers for input events */
extern int RAWINPUT_RegisterNotifications(HWND hWnd); extern int RAWINPUT_RegisterNotifications(HWND hWnd);
extern int RAWINPUT_UnregisterNotifications(); extern int RAWINPUT_UnregisterNotifications();

View File

@ -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); 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_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() static void WGI_LoadRawGameControllerStatics()
{ {
HRESULT hr; HRESULT hr;
@ -448,23 +342,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
name = SDL_strdup(""); name = SDL_strdup("");
} }
#ifdef SDL_JOYSTICK_HIDAPI if (!ignore_joystick && SDL_JoystickHandledByAnotherDriver(&SDL_WGI_JoystickDriver, vendor, product, version, name)) {
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)) {
ignore_joystick = SDL_TRUE; 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) static const char *WGI_JoystickGetDeviceName(int device_index)
{ {
return wgi.controllers[device_index].name; return wgi.controllers[device_index].name;
@ -1009,6 +893,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = {
WGI_JoystickInit, WGI_JoystickInit,
WGI_JoystickGetCount, WGI_JoystickGetCount,
WGI_JoystickDetect, WGI_JoystickDetect,
WGI_JoystickIsDevicePresent,
WGI_JoystickGetDeviceName, WGI_JoystickGetDeviceName,
WGI_JoystickGetDevicePath, WGI_JoystickGetDevicePath,
WGI_JoystickGetDeviceSteamVirtualGamepadSlot, WGI_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -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) static const char *WINDOWS_JoystickGetDeviceName(int device_index)
{ {
JoyStick_DeviceData *device = SYS_Joystick; JoyStick_DeviceData *device = SYS_Joystick;
@ -788,6 +799,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
WINDOWS_JoystickInit, WINDOWS_JoystickInit,
WINDOWS_JoystickGetCount, WINDOWS_JoystickGetCount,
WINDOWS_JoystickDetect, WINDOWS_JoystickDetect,
WINDOWS_JoystickIsDevicePresent,
WINDOWS_JoystickGetDeviceName, WINDOWS_JoystickGetDeviceName,
WINDOWS_JoystickGetDevicePath, WINDOWS_JoystickGetDevicePath,
WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot, WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,

View File

@ -97,6 +97,13 @@ static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Ui
SDL_XINPUT_CAPABILITIES_EX capabilities; SDL_XINPUT_CAPABILITIES_EX capabilities;
if (!XINPUTGETCAPABILITIESEX || XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) != ERROR_SUCCESS) { 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; return SDL_FALSE;
} }
@ -199,22 +206,10 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
return; return;
} }
#ifdef SDL_JOYSTICK_HIDAPI if (SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname)) {
/* 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); SDL_free(pNewJoystick);
return; return;
} }
#endif
#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)) {
/* The RAWINPUT driver is taking care of this device */
SDL_free(pNewJoystick);
return;
}
#endif
WINDOWS_AddJoystickDevice(pNewJoystick); 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) int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
{ {
const Uint8 userId = joystickdevice->XInputUserId; 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) int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
{ {
return SDL_Unsupported(); return SDL_Unsupported();

View File

@ -30,6 +30,7 @@ extern "C" {
extern SDL_bool SDL_XINPUT_Enabled(void); extern SDL_bool SDL_XINPUT_Enabled(void);
extern int SDL_XINPUT_JoystickInit(void); extern int SDL_XINPUT_JoystickInit(void);
extern void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext); 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_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice);
extern int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); extern int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick);