mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-31 05:56:24 +08:00
Eliminate contention between HIDAPI controller reads and writes
Rumble can often take a long time, and it is theoretically safe to simultaneously read and write hidapi devices on all platforms. Fixes https://github.com/libsdl-org/SDL/issues/9441
This commit is contained in:
@@ -77,14 +77,12 @@ static int SDLCALL SDL_HIDAPI_RumbleThread(void *data)
|
|||||||
SDL_UnlockMutex(SDL_HIDAPI_rumble_lock);
|
SDL_UnlockMutex(SDL_HIDAPI_rumble_lock);
|
||||||
|
|
||||||
if (request) {
|
if (request) {
|
||||||
SDL_LockMutex(request->device->dev_lock);
|
|
||||||
if (request->device->dev) {
|
if (request->device->dev) {
|
||||||
#ifdef DEBUG_RUMBLE
|
#ifdef DEBUG_RUMBLE
|
||||||
HIDAPI_DumpPacket("Rumble packet: size = %d", request->data, request->size);
|
HIDAPI_DumpPacket("Rumble packet: size = %d", request->data, request->size);
|
||||||
#endif
|
#endif
|
||||||
SDL_hid_write(request->device->dev, request->data, request->size);
|
SDL_hid_write(request->device->dev, request->data, request->size);
|
||||||
}
|
}
|
||||||
SDL_UnlockMutex(request->device->dev_lock);
|
|
||||||
if (request->callback) {
|
if (request->callback) {
|
||||||
request->callback(request->userdata);
|
request->callback(request->userdata);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2726,17 +2726,7 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
|||||||
Uint64 now = SDL_GetTicks();
|
Uint64 now = SDL_GetTicks();
|
||||||
|
|
||||||
if (now >= (ctx->m_ulLastIMUReset + IMU_RESET_DELAY_MS)) {
|
if (now >= (ctx->m_ulLastIMUReset + IMU_RESET_DELAY_MS)) {
|
||||||
SDL_HIDAPI_Device *device = ctx->device;
|
|
||||||
|
|
||||||
if (device->updating) {
|
|
||||||
SDL_UnlockMutex(device->dev_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetIMUEnabled(ctx, true);
|
SetIMUEnabled(ctx, true);
|
||||||
|
|
||||||
if (device->updating) {
|
|
||||||
SDL_LockMutex(device->dev_lock);
|
|
||||||
}
|
|
||||||
ctx->m_ulLastIMUReset = now;
|
ctx->m_ulLastIMUReset = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -439,19 +439,15 @@ static void HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
|
|||||||
device->driver->FreeDevice(device);
|
device->driver->FreeDevice(device);
|
||||||
device->driver = NULL;
|
device->driver = NULL;
|
||||||
|
|
||||||
SDL_LockMutex(device->dev_lock);
|
if (device->dev) {
|
||||||
{
|
SDL_hid_close(device->dev);
|
||||||
if (device->dev) {
|
device->dev = NULL;
|
||||||
SDL_hid_close(device->dev);
|
}
|
||||||
device->dev = NULL;
|
|
||||||
}
|
if (device->context) {
|
||||||
|
SDL_free(device->context);
|
||||||
if (device->context) {
|
device->context = NULL;
|
||||||
SDL_free(device->context);
|
|
||||||
device->context = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SDL_UnlockMutex(device->dev_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, bool *removed) SDL_NO_THREAD_SAFETY_ANALYSIS // We unlock the joystick lock to be able to open the HID device on Android
|
static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, bool *removed) SDL_NO_THREAD_SAFETY_ANALYSIS // We unlock the joystick lock to be able to open the HID device on Android
|
||||||
@@ -916,7 +912,6 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
|
|||||||
device->usage_page = info->usage_page;
|
device->usage_page = info->usage_page;
|
||||||
device->usage = info->usage;
|
device->usage = info->usage;
|
||||||
device->is_bluetooth = (info->bus_type == SDL_HID_API_BUS_BLUETOOTH);
|
device->is_bluetooth = (info->bus_type == SDL_HID_API_BUS_BLUETOOTH);
|
||||||
device->dev_lock = SDL_CreateMutex();
|
|
||||||
|
|
||||||
// Need the device name before getting the driver to know whether to ignore this device
|
// Need the device name before getting the driver to know whether to ignore this device
|
||||||
{
|
{
|
||||||
@@ -1013,7 +1008,6 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetObjectValid(device, SDL_OBJECT_TYPE_HIDAPI_JOYSTICK, false);
|
SDL_SetObjectValid(device, SDL_OBJECT_TYPE_HIDAPI_JOYSTICK, false);
|
||||||
SDL_DestroyMutex(device->dev_lock);
|
|
||||||
SDL_free(device->manufacturer_string);
|
SDL_free(device->manufacturer_string);
|
||||||
SDL_free(device->product_string);
|
SDL_free(device->product_string);
|
||||||
SDL_free(device->serial);
|
SDL_free(device->serial);
|
||||||
@@ -1434,12 +1428,7 @@ void HIDAPI_UpdateDevices(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (device->driver) {
|
if (device->driver) {
|
||||||
if (SDL_TryLockMutex(device->dev_lock)) {
|
device->driver->UpdateDevice(device);
|
||||||
device->updating = true;
|
|
||||||
device->driver->UpdateDevice(device);
|
|
||||||
device->updating = false;
|
|
||||||
SDL_UnlockMutex(device->dev_lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HIDAPI_FinishUpdatingDevices();
|
HIDAPI_FinishUpdatingDevices();
|
||||||
@@ -1552,11 +1541,7 @@ static bool HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|||||||
hwdata->device = device;
|
hwdata->device = device;
|
||||||
|
|
||||||
// Process any pending reports before opening the device
|
// Process any pending reports before opening the device
|
||||||
SDL_LockMutex(device->dev_lock);
|
|
||||||
device->updating = true;
|
|
||||||
device->driver->UpdateDevice(device);
|
device->driver->UpdateDevice(device);
|
||||||
device->updating = false;
|
|
||||||
SDL_UnlockMutex(device->dev_lock);
|
|
||||||
|
|
||||||
// UpdateDevice() may have called HIDAPI_JoystickDisconnected() if the device went away
|
// UpdateDevice() may have called HIDAPI_JoystickDisconnected() if the device went away
|
||||||
if (device->num_joysticks == 0) {
|
if (device->num_joysticks == 0) {
|
||||||
@@ -1682,22 +1667,13 @@ static void HIDAPI_JoystickClose(SDL_Joystick *joystick) SDL_NO_THREAD_SAFETY_AN
|
|||||||
|
|
||||||
if (joystick->hwdata) {
|
if (joystick->hwdata) {
|
||||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||||
int i;
|
|
||||||
|
|
||||||
// Wait up to 30 ms for pending rumble to complete
|
// Wait up to 30 ms for pending rumble to complete
|
||||||
if (device->updating) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
// Unlock the device so rumble can complete
|
|
||||||
SDL_UnlockMutex(device->dev_lock);
|
|
||||||
}
|
|
||||||
for (i = 0; i < 3; ++i) {
|
|
||||||
if (SDL_GetAtomicInt(&device->rumble_pending) > 0) {
|
if (SDL_GetAtomicInt(&device->rumble_pending) > 0) {
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (device->updating) {
|
|
||||||
// Relock the device
|
|
||||||
SDL_LockMutex(device->dev_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
device->driver->CloseJoystick(device, joystick);
|
device->driver->CloseJoystick(device, joystick);
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ typedef struct SDL_HIDAPI_Device
|
|||||||
|
|
||||||
struct SDL_HIDAPI_DeviceDriver *driver;
|
struct SDL_HIDAPI_DeviceDriver *driver;
|
||||||
void *context;
|
void *context;
|
||||||
SDL_Mutex *dev_lock;
|
|
||||||
SDL_hid_device *dev;
|
SDL_hid_device *dev;
|
||||||
SDL_AtomicInt rumble_pending;
|
SDL_AtomicInt rumble_pending;
|
||||||
int num_joysticks;
|
int num_joysticks;
|
||||||
@@ -109,9 +108,6 @@ typedef struct SDL_HIDAPI_Device
|
|||||||
// Used during scanning for device changes
|
// Used during scanning for device changes
|
||||||
bool seen;
|
bool seen;
|
||||||
|
|
||||||
// Used to flag that the device is being updated
|
|
||||||
bool updating;
|
|
||||||
|
|
||||||
// Used to flag devices that failed open
|
// Used to flag devices that failed open
|
||||||
// This can happen on Windows with Bluetooth devices that have turned off
|
// This can happen on Windows with Bluetooth devices that have turned off
|
||||||
bool broken;
|
bool broken;
|
||||||
|
|||||||
Reference in New Issue
Block a user