From 5a3adbfdb22e6f3d9d8260356ad9a7e44f8ae829 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 19 Aug 2022 11:11:25 -0700
Subject: [PATCH] Added the hint SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED
to control whether the player LED is set on Xbox 360 controllers
---
include/SDL_hints.h | 9 ++++
src/joystick/hidapi/SDL_hidapi_xbox360.c | 59 ++++++++++++++++++-----
src/joystick/hidapi/SDL_hidapi_xbox360w.c | 58 +++++++++++++++++++---
3 files changed, 108 insertions(+), 18 deletions(-)
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index c13c206241b..d99fe1373f5 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -862,6 +862,15 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 "SDL_JOYSTICK_HIDAPI_XBOX_360"
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with an Xbox 360 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_XBOX_360_PLAYER_LED "SDL_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED"
+
/**
* \brief A variable controlling whether the HIDAPI driver for XBox 360 wireless controllers should be used.
*
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c
index 2ac3b17ba73..a3a968ba9fb 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c
@@ -26,6 +26,7 @@
#include "SDL_timer.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
+#include "../../SDL_hints_c.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
@@ -38,6 +39,9 @@
typedef struct {
+ SDL_HIDAPI_Device *device;
+ int player_index;
+ SDL_bool player_lights;
Uint8 last_state[USB_PACKET_LENGTH];
} SDL_DriverXbox360_Context;
@@ -110,10 +114,10 @@ HIDAPI_DriverXbox360_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 pr
return NULL;
}
-static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
+static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot, SDL_bool on)
{
const SDL_bool blink = SDL_FALSE;
- Uint8 mode = (blink ? 0x02 : 0x06) + slot;
+ Uint8 mode = on ? ((blink ? 0x02 : 0x06) + slot) : 0;
Uint8 led_packet[] = { 0x01, 0x03, 0x00 };
led_packet[2] = mode;
@@ -123,6 +127,27 @@ static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
return SDL_TRUE;
}
+static void UpdateSlotLED(SDL_DriverXbox360_Context *ctx)
+{
+ if (ctx->player_lights && ctx->player_lights >= 0) {
+ SetSlotLED(ctx->device->dev, (ctx->player_index % 4), SDL_TRUE);
+ } else {
+ SetSlotLED(ctx->device->dev, 0, SDL_FALSE);
+ }
+}
+
+static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)userdata;
+ SDL_bool player_lights = SDL_GetStringBoolean(hint, SDL_TRUE);
+
+ if (player_lights != ctx->player_lights) {
+ ctx->player_lights = player_lights;
+
+ UpdateSlotLED(ctx);
+ }
+}
+
static SDL_bool
HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device)
{
@@ -138,25 +163,28 @@ HIDAPI_DriverXbox360_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystic
static void
HIDAPI_DriverXbox360_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
- if (!device->dev) {
+ SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context;
+
+ if (!ctx) {
return;
}
- if (player_index >= 0) {
- SetSlotLED(device->dev, (player_index % 4));
- }
+
+ ctx->player_index = player_index;
+
+ UpdateSlotLED(ctx);
}
static SDL_bool
HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverXbox360_Context *ctx;
- int player_index;
ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
return SDL_FALSE;
}
+ ctx->device = device;
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
@@ -166,11 +194,13 @@ HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
}
device->context = ctx;
- /* Set the controller LED */
- player_index = SDL_JoystickGetPlayerIndex(joystick);
- if (player_index >= 0) {
- SetSlotLED(device->dev, (player_index % 4));
- }
+ /* Initialize player index (needed for setting LEDs) */
+ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick);
+ ctx->player_lights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED, SDL_TRUE);
+ UpdateSlotLED(ctx);
+
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED,
+ SDL_PlayerLEDHintChanged, ctx);
/* Initialize the joystick capabilities */
joystick->nbuttons = 15;
@@ -337,6 +367,11 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
static void
HIDAPI_DriverXbox360_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
+ SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context;
+
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED,
+ SDL_PlayerLEDHintChanged, ctx);
+
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c
index a75d1bd599d..2d0ad026ef1 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c
@@ -26,6 +26,7 @@
#include "SDL_timer.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
+#include "../../SDL_hints_c.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
@@ -38,7 +39,11 @@
typedef struct {
+ SDL_HIDAPI_Device *device;
SDL_bool connected;
+ SDL_bool opened;
+ int player_index;
+ SDL_bool player_lights;
Uint8 last_state[USB_PACKET_LENGTH];
} SDL_DriverXbox360W_Context;
@@ -87,10 +92,10 @@ HIDAPI_DriverXbox360W_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 p
return "Xbox 360 Wireless Controller";
}
-static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
+static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot, SDL_bool on)
{
const SDL_bool blink = SDL_FALSE;
- Uint8 mode = (blink ? 0x02 : 0x06) + slot;
+ Uint8 mode = on ? ((blink ? 0x02 : 0x06) + slot) : 0;
Uint8 led_packet[] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
led_packet[3] = 0x40 + (mode % 0x0e);
@@ -100,6 +105,27 @@ static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
return SDL_TRUE;
}
+static void UpdateSlotLED(SDL_DriverXbox360W_Context *ctx)
+{
+ if (ctx->player_lights && ctx->player_lights >= 0) {
+ SetSlotLED(ctx->device->dev, (ctx->player_index % 4), SDL_TRUE);
+ } else {
+ SetSlotLED(ctx->device->dev, 0, SDL_FALSE);
+ }
+}
+
+static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)userdata;
+ SDL_bool player_lights = SDL_GetStringBoolean(hint, SDL_TRUE);
+
+ if (player_lights != ctx->player_lights) {
+ ctx->player_lights = player_lights;
+
+ UpdateSlotLED(ctx);
+ }
+}
+
static void
UpdatePowerLevel(SDL_Joystick *joystick, Uint8 level)
{
@@ -129,6 +155,7 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
SDL_OutOfMemory();
return SDL_FALSE;
}
+ ctx->device = device;
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
@@ -155,12 +182,15 @@ HIDAPI_DriverXbox360W_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joysti
static void
HIDAPI_DriverXbox360W_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
- if (!device->dev) {
+ SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context;
+
+ if (!ctx) {
return;
}
- if (player_index >= 0) {
- SetSlotLED(device->dev, (player_index % 4));
- }
+
+ ctx->player_index = player_index;
+
+ UpdateSlotLED(ctx);
}
static SDL_bool
@@ -170,6 +200,16 @@ HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
SDL_zeroa(ctx->last_state);
+ ctx->opened = SDL_TRUE;
+
+ /* Initialize player index (needed for setting LEDs) */
+ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick);
+ ctx->player_lights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED, SDL_TRUE);
+ UpdateSlotLED(ctx);
+
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED,
+ SDL_PlayerLEDHintChanged, ctx);
+
/* Initialize the joystick capabilities */
joystick->nbuttons = 15;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
@@ -339,6 +379,12 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
static void
HIDAPI_DriverXbox360W_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
+ SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context;
+
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED,
+ SDL_PlayerLEDHintChanged, ctx);
+
+ ctx->opened = SDL_FALSE;
}
static void