From d4da5df0887b87ba902cbaa870c99929deb79791 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 27 Jan 2026 11:25:38 -0800
Subject: [PATCH] Fixed unaligned access in NVIDIA SHIELD Controller driver
Also refactored the LOAD16() and LOAD32() macros into SDL_hidapijoystick_c.h
(cherry picked from commit cae2a28f5b470fc56de14c71a7edcddae101312d)
---
src/joystick/hidapi/SDL_hidapi_flydigi.c | 2 --
src/joystick/hidapi/SDL_hidapi_ps3.c | 2 --
src/joystick/hidapi/SDL_hidapi_ps4.c | 6 ----
src/joystick/hidapi/SDL_hidapi_ps5.c | 6 ----
src/joystick/hidapi/SDL_hidapi_shield.c | 38 ++++++++++++++-------
src/joystick/hidapi/SDL_hidapi_steam_hori.c | 2 --
src/joystick/hidapi/SDL_hidapi_xboxone.c | 2 --
src/joystick/hidapi/SDL_hidapijoystick_c.h | 6 ++++
8 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/src/joystick/hidapi/SDL_hidapi_flydigi.c b/src/joystick/hidapi/SDL_hidapi_flydigi.c
index 3979861733ba3..96b8b967cbce2 100644
--- a/src/joystick/hidapi/SDL_hidapi_flydigi.c
+++ b/src/joystick/hidapi/SDL_hidapi_flydigi.c
@@ -80,8 +80,6 @@ enum
#define FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND 0x1C
#define FLYDIGI_V2_INPUT_REPORT 0xEF
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
-
typedef struct
{
SDL_HIDAPI_Device *device;
diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c
index 95f6d99880414..ede49cbaa753a 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps3.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps3.c
@@ -32,8 +32,6 @@
// Define this if you want to log all packets from the controller
// #define DEBUG_PS3_PROTOCOL
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
-
typedef enum
{
k_EPS3ReportIdState = 1,
diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index de2c047ad7633..3f57a6d30f593 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps4.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps4.c
@@ -44,12 +44,6 @@
#define BLUETOOTH_DISCONNECT_TIMEOUT_MS 500
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
-#define LOAD32(A, B, C, D) ((((Uint32)(A)) << 0) | \
- (((Uint32)(B)) << 8) | \
- (((Uint32)(C)) << 16) | \
- (((Uint32)(D)) << 24))
-
enum
{
SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD = 11
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index 526d6a37069ba..133db1a13750a 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -43,12 +43,6 @@
#define ACCEL_RES_PER_G 8192.0f
#define BLUETOOTH_DISCONNECT_TIMEOUT_MS 500
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
-#define LOAD32(A, B, C, D) ((((Uint32)(A)) << 0) | \
- (((Uint32)(B)) << 8) | \
- (((Uint32)(C)) << 16) | \
- (((Uint32)(D)) << 24))
-
enum
{
SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD = 11,
diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c
index e6a25d5c716a3..a057a04865aaf 100644
--- a/src/joystick/hidapi/SDL_hidapi_shield.c
+++ b/src/joystick/hidapi/SDL_hidapi_shield.c
@@ -289,6 +289,7 @@ static bool HIDAPI_DriverShield_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *dev
static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SDL_DriverShield_Context *ctx, Uint8 *data, int size)
{
Uint64 timestamp = SDL_GetTicksNS();
+ Sint16 axis;
if (ctx->last_state[3] != data[3]) {
Uint8 hat;
@@ -346,14 +347,20 @@ static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SD
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[2] & 0x80) != 0));
}
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_Swap16LE(*(Sint16 *)&data[4]) - 0x8000);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_Swap16LE(*(Sint16 *)&data[6]) - 0x8000);
+ axis = LOAD16(data[4], data[5]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
+ axis = LOAD16(data[6], data[7]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_Swap16LE(*(Sint16 *)&data[8]) - 0x8000);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_Swap16LE(*(Sint16 *)&data[10]) - 0x8000);
+ axis = LOAD16(data[8], data[9]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
+ axis = LOAD16(data[10], data[11]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_Swap16LE(*(Sint16 *)&data[12]) - 0x8000);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, SDL_Swap16LE(*(Sint16 *)&data[14]) - 0x8000);
+ axis = LOAD16(data[12], data[13]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
+ axis = LOAD16(data[14], data[15]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
@@ -379,6 +386,7 @@ static void HIDAPI_DriverShield_HandleTouchPacketV103(SDL_Joystick *joystick, SD
static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SDL_DriverShield_Context *ctx, Uint8 *data, int size)
{
Uint64 timestamp = SDL_GetTicksNS();
+ Sint16 axis;
if (size < 23) {
return;
@@ -434,14 +442,20 @@ static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SD
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[4] & 0x01) != 0));
}
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_Swap16LE(*(Sint16 *)&data[9]) - 0x8000);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_Swap16LE(*(Sint16 *)&data[11]) - 0x8000);
+ axis = LOAD16(data[9], data[10]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
+ axis = LOAD16(data[11], data[12]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_Swap16LE(*(Sint16 *)&data[13]) - 0x8000);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_Swap16LE(*(Sint16 *)&data[15]) - 0x8000);
+ axis = LOAD16(data[13], data[14]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
+ axis = LOAD16(data[15], data[16]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_Swap16LE(*(Sint16 *)&data[19]) - 0x8000);
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, SDL_Swap16LE(*(Sint16 *)&data[21]) - 0x8000);
+ axis = LOAD16(data[19], data[20]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
+ axis = LOAD16(data[21], data[22]) - 0x8000;
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
if (ctx->last_state[17] != data[17]) {
//SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_SHARE, ((data[17] & 0x01) != 0));
diff --git a/src/joystick/hidapi/SDL_hidapi_steam_hori.c b/src/joystick/hidapi/SDL_hidapi_steam_hori.c
index d92634d54accd..8d445c979119f 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam_hori.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam_hori.c
@@ -32,8 +32,6 @@
/* Define this if you want to log all packets from the controller */
/*#define DEBUG_HORI_PROTOCOL*/
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
-
enum
{
SDL_GAMEPAD_BUTTON_HORI_QAM = 11,
diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c
index 6f7e57e2c3f2f..11e7f574cece3 100644
--- a/src/joystick/hidapi/SDL_hidapi_xboxone.c
+++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c
@@ -52,8 +52,6 @@
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD -25058 // Uint8 30 scaled to Sint16 full range
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
-
enum
{
SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON = 11
diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h
index 857b466980335..6129441881a47 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick_c.h
+++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h
@@ -176,6 +176,12 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverFlydigi;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSInput;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverZUIKI;
+#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
+#define LOAD32(A, B, C, D) ((((Uint32)(A)) << 0) | \
+ (((Uint32)(B)) << 8) | \
+ (((Uint32)(C)) << 16) | \
+ (((Uint32)(D)) << 24))
+
// Return true if a HID device is present and supported as a joystick of the given type
extern bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type);