mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-21 15:59:43 +00:00
Added support for clang thread-safety analysis
The annotations have been added to SDL_mutex.h and have been made public so applications can enable this for their own code. Clang assumes that locking and unlocking can't fail, but SDL has the concept of a NULL mutex, so the mutex functions have been changed not to report errors if a mutex hasn't been initialized. We do have mutexes that might be accessed when they are NULL, notably in the event system, so this is an important change. This commit cleans up a bunch of rare race conditions in the joystick and game controller code so now everything should be completely protected by the joystick lock. To test this, change the compiler to "clang -Wthread-safety -Werror=thread-safety -DSDL_THREAD_SAFETY_ANALYSIS"
This commit is contained in:
@@ -67,6 +67,8 @@ static SDL_bool HIDAPI_DriverCombined_OpenJoystick(SDL_HIDAPI_Device *device, SD
|
||||
char *serial = NULL, *new_serial;
|
||||
size_t serial_length = 0, new_length;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
for (i = 0; i < device->num_children; ++i) {
|
||||
SDL_HIDAPI_Device *child = device->children[i];
|
||||
if (!child->driver->OpenJoystick(child, joystick)) {
|
||||
|
||||
@@ -408,6 +408,9 @@ static SDL_bool HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_Device *device, SD
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
|
||||
Uint8 i;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
|
||||
if (joystick->instance_id == ctx->joysticks[i]) {
|
||||
joystick->nbuttons = 12;
|
||||
@@ -424,6 +427,8 @@ static int HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_J
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
|
||||
Uint8 i, val;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (ctx->pc_mode) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
@@ -469,6 +474,8 @@ static Uint32 HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *d
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
|
||||
Uint32 result = 0;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (!ctx->pc_mode) {
|
||||
Uint8 i;
|
||||
|
||||
|
||||
@@ -100,6 +100,8 @@ static SDL_bool HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Jo
|
||||
{
|
||||
SDL_DriverLuna_Context *ctx = (SDL_DriverLuna_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
SDL_zeroa(ctx->last_state);
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
|
||||
@@ -234,6 +234,8 @@ static SDL_bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
{
|
||||
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
ctx->effects_updated = SDL_FALSE;
|
||||
ctx->rumble_left = 0;
|
||||
@@ -630,6 +632,8 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_OpenJoystick(SDL_HIDAPI_Device *devic
|
||||
{
|
||||
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
SDL_zeroa(ctx->last_state);
|
||||
|
||||
|
||||
@@ -668,6 +668,8 @@ static SDL_bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
ctx->last_packet = SDL_GetTicks();
|
||||
ctx->report_sensors = SDL_FALSE;
|
||||
|
||||
@@ -822,6 +822,8 @@ static SDL_bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
ctx->last_packet = SDL_GetTicks();
|
||||
ctx->report_sensors = SDL_FALSE;
|
||||
@@ -961,7 +963,7 @@ static int HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Jo
|
||||
SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
|
||||
}
|
||||
|
||||
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||
if (SDL_HIDAPI_LockRumble() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,13 +46,13 @@ typedef struct SDL_HIDAPI_RumbleContext
|
||||
SDL_atomic_t initialized;
|
||||
SDL_atomic_t running;
|
||||
SDL_Thread *thread;
|
||||
SDL_mutex *lock;
|
||||
SDL_sem *request_sem;
|
||||
SDL_HIDAPI_RumbleRequest *requests_head;
|
||||
SDL_HIDAPI_RumbleRequest *requests_tail;
|
||||
} SDL_HIDAPI_RumbleContext;
|
||||
|
||||
static SDL_HIDAPI_RumbleContext rumble_context;
|
||||
SDL_mutex *SDL_HIDAPI_rumble_lock;
|
||||
static SDL_HIDAPI_RumbleContext rumble_context SDL_GUARDED_BY(SDL_HIDAPI_rumble_lock);
|
||||
|
||||
static int SDLCALL SDL_HIDAPI_RumbleThread(void *data)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ static int SDLCALL SDL_HIDAPI_RumbleThread(void *data)
|
||||
|
||||
SDL_SemWait(ctx->request_sem);
|
||||
|
||||
SDL_LockMutex(ctx->lock);
|
||||
SDL_LockMutex(SDL_HIDAPI_rumble_lock);
|
||||
request = ctx->requests_tail;
|
||||
if (request) {
|
||||
if (request == ctx->requests_head) {
|
||||
@@ -73,7 +73,7 @@ static int SDLCALL SDL_HIDAPI_RumbleThread(void *data)
|
||||
}
|
||||
ctx->requests_tail = request->prev;
|
||||
}
|
||||
SDL_UnlockMutex(ctx->lock);
|
||||
SDL_UnlockMutex(SDL_HIDAPI_rumble_lock);
|
||||
|
||||
if (request) {
|
||||
SDL_LockMutex(request->device->dev_lock);
|
||||
@@ -111,7 +111,7 @@ static void SDL_HIDAPI_StopRumbleThread(SDL_HIDAPI_RumbleContext *ctx)
|
||||
ctx->thread = NULL;
|
||||
}
|
||||
|
||||
SDL_LockMutex(ctx->lock);
|
||||
SDL_LockMutex(SDL_HIDAPI_rumble_lock);
|
||||
while (ctx->requests_tail) {
|
||||
request = ctx->requests_tail;
|
||||
if (request == ctx->requests_head) {
|
||||
@@ -125,16 +125,16 @@ static void SDL_HIDAPI_StopRumbleThread(SDL_HIDAPI_RumbleContext *ctx)
|
||||
(void)SDL_AtomicDecRef(&request->device->rumble_pending);
|
||||
SDL_free(request);
|
||||
}
|
||||
SDL_UnlockMutex(ctx->lock);
|
||||
SDL_UnlockMutex(SDL_HIDAPI_rumble_lock);
|
||||
|
||||
if (ctx->request_sem) {
|
||||
SDL_DestroySemaphore(ctx->request_sem);
|
||||
ctx->request_sem = NULL;
|
||||
}
|
||||
|
||||
if (ctx->lock) {
|
||||
SDL_DestroyMutex(ctx->lock);
|
||||
ctx->lock = NULL;
|
||||
if (SDL_HIDAPI_rumble_lock) {
|
||||
SDL_DestroyMutex(SDL_HIDAPI_rumble_lock);
|
||||
SDL_HIDAPI_rumble_lock = NULL;
|
||||
}
|
||||
|
||||
SDL_AtomicSet(&ctx->initialized, SDL_FALSE);
|
||||
@@ -142,8 +142,8 @@ static void SDL_HIDAPI_StopRumbleThread(SDL_HIDAPI_RumbleContext *ctx)
|
||||
|
||||
static int SDL_HIDAPI_StartRumbleThread(SDL_HIDAPI_RumbleContext *ctx)
|
||||
{
|
||||
ctx->lock = SDL_CreateMutex();
|
||||
if (!ctx->lock) {
|
||||
SDL_HIDAPI_rumble_lock = SDL_CreateMutex();
|
||||
if (!SDL_HIDAPI_rumble_lock) {
|
||||
SDL_HIDAPI_StopRumbleThread(ctx);
|
||||
return -1;
|
||||
}
|
||||
@@ -173,7 +173,8 @@ int SDL_HIDAPI_LockRumble(void)
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_LockMutex(ctx->lock);
|
||||
SDL_LockMutex(SDL_HIDAPI_rumble_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size)
|
||||
@@ -241,9 +242,7 @@ int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const
|
||||
|
||||
void SDL_HIDAPI_UnlockRumble(void)
|
||||
{
|
||||
SDL_HIDAPI_RumbleContext *ctx = &rumble_context;
|
||||
|
||||
SDL_UnlockMutex(ctx->lock);
|
||||
SDL_UnlockMutex(SDL_HIDAPI_rumble_lock);
|
||||
}
|
||||
|
||||
int SDL_HIDAPI_SendRumble(SDL_HIDAPI_Device *device, const Uint8 *data, int size)
|
||||
@@ -256,7 +255,7 @@ int SDL_HIDAPI_SendRumble(SDL_HIDAPI_Device *device, const Uint8 *data, int size
|
||||
return SDL_SetError("Tried to send rumble with invalid size");
|
||||
}
|
||||
|
||||
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||
if (SDL_HIDAPI_LockRumble() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,12 +25,15 @@
|
||||
/* Handle rumble on a separate thread so it doesn't block the application */
|
||||
|
||||
/* Advanced API */
|
||||
int SDL_HIDAPI_LockRumble(void);
|
||||
#ifdef SDL_THREAD_SAFETY_ANALYSIS
|
||||
extern SDL_mutex *SDL_HIDAPI_rumble_lock;
|
||||
#endif
|
||||
int SDL_HIDAPI_LockRumble(void) SDL_TRY_ACQUIRE(0, SDL_HIDAPI_rumble_lock);
|
||||
SDL_bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size);
|
||||
int SDL_HIDAPI_SendRumbleAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size);
|
||||
int SDL_HIDAPI_SendRumbleAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size) SDL_RELEASE(SDL_HIDAPI_rumble_lock);
|
||||
typedef void (*SDL_HIDAPI_RumbleSentCallback)(void *userdata);
|
||||
int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size, SDL_HIDAPI_RumbleSentCallback callback, void *userdata);
|
||||
void SDL_HIDAPI_UnlockRumble(void);
|
||||
int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size, SDL_HIDAPI_RumbleSentCallback callback, void *userdata) SDL_RELEASE(SDL_HIDAPI_rumble_lock);
|
||||
void SDL_HIDAPI_UnlockRumble(void) SDL_RELEASE(SDL_HIDAPI_rumble_lock);
|
||||
|
||||
/* Simple API, will replace any pending rumble with the new data */
|
||||
int SDL_HIDAPI_SendRumble(SDL_HIDAPI_Device *device, const Uint8 *data, int size);
|
||||
|
||||
@@ -148,7 +148,7 @@ static int HIDAPI_DriverShield_SendCommand(SDL_HIDAPI_Device *device, Uint8 cmd,
|
||||
return SDL_SetError("Command data exceeds HID report size");
|
||||
}
|
||||
|
||||
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||
if (SDL_HIDAPI_LockRumble() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -175,6 +175,8 @@ static SDL_bool HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
|
||||
{
|
||||
SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->rumble_report_pending = SDL_FALSE;
|
||||
ctx->rumble_update_pending = SDL_FALSE;
|
||||
ctx->left_motor_amplitude = 0;
|
||||
|
||||
@@ -96,6 +96,8 @@ static SDL_bool HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
|
||||
{
|
||||
SDL_DriverStadia_Context *ctx = (SDL_DriverStadia_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
SDL_zeroa(ctx->last_state);
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
|
||||
@@ -1012,6 +1012,8 @@ static SDL_bool HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_J
|
||||
SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
|
||||
float update_rate_in_hz = 0.0f;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->report_sensors = SDL_FALSE;
|
||||
SDL_zero(ctx->m_assembler);
|
||||
SDL_zero(ctx->m_state);
|
||||
|
||||
@@ -323,7 +323,7 @@ static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int siz
|
||||
return SDL_hid_write(ctx->device->dev, data, size);
|
||||
#else
|
||||
/* Use the rumble thread for general asynchronous writes */
|
||||
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||
if (SDL_HIDAPI_LockRumble() != 0) {
|
||||
return -1;
|
||||
}
|
||||
return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size);
|
||||
@@ -1253,6 +1253,8 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
|
||||
Uint8 input_mode;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
|
||||
ctx->m_bSyncWrite = SDL_TRUE;
|
||||
@@ -1891,7 +1893,7 @@ static void HandleMiniControllerStateR(SDL_Joystick *joystick, SDL_DriverSwitch_
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
||||
}
|
||||
|
||||
static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
||||
static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet) SDL_NO_THREAD_SAFETY_ANALYSIS /* We unlock and lock the device lock to be able to change IMU state */
|
||||
{
|
||||
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
|
||||
if (ctx->device->parent || ctx->m_bVerticalMode) {
|
||||
|
||||
@@ -221,7 +221,7 @@ static SDL_bool WriteOutput(SDL_DriverWii_Context *ctx, const Uint8 *data, int s
|
||||
return SDL_hid_write(ctx->device->dev, data, size) >= 0;
|
||||
} else {
|
||||
/* Use the rumble thread for general asynchronous writes */
|
||||
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||
if (SDL_HIDAPI_LockRumble() != 0) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size) >= 0;
|
||||
@@ -770,6 +770,8 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
{
|
||||
SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
|
||||
InitializeExtension(ctx);
|
||||
|
||||
@@ -176,6 +176,8 @@ static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL
|
||||
{
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->joystick = joystick;
|
||||
SDL_zeroa(ctx->last_state);
|
||||
|
||||
|
||||
@@ -175,6 +175,8 @@ static SDL_bool HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SD
|
||||
{
|
||||
SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
SDL_zeroa(ctx->last_state);
|
||||
|
||||
/* Initialize player index (needed for setting LEDs) */
|
||||
|
||||
@@ -234,7 +234,7 @@ static void SendAckIfNeeded(SDL_HIDAPI_Device *device, const Uint8 *data, int si
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
HIDAPI_DumpPacket("Xbox One sending ACK packet: size = %d", ack_packet, sizeof(ack_packet));
|
||||
#endif
|
||||
if (SDL_HIDAPI_LockRumble() < 0 ||
|
||||
if (SDL_HIDAPI_LockRumble() != 0 ||
|
||||
SDL_HIDAPI_SendRumbleAndUnlock(device, ack_packet, sizeof(ack_packet)) != sizeof(ack_packet)) {
|
||||
SDL_SetError("Couldn't send ack packet");
|
||||
}
|
||||
@@ -254,7 +254,7 @@ static SDL_bool SendSerialRequest(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_C
|
||||
* It will cancel the announce packet if sent before that, and will be
|
||||
* ignored if sent during the negotiation.
|
||||
*/
|
||||
if (SDL_HIDAPI_LockRumble() < 0 ||
|
||||
if (SDL_HIDAPI_LockRumble() != 0 ||
|
||||
SDL_HIDAPI_SendRumbleAndUnlock(device, serial_packet, sizeof(serial_packet)) != sizeof(serial_packet)) {
|
||||
SDL_SetError("Couldn't send serial packet");
|
||||
return SDL_FALSE;
|
||||
@@ -312,7 +312,7 @@ static SDL_bool SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_
|
||||
#endif
|
||||
ctx->send_time = SDL_GetTicks();
|
||||
|
||||
if (SDL_HIDAPI_LockRumble() < 0 ||
|
||||
if (SDL_HIDAPI_LockRumble() != 0 ||
|
||||
SDL_HIDAPI_SendRumbleAndUnlock(device, init_packet, packet->size) != packet->size) {
|
||||
SDL_SetError("Couldn't write Xbox One initialization packet");
|
||||
return SDL_FALSE;
|
||||
@@ -415,6 +415,8 @@ static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
ctx->low_frequency_rumble = 0;
|
||||
ctx->high_frequency_rumble = 0;
|
||||
ctx->left_trigger_rumble = 0;
|
||||
@@ -478,7 +480,7 @@ static int HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device)
|
||||
/* We're no longer pending, even if we fail to send the rumble below */
|
||||
ctx->rumble_pending = SDL_FALSE;
|
||||
|
||||
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||
if (SDL_HIDAPI_LockRumble() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ static int SDL_HIDAPI_numdrivers = 0;
|
||||
static SDL_SpinLock SDL_HIDAPI_spinlock;
|
||||
static SDL_bool SDL_HIDAPI_hints_changed = SDL_FALSE;
|
||||
static Uint32 SDL_HIDAPI_change_count = 0;
|
||||
static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
|
||||
static SDL_HIDAPI_Device *SDL_HIDAPI_devices SDL_GUARDED_BY(SDL_joystick_lock);
|
||||
static int SDL_HIDAPI_numjoysticks = 0;
|
||||
static SDL_bool SDL_HIDAPI_combine_joycons = SDL_TRUE;
|
||||
static SDL_bool initialized = SDL_FALSE;
|
||||
@@ -264,6 +264,8 @@ static SDL_HIDAPI_Device *HIDAPI_GetDeviceByIndex(int device_index, SDL_Joystick
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||
if (device->parent) {
|
||||
continue;
|
||||
@@ -285,6 +287,8 @@ static SDL_HIDAPI_Device *HIDAPI_GetJoystickByInfo(const char *path, Uint16 vend
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||
if (device->vendor_id == vendor_id && device->product_id == product_id &&
|
||||
SDL_strcmp(device->path, path) == 0) {
|
||||
@@ -323,7 +327,7 @@ static void HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
|
||||
SDL_UnlockMutex(device->dev_lock);
|
||||
}
|
||||
|
||||
static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *removed)
|
||||
static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *removed) SDL_NO_THREAD_SAFETY_ANALYSIS /* We unlock the joystick lock to be able to open the HID device on Android */
|
||||
{
|
||||
*removed = SDL_FALSE;
|
||||
|
||||
@@ -426,6 +430,8 @@ static void SDL_HIDAPI_UpdateDrivers(void)
|
||||
SDL_HIDAPI_Device *device;
|
||||
SDL_bool removed;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
SDL_HIDAPI_numdrivers = 0;
|
||||
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
|
||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||
@@ -571,6 +577,8 @@ HIDAPI_HasConnectedUSBDevice(const char *serial)
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (serial == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
@@ -595,6 +603,8 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial)
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (serial == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -622,6 +632,8 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
|
||||
int i, j;
|
||||
SDL_JoystickID joystickID;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
for (i = 0; i < device->num_children; ++i) {
|
||||
SDL_HIDAPI_Device *child = device->children[i];
|
||||
for (j = child->num_joysticks; j--;) {
|
||||
@@ -717,6 +729,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
|
||||
SDL_HIDAPI_Device *curr, *last = NULL;
|
||||
SDL_bool removed;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) {
|
||||
}
|
||||
|
||||
@@ -810,6 +824,8 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
|
||||
SDL_HIDAPI_Device *curr, *last;
|
||||
int i;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
#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->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
|
||||
#endif
|
||||
@@ -849,6 +865,8 @@ static SDL_bool HIDAPI_CreateCombinedJoyCons()
|
||||
SDL_HIDAPI_Device *device, *combined;
|
||||
SDL_HIDAPI_Device *joycons[2] = { NULL, NULL };
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (!SDL_HIDAPI_combine_joycons) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
@@ -1160,6 +1178,8 @@ void HIDAPI_UpdateDevices(void)
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
/* Update the devices, which may change connected joysticks and send events */
|
||||
|
||||
/* Prepare the existing device list */
|
||||
@@ -1262,6 +1282,8 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index, &joystickID);
|
||||
struct joystick_hwdata *hwdata;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (device == NULL || !device->driver) {
|
||||
/* This should never happen - validated before being called */
|
||||
return SDL_SetError("Couldn't find HIDAPI device at index %d\n", device_index);
|
||||
@@ -1299,6 +1321,8 @@ static int HIDAPI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_ru
|
||||
{
|
||||
int result;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
|
||||
@@ -1314,6 +1338,8 @@ static int HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rum
|
||||
{
|
||||
int result;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
|
||||
@@ -1329,6 +1355,8 @@ static Uint32 HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick)
|
||||
{
|
||||
Uint32 result = 0;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
|
||||
@@ -1342,6 +1370,8 @@ static int HIDAPI_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green,
|
||||
{
|
||||
int result;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
|
||||
@@ -1357,6 +1387,8 @@ static int HIDAPI_JoystickSendEffect(SDL_Joystick *joystick, const void *data, i
|
||||
{
|
||||
int result;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
|
||||
@@ -1372,6 +1404,8 @@ static int HIDAPI_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool ena
|
||||
{
|
||||
int result;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
|
||||
@@ -1388,8 +1422,10 @@ static void HIDAPI_JoystickUpdate(SDL_Joystick *joystick)
|
||||
/* This is handled in SDL_HIDAPI_UpdateDevices() */
|
||||
}
|
||||
|
||||
static void HIDAPI_JoystickClose(SDL_Joystick *joystick)
|
||||
static void HIDAPI_JoystickClose(SDL_Joystick *joystick) SDL_NO_THREAD_SAFETY_ANALYSIS /* We unlock the device lock so rumble can complete */
|
||||
{
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
if (joystick->hwdata) {
|
||||
SDL_HIDAPI_Device *device = joystick->hwdata->device;
|
||||
int i;
|
||||
@@ -1420,6 +1456,8 @@ static void HIDAPI_JoystickQuit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
shutting_down = SDL_TRUE;
|
||||
|
||||
SDL_HIDAPI_QuitRumble();
|
||||
|
||||
Reference in New Issue
Block a user