From 51902010c6152c358354d9d158b105573fcba4e9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Aug 2018 19:53:26 -0700 Subject: [PATCH] Remove the HIDAPI device if we get a read error from it This fixes detecting PS4 controller disconnect on Mac OS X, where there isn't any device removed notification --- src/joystick/hidapi/SDL_hidapi_ps4.c | 4 +++- src/joystick/hidapi/SDL_hidapi_switch.c | 6 ++++-- src/joystick/hidapi/SDL_hidapi_xbox360.c | 4 +++- src/joystick/hidapi/SDL_hidapi_xboxone.c | 4 +++- src/joystick/hidapi/SDL_hidapijoystick.c | 13 +++++++++++-- src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 +- 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 10345db2dd925..44e9b9913bff9 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -479,7 +479,7 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_ SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state)); } -static void +static SDL_bool HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context) { SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context; @@ -509,6 +509,8 @@ HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context) HIDAPI_DriverPS4_Rumble(joystick, dev, context, 0, 0, 0); } } + + return (size >= 0); } static void diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 5f8e0f8fadfb6..c37ba8fc59335 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -846,12 +846,13 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C ctx->m_lastFullState = *packet; } -static void +static SDL_bool HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *context) { SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context; + int size; - while (ReadInput(ctx) > 0) { + while ((size = ReadInput(ctx)) > 0) { switch (ctx->m_rgucReadBuffer[0]) { case k_eSwitchInputReportIDs_SimpleControllerState: HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]); @@ -870,6 +871,7 @@ HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *contex HIDAPI_DriverSwitch_Rumble(joystick, dev, context, 0, 0, 0); } } + return (size >= 0); } static void diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index e7e5980074ade..ab4f417b23786 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -310,7 +310,7 @@ HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); } -static void +static SDL_bool HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *context) { SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context; @@ -336,6 +336,8 @@ HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *conte HIDAPI_DriverXbox360_Rumble(joystick, dev, context, 0, 0, 0); } } + + return (size >= 0); } static void diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 959b281a7f535..16fab5a1fadb7 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -308,7 +308,7 @@ HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, S SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } -static void +static SDL_bool HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *context) { SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context; @@ -337,6 +337,8 @@ HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *conte HIDAPI_DriverXboxOne_Rumble(joystick, dev, context, 0, 0, 0); } } + + return (size >= 0); } static void diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 1e9e2bd9ec1ca..6d52224035754 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -146,7 +146,7 @@ typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR; #define DBT_DEVNODES_CHANGED 0x0007 #define DBT_CONFIGCHANGED 0x0018 #define DBT_DEVICETYPESPECIFIC 0x8005 /* type specific event */ -#define DBT_DEVINSTSTARTED 0x8008 /* device installed and started */ +#define DBT_DEVINSTSTARTED 0x8008 /* device installed and started */ #include DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); @@ -605,6 +605,7 @@ HIDAPI_AddDevice(struct hid_device_info *info) return; } +#define DEBUG_HIDAPI #ifdef DEBUG_HIDAPI SDL_Log("Adding HIDAPI device '%s' interface %d, usage page 0x%.4x, usage 0x%.4x\n", device->name, device->interface_number, device->usage_page, device->usage); #endif @@ -786,7 +787,15 @@ HIDAPI_JoystickUpdate(SDL_Joystick * joystick) { struct joystick_hwdata *hwdata = joystick->hwdata; SDL_HIDAPI_DeviceDriver *driver = hwdata->driver; - driver->Update(joystick, hwdata->dev, hwdata->context); + if (!driver->Update(joystick, hwdata->dev, hwdata->context)) { + SDL_HIDAPI_Device *device; + for (device = SDL_HIDAPI_devices; device; device = device->next) { + if (device->instance_id == joystick->instance_id) { + HIDAPI_DelDevice(device, SDL_TRUE); + break; + } + } + } } static void diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index fbfd3a33adf63..a21a69d1866fe 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -50,7 +50,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id); SDL_bool (*Init)(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context); int (*Rumble)(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); - void (*Update)(SDL_Joystick *joystick, hid_device *dev, void *context); + SDL_bool (*Update)(SDL_Joystick *joystick, hid_device *dev, void *context); void (*Quit)(SDL_Joystick *joystick, hid_device *dev, void *context); } SDL_HIDAPI_DeviceDriver;