Added the hint SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED to control whether the player LED is set on Xbox 360 controllers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index c13c206..d99fe13 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -863,6 +863,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.
*
* This variable can be set to the following values:
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c
index 2ac3b17..a3a968b 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 a75d1bd..2d0ad02 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