Worked around bug with Sony PS Now PS3 controller where DirectInput polling will continue to return success after the controller is unplugged.

The code is now reliant on SDL_PrivateJoystickAdded() and SDL_PrivateJoystickRemoved() being called correctly when devices are added or removed on Windows
This commit is contained in:
Sam Lantinga 2018-08-09 16:03:50 -07:00
parent f35e97ba8a
commit 888bf1af69
17 changed files with 31 additions and 118 deletions

View File

@ -297,6 +297,7 @@ SDL_JoystickOpen(int device_index)
} }
joystick->driver = driver; joystick->driver = driver;
joystick->instance_id = instance_id; joystick->instance_id = instance_id;
joystick->attached = SDL_TRUE;
if (driver->Open(joystick, device_index) < 0) { if (driver->Open(joystick, device_index) < 0) {
SDL_free(joystick); SDL_free(joystick);
@ -545,7 +546,7 @@ SDL_JoystickGetAttached(SDL_Joystick * joystick)
return SDL_FALSE; return SDL_FALSE;
} }
return joystick->driver->IsAttached(joystick); return joystick->attached;
} }
/* /*
@ -765,6 +766,8 @@ static void UpdateEventsForDeviceRemoval()
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance) void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
{ {
SDL_Joystick *joystick;
#if !SDL_EVENTS_DISABLED #if !SDL_EVENTS_DISABLED
SDL_Event event; SDL_Event event;
@ -777,6 +780,15 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
UpdateEventsForDeviceRemoval(); UpdateEventsForDeviceRemoval();
#endif /* !SDL_EVENTS_DISABLED */ #endif /* !SDL_EVENTS_DISABLED */
/* Mark this joystick as no longer attached */
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->instance_id == device_instance) {
joystick->attached = SDL_FALSE;
joystick->force_recentering = SDL_TRUE;
break;
}
}
} }
int int
@ -984,11 +996,13 @@ SDL_JoystickUpdate(void)
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->attached) {
joystick->driver->Update(joystick); joystick->driver->Update(joystick);
if (joystick->delayed_guide_button) { if (joystick->delayed_guide_button) {
SDL_GameControllerHandleDelayedGuideButton(joystick); SDL_GameControllerHandleDelayedGuideButton(joystick);
} }
}
if (joystick->force_recentering) { if (joystick->force_recentering) {
/* Tell the app that everything is centered/unpressed... */ /* Tell the app that everything is centered/unpressed... */

View File

@ -59,6 +59,7 @@ struct _SDL_Joystick
int nbuttons; /* Number of buttons on the joystick */ int nbuttons; /* Number of buttons on the joystick */
Uint8 *buttons; /* Current button states */ Uint8 *buttons; /* Current button states */
SDL_bool attached;
SDL_bool is_game_controller; SDL_bool is_game_controller;
SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */ SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */
SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */ SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
@ -117,11 +118,6 @@ typedef struct _SDL_JoystickDriver
*/ */
int (*Open)(SDL_Joystick * joystick, int device_index); int (*Open)(SDL_Joystick * joystick, int device_index);
/* Function to query if the joystick is currently attached
* It returns SDL_TRUE if attached, SDL_FALSE otherwise.
*/
SDL_bool (*IsAttached)(SDL_Joystick * joystick);
/* Rumble functionality */ /* Rumble functionality */
int (*Rumble)(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); int (*Rumble)(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);

View File

@ -617,12 +617,6 @@ ANDROID_JoystickOpen(SDL_Joystick * joystick, int device_index)
return (0); return (0);
} }
static SDL_bool
ANDROID_JoystickIsAttached(SDL_Joystick *joystick)
{
return joystick->hwdata != NULL;
}
static int static int
ANDROID_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) ANDROID_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{ {
@ -698,7 +692,6 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver =
ANDROID_JoystickGetDeviceGUID, ANDROID_JoystickGetDeviceGUID,
ANDROID_JoystickGetDeviceInstanceID, ANDROID_JoystickGetDeviceInstanceID,
ANDROID_JoystickOpen, ANDROID_JoystickOpen,
ANDROID_JoystickIsAttached,
ANDROID_JoystickRumble, ANDROID_JoystickRumble,
ANDROID_JoystickUpdate, ANDROID_JoystickUpdate,
ANDROID_JoystickClose, ANDROID_JoystickClose,

View File

@ -467,12 +467,6 @@ desc_failed:
return (-1); return (-1);
} }
/* Function to determine if this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return SDL_TRUE;
}
void void
SDL_SYS_JoystickUpdate(SDL_Joystick * joy) SDL_SYS_JoystickUpdate(SDL_Joystick * joy)
{ {

View File

@ -736,12 +736,6 @@ DARWIN_JoystickOpen(SDL_Joystick * joystick, int device_index)
return 0; return 0;
} }
static SDL_bool
DARWIN_JoystickIsAttached(SDL_Joystick * joystick)
{
return joystick->hwdata != NULL;
}
/* /*
* Like strerror but for force feedback errors. * Like strerror but for force feedback errors.
*/ */
@ -1007,7 +1001,6 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver =
DARWIN_JoystickGetDeviceGUID, DARWIN_JoystickGetDeviceGUID,
DARWIN_JoystickGetDeviceInstanceID, DARWIN_JoystickGetDeviceInstanceID,
DARWIN_JoystickOpen, DARWIN_JoystickOpen,
DARWIN_JoystickIsAttached,
DARWIN_JoystickRumble, DARWIN_JoystickRumble,
DARWIN_JoystickUpdate, DARWIN_JoystickUpdate,
DARWIN_JoystickClose, DARWIN_JoystickClose,

View File

@ -72,12 +72,6 @@ DUMMY_JoystickOpen(SDL_Joystick * joystick, int device_index)
return SDL_SetError("Logic error: No joysticks available"); return SDL_SetError("Logic error: No joysticks available");
} }
static SDL_bool
DUMMY_JoystickIsAttached(SDL_Joystick *joystick)
{
return SDL_FALSE;
}
static int static int
DUMMY_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) DUMMY_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{ {
@ -108,7 +102,6 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver =
DUMMY_JoystickGetDeviceGUID, DUMMY_JoystickGetDeviceGUID,
DUMMY_JoystickGetDeviceInstanceID, DUMMY_JoystickGetDeviceInstanceID,
DUMMY_JoystickOpen, DUMMY_JoystickOpen,
DUMMY_JoystickIsAttached,
DUMMY_JoystickRumble, DUMMY_JoystickRumble,
DUMMY_JoystickUpdate, DUMMY_JoystickUpdate,
DUMMY_JoystickClose, DUMMY_JoystickClose,

View File

@ -295,12 +295,6 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
return (0); return (0);
} }
/* Function to determine if this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return joystick->hwdata != NULL;
}
/* Function to update the state of a joystick - called as a device poll. /* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly, * This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events

View File

@ -152,12 +152,6 @@ extern "C"
return (0); return (0);
} }
/* Function to determine if this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return SDL_TRUE;
}
/* Function to update the state of a joystick - called as a device poll. /* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly, * This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events

View File

@ -458,21 +458,6 @@ HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
return 0; return 0;
} }
static SDL_bool
HIDAPI_JoystickIsAttached(SDL_Joystick *joystick)
{
SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
while (device) {
if (device->driver) {
if (joystick->instance_id == device->instance_id) {
return SDL_TRUE;
}
}
device = device->next;
}
return SDL_FALSE;
}
static int static int
HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{ {
@ -529,7 +514,6 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
HIDAPI_JoystickGetDeviceGUID, HIDAPI_JoystickGetDeviceGUID,
HIDAPI_JoystickGetDeviceInstanceID, HIDAPI_JoystickGetDeviceInstanceID,
HIDAPI_JoystickOpen, HIDAPI_JoystickOpen,
HIDAPI_JoystickIsAttached,
HIDAPI_JoystickRumble, HIDAPI_JoystickRumble,
HIDAPI_JoystickUpdate, HIDAPI_JoystickUpdate,
HIDAPI_JoystickClose, HIDAPI_JoystickClose,

View File

@ -425,12 +425,6 @@ IOS_JoystickOpen(SDL_Joystick * joystick, int device_index)
return 0; return 0;
} }
static SDL_bool
IOS_JoystickIsAttached(SDL_Joystick *joystick)
{
return joystick->hwdata != NULL;
}
static void static void
IOS_AccelerometerUpdate(SDL_Joystick * joystick) IOS_AccelerometerUpdate(SDL_Joystick * joystick)
{ {
@ -724,7 +718,6 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver =
IOS_JoystickGetDeviceGUID, IOS_JoystickGetDeviceGUID,
IOS_JoystickGetDeviceInstanceID, IOS_JoystickGetDeviceInstanceID,
IOS_JoystickOpen, IOS_JoystickOpen,
IOS_JoystickIsAttached,
IOS_JoystickRumble, IOS_JoystickRumble,
IOS_JoystickUpdate, IOS_JoystickUpdate,
IOS_JoystickClose, IOS_JoystickClose,

View File

@ -809,13 +809,6 @@ LINUX_JoystickOpen(SDL_Joystick * joystick, int device_index)
return (0); return (0);
} }
/* Function to determine if this joystick is attached to the system right now */
static SDL_bool
LINUX_JoystickIsAttached(SDL_Joystick *joystick)
{
return joystick->hwdata->item != NULL;
}
static int static int
LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{ {
@ -1112,7 +1105,6 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver =
LINUX_JoystickGetDeviceGUID, LINUX_JoystickGetDeviceGUID,
LINUX_JoystickGetDeviceInstanceID, LINUX_JoystickGetDeviceInstanceID,
LINUX_JoystickOpen, LINUX_JoystickOpen,
LINUX_JoystickIsAttached,
LINUX_JoystickRumble, LINUX_JoystickRumble,
LINUX_JoystickUpdate, LINUX_JoystickUpdate,
LINUX_JoystickClose, LINUX_JoystickClose,

View File

@ -177,12 +177,6 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
return 0; return 0;
} }
/* Function to determine if this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return SDL_TRUE;
}
/* Function to update the state of a joystick - called as a device poll. /* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly, * This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events

View File

@ -955,8 +955,6 @@ UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
/* Handle the events or punt */ /* Handle the events or punt */
if (FAILED(result)) { if (FAILED(result)) {
joystick->hwdata->send_remove_event = SDL_TRUE;
joystick->hwdata->removed = SDL_TRUE;
return; return;
} }
@ -1011,8 +1009,6 @@ UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
} }
if (result != DI_OK) { if (result != DI_OK) {
joystick->hwdata->send_remove_event = SDL_TRUE;
joystick->hwdata->removed = SDL_TRUE;
return; return;
} }

View File

@ -279,12 +279,6 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
return (0); return (0);
} }
/* Function to determine if this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return SDL_TRUE;
}
static Uint8 static Uint8
TranslatePOV(DWORD value) TranslatePOV(DWORD value)
{ {

View File

@ -463,13 +463,6 @@ WINDOWS_JoystickOpen(SDL_Joystick * joystick, int device_index)
} }
} }
/* return true if this joystick is plugged in right now */
static SDL_bool
WINDOWS_JoystickIsAttached(SDL_Joystick * joystick)
{
return joystick->hwdata && !joystick->hwdata->removed;
}
static int static int
WINDOWS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) WINDOWS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{ {
@ -483,7 +476,7 @@ WINDOWS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin
static void static void
WINDOWS_JoystickUpdate(SDL_Joystick * joystick) WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
{ {
if (!joystick->hwdata || joystick->hwdata->removed) { if (!joystick->hwdata) {
return; return;
} }
@ -492,10 +485,6 @@ WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
} else { } else {
SDL_DINPUT_JoystickUpdate(joystick); SDL_DINPUT_JoystickUpdate(joystick);
} }
if (joystick->hwdata->removed) {
joystick->force_recentering = SDL_TRUE;
}
} }
/* Function to close a joystick after use */ /* Function to close a joystick after use */
@ -558,7 +547,6 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
WINDOWS_JoystickGetDeviceGUID, WINDOWS_JoystickGetDeviceGUID,
WINDOWS_JoystickGetDeviceInstanceID, WINDOWS_JoystickGetDeviceInstanceID,
WINDOWS_JoystickOpen, WINDOWS_JoystickOpen,
WINDOWS_JoystickIsAttached,
WINDOWS_JoystickRumble, WINDOWS_JoystickRumble,
WINDOWS_JoystickUpdate, WINDOWS_JoystickUpdate,
WINDOWS_JoystickClose, WINDOWS_JoystickClose,

View File

@ -66,8 +66,6 @@ typedef struct input_t
struct joystick_hwdata struct joystick_hwdata
{ {
SDL_JoystickGUID guid; SDL_JoystickGUID guid;
SDL_bool removed;
SDL_bool send_remove_event;
Uint32 rumble_expiration; Uint32 rumble_expiration;
#if SDL_JOYSTICK_DINPUT #if SDL_JOYSTICK_DINPUT

View File

@ -270,6 +270,15 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
WINDOWS_AddJoystickDevice(pNewJoystick); WINDOWS_AddJoystickDevice(pNewJoystick);
} }
static void
DelXInputDevice(Uint8 userid)
{
if (s_arrXInputDevicePath[userid]) {
SDL_free(s_arrXInputDevicePath[userid]);
s_arrXInputDevicePath[userid] = NULL;
}
}
void void
SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext) SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
{ {
@ -285,6 +294,8 @@ SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
XINPUT_CAPABILITIES capabilities; XINPUT_CAPABILITIES capabilities;
if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) { if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
AddXInputDevice(userid, capabilities.SubType, pContext); AddXInputDevice(userid, capabilities.SubType, pContext);
} else {
DelXInputDevice(userid);
} }
} }
} }
@ -456,14 +467,6 @@ SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState); result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
if (result == ERROR_DEVICE_NOT_CONNECTED) { if (result == ERROR_DEVICE_NOT_CONNECTED) {
Uint8 userid = joystick->hwdata->userid;
joystick->hwdata->send_remove_event = SDL_TRUE;
joystick->hwdata->removed = SDL_TRUE;
if (s_arrXInputDevicePath[userid]) {
SDL_free(s_arrXInputDevicePath[userid]);
s_arrXInputDevicePath[userid] = NULL;
}
return; return;
} }