From d59caffe2c8e80aa9d38574fd17974ec5cf05d2b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 13 Dec 2022 14:03:40 -0800 Subject: [PATCH] Added support for clang thread-safety analysis The annotations have been added to SDL_mutex.h and have been made public so applications can enable this for their own code. Clang assumes that locking and unlocking can't fail, but SDL has the concept of a NULL mutex, so the mutex functions have been changed not to report errors if a mutex hasn't been initialized. We do have mutexes that might be accessed when they are NULL, notably in the event system, so this is an important change. This commit cleans up a bunch of rare race conditions in the joystick and game controller code so now everything should be completely protected by the joystick lock. To test this, change the compiler to "clang -Wthread-safety -Werror=thread-safety -DSDL_THREAD_SAFETY_ANALYSIS" --- include/SDL_joystick.h | 8 +- include/SDL_mutex.h | 80 +- src/SDL_assert.c | 6 +- src/SDL_log.c | 10 +- src/audio/SDL_audio.c | 4 +- src/dynapi/SDL_dynapi.h | 2 +- src/events/SDL_events.c | 195 ++-- src/haptic/SDL_haptic.c | 92 +- src/haptic/linux/SDL_syshaptic.c | 6 + src/joystick/SDL_gamecontroller.c | 1023 ++++++++++++-------- src/joystick/SDL_joystick.c | 844 +++++++++------- src/joystick/SDL_joystick_c.h | 2 +- src/joystick/SDL_sysjoystick.h | 82 +- src/joystick/hidapi/SDL_hidapi_combined.c | 2 + src/joystick/hidapi/SDL_hidapi_gamecube.c | 7 + src/joystick/hidapi/SDL_hidapi_luna.c | 2 + src/joystick/hidapi/SDL_hidapi_ps3.c | 4 + src/joystick/hidapi/SDL_hidapi_ps4.c | 2 + src/joystick/hidapi/SDL_hidapi_ps5.c | 4 +- src/joystick/hidapi/SDL_hidapi_rumble.c | 31 +- src/joystick/hidapi/SDL_hidapi_rumble.h | 11 +- src/joystick/hidapi/SDL_hidapi_shield.c | 4 +- src/joystick/hidapi/SDL_hidapi_stadia.c | 2 + src/joystick/hidapi/SDL_hidapi_steam.c | 2 + src/joystick/hidapi/SDL_hidapi_switch.c | 6 +- src/joystick/hidapi/SDL_hidapi_wii.c | 4 +- src/joystick/hidapi/SDL_hidapi_xbox360.c | 2 + src/joystick/hidapi/SDL_hidapi_xbox360w.c | 2 + src/joystick/hidapi/SDL_hidapi_xboxone.c | 10 +- src/joystick/hidapi/SDL_hidapijoystick.c | 44 +- src/joystick/linux/SDL_sysjoystick.c | 35 +- src/joystick/virtual/SDL_virtualjoystick.c | 53 +- src/sensor/SDL_sensor.c | 51 +- src/thread/generic/SDL_sysmutex.c | 10 +- src/thread/n3ds/SDL_sysmutex.c | 10 +- src/thread/ngage/SDL_sysmutex.cpp | 39 +- src/thread/os2/SDL_sysmutex.c | 10 +- src/thread/psp/SDL_sysmutex.c | 49 +- src/thread/pthread/SDL_sysmutex.c | 10 +- src/thread/stdcpp/SDL_sysmutex.cpp | 13 +- src/thread/vita/SDL_sysmutex.c | 48 +- src/thread/windows/SDL_sysmutex.c | 20 +- 42 files changed, 1667 insertions(+), 1174 deletions(-) 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);