Generalized the raw input controller driver and moved XInput/WGI detection into it for XInput devices

This fixes bad report parsing for various newer Xbox controllers, and this driver is now preferred over XInput, since it handles more than 4 controllers.
This commit is contained in:
Sam Lantinga
2020-11-23 18:24:05 -08:00
parent 0ff5d55a07
commit 5b3616c325
23 changed files with 1804 additions and 1363 deletions

View File

@@ -175,11 +175,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], SDL_FALSE);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
}
} else {
if (ctx->joysticks[i] != -1) {
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i], SDL_FALSE);
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
ctx->joysticks[i] = -1;
}
continue;
@@ -251,7 +251,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], SDL_FALSE);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
}
joystick = SDL_JoystickFromInstanceID(ctx->joysticks[i]);
@@ -261,7 +261,7 @@ HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
}
} else {
if (ctx->joysticks[i] != -1) {
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i], SDL_FALSE);
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
ctx->joysticks[i] = -1;
}
continue;
@@ -432,7 +432,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,
HIDAPI_DriverGameCube_CloseJoystick,
HIDAPI_DriverGameCube_FreeDevice,
NULL,
};
#endif /* SDL_JOYSTICK_HIDAPI_GAMECUBE */

View File

@@ -143,7 +143,7 @@ typedef struct {
static SDL_bool
HIDAPI_DriverPS4_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
return (type == SDL_CONTROLLER_TYPE_PS4);
return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE;
}
static const char *
@@ -202,7 +202,7 @@ SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index)
static SDL_bool
HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
{
return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
return HIDAPI_JoystickConnected(device, NULL);
}
static int
@@ -769,7 +769,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
}
return (size >= 0);
}
@@ -807,7 +807,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
HIDAPI_DriverPS4_SetJoystickSensorsEnabled,
HIDAPI_DriverPS4_CloseJoystick,
HIDAPI_DriverPS4_FreeDevice,
NULL
};
#endif /* SDL_JOYSTICK_HIDAPI_PS4 */

View File

@@ -171,7 +171,7 @@ typedef struct {
static SDL_bool
HIDAPI_DriverPS5_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
return (type == SDL_CONTROLLER_TYPE_PS5);
return (type == SDL_CONTROLLER_TYPE_PS5) ? SDL_TRUE : SDL_FALSE;
}
static const char *
@@ -220,7 +220,7 @@ SetLedsForPlayerIndex(DS5EffectsState_t *effects, int player_index)
static SDL_bool
HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
{
return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
return HIDAPI_JoystickConnected(device, NULL);
}
static int
@@ -885,7 +885,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
}
return (size >= 0);
}
@@ -923,7 +923,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
HIDAPI_DriverPS5_SetJoystickSensorsEnabled,
HIDAPI_DriverPS5_CloseJoystick,
HIDAPI_DriverPS5_FreeDevice,
NULL
};
#endif /* SDL_JOYSTICK_HIDAPI_PS5 */

View File

@@ -971,7 +971,7 @@ HIDAPI_DriverSteam_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
static SDL_bool
HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
{
return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
return HIDAPI_JoystickConnected(device, NULL);
}
static int
@@ -1160,7 +1160,7 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
if (r <= 0) {
/* Failed to read from controller */
HIDAPI_JoystickDisconnected(device, device->joysticks[0], SDL_FALSE);
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
return SDL_FALSE;
}
}
@@ -1201,7 +1201,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
HIDAPI_DriverSteam_SetSensorsEnabled,
HIDAPI_DriverSteam_CloseJoystick,
HIDAPI_DriverSteam_FreeDevice,
NULL
};
#endif /* SDL_JOYSTICK_HIDAPI_STEAM */

View File

@@ -288,7 +288,7 @@ HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, SDL_GameControllerType t
if (SDL_strcmp( name, "HORI Wireless Switch Pad" ) == 0) {
return SDL_FALSE;
}
return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO);
return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
}
static const char *
@@ -697,7 +697,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, SDL_FALSE);
return HIDAPI_JoystickConnected(device, NULL);
}
static int
@@ -1259,7 +1259,7 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
}
return (size >= 0);
}
@@ -1307,7 +1307,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,
HIDAPI_DriverSwitch_CloseJoystick,
HIDAPI_DriverSwitch_FreeDevice,
NULL
};
#endif /* SDL_JOYSTICK_HIDAPI_SWITCH */

File diff suppressed because it is too large Load Diff

View File

@@ -255,10 +255,10 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
if (connected) {
SDL_JoystickID joystickID;
HIDAPI_JoystickConnected(device, &joystickID, SDL_FALSE);
HIDAPI_JoystickConnected(device, &joystickID);
} else if (device->num_joysticks > 0) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0], SDL_FALSE);
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
}
} else if (size == 29 && data[0] == 0x00 && data[1] == 0x0f && data[2] == 0x00 && data[3] == 0xf0) {
@@ -286,7 +286,7 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
if (joystick) {
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
}
}
return (size >= 0);
@@ -325,7 +325,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled,
HIDAPI_DriverXbox360W_CloseJoystick,
HIDAPI_DriverXbox360W_FreeDevice,
NULL
};
#endif /* SDL_JOYSTICK_HIDAPI_XBOX360 */

View File

@@ -291,7 +291,7 @@ HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, SDL_GameControllerType
return SDL_FALSE;
}
#endif
return (type == SDL_CONTROLLER_TYPE_XBOXONE);
return (type == SDL_CONTROLLER_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE;
}
static const char *
@@ -303,7 +303,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, SDL_FALSE);
return HIDAPI_JoystickConnected(device, NULL);
}
static int
@@ -852,7 +852,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, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
return SDL_FALSE;
}
ctx->initialized = SDL_TRUE;
@@ -918,7 +918,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, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
return SDL_FALSE;
}
ctx->initialized = SDL_TRUE;
@@ -973,7 +973,7 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
}
return (size >= 0);
}
@@ -1011,7 +1011,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled,
HIDAPI_DriverXboxOne_CloseJoystick,
HIDAPI_DriverXboxOne_FreeDevice,
NULL
};
#endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */

View File

@@ -443,13 +443,6 @@ 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->vendor_id != USB_VENDOR_VALVE) {
if (device->usage_page && device->usage_page != USAGE_PAGE_GENERIC_DESKTOP) {
return NULL;
@@ -535,7 +528,7 @@ HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
/* Disconnect any joysticks */
while (device->num_joysticks) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0], SDL_FALSE);
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
device->driver->FreeDevice(device);
@@ -608,11 +601,6 @@ 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);
@@ -629,7 +617,7 @@ HIDAPI_JoystickInit(void)
}
SDL_bool
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID, SDL_bool is_external)
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
{
SDL_JoystickID joystickID;
SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1)*sizeof(*device->joysticks));
@@ -640,9 +628,7 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID,
joystickID = SDL_GetNextJoystickInstanceID();
device->joysticks = joysticks;
device->joysticks[device->num_joysticks++] = joystickID;
if (!is_external) {
++SDL_HIDAPI_numjoysticks;
}
++SDL_HIDAPI_numjoysticks;
SDL_PrivateJoystickAdded(joystickID);
@@ -653,14 +639,14 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID,
}
void
HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID, SDL_bool is_external)
HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
{
int i, size;
for (i = 0; i < device->num_joysticks; ++i) {
if (device->joysticks[i] == joystickID) {
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(joystickID);
if (joystick && !is_external) {
if (joystick) {
HIDAPI_JoystickClose(joystick);
}
@@ -668,9 +654,7 @@ HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID
SDL_memmove(&device->joysticks[i], &device->joysticks[i+1], size);
--device->num_joysticks;
if (!is_external) {
--SDL_HIDAPI_numjoysticks;
}
--SDL_HIDAPI_numjoysticks;
if (device->num_joysticks == 0) {
SDL_free(device->joysticks);
device->joysticks = NULL;
@@ -932,7 +916,6 @@ 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) {
@@ -942,12 +925,6 @@ 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

@@ -38,11 +38,6 @@
#define SDL_JOYSTICK_HIDAPI_XBOXONE
#define SDL_JOYSTICK_HIDAPI_GAMECUBE
#ifdef __WINDOWS__
/* On Windows, Xbox One controllers are handled by the Xbox 360 driver */
#undef SDL_JOYSTICK_HIDAPI_XBOXONE
#endif
#if defined(__IPHONEOS__) || defined(__TVOS__) || defined(__ANDROID__)
/* Very basic Steam Controller support on mobile devices */
#define SDL_JOYSTICK_HIDAPI_STEAM
@@ -102,10 +97,6 @@ typedef struct _SDL_HIDAPI_DeviceDriver
int (*SetJoystickSensorsEnabled)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled);
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;
@@ -124,8 +115,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, SDL_bool is_external);
extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID, SDL_bool is_external);
extern SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID);
extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID);
extern void HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size);