Added the hint SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED to control whether the player LED should be lit on the Nintendo Wii controllers Also fixed the Y axes on the Wii U Pro controller, and various formatting cleanup
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 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
diff --git a/WhatsNew.txt b/WhatsNew.txt
index 1870f56..0318b90 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -7,6 +7,8 @@ This is a list of major changes in SDL's version history.
General:
* Added SDL_GetJoystickGUIDInfo() to get device information encoded in a joystick GUID
+* Added support for Nintendo Wii controllers to the HIDAPI driver, and a hint SDL_HINT_JOYSTICK_HIDAPI_WII to control whether this is used
+* Added the hint SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED to control whether the player LED should be lit on the Nintendo Wii controllers
---------------------------------------------------------------------------
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 60b6287..10171c4 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -866,6 +866,15 @@ extern "C" {
#define SDL_HINT_JOYSTICK_HIDAPI_WII "SDL_JOYSTICK_HIDAPI_WII"
/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Wii 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_WII_PLAYER_LED "SDL_JOYSTICK_HIDAPI_WII_PLAYER_LED"
+
+/**
* \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used.
*
* This variable can be set to the following values:
diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c
index 0aae485..59dfd46 100644
--- a/src/joystick/hidapi/SDL_hidapi_wii.c
+++ b/src/joystick/hidapi/SDL_hidapi_wii.c
@@ -100,10 +100,11 @@ typedef struct {
SDL_HIDAPI_Device *device;
EWiiExtensionControllerType m_eExtensionControllerType;
SDL_bool m_bUseButtonLabels;
+ SDL_bool m_bPlayerLights;
+ int m_nPlayerIndex;
SDL_bool m_bRumbleActive;
Uint8 m_rgucReadBuffer[k_unWiiPacketDataLength];
Uint32 m_iLastStatus;
- int m_playerIndex;
struct StickCalibrationData {
Uint16 min;
@@ -344,7 +345,7 @@ static void UpdatePowerLevelWiiU(SDL_Joystick *joystick, Uint8 extensionBatteryB
static SDL_bool IdentifyController(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
{
- static const Uint8 statusRequest[2] = { k_eWiiOutputReportIDs_StatusRequest, 0 };
+ const Uint8 statusRequest[2] = { k_eWiiOutputReportIDs_StatusRequest, 0 };
SDL_bool hasExtension;
WriteOutput(ctx, statusRequest, sizeof(statusRequest), SDL_TRUE);
if (!ReadInputSync(ctx, k_eWiiInputReportIDs_Status, NULL)) {
@@ -354,12 +355,15 @@ static SDL_bool IdentifyController(SDL_DriverWii_Context *ctx, SDL_Joystick *joy
hasExtension = ctx->m_rgucReadBuffer[3] & 2 ? SDL_TRUE : SDL_FALSE;
if (hasExtension) {
/* http://wiibrew.org/wiki/Wiimote/Extension_Controllers#The_New_Way */
- Uint8 data[2] = {0x55, 0x00};
- SDL_bool ok = WriteRegister(ctx, 0xA400F0, &data[0], 1, SDL_TRUE)
- && WriteRegister(ctx, 0xA400FB, &data[1], 1, SDL_TRUE)
+ Uint8 data_0x55 = 0x55;
+ Uint8 data_0x00 = 0x00;
+ SDL_bool ok = WriteRegister(ctx, 0xA400F0, &data_0x55, sizeof(data_0x55), SDL_TRUE)
+ && WriteRegister(ctx, 0xA400FB, &data_0x00, sizeof(data_0x00), SDL_TRUE)
&& ReadRegister(ctx, 0xA400FA, 6, SDL_TRUE)
&& ParseExtensionResponse(ctx);
- if (!ok) { return SDL_FALSE; }
+ if (!ok) {
+ return SDL_FALSE;
+ }
} else {
ctx->m_eExtensionControllerType = k_eWiiExtensionControllerType_None;
}
@@ -382,13 +386,14 @@ static EWiiInputReportIDs GetButtonPacketType(SDL_DriverWii_Context *ctx)
static SDL_bool RequestButtonPacketType(SDL_DriverWii_Context *ctx, EWiiInputReportIDs type)
{
- Uint8 tt = ctx->m_bRumbleActive;
Uint8 data[3];
+ Uint8 tt = ctx->m_bRumbleActive;
+
/* Continuous reporting off, tt & 4 == 0 */
data[0] = k_eWiiOutputReportIDs_DataReportingMode;
data[1] = tt;
data[2] = type;
- return WriteOutput(ctx, data, 3, SDL_FALSE);
+ return WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
}
static void InitStickCalibrationData(SDL_DriverWii_Context *ctx)
@@ -428,12 +433,18 @@ static void InitStickCalibrationData(SDL_DriverWii_Context *ctx)
static const char* GetNameFromExtensionInfo(SDL_DriverWii_Context *ctx)
{
switch (ctx->m_eExtensionControllerType) {
- case k_eWiiExtensionControllerType_None: return "Nintendo Wii Remote";
- case k_eWiiExtensionControllerType_Nunchuck: return "Nintendo Wii Remote with Nunchuck";
- case k_eWiiExtensionControllerType_ClassicController: return "Nintendo Wii Remote with Classic Controller";
- case k_eWiiExtensionControllerType_ClassicControllerPro: return "Nintendo Wii Remote with Classic Controller Pro";
- case k_eWiiExtensionControllerType_WiiUPro: return "Nintendo Wii U Pro Controller";
- default: return "Nintendo Wii Remote with Unknown Extension";
+ case k_eWiiExtensionControllerType_None:
+ return "Nintendo Wii Remote";
+ case k_eWiiExtensionControllerType_Nunchuck:
+ return "Nintendo Wii Remote with Nunchuck";
+ case k_eWiiExtensionControllerType_ClassicController:
+ return "Nintendo Wii Remote with Classic Controller";
+ case k_eWiiExtensionControllerType_ClassicControllerPro:
+ return "Nintendo Wii Remote with Classic Controller Pro";
+ case k_eWiiExtensionControllerType_WiiUPro:
+ return "Nintendo Wii U Pro Controller";
+ default:
+ return "Nintendo Wii Remote with Unknown Extension";
}
}
@@ -446,6 +457,7 @@ static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata,
static Uint8 RemapButton(SDL_DriverWii_Context *ctx, Uint8 button)
{
if (!ctx->m_bUseButtonLabels) {
+ /* Use button positions */
switch (button) {
case SDL_CONTROLLER_BUTTON_A:
return SDL_CONTROLLER_BUTTON_B;
@@ -462,6 +474,51 @@ static Uint8 RemapButton(SDL_DriverWii_Context *ctx, Uint8 button)
return button;
}
+static void UpdateSlotLED(SDL_DriverWii_Context *ctx)
+{
+ Uint8 leds;
+ Uint8 data[2];
+
+ /* The lowest bit needs to have the rumble status */
+ leds = ctx->m_bRumbleActive;
+
+ if (ctx->m_bPlayerLights) {
+ /* Use the same LED codes as Smash 8-player for 5-7 */
+ if (ctx->m_nPlayerIndex == 0 || ctx->m_nPlayerIndex > 3) {
+ leds |= k_eWiiPlayerLEDs_P1;
+ }
+ if (ctx->m_nPlayerIndex == 1 || ctx->m_nPlayerIndex == 4) {
+ leds |= k_eWiiPlayerLEDs_P2;
+ }
+ if (ctx->m_nPlayerIndex == 2 || ctx->m_nPlayerIndex == 5) {
+ leds |= k_eWiiPlayerLEDs_P3;
+ }
+ if (ctx->m_nPlayerIndex == 3 || ctx->m_nPlayerIndex == 6) {
+ leds |= k_eWiiPlayerLEDs_P4;
+ }
+ /* Turn on all lights for other player indexes */
+ if (ctx->m_nPlayerIndex < 0 || ctx->m_nPlayerIndex > 6) {
+ leds |= k_eWiiPlayerLEDs_P1 | k_eWiiPlayerLEDs_P2 | k_eWiiPlayerLEDs_P3 | k_eWiiPlayerLEDs_P4;
+ }
+ }
+
+ data[0] = k_eWiiOutputReportIDs_LEDs;
+ data[1] = leds;
+ WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
+}
+
+static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)userdata;
+ SDL_bool bPlayerLights = SDL_GetStringBoolean(hint, SDL_TRUE);
+
+ if (bPlayerLights != ctx->m_bPlayerLights) {
+ ctx->m_bPlayerLights = bPlayerLights;
+
+ UpdateSlotLED(ctx);
+ }
+}
+
static SDL_bool
HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device)
{
@@ -471,9 +528,6 @@ HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device)
static int
HIDAPI_DriverWii_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
{
- if (device->context) {
- return ((SDL_DriverWii_Context *)device->context)->m_playerIndex;
- }
return -1;
}
@@ -481,37 +535,14 @@ static void
HIDAPI_DriverWii_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
SDL_DriverWii_Context *ctx = device->context;
- Uint8 leds;
- Uint8 data[2];
if (!ctx) {
return;
}
- ctx->m_playerIndex = player_index;
-
- leds = ctx->m_bRumbleActive;
- /* Use the same LED codes as Smash 8-player for 5-7 */
- if (player_index == 1 || player_index > 4) {
- leds |= k_eWiiPlayerLEDs_P1;
- }
- if (player_index == 2 || player_index == 5) {
- leds |= k_eWiiPlayerLEDs_P2;
- }
- if (player_index == 3 || player_index == 6) {
- leds |= k_eWiiPlayerLEDs_P3;
- }
- if (player_index == 4 || player_index == 7) {
- leds |= k_eWiiPlayerLEDs_P4;
- }
- /* Turn on all lights for other player indexes */
- if (player_index < 1 || player_index > 7) {
- leds |= k_eWiiPlayerLEDs_P1 | k_eWiiPlayerLEDs_P2 | k_eWiiPlayerLEDs_P3 | k_eWiiPlayerLEDs_P4;
- }
+ ctx->m_nPlayerIndex = player_index;
- data[0] = k_eWiiOutputReportIDs_LEDs;
- data[1] = leds;
- WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
+ UpdateSlotLED(ctx);
}
static SDL_bool
@@ -547,6 +578,14 @@ HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
SDL_free(device->name);
device->name = SDL_strdup(GetNameFromExtensionInfo(ctx));
+ /* Initialize player index (needed for setting LEDs) */
+ ctx->m_nPlayerIndex = SDL_JoystickGetPlayerIndex(joystick);
+ ctx->m_bPlayerLights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED, SDL_TRUE);
+ UpdateSlotLED(ctx);
+
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED,
+ SDL_PlayerLEDHintChanged, ctx);
+
/* Initialize the joystick capabilities */
if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_WiiUPro) {
joystick->nbuttons = 15;
@@ -556,7 +595,6 @@ HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
}
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
- HIDAPI_DriverWii_SetDevicePlayerIndex(device, 0, SDL_JoystickGetPlayerIndex(joystick));
RequestButtonPacketType(ctx, GetButtonPacketType(ctx));
return SDL_TRUE;
@@ -653,6 +691,11 @@ static void PostStickCalibrated(SDL_Joystick *joystick, struct StickCalibrationD
float fvalue = (float)distance / (float)range;
value = (Sint16)(fvalue * SDL_MAX_SINT16);
}
+ if (axis == SDL_CONTROLLER_AXIS_LEFTY || axis == SDL_CONTROLLER_AXIS_RIGHTY) {
+ if (value) {
+ value = ~value;
+ }
+ }
SDL_PrivateJoystickAxis(joystick, axis, value);
}
@@ -817,6 +860,7 @@ HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
SDL_Joystick *joystick = NULL;
int size;
+ Uint32 now;
if (device->num_joysticks > 0) {
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
@@ -833,12 +877,15 @@ HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
}
/* Request a status update periodically to make sure our battery value is up to date */
- if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_iLastStatus + FIFTEEN_MINUTES_IN_MS)) {
+ now = SDL_GetTicks();
+ if (SDL_TICKS_PASSED(now, ctx->m_iLastStatus + FIFTEEN_MINUTES_IN_MS)) {
Uint8 data[2];
- ctx->m_iLastStatus = SDL_GetTicks();
+
data[0] = k_eWiiOutputReportIDs_StatusRequest;
data[1] = ctx->m_bRumbleActive;
- WriteOutput(ctx, data, 2, SDL_FALSE);
+ WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
+
+ ctx->m_iLastStatus = now;
}
if (size < 0) {
@@ -856,6 +903,9 @@ HIDAPI_DriverWii_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED,
+ SDL_PlayerLEDHintChanged, ctx);
+
SDL_LockMutex(device->dev_lock);
{
SDL_hid_close(device->dev);