From 52bf5b1de98fd0588ef4d9b4efd6860ce495a445 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 6 Aug 2022 10:34:19 -0700 Subject: [PATCH] Added the hint SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED to control whether the player LED is set on Nintendo Switch controllers --- include/SDL_hints.h | 9 +++++ src/joystick/hidapi/SDL_hidapi_switch.c | 45 ++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 368cb0a3c..9c11eb1fe 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -820,6 +820,15 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED" +/** + * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Nintendo Switch controller. + * + * This variable can be set to the following values: + * "0" - player LEDs are not enabled + * "1" - player LEDs are enabled (the default) + */ +#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED" + /** * \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used. * diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index c1ef34deb..9b9be148a 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -253,6 +253,8 @@ typedef struct { SDL_bool m_bUsingBluetooth; SDL_bool m_bIsGameCube; SDL_bool m_bUseButtonLabels; + SDL_bool m_bPlayerLights; + int m_nPlayerIndex; SDL_bool m_bSyncWrite; int m_nMaxWriteAttempts; ESwitchDeviceInfoControllerType m_eControllerType; @@ -835,10 +837,26 @@ static void SDLCALL SDL_HomeLEDHintChanged(void *userdata, const char *name, con } } -static SDL_bool SetSlotLED(SDL_DriverSwitch_Context *ctx, Uint8 slot) +static void UpdateSlotLED(SDL_DriverSwitch_Context *ctx) { - Uint8 led_data = (1 << slot); - return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetPlayerLights, &led_data, sizeof(led_data), NULL); + if (!ctx->m_bInputOnly) { + Uint8 slot = (ctx->m_nPlayerIndex % 4); + Uint8 led_data = ctx->m_bPlayerLights ? (1 << slot) : 0; + + WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetPlayerLights, &led_data, sizeof(led_data), NULL); + } +} + +static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata; + SDL_bool bPlayerLights = SDL_GetStringBoolean(hint, SDL_TRUE); + + if (bPlayerLights != ctx->m_bPlayerLights) { + ctx->m_bPlayerLights = bPlayerLights; + + UpdateSlotLED(ctx); + } } static SDL_bool SetIMUEnabled(SDL_DriverSwitch_Context* ctx, SDL_bool enabled) @@ -1171,6 +1189,15 @@ HIDAPI_DriverSwitch_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystick static void HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) { + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; + + if (!ctx) { + return; + } + + ctx->m_nPlayerIndex = player_index; + + UpdateSlotLED(ctx); } static SDL_bool @@ -1281,7 +1308,6 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, SDL_HomeLEDHintChanged, ctx); } - SetSlotLED(ctx, (joystick->instance_id % 4)); /* Set the serial number */ { @@ -1313,6 +1339,14 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti SDL_GameControllerButtonReportingHintChanged, ctx); } + /* Initialize player index (needed for setting LEDs) */ + ctx->m_nPlayerIndex = SDL_JoystickGetPlayerIndex(joystick); + ctx->m_bPlayerLights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, SDL_TRUE); + UpdateSlotLED(ctx); + + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, + SDL_PlayerLEDHintChanged, ctx); + /* Initialize the joystick capabilities */ joystick->nbuttons = 16; joystick->naxes = SDL_CONTROLLER_AXIS_MAX; @@ -2013,6 +2047,9 @@ HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, SDL_HomeLEDHintChanged, ctx); + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, + SDL_PlayerLEDHintChanged, ctx); + SDL_LockMutex(device->dev_lock); { SDL_hid_close(device->dev);