Fixed bug 4477 - Support more than 4 XInput-capable devices on Windows

Jimb Esser

Add new RawInput controller API, and improved correlation with XInput/WGI

Reorder joystick init so drivers can ask the others if they handle a device reliably
Do not poll disconnected XInput devices (major perf issue)
Fix various cases where incorrect correlation could happen
Simple mechanism for propagating unhandled Guide button presses even before guaranteed correlation
Correlate by axis motion as well as button presses
Fix failing to zero other trigger
Fix SDL_HINT_JOYSTICK_HIDAPI not working if set before calling SDL_Init()
Add missing device to device names
Disable RawInput if we have a mismatch of XInput-capable but not RawInput-capable devices

Updated to SDL 2.0.13 code with the following notes:
New HID driver: xbox360w - no idea what that is, hopefully urelated
SDL_hidapijoystick.c had been refactored to couple data handling logic with device opening logic and device lists caused some problems, yields slightly uglier integration than previously when the 360 HID device driver was just handling the data.
SDL_hidapijoystick.c now often pulls the device off of the joystick_hwdata structure for some rumble logic, but it appears that code path is never reached, so probably not a problem.
Looks like joystick_hwdata was refactored to not include a mutex in other drivers, maintainers may want to do the same refactor here if that's useful for some reason.
Something changed in how devices get names, so getting generic names.
Had to fix a (new?) bug where removing an XInput controller caused existing controllers (that moved to a new XInput index) to get identified as 0x045e/0x02fd ("it's probably Bluetooth" in code), rendering the existing HIDAPI_IsDevicePresent and new RAWINPUT_IsDevicePresent unreliable.
Sam Lantinga 2020-03-16 12:23:38 -07:00
parent cc37ee8a0c
commit 4dea340ca7
22 changed files with 889 additions and 220 deletions

View File

@ -318,12 +318,15 @@
<ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
<ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
<ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
<ClInclude Include="..\..\src\hidapi\hidapi\hidapi.h" />
<ClInclude Include="..\..\src\joystick\controller_type.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_rawinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
<ClInclude Include="..\..\src\libm\math_libm.h" />
@ -432,6 +435,7 @@
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_mmjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
<ClCompile Include="..\..\src\libm\e_atan2.c" />

View File

@ -323,6 +323,9 @@
<ClInclude Include="..\..\src\video\windows\SDL_windowswindow.h" />
<ClInclude Include="..\..\src\video\windows\wmmsg.h" />
<ClInclude Include="..\..\src\video\yuv2rgb\yuv_rgb.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_rawinputjoystick_c.h" />
<ClInclude Include="..\..\src\hidapi\hidapi\hidapi.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\atomic\SDL_atomic.c" />
@ -478,6 +481,7 @@
<ClCompile Include="..\..\src\video\windows\SDL_windowsvulkan.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowswindow.c" />
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\src\main\windows\version.rc" />

2
configure vendored
View File

@ -24336,6 +24336,8 @@ fi
$as_echo "#define SDL_JOYSTICK_HIDAPI 1" >>confdefs.h
$as_echo "#define SDL_JOYSTICK_RAWINPUT 1" >>confdefs.h
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
SOURCES="$SOURCES $srcdir/src/hidapi/SDL_hidapi.c"

View File

@ -3316,6 +3316,7 @@ AS_HELP_STRING([--enable-hidapi], [use HIDAPI for low level joystick drivers [[d
if test x$hidapi_support = xyes; then
AC_DEFINE(SDL_JOYSTICK_HIDAPI, 1, [ ])
AC_DEFINE(SDL_JOYSTICK_RAWINPUT, 1, [ ])
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
SOURCES="$SOURCES $srcdir/src/hidapi/SDL_hidapi.c"

View File

@ -289,6 +289,7 @@
#undef SDL_JOYSTICK_USBHID
#undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
#undef SDL_JOYSTICK_HIDAPI
#undef SDL_JOYSTICK_RAWINPUT
#undef SDL_JOYSTICK_EMSCRIPTEN
#undef SDL_JOYSTICK_VIRTUAL
#undef SDL_HAPTIC_DUMMY

View File

@ -197,6 +197,7 @@ typedef unsigned int uintptr_t;
#define SDL_JOYSTICK_DINPUT 1
#define SDL_JOYSTICK_XINPUT 1
#define SDL_JOYSTICK_HIDAPI 1
#define SDL_JOYSTICK_RAWINPUT 1
#define SDL_HAPTIC_DINPUT 1
#define SDL_HAPTIC_XINPUT 1

View File

@ -634,10 +634,23 @@ extern "C" {
* "0" - HIDAPI driver is not used
* "1" - HIDAPI driver is used
*
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
* The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI
*/
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
/**
* \brief A variable controlling whether the HIDAPI driver for XBox controllers on Windows should pull correlated
* data from XInput.
*
* This variable can be set to the following values:
* "0" - HIDAPI Xbox driver will only use HIDAPI data
* "1" - HIDAPI Xbox driver will also pull data from XInput, providing better trigger axes, guide button
* presses, and rumble support
*
* The default is "1". This hint applies to any joysticks opened after setting the hint.
*/
#define SDL_HINT_JOYSTICK_HIDAPI_CORRELATE_XINPUT "SDL_JOYSTICK_HIDAPI_CORRELATE_XINPUT"
/**
* \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
*
@ -660,6 +673,15 @@ extern "C" {
*/
#define SDL_HINT_ENABLE_STEAM_CONTROLLERS "SDL_ENABLE_STEAM_CONTROLLERS"
/**
* \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices.
*
* This variable can be set to the following values:
* "0" - RAWINPUT drivers are not used
* "1" - RAWINPUT drivers are used (the default)
*
*/
#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT"
/**
* \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it.

View File

@ -439,6 +439,12 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickG
/* This is a HIDAPI device */
return s_pHIDAPIMapping;
}
#if SDL_JOYSTICK_RAWINPUT
if (SDL_IsJoystickRAWINPUT(*guid)) {
/* This is a RAWINPUT device - same data as HIDAPI */
return s_pHIDAPIMapping;
}
#endif
#if SDL_JOYSTICK_XINPUT
if (SDL_IsJoystickXInput(*guid)) {
/* This is an XInput device */

View File

@ -51,6 +51,13 @@
#endif
static SDL_JoystickDriver *SDL_joystick_drivers[] = {
#ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
/* Also before HIDAPI, as HIDAPI wants to check if this driver is handling things */
&SDL_RAWINPUT_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
&SDL_HIDAPI_JoystickDriver,
#endif
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
&SDL_WINDOWS_JoystickDriver,
#endif
@ -75,9 +82,6 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
#ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */
&SDL_BSD_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_HIDAPI
&SDL_HIDAPI_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_VIRTUAL
&SDL_VIRTUAL_JoystickDriver,
#endif
@ -1729,6 +1733,12 @@ SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE;
}
SDL_bool
SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid)
{
return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE;
}
SDL_bool
SDL_IsJoystickVirtual(SDL_JoystickGUID guid)
{

View File

@ -73,6 +73,9 @@ extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
/* Function to return whether a joystick guid comes from the HIDAPI driver */
extern SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid);
/* Function to return whether a joystick guid comes from the RAWINPUT driver */
extern SDL_bool SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid);
/* Function to return whether a joystick guid comes from the Virtual driver */
extern SDL_bool SDL_IsJoystickVirtual(SDL_JoystickGUID guid);

View File

@ -150,6 +150,7 @@ extern SDL_JoystickDriver SDL_DUMMY_JoystickDriver;
extern SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver;
extern SDL_JoystickDriver SDL_HAIKU_JoystickDriver;
extern SDL_JoystickDriver SDL_HIDAPI_JoystickDriver;
extern SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver;
extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;

View File

@ -176,11 +176,11 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
if (ctx->joysticks[i] == -1) {
ResetAxisRange(ctx, i);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i], SDL_FALSE);
}
} else {
if (ctx->joysticks[i] != -1) {
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i], SDL_FALSE);
ctx->joysticks[i] = -1;
}
continue;
@ -252,7 +252,7 @@ HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
if (ctx->joysticks[i] == -1) {
ResetAxisRange(ctx, i);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i], SDL_FALSE);
}
joystick = SDL_JoystickFromInstanceID(ctx->joysticks[i]);
@ -262,7 +262,7 @@ HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
}
} else {
if (ctx->joysticks[i] != -1) {
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i], SDL_FALSE);
ctx->joysticks[i] = -1;
}
continue;

View File

@ -213,7 +213,7 @@ SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index)
static SDL_bool
HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
{
return HIDAPI_JoystickConnected(device, NULL);
return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
}
static int
@ -496,7 +496,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
}
return (size >= 0);
}

View File

@ -671,7 +671,7 @@ static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
static SDL_bool
HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
{
return HIDAPI_JoystickConnected(device, NULL);
return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
}
static int
@ -1121,7 +1121,7 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
}
return (size >= 0);
}

File diff suppressed because it is too large Load Diff

View File

@ -231,10 +231,10 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
if (connected) {
SDL_JoystickID joystickID;
HIDAPI_JoystickConnected(device, &joystickID);
HIDAPI_JoystickConnected(device, &joystickID, SDL_FALSE);
} else if (device->num_joysticks > 0) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
HIDAPI_JoystickDisconnected(device, device->joysticks[0], SDL_FALSE);
}
}
} else if (size == 29 && data[0] == 0x00 && data[1] == 0x0f && data[2] == 0x00 && data[3] == 0xf0) {
@ -262,7 +262,7 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
if (joystick) {
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
}
}
return (size >= 0);

View File

@ -279,7 +279,7 @@ HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
static SDL_bool
HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
{
return HIDAPI_JoystickConnected(device, NULL);
return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
}
static int
@ -694,7 +694,7 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
!ControllerSendsWaitingForInit(device->vendor_id, device->product_id)) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
if (!SendControllerInit(device, ctx)) {
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
return SDL_FALSE;
}
ctx->initialized = SDL_TRUE;
@ -737,7 +737,7 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
#endif
if (!SendControllerInit(device, ctx)) {
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
return SDL_FALSE;
}
ctx->initialized = SDL_TRUE;

View File

@ -37,6 +37,7 @@
#if defined(__WIN32__)
#include "../../core/windows/SDL_windows.h"
#include "../windows/SDL_rawinputjoystick_c.h"
#endif
#if defined(__MACOSX__)
@ -419,6 +420,13 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
return NULL;
}
#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsDevicePresent(device->vendor_id, device->product_id, device->version)) {
/* The RAWINPUT driver is taking care of this device */
return NULL;
}
#endif
if (device->usage_page && device->usage_page != USAGE_PAGE_GENERIC_DESKTOP) {
return NULL;
}
@ -502,7 +510,7 @@ HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
/* Disconnect any joysticks */
while (device->num_joysticks) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
HIDAPI_JoystickDisconnected(device, device->joysticks[0], SDL_FALSE);
}
device->driver->FreeDevice(device);
@ -575,6 +583,11 @@ HIDAPI_JoystickInit(void)
return -1;
}
#ifdef __WINDOWS__
/* On Windows, turns out HIDAPI for Xbox controllers doesn't allow background input, so off by default */
SDL_SetHintWithPriority(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0", SDL_HINT_DEFAULT);
#endif
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
SDL_AddHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
@ -591,7 +604,7 @@ HIDAPI_JoystickInit(void)
}
SDL_bool
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID, SDL_bool is_external)
{
SDL_JoystickID joystickID;
SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1)*sizeof(*device->joysticks));
@ -602,7 +615,9 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
joystickID = SDL_GetNextJoystickInstanceID();
device->joysticks = joysticks;
device->joysticks[device->num_joysticks++] = joystickID;
++SDL_HIDAPI_numjoysticks;
if (!is_external) {
++SDL_HIDAPI_numjoysticks;
}
SDL_PrivateJoystickAdded(joystickID);
@ -613,20 +628,22 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
}
void
HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID, SDL_bool is_external)
{
int i;
for (i = 0; i < device->num_joysticks; ++i) {
if (device->joysticks[i] == joystickID) {
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(joystickID);
if (joystick) {
if (joystick && !is_external) {
HIDAPI_JoystickClose(joystick);
}
SDL_memmove(&device->joysticks[i], &device->joysticks[i+1], device->num_joysticks - i - 1);
--device->num_joysticks;
--SDL_HIDAPI_numjoysticks;
if (!is_external) {
--SDL_HIDAPI_numjoysticks;
}
if (device->num_joysticks == 0) {
SDL_free(device->joysticks);
device->joysticks = NULL;
@ -882,6 +899,7 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
static void
HIDAPI_JoystickDetect(void)
{
int i;
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
HIDAPI_UpdateDiscovery();
if (SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
@ -891,6 +909,12 @@ HIDAPI_JoystickDetect(void)
}
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
}
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
if (driver->enabled && driver->PostUpdate) {
driver->PostUpdate();
}
}
}
void

View File

@ -40,8 +40,6 @@
#ifdef __WINDOWS__
/* On Windows, Xbox One controllers are handled by the Xbox 360 driver */
#undef SDL_JOYSTICK_HIDAPI_XBOXONE
/* It turns out HIDAPI for Xbox controllers doesn't allow background input */
#undef SDL_JOYSTICK_HIDAPI_XBOX360
#endif
#ifdef __MACOSX__
@ -103,6 +101,10 @@ typedef struct _SDL_HIDAPI_DeviceDriver
int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
void (*CloseJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
void (*FreeDevice)(SDL_HIDAPI_Device *device);
void (*PostUpdate)(void);
#ifdef SDL_JOYSTICK_RAWINPUT
void (*HandleStatePacketFromRAWINPUT)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 *data, int size);
#endif
} SDL_HIDAPI_DeviceDriver;
@ -120,8 +122,8 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube;
extern SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
extern void HIDAPI_UpdateDevices(void);
extern SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID);
extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID);
extern SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID, SDL_bool is_external);
extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID, SDL_bool is_external);
#endif /* SDL_JOYSTICK_HIDAPI_H */

View File

@ -26,6 +26,7 @@
#include "SDL_windowsjoystick_c.h"
#include "SDL_dinputjoystick_c.h"
#include "SDL_rawinputjoystick_c.h"
#include "SDL_xinputjoystick_c.h"
#include "../hidapi/SDL_hidapijoystick_c.h"
@ -672,6 +673,14 @@ EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
}
#endif
#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsDevicePresent(vendor, product, 0)) {
/* The RAWINPUT driver is taking care of this device */
SDL_free(pNewJoystick);
return DIENUM_CONTINUE;
}
#endif
WINDOWS_AddJoystickDevice(pNewJoystick);
return DIENUM_CONTINUE; /* get next device, please */

View File

@ -30,6 +30,7 @@
#include "SDL_timer.h"
#include "SDL_windowsjoystick_c.h"
#include "SDL_xinputjoystick_c.h"
#include "SDL_rawinputjoystick_c.h"
#include "../hidapi/SDL_hidapijoystick_c.h"
/*
@ -292,6 +293,14 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
}
#endif
#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsDevicePresent(vendor, product, version)) {
/* The RAWINPUT driver is taking care of this device */
SDL_free(pNewJoystick);
return;
}
#endif
WINDOWS_AddJoystickDevice(pNewJoystick);
}
@ -318,6 +327,18 @@ SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
const Uint8 userid = (Uint8)iuserid;
XINPUT_CAPABILITIES capabilities;
if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
/* Adding a new device, must handle all removes first, or GuessXInputDevice goes terribly wrong (returns
a product/vendor ID that is not even attached to the system) when we get a remove and add on the same tick
(e.g. when disconnecting a device and the OS reassigns which userid an already-attached controller is)
*/
int iuserid2;
for (iuserid2 = iuserid - 1; iuserid2 >= 0; iuserid2--) {
const Uint8 userid2 = (Uint8)iuserid2;
XINPUT_CAPABILITIES capabilities2;
if (XINPUTGETCAPABILITIES(userid2, XINPUT_FLAG_GAMEPAD, &capabilities2) != ERROR_SUCCESS) {
DelXInputDevice(userid2);
}
}
AddXInputDevice(userid, capabilities.SubType, pContext);
} else {
DelXInputDevice(userid);

View File

@ -30,6 +30,7 @@
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../../joystick/windows/SDL_rawinputjoystick_c.h"
#include "SDL_windowsvideo.h"
#include "SDL_windowswindow.h"
#include "SDL_hints.h"
@ -808,9 +809,18 @@ WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
}
}
static LRESULT CALLBACK SDL_HelperWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
#if SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_WindowProc(hWnd, msg, wParam, lParam) == 0) {
return 0;
}
#endif
return DefWindowProc(hWnd, msg, wParam, lParam);
}
/*
* Creates a HelperWindow used for DirectInput events.
* Creates a HelperWindow used for DirectInput and RawInput events.
*/
int
SDL_HelperWindowCreate(void)
@ -825,7 +835,7 @@ SDL_HelperWindowCreate(void)
/* Create the class. */
SDL_zero(wce);
wce.lpfnWndProc = DefWindowProc;
wce.lpfnWndProc = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, SDL_TRUE) ? SDL_HelperWindowProc : DefWindowProc;
wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
wce.hInstance = hInstance;