diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 84232f90d..fc0554124 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -24,6 +24,7 @@ #include "SDL_hints.h" #include "SDL_events.h" +#include "SDL_timer.h" #include "SDL_joystick.h" #include "SDL_gamecontroller.h" #include "../SDL_sysjoystick.h" @@ -41,6 +42,7 @@ #define GYRO_RES_PER_DEGREE 1024.0f #define ACCEL_RES_PER_G 8192.0f +#define BLUETOOTH_DISCONNECT_TIMEOUT_MS 500 #define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8)) @@ -152,6 +154,7 @@ typedef struct { SDL_bool report_sensors; SDL_bool hardware_calibration; IMUCalibrationData calibration[6]; + Uint32 last_packet; int player_index; Uint8 rumble_left; Uint8 rumble_right; @@ -516,6 +519,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) SDL_OutOfMemory(); return SDL_FALSE; } + ctx->last_packet = SDL_GetTicks(); device->dev = hid_open_path(device->path, 0); if (!device->dev) { @@ -847,6 +851,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) SDL_Joystick *joystick = NULL; Uint8 data[USB_PACKET_LENGTH*2]; int size; + int packet_count = 0; if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); @@ -859,6 +864,9 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_PS5_PROTOCOL HIDAPI_DumpPacket("PS5 packet: size = %d", data, size); #endif + ++packet_count; + ctx->last_packet = SDL_GetTicks(); + switch (data[0]) { case k_EPS5ReportIdState: if (size == 10) { @@ -884,6 +892,14 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) } } + if (ctx->is_bluetooth && packet_count == 0) { + /* Check to see if it looks like the device disconnected */ + if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) { + /* Send an empty output report to tickle the Bluetooth stack */ + HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectNone); + } + } + if (size < 0) { /* Read error, device is disconnected */ HIDAPI_JoystickDisconnected(device, joystick->instance_id); diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index c8683fe50..a6a1c3d87 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -822,6 +822,11 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device) { SDL_HIDAPI_Device *curr, *last; + +#ifdef DEBUG_HIDAPI + SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->hint : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED"); +#endif + for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) { if (curr == device) { if (last) { @@ -1002,7 +1007,9 @@ HIDAPI_UpdateDevices(void) while (device) { if (device->driver) { if (SDL_TryLockMutex(device->dev_lock) == 0) { + device->updating = SDL_TRUE; device->driver->UpdateDevice(device); + device->updating = SDL_FALSE; SDL_UnlockMutex(device->dev_lock); } } @@ -1200,11 +1207,19 @@ HIDAPI_JoystickClose(SDL_Joystick * joystick) int i; /* Wait up to 30 ms for pending rumble to complete */ + if (device->updating) { + /* Unlock the device so rumble can complete */ + SDL_UnlockMutex(device->dev_lock); + } for (i = 0; i < 3; ++i) { - while (SDL_AtomicGet(&device->rumble_pending) > 0) { + if (SDL_AtomicGet(&device->rumble_pending) > 0) { SDL_Delay(10); } } + if (device->updating) { + /* Relock the device */ + SDL_LockMutex(device->dev_lock); + } device->driver->CloseJoystick(device, joystick); diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index d16a67360..5af5b08c0 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -76,6 +76,9 @@ typedef struct _SDL_HIDAPI_Device /* Used during scanning for device changes */ SDL_bool seen; + /* Used to flag that the device is being updated */ + SDL_bool updating; + struct _SDL_HIDAPI_Device *next; } SDL_HIDAPI_Device;