Commit 51902010c6152c358354d9d158b105573fcba4e9

Sam Lantinga 2018-08-15T19:53:26

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

diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index 10345db..44e9b99 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 5f8e0f8..c37ba8f 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 e7e5980..ab4f417 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 959b281..16fab5a 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 1e9e2bd..6d52224 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 <initguid.h>
 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 fbfd3a3..a21a69d 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;