From 0e4baf1c4eb3d18b248f1b5b28ed0864026b7872 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 30 Aug 2022 12:39:23 -0700 Subject: [PATCH] Don't crash if SDL functions are passed a closed joystick or gamecontroller --- include/SDL_joystick.h | 4 +- src/joystick/SDL_gamecontroller.c | 207 +++++++++++++++++++++++------- src/joystick/SDL_joystick.c | 186 +++++++++++++-------------- src/joystick/SDL_sysjoystick.h | 2 + 4 files changed, 257 insertions(+), 142 deletions(-) diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index 4c2e50a08..d6531699e 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -126,8 +126,8 @@ typedef enum * * As of SDL 2.26.0, you can take the joystick lock around reinitializing the * joystick subsystem, to prevent other threads from seeing joysticks in an - * uninitialized state. However, all open joysticks will be closed and calling - * SDL functions using them will potentially cause a crash. + * uninitialized state. However, all open joysticks will be closed and SDL + * functions called with them will fail. * * \since This function is available since SDL 2.0.7. */ diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 79e8a4fd1..14fae84d4 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -107,10 +107,13 @@ static SDL_JoystickGUID s_zeroGUID; static ControllerMapping_t *s_pSupportedControllers = NULL; static ControllerMapping_t *s_pDefaultMapping = NULL; static ControllerMapping_t *s_pXInputMapping = NULL; +static char gamecontroller_magic; /* The SDL game controller structure */ struct _SDL_GameController { + const void *magic; + SDL_Joystick *joystick; /* underlying joystick device */ int ref_count; @@ -125,6 +128,13 @@ struct _SDL_GameController }; +#define CHECK_GAMECONTROLLER_MAGIC(gamecontroller, retval) \ + if (!gamecontroller || gamecontroller->magic != &gamecontroller_magic || \ + !SDL_PrivateJoystickValid(gamecontroller->joystick)) { \ + SDL_InvalidParamError("gamecontroller"); \ + return retval; \ + } + typedef struct { int num_entries; @@ -222,9 +232,12 @@ static void ResetOutput(SDL_GameController *gamecontroller, SDL_ExtendedGameCont static void HandleJoystickAxis(SDL_GameController *gamecontroller, int axis, int value) { int i; - SDL_ExtendedGameControllerBind *last_match = gamecontroller->last_match_axis[axis]; + SDL_ExtendedGameControllerBind *last_match; SDL_ExtendedGameControllerBind *match = NULL; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + + last_match = gamecontroller->last_match_axis[axis]; for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS && @@ -275,6 +288,8 @@ static void HandleJoystickButton(SDL_GameController *gamecontroller, int button, { int i; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON && @@ -293,9 +308,12 @@ static void HandleJoystickButton(SDL_GameController *gamecontroller, int button, static void HandleJoystickHat(SDL_GameController *gamecontroller, int hat, Uint8 value) { int i; - Uint8 last_mask = gamecontroller->last_hat_mask[hat]; - Uint8 changed_mask = (last_mask ^ value); + Uint8 last_mask, changed_mask; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + + last_mask = gamecontroller->last_hat_mask[hat]; + changed_mask = (last_mask ^ value); for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT && hat == binding->input.hat.hat) { @@ -327,6 +345,8 @@ 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); @@ -850,6 +870,8 @@ static void SDL_PrivateGameControllerParseElement(SDL_GameController *gamecontro char half_axis_input = 0; char half_axis_output = 0; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + if (*szGameButton == '+' || *szGameButton == '-') { half_axis_output = *szGameButton++; } @@ -945,6 +967,8 @@ SDL_PrivateGameControllerParseControllerConfigString(SDL_GameController *gamecon int i = 0; const char *pchPos = pchString; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_zeroa(szGameButton); SDL_zeroa(szJoystickButton); @@ -992,6 +1016,8 @@ static void SDL_PrivateLoadButtonMapping(SDL_GameController *gamecontroller, con { int i; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + gamecontroller->name = pchName; gamecontroller->num_bindings = 0; if (gamecontroller->joystick->naxes) { @@ -1679,9 +1705,7 @@ SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid) char * SDL_GameControllerMapping(SDL_GameController *gamecontroller) { - if (!gamecontroller) { - return NULL; - } + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); return SDL_GameControllerMappingForGUID(gamecontroller->joystick->guid); } @@ -2001,6 +2025,7 @@ SDL_GameControllerOpen(int device_index) SDL_UnlockJoysticks(); return NULL; } + gamecontroller->magic = &gamecontroller_magic; gamecontroller->joystick = SDL_JoystickOpen(device_index); if (!gamecontroller->joystick) { @@ -2060,7 +2085,11 @@ SDL_GameControllerUpdate(void) SDL_bool SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { - SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForAxis(gamecontroller, axis); + SDL_GameControllerButtonBind bind; + + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + + bind = SDL_GameControllerGetBindForAxis(gamecontroller, axis); return (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE; } @@ -2072,8 +2101,7 @@ SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameController { int i; - if (!gamecontroller) - return 0; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; @@ -2129,7 +2157,11 @@ SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameController SDL_bool SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { - SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForButton(gamecontroller, button); + SDL_GameControllerButtonBind bind; + + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + + bind = SDL_GameControllerGetBindForButton(gamecontroller, button); return (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE; } @@ -2141,8 +2173,7 @@ SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameControll { int i; - if (!gamecontroller) - return 0; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; @@ -2267,7 +2298,7 @@ int SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_S int i; if (!joystick) { - return SDL_InvalidParamError("gamecontroller"); + return -1; } for (i = 0; i < joystick->nsensors; ++i) { @@ -2352,7 +2383,7 @@ SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorTy int i; if (!joystick) { - return SDL_InvalidParamError("gamecontroller"); + return -1; } for (i = 0; i < joystick->nsensors; ++i) { @@ -2370,8 +2401,7 @@ SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorTy const char * SDL_GameControllerName(SDL_GameController *gamecontroller) { - if (!gamecontroller) - return NULL; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); if (SDL_strcmp(gamecontroller->name, "*") == 0) { return SDL_JoystickName(SDL_GameControllerGetJoystick(gamecontroller)); @@ -2383,22 +2413,34 @@ SDL_GameControllerName(SDL_GameController *gamecontroller) const char * SDL_GameControllerPath(SDL_GameController *gamecontroller) { - if (!gamecontroller) - return NULL; + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - return SDL_JoystickPath(SDL_GameControllerGetJoystick(gamecontroller)); + if (!joystick) { + return NULL; + } + return SDL_JoystickPath(joystick); } SDL_GameControllerType SDL_GameControllerGetType(SDL_GameController *gamecontroller) { - return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(SDL_GameControllerGetJoystick(gamecontroller)), SDL_JoystickName(SDL_GameControllerGetJoystick(gamecontroller))); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return SDL_CONTROLLER_TYPE_UNKNOWN; + } + return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(joystick), SDL_JoystickName(joystick)); } int SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller) { - return SDL_JoystickGetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return -1; + } + return SDL_JoystickGetPlayerIndex(joystick); } /** @@ -2407,37 +2449,67 @@ SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller) void SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index) { - SDL_JoystickSetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller), player_index); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return; + } + SDL_JoystickSetPlayerIndex(joystick, player_index); } Uint16 SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) { - return SDL_JoystickGetVendor(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return 0; + } + return SDL_JoystickGetVendor(joystick); } Uint16 SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) { - return SDL_JoystickGetProduct(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return 0; + } + return SDL_JoystickGetProduct(joystick); } Uint16 SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) { - return SDL_JoystickGetProductVersion(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return 0; + } + return SDL_JoystickGetProductVersion(joystick); } Uint16 SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) { - return SDL_JoystickGetFirmwareVersion(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return 0; + } + return SDL_JoystickGetFirmwareVersion(joystick); } const char * SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) { - return SDL_JoystickGetSerial(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return NULL; + } + return SDL_JoystickGetSerial(joystick); } /* @@ -2447,8 +2519,7 @@ SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) SDL_bool SDL_GameControllerGetAttached(SDL_GameController *gamecontroller) { - if (!gamecontroller) - return SDL_FALSE; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); return SDL_JoystickGetAttached(gamecontroller->joystick); } @@ -2459,8 +2530,7 @@ SDL_GameControllerGetAttached(SDL_GameController *gamecontroller) SDL_Joystick * SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller) { - if (!gamecontroller) - return NULL; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); return gamecontroller->joystick; } @@ -2510,7 +2580,9 @@ SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController SDL_GameControllerButtonBind bind; SDL_zero(bind); - if (!gamecontroller || axis == SDL_CONTROLLER_AXIS_INVALID) + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); + + if (axis == SDL_CONTROLLER_AXIS_INVALID) return bind; for (i = 0; i < gamecontroller->num_bindings; ++i) { @@ -2542,7 +2614,9 @@ SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameControll SDL_GameControllerButtonBind bind; SDL_zero(bind); - if (!gamecontroller || button == SDL_CONTROLLER_BUTTON_INVALID) + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); + + if (button == SDL_CONTROLLER_BUTTON_INVALID) return bind; for (i = 0; i < gamecontroller->num_bindings; ++i) { @@ -2567,43 +2641,78 @@ SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameControll int SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) { - return SDL_JoystickRumble(SDL_GameControllerGetJoystick(gamecontroller), low_frequency_rumble, high_frequency_rumble, duration_ms); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return -1; + } + return SDL_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms); } int SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms) { - return SDL_JoystickRumbleTriggers(SDL_GameControllerGetJoystick(gamecontroller), left_rumble, right_rumble, duration_ms); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return -1; + } + return SDL_JoystickRumbleTriggers(joystick, left_rumble, right_rumble, duration_ms); } SDL_bool SDL_GameControllerHasLED(SDL_GameController *gamecontroller) { - return SDL_JoystickHasLED(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return SDL_FALSE; + } + return SDL_JoystickHasLED(joystick); } SDL_bool SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) { - return SDL_JoystickHasRumble(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return SDL_FALSE; + } + return SDL_JoystickHasRumble(joystick); } SDL_bool SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller) { - return SDL_JoystickHasRumbleTriggers(SDL_GameControllerGetJoystick(gamecontroller)); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return SDL_FALSE; + } + return SDL_JoystickHasRumbleTriggers(joystick); } int SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue) { - return SDL_JoystickSetLED(SDL_GameControllerGetJoystick(gamecontroller), red, green, blue); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return -1; + } + return SDL_JoystickSetLED(joystick, red, green, blue); } int SDL_GameControllerSendEffect(SDL_GameController *gamecontroller, const void *data, int size) { - return SDL_JoystickSendEffect(SDL_GameControllerGetJoystick(gamecontroller), data, size); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + + if (!joystick) { + return -1; + } + return SDL_JoystickSendEffect(joystick, data, size); } void @@ -2611,7 +2720,7 @@ SDL_GameControllerClose(SDL_GameController *gamecontroller) { SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev; - if (!gamecontroller) + if (!gamecontroller || gamecontroller->magic != &gamecontroller_magic) return; SDL_LockJoysticks(); @@ -2640,6 +2749,7 @@ SDL_GameControllerClose(SDL_GameController *gamecontroller) gamecontrollerlist = gamecontrollerlist->next; } + gamecontroller->magic = NULL; SDL_free(gamecontroller->bindings); SDL_free(gamecontroller->last_match_axis); SDL_free(gamecontroller->last_hat_mask); @@ -2701,6 +2811,8 @@ SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL_GameContro { int posted; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + /* translate the event, if desired */ posted = 0; #if !SDL_EVENTS_DISABLED @@ -2727,8 +2839,11 @@ SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, SDL_GameCont #if !SDL_EVENTS_DISABLED SDL_Event event; - if (button == SDL_CONTROLLER_BUTTON_INVALID) - return (0); + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + + if (button == SDL_CONTROLLER_BUTTON_INVALID) { + return 0; + } switch (state) { case SDL_PRESSED: @@ -2828,6 +2943,9 @@ SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontrol { #if defined(SDL_JOYSTICK_MFI) const char *IOS_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button); + + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + return IOS_GameControllerGetAppleSFSymbolsNameForButton(gamecontroller, button); #else return NULL; @@ -2839,6 +2957,9 @@ SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontrolle { #if defined(SDL_JOYSTICK_MFI) const char *IOS_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis); + + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + return IOS_GameControllerGetAppleSFSymbolsNameForAxis(gamecontroller, axis); #else return NULL; diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index da8773739..cd41ca5b2 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -115,6 +115,14 @@ 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_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"); \ + return retval; \ + } SDL_bool SDL_JoysticksInitialized(void) @@ -497,6 +505,7 @@ SDL_JoystickOpen(int device_index) SDL_UnlockJoysticks(); return NULL; } + joystick->magic = &joystick_magic; joystick->driver = driver; joystick->instance_id = instance_id; joystick->attached = SDL_TRUE; @@ -648,6 +657,8 @@ SDL_JoystickIsVirtual(int device_index) int SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value) { + CHECK_JOYSTICK_MAGIC(joystick, -1); + #if SDL_JOYSTICK_VIRTUAL return SDL_JoystickSetVirtualAxisInner(joystick, axis, value); #else @@ -658,6 +669,8 @@ SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value) int SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value) { + CHECK_JOYSTICK_MAGIC(joystick, -1); + #if SDL_JOYSTICK_VIRTUAL return SDL_JoystickSetVirtualButtonInner(joystick, button, value); #else @@ -668,6 +681,8 @@ SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value) int SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value) { + CHECK_JOYSTICK_MAGIC(joystick, -1); + #if SDL_JOYSTICK_VIRTUAL return SDL_JoystickSetVirtualHatInner(joystick, hat, value); #else @@ -681,16 +696,8 @@ SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value) SDL_bool SDL_PrivateJoystickValid(SDL_Joystick *joystick) { - SDL_bool valid; - - if (joystick == NULL) { - SDL_SetError("Joystick hasn't been opened yet"); - valid = SDL_FALSE; - } else { - valid = SDL_TRUE; - } - - return valid; + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + return SDL_TRUE; } SDL_bool @@ -714,9 +721,8 @@ SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping * int SDL_JoystickNumAxes(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); + return joystick->naxes; } @@ -726,9 +732,8 @@ SDL_JoystickNumAxes(SDL_Joystick *joystick) int SDL_JoystickNumHats(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); + return joystick->nhats; } @@ -738,9 +743,8 @@ SDL_JoystickNumHats(SDL_Joystick *joystick) int SDL_JoystickNumBalls(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); + return joystick->nballs; } @@ -750,9 +754,8 @@ SDL_JoystickNumBalls(SDL_Joystick *joystick) int SDL_JoystickNumButtons(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); + return joystick->nbuttons; } @@ -764,9 +767,8 @@ SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) { Sint16 state; - if (!SDL_PrivateJoystickValid(joystick)) { - return 0; - } + CHECK_JOYSTICK_MAGIC(joystick, 0); + if (axis < joystick->naxes) { state = joystick->axes[axis].value; } else { @@ -782,9 +784,8 @@ SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) SDL_bool SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state) { - if (!SDL_PrivateJoystickValid(joystick)) { - return SDL_FALSE; - } + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + if (axis >= joystick->naxes) { SDL_SetError("Joystick only has %d axes", joystick->naxes); return SDL_FALSE; @@ -803,9 +804,8 @@ SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) { Uint8 state; - if (!SDL_PrivateJoystickValid(joystick)) { - return 0; - } + CHECK_JOYSTICK_MAGIC(joystick, 0); + if (hat < joystick->nhats) { state = joystick->hats[hat]; } else { @@ -823,9 +823,7 @@ SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) { int retval; - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); retval = 0; if (ball < joystick->nballs) { @@ -851,9 +849,8 @@ SDL_JoystickGetButton(SDL_Joystick *joystick, int button) { Uint8 state; - if (!SDL_PrivateJoystickValid(joystick)) { - return 0; - } + CHECK_JOYSTICK_MAGIC(joystick, 0); + if (button < joystick->nbuttons) { state = joystick->buttons[button]; } else { @@ -870,9 +867,7 @@ SDL_JoystickGetButton(SDL_Joystick *joystick, int button) SDL_bool SDL_JoystickGetAttached(SDL_Joystick *joystick) { - if (!joystick) { - return SDL_FALSE; - } + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); return joystick->attached; } @@ -883,9 +878,7 @@ SDL_JoystickGetAttached(SDL_Joystick *joystick) SDL_JoystickID SDL_JoystickInstanceID(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); return joystick->instance_id; } @@ -934,9 +927,7 @@ SDL_JoystickFromPlayerIndex(int player_index) const char * SDL_JoystickName(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return NULL; - } + CHECK_JOYSTICK_MAGIC(joystick, NULL); return joystick->name; } @@ -947,9 +938,7 @@ SDL_JoystickName(SDL_Joystick *joystick) const char * SDL_JoystickPath(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return NULL; - } + CHECK_JOYSTICK_MAGIC(joystick, NULL); if (!joystick->path) { SDL_Unsupported(); @@ -966,9 +955,7 @@ SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick) { int player_index; - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); SDL_LockJoysticks(); player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id); @@ -983,9 +970,7 @@ SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick) void SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index) { - if (!SDL_PrivateJoystickValid(joystick)) { - return; - } + CHECK_JOYSTICK_MAGIC(joystick, ); SDL_LockJoysticks(); SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id); @@ -997,9 +982,7 @@ SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h { int result; - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); SDL_LockJoysticks(); if (low_frequency_rumble == joystick->low_frequency_rumble && @@ -1033,9 +1016,7 @@ SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri { int result; - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); SDL_LockJoysticks(); if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) { @@ -1068,9 +1049,7 @@ SDL_JoystickHasLED(SDL_Joystick *joystick) { SDL_bool result; - if (!SDL_PrivateJoystickValid(joystick)) { - return SDL_FALSE; - } + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); SDL_LockJoysticks(); @@ -1086,9 +1065,7 @@ SDL_JoystickHasRumble(SDL_Joystick *joystick) { SDL_bool result; - if (!SDL_PrivateJoystickValid(joystick)) { - return SDL_FALSE; - } + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); SDL_LockJoysticks(); @@ -1104,9 +1081,7 @@ SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick) { SDL_bool result; - if (!SDL_PrivateJoystickValid(joystick)) { - return SDL_FALSE; - } + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); SDL_LockJoysticks(); @@ -1123,9 +1098,7 @@ SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) int result; SDL_bool isfreshvalue; - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); SDL_LockJoysticks(); @@ -1156,9 +1129,7 @@ SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) { int result; - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + CHECK_JOYSTICK_MAGIC(joystick, -1); SDL_LockJoysticks(); @@ -1179,9 +1150,7 @@ SDL_JoystickClose(SDL_Joystick *joystick) SDL_Joystick *joysticklistprev; int i; - if (!SDL_PrivateJoystickValid(joystick)) { - return; - } + CHECK_JOYSTICK_MAGIC(joystick, ); SDL_LockJoysticks(); @@ -1200,6 +1169,7 @@ SDL_JoystickClose(SDL_Joystick *joystick) joystick->driver->Close(joystick); joystick->hwdata = NULL; + joystick->magic = NULL; joysticklist = SDL_joysticks; joysticklistprev = NULL; @@ -1297,8 +1267,13 @@ SDL_PrivateJoystickShouldIgnoreEvent() void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers) { - int ntouchpads = joystick->ntouchpads + 1; - SDL_JoystickTouchpadInfo *touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo))); + int ntouchpads; + SDL_JoystickTouchpadInfo *touchpads; + + CHECK_JOYSTICK_MAGIC(joystick, ); + + ntouchpads = joystick->ntouchpads + 1; + touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo))); if (touchpads) { SDL_JoystickTouchpadInfo *touchpad = &touchpads[ntouchpads - 1]; SDL_JoystickTouchpadFingerInfo *fingers = (SDL_JoystickTouchpadFingerInfo *)SDL_calloc(nfingers, sizeof(SDL_JoystickTouchpadFingerInfo)); @@ -1319,8 +1294,13 @@ void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers) void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, float rate) { - int nsensors = joystick->nsensors + 1; - SDL_JoystickSensorInfo *sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo))); + int nsensors; + SDL_JoystickSensorInfo *sensors; + + CHECK_JOYSTICK_MAGIC(joystick, ); + + nsensors = joystick->nsensors + 1; + sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo))); if (sensors) { SDL_JoystickSensorInfo *sensor = &sensors[nsensors - 1]; @@ -1438,6 +1418,8 @@ SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick) { int i, j; + CHECK_JOYSTICK_MAGIC(joystick, ); + /* Tell the app that everything is centered/unpressed... */ for (i = 0; i < joystick->naxes; i++) { if (joystick->axes[i].has_initial_value) { @@ -1512,6 +1494,8 @@ 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; @@ -1577,6 +1561,8 @@ 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; @@ -1620,6 +1606,8 @@ SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, SDL_AssertJoysticksLocked(); + CHECK_JOYSTICK_MAGIC(joystick, 0); + /* Make sure we're not getting garbage events */ if (ball >= joystick->nballs) { return 0; @@ -1657,6 +1645,8 @@ SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) #if !SDL_EVENTS_DISABLED SDL_Event event; + CHECK_JOYSTICK_MAGIC(joystick, 0); + switch (state) { case SDL_PRESSED: event.type = SDL_JOYBUTTONDOWN; @@ -2808,11 +2798,10 @@ int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id) SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - SDL_JoystickGUID emptyGUID; - SDL_zero(emptyGUID); - return emptyGUID; - } + static SDL_JoystickGUID emptyGUID; + + CHECK_JOYSTICK_MAGIC(joystick, emptyGUID); + return joystick->guid; } @@ -2845,17 +2834,15 @@ Uint16 SDL_JoystickGetProductVersion(SDL_Joystick *joystick) Uint16 SDL_JoystickGetFirmwareVersion(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return 0; - } + CHECK_JOYSTICK_MAGIC(joystick, 0); + return joystick->firmware_version; } const char *SDL_JoystickGetSerial(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return NULL; - } + CHECK_JOYSTICK_MAGIC(joystick, NULL); + return joystick->serial; } @@ -2888,6 +2875,8 @@ 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_assert(joystick->ref_count); /* make sure we are calling this only for update, not for initialisation */ if (ePowerLevel != joystick->epowerlevel) { #if !SDL_EVENTS_DISABLED @@ -2906,9 +2895,8 @@ void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLe /* return its power level */ SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick) { - if (!SDL_PrivateJoystickValid(joystick)) { - return SDL_JOYSTICK_POWER_UNKNOWN; - } + CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_POWER_UNKNOWN); + return joystick->epowerlevel; } @@ -2919,6 +2907,8 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger int posted; Uint32 event_type; + CHECK_JOYSTICK_MAGIC(joystick, 0); + if (touchpad < 0 || touchpad >= joystick->ntouchpads) { return 0; } @@ -3005,6 +2995,8 @@ int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const int i; int posted = 0; + CHECK_JOYSTICK_MAGIC(joystick, 0); + /* We ignore events if we don't have keyboard focus */ if (SDL_PrivateJoystickShouldIgnoreEvent()) { return 0; diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 79a3720f7..34a17429f 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -68,6 +68,8 @@ typedef struct _SDL_JoystickSensorInfo struct _SDL_Joystick { + const void *magic; + SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */ char *name; /* Joystick name - system dependent */ char *path; /* Joystick path - system dependent */