From e555d453310fbf4094c25feae5e63f4efc5526d5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 5 Nov 2020 11:07:54 -0800 Subject: [PATCH] Added SDL_JoystickHasLED Currently, this is only supported by the PS4 HIDAPI driver. --- include/SDL_gamecontroller.h | 9 ++ include/SDL_joystick.h | 9 ++ src/dynapi/SDL_dynapi_overrides.h | 4 + src/dynapi/SDL_dynapi_procs.h | 4 + src/joystick/SDL_gamecontroller.c | 6 + src/joystick/SDL_joystick.c | 18 +++ src/joystick/SDL_sysjoystick.h | 1 + src/joystick/android/SDL_sysjoystick.c | 7 + src/joystick/bsd/SDL_sysjoystick.c | 7 + src/joystick/darwin/SDL_sysjoystick.c | 7 + src/joystick/dummy/SDL_sysjoystick.c | 7 + src/joystick/emscripten/SDL_sysjoystick.c | 7 + src/joystick/haiku/SDL_haikujoystick.cc | 6 + src/joystick/hidapi/SDL_hidapi_gamecube.c | 7 + src/joystick/hidapi/SDL_hidapi_ps4.c | 11 +- src/joystick/hidapi/SDL_hidapi_steam.c | 8 ++ src/joystick/hidapi/SDL_hidapi_switch.c | 8 ++ src/joystick/hidapi/SDL_hidapi_xbox360.c | 8 ++ src/joystick/hidapi/SDL_hidapi_xbox360w.c | 8 ++ src/joystick/hidapi/SDL_hidapi_xboxone.c | 8 ++ src/joystick/hidapi/SDL_hidapijoystick.c | 15 ++ src/joystick/hidapi/SDL_hidapijoystick_c.h | 1 + src/joystick/iphoneos/SDL_sysjoystick.m | 153 +++++++++++---------- src/joystick/linux/SDL_sysjoystick.c | 7 + src/joystick/virtual/SDL_virtualjoystick.c | 8 ++ src/joystick/windows/SDL_windowsjoystick.c | 7 + test/testgamecontroller.c | 12 ++ 27 files changed, 278 insertions(+), 75 deletions(-) diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h index 7089d5d45..a0984bbcb 100644 --- a/include/SDL_gamecontroller.h +++ b/include/SDL_gamecontroller.h @@ -404,6 +404,15 @@ extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController *ga */ extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); +/** + * Return whether a controller has an LED + * + * \param gamecontroller The controller to query + * + * \return SDL_TRUE, or SDL_FALSE if this controller does not have a modifiable LED + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasLED(SDL_GameController *gamecontroller); + /** * Update a controller's LED color. * diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index 3ee433b76..30790fcf9 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -432,6 +432,15 @@ extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick * joystick, */ extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); +/** + * Return whether a joystick has an LED + * + * \param joystick The joystick to query + * + * \return SDL_TRUE, or SDL_FALSE if this joystick does not have a modifiable LED + */ +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasLED(SDL_Joystick * joystick); + /** * Update a joystick's LED color. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 2c7d35fb2..555255884 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -768,3 +768,7 @@ #define SDL_AndroidRequestPermission SDL_AndroidRequestPermission_REAL #define SDL_OpenURL SDL_OpenURL_REAL #define SDL_HasSurfaceRLE SDL_HasSurfaceRLE_REAL +#define SDL_GameControllerHasLED SDL_GameControllerHasLED_REAL +#define SDL_GameControllerSetLED SDL_GameControllerSetLED_REAL +#define SDL_JoystickHasLED SDL_JoystickHasLED_REAL +#define SDL_JoystickSetLED SDL_JoystickSetLED_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 4ddd57b21..1688a357e 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -829,3 +829,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_AndroidRequestPermission,(const char *a),(a),return #endif SDL_DYNAPI_PROC(int,SDL_OpenURL,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_HasSurfaceRLE,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_GameControllerHasLED,(SDL_GameController *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GameControllerSetLED,(SDL_GameController *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickHasLED,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_JoystickSetLED,(SDL_Joystick *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 767b5df74..81c387416 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -2107,6 +2107,12 @@ SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequenc return SDL_JoystickRumble(SDL_GameControllerGetJoystick(gamecontroller), low_frequency_rumble, high_frequency_rumble, duration_ms); } +SDL_bool +SDL_GameControllerHasLED(SDL_GameController *gamecontroller) +{ + return SDL_JoystickHasLED(SDL_GameControllerGetJoystick(gamecontroller)); +} + int SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue) { diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 01b7bd2a3..a3e51996b 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -901,6 +901,24 @@ SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 return result; } +SDL_bool +SDL_JoystickHasLED(SDL_Joystick * joystick) +{ + SDL_bool result; + + if (!SDL_PrivateJoystickValid(joystick)) { + return SDL_FALSE; + } + + SDL_LockJoysticks(); + + result = joystick->driver->HasLED(joystick); + + SDL_UnlockJoysticks(); + + return result; +} + int SDL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 92230fdd9..6de1e37f3 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -128,6 +128,7 @@ typedef struct _SDL_JoystickDriver int (*Rumble)(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); /* LED functionality */ + SDL_bool (*HasLED)(SDL_Joystick * joystick); int (*SetLED)(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue); /* Function to update the state of a joystick - called as a device poll. diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index d9b8c0be7..2f967fe05 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -633,6 +633,12 @@ ANDROID_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin return SDL_Unsupported(); } +static SDL_bool +ANDROID_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int ANDROID_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -717,6 +723,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = ANDROID_JoystickGetDeviceInstanceID, ANDROID_JoystickOpen, ANDROID_JoystickRumble, + ANDROID_JoystickHasLED, ANDROID_JoystickSetLED, ANDROID_JoystickUpdate, ANDROID_JoystickClose, diff --git a/src/joystick/bsd/SDL_sysjoystick.c b/src/joystick/bsd/SDL_sysjoystick.c index f588687aa..ff5203466 100644 --- a/src/joystick/bsd/SDL_sysjoystick.c +++ b/src/joystick/bsd/SDL_sysjoystick.c @@ -768,6 +768,12 @@ BSD_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) return SDL_FALSE; } +static SDL_bool +BSD_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int BSD_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -786,6 +792,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = BSD_JoystickGetDeviceInstanceID, BSD_JoystickOpen, BSD_JoystickRumble, + BSD_JoystickHasLED, BSD_JoystickSetLED, BSD_JoystickUpdate, BSD_JoystickClose, diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index 999eabaca..12b8a8fdd 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -922,6 +922,12 @@ DARWIN_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint return 0; } +static SDL_bool +DARWIN_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int DARWIN_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1075,6 +1081,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = DARWIN_JoystickGetDeviceInstanceID, DARWIN_JoystickOpen, DARWIN_JoystickRumble, + DARWIN_JoystickHasLED, DARWIN_JoystickSetLED, DARWIN_JoystickUpdate, DARWIN_JoystickClose, diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index fdac88091..345333f27 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -89,6 +89,12 @@ DUMMY_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint1 return SDL_Unsupported(); } +static SDL_bool +DUMMY_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int DUMMY_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -128,6 +134,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = DUMMY_JoystickGetDeviceInstanceID, DUMMY_JoystickOpen, DUMMY_JoystickRumble, + DUMMY_JoystickHasLED, DUMMY_JoystickSetLED, DUMMY_JoystickUpdate, DUMMY_JoystickClose, diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 78a8c1776..74727397f 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -409,6 +409,12 @@ EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) return SDL_FALSE; } +static SDL_bool +EMSCRIPTEN_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int EMSCRIPTEN_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -427,6 +433,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = EMSCRIPTEN_JoystickGetDeviceInstanceID, EMSCRIPTEN_JoystickOpen, EMSCRIPTEN_JoystickRumble, + EMSCRIPTEN_JoystickHasLED, EMSCRIPTEN_JoystickSetLED, EMSCRIPTEN_JoystickUpdate, EMSCRIPTEN_JoystickClose, diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index c9a9a65fb..ab5f743c4 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -265,6 +265,11 @@ extern "C" return SDL_FALSE; } + static SDL_bool HAIKU_JoystickHasLED(SDL_Joystick * joystick) + { + return SDL_FALSE; + } + static int HAIKU_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -282,6 +287,7 @@ extern "C" HAIKU_JoystickGetDeviceInstanceID, HAIKU_JoystickOpen, HAIKU_JoystickRumble, + HAIKU_JoystickHasLED, HAIKU_JoystickSetLED, HAIKU_JoystickUpdate, HAIKU_JoystickClose, diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 883bea1f7..8c7a7bd47 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -363,6 +363,12 @@ HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo return -1; } +static SDL_bool +HIDAPI_DriverGameCube_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return SDL_FALSE; +} + static int HIDAPI_DriverGameCube_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -408,6 +414,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube = HIDAPI_DriverGameCube_UpdateDevice, HIDAPI_DriverGameCube_OpenJoystick, HIDAPI_DriverGameCube_RumbleJoystick, + HIDAPI_DriverGameCube_HasJoystickLED, HIDAPI_DriverGameCube_SetJoystickLED, HIDAPI_DriverGameCube_CloseJoystick, HIDAPI_DriverGameCube_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index bd458948b..173e1ed12 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -102,7 +102,7 @@ typedef struct { int player_index; Uint16 rumble_left; Uint16 rumble_right; - Uint8 color_set; + SDL_bool color_set; Uint8 led_red; Uint8 led_green; Uint8 led_blue; @@ -365,12 +365,18 @@ HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic return 0; } +static SDL_bool +HIDAPI_DriverPS4_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return SDL_TRUE; +} + static int HIDAPI_DriverPS4_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; - ctx->color_set = 1; + ctx->color_set = SDL_TRUE; ctx->led_red = red; ctx->led_green = green; ctx->led_blue = blue; @@ -564,6 +570,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 = HIDAPI_DriverPS4_UpdateDevice, HIDAPI_DriverPS4_OpenJoystick, HIDAPI_DriverPS4_RumbleJoystick, + HIDAPI_DriverPS4_HasJoystickLED, HIDAPI_DriverPS4_SetJoystickLED, HIDAPI_DriverPS4_CloseJoystick, HIDAPI_DriverPS4_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 8d2474172..b28e39571 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1034,6 +1034,13 @@ HIDAPI_DriverSteam_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst return SDL_Unsupported(); } +static SDL_bool +HIDAPI_DriverSteam_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + /* You should use the full Steam Input API for LED support */ + return SDL_FALSE; +} + static int HIDAPI_DriverSteam_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1171,6 +1178,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam = HIDAPI_DriverSteam_UpdateDevice, HIDAPI_DriverSteam_OpenJoystick, HIDAPI_DriverSteam_RumbleJoystick, + HIDAPI_DriverSteam_HasJoystickLED, HIDAPI_DriverSteam_SetJoystickLED, HIDAPI_DriverSteam_CloseJoystick, HIDAPI_DriverSteam_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 27ad4fcdf..4b33e13c5 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -920,6 +920,13 @@ HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble); } +static SDL_bool +HIDAPI_DriverSwitch_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + /* Doesn't have an RGB LED, so don't return true here */ + return SDL_FALSE; +} + static int HIDAPI_DriverSwitch_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1273,6 +1280,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch = HIDAPI_DriverSwitch_UpdateDevice, HIDAPI_DriverSwitch_OpenJoystick, HIDAPI_DriverSwitch_RumbleJoystick, + HIDAPI_DriverSwitch_HasJoystickLED, HIDAPI_DriverSwitch_SetJoystickLED, HIDAPI_DriverSwitch_CloseJoystick, HIDAPI_DriverSwitch_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index 85345cb6f..b82f793a2 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -796,6 +796,13 @@ HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy return 0; } +static SDL_bool +HIDAPI_DriverXbox360_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + /* Doesn't have an RGB LED, so don't return true here */ + return SDL_FALSE; +} + static int HIDAPI_DriverXbox360_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1308,6 +1315,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 = HIDAPI_DriverXbox360_UpdateDevice, HIDAPI_DriverXbox360_OpenJoystick, HIDAPI_DriverXbox360_RumbleJoystick, + HIDAPI_DriverXbox360_HasJoystickLED, HIDAPI_DriverXbox360_SetJoystickLED, HIDAPI_DriverXbox360_CloseJoystick, HIDAPI_DriverXbox360_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 9b84c86b8..6e4b70cb7 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -157,6 +157,13 @@ HIDAPI_DriverXbox360W_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo return 0; } +static SDL_bool +HIDAPI_DriverXbox360W_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + /* Doesn't have an RGB LED, so don't return true here */ + return SDL_FALSE; +} + static int HIDAPI_DriverXbox360W_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -300,6 +307,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W = HIDAPI_DriverXbox360W_UpdateDevice, HIDAPI_DriverXbox360W_OpenJoystick, HIDAPI_DriverXbox360W_RumbleJoystick, + HIDAPI_DriverXbox360W_HasJoystickLED, HIDAPI_DriverXbox360W_SetJoystickLED, HIDAPI_DriverXbox360W_CloseJoystick, HIDAPI_DriverXbox360W_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index cfca08a3d..5c2ecdee2 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -364,6 +364,13 @@ HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy return 0; } +static SDL_bool +HIDAPI_DriverXboxOne_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + /* Doesn't have an RGB LED, so don't return true here */ + return SDL_FALSE; +} + static int HIDAPI_DriverXboxOne_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -836,6 +843,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne = HIDAPI_DriverXboxOne_UpdateDevice, HIDAPI_DriverXboxOne_OpenJoystick, HIDAPI_DriverXboxOne_RumbleJoystick, + HIDAPI_DriverXboxOne_HasJoystickLED, HIDAPI_DriverXboxOne_SetJoystickLED, HIDAPI_DriverXboxOne_CloseJoystick, HIDAPI_DriverXboxOne_FreeDevice, diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index db213f34e..2ce2f13de 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1048,6 +1048,20 @@ HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint return result; } +static SDL_bool +HIDAPI_JoystickHasLED(SDL_Joystick * joystick) +{ + SDL_bool result = SDL_FALSE; + + if (joystick->hwdata) { + SDL_HIDAPI_Device *device = joystick->hwdata->device; + + result = device->driver->HasJoystickLED(device, joystick); + } + + return result; +} + static int HIDAPI_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1138,6 +1152,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = HIDAPI_JoystickGetDeviceInstanceID, HIDAPI_JoystickOpen, HIDAPI_JoystickRumble, + HIDAPI_JoystickHasLED, HIDAPI_JoystickSetLED, HIDAPI_JoystickUpdate, HIDAPI_JoystickClose, diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index e6275f207..f88542be6 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -94,6 +94,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver SDL_bool (*UpdateDevice)(SDL_HIDAPI_Device *device); SDL_bool (*OpenJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); + SDL_bool (*HasJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); int (*SetJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); void (*CloseJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); void (*FreeDevice)(SDL_HIDAPI_Device *device); diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index dd9944957..915016308 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -827,7 +827,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) @implementation SDL_RumbleMotor { CHHapticEngine *engine API_AVAILABLE(ios(13.0), tvos(14.0)); id player API_AVAILABLE(ios(13.0), tvos(14.0)); - bool active; + bool active; } -(void)cleanup @@ -845,91 +845,91 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) -(int)setIntensity:(float)intensity { @autoreleasepool { - if (@available(iOS 14.0, tvOS 14.0, *)) { - NSError *error; - - if (self->engine == nil) { - return SDL_SetError("Haptics engine was stopped"); - } + if (@available(iOS 14.0, tvOS 14.0, *)) { + NSError *error; + + if (self->engine == nil) { + return SDL_SetError("Haptics engine was stopped"); + } - if (intensity == 0.0f) { - if (self->player && self->active) { - [self->player stopAtTime:0 error:&error]; - } - self->active = false; - return 0; - } + if (intensity == 0.0f) { + if (self->player && self->active) { + [self->player stopAtTime:0 error:&error]; + } + self->active = false; + return 0; + } - if (self->player == nil) { - CHHapticEventParameter *param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f]; - CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:param, nil] relativeTime:0 duration:GCHapticDurationInfinite]; - CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error]; - if (error != nil) { - return SDL_SetError("Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]); - } + if (self->player == nil) { + CHHapticEventParameter *param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f]; + CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:param, nil] relativeTime:0 duration:GCHapticDurationInfinite]; + CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error]; + if (error != nil) { + return SDL_SetError("Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]); + } - self->player = [self->engine createPlayerWithPattern:pattern error:&error]; - if (error != nil) { - return SDL_SetError("Couldn't create haptic player: %s", [error.localizedDescription UTF8String]); - } - self->active = false; - } + self->player = [self->engine createPlayerWithPattern:pattern error:&error]; + if (error != nil) { + return SDL_SetError("Couldn't create haptic player: %s", [error.localizedDescription UTF8String]); + } + self->active = false; + } - CHHapticDynamicParameter *param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0]; - [self->player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error]; - if (error != nil) { - return SDL_SetError("Couldn't update haptic player: %s", [error.localizedDescription UTF8String]); - } + CHHapticDynamicParameter *param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0]; + [self->player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error]; + if (error != nil) { + return SDL_SetError("Couldn't update haptic player: %s", [error.localizedDescription UTF8String]); + } - if (!self->active) { - [self->player startAtTime:0 error:&error]; - self->active = true; - } - } + if (!self->active) { + [self->player startAtTime:0 error:&error]; + self->active = true; + } + } - return 0; - } + return 0; + } } -(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(ios(14.0), tvos(14.0)) { @autoreleasepool { - NSError *error; + NSError *error; - self->engine = [controller.haptics createEngineWithLocality:locality]; - if (self->engine == nil) { - SDL_SetError("Couldn't create haptics engine"); - return nil; - } + self->engine = [controller.haptics createEngineWithLocality:locality]; + if (self->engine == nil) { + SDL_SetError("Couldn't create haptics engine"); + return nil; + } - [self->engine startAndReturnError:&error]; - if (error != nil) { - SDL_SetError("Couldn't start haptics engine"); - return nil; - } + [self->engine startAndReturnError:&error]; + if (error != nil) { + SDL_SetError("Couldn't start haptics engine"); + return nil; + } - __weak typeof(self) weakSelf = self; - self->engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) { - SDL_RumbleMotor *_this = weakSelf; - if (_this == nil) { - return; - } + __weak typeof(self) weakSelf = self; + self->engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) { + SDL_RumbleMotor *_this = weakSelf; + if (_this == nil) { + return; + } - _this->player = nil; - _this->engine = nil; - }; - self->engine.resetHandler = ^{ - SDL_RumbleMotor *_this = weakSelf; - if (_this == nil) { - return; - } + _this->player = nil; + _this->engine = nil; + }; + self->engine.resetHandler = ^{ + SDL_RumbleMotor *_this = weakSelf; + if (_this == nil) { + return; + } - _this->player = nil; - [_this->engine startAndReturnError:nil]; - }; + _this->player = nil; + [_this->engine startAndReturnError:nil]; + }; - return self; - } + return self; + } } @end @@ -960,8 +960,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) -(void)cleanup { - [self->low_frequency_motor cleanup]; - [self->high_frequency_motor cleanup]; + [self->low_frequency_motor cleanup]; + [self->high_frequency_motor cleanup]; } @end @@ -1008,6 +1008,12 @@ IOS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 #endif } +static SDL_bool +IOS_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int IOS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1044,9 +1050,9 @@ IOS_JoystickClose(SDL_Joystick * joystick) @autoreleasepool { #ifdef ENABLE_MFI_RUMBLE if (device->rumble) { - SDL_RumbleContext *rumble = (__bridge SDL_RumbleContext *)device->rumble; + SDL_RumbleContext *rumble = (__bridge SDL_RumbleContext *)device->rumble; - [rumble cleanup]; + [rumble cleanup]; CFRelease(device->rumble); device->rumble = NULL; } @@ -1122,6 +1128,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = IOS_JoystickGetDeviceInstanceID, IOS_JoystickOpen, IOS_JoystickRumble, + IOS_JoystickHasLED, IOS_JoystickSetLED, IOS_JoystickUpdate, IOS_JoystickClose, diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 1ac1e0a5c..4cc32f3a4 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -891,6 +891,12 @@ LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint1 return 0; } +static SDL_bool +LINUX_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int LINUX_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -1372,6 +1378,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = LINUX_JoystickGetDeviceInstanceID, LINUX_JoystickOpen, LINUX_JoystickRumble, + LINUX_JoystickHasLED, LINUX_JoystickSetLED, LINUX_JoystickUpdate, LINUX_JoystickClose, diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index da903178f..9e34caeb4 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -339,6 +339,13 @@ VIRTUAL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin } +static SDL_bool +VIRTUAL_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + + static int VIRTUAL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -416,6 +423,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = VIRTUAL_JoystickGetDeviceInstanceID, VIRTUAL_JoystickOpen, VIRTUAL_JoystickRumble, + VIRTUAL_JoystickHasLED, VIRTUAL_JoystickSetLED, VIRTUAL_JoystickUpdate, VIRTUAL_JoystickClose, diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index bf3df0cb1..e37e7ddfe 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -500,6 +500,12 @@ WINDOWS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin } } +static SDL_bool +WINDOWS_JoystickHasLED(SDL_Joystick * joystick) +{ + return SDL_FALSE; +} + static int WINDOWS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) { @@ -589,6 +595,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = WINDOWS_JoystickGetDeviceInstanceID, WINDOWS_JoystickOpen, WINDOWS_JoystickRumble, + WINDOWS_JoystickHasLED, WINDOWS_JoystickSetLED, WINDOWS_JoystickUpdate, WINDOWS_JoystickClose, diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 5ecf0c1e5..9a3c95704 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -193,6 +193,18 @@ loop(void *arg) } } + /* Update LED based on left thumbstick position */ + { + Uint8 r, g, b; + Sint16 x = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_LEFTX); + Sint16 y = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_LEFTY); + + r = (Uint8)((float)(((int)x + 32767) * 255) / 65535); + b = (Uint8)((float)(((int)y + 32767) * 255) / 65535); + g = (Uint8)((int)(r + b) / 2); + SDL_GameControllerSetLED(gamecontroller, r, g, b); + } + /* Update rumble based on trigger state */ { Uint16 low_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) * 2;