diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index 72c6604df..9dcadc7b4 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -44,6 +44,7 @@ #include "SDL_stdinc.h" #include "SDL_error.h" #include "SDL_guid.h" +#include "SDL_mutex.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ @@ -66,6 +67,9 @@ extern "C" { /** * The joystick structure used to identify an SDL joystick */ +#ifdef SDL_THREAD_SAFETY_ANALYSIS +extern SDL_mutex *SDL_joystick_lock; +#endif struct _SDL_Joystick; typedef struct _SDL_Joystick SDL_Joystick; @@ -131,7 +135,7 @@ typedef enum * * \since This function is available since SDL 2.0.7. */ -extern DECLSPEC void SDLCALL SDL_LockJoysticks(void); +extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock); /** @@ -146,7 +150,7 @@ extern DECLSPEC void SDLCALL SDL_LockJoysticks(void); * * \since This function is available since SDL 2.0.7. */ -extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void); +extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock); /** * Count the number of joysticks attached to the system. diff --git a/include/SDL_mutex.h b/include/SDL_mutex.h index d4d55a4bf..1e2f2f44d 100644 --- a/include/SDL_mutex.h +++ b/include/SDL_mutex.h @@ -31,6 +31,80 @@ #include "SDL_stdinc.h" #include "SDL_error.h" +/******************************************************************************/ +/* Enable thread safety attributes only with clang. + * The attributes can be safely erased when compiling with other compilers. + */ +#if defined(SDL_THREAD_SAFETY_ANALYSIS) && \ + defined(__clang__) && (!defined(SWIG)) +#define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define SDL_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SDL_SCOPED_CAPABILITY \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define SDL_GUARDED_BY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define SDL_PT_GUARDED_BY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define SDL_ACQUIRED_BEFORE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define SDL_ACQUIRED_AFTER(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define SDL_REQUIRES(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SDL_REQUIRES_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define SDL_ACQUIRE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define SDL_ACQUIRE_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define SDL_RELEASE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define SDL_RELEASE_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define SDL_RELEASE_GENERIC(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define SDL_TRY_ACQUIRE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define SDL_TRY_ACQUIRE_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define SDL_EXCLUDES(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define SDL_ASSERT_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define SDL_ASSERT_SHARED_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define SDL_RETURN_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define SDL_NO_THREAD_SAFETY_ANALYSIS \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +/******************************************************************************/ + + #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -96,7 +170,7 @@ extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void); * * \since This function is available since SDL 2.0.0. */ -extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex); +extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex) SDL_ACQUIRE(mutex); #define SDL_mutexP(m) SDL_LockMutex(m) /** @@ -119,7 +193,7 @@ extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex); * \sa SDL_LockMutex * \sa SDL_UnlockMutex */ -extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex); +extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex) SDL_TRY_ACQUIRE(0, mutex); /** * Unlock the mutex. @@ -138,7 +212,7 @@ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex); * * \since This function is available since SDL 2.0.0. */ -extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex); +extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex) SDL_RELEASE(mutex); #define SDL_mutexV(m) SDL_UnlockMutex(m) /** diff --git a/src/SDL_assert.c b/src/SDL_assert.c index a689a550b..7ff864a01 100644 --- a/src/SDL_assert.c +++ b/src/SDL_assert.c @@ -345,10 +345,8 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file, } SDL_AtomicUnlock(&spinlock); - if (SDL_LockMutex(assertion_mutex) < 0) { - return SDL_ASSERTION_IGNORE; /* oh well, I guess. */ - } -#endif + SDL_LockMutex(assertion_mutex); +#endif /* !SDL_THREADS_DISABLED */ /* doing this because Visual C is upset over assigning in the macro. */ if (data->trigger_count == 0) { diff --git a/src/SDL_log.c b/src/SDL_log.c index e9199cc2e..80d36b5a4 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -336,15 +336,9 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va } } - if (log_function_mutex) { - SDL_LockMutex(log_function_mutex); - } - + SDL_LockMutex(log_function_mutex); SDL_log_function(SDL_log_userdata, category, priority, message); - - if (log_function_mutex) { - SDL_UnlockMutex(log_function_mutex); - } + SDL_UnlockMutex(log_function_mutex); /* Free only if dynamically allocated */ if (message != stack_buf) { diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 959ce0d7a..251391a63 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -301,14 +301,14 @@ static SDL_INLINE SDL_bool is_in_audio_device_thread(SDL_AudioDevice *device) return SDL_FALSE; } -static void SDL_AudioLockDevice_Default(SDL_AudioDevice *device) +static void SDL_AudioLockDevice_Default(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang assumes recursive locks */ { if (!is_in_audio_device_thread(device)) { SDL_LockMutex(device->mixer_lock); } } -static void SDL_AudioUnlockDevice_Default(SDL_AudioDevice *device) +static void SDL_AudioUnlockDevice_Default(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang assumes recursive locks */ { if (!is_in_audio_device_thread(device)) { SDL_UnlockMutex(device->mixer_lock); diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 7543f2a6b..adb8bec59 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -59,7 +59,7 @@ #define SDL_DYNAMIC_API 0 #elif defined(__riscos__) && __riscos__ /* probably not useful on RISC OS, since dlopen() can't be used when using static linking. */ #define SDL_DYNAMIC_API 0 -#elif defined(__clang_analyzer__) +#elif defined(__clang_analyzer__) || defined(SDL_THREAD_SAFETY_ANALYSIS) #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ #elif defined(__VITA__) #define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 441038ef2..39a7fe027 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -546,9 +546,7 @@ void SDL_StopEventLoop(void) SDL_EventEntry *entry; SDL_SysWMEntry *wmmsg; - if (SDL_EventQ.lock) { - SDL_LockMutex(SDL_EventQ.lock); - } + SDL_LockMutex(SDL_EventQ.lock); SDL_EventQ.active = SDL_FALSE; @@ -605,8 +603,9 @@ void SDL_StopEventLoop(void) } SDL_zero(SDL_EventOK); + SDL_UnlockMutex(SDL_EventQ.lock); + if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); SDL_DestroyMutex(SDL_EventQ.lock); SDL_EventQ.lock = NULL; } @@ -650,9 +649,7 @@ int SDL_StartEventLoop(void) #endif SDL_EventQ.active = SDL_TRUE; - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } + SDL_UnlockMutex(SDL_EventQ.lock); return 0; } @@ -746,17 +743,18 @@ static int SDL_SendWakeupEvent() if (_this == NULL || !_this->SendWakeupEvent) { return 0; } - if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) { + + SDL_LockMutex(_this->wakeup_lock); + { if (_this->wakeup_window) { _this->SendWakeupEvent(_this, _this->wakeup_window); /* No more wakeup events needed until we enter a new wait */ _this->wakeup_window = NULL; } - if (_this->wakeup_lock) { - SDL_UnlockMutex(_this->wakeup_lock); - } } + SDL_UnlockMutex(_this->wakeup_lock); + return 0; } @@ -768,16 +766,16 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact /* Lock the event queue */ used = 0; - if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { + + SDL_LockMutex(SDL_EventQ.lock); + { /* Don't look after we've quit */ if (!SDL_EventQ.active) { - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } /* We get a few spurious events at shutdown, so don't warn then */ if (action == SDL_GETEVENT) { SDL_SetError("The event system has been shut down"); } + SDL_UnlockMutex(SDL_EventQ.lock); return -1; } if (action == SDL_ADDEVENT) { @@ -846,12 +844,8 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact } } } - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } - } else { - return SDL_SetError("Couldn't lock event queue"); } + SDL_UnlockMutex(SDL_EventQ.lock); if (used > 0 && action == SDL_ADDEVENT) { SDL_SendWakeupEvent(); @@ -865,14 +859,12 @@ int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, SDL_FALSE); } -SDL_bool -SDL_HasEvent(Uint32 type) +SDL_bool SDL_HasEvent(Uint32 type) { return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0; } -SDL_bool -SDL_HasEvents(Uint32 minType, Uint32 maxType) +SDL_bool SDL_HasEvents(Uint32 minType, Uint32 maxType) { return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0; } @@ -899,12 +891,11 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) #endif /* Lock the event queue */ - if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { + SDL_LockMutex(SDL_EventQ.lock); + { /* Don't look after we've quit */ if (!SDL_EventQ.active) { - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } + SDL_UnlockMutex(SDL_EventQ.lock); return; } for (entry = SDL_EventQ.head; entry; entry = next) { @@ -914,10 +905,8 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) SDL_CutEvent(entry); } } - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } } + SDL_UnlockMutex(SDL_EventQ.lock); } /* Run the system dependent event loops */ @@ -1002,58 +991,59 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve /* We only want a single sentinel in the queue. We could get more than one if event is NULL, * since the SDL_PeepEvents() call below won't remove it in that case. */ + int status; SDL_bool add_sentinel = (SDL_AtomicGet(&SDL_sentinel_pending) == 0) ? SDL_TRUE : SDL_FALSE; SDL_PumpEventsInternal(add_sentinel); - if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) { - int status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); + SDL_LockMutex(_this->wakeup_lock); + { + status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); /* If status == 0 we are going to block so wakeup will be needed. */ if (status == 0) { _this->wakeup_window = wakeup_window; } else { _this->wakeup_window = NULL; } - if (_this->wakeup_lock) { - SDL_UnlockMutex(_this->wakeup_lock); - } - if (status < 0) { - /* Got an error: return */ - break; - } - if (status > 0) { - /* There is an event, we can return. */ - return 1; - } - /* No events found in the queue, call WaitEventTimeout to wait for an event. */ - if (timeout > 0) { - Uint32 elapsed = SDL_GetTicks() - start; - if (elapsed >= (Uint32)timeout) { - /* Set wakeup_window to NULL without holding the lock. */ - _this->wakeup_window = NULL; - return 0; - } - loop_timeout = (int)((Uint32)timeout - elapsed); - } - if (need_periodic_poll) { - if (loop_timeout >= 0) { - loop_timeout = SDL_min(loop_timeout, PERIODIC_POLL_INTERVAL_MS); - } else { - loop_timeout = PERIODIC_POLL_INTERVAL_MS; - } - } - status = _this->WaitEventTimeout(_this, loop_timeout); - /* Set wakeup_window to NULL without holding the lock. */ - _this->wakeup_window = NULL; - if (status == 0 && need_periodic_poll && loop_timeout == PERIODIC_POLL_INTERVAL_MS) { - /* We may have woken up to poll. Try again */ - continue; - } else if (status <= 0) { - /* There is either an error or the timeout is elapsed: return */ - return status; - } - /* An event was found and pumped into the SDL events queue. Continue the loop - to let SDL_PeepEvents pick it up .*/ } + SDL_UnlockMutex(_this->wakeup_lock); + + if (status < 0) { + /* Got an error: return */ + break; + } + if (status > 0) { + /* There is an event, we can return. */ + return 1; + } + /* No events found in the queue, call WaitEventTimeout to wait for an event. */ + if (timeout > 0) { + Uint32 elapsed = SDL_GetTicks() - start; + if (elapsed >= (Uint32)timeout) { + /* Set wakeup_window to NULL without holding the lock. */ + _this->wakeup_window = NULL; + return 0; + } + loop_timeout = (int)((Uint32)timeout - elapsed); + } + if (need_periodic_poll) { + if (loop_timeout >= 0) { + loop_timeout = SDL_min(loop_timeout, PERIODIC_POLL_INTERVAL_MS); + } else { + loop_timeout = PERIODIC_POLL_INTERVAL_MS; + } + } + status = _this->WaitEventTimeout(_this, loop_timeout); + /* Set wakeup_window to NULL without holding the lock. */ + _this->wakeup_window = NULL; + if (status == 0 && need_periodic_poll && loop_timeout == PERIODIC_POLL_INTERVAL_MS) { + /* We may have woken up to poll. Try again */ + continue; + } else if (status <= 0) { + /* There is either an error or the timeout is elapsed: return */ + return status; + } + /* An event was found and pumped into the SDL events queue. Continue the loop + to let SDL_PeepEvents pick it up .*/ } return 0; } @@ -1187,11 +1177,10 @@ int SDL_PushEvent(SDL_Event *event) event->common.timestamp = SDL_GetTicks(); if (SDL_EventOK.callback || SDL_event_watchers_count > 0) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) { - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } + SDL_UnlockMutex(SDL_event_watchers_lock); return 0; } @@ -1219,11 +1208,8 @@ int SDL_PushEvent(SDL_Event *event) SDL_event_watchers_removed = SDL_FALSE; } } - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) { @@ -1237,32 +1223,25 @@ int SDL_PushEvent(SDL_Event *event) void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { /* Set filter and discard pending events */ SDL_EventOK.callback = filter; SDL_EventOK.userdata = userdata; SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } -SDL_bool -SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) +SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) { SDL_EventWatcher event_ok; - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { event_ok = SDL_EventOK; - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } - } else { - SDL_zero(event_ok); } + SDL_UnlockMutex(SDL_event_watchers_lock); if (filter) { *filter = event_ok.callback; @@ -1275,7 +1254,8 @@ SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { SDL_EventWatcher *event_watchers; event_watchers = SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers)); @@ -1289,16 +1269,14 @@ void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) watcher->removed = SDL_FALSE; ++SDL_event_watchers_count; } - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { int i; for (i = 0; i < SDL_event_watchers_count; ++i) { @@ -1315,16 +1293,14 @@ void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) break; } } - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } void SDL_FilterEvents(SDL_EventFilter filter, void *userdata) { - if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { + SDL_LockMutex(SDL_EventQ.lock); + { SDL_EventEntry *entry, *next; for (entry = SDL_EventQ.head; entry; entry = next) { next = entry->next; @@ -1332,10 +1308,8 @@ void SDL_FilterEvents(SDL_EventFilter filter, void *userdata) SDL_CutEvent(entry); } } - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } } + SDL_UnlockMutex(SDL_EventQ.lock); } Uint8 SDL_EventState(Uint32 type, int state) @@ -1384,8 +1358,7 @@ Uint8 SDL_EventState(Uint32 type, int state) return current_state; } -Uint32 -SDL_RegisterEvents(int numevents) +Uint32 SDL_RegisterEvents(int numevents) { Uint32 event_base; diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index c20962cae..f1035012d 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -233,12 +233,17 @@ int SDL_JoystickIsHaptic(SDL_Joystick *joystick) { int ret; - /* Must be a valid joystick */ - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + SDL_LockJoysticks(); + { + /* Must be a valid joystick */ + if (!SDL_PrivateJoystickValid(joystick)) { + SDL_UnlockJoysticks(); + return -1; + } - ret = SDL_SYS_JoystickIsHaptic(joystick); + ret = SDL_SYS_JoystickIsHaptic(joystick); + } + SDL_UnlockJoysticks(); if (ret > 0) { return SDL_TRUE; @@ -265,44 +270,53 @@ SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) return NULL; } - /* Must be a valid joystick */ - if (!SDL_PrivateJoystickValid(joystick)) { - SDL_SetError("Haptic: Joystick isn't valid."); - return NULL; - } - - /* Joystick must be haptic */ - if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) { - SDL_SetError("Haptic: Joystick isn't a haptic device."); - return NULL; - } - - hapticlist = SDL_haptics; - /* Check to see if joystick's haptic is already open */ - while (hapticlist) { - if (SDL_SYS_JoystickSameHaptic(hapticlist, joystick)) { - haptic = hapticlist; - ++haptic->ref_count; - return haptic; + SDL_LockJoysticks(); + { + /* Must be a valid joystick */ + if (!SDL_PrivateJoystickValid(joystick)) { + SDL_SetError("Haptic: Joystick isn't valid."); + SDL_UnlockJoysticks(); + return NULL; } - hapticlist = hapticlist->next; - } - /* Create the haptic device */ - haptic = (SDL_Haptic *)SDL_malloc((sizeof *haptic)); - if (haptic == NULL) { - SDL_OutOfMemory(); - return NULL; - } + /* Joystick must be haptic */ + if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) { + SDL_SetError("Haptic: Joystick isn't a haptic device."); + SDL_UnlockJoysticks(); + return NULL; + } - /* Initialize the haptic device */ - SDL_memset(haptic, 0, sizeof(SDL_Haptic)); - haptic->rumble_id = -1; - if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) { - SDL_SetError("Haptic: SDL_SYS_HapticOpenFromJoystick failed."); - SDL_free(haptic); - return NULL; + hapticlist = SDL_haptics; + /* Check to see if joystick's haptic is already open */ + while (hapticlist) { + if (SDL_SYS_JoystickSameHaptic(hapticlist, joystick)) { + haptic = hapticlist; + ++haptic->ref_count; + SDL_UnlockJoysticks(); + return haptic; + } + hapticlist = hapticlist->next; + } + + /* Create the haptic device */ + haptic = (SDL_Haptic *)SDL_malloc((sizeof *haptic)); + if (haptic == NULL) { + SDL_OutOfMemory(); + SDL_UnlockJoysticks(); + return NULL; + } + + /* Initialize the haptic device */ + SDL_memset(haptic, 0, sizeof(SDL_Haptic)); + haptic->rumble_id = -1; + if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) { + SDL_SetError("Haptic: SDL_SYS_HapticOpenFromJoystick failed."); + SDL_free(haptic); + SDL_UnlockJoysticks(); + return NULL; + } } + SDL_UnlockJoysticks(); /* Add haptic to list */ ++haptic->ref_count; diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 1a333ec7f..721cff6fd 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -489,6 +489,8 @@ int SDL_SYS_HapticMouse(void) int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_LINUX + SDL_AssertJoysticksLocked(); + if (joystick->driver != &SDL_LINUX_JoystickDriver) { return SDL_FALSE; } @@ -505,6 +507,8 @@ int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_LINUX + SDL_AssertJoysticksLocked(); + if (joystick->driver != &SDL_LINUX_JoystickDriver) { return 0; } @@ -528,6 +532,8 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) int ret; SDL_hapticlist_item *item; + SDL_AssertJoysticksLocked(); + if (joystick->driver != &SDL_LINUX_JoystickDriver) { return -1; } diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 4e0aa174f..f63368e0d 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -55,7 +55,7 @@ #define SDL_CONTROLLER_SDKLE_FIELD_SIZE SDL_strlen(SDL_CONTROLLER_SDKLE_FIELD) /* a list of currently opened game controllers */ -static SDL_GameController *SDL_gamecontrollers = NULL; +static SDL_GameController *SDL_gamecontrollers SDL_GUARDED_BY(SDL_joystick_lock) = NULL; typedef struct { @@ -103,44 +103,53 @@ typedef enum SDL_CONTROLLER_MAPPING_PRIORITY_USER, } SDL_ControllerMappingPriority; +#define _guarded SDL_GUARDED_BY(SDL_joystick_lock) + typedef struct _ControllerMapping_t { - SDL_JoystickGUID guid; - char *name; - char *mapping; - SDL_ControllerMappingPriority priority; - struct _ControllerMapping_t *next; + SDL_JoystickGUID guid _guarded; + char *name _guarded; + char *mapping _guarded; + SDL_ControllerMappingPriority priority _guarded; + struct _ControllerMapping_t *next _guarded; } ControllerMapping_t; +#undef _guarded + static SDL_JoystickGUID s_zeroGUID; -static ControllerMapping_t *s_pSupportedControllers = NULL; -static ControllerMapping_t *s_pDefaultMapping = NULL; -static ControllerMapping_t *s_pXInputMapping = NULL; +static ControllerMapping_t *s_pSupportedControllers SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static ControllerMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static ControllerMapping_t *s_pXInputMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static char gamecontroller_magic; +#define _guarded SDL_GUARDED_BY(SDL_joystick_lock) + /* The SDL game controller structure */ struct _SDL_GameController { - const void *magic; + const void *magic _guarded; - SDL_Joystick *joystick; /* underlying joystick device */ - int ref_count; + SDL_Joystick *joystick _guarded; /* underlying joystick device */ + int ref_count _guarded; - const char *name; - ControllerMapping_t *mapping; - int num_bindings; - SDL_ExtendedGameControllerBind *bindings; - SDL_ExtendedGameControllerBind **last_match_axis; - Uint8 *last_hat_mask; - Uint32 guide_button_down; + const char *name _guarded; + ControllerMapping_t *mapping _guarded; + int num_bindings _guarded; + SDL_ExtendedGameControllerBind *bindings _guarded; + SDL_ExtendedGameControllerBind **last_match_axis _guarded; + Uint8 *last_hat_mask _guarded; + Uint32 guide_button_down _guarded; - struct _SDL_GameController *next; /* pointer to next game controller we have allocated */ + struct _SDL_GameController *next _guarded; /* pointer to next game controller we have allocated */ }; +#undef _guarded + #define CHECK_GAMECONTROLLER_MAGIC(gamecontroller, retval) \ if (!gamecontroller || gamecontroller->magic != &gamecontroller_magic || \ !SDL_PrivateJoystickValid(gamecontroller->joystick)) { \ SDL_InvalidParamError("gamecontroller"); \ + SDL_UnlockJoysticks(); \ return retval; \ } @@ -241,7 +250,7 @@ static void HandleJoystickAxis(SDL_GameController *gamecontroller, int axis, int SDL_ExtendedGameControllerBind *last_match; SDL_ExtendedGameControllerBind *match = NULL; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); last_match = gamecontroller->last_match_axis[axis]; for (i = 0; i < gamecontroller->num_bindings; ++i) { @@ -294,7 +303,7 @@ static void HandleJoystickButton(SDL_GameController *gamecontroller, int button, { int i; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; @@ -316,7 +325,7 @@ static void HandleJoystickHat(SDL_GameController *gamecontroller, int hat, Uint8 int i; Uint8 last_mask, changed_mask; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); last_mask = gamecontroller->last_hat_mask[hat]; changed_mask = (last_mask ^ value); @@ -350,8 +359,6 @@ static void RecenterGameController(SDL_GameController *gamecontroller) SDL_GameControllerButton button; SDL_GameControllerAxis axis; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); - for (button = (SDL_GameControllerButton)0; button < SDL_CONTROLLER_BUTTON_MAX; button++) { if (SDL_GameControllerGetButton(gamecontroller, button)) { SDL_PrivateGameControllerButton(gamecontroller, button, SDL_RELEASED); @@ -370,39 +377,41 @@ static void RecenterGameController(SDL_GameController *gamecontroller) */ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *event) { + SDL_GameController *controller; + switch (event->type) { case SDL_JOYAXISMOTION: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jaxis.which) { - HandleJoystickAxis(controllerlist, event->jaxis.axis, event->jaxis.value); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jaxis.which) { + HandleJoystickAxis(controller, event->jaxis.axis, event->jaxis.value); break; } - controllerlist = controllerlist->next; } } break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jbutton.which) { - HandleJoystickButton(controllerlist, event->jbutton.button, event->jbutton.state); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jbutton.which) { + HandleJoystickButton(controller, event->jbutton.button, event->jbutton.state); break; } - controllerlist = controllerlist->next; } } break; case SDL_JOYHATMOTION: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jhat.which) { - HandleJoystickHat(controllerlist, event->jhat.hat, event->jhat.value); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jhat.which) { + HandleJoystickHat(controller, event->jhat.hat, event->jhat.value); break; } - controllerlist = controllerlist->next; } } break; case SDL_JOYDEVICEADDED: @@ -416,13 +425,13 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *eve } break; case SDL_JOYDEVICEREMOVED: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jdevice.which) { - RecenterGameController(controllerlist); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jdevice.which) { + RecenterGameController(controller); break; } - controllerlist = controllerlist->next; } /* We don't know if this was a game controller, so go ahead and send an event */ @@ -717,6 +726,8 @@ static ControllerMapping_t *SDL_PrivateMatchControllerMappingForGUID(SDL_Joystic ControllerMapping_t *mapping; Uint16 crc = 0; + SDL_AssertJoysticksLocked(); + if (match_crc) { SDL_GetJoystickGUIDInfo(guid, NULL, NULL, NULL, &crc); } @@ -829,8 +840,7 @@ static const char *map_StringForControllerAxis[] = { /* * convert a string to its enum equivalent */ -SDL_GameControllerAxis -SDL_GameControllerGetAxisFromString(const char *str) +SDL_GameControllerAxis SDL_GameControllerGetAxisFromString(const char *str) { int entry; @@ -889,8 +899,7 @@ static const char *map_StringForControllerButton[] = { /* * convert a string to its enum equivalent */ -SDL_GameControllerButton -SDL_GameControllerGetButtonFromString(const char *str) +SDL_GameControllerButton SDL_GameControllerGetButtonFromString(const char *str) { int entry; if (str == NULL || str[0] == '\0') { @@ -928,7 +937,7 @@ static void SDL_PrivateGameControllerParseElement(SDL_GameController *gamecontro char half_axis_input = 0; char half_axis_output = 0; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); if (*szGameButton == '+' || *szGameButton == '-') { half_axis_output = *szGameButton++; @@ -1023,8 +1032,6 @@ static void SDL_PrivateGameControllerParseControllerConfigString(SDL_GameControl int i = 0; const char *pchPos = pchString; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); - SDL_zeroa(szGameButton); SDL_zeroa(szJoystickButton); @@ -1072,7 +1079,7 @@ static void SDL_PrivateLoadButtonMapping(SDL_GameController *gamecontroller, Con { int i; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); gamecontroller->name = pControllerMapping->name; gamecontroller->num_bindings = 0; @@ -1189,21 +1196,23 @@ static char *SDL_PrivateGetControllerMappingFromMappingString(const char *pMappi */ static void SDL_PrivateGameControllerRefreshMapping(ControllerMapping_t *pControllerMapping) { - SDL_GameController *gamecontrollerlist = SDL_gamecontrollers; - while (gamecontrollerlist) { - if (gamecontrollerlist->mapping == pControllerMapping) { - /* Not really threadsafe. Should this lock access within SDL_GameControllerEventWatcher? */ - SDL_PrivateLoadButtonMapping(gamecontrollerlist, pControllerMapping); + SDL_GameController *controller; + + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->mapping == pControllerMapping) { + SDL_PrivateLoadButtonMapping(controller, pControllerMapping); { SDL_Event event; event.type = SDL_CONTROLLERDEVICEREMAPPED; - event.cdevice.which = gamecontrollerlist->joystick->instance_id; + event.cdevice.which = controller->joystick->instance_id; SDL_PushEvent(&event); } } - gamecontrollerlist = gamecontrollerlist->next; + controller = controller->next; } } @@ -1217,6 +1226,8 @@ static ControllerMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, ControllerMapping_t *pControllerMapping; Uint16 crc; + SDL_AssertJoysticksLocked(); + pchName = SDL_PrivateGetControllerNameFromMappingString(mappingString); if (pchName == NULL) { SDL_SetError("Couldn't parse name from %s", mappingString); @@ -1322,6 +1333,8 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForNameAndGUID(const { ControllerMapping_t *mapping; + SDL_AssertJoysticksLocked(); + mapping = SDL_PrivateGetControllerMappingForGUID(guid); #ifdef __LINUX__ if (mapping == NULL && name) { @@ -1428,11 +1441,10 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) SDL_JoystickGUID guid; ControllerMapping_t *mapping; - SDL_LockJoysticks(); + SDL_AssertJoysticksLocked(); if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); - SDL_UnlockJoysticks(); return NULL; } @@ -1448,7 +1460,6 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) } } - SDL_UnlockJoysticks(); return mapping; } @@ -1534,6 +1545,8 @@ static int SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_Co SDL_bool existing = SDL_FALSE; ControllerMapping_t *pControllerMapping; + SDL_AssertJoysticksLocked(); + if (mappingString == NULL) { return SDL_InvalidParamError("mappingString"); } @@ -1634,7 +1647,15 @@ static int SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_Co */ int SDL_GameControllerAddMapping(const char *mappingString) { - return SDL_PrivateGameControllerAddMapping(mappingString, SDL_CONTROLLER_MAPPING_PRIORITY_API); + int retval; + + SDL_LockJoysticks(); + { + retval = SDL_PrivateGameControllerAddMapping(mappingString, SDL_CONTROLLER_MAPPING_PRIORITY_API); + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -1643,14 +1664,20 @@ int SDL_GameControllerAddMapping(const char *mappingString) int SDL_GameControllerNumMappings(void) { int num_mappings = 0; - ControllerMapping_t *mapping; - for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { - if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { - continue; + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping; + + for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + ++num_mappings; } - ++num_mappings; } + SDL_UnlockJoysticks(); + return num_mappings; } @@ -1664,6 +1691,8 @@ static char *CreateMappingString(ControllerMapping_t *mapping, SDL_JoystickGUID size_t needed; const char *platform = SDL_GetPlatform(); + SDL_AssertJoysticksLocked(); + SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ @@ -1707,48 +1736,71 @@ static char *CreateMappingString(ControllerMapping_t *mapping, SDL_JoystickGUID /* * Get the mapping at a particular index. */ -char * -SDL_GameControllerMappingForIndex(int mapping_index) +char *SDL_GameControllerMappingForIndex(int mapping_index) { - ControllerMapping_t *mapping; + char *retval = NULL; - for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { - if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { - continue; + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping; + + for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + if (mapping_index == 0) { + retval = CreateMappingString(mapping, mapping->guid); + break; + } + --mapping_index; } - if (mapping_index == 0) { - return CreateMappingString(mapping, mapping->guid); - } - --mapping_index; } - SDL_SetError("Mapping not available"); - return NULL; + SDL_UnlockJoysticks(); + + if (retval == NULL) { + SDL_SetError("Mapping not available"); + } + return retval; } /* * Get the mapping string for this GUID */ -char * -SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid) +char *SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid) { - ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(guid); - if (mapping) { - return CreateMappingString(mapping, guid); - } else { - SDL_SetError("Mapping not available"); + char *retval; + + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(guid); + if (mapping) { + retval = CreateMappingString(mapping, guid); + } else { + SDL_SetError("Mapping not available"); + retval = NULL; + } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /* * Get the mapping string for this device */ -char * -SDL_GameControllerMapping(SDL_GameController *gamecontroller) +char *SDL_GameControllerMapping(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + char *retval; - return CreateMappingString(gamecontroller->mapping, gamecontroller->joystick->guid); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + + retval = CreateMappingString(gamecontroller->mapping, gamecontroller->joystick->guid); + } + SDL_UnlockJoysticks(); + + return retval; } static void SDL_GameControllerLoadHints() @@ -1807,6 +1859,9 @@ int SDL_GameControllerInitMappings(void) char szControllerMapPath[1024]; int i = 0; const char *pMappingString = NULL; + + SDL_AssertJoysticksLocked(); + pMappingString = s_ControllerMappings[i]; while (pMappingString) { SDL_PrivateGameControllerAddMapping(pMappingString, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT); @@ -1853,38 +1908,49 @@ int SDL_GameControllerInit(void) /* * Get the implementation dependent name of a controller */ -const char * -SDL_GameControllerNameForIndex(int joystick_index) +const char *SDL_GameControllerNameForIndex(int joystick_index) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(joystick_index); - if (pSupportedController != NULL) { - if (SDL_strcmp(pSupportedController->name, "*") == 0) { - return SDL_JoystickNameForIndex(joystick_index); - } else { - return pSupportedController->name; + const char *retval = NULL; + + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping != NULL) { + if (SDL_strcmp(mapping->name, "*") == 0) { + retval = SDL_JoystickNameForIndex(joystick_index); + } else { + retval = mapping->name; + } } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /* * Get the implementation dependent path of a controller */ -const char * -SDL_GameControllerPathForIndex(int joystick_index) +const char *SDL_GameControllerPathForIndex(int joystick_index) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(joystick_index); - if (pSupportedController != NULL) { - return SDL_JoystickPathForIndex(joystick_index); + const char *retval = NULL; + + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping != NULL) { + retval = SDL_JoystickPathForIndex(joystick_index); + } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /** * Get the type of a game controller. */ -SDL_GameControllerType -SDL_GameControllerTypeForIndex(int joystick_index) +SDL_GameControllerType SDL_GameControllerTypeForIndex(int joystick_index) { return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetDeviceGUID(joystick_index), SDL_JoystickNameForIndex(joystick_index)); } @@ -1894,58 +1960,71 @@ SDL_GameControllerTypeForIndex(int joystick_index) * This can be called before any controllers are opened. * If no mapping can be found, this function returns NULL. */ -char * -SDL_GameControllerMappingForDeviceIndex(int joystick_index) +char *SDL_GameControllerMappingForDeviceIndex(int joystick_index) { - char *pMappingString = NULL; - ControllerMapping_t *mapping; + char *retval = NULL; SDL_LockJoysticks(); - mapping = SDL_PrivateGetControllerMapping(joystick_index); - if (mapping) { - SDL_JoystickGUID guid; - char pchGUID[33]; - size_t needed; - guid = SDL_JoystickGetDeviceGUID(joystick_index); - SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); - /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ - needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; - pMappingString = SDL_malloc(needed); - if (pMappingString == NULL) { - SDL_OutOfMemory(); - SDL_UnlockJoysticks(); - return NULL; + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping != NULL) { + SDL_JoystickGUID guid; + char pchGUID[33]; + size_t needed; + guid = SDL_JoystickGetDeviceGUID(joystick_index); + SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); + /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ + needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; + retval = (char *)SDL_malloc(needed); + if (retval != NULL) { + (void)SDL_snprintf(retval, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); + } else { + SDL_OutOfMemory(); + } } - (void)SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); } SDL_UnlockJoysticks(); - return pMappingString; + return retval; } /* * Return 1 if the joystick with this name and GUID is a supported controller */ -SDL_bool -SDL_IsGameControllerNameAndGUID(const char *name, SDL_JoystickGUID guid) +SDL_bool SDL_IsGameControllerNameAndGUID(const char *name, SDL_JoystickGUID guid) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMappingForNameAndGUID(name, guid); - if (pSupportedController) { - return SDL_TRUE; + SDL_bool retval; + + SDL_LockJoysticks(); + { + if (SDL_PrivateGetControllerMappingForNameAndGUID(name, guid) != NULL) { + retval = SDL_TRUE; + } else { + retval = SDL_FALSE; + } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } /* * Return 1 if the joystick at this device index is a supported controller */ -SDL_bool -SDL_IsGameController(int joystick_index) +SDL_bool SDL_IsGameController(int joystick_index) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(joystick_index); - if (pSupportedController != NULL) { - return SDL_TRUE; + SDL_bool retval; + + SDL_LockJoysticks(); + { + if (SDL_PrivateGetControllerMapping(joystick_index) != NULL) { + retval = SDL_TRUE; + } else { + retval = SDL_FALSE; + } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } #if defined(__LINUX__) @@ -2047,8 +2126,7 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) * * This function returns a controller identifier, or NULL if an error occurred. */ -SDL_GameController * -SDL_GameControllerOpen(int joystick_index) +SDL_GameController *SDL_GameControllerOpen(int joystick_index) { SDL_JoystickID instance_id; SDL_GameController *gamecontroller; @@ -2141,86 +2219,101 @@ void SDL_GameControllerUpdate(void) /** * Return whether a game controller has a given axis */ -SDL_bool -SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) +SDL_bool SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { SDL_GameControllerButtonBind bind; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + + bind = SDL_GameControllerGetBindForAxis(gamecontroller, axis); + } + SDL_UnlockJoysticks(); - bind = SDL_GameControllerGetBindForAxis(gamecontroller, axis); return (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE; } /* * Get the current state of an axis control on a controller */ -Sint16 -SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) +Sint16 SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { - int i; + Sint16 retval = 0; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_LockJoysticks(); + { + int i; - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { - int value = 0; - SDL_bool valid_input_range; - SDL_bool valid_output_range; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); - if (binding->input.axis.axis_min < binding->input.axis.axis_max) { - valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); - } else { - valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); - } - if (valid_input_range) { - if (binding->input.axis.axis_min != binding->output.axis.axis_min || binding->input.axis.axis_max != binding->output.axis.axis_max) { - float normalized_value = (float)(value - binding->input.axis.axis_min) / (binding->input.axis.axis_max - binding->input.axis.axis_min); - value = binding->output.axis.axis_min + (int)(normalized_value * (binding->output.axis.axis_max - binding->output.axis.axis_min)); + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { + int value = 0; + SDL_bool valid_input_range; + SDL_bool valid_output_range; + + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); + if (binding->input.axis.axis_min < binding->input.axis.axis_max) { + valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); + } else { + valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); + } + if (valid_input_range) { + if (binding->input.axis.axis_min != binding->output.axis.axis_min || binding->input.axis.axis_max != binding->output.axis.axis_max) { + float normalized_value = (float)(value - binding->input.axis.axis_min) / (binding->input.axis.axis_max - binding->input.axis.axis_min); + value = binding->output.axis.axis_min + (int)(normalized_value * (binding->output.axis.axis_max - binding->output.axis.axis_min)); + } + } else { + value = 0; + } + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + value = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); + if (value == SDL_PRESSED) { + value = binding->output.axis.axis_max; + } + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); + if (hat_mask & binding->input.hat.hat_mask) { + value = binding->output.axis.axis_max; } - } else { - value = 0; } - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - value = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); - if (value == SDL_PRESSED) { - value = binding->output.axis.axis_max; - } - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); - if (hat_mask & binding->input.hat.hat_mask) { - value = binding->output.axis.axis_max; - } - } - if (binding->output.axis.axis_min < binding->output.axis.axis_max) { - valid_output_range = (value >= binding->output.axis.axis_min && value <= binding->output.axis.axis_max); - } else { - valid_output_range = (value >= binding->output.axis.axis_max && value <= binding->output.axis.axis_min); - } - /* If the value is zero, there might be another binding that makes it non-zero */ - if (value != 0 && valid_output_range) { - return (Sint16)value; + if (binding->output.axis.axis_min < binding->output.axis.axis_max) { + valid_output_range = (value >= binding->output.axis.axis_min && value <= binding->output.axis.axis_max); + } else { + valid_output_range = (value >= binding->output.axis.axis_max && value <= binding->output.axis.axis_min); + } + /* If the value is zero, there might be another binding that makes it non-zero */ + if (value != 0 && valid_output_range) { + retval = (Sint16)value; + break; + } } } } - return 0; + SDL_UnlockJoysticks(); + + return retval; } /** * Return whether a game controller has a given button */ -SDL_bool -SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) +SDL_bool SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { SDL_GameControllerButtonBind bind; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + + bind = SDL_GameControllerGetBindForButton(gamecontroller, button); + } + SDL_UnlockJoysticks(); - bind = SDL_GameControllerGetBindForButton(gamecontroller, button); return (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE; } @@ -2229,38 +2322,49 @@ SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControll */ Uint8 SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { - int i; + Uint8 retval = SDL_RELEASED; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_LockJoysticks(); + { + int i; - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - SDL_bool valid_input_range; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); - int value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); - int threshold = binding->input.axis.axis_min + (binding->input.axis.axis_max - binding->input.axis.axis_min) / 2; - if (binding->input.axis.axis_min < binding->input.axis.axis_max) { - valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); - if (valid_input_range) { - return (value >= threshold) ? SDL_PRESSED : SDL_RELEASED; - } - } else { - valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); - if (valid_input_range) { - return (value <= threshold) ? SDL_PRESSED : SDL_RELEASED; + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + SDL_bool valid_input_range; + + int value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); + int threshold = binding->input.axis.axis_min + (binding->input.axis.axis_max - binding->input.axis.axis_min) / 2; + if (binding->input.axis.axis_min < binding->input.axis.axis_max) { + valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); + if (valid_input_range) { + retval = (value >= threshold) ? SDL_PRESSED : SDL_RELEASED; + break; + } + } else { + valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); + if (valid_input_range) { + retval = (value <= threshold) ? SDL_PRESSED : SDL_RELEASED; + break; + } } + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + retval = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); + break; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); + retval = (hat_mask & binding->input.hat.hat_mask) ? SDL_PRESSED : SDL_RELEASED; + break; } - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - return SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); - return (hat_mask & binding->input.hat.hat_mask) ? SDL_PRESSED : SDL_RELEASED; } } } - return SDL_RELEASED; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -2268,12 +2372,18 @@ Uint8 SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameCo */ int SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + int retval = 0; - if (joystick) { - return joystick->ntouchpads; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + retval = joystick->ntouchpads; + } } - return 0; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -2281,12 +2391,22 @@ int SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller) */ int SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, int touchpad) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + int retval = 0; - if (joystick && touchpad >= 0 && touchpad < joystick->ntouchpads) { - return joystick->touchpads[touchpad].nfingers; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + if (touchpad >= 0 && touchpad < joystick->ntouchpads) { + retval = joystick->touchpads[touchpad].nfingers; + } else { + retval = SDL_InvalidParamError("touchpad"); + } + } } - return 0; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -2294,55 +2414,66 @@ int SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, */ int SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + int retval = -1; - if (joystick) { - if (touchpad >= 0 && touchpad < joystick->ntouchpads) { - SDL_JoystickTouchpadInfo *touchpad_info = &joystick->touchpads[touchpad]; - if (finger >= 0 && finger < touchpad_info->nfingers) { - SDL_JoystickTouchpadFingerInfo *info = &touchpad_info->fingers[finger]; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + if (touchpad >= 0 && touchpad < joystick->ntouchpads) { + SDL_JoystickTouchpadInfo *touchpad_info = &joystick->touchpads[touchpad]; + if (finger >= 0 && finger < touchpad_info->nfingers) { + SDL_JoystickTouchpadFingerInfo *info = &touchpad_info->fingers[finger]; - if (state) { - *state = info->state; + if (state) { + *state = info->state; + } + if (x) { + *x = info->x; + } + if (y) { + *y = info->y; + } + if (pressure) { + *pressure = info->pressure; + } + retval = 0; + } else { + retval = SDL_InvalidParamError("finger"); } - if (x) { - *x = info->x; - } - if (y) { - *y = info->y; - } - if (pressure) { - *pressure = info->pressure; - } - return 0; } else { - return SDL_InvalidParamError("finger"); + retval = SDL_InvalidParamError("touchpad"); } - } else { - return SDL_InvalidParamError("touchpad"); } - } else { - return SDL_InvalidParamError("gamecontroller"); } + SDL_UnlockJoysticks(); + + return retval; } /** * Return whether a game controller has a particular sensor. */ -SDL_bool -SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type) +SDL_bool SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_bool retval = SDL_FALSE; - if (joystick) { - for (i = 0; i < joystick->nsensors; ++i) { - if (joystick->sensors[i].type == type) { - return SDL_TRUE; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + if (joystick->sensors[i].type == type) { + retval = SDL_TRUE; + break; + } } } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2350,41 +2481,47 @@ SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType t */ int SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - if (joystick == NULL) { - return -1; - } - - for (i = 0; i < joystick->nsensors; ++i) { - SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - - if (sensor->type == type) { - if (sensor->enabled == enabled) { - return 0; - } - - if (enabled) { - if (joystick->nsensors_enabled == 0) { - if (joystick->driver->SetSensorsEnabled(joystick, SDL_TRUE) < 0) { - return -1; + if (sensor->type == type) { + if (sensor->enabled == enabled) { + SDL_UnlockJoysticks(); + return 0; } - } - ++joystick->nsensors_enabled; - } else { - if (joystick->nsensors_enabled == 1) { - if (joystick->driver->SetSensorsEnabled(joystick, SDL_FALSE) < 0) { - return -1; - } - } - --joystick->nsensors_enabled; - } - sensor->enabled = enabled; - return 0; + if (enabled) { + if (joystick->nsensors_enabled == 0) { + if (joystick->driver->SetSensorsEnabled(joystick, SDL_TRUE) < 0) { + SDL_UnlockJoysticks(); + return -1; + } + } + ++joystick->nsensors_enabled; + } else { + if (joystick->nsensors_enabled == 1) { + if (joystick->driver->SetSensorsEnabled(joystick, SDL_FALSE) < 0) { + SDL_UnlockJoysticks(); + return -1; + } + } + --joystick->nsensors_enabled; + } + + sensor->enabled = enabled; + SDL_UnlockJoysticks(); + return 0; + } + } } } + SDL_UnlockJoysticks(); + return SDL_Unsupported(); } @@ -2393,17 +2530,24 @@ int SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_S */ SDL_bool SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_bool retval = SDL_FALSE; - if (joystick) { - for (i = 0; i < joystick->nsensors; ++i) { - if (joystick->sensors[i].type == type) { - return joystick->sensors[i].enabled; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + if (joystick->sensors[i].type == type) { + retval = joystick->sensors[i].enabled; + break; + } } } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2411,21 +2555,26 @@ SDL_bool SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, S */ float SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_SensorType type) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + float retval = 0.0f; - if (joystick == NULL) { - return 0.0f; - } + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - for (i = 0; i < joystick->nsensors; ++i) { - SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - - if (sensor->type == type) { - return sensor->rate; + if (sensor->type == type) { + retval = sensor->rate; + break; + } + } } } - return 0.0f; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2441,42 +2590,51 @@ int SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_Sens */ int SDL_GameControllerGetSensorDataWithTimestamp(SDL_GameController *gamecontroller, SDL_SensorType type, Uint64 *timestamp, float *data, int num_values) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - if (joystick == NULL) { - return -1; - } - - for (i = 0; i < joystick->nsensors; ++i) { - SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - - if (sensor->type == type) { - num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); - SDL_memcpy(data, sensor->data, num_values * sizeof(*data)); - if (timestamp) { - *timestamp = sensor->timestamp_us; + if (sensor->type == type) { + num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); + SDL_memcpy(data, sensor->data, num_values * sizeof(*data)); + if (timestamp) { + *timestamp = sensor->timestamp_us; + } + SDL_UnlockJoysticks(); + return 0; + } } - return 0; } } + SDL_UnlockJoysticks(); + return SDL_Unsupported(); } -const char * -SDL_GameControllerName(SDL_GameController *gamecontroller) +const char *SDL_GameControllerName(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + const char *retval = NULL; - if (SDL_strcmp(gamecontroller->name, "*") == 0) { - return SDL_JoystickName(SDL_GameControllerGetJoystick(gamecontroller)); - } else { - return gamecontroller->name; + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + + if (SDL_strcmp(gamecontroller->name, "*") == 0) { + retval = SDL_JoystickName(gamecontroller->joystick); + } else { + retval = gamecontroller->name; + } } + SDL_UnlockJoysticks(); + + return retval; } -const char * -SDL_GameControllerPath(SDL_GameController *gamecontroller) +const char *SDL_GameControllerPath(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2486,8 +2644,7 @@ SDL_GameControllerPath(SDL_GameController *gamecontroller) return SDL_JoystickPath(joystick); } -SDL_GameControllerType -SDL_GameControllerGetType(SDL_GameController *gamecontroller) +SDL_GameControllerType SDL_GameControllerGetType(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2520,8 +2677,7 @@ void SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int pl SDL_JoystickSetPlayerIndex(joystick, player_index); } -Uint16 -SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2531,8 +2687,7 @@ SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) return SDL_JoystickGetVendor(joystick); } -Uint16 -SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2542,8 +2697,7 @@ SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) return SDL_JoystickGetProduct(joystick); } -Uint16 -SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2553,8 +2707,7 @@ SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) return SDL_JoystickGetProductVersion(joystick); } -Uint16 -SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2564,8 +2717,7 @@ SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) return SDL_JoystickGetFirmwareVersion(joystick); } -const char * -SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) +const char * SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2579,30 +2731,38 @@ SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) * Return if the controller in question is currently attached to the system, * \return 0 if not plugged in, 1 if still present. */ -SDL_bool -SDL_GameControllerGetAttached(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerGetAttached(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - return SDL_JoystickGetAttached(gamecontroller->joystick); + if (joystick == NULL) { + return SDL_FALSE; + } + return SDL_JoystickGetAttached(joystick); } /* * Get the joystick for this controller */ -SDL_Joystick * -SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller) +SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + SDL_Joystick *joystick; - return gamecontroller->joystick; + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + + joystick = gamecontroller->joystick; + } + SDL_UnlockJoysticks(); + + return joystick; } /* * Return the SDL_GameController associated with an instance id. */ -SDL_GameController * -SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) +SDL_GameController *SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) { SDL_GameController *gamecontroller; @@ -2624,11 +2784,18 @@ SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) */ SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index) { - SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index); - if (joystick) { - return SDL_GameControllerFromInstanceID(joystick->instance_id); + SDL_GameController *retval = NULL; + + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index); + if (joystick) { + retval = SDL_GameControllerFromInstanceID(joystick->instance_id); + } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2636,32 +2803,36 @@ SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index) */ SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { - int i; SDL_GameControllerButtonBind bind; + SDL_zero(bind); - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); - if (axis == SDL_CONTROLLER_AXIS_INVALID) { - return bind; - } - - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { - bind.bindType = binding->inputType; - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - /* FIXME: There might be multiple axes bound now that we have axis ranges... */ - bind.value.axis = binding->input.axis.axis; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - bind.value.button = binding->input.button; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - bind.value.hat.hat = binding->input.hat.hat; - bind.value.hat.hat_mask = binding->input.hat.hat_mask; + if (axis != SDL_CONTROLLER_AXIS_INVALID) { + int i; + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { + bind.bindType = binding->inputType; + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + /* FIXME: There might be multiple axes bound now that we have axis ranges... */ + bind.value.axis = binding->input.axis.axis; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + bind.value.button = binding->input.button; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + bind.value.hat.hat = binding->input.hat.hat; + bind.value.hat.hat_mask = binding->input.hat.hat_mask; + } + break; + } } - break; } } + SDL_UnlockJoysticks(); + return bind; } @@ -2670,31 +2841,35 @@ SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController */ SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { - int i; SDL_GameControllerButtonBind bind; + SDL_zero(bind); - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); - if (button == SDL_CONTROLLER_BUTTON_INVALID) { - return bind; - } - - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { - bind.bindType = binding->inputType; - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - bind.value.axis = binding->input.axis.axis; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - bind.value.button = binding->input.button; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - bind.value.hat.hat = binding->input.hat.hat; - bind.value.hat.hat_mask = binding->input.hat.hat_mask; + if (button != SDL_CONTROLLER_BUTTON_INVALID) { + int i; + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { + bind.bindType = binding->inputType; + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + bind.value.axis = binding->input.axis.axis; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + bind.value.button = binding->input.button; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + bind.value.hat.hat = binding->input.hat.hat; + bind.value.hat.hat_mask = binding->input.hat.hat_mask; + } + break; + } } - break; } } + SDL_UnlockJoysticks(); + return bind; } @@ -2718,8 +2893,7 @@ int SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 return SDL_JoystickRumbleTriggers(joystick, left_rumble, right_rumble, duration_ms); } -SDL_bool -SDL_GameControllerHasLED(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerHasLED(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2729,8 +2903,7 @@ SDL_GameControllerHasLED(SDL_GameController *gamecontroller) return SDL_JoystickHasLED(joystick); } -SDL_bool -SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2740,8 +2913,7 @@ SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) return SDL_JoystickHasRumble(joystick); } -SDL_bool -SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2775,12 +2947,13 @@ void SDL_GameControllerClose(SDL_GameController *gamecontroller) { SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev; + SDL_LockJoysticks(); + if (gamecontroller == NULL || gamecontroller->magic != &gamecontroller_magic) { + SDL_UnlockJoysticks(); return; } - SDL_LockJoysticks(); - /* First decrement ref count */ if (--gamecontroller->ref_count > 0) { SDL_UnlockJoysticks(); @@ -2831,6 +3004,8 @@ void SDL_GameControllerQuitMappings(void) { ControllerMapping_t *pControllerMap; + SDL_AssertJoysticksLocked(); + while (s_pSupportedControllers) { pControllerMap = s_pSupportedControllers; s_pSupportedControllers = s_pSupportedControllers->next; @@ -2863,7 +3038,7 @@ static int SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL { int posted; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_AssertJoysticksLocked(); /* translate the event, if desired */ posted = 0; @@ -2889,7 +3064,7 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S #if !SDL_EVENTS_DISABLED SDL_Event event; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_AssertJoysticksLocked(); if (button == SDL_CONTROLLER_BUTTON_INVALID) { return 0; @@ -2983,39 +3158,53 @@ int SDL_GameControllerEventState(int state) void SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick) { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick == joystick) { - SDL_PrivateGameControllerButton(controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED); + SDL_GameController *controller; + + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick == joystick) { + SDL_PrivateGameControllerButton(controller, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED); break; } - controllerlist = controllerlist->next; } } -const char * -SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) +const char *SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { #if defined(SDL_JOYSTICK_MFI) const char *IOS_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button); + const char *retval; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); - return IOS_GameControllerGetAppleSFSymbolsNameForButton(gamecontroller, button); + retval = IOS_GameControllerGetAppleSFSymbolsNameForButton(gamecontroller, button); + } + SDL_UnlockJoysticks(); + + return retval; #else return NULL; #endif } -const char * -SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) +const char *SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { #if defined(SDL_JOYSTICK_MFI) const char *IOS_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis); + const char *retval; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); - return IOS_GameControllerGetAppleSFSymbolsNameForAxis(gamecontroller, axis); + retval = IOS_GameControllerGetAppleSFSymbolsNameForAxis(gamecontroller, axis); + } + SDL_UnlockJoysticks(); + + return retval; #else return NULL; #endif diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 54791dcda..4e874a693 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -109,40 +109,37 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = { &SDL_DUMMY_JoystickDriver #endif }; +SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ +static int SDL_joysticks_locked; static SDL_bool SDL_joysticks_initialized; static SDL_bool SDL_joysticks_quitting = SDL_FALSE; -static SDL_Joystick *SDL_joysticks = NULL; -static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ -static int SDL_joysticks_locked; -static SDL_atomic_t SDL_next_joystick_instance_id; -static int SDL_joystick_player_count = 0; -static SDL_JoystickID *SDL_joystick_players = NULL; +static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static SDL_atomic_t SDL_next_joystick_instance_id SDL_GUARDED_BY(SDL_joystick_lock); +static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; +static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; static char joystick_magic; #define CHECK_JOYSTICK_MAGIC(joystick, retval) \ if (!joystick || joystick->magic != &joystick_magic) { \ SDL_InvalidParamError("joystick"); \ + SDL_UnlockJoysticks(); \ return retval; \ } -SDL_bool -SDL_JoysticksInitialized(void) +SDL_bool SDL_JoysticksInitialized(void) { return SDL_joysticks_initialized; } -SDL_bool -SDL_JoysticksQuitting(void) +SDL_bool SDL_JoysticksQuitting(void) { return SDL_joysticks_quitting; } void SDL_LockJoysticks(void) { - if (SDL_joystick_lock) { - SDL_LockMutex(SDL_joystick_lock); - } + SDL_LockMutex(SDL_joystick_lock); ++SDL_joysticks_locked; } @@ -151,22 +148,18 @@ void SDL_UnlockJoysticks(void) { --SDL_joysticks_locked; - if (SDL_joystick_lock) { - SDL_UnlockMutex(SDL_joystick_lock); + SDL_UnlockMutex(SDL_joystick_lock); - /* The last unlock after joysticks are uninitialized will cleanup the mutex, - * allowing applications to lock joysticks while reinitializing the system. - */ - if (!SDL_joysticks_locked && - !SDL_joysticks_initialized) { - SDL_DestroyMutex(SDL_joystick_lock); - SDL_joystick_lock = NULL; - } + /* The last unlock after joysticks are uninitialized will cleanup the mutex, + * allowing applications to lock joysticks while reinitializing the system. + */ + if (SDL_joystick_lock && !SDL_joysticks_locked && !SDL_joysticks_initialized) { + SDL_DestroyMutex(SDL_joystick_lock); + SDL_joystick_lock = NULL; } } -SDL_bool -SDL_JoysticksLocked(void) +SDL_bool SDL_JoysticksLocked(void) { return (SDL_joysticks_locked > 0) ? SDL_TRUE : SDL_FALSE; } @@ -366,8 +359,7 @@ SDL_JoystickID SDL_GetNextJoystickInstanceID() /* * Get the implementation dependent name of a joystick */ -const char * -SDL_JoystickNameForIndex(int device_index) +const char *SDL_JoystickNameForIndex(int device_index) { SDL_JoystickDriver *driver; const char *name = NULL; @@ -385,8 +377,7 @@ SDL_JoystickNameForIndex(int device_index) /* * Get the implementation dependent path of a joystick */ -const char * -SDL_JoystickPathForIndex(int device_index) +const char *SDL_JoystickPathForIndex(int device_index) { SDL_JoystickDriver *driver; const char *path = NULL; @@ -433,23 +424,30 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) MAKE_VIDPID(0x05a0, 0x3232), /* 8Bitdo Zero Gamepad */ }; + SDL_bool retval = SDL_FALSE; int i; Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick)); /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/ - if (joystick->naxes == 2) { - /* Assume D-pad or thumbstick style axes are centered at 0 */ - return SDL_TRUE; - } + SDL_LockJoysticks(); + { + if (joystick->naxes == 2) { + /* Assume D-pad or thumbstick style axes are centered at 0 */ + retval = SDL_TRUE; + } - for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) { - if (id == zero_centered_joysticks[i]) { - return SDL_TRUE; + for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) { + if (id == zero_centered_joysticks[i]) { + retval = SDL_TRUE; + break; + } } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; #endif /* __WINRT__ */ } @@ -460,8 +458,7 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) * * This function returns a joystick identifier, or NULL if an error occurred. */ -SDL_Joystick * -SDL_JoystickOpen(int device_index) +SDL_Joystick *SDL_JoystickOpen(int device_index) { SDL_JoystickDriver *driver; SDL_JoystickID instance_id; @@ -577,8 +574,7 @@ SDL_JoystickOpen(int device_index) return joystick; } -int SDL_JoystickAttachVirtual(SDL_JoystickType type, - int naxes, int nbuttons, int nhats) +int SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nbuttons, int nhats) { SDL_VirtualJoystickDesc desc; @@ -594,12 +590,12 @@ int SDL_JoystickAttachVirtual(SDL_JoystickType type, int SDL_JoystickAttachVirtualEx(const SDL_VirtualJoystickDesc *desc) { #if SDL_JOYSTICK_VIRTUAL - int result; + int retval; SDL_LockJoysticks(); - result = SDL_JoystickAttachVirtualInner(desc); + retval = SDL_JoystickAttachVirtualInner(desc); SDL_UnlockJoysticks(); - return result; + return retval; #else return SDL_SetError("SDL not built with virtual-joystick support"); #endif @@ -613,9 +609,9 @@ int SDL_JoystickDetachVirtual(int device_index) SDL_LockJoysticks(); if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { if (driver == &SDL_VIRTUAL_JoystickDriver) { - const int result = SDL_JoystickDetachVirtualInner(device_index); + const int retval = SDL_JoystickDetachVirtualInner(device_index); SDL_UnlockJoysticks(); - return result; + return retval; } } SDL_UnlockJoysticks(); @@ -626,8 +622,7 @@ int SDL_JoystickDetachVirtual(int device_index) #endif } -SDL_bool -SDL_JoystickIsVirtual(int device_index) +SDL_bool SDL_JoystickIsVirtual(int device_index) { #if SDL_JOYSTICK_VIRTUAL SDL_JoystickDriver *driver; @@ -650,49 +645,71 @@ SDL_JoystickIsVirtual(int device_index) int SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); #if SDL_JOYSTICK_VIRTUAL - return SDL_JoystickSetVirtualAxisInner(joystick, axis, value); + retval = SDL_JoystickSetVirtualAxisInner(joystick, axis, value); #else - return SDL_SetError("SDL not built with virtual-joystick support"); + retval = SDL_SetError("SDL not built with virtual-joystick support"); #endif + } + SDL_UnlockJoysticks(); + + return retval; } int SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); #if SDL_JOYSTICK_VIRTUAL - return SDL_JoystickSetVirtualButtonInner(joystick, button, value); + retval = SDL_JoystickSetVirtualButtonInner(joystick, button, value); #else - return SDL_SetError("SDL not built with virtual-joystick support"); + retval = SDL_SetError("SDL not built with virtual-joystick support"); #endif + } + SDL_UnlockJoysticks(); + + return retval; } int SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); #if SDL_JOYSTICK_VIRTUAL - return SDL_JoystickSetVirtualHatInner(joystick, hat, value); + retval = SDL_JoystickSetVirtualHatInner(joystick, hat, value); #else - return SDL_SetError("SDL not built with virtual-joystick support"); + retval = SDL_SetError("SDL not built with virtual-joystick support"); #endif + } + SDL_UnlockJoysticks(); + + return retval; } /* * Checks to make sure the joystick is valid. */ -SDL_bool -SDL_PrivateJoystickValid(SDL_Joystick *joystick) +SDL_bool SDL_PrivateJoystickValid(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - return SDL_TRUE; + SDL_AssertJoysticksLocked(); + return (joystick && joystick->magic == &joystick_magic); } -SDL_bool -SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *out) +SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *out) { SDL_JoystickDriver *driver; SDL_bool is_ok = SDL_FALSE; @@ -711,9 +728,17 @@ SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *o */ int SDL_JoystickNumAxes(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->naxes; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->naxes; + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -721,9 +746,17 @@ int SDL_JoystickNumAxes(SDL_Joystick *joystick) */ int SDL_JoystickNumHats(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->nhats; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->nhats; + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -731,9 +764,17 @@ int SDL_JoystickNumHats(SDL_Joystick *joystick) */ int SDL_JoystickNumBalls(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->nballs; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->nballs; + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -741,46 +782,66 @@ int SDL_JoystickNumBalls(SDL_Joystick *joystick) */ int SDL_JoystickNumButtons(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->nbuttons; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->nbuttons; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Get the current state of an axis control on a joystick */ -Sint16 -SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) +Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) { Sint16 state; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - if (axis < joystick->naxes) { - state = joystick->axes[axis].value; - } else { - SDL_SetError("Joystick only has %d axes", joystick->naxes); - state = 0; + if (axis < joystick->naxes) { + state = joystick->axes[axis].value; + } else { + SDL_SetError("Joystick only has %d axes", joystick->naxes); + state = 0; + } } + SDL_UnlockJoysticks(); + return state; } /* * Get the initial state of an axis control on a joystick */ -SDL_bool -SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state) +SDL_bool SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; - if (axis >= joystick->naxes) { - SDL_SetError("Joystick only has %d axes", joystick->naxes); - return SDL_FALSE; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + + if (axis >= joystick->naxes) { + SDL_SetError("Joystick only has %d axes", joystick->naxes); + retval = SDL_FALSE; + } else { + if (state) { + *state = joystick->axes[axis].initial_value; + } + retval = joystick->axes[axis].has_initial_value; + } } - if (state) { - *state = joystick->axes[axis].initial_value; - } - return joystick->axes[axis].has_initial_value; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -790,14 +851,19 @@ Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) { Uint8 state; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - if (hat < joystick->nhats) { - state = joystick->hats[hat]; - } else { - SDL_SetError("Joystick only has %d hats", joystick->nhats); - state = 0; + if (hat < joystick->nhats) { + state = joystick->hats[hat]; + } else { + SDL_SetError("Joystick only has %d hats", joystick->nhats); + state = 0; + } } + SDL_UnlockJoysticks(); + return state; } @@ -808,21 +874,26 @@ int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) { int retval; - CHECK_JOYSTICK_MAGIC(joystick, -1); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - retval = 0; - if (ball < joystick->nballs) { - if (dx) { - *dx = joystick->balls[ball].dx; + if (ball < joystick->nballs) { + if (dx) { + *dx = joystick->balls[ball].dx; + } + if (dy) { + *dy = joystick->balls[ball].dy; + } + joystick->balls[ball].dx = 0; + joystick->balls[ball].dy = 0; + retval = 0; + } else { + retval = SDL_SetError("Joystick only has %d balls", joystick->nballs); } - if (dy) { - *dy = joystick->balls[ball].dy; - } - joystick->balls[ball].dx = 0; - joystick->balls[ball].dy = 0; - } else { - return SDL_SetError("Joystick only has %d balls", joystick->nballs); } + SDL_UnlockJoysticks(); + return retval; } @@ -833,14 +904,19 @@ Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) { Uint8 state; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - if (button < joystick->nbuttons) { - state = joystick->buttons[button]; - } else { - SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); - state = 0; + if (button < joystick->nbuttons) { + state = joystick->buttons[button]; + } else { + SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); + state = 0; + } } + SDL_UnlockJoysticks(); + return state; } @@ -848,30 +924,43 @@ Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) * Return if the joystick in question is currently attached to the system, * \return SDL_FALSE if not plugged in, SDL_TRUE if still present. */ -SDL_bool -SDL_JoystickGetAttached(SDL_Joystick *joystick) +SDL_bool SDL_JoystickGetAttached(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; - return joystick->attached; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + + retval = joystick->attached; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Get the instance id for this opened joystick */ -SDL_JoystickID -SDL_JoystickInstanceID(SDL_Joystick *joystick) +SDL_JoystickID SDL_JoystickInstanceID(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + SDL_JoystickID retval; - return joystick->instance_id; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->instance_id; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Return the SDL_Joystick associated with an instance id. */ -SDL_Joystick * -SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) +SDL_Joystick *SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) { SDL_Joystick *joystick; @@ -888,8 +977,7 @@ SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) /** * Return the SDL_Joystick associated with a player index. */ -SDL_Joystick * -SDL_JoystickFromPlayerIndex(int player_index) +SDL_Joystick *SDL_JoystickFromPlayerIndex(int player_index) { SDL_JoystickID instance_id; SDL_Joystick *joystick; @@ -908,27 +996,42 @@ SDL_JoystickFromPlayerIndex(int player_index) /* * Get the friendly name of this joystick */ -const char * -SDL_JoystickName(SDL_Joystick *joystick) +const char *SDL_JoystickName(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, NULL); + const char *retval; - return joystick->name; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + retval = joystick->name; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Get the implementation dependent path of this joystick */ -const char * -SDL_JoystickPath(SDL_Joystick *joystick) +const char *SDL_JoystickPath(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, NULL); + const char *retval; - if (!joystick->path) { - SDL_Unsupported(); - return NULL; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + if (joystick->path) { + retval = joystick->path; + } else { + SDL_Unsupported(); + retval = NULL; + } } - return joystick->path; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -936,15 +1039,17 @@ SDL_JoystickPath(SDL_Joystick *joystick) */ int SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick) { - int player_index; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); - player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = SDL_GetPlayerIndexForJoystickID(joystick->instance_id); + } SDL_UnlockJoysticks(); - return player_index; + return retval; } /** @@ -952,175 +1057,178 @@ int SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick) */ void SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index) { - CHECK_JOYSTICK_MAGIC(joystick, ); - SDL_LockJoysticks(); - SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id); + { + CHECK_JOYSTICK_MAGIC(joystick, ); + + SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id); + } SDL_UnlockJoysticks(); } int SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) { - int result; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); - if (low_frequency_rumble == joystick->low_frequency_rumble && - high_frequency_rumble == joystick->high_frequency_rumble) { - /* Just update the expiration */ - result = 0; - } else { - result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble); - joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS; - if (!joystick->rumble_resend) { - joystick->rumble_resend = 1; - } - } + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - if (result == 0) { - joystick->low_frequency_rumble = low_frequency_rumble; - joystick->high_frequency_rumble = high_frequency_rumble; - - if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) { - joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); - if (!joystick->rumble_expiration) { - joystick->rumble_expiration = 1; - } + if (low_frequency_rumble == joystick->low_frequency_rumble && + high_frequency_rumble == joystick->high_frequency_rumble) { + /* Just update the expiration */ + retval = 0; } else { - joystick->rumble_expiration = 0; - joystick->rumble_resend = 0; + retval = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble); + joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS; + if (!joystick->rumble_resend) { + joystick->rumble_resend = 1; + } + } + + if (retval == 0) { + joystick->low_frequency_rumble = low_frequency_rumble; + joystick->high_frequency_rumble = high_frequency_rumble; + + if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) { + joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); + if (!joystick->rumble_expiration) { + joystick->rumble_expiration = 1; + } + } else { + joystick->rumble_expiration = 0; + joystick->rumble_resend = 0; + } } } SDL_UnlockJoysticks(); - return result; + return retval; } int SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms) { - int result; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); - if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) { - /* Just update the expiration */ - result = 0; - } else { - result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble); - } + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - if (result == 0) { - joystick->left_trigger_rumble = left_rumble; - joystick->right_trigger_rumble = right_rumble; - - if ((left_rumble || right_rumble) && duration_ms) { - joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); - if (!joystick->trigger_rumble_expiration) { - joystick->trigger_rumble_expiration = 1; - } + if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) { + /* Just update the expiration */ + retval = 0; } else { - joystick->trigger_rumble_expiration = 0; + retval = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble); + } + + if (retval == 0) { + joystick->left_trigger_rumble = left_rumble; + joystick->right_trigger_rumble = right_rumble; + + if ((left_rumble || right_rumble) && duration_ms) { + joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); + if (!joystick->trigger_rumble_expiration) { + joystick->trigger_rumble_expiration = 1; + } + } else { + joystick->trigger_rumble_expiration = 0; + } } } SDL_UnlockJoysticks(); - return result; + return retval; } -SDL_bool -SDL_JoystickHasLED(SDL_Joystick *joystick) +SDL_bool SDL_JoystickHasLED(SDL_Joystick *joystick) { - SDL_bool result; - - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0; - + retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0; + } SDL_UnlockJoysticks(); - return result; + return retval; } -SDL_bool -SDL_JoystickHasRumble(SDL_Joystick *joystick) +SDL_bool SDL_JoystickHasRumble(SDL_Joystick *joystick) { - SDL_bool result; - - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0; - + retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0; + } SDL_UnlockJoysticks(); - return result; + return retval; } -SDL_bool -SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick) +SDL_bool SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick) { - SDL_bool result; - - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0; - + retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0; + } SDL_UnlockJoysticks(); - return result; + return retval; } int SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { - int result; + int retval; SDL_bool isfreshvalue; - CHECK_JOYSTICK_MAGIC(joystick, -1); - SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - isfreshvalue = red != joystick->led_red || - green != joystick->led_green || - blue != joystick->led_blue; + isfreshvalue = red != joystick->led_red || + green != joystick->led_green || + blue != joystick->led_blue; - if (isfreshvalue || SDL_TICKS_PASSED(SDL_GetTicks(), joystick->led_expiration)) { - result = joystick->driver->SetLED(joystick, red, green, blue); - joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS; - } else { - /* Avoid spamming the driver */ - result = 0; + if (isfreshvalue || SDL_TICKS_PASSED(SDL_GetTicks(), joystick->led_expiration)) { + retval = joystick->driver->SetLED(joystick, red, green, blue); + joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS; + } else { + /* Avoid spamming the driver */ + retval = 0; + } + + /* Save the LED value regardless of success, so we don't spam the driver */ + joystick->led_red = red; + joystick->led_green = green; + joystick->led_blue = blue; } - - /* Save the LED value regardless of success, so we don't spam the driver */ - joystick->led_red = red; - joystick->led_green = green; - joystick->led_blue = blue; - SDL_UnlockJoysticks(); - return result; + return retval; } int SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) { - int result; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - result = joystick->driver->SendEffect(joystick, data, size); - + retval = joystick->driver->SendEffect(joystick, data, size); + } SDL_UnlockJoysticks(); - return result; + return retval; } /* @@ -1132,60 +1240,60 @@ void SDL_JoystickClose(SDL_Joystick *joystick) SDL_Joystick *joysticklistprev; int i; - CHECK_JOYSTICK_MAGIC(joystick, ); - SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, ); - /* First decrement ref count */ - if (--joystick->ref_count > 0) { - SDL_UnlockJoysticks(); - return; - } - - if (joystick->rumble_expiration) { - SDL_JoystickRumble(joystick, 0, 0, 0); - } - if (joystick->trigger_rumble_expiration) { - SDL_JoystickRumbleTriggers(joystick, 0, 0, 0); - } - - joystick->driver->Close(joystick); - joystick->hwdata = NULL; - joystick->magic = NULL; - - joysticklist = SDL_joysticks; - joysticklistprev = NULL; - while (joysticklist) { - if (joystick == joysticklist) { - if (joysticklistprev) { - /* unlink this entry */ - joysticklistprev->next = joysticklist->next; - } else { - SDL_joysticks = joystick->next; - } - break; + /* First decrement ref count */ + if (--joystick->ref_count > 0) { + SDL_UnlockJoysticks(); + return; } - joysticklistprev = joysticklist; - joysticklist = joysticklist->next; + + if (joystick->rumble_expiration) { + SDL_JoystickRumble(joystick, 0, 0, 0); + } + if (joystick->trigger_rumble_expiration) { + SDL_JoystickRumbleTriggers(joystick, 0, 0, 0); + } + + joystick->driver->Close(joystick); + joystick->hwdata = NULL; + joystick->magic = NULL; + + joysticklist = SDL_joysticks; + joysticklistprev = NULL; + while (joysticklist) { + if (joystick == joysticklist) { + if (joysticklistprev) { + /* unlink this entry */ + joysticklistprev->next = joysticklist->next; + } else { + SDL_joysticks = joystick->next; + } + break; + } + joysticklistprev = joysticklist; + joysticklist = joysticklist->next; + } + + SDL_free(joystick->name); + SDL_free(joystick->path); + SDL_free(joystick->serial); + + /* Free the data associated with this joystick */ + SDL_free(joystick->axes); + SDL_free(joystick->hats); + SDL_free(joystick->balls); + SDL_free(joystick->buttons); + for (i = 0; i < joystick->ntouchpads; i++) { + SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i]; + SDL_free(touchpad->fingers); + } + SDL_free(joystick->touchpads); + SDL_free(joystick->sensors); + SDL_free(joystick); } - - SDL_free(joystick->name); - SDL_free(joystick->path); - SDL_free(joystick->serial); - - /* Free the data associated with this joystick */ - SDL_free(joystick->axes); - SDL_free(joystick->hats); - SDL_free(joystick->balls); - SDL_free(joystick->buttons); - for (i = 0; i < joystick->ntouchpads; i++) { - SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i]; - SDL_free(touchpad->fingers); - } - SDL_free(joystick->touchpads); - SDL_free(joystick->sensors); - SDL_free(joystick); - SDL_UnlockJoysticks(); } @@ -1249,7 +1357,7 @@ void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers) int ntouchpads; SDL_JoystickTouchpadInfo *touchpads; - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); ntouchpads = joystick->ntouchpads + 1; touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo))); @@ -1276,7 +1384,7 @@ void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, f int nsensors; SDL_JoystickSensorInfo *sensors; - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); nsensors = joystick->nsensors + 1; sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo))); @@ -1396,7 +1504,7 @@ void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick) { int i, j; - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); /* Tell the app that everything is centered/unpressed... */ for (i = 0; i < joystick->naxes; i++) { @@ -1471,8 +1579,6 @@ int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value) SDL_AssertJoysticksLocked(); - CHECK_JOYSTICK_MAGIC(joystick, 0); - /* Make sure we're not getting garbage or duplicate events */ if (axis >= joystick->naxes) { return 0; @@ -1538,8 +1644,6 @@ int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value) SDL_AssertJoysticksLocked(); - CHECK_JOYSTICK_MAGIC(joystick, 0); - /* Make sure we're not getting garbage or duplicate events */ if (hat >= joystick->nhats) { return 0; @@ -1575,15 +1679,12 @@ int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value) return posted; } -int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, - Sint16 xrel, Sint16 yrel) +int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, Sint16 xrel, Sint16 yrel) { int posted; SDL_AssertJoysticksLocked(); - CHECK_JOYSTICK_MAGIC(joystick, 0); - /* Make sure we're not getting garbage events */ if (ball >= joystick->nballs) { return 0; @@ -1620,7 +1721,7 @@ int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) #if !SDL_EVENTS_DISABLED SDL_Event event; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_AssertJoysticksLocked(); switch (state) { case SDL_PRESSED: @@ -1835,8 +1936,7 @@ static int PrefixMatch(const char *a, const char *b) return matchlen; } -char * -SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name) +char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name) { static struct { @@ -1975,8 +2075,7 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c return name; } -SDL_JoystickGUID -SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data) +SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data) { SDL_JoystickGUID guid; Uint16 *guid16 = (Uint16 *)guid.data; @@ -2013,8 +2112,7 @@ SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version return guid; } -SDL_JoystickGUID -SDL_CreateJoystickGUIDForName(const char *name) +SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name) { return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, name, 0, 0); } @@ -2047,8 +2145,7 @@ void SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc) guid16[1] = SDL_SwapLE16(crc); } -SDL_GameControllerType -SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI) +SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI) { SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN; @@ -2143,8 +2240,7 @@ SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const return type; } -SDL_GameControllerType -SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name) +SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name) { SDL_GameControllerType type; Uint16 vendor, product; @@ -2168,15 +2264,13 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam return type; } -SDL_bool -SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_XBoxOneController; } -SDL_bool -SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_MICROSOFT) { if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 || @@ -2189,8 +2283,7 @@ SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_MICROSOFT) { if (product_id == USB_PRODUCT_XBOX_SERIES_X || @@ -2226,8 +2319,7 @@ SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_MICROSOFT) { if (product_id == USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH || @@ -2244,22 +2336,19 @@ SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_PS4Controller; } -SDL_bool -SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_PS5Controller; } -SDL_bool -SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_SONY) { if (product_id == USB_PRODUCT_SONY_DS5_EDGE) { @@ -2269,86 +2358,73 @@ SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchProController || eType == k_eControllerType_SwitchInputOnlyController; } -SDL_bool -SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchInputOnlyController; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyCon(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyCon(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchJoyConLeft || eType == k_eControllerType_SwitchJoyConRight; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConLeft(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConLeft(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchJoyConLeft; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchJoyConRight; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id) { return vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id) { return vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; } -SDL_bool -SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SteamController || eType == k_eControllerType_SteamControllerV2; } -SDL_bool -SDL_IsJoystickXInput(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid) { return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickWGI(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickWGI(SDL_JoystickGUID guid) { return (guid.data[14] == 'w') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid) { return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid) { return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickVirtual(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickVirtual(SDL_JoystickGUID guid) { return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE; } @@ -2791,11 +2867,19 @@ int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id) SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick) { - static SDL_JoystickGUID emptyGUID; + SDL_JoystickGUID retval; - CHECK_JOYSTICK_MAGIC(joystick, emptyGUID); + SDL_LockJoysticks(); + { + static SDL_JoystickGUID emptyGUID; - return joystick->guid; + CHECK_JOYSTICK_MAGIC(joystick, emptyGUID); + + retval = joystick->guid; + } + SDL_UnlockJoysticks(); + + return retval; } Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick) @@ -2827,16 +2911,32 @@ Uint16 SDL_JoystickGetProductVersion(SDL_Joystick *joystick) Uint16 SDL_JoystickGetFirmwareVersion(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, 0); + Uint16 retval; - return joystick->firmware_version; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); + + retval = joystick->firmware_version; + } + SDL_UnlockJoysticks(); + + return retval; } const char *SDL_JoystickGetSerial(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, NULL); + const char *retval; - return joystick->serial; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + retval = joystick->serial; + } + SDL_UnlockJoysticks(); + + return retval; } SDL_JoystickType SDL_JoystickGetType(SDL_Joystick *joystick) @@ -2846,9 +2946,15 @@ SDL_JoystickType SDL_JoystickGetType(SDL_Joystick *joystick) type = SDL_GetJoystickGUIDType(guid); if (type == SDL_JOYSTICK_TYPE_UNKNOWN) { - if (joystick && joystick->is_game_controller) { - type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_TYPE_UNKNOWN); + + if (joystick->is_game_controller) { + type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; + } } + SDL_UnlockJoysticks(); } return type; } @@ -2868,7 +2974,7 @@ SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID) /* update the power level for this joystick */ void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel) { - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); SDL_assert(joystick->ref_count); /* make sure we are calling this only for update, not for initialization */ if (ePowerLevel != joystick->epowerlevel) { @@ -2888,9 +2994,17 @@ void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLe /* return its power level */ SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_POWER_UNKNOWN); + SDL_JoystickPowerLevel retval; - return joystick->epowerlevel; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_POWER_UNKNOWN); + + retval = joystick->epowerlevel; + } + SDL_UnlockJoysticks(); + + return retval; } int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure) @@ -2900,7 +3014,7 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger int posted; Uint32 event_type; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_AssertJoysticksLocked(); if (touchpad < 0 || touchpad >= joystick->ntouchpads) { return 0; @@ -2988,7 +3102,7 @@ int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, Uint6 int i; int posted = 0; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_AssertJoysticksLocked(); /* We ignore events if we don't have keyboard focus */ if (SDL_PrivateJoystickShouldIgnoreEvent()) { diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 71d354236..7b6dca09e 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -49,7 +49,7 @@ extern SDL_bool SDL_JoysticksQuitting(void); extern SDL_bool SDL_JoysticksLocked(void); /* Make sure we currently have the joysticks locked */ -extern void SDL_AssertJoysticksLocked(void); +extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_lock); /* Function to get the next available joystick instance ID */ extern SDL_JoystickID SDL_GetNextJoystickInstanceID(void); diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 8a8312495..4bad9528e 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -67,68 +67,72 @@ typedef struct _SDL_JoystickSensorInfo Uint64 timestamp_us; } SDL_JoystickSensorInfo; +#define _guarded SDL_GUARDED_BY(SDL_joystick_lock) + struct _SDL_Joystick { - const void *magic; + const void *magic _guarded; - SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */ - char *name; /* Joystick name - system dependent */ - char *path; /* Joystick path - system dependent */ - char *serial; /* Joystick serial */ - SDL_JoystickGUID guid; /* Joystick guid */ - Uint16 firmware_version; /* Firmware version, if available */ + SDL_JoystickID instance_id _guarded; /* Device instance, monotonically increasing from 0 */ + char *name _guarded; /* Joystick name - system dependent */ + char *path _guarded; /* Joystick path - system dependent */ + char *serial _guarded; /* Joystick serial */ + SDL_JoystickGUID guid _guarded; /* Joystick guid */ + Uint16 firmware_version _guarded; /* Firmware version, if available */ - int naxes; /* Number of axis controls on the joystick */ - SDL_JoystickAxisInfo *axes; + int naxes _guarded; /* Number of axis controls on the joystick */ + SDL_JoystickAxisInfo *axes _guarded; - int nhats; /* Number of hats on the joystick */ - Uint8 *hats; /* Current hat states */ + int nhats _guarded; /* Number of hats on the joystick */ + Uint8 *hats _guarded; /* Current hat states */ - int nballs; /* Number of trackballs on the joystick */ + int nballs _guarded; /* Number of trackballs on the joystick */ struct balldelta { int dx; int dy; - } *balls; /* Current ball motion deltas */ + } *balls _guarded; /* Current ball motion deltas */ - int nbuttons; /* Number of buttons on the joystick */ - Uint8 *buttons; /* Current button states */ + int nbuttons _guarded; /* Number of buttons on the joystick */ + Uint8 *buttons _guarded; /* Current button states */ - int ntouchpads; /* Number of touchpads on the joystick */ - SDL_JoystickTouchpadInfo *touchpads; /* Current touchpad states */ + int ntouchpads _guarded; /* Number of touchpads on the joystick */ + SDL_JoystickTouchpadInfo *touchpads _guarded; /* Current touchpad states */ - int nsensors; /* Number of sensors on the joystick */ - int nsensors_enabled; - SDL_JoystickSensorInfo *sensors; + int nsensors _guarded; /* Number of sensors on the joystick */ + int nsensors_enabled _guarded; + SDL_JoystickSensorInfo *sensors _guarded; - Uint16 low_frequency_rumble; - Uint16 high_frequency_rumble; - Uint32 rumble_expiration; - Uint32 rumble_resend; + Uint16 low_frequency_rumble _guarded; + Uint16 high_frequency_rumble _guarded; + Uint32 rumble_expiration _guarded; + Uint32 rumble_resend _guarded; - Uint16 left_trigger_rumble; - Uint16 right_trigger_rumble; - Uint32 trigger_rumble_expiration; + Uint16 left_trigger_rumble _guarded; + Uint16 right_trigger_rumble _guarded; + Uint32 trigger_rumble_expiration _guarded; - Uint8 led_red; - Uint8 led_green; - Uint8 led_blue; - Uint32 led_expiration; + Uint8 led_red _guarded; + Uint8 led_green _guarded; + Uint8 led_blue _guarded; + Uint32 led_expiration _guarded; - SDL_bool attached; - SDL_bool is_game_controller; - SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */ - SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */ + SDL_bool attached _guarded; + SDL_bool is_game_controller _guarded; + SDL_bool delayed_guide_button _guarded; /* SDL_TRUE if this device has the guide button event delayed */ + SDL_JoystickPowerLevel epowerlevel _guarded; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */ - struct _SDL_JoystickDriver *driver; + struct _SDL_JoystickDriver *driver _guarded; - struct joystick_hwdata *hwdata; /* Driver dependent information */ + struct joystick_hwdata *hwdata _guarded; /* Driver dependent information */ - int ref_count; /* Reference count for multiple opens */ + int ref_count _guarded; /* Reference count for multiple opens */ - struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */ + struct _SDL_Joystick *next _guarded; /* pointer to next joystick we have allocated */ }; +#undef _guarded + /* Device bus definitions */ #define SDL_HARDWARE_BUS_UNKNOWN 0x00 #define SDL_HARDWARE_BUS_USB 0x03 diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c index a8dbe931e..599a385bb 100644 --- a/src/joystick/hidapi/SDL_hidapi_combined.c +++ b/src/joystick/hidapi/SDL_hidapi_combined.c @@ -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)) { diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 7e6abba73..7b39c73b4 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -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; diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 5c2a7f426..f4e076189 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -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 */ diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index 6c4fcd82b..e5eadbc59 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -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); diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 56c58073d..8834b545f 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -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; diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index b5086a572..66122735a 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -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; } diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c index d109b0e3c..6cd8dd535 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.c +++ b/src/joystick/hidapi/SDL_hidapi_rumble.c @@ -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; } diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.h b/src/joystick/hidapi/SDL_hidapi_rumble.h index bf9f1adba..fea37de20 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.h +++ b/src/joystick/hidapi/SDL_hidapi_rumble.h @@ -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); diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 4fea8a80c..79c44c57e 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -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; diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index 15542a0f2..93af500ef 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -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 */ diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index a7a4acb79..17cc0bd2c 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -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); diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index a287ca09c..1bff6f56f 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -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) { diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 3ec2ec65c..6ca52fb22 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -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); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index df618df96..98a3d4279 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -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); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 10309f09c..d735b121f 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -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) */ diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 1f6f90763..c66d39a83 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -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; } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 3e35997ac..706115887 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -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(); diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 50dd3b51c..4cb84a8fa 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -852,6 +852,8 @@ static int allocate_hatdata(SDL_Joystick *joystick) { int i; + SDL_AssertJoysticksLocked(); + joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(joystick->nhats * sizeof(struct hwdata_hat)); @@ -869,6 +871,8 @@ static int allocate_balldata(SDL_Joystick *joystick) { int i; + SDL_AssertJoysticksLocked(); + joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc(joystick->nballs * sizeof(struct hwdata_ball)); @@ -925,6 +929,8 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd) SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE); SDL_bool use_hat_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_HAT_DEADZONES, SDL_TRUE); + SDL_AssertJoysticksLocked(); + /* See if this device uses the new unified event API */ if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && @@ -1132,6 +1138,8 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd) on error. Returns -1 on error, 0 on success. */ static int PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item) { + SDL_AssertJoysticksLocked(); + joystick->hwdata->item = item; joystick->hwdata->guid = item->guid; joystick->hwdata->effect.id = -1; @@ -1180,6 +1188,8 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) { SDL_joylist_item *item = JoystickByDevIndex(device_index); + SDL_AssertJoysticksLocked(); + if (item == NULL) { return SDL_SetError("No such device"); } @@ -1210,6 +1220,8 @@ static int LINUX_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rum { struct input_event event; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->ff_rumble) { struct ff_effect *effect = &joystick->hwdata->effect; @@ -1256,6 +1268,8 @@ static Uint32 LINUX_JoystickGetCapabilities(SDL_Joystick *joystick) { Uint32 result = 0; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) { result |= SDL_JOYCAP_RUMBLE; } @@ -1280,7 +1294,7 @@ static int LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enab static void HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value) { - const int hatnum = stick->hwdata->hats_indices[hatidx]; + int hatnum; struct hwdata_hat *the_hat; struct hat_axis_correct *correct; const Uint8 position_map[3][3] = { @@ -1289,6 +1303,9 @@ static void HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value) { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } }; + SDL_AssertJoysticksLocked(); + + hatnum = stick->hwdata->hats_indices[hatidx]; the_hat = &stick->hwdata->hats[hatnum]; correct = &stick->hwdata->hat_correct[hatidx]; /* Hopefully we detected any analog axes and left them as is rather than trying @@ -1326,6 +1343,8 @@ static void HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value) static void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) { + SDL_AssertJoysticksLocked(); + stick->hwdata->balls[ball].axis[axis] += value; } @@ -1333,6 +1352,8 @@ static int AxisCorrect(SDL_Joystick *joystick, int which, int value) { struct axis_correct *correct; + SDL_AssertJoysticksLocked(); + correct = &joystick->hwdata->abs_correct[which]; if (correct->minimum != correct->maximum) { if (correct->use_deadzones) { @@ -1368,6 +1389,8 @@ static void PollAllValues(SDL_Joystick *joystick) unsigned long keyinfo[NBITS(KEY_MAX)]; int i; + SDL_AssertJoysticksLocked(); + /* Poll all axis */ for (i = ABS_X; i < ABS_MAX; i++) { /* We don't need to test for digital hats here, they won't have has_abs[] set */ @@ -1424,6 +1447,8 @@ static void HandleInputEvents(SDL_Joystick *joystick) struct input_event events[32]; int i, len, code, hat_index; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->fresh) { PollAllValues(joystick); joystick->hwdata->fresh = SDL_FALSE; @@ -1515,6 +1540,8 @@ static void HandleClassicEvents(SDL_Joystick *joystick) struct js_event events[32]; int i, len, code, hat_index; + SDL_AssertJoysticksLocked(); + joystick->hwdata->fresh = SDL_FALSE; while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) { len /= sizeof(events[0]); @@ -1557,6 +1584,8 @@ static void LINUX_JoystickUpdate(SDL_Joystick *joystick) { int i; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->m_bSteamController) { SDL_UpdateSteamController(joystick); return; @@ -1585,6 +1614,8 @@ static void LINUX_JoystickUpdate(SDL_Joystick *joystick) /* Function to close a joystick after use */ static void LINUX_JoystickClose(SDL_Joystick *joystick) { + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { if (joystick->hwdata->effect.id >= 0) { ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id); @@ -1645,6 +1676,8 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap SDL_joylist_item *item = JoystickByDevIndex(device_index); unsigned int mapped; + SDL_AssertJoysticksLocked(); + if (item->checked_mapping) { if (item->mapping) { SDL_memcpy(out, item->mapping, sizeof(*out)); diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index a6c9140fb..cb165b068 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -29,32 +29,36 @@ #include "../SDL_sysjoystick.h" #include "../SDL_joystick_c.h" -static joystick_hwdata *g_VJoys = NULL; +static joystick_hwdata *g_VJoys SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static joystick_hwdata *VIRTUAL_HWDataForIndex(int device_index) { - joystick_hwdata *vjoy = g_VJoys; - while (vjoy) { + joystick_hwdata *vjoy; + + SDL_AssertJoysticksLocked(); + + for (vjoy = g_VJoys; vjoy; vjoy = vjoy->next) { if (device_index == 0) { break; } --device_index; - vjoy = vjoy->next; } return vjoy; } static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata) { - joystick_hwdata *cur = g_VJoys; + joystick_hwdata *cur; joystick_hwdata *prev = NULL; + SDL_AssertJoysticksLocked(); + if (hwdata == NULL) { return; } /* Remove hwdata from SDL-global list */ - while (cur) { + for (cur = g_VJoys; cur; prev = cur, cur = cur->next) { if (hwdata == cur) { if (prev) { prev->next = cur->next; @@ -63,8 +67,6 @@ static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata) } break; } - prev = cur; - cur = cur->next; } if (hwdata->joystick) { @@ -98,6 +100,8 @@ int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc) int axis_triggerleft = -1; int axis_triggerright = -1; + SDL_AssertJoysticksLocked(); + if (desc == NULL) { return SDL_InvalidParamError("desc"); } @@ -329,11 +333,13 @@ static int VIRTUAL_JoystickInit(void) static int VIRTUAL_JoystickGetCount(void) { + joystick_hwdata *cur; int count = 0; - joystick_hwdata *cur = g_VJoys; - while (cur) { + + SDL_AssertJoysticksLocked(); + + for (cur = g_VJoys; cur; cur = cur->next) { ++count; - cur = cur->next; } return count; } @@ -392,7 +398,11 @@ static SDL_JoystickID VIRTUAL_JoystickGetDeviceInstanceID(int device_index) static int VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) { - joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); + joystick_hwdata *hwdata; + + SDL_AssertJoysticksLocked(); + + hwdata = VIRTUAL_HWDataForIndex(device_index); if (hwdata == NULL) { return SDL_SetError("No such device"); } @@ -409,6 +419,8 @@ static int VIRTUAL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_r { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.Rumble) { @@ -427,6 +439,8 @@ static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.RumbleTriggers) { @@ -443,9 +457,12 @@ static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru static Uint32 VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick) { - joystick_hwdata *hwdata = joystick->hwdata; + joystick_hwdata *hwdata; Uint32 caps = 0; + SDL_AssertJoysticksLocked(); + + hwdata = joystick->hwdata; if (hwdata) { if (hwdata->desc.Rumble) { caps |= SDL_JOYCAP_RUMBLE; @@ -464,6 +481,8 @@ static int VIRTUAL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.SetLED) { @@ -482,6 +501,8 @@ static int VIRTUAL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.SendEffect) { @@ -506,6 +527,8 @@ static void VIRTUAL_JoystickUpdate(SDL_Joystick *joystick) joystick_hwdata *hwdata; int i; + SDL_AssertJoysticksLocked(); + if (joystick == NULL) { return; } @@ -532,6 +555,8 @@ static void VIRTUAL_JoystickUpdate(SDL_Joystick *joystick) static void VIRTUAL_JoystickClose(SDL_Joystick *joystick) { + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; hwdata->joystick = NULL; @@ -541,6 +566,8 @@ static void VIRTUAL_JoystickClose(SDL_Joystick *joystick) static void VIRTUAL_JoystickQuit(void) { + SDL_AssertJoysticksLocked(); + while (g_VJoys) { VIRTUAL_FreeHWData(g_VJoys); } diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 2b73f1ced..e5cfeed1f 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -51,23 +51,19 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = { &SDL_DUMMY_SensorDriver #endif }; -static SDL_Sensor *SDL_sensors = NULL; -static SDL_bool SDL_updating_sensor = SDL_FALSE; static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */ -static SDL_atomic_t SDL_next_sensor_instance_id; +static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL; +static SDL_atomic_t SDL_next_sensor_instance_id SDL_GUARDED_BY(SDL_sensor_lock); +static SDL_bool SDL_updating_sensor SDL_GUARDED_BY(SDL_sensor_lock) = SDL_FALSE; -void SDL_LockSensors(void) +void SDL_LockSensors(void) SDL_ACQUIRE(SDL_sensor_lock) { - if (SDL_sensor_lock) { - SDL_LockMutex(SDL_sensor_lock); - } + SDL_LockMutex(SDL_sensor_lock); } -void SDL_UnlockSensors(void) +void SDL_UnlockSensors(void) SDL_RELEASE(SDL_sensor_lock) { - if (SDL_sensor_lock) { - SDL_UnlockMutex(SDL_sensor_lock); - } + SDL_UnlockMutex(SDL_sensor_lock); } int SDL_SensorInit(void) @@ -145,8 +141,7 @@ static SDL_bool SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver * /* * Get the implementation dependent name of a sensor */ -const char * -SDL_SensorGetDeviceName(int device_index) +const char *SDL_SensorGetDeviceName(int device_index) { SDL_SensorDriver *driver; const char *name = NULL; @@ -161,8 +156,7 @@ SDL_SensorGetDeviceName(int device_index) return name; } -SDL_SensorType -SDL_SensorGetDeviceType(int device_index) +SDL_SensorType SDL_SensorGetDeviceType(int device_index) { SDL_SensorDriver *driver; SDL_SensorType type = SDL_SENSOR_INVALID; @@ -190,8 +184,7 @@ int SDL_SensorGetDeviceNonPortableType(int device_index) return type; } -SDL_SensorID -SDL_SensorGetDeviceInstanceID(int device_index) +SDL_SensorID SDL_SensorGetDeviceInstanceID(int device_index) { SDL_SensorDriver *driver; SDL_SensorID instance_id = -1; @@ -212,8 +205,7 @@ SDL_SensorGetDeviceInstanceID(int device_index) * * This function returns a sensor identifier, or NULL if an error occurred. */ -SDL_Sensor * -SDL_SensorOpen(int device_index) +SDL_Sensor *SDL_SensorOpen(int device_index) { SDL_SensorDriver *driver; SDL_SensorID instance_id; @@ -284,8 +276,7 @@ SDL_SensorOpen(int device_index) /* * Find the SDL_Sensor that owns this instance id */ -SDL_Sensor * -SDL_SensorFromInstanceID(SDL_SensorID instance_id) +SDL_Sensor *SDL_SensorFromInstanceID(SDL_SensorID instance_id) { SDL_Sensor *sensor; @@ -319,8 +310,7 @@ static int SDL_PrivateSensorValid(SDL_Sensor *sensor) /* * Get the friendly name of this sensor */ -const char * -SDL_SensorGetName(SDL_Sensor *sensor) +const char *SDL_SensorGetName(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return NULL; @@ -332,8 +322,7 @@ SDL_SensorGetName(SDL_Sensor *sensor) /* * Get the type of this sensor */ -SDL_SensorType -SDL_SensorGetType(SDL_Sensor *sensor) +SDL_SensorType SDL_SensorGetType(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return SDL_SENSOR_INVALID; @@ -357,8 +346,7 @@ int SDL_SensorGetNonPortableType(SDL_Sensor *sensor) /* * Get the instance id for this opened sensor */ -SDL_SensorID -SDL_SensorGetInstanceID(SDL_Sensor *sensor) +SDL_SensorID SDL_SensorGetInstanceID(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return -1; @@ -448,11 +436,11 @@ void SDL_SensorQuit(void) { int i; + SDL_LockSensors(); + /* Make sure we're not getting called in the middle of updating sensors */ SDL_assert(!SDL_updating_sensor); - SDL_LockSensors(); - /* Stop the event polling */ while (SDL_sensors) { SDL_sensors->ref_count = 1; @@ -525,15 +513,10 @@ void SDL_SensorUpdate(void) SDL_updating_sensor = SDL_TRUE; - /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */ - SDL_UnlockSensors(); - for (sensor = SDL_sensors; sensor; sensor = sensor->next) { sensor->driver->Update(sensor); } - SDL_LockSensors(); - SDL_updating_sensor = SDL_FALSE; /* If any sensors were closed while updating, free them here */ diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index dce32191f..cda718319 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -71,7 +71,7 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; @@ -79,7 +79,7 @@ int SDL_LockMutex(SDL_mutex *mutex) SDL_threadID this_thread; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = SDL_ThreadID(); @@ -109,7 +109,7 @@ int SDL_TryLockMutex(SDL_mutex *mutex) SDL_threadID this_thread; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = SDL_ThreadID(); @@ -132,13 +132,13 @@ int SDL_TryLockMutex(SDL_mutex *mutex) } /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; #else if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } /* If we don't own the mutex, we can't unlock it */ diff --git a/src/thread/n3ds/SDL_sysmutex.c b/src/thread/n3ds/SDL_sysmutex.c index 1a4063d97..63b4d35ec 100644 --- a/src/thread/n3ds/SDL_sysmutex.c +++ b/src/thread/n3ds/SDL_sysmutex.c @@ -51,10 +51,10 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_SetError("Passed a NULL mutex"); + return 0; } RecursiveLock_Lock(&mutex->lock); @@ -66,17 +66,17 @@ int SDL_LockMutex(SDL_mutex *mutex) int SDL_TryLockMutex(SDL_mutex *mutex) { if (mutex == NULL) { - return SDL_SetError("Passed a NULL mutex"); + return 0; } return RecursiveLock_TryLock(&mutex->lock); } /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_SetError("Passed a NULL mutex"); + return 0; } RecursiveLock_Unlock(&mutex->lock); diff --git a/src/thread/ngage/SDL_sysmutex.cpp b/src/thread/ngage/SDL_sysmutex.cpp index 0983f71af..68879382d 100644 --- a/src/thread/ngage/SDL_sysmutex.cpp +++ b/src/thread/ngage/SDL_sysmutex.cpp @@ -68,27 +68,11 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } } -/* Try to lock the mutex */ -#if 0 -int -SDL_TryLockMutex(SDL_mutex * mutex) -{ - if (mutex == NULL) - { - SDL_SetError("Passed a NULL mutex."); - return -1; - } - - // Not yet implemented. - return 0; -} -#endif - /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } RMutex rmutex; @@ -98,11 +82,26 @@ int SDL_LockMutex(SDL_mutex *mutex) return 0; } +/* Try to lock the mutex */ +#if 0 +int +SDL_TryLockMutex(SDL_mutex *mutex) +{ + if (mutex == NULL) + { + return 0; + } + + // Not yet implemented. + return 0; +} +#endif + /* Unlock the mutex */ -int SDL_UnlockMutex(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } RMutex rmutex; diff --git a/src/thread/os2/SDL_sysmutex.c b/src/thread/os2/SDL_sysmutex.c index d3fc7a3bd..f1e7049f6 100644 --- a/src/thread/os2/SDL_sysmutex.c +++ b/src/thread/os2/SDL_sysmutex.c @@ -67,13 +67,13 @@ SDL_DestroyMutex(SDL_mutex * mutex) /* Lock the mutex */ int -SDL_LockMutex(SDL_mutex * mutex) +SDL_LockMutex(SDL_mutex * mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { ULONG ulRC; HMTX hMtx = (HMTX)mutex; if (hMtx == NULLHANDLE) - return SDL_InvalidParamError("mutex"); + return 0; ulRC = DosRequestMutexSem(hMtx, SEM_INDEFINITE_WAIT); if (ulRC != NO_ERROR) { @@ -92,7 +92,7 @@ SDL_TryLockMutex(SDL_mutex * mutex) HMTX hMtx = (HMTX)mutex; if (hMtx == NULLHANDLE) - return SDL_InvalidParamError("mutex"); + return 0; ulRC = DosRequestMutexSem(hMtx, SEM_IMMEDIATE_RETURN); @@ -109,13 +109,13 @@ SDL_TryLockMutex(SDL_mutex * mutex) /* Unlock the mutex */ int -SDL_UnlockMutex(SDL_mutex * mutex) +SDL_UnlockMutex(SDL_mutex * mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { ULONG ulRC; HMTX hMtx = (HMTX)mutex; if (hMtx == NULLHANDLE) - return SDL_InvalidParamError("mutex"); + return 0; ulRC = DosReleaseMutexSem(hMtx); if (ulRC != NO_ERROR) diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index 5f3a7f27d..cf52deb96 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -73,6 +73,27 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } } +/* Lock the mutex */ +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +{ +#if SDL_THREADS_DISABLED + return 0; +#else + SceInt32 res = 0; + + if (mutex == NULL) { + return 0; + } + + res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); + if (res != SCE_KERNEL_ERROR_OK) { + return SDL_SetError("Error trying to lock mutex: %lx", res); + } + + return 0; +#endif /* SDL_THREADS_DISABLED */ +} + /* Try to lock the mutex */ int SDL_TryLockMutex(SDL_mutex *mutex) { @@ -80,8 +101,9 @@ int SDL_TryLockMutex(SDL_mutex *mutex) return 0; #else SceInt32 res = 0; + if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelTryLockLwMutex(&mutex->lock, 1); @@ -101,28 +123,8 @@ int SDL_TryLockMutex(SDL_mutex *mutex) #endif /* SDL_THREADS_DISABLED */ } -/* Lock the mutex */ -int SDL_mutexP(SDL_mutex *mutex) -{ -#if SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); - } - - res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); - if (res != SCE_KERNEL_ERROR_OK) { - return SDL_SetError("Error trying to lock mutex: %lx", res); - } - - return 0; -#endif /* SDL_THREADS_DISABLED */ -} - /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; @@ -130,7 +132,7 @@ int SDL_mutexV(SDL_mutex *mutex) SceInt32 res = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelUnlockLwMutex(&mutex->lock, 1); @@ -141,6 +143,7 @@ int SDL_mutexV(SDL_mutex *mutex) return 0; #endif /* SDL_THREADS_DISABLED */ } + #endif /* SDL_THREAD_PSP */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index c89c095ca..75ee73205 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -76,14 +76,14 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if FAKE_RECURSIVE_MUTEX pthread_t this_thread; #endif if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } #if FAKE_RECURSIVE_MUTEX @@ -119,7 +119,7 @@ int SDL_TryLockMutex(SDL_mutex *mutex) #endif if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } retval = 0; @@ -155,10 +155,10 @@ int SDL_TryLockMutex(SDL_mutex *mutex) return retval; } -int SDL_UnlockMutex(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } #if FAKE_RECURSIVE_MUTEX diff --git a/src/thread/stdcpp/SDL_sysmutex.cpp b/src/thread/stdcpp/SDL_sysmutex.cpp index 0113e67aa..0c170195f 100644 --- a/src/thread/stdcpp/SDL_sysmutex.cpp +++ b/src/thread/stdcpp/SDL_sysmutex.cpp @@ -56,12 +56,12 @@ SDL_DestroyMutex(SDL_mutex *mutex) } } -/* Lock the semaphore */ +/* Lock the mutex */ extern "C" int -SDL_mutexP(SDL_mutex *mutex) +SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } try { @@ -76,8 +76,9 @@ SDL_mutexP(SDL_mutex *mutex) int SDL_TryLockMutex(SDL_mutex *mutex) { int retval = 0; + if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } if (mutex->cpp_mutex.try_lock() == false) { @@ -88,10 +89,10 @@ int SDL_TryLockMutex(SDL_mutex *mutex) /* Unlock the mutex */ extern "C" int -SDL_mutexV(SDL_mutex *mutex) +SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } mutex->cpp_mutex.unlock(); diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c index 4fbd4b463..460f43bbf 100644 --- a/src/thread/vita/SDL_sysmutex.c +++ b/src/thread/vita/SDL_sysmutex.c @@ -69,6 +69,27 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } } +/* Lock the mutex */ +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +{ +#if SDL_THREADS_DISABLED + return 0; +#else + SceInt32 res = 0; + + if (mutex == NULL) { + return 0; + } + + res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); + if (res != SCE_KERNEL_OK) { + return SDL_SetError("Error trying to lock mutex: %x", res); + } + + return 0; +#endif /* SDL_THREADS_DISABLED */ +} + /* Try to lock the mutex */ int SDL_TryLockMutex(SDL_mutex *mutex) { @@ -76,8 +97,9 @@ int SDL_TryLockMutex(SDL_mutex *mutex) return 0; #else SceInt32 res = 0; + if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelTryLockLwMutex(&mutex->lock, 1); @@ -97,28 +119,8 @@ int SDL_TryLockMutex(SDL_mutex *mutex) #endif /* SDL_THREADS_DISABLED */ } -/* Lock the mutex */ -int SDL_mutexP(SDL_mutex *mutex) -{ -#if SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); - } - - res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); - if (res != SCE_KERNEL_OK) { - return SDL_SetError("Error trying to lock mutex: %x", res); - } - - return 0; -#endif /* SDL_THREADS_DISABLED */ -} - /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; @@ -126,7 +128,7 @@ int SDL_mutexV(SDL_mutex *mutex) SceInt32 res = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelUnlockLwMutex(&mutex->lock, 1); diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index c995244de..b3c933cb1 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -77,13 +77,13 @@ static void SDL_DestroyMutex_srw(SDL_mutex *mutex) } } -static int SDL_LockMutex_srw(SDL_mutex *_mutex) +static int SDL_LockMutex_srw(SDL_mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; DWORD this_thread; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = GetCurrentThreadId(); @@ -109,7 +109,7 @@ static int SDL_TryLockMutex_srw(SDL_mutex *_mutex) int retval = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = GetCurrentThreadId(); @@ -127,12 +127,12 @@ static int SDL_TryLockMutex_srw(SDL_mutex *_mutex) return retval; } -static int SDL_UnlockMutex_srw(SDL_mutex *_mutex) +static int SDL_UnlockMutex_srw(SDL_mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } if (mutex->owner == GetCurrentThreadId()) { @@ -192,11 +192,11 @@ static void SDL_DestroyMutex_cs(SDL_mutex *mutex_) } /* Lock the mutex */ -static int SDL_LockMutex_cs(SDL_mutex *mutex_) +static int SDL_LockMutex_cs(SDL_mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } EnterCriticalSection(&mutex->cs); @@ -209,7 +209,7 @@ static int SDL_TryLockMutex_cs(SDL_mutex *mutex_) SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; int retval = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } if (TryEnterCriticalSection(&mutex->cs) == 0) { @@ -219,11 +219,11 @@ static int SDL_TryLockMutex_cs(SDL_mutex *mutex_) } /* Unlock the mutex */ -static int SDL_UnlockMutex_cs(SDL_mutex *mutex_) +static int SDL_UnlockMutex_cs(SDL_mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } LeaveCriticalSection(&mutex->cs);