Fixed regression handling touchpad input with PS5 controllers using the original shipping firmware
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
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index 172d5e6..771911c 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -109,14 +109,19 @@ typedef struct
Uint8 rgucAccelX[2]; /* 21 */
Uint8 rgucAccelY[2]; /* 23 */
Uint8 rgucAccelZ[2]; /* 25 */
- Uint8 rgucUnknown1[4]; /* 27 */
- Uint8 ucTouchpadCounter1; /* 31 - high bit clear + counter */
- Uint8 rgucTouchpadData1[3]; /* 32 - X/Y, 12 bits per axis */
- Uint8 ucTouchpadCounter2; /* 35 - high bit clear + counter */
- Uint8 rgucTouchpadData2[3]; /* 36 - X/Y, 12 bits per axis */
+ Uint8 rgucTimer1[4]; /* 27 - 32 bit little endian */
+ Uint8 ucBatteryTemp; /* 31 */
+ Uint8 ucTouchpadCounter1; /* 32 - high bit clear + counter */
+ Uint8 rgucTouchpadData1[3]; /* 33 - X/Y, 12 bits per axis */
+ Uint8 ucTouchpadCounter2; /* 36 - high bit clear + counter */
+ Uint8 rgucTouchpadData2[3]; /* 37 - X/Y, 12 bits per axis */
+ Uint8 rgucUnknown1[8]; /* 40 */
+ Uint8 rgucTimer2[4]; /* 48 - 32 bit little endian */
+ Uint8 ucBatteryLevel; /* 52 */
+ Uint8 ucConnectState; /* 53 - 0x08 = USB, 0x01 = headphone */
/* There's more unknown data at the end, and a 32-bit CRC on Bluetooth */
-} PS5StatePacketV1_t;
+} PS5StatePacket_t;
typedef struct
{
@@ -135,19 +140,14 @@ typedef struct
Uint8 rgucAccelX[2]; /* 21 */
Uint8 rgucAccelY[2]; /* 23 */
Uint8 rgucAccelZ[2]; /* 25 */
- Uint8 rgucTimer1[4]; /* 27 - 32 bit little endian */
- Uint8 ucBatteryTemp; /* 31 */
- Uint8 ucTouchpadCounter1; /* 32 - high bit clear + counter */
- Uint8 rgucTouchpadData1[3]; /* 33 - X/Y, 12 bits per axis */
- Uint8 ucTouchpadCounter2; /* 36 - high bit clear + counter */
- Uint8 rgucTouchpadData2[3]; /* 37 - X/Y, 12 bits per axis */
- Uint8 rgucUnknown1[8]; /* 40 */
- Uint8 rgucTimer2[4]; /* 48 - 32 bit little endian */
- Uint8 ucBatteryLevel; /* 52 */
- Uint8 ucConnectState; /* 53 - 0x08 = USB, 0x01 = headphone */
+ Uint8 rgucUnknown1[4]; /* 27 */
+ Uint8 ucTouchpadCounter1; /* 31 - high bit clear + counter */
+ Uint8 rgucTouchpadData1[3]; /* 32 - X/Y, 12 bits per axis */
+ Uint8 ucTouchpadCounter2; /* 35 - high bit clear + counter */
+ Uint8 rgucTouchpadData2[3]; /* 36 - X/Y, 12 bits per axis */
/* There's more unknown data at the end, and a 32-bit CRC on Bluetooth */
-} PS5StatePacketV2_t;
+} PS5StatePacketAlt_t;
typedef struct
{
@@ -198,6 +198,7 @@ typedef struct {
SDL_HIDAPI_Device *device;
SDL_Joystick *joystick;
SDL_bool is_bluetooth;
+ SDL_bool use_alternate_report;
SDL_bool effects_supported;
SDL_bool sensors_supported;
SDL_bool touchpad_supported;
@@ -221,6 +222,7 @@ typedef struct {
{
PS5SimpleStatePacket_t simple;
PS5StatePacketCommon_t state;
+ PS5StatePacket_t full_state;
Uint8 data[64];
} last_state;
} SDL_DriverPS5_Context;
@@ -250,6 +252,16 @@ static SDL_bool HIDAPI_DriverPS5_HasTouchpad(Uint16 vendor_id, Uint16 product_id
return SDL_TRUE;
}
+static SDL_bool HIDAPI_DriverPS5_UseAlternateReport(Uint16 vendor_id, Uint16 product_id)
+{
+ /* The Hori Fighting Stick Alpha reports touchpad at a different offset than the PS5 controller */
+ if (vendor_id == USB_VENDOR_HORI && product_id == USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5) {
+ return SDL_TRUE;
+ }
+
+ return SDL_FALSE;
+}
+
static int HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size);
static void
@@ -553,11 +565,11 @@ HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device)
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
SDL_bool led_reset_complete = SDL_FALSE;
- if (ctx->firmware_version <= 0x204) {
+ if (ctx->use_alternate_report) {
/* We don't know how to check the timer, just assume it's complete for now */
led_reset_complete = SDL_TRUE;
} else {
- const PS5StatePacketV2_t *packet = (PS5StatePacketV2_t *)ctx->last_state.data;
+ const PS5StatePacket_t *packet = &ctx->last_state.full_state;
/* Check the timer to make sure the Bluetooth connection LED animation is complete */
const Uint32 connection_complete = 10200000;
@@ -730,6 +742,10 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
}
}
+ if (HIDAPI_DriverPS5_UseAlternateReport(device->vendor_id, device->product_id)) {
+ ctx->use_alternate_report = SDL_TRUE;
+ }
+
if (HIDAPI_DriverPS5_CanRumble(device->vendor_id, device->product_id)) {
ctx->effects_supported = SDL_TRUE;
}
@@ -1116,30 +1132,7 @@ HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL_hid_device
}
static void
-HIDAPI_DriverPS5_HandleStatePacketV1(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacketV1_t *packet)
-{
- static const float TOUCHPAD_SCALEX = 1.0f / 1920;
- static const float TOUCHPAD_SCALEY = 1.0f / 1070;
- Uint8 touchpad_state;
- int touchpad_x, touchpad_y;
-
- if (ctx->report_touchpad) {
- touchpad_state = ((packet->ucTouchpadCounter1 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED;
- touchpad_x = packet->rgucTouchpadData1[0] | (((int)packet->rgucTouchpadData1[1] & 0x0F) << 8);
- touchpad_y = (packet->rgucTouchpadData1[1] >> 4) | ((int)packet->rgucTouchpadData1[2] << 4);
- SDL_PrivateJoystickTouchpad(joystick, 0, 0, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
-
- touchpad_state = ((packet->ucTouchpadCounter2 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED;
- touchpad_x = packet->rgucTouchpadData2[0] | (((int)packet->rgucTouchpadData2[1] & 0x0F) << 8);
- touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int)packet->rgucTouchpadData2[2] << 4);
- SDL_PrivateJoystickTouchpad(joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
- }
-
- SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
-}
-
-static void
-HIDAPI_DriverPS5_HandleStatePacketV2(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacketV2_t *packet)
+HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
@@ -1181,6 +1174,29 @@ HIDAPI_DriverPS5_HandleStatePacketV2(SDL_Joystick *joystick, SDL_hid_device *dev
SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
}
+static void
+HIDAPI_DriverPS5_HandleStatePacketAlt(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacketAlt_t *packet)
+{
+ static const float TOUCHPAD_SCALEX = 1.0f / 1920;
+ static const float TOUCHPAD_SCALEY = 1.0f / 1070;
+ Uint8 touchpad_state;
+ int touchpad_x, touchpad_y;
+
+ if (ctx->report_touchpad) {
+ touchpad_state = ((packet->ucTouchpadCounter1 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED;
+ touchpad_x = packet->rgucTouchpadData1[0] | (((int) packet->rgucTouchpadData1[1] & 0x0F) << 8);
+ touchpad_y = (packet->rgucTouchpadData1[1] >> 4) | ((int) packet->rgucTouchpadData1[2] << 4);
+ SDL_PrivateJoystickTouchpad(joystick, 0, 0, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
+
+ touchpad_state = ((packet->ucTouchpadCounter2 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED;
+ touchpad_x = packet->rgucTouchpadData2[0] | (((int) packet->rgucTouchpadData2[1] & 0x0F) << 8);
+ touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int) packet->rgucTouchpadData2[2] << 4);
+ SDL_PrivateJoystickTouchpad(joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
+ }
+
+ SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
+}
+
static SDL_bool
HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
{
@@ -1210,10 +1226,10 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
HIDAPI_DriverPS5_HandleSimpleStatePacket(joystick, device->dev, ctx, (PS5SimpleStatePacket_t *)&data[1]);
} else {
HIDAPI_DriverPS5_HandleStatePacketCommon(joystick, device->dev, ctx, (PS5StatePacketCommon_t *)&data[1]);
- if (ctx->firmware_version <= 0x204) {
- HIDAPI_DriverPS5_HandleStatePacketV1(joystick, device->dev, ctx, (PS5StatePacketV1_t *)&data[1]);
+ if (ctx->use_alternate_report) {
+ HIDAPI_DriverPS5_HandleStatePacketAlt(joystick, device->dev, ctx, (PS5StatePacketAlt_t *)&data[1]);
} else {
- HIDAPI_DriverPS5_HandleStatePacketV2(joystick, device->dev, ctx, (PS5StatePacketV2_t *)&data[1]);
+ HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[1]);
}
}
break;
@@ -1226,10 +1242,10 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
HIDAPI_DriverPS5_CheckPendingLEDReset(device);
}
HIDAPI_DriverPS5_HandleStatePacketCommon(joystick, device->dev, ctx, (PS5StatePacketCommon_t *)&data[2]);
- if (ctx->firmware_version <= 0x204) {
- HIDAPI_DriverPS5_HandleStatePacketV1(joystick, device->dev, ctx, (PS5StatePacketV1_t *)&data[2]);
+ if (ctx->use_alternate_report) {
+ HIDAPI_DriverPS5_HandleStatePacketAlt(joystick, device->dev, ctx, (PS5StatePacketAlt_t *)&data[2]);
} else {
- HIDAPI_DriverPS5_HandleStatePacketV2(joystick, device->dev, ctx, (PS5StatePacketV2_t *)&data[2]);
+ HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[2]);
}
break;
default: