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
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->instance_id = instance_id;
joystick->attached = SDL_TRUE;
if (driver->Open(joystick, device_index) < 0) {
SDL_free(joystick);
@ -545,7 +546,7 @@ SDL_JoystickGetAttached(SDL_Joystick * joystick)
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)
{
SDL_Joystick *joystick;
#if !SDL_EVENTS_DISABLED
SDL_Event event;
@ -777,6 +780,15 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
UpdateEventsForDeviceRemoval();
#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
@ -984,10 +996,12 @@ SDL_JoystickUpdate(void)
SDL_UnlockJoysticks();
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
joystick->driver->Update(joystick);
if (joystick->attached) {
joystick->driver->Update(joystick);
if (joystick->delayed_guide_button) {
SDL_GameControllerHandleDelayedGuideButton(joystick);
if (joystick->delayed_guide_button) {
SDL_GameControllerHandleDelayedGuideButton(joystick);
}
}
if (joystick->force_recentering) {

View File

@ -59,6 +59,7 @@ struct _SDL_Joystick
int nbuttons; /* Number of buttons on the joystick */
Uint8 *buttons; /* Current button states */
SDL_bool attached;
SDL_bool is_game_controller;
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 */
@ -117,11 +118,6 @@ typedef struct _SDL_JoystickDriver
*/
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 */
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);
}
static SDL_bool
ANDROID_JoystickIsAttached(SDL_Joystick *joystick)
{
return joystick->hwdata != NULL;
}
static int
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_JoystickGetDeviceInstanceID,
ANDROID_JoystickOpen,
ANDROID_JoystickIsAttached,
ANDROID_JoystickRumble,
ANDROID_JoystickUpdate,
ANDROID_JoystickClose,

View File

@ -467,12 +467,6 @@ desc_failed:
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
SDL_SYS_JoystickUpdate(SDL_Joystick * joy)
{

View File

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

View File

@ -72,12 +72,6 @@ DUMMY_JoystickOpen(SDL_Joystick * joystick, int device_index)
return SDL_SetError("Logic error: No joysticks available");
}
static SDL_bool
DUMMY_JoystickIsAttached(SDL_Joystick *joystick)
{
return SDL_FALSE;
}
static int
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_JoystickGetDeviceInstanceID,
DUMMY_JoystickOpen,
DUMMY_JoystickIsAttached,
DUMMY_JoystickRumble,
DUMMY_JoystickUpdate,
DUMMY_JoystickClose,

View File

@ -295,12 +295,6 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
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.
* This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events

View File

@ -152,12 +152,6 @@ extern "C"
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.
* This function shouldn't update the joystick structure directly,
* 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;
}
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
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_JoystickGetDeviceInstanceID,
HIDAPI_JoystickOpen,
HIDAPI_JoystickIsAttached,
HIDAPI_JoystickRumble,
HIDAPI_JoystickUpdate,
HIDAPI_JoystickClose,

View File

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

View File

@ -809,13 +809,6 @@ LINUX_JoystickOpen(SDL_Joystick * joystick, int device_index)
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
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_JoystickGetDeviceInstanceID,
LINUX_JoystickOpen,
LINUX_JoystickIsAttached,
LINUX_JoystickRumble,
LINUX_JoystickUpdate,
LINUX_JoystickClose,

View File

@ -177,12 +177,6 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
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.
* This function shouldn't update the joystick structure directly,
* 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 */
if (FAILED(result)) {
joystick->hwdata->send_remove_event = SDL_TRUE;
joystick->hwdata->removed = SDL_TRUE;
return;
}
@ -1011,8 +1009,6 @@ UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
}
if (result != DI_OK) {
joystick->hwdata->send_remove_event = SDL_TRUE;
joystick->hwdata->removed = SDL_TRUE;
return;
}

View File

@ -279,12 +279,6 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
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
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
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
WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
{
if (!joystick->hwdata || joystick->hwdata->removed) {
if (!joystick->hwdata) {
return;
}
@ -492,10 +485,6 @@ WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
} else {
SDL_DINPUT_JoystickUpdate(joystick);
}
if (joystick->hwdata->removed) {
joystick->force_recentering = SDL_TRUE;
}
}
/* Function to close a joystick after use */
@ -558,7 +547,6 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
WINDOWS_JoystickGetDeviceGUID,
WINDOWS_JoystickGetDeviceInstanceID,
WINDOWS_JoystickOpen,
WINDOWS_JoystickIsAttached,
WINDOWS_JoystickRumble,
WINDOWS_JoystickUpdate,
WINDOWS_JoystickClose,

View File

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

View File

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