Browse Source

Add SDL_JoystickSetLED.

Currently, this is only supported by the PS4 HIDAPI driver.
Ethan Lee 5 years ago
parent
commit
83cddd2ebc

+ 12 - 0
include/SDL_gamecontroller.h

@@ -404,6 +404,18 @@ 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);
 extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
 
 
+/**
+ *  Update a controller's LED color.
+ *
+ *  \param controller The joystick to update
+ *  \param red The intensity of the red LED
+ *  \param green The intensity of the green LED
+ *  \param blue The intensity of the blue LED
+ *
+ *  \return 0, or -1 if this controller does not have a modifiable LED
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue);
+
 /**
 /**
  *  Close a controller previously opened with SDL_GameControllerOpen().
  *  Close a controller previously opened with SDL_GameControllerOpen().
  */
  */

+ 12 - 0
include/SDL_joystick.h

@@ -432,6 +432,18 @@ 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);
 extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
 
 
+/**
+ *  Update a joystick's LED color.
+ *
+ *  \param joystick The joystick to update
+ *  \param red The intensity of the red LED
+ *  \param green The intensity of the green LED
+ *  \param blue The intensity of the blue LED
+ *
+ *  \return 0, or -1 if this joystick does not have a modifiable LED
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue);
+
 /**
 /**
  *  Close a joystick previously opened with SDL_JoystickOpen().
  *  Close a joystick previously opened with SDL_JoystickOpen().
  */
  */

+ 6 - 0
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);
     return SDL_JoystickRumble(SDL_GameControllerGetJoystick(gamecontroller), low_frequency_rumble, high_frequency_rumble, duration_ms);
 }
 }
 
 
+int
+SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_JoystickSetLED(SDL_GameControllerGetJoystick(gamecontroller), red, green, blue);
+}
+
 void
 void
 SDL_GameControllerClose(SDL_GameController * gamecontroller)
 SDL_GameControllerClose(SDL_GameController * gamecontroller)
 {
 {

+ 30 - 0
src/joystick/SDL_joystick.c

@@ -901,6 +901,36 @@ SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16
     return result;
     return result;
 }
 }
 
 
+int
+SDL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    int result;
+
+    if (!SDL_PrivateJoystickValid(joystick)) {
+        return -1;
+    }
+
+    SDL_LockJoysticks();
+
+    if (red == joystick->led_red &&
+        green == joystick->led_green &&
+        blue == joystick->led_blue) {
+        /* Avoid spamming the driver */
+        result = 0;
+    } else {
+        result = joystick->driver->SetLED(joystick, red, green, 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;
+}
+
 /*
 /*
  * Close a joystick previously opened with SDL_JoystickOpen()
  * Close a joystick previously opened with SDL_JoystickOpen()
  */
  */

+ 7 - 0
src/joystick/SDL_sysjoystick.h

@@ -64,6 +64,10 @@ struct _SDL_Joystick
     Uint16 high_frequency_rumble;
     Uint16 high_frequency_rumble;
     Uint32 rumble_expiration;
     Uint32 rumble_expiration;
 
 
+    Uint8 led_red;
+    Uint8 led_green;
+    Uint8 led_blue;
+
     SDL_bool attached;
     SDL_bool attached;
     SDL_bool is_game_controller;
     SDL_bool is_game_controller;
     SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */
     SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */
@@ -123,6 +127,9 @@ typedef struct _SDL_JoystickDriver
     /* Rumble functionality */
     /* Rumble functionality */
     int (*Rumble)(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
     int (*Rumble)(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
 
 
+    /* LED functionality */
+    int (*SetLED)(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue);
+
     /* Function to update the state of a joystick - called as a device poll.
     /* Function to update the state of a joystick - called as a device poll.
      * This function shouldn't update the joystick structure directly,
      * This function shouldn't update the joystick structure directly,
      * but instead should call SDL_PrivateJoystick*() to deliver events
      * but instead should call SDL_PrivateJoystick*() to deliver events

+ 7 - 0
src/joystick/android/SDL_sysjoystick.c

@@ -633,6 +633,12 @@ ANDROID_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin
     return SDL_Unsupported();
     return SDL_Unsupported();
 }
 }
 
 
+static int
+ANDROID_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 ANDROID_JoystickUpdate(SDL_Joystick * joystick)
 ANDROID_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -711,6 +717,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver =
     ANDROID_JoystickGetDeviceInstanceID,
     ANDROID_JoystickGetDeviceInstanceID,
     ANDROID_JoystickOpen,
     ANDROID_JoystickOpen,
     ANDROID_JoystickRumble,
     ANDROID_JoystickRumble,
+    ANDROID_JoystickSetLED,
     ANDROID_JoystickUpdate,
     ANDROID_JoystickUpdate,
     ANDROID_JoystickClose,
     ANDROID_JoystickClose,
     ANDROID_JoystickQuit,
     ANDROID_JoystickQuit,

+ 7 - 0
src/joystick/bsd/SDL_sysjoystick.c

@@ -768,6 +768,12 @@ BSD_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
     return SDL_FALSE;
     return SDL_FALSE;
 }
 }
 
 
+static int
+BSD_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 SDL_JoystickDriver SDL_BSD_JoystickDriver =
 SDL_JoystickDriver SDL_BSD_JoystickDriver =
 {
 {
     BSD_JoystickInit,
     BSD_JoystickInit,
@@ -780,6 +786,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver =
     BSD_JoystickGetDeviceInstanceID,
     BSD_JoystickGetDeviceInstanceID,
     BSD_JoystickOpen,
     BSD_JoystickOpen,
     BSD_JoystickRumble,
     BSD_JoystickRumble,
+    BSD_JoystickSetLED,
     BSD_JoystickUpdate,
     BSD_JoystickUpdate,
     BSD_JoystickClose,
     BSD_JoystickClose,
     BSD_JoystickQuit,
     BSD_JoystickQuit,

+ 7 - 0
src/joystick/darwin/SDL_sysjoystick.c

@@ -922,6 +922,12 @@ DARWIN_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint
     return 0;
     return 0;
 }
 }
 
 
+static int
+DARWIN_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 DARWIN_JoystickUpdate(SDL_Joystick * joystick)
 DARWIN_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -1069,6 +1075,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver =
     DARWIN_JoystickGetDeviceInstanceID,
     DARWIN_JoystickGetDeviceInstanceID,
     DARWIN_JoystickOpen,
     DARWIN_JoystickOpen,
     DARWIN_JoystickRumble,
     DARWIN_JoystickRumble,
+    DARWIN_JoystickSetLED,
     DARWIN_JoystickUpdate,
     DARWIN_JoystickUpdate,
     DARWIN_JoystickClose,
     DARWIN_JoystickClose,
     DARWIN_JoystickQuit,
     DARWIN_JoystickQuit,

+ 7 - 0
src/joystick/dummy/SDL_sysjoystick.c

@@ -89,6 +89,12 @@ DUMMY_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint1
     return SDL_Unsupported();
     return SDL_Unsupported();
 }
 }
 
 
+static int
+DUMMY_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 DUMMY_JoystickUpdate(SDL_Joystick * joystick)
 DUMMY_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -122,6 +128,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver =
     DUMMY_JoystickGetDeviceInstanceID,
     DUMMY_JoystickGetDeviceInstanceID,
     DUMMY_JoystickOpen,
     DUMMY_JoystickOpen,
     DUMMY_JoystickRumble,
     DUMMY_JoystickRumble,
+    DUMMY_JoystickSetLED,
     DUMMY_JoystickUpdate,
     DUMMY_JoystickUpdate,
     DUMMY_JoystickClose,
     DUMMY_JoystickClose,
     DUMMY_JoystickQuit,
     DUMMY_JoystickQuit,

+ 7 - 0
src/joystick/emscripten/SDL_sysjoystick.c

@@ -409,6 +409,12 @@ EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
     return SDL_FALSE;
     return SDL_FALSE;
 }
 }
 
 
+static int
+EMSCRIPTEN_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver =
 SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver =
 {
 {
     EMSCRIPTEN_JoystickInit,
     EMSCRIPTEN_JoystickInit,
@@ -421,6 +427,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver =
     EMSCRIPTEN_JoystickGetDeviceInstanceID,
     EMSCRIPTEN_JoystickGetDeviceInstanceID,
     EMSCRIPTEN_JoystickOpen,
     EMSCRIPTEN_JoystickOpen,
     EMSCRIPTEN_JoystickRumble,
     EMSCRIPTEN_JoystickRumble,
+    EMSCRIPTEN_JoystickSetLED,
     EMSCRIPTEN_JoystickUpdate,
     EMSCRIPTEN_JoystickUpdate,
     EMSCRIPTEN_JoystickClose,
     EMSCRIPTEN_JoystickClose,
     EMSCRIPTEN_JoystickQuit,
     EMSCRIPTEN_JoystickQuit,

+ 6 - 0
src/joystick/haiku/SDL_haikujoystick.cc

@@ -265,6 +265,11 @@ extern "C"
         return SDL_FALSE;
         return SDL_FALSE;
     }
     }
 
 
+    static int HAIKU_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+    {
+        return SDL_Unsupported();
+    }
+
     SDL_JoystickDriver SDL_HAIKU_JoystickDriver =
     SDL_JoystickDriver SDL_HAIKU_JoystickDriver =
     {
     {
         HAIKU_JoystickInit,
         HAIKU_JoystickInit,
@@ -277,6 +282,7 @@ extern "C"
         HAIKU_JoystickGetDeviceInstanceID,
         HAIKU_JoystickGetDeviceInstanceID,
         HAIKU_JoystickOpen,
         HAIKU_JoystickOpen,
         HAIKU_JoystickRumble,
         HAIKU_JoystickRumble,
+        HAIKU_JoystickSetLED,
         HAIKU_JoystickUpdate,
         HAIKU_JoystickUpdate,
         HAIKU_JoystickClose,
         HAIKU_JoystickClose,
         HAIKU_JoystickQuit,
         HAIKU_JoystickQuit,

+ 7 - 0
src/joystick/hidapi/SDL_hidapi_gamecube.c

@@ -363,6 +363,12 @@ HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo
     return -1;
     return -1;
 }
 }
 
 
+static int
+HIDAPI_DriverGameCube_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
 HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
 {
 {
@@ -402,6 +408,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
     HIDAPI_DriverGameCube_UpdateDevice,
     HIDAPI_DriverGameCube_UpdateDevice,
     HIDAPI_DriverGameCube_OpenJoystick,
     HIDAPI_DriverGameCube_OpenJoystick,
     HIDAPI_DriverGameCube_RumbleJoystick,
     HIDAPI_DriverGameCube_RumbleJoystick,
+    HIDAPI_DriverGameCube_SetJoystickLED,
     HIDAPI_DriverGameCube_CloseJoystick,
     HIDAPI_DriverGameCube_CloseJoystick,
     HIDAPI_DriverGameCube_FreeDevice,
     HIDAPI_DriverGameCube_FreeDevice,
     NULL,
     NULL,

+ 30 - 1
src/joystick/hidapi/SDL_hidapi_ps4.c

@@ -100,6 +100,12 @@ typedef struct {
     SDL_bool audio_supported;
     SDL_bool audio_supported;
     SDL_bool rumble_supported;
     SDL_bool rumble_supported;
     int player_index;
     int player_index;
+    Uint16 rumble_left;
+    Uint16 rumble_right;
+    Uint8 color_set;
+    Uint8 led_red;
+    Uint8 led_green;
+    Uint8 led_blue;
     Uint8 volume;
     Uint8 volume;
     Uint32 last_volume_check;
     Uint32 last_volume_check;
     PS4StatePacket_t last_state;
     PS4StatePacket_t last_state;
@@ -330,11 +336,19 @@ HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
     }
     }
     effects = (DS4EffectsState_t *)&data[offset];
     effects = (DS4EffectsState_t *)&data[offset];
 
 
+    ctx->rumble_left = low_frequency_rumble;
+    ctx->rumble_right = high_frequency_rumble;
     effects->ucRumbleLeft = (low_frequency_rumble >> 8);
     effects->ucRumbleLeft = (low_frequency_rumble >> 8);
     effects->ucRumbleRight = (high_frequency_rumble >> 8);
     effects->ucRumbleRight = (high_frequency_rumble >> 8);
 
 
     /* Populate the LED state with the appropriate color from our lookup table */
     /* Populate the LED state with the appropriate color from our lookup table */
-    SetLedsForPlayerIndex(effects, ctx->player_index);
+    if (ctx->color_set) {
+        effects->ucLedRed = ctx->led_red;
+        effects->ucLedGreen = ctx->led_green;
+        effects->ucLedBlue = ctx->led_blue;
+    } else {
+        SetLedsForPlayerIndex(effects, ctx->player_index);
+    }
 
 
     if (ctx->is_bluetooth) {
     if (ctx->is_bluetooth) {
         /* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */
         /* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */
@@ -351,6 +365,20 @@ HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
     return 0;
     return 0;
 }
 }
 
 
+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->led_red = red;
+    ctx->led_green = green;
+    ctx->led_blue = blue;
+
+    /* FIXME: Is there a better way to send this without sending another rumble packet? */
+    return HIDAPI_DriverPS4_RumbleJoystick(device, joystick, ctx->rumble_left, ctx->rumble_right);
+}
+
 static void
 static void
 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
 {
 {
@@ -536,6 +564,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
     HIDAPI_DriverPS4_UpdateDevice,
     HIDAPI_DriverPS4_UpdateDevice,
     HIDAPI_DriverPS4_OpenJoystick,
     HIDAPI_DriverPS4_OpenJoystick,
     HIDAPI_DriverPS4_RumbleJoystick,
     HIDAPI_DriverPS4_RumbleJoystick,
+    HIDAPI_DriverPS4_SetJoystickLED,
     HIDAPI_DriverPS4_CloseJoystick,
     HIDAPI_DriverPS4_CloseJoystick,
     HIDAPI_DriverPS4_FreeDevice,
     HIDAPI_DriverPS4_FreeDevice,
     NULL
     NULL

+ 8 - 0
src/joystick/hidapi/SDL_hidapi_steam.c

@@ -1034,6 +1034,13 @@ HIDAPI_DriverSteam_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
     return SDL_Unsupported();
     return SDL_Unsupported();
 }
 }
 
 
+static int
+HIDAPI_DriverSteam_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    /* You should use the full Steam Input API for LED support */
+    return SDL_Unsupported();
+}
+
 static SDL_bool
 static SDL_bool
 HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
 HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
 {
 {
@@ -1164,6 +1171,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
     HIDAPI_DriverSteam_UpdateDevice,
     HIDAPI_DriverSteam_UpdateDevice,
     HIDAPI_DriverSteam_OpenJoystick,
     HIDAPI_DriverSteam_OpenJoystick,
     HIDAPI_DriverSteam_RumbleJoystick,
     HIDAPI_DriverSteam_RumbleJoystick,
+    HIDAPI_DriverSteam_SetJoystickLED,
     HIDAPI_DriverSteam_CloseJoystick,
     HIDAPI_DriverSteam_CloseJoystick,
     HIDAPI_DriverSteam_FreeDevice,
     HIDAPI_DriverSteam_FreeDevice,
 	NULL
 	NULL

+ 7 - 0
src/joystick/hidapi/SDL_hidapi_switch.c

@@ -920,6 +920,12 @@ HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
     return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble);
     return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble);
 }
 }
 
 
+static int
+HIDAPI_DriverSwitch_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
 static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
 {
 {
     Sint16 axis;
     Sint16 axis;
@@ -1267,6 +1273,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
     HIDAPI_DriverSwitch_UpdateDevice,
     HIDAPI_DriverSwitch_UpdateDevice,
     HIDAPI_DriverSwitch_OpenJoystick,
     HIDAPI_DriverSwitch_OpenJoystick,
     HIDAPI_DriverSwitch_RumbleJoystick,
     HIDAPI_DriverSwitch_RumbleJoystick,
+    HIDAPI_DriverSwitch_SetJoystickLED,
     HIDAPI_DriverSwitch_CloseJoystick,
     HIDAPI_DriverSwitch_CloseJoystick,
     HIDAPI_DriverSwitch_FreeDevice,
     HIDAPI_DriverSwitch_FreeDevice,
     NULL
     NULL

+ 7 - 0
src/joystick/hidapi/SDL_hidapi_xbox360.c

@@ -796,6 +796,12 @@ HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
     return 0;
     return 0;
 }
 }
 
 
+static int
+HIDAPI_DriverXbox360_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 #ifdef __WIN32__
 #ifdef __WIN32__
  /* This is the packet format for Xbox 360 and Xbox One controllers on Windows,
  /* This is the packet format for Xbox 360 and Xbox One controllers on Windows,
     however with this interface there is no rumble support, no guide button,
     however with this interface there is no rumble support, no guide button,
@@ -1302,6 +1308,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
     HIDAPI_DriverXbox360_UpdateDevice,
     HIDAPI_DriverXbox360_UpdateDevice,
     HIDAPI_DriverXbox360_OpenJoystick,
     HIDAPI_DriverXbox360_OpenJoystick,
     HIDAPI_DriverXbox360_RumbleJoystick,
     HIDAPI_DriverXbox360_RumbleJoystick,
+    HIDAPI_DriverXbox360_SetJoystickLED,
     HIDAPI_DriverXbox360_CloseJoystick,
     HIDAPI_DriverXbox360_CloseJoystick,
     HIDAPI_DriverXbox360_FreeDevice,
     HIDAPI_DriverXbox360_FreeDevice,
     HIDAPI_DriverXbox360_PostUpdate,
     HIDAPI_DriverXbox360_PostUpdate,

+ 7 - 0
src/joystick/hidapi/SDL_hidapi_xbox360w.c

@@ -157,6 +157,12 @@ HIDAPI_DriverXbox360W_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo
     return 0;
     return 0;
 }
 }
 
 
+static int
+HIDAPI_DriverXbox360W_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
 HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
 {
 {
@@ -294,6 +300,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
     HIDAPI_DriverXbox360W_UpdateDevice,
     HIDAPI_DriverXbox360W_UpdateDevice,
     HIDAPI_DriverXbox360W_OpenJoystick,
     HIDAPI_DriverXbox360W_OpenJoystick,
     HIDAPI_DriverXbox360W_RumbleJoystick,
     HIDAPI_DriverXbox360W_RumbleJoystick,
+    HIDAPI_DriverXbox360W_SetJoystickLED,
     HIDAPI_DriverXbox360W_CloseJoystick,
     HIDAPI_DriverXbox360W_CloseJoystick,
     HIDAPI_DriverXbox360W_FreeDevice,
     HIDAPI_DriverXbox360W_FreeDevice,
     NULL
     NULL

+ 7 - 0
src/joystick/hidapi/SDL_hidapi_xboxone.c

@@ -364,6 +364,12 @@ HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
     return 0;
     return 0;
 }
 }
 
 
+static int
+HIDAPI_DriverXboxOne_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
 {
 {
@@ -830,6 +836,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
     HIDAPI_DriverXboxOne_UpdateDevice,
     HIDAPI_DriverXboxOne_UpdateDevice,
     HIDAPI_DriverXboxOne_OpenJoystick,
     HIDAPI_DriverXboxOne_OpenJoystick,
     HIDAPI_DriverXboxOne_RumbleJoystick,
     HIDAPI_DriverXboxOne_RumbleJoystick,
+    HIDAPI_DriverXboxOne_SetJoystickLED,
     HIDAPI_DriverXboxOne_CloseJoystick,
     HIDAPI_DriverXboxOne_CloseJoystick,
     HIDAPI_DriverXboxOne_FreeDevice,
     HIDAPI_DriverXboxOne_FreeDevice,
     NULL
     NULL

+ 18 - 0
src/joystick/hidapi/SDL_hidapijoystick.c

@@ -1048,6 +1048,23 @@ HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint
     return result;
     return result;
 }
 }
 
 
+static int
+HIDAPI_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    int result;
+
+    if (joystick->hwdata) {
+        SDL_HIDAPI_Device *device = joystick->hwdata->device;
+
+        result = device->driver->SetJoystickLED(device, joystick, red, green, blue);
+    } else {
+        SDL_SetError("SetLED failed, device disconnected");
+        result = -1;
+    }
+
+    return result;
+}
+
 static void
 static void
 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -1121,6 +1138,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
     HIDAPI_JoystickGetDeviceInstanceID,
     HIDAPI_JoystickGetDeviceInstanceID,
     HIDAPI_JoystickOpen,
     HIDAPI_JoystickOpen,
     HIDAPI_JoystickRumble,
     HIDAPI_JoystickRumble,
+    HIDAPI_JoystickSetLED,
     HIDAPI_JoystickUpdate,
     HIDAPI_JoystickUpdate,
     HIDAPI_JoystickClose,
     HIDAPI_JoystickClose,
     HIDAPI_JoystickQuit,
     HIDAPI_JoystickQuit,

+ 1 - 0
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 (*UpdateDevice)(SDL_HIDAPI_Device *device);
     SDL_bool (*OpenJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
     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);
     int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
+    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 (*CloseJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
     void (*FreeDevice)(SDL_HIDAPI_Device *device);
     void (*FreeDevice)(SDL_HIDAPI_Device *device);
     void (*PostUpdate)(void);
     void (*PostUpdate)(void);

+ 7 - 0
src/joystick/iphoneos/SDL_sysjoystick.m

@@ -1008,6 +1008,12 @@ IOS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16
 #endif
 #endif
 }
 }
 
 
+static int
+IOS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 IOS_JoystickUpdate(SDL_Joystick * joystick)
 IOS_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -1116,6 +1122,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver =
     IOS_JoystickGetDeviceInstanceID,
     IOS_JoystickGetDeviceInstanceID,
     IOS_JoystickOpen,
     IOS_JoystickOpen,
     IOS_JoystickRumble,
     IOS_JoystickRumble,
+    IOS_JoystickSetLED,
     IOS_JoystickUpdate,
     IOS_JoystickUpdate,
     IOS_JoystickClose,
     IOS_JoystickClose,
     IOS_JoystickQuit,
     IOS_JoystickQuit,

+ 7 - 0
src/joystick/linux/SDL_sysjoystick.c

@@ -891,6 +891,12 @@ LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint1
     return 0;
     return 0;
 }
 }
 
 
+static int
+LINUX_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static SDL_INLINE void
 static SDL_INLINE void
 HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
 HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
 {
 {
@@ -1366,6 +1372,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver =
     LINUX_JoystickGetDeviceInstanceID,
     LINUX_JoystickGetDeviceInstanceID,
     LINUX_JoystickOpen,
     LINUX_JoystickOpen,
     LINUX_JoystickRumble,
     LINUX_JoystickRumble,
+    LINUX_JoystickSetLED,
     LINUX_JoystickUpdate,
     LINUX_JoystickUpdate,
     LINUX_JoystickClose,
     LINUX_JoystickClose,
     LINUX_JoystickQuit,
     LINUX_JoystickQuit,

+ 8 - 0
src/joystick/virtual/SDL_virtualjoystick.c

@@ -339,6 +339,13 @@ VIRTUAL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin
 }
 }
 
 
 
 
+static int
+VIRTUAL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
+
 static void
 static void
 VIRTUAL_JoystickUpdate(SDL_Joystick * joystick)
 VIRTUAL_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -409,6 +416,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver =
     VIRTUAL_JoystickGetDeviceInstanceID,
     VIRTUAL_JoystickGetDeviceInstanceID,
     VIRTUAL_JoystickOpen,
     VIRTUAL_JoystickOpen,
     VIRTUAL_JoystickRumble,
     VIRTUAL_JoystickRumble,
+    VIRTUAL_JoystickSetLED,
     VIRTUAL_JoystickUpdate,
     VIRTUAL_JoystickUpdate,
     VIRTUAL_JoystickClose,
     VIRTUAL_JoystickClose,
     VIRTUAL_JoystickQuit,
     VIRTUAL_JoystickQuit,

+ 7 - 0
src/joystick/windows/SDL_windowsjoystick.c

@@ -500,6 +500,12 @@ WINDOWS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uin
     }
     }
 }
 }
 
 
+static int
+WINDOWS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+    return SDL_Unsupported();
+}
+
 static void
 static void
 WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
 WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
 {
 {
@@ -583,6 +589,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
     WINDOWS_JoystickGetDeviceInstanceID,
     WINDOWS_JoystickGetDeviceInstanceID,
     WINDOWS_JoystickOpen,
     WINDOWS_JoystickOpen,
     WINDOWS_JoystickRumble,
     WINDOWS_JoystickRumble,
+    WINDOWS_JoystickSetLED,
     WINDOWS_JoystickUpdate,
     WINDOWS_JoystickUpdate,
     WINDOWS_JoystickClose,
     WINDOWS_JoystickClose,
     WINDOWS_JoystickQuit,
     WINDOWS_JoystickQuit,