mirror of
https://github.com/encounter/SDL.git
synced 2025-12-12 22:56:09 +00:00
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user