diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 7326a7041..bda9dab22 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -431,6 +431,7 @@
+
diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index ed593a6fd..e969617f2 100644
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -3979,6 +3979,15 @@
F3950CD8212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
F3950CD9212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
F3950CDA212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ F3A4909E2554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A4909F2554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A02554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A12554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A22554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A32554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A42554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A52554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
+ F3A490A62554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; };
FA24348B21D41FFB00B8918A /* SDL_metal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348A21D41FFB00B8918A /* SDL_metal.h */; settings = {ATTRIBUTES = (Public, ); }; };
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
@@ -4531,6 +4540,7 @@
F37DC5F225350EBC0002E6F7 /* CoreHaptics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreHaptics.framework; path = System/Library/Frameworks/CoreHaptics.framework; sourceTree = SDKROOT; };
F37DC5F425350ECC0002E6F7 /* CoreHaptics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreHaptics.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS14.0.sdk/System/Library/Frameworks/CoreHaptics.framework; sourceTree = DEVELOPER_DIR; };
F3950CD7212BC88D00F51292 /* SDL_sensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sensor.h; sourceTree = ""; };
+ F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_ps5.c; sourceTree = ""; };
F59C710300D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = ""; };
F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; };
F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
@@ -5448,6 +5458,7 @@
children = (
A7D8A7C923E2513E00DCD162 /* SDL_hidapi_gamecube.c */,
A7D8A7C323E2513E00DCD162 /* SDL_hidapi_ps4.c */,
+ F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */,
A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */,
A75FDBC323EA380300529352 /* SDL_hidapi_rumble.h */,
A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */,
@@ -8471,6 +8482,7 @@
A75FCDE923E25AB700529352 /* SDL_drawline.c in Sources */,
A75FCDEA23E25AB700529352 /* SDL_yuv.c in Sources */,
A75FCDEB23E25AB700529352 /* SDL_sysfilesystem.m in Sources */,
+ F3A490A52554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A75FCDEC23E25AB700529352 /* e_pow.c in Sources */,
A75FCDED23E25AB700529352 /* SDL_systls.c in Sources */,
A75FCDEE23E25AB700529352 /* SDL_vulkan_utils.c in Sources */,
@@ -8671,6 +8683,7 @@
A75FCFA223E25AC700529352 /* SDL_drawline.c in Sources */,
A75FCFA323E25AC700529352 /* SDL_yuv.c in Sources */,
A75FCFA423E25AC700529352 /* SDL_sysfilesystem.m in Sources */,
+ F3A490A62554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A75FCFA523E25AC700529352 /* e_pow.c in Sources */,
A75FCFA623E25AC700529352 /* SDL_systls.c in Sources */,
A75FCFA723E25AC700529352 /* SDL_vulkan_utils.c in Sources */,
@@ -8979,6 +8992,7 @@
A769B1C523E259AE00872273 /* SDL_wave.c in Sources */,
A769B1C623E259AE00872273 /* s_tan.c in Sources */,
A769B1C723E259AE00872273 /* SDL_hints.c in Sources */,
+ F3A490A32554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A769B1C823E259AE00872273 /* SDL_hidapi_ps4.c in Sources */,
A769B1C923E259AE00872273 /* SDL_pixels.c in Sources */,
A769B1CA23E259AE00872273 /* SDL_x11clipboard.c in Sources */,
@@ -9265,6 +9279,7 @@
A7D8BA5C23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
A7D8B14123E2514200DCD162 /* SDL_blit_1.c in Sources */,
5605720F2473688000B46B66 /* SDL_locale.c in Sources */,
+ F3A4909F2554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A7D8B17D23E2514200DCD162 /* SDL_x11dyn.c in Sources */,
A7D8BB1623E2514500DCD162 /* SDL_mouse.c in Sources */,
A7D8BADA23E2514500DCD162 /* e_rem_pio2.c in Sources */,
@@ -9464,6 +9479,7 @@
A7D8BA5D23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
A7D8B14223E2514200DCD162 /* SDL_blit_1.c in Sources */,
560572102473688000B46B66 /* SDL_locale.c in Sources */,
+ F3A490A02554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A7D8B17E23E2514200DCD162 /* SDL_x11dyn.c in Sources */,
A7D8BB1723E2514500DCD162 /* SDL_mouse.c in Sources */,
A7D8BADB23E2514500DCD162 /* e_rem_pio2.c in Sources */,
@@ -9578,6 +9594,7 @@
A7D8B76E23E2514300DCD162 /* SDL_wave.c in Sources */,
A7D8BAD723E2514500DCD162 /* s_tan.c in Sources */,
A7D8AA6923E2514000DCD162 /* SDL_hints.c in Sources */,
+ F3A490A22554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A7D8B54323E2514300DCD162 /* SDL_hidapi_ps4.c in Sources */,
A7D8AD7223E2514100DCD162 /* SDL_pixels.c in Sources */,
A7D8B1A423E2514200DCD162 /* SDL_x11clipboard.c in Sources */,
@@ -9835,6 +9852,7 @@
A7D8B54B23E2514300DCD162 /* SDL_hidapi_xboxone.c in Sources */,
A7D8AD2323E2514100DCD162 /* SDL_blit_auto.c in Sources */,
A7D8B1A623E2514200DCD162 /* SDL_x11keyboard.c in Sources */,
+ F3A4909E2554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A7D8BB6923E2514500DCD162 /* SDL_keyboard.c in Sources */,
A7D8ACE723E2514100DCD162 /* SDL_rect.c in Sources */,
A7D8AE9A23E2514100DCD162 /* SDL_cocoaopengles.m in Sources */,
@@ -9898,6 +9916,7 @@
A7D8AD2C23E2514100DCD162 /* SDL_vulkan_utils.c in Sources */,
A7D8A95423E2514000DCD162 /* SDL_spinlock.c in Sources */,
A7D8BAB223E2514400DCD162 /* s_atan.c in Sources */,
+ F3A490A12554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A7D8B75523E2514300DCD162 /* SDL_sysloadso.c in Sources */,
A7D8B98923E2514400DCD162 /* SDL_render_metal.m in Sources */,
A7D8AE7923E2514100DCD162 /* SDL_clipboard.c in Sources */,
@@ -10096,6 +10115,7 @@
A7D8A95623E2514000DCD162 /* SDL_spinlock.c in Sources */,
A7D8BAB423E2514400DCD162 /* s_atan.c in Sources */,
A7D8B75723E2514300DCD162 /* SDL_sysloadso.c in Sources */,
+ F3A490A42554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */,
A7D8B98B23E2514400DCD162 /* SDL_render_metal.m in Sources */,
A7D8AE7B23E2514100DCD162 /* SDL_clipboard.c in Sources */,
A7D8AEC923E2514100DCD162 /* SDL_cocoaevents.m in Sources */,
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 70319acb0..a9dbbae7e 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -493,6 +493,7 @@ extern "C" {
* XboxOne
* PS3
* PS4
+ * PS5
* SwitchPro
*
* This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
@@ -603,6 +604,17 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4"
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS5 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5"
+
/**
* \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver.
*
diff --git a/src/joystick/controller_type.h b/src/joystick/controller_type.h
index cf079f799..6fb50d425 100644
--- a/src/joystick/controller_type.h
+++ b/src/joystick/controller_type.h
@@ -629,6 +629,10 @@ static SDL_INLINE EControllerType GuessControllerType( int nVID, int nPID )
{
return k_eControllerType_PS4Controller;
}
+ if ( SDL_strncasecmp( pszOverride, "PS5", 3 ) == 0 )
+ {
+ return k_eControllerType_PS5Controller;
+ }
if ( SDL_strncasecmp( pszOverride, "SwitchPro", 9 ) == 0 )
{
return k_eControllerType_SwitchProController;
diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index b044b9b80..173e1ed12 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps4.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps4.c
@@ -78,19 +78,6 @@ typedef struct
Uint8 rgucTrackpadData2[ 3 ];
} PS4StatePacket_t;
-typedef struct
-{
- Uint8 ucLeftJoystickX;
- Uint8 ucLeftJoystickY;
- Uint8 ucRightJoystickX;
- Uint8 ucRightJoystickY;
- Uint8 ucTriggerLeft;
- Uint8 ucTriggerRight;
- Uint8 ucCounter;
- Uint8 rgucButtonsAndHat[ 3 ];
- Uint8 rgucUnknown[ 53 ];
-} PS5StatePacket_t;
-
typedef struct
{
Uint8 ucRumbleRight;
@@ -108,7 +95,6 @@ typedef struct
} DS4EffectsState_t;
typedef struct {
- SDL_bool is_PS5;
SDL_bool is_dongle;
SDL_bool is_bluetooth;
SDL_bool audio_supported;
@@ -122,40 +108,10 @@ typedef struct {
Uint8 led_blue;
Uint8 volume;
Uint32 last_volume_check;
- union
- {
- PS4StatePacket_t PS4;
- PS5StatePacket_t PS5;
- } last_state;
+ PS4StatePacket_t last_state;
} SDL_DriverPS4_Context;
-/* Define this if you want to log all packets from the controller */
-/*#define DEBUG_PS4_PROTOCOL*/
-#define DEBUG_PS4_PROTOCOL
-
-#ifdef DEBUG_PS4_PROTOCOL
-static void
-DumpPacket(const char *prefix, Uint8 *data, int size)
-{
- int i;
- char *buffer;
- size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH) + 1 + 1;
-
- buffer = (char *)SDL_malloc(length);
- SDL_snprintf(buffer, length, prefix, size);
- for (i = 0; i < size; ++i) {
- if ((i % 8) == 0) {
- SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
- }
- SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
- }
- SDL_strlcat(buffer, "\n", length);
- SDL_Log("%s", buffer);
- SDL_free(buffer);
-}
-#endif /* DEBUG_PS4_PROTOCOL */
-
/* Public domain CRC implementation adapted from:
http://home.thep.lu.se/~bjorn/crc/crc32_simple.c
*/
@@ -180,18 +136,14 @@ static Uint32 crc32(Uint32 crc, const void *data, int count)
static SDL_bool
HIDAPI_DriverPS4_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
- return (type == SDL_CONTROLLER_TYPE_PS4 || type == SDL_CONTROLLER_TYPE_PS5);
+ return (type == SDL_CONTROLLER_TYPE_PS4);
}
static const char *
HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_SONY) {
- if (SDL_IsJoystickPS5(vendor_id, product_id)) {
- return "PS5 Controller";
- } else {
- return "PS4 Controller";
- }
+ return "PS4 Controller";
}
return NULL;
}
@@ -339,14 +291,6 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
}
}
- /* Special handling for PS5 controller */
- ctx->is_PS5 = SDL_IsJoystickPS5(device->vendor_id, device->product_id);
- if (ctx->is_PS5) {
- /* Don't know how these work yet... */
- ctx->audio_supported = SDL_FALSE;
- ctx->rumble_supported = SDL_FALSE;
- }
-
/* Initialize player index (needed for setting LEDs) */
ctx->player_index = SDL_JoystickGetPlayerIndex(joystick);
@@ -424,9 +368,7 @@ HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
static SDL_bool
HIDAPI_DriverPS4_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
- SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
-
- return ctx->rumble_supported;
+ return SDL_TRUE;
}
static int
@@ -439,15 +381,16 @@ HIDAPI_DriverPS4_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
ctx->led_green = green;
ctx->led_blue = blue;
+ /* FIXME: Is there a better way to send this without sending another rumble packet? */
return HIDAPI_DriverPS4_RumbleJoystick(device, joystick, ctx->rumble_left, ctx->rumble_right);
}
static void
-HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet, int size)
+HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
{
Sint16 axis;
- if (ctx->last_state.PS4.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
+ if (ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
{
Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
@@ -502,7 +445,7 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_
}
}
- if (ctx->last_state.PS4.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
+ if (ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
Uint8 data = packet->rgucButtonsHatAndCounter[1];
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
@@ -522,7 +465,7 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_
packet->ucTriggerRight = (data & 0x08) && packet->ucTriggerRight == 0 ? 255 : packet->ucTriggerRight;
}
- if (ctx->last_state.PS4.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
+ if (ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
@@ -542,119 +485,23 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_
axis = ((int)packet->ucRightJoystickY * 257) - 32768;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
- if (size >= 30) {
- if (packet->ucBatteryLevel & 0x10) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
+ if (packet->ucBatteryLevel & 0x10) {
+ joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
+ } else {
+ /* Battery level ranges from 0 to 10 */
+ int level = (packet->ucBatteryLevel & 0xF);
+ if (level == 0) {
+ joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
+ } else if (level <= 2) {
+ joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
+ } else if (level <= 7) {
+ joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
} else {
- /* Battery level ranges from 0 to 10 */
- int level = (packet->ucBatteryLevel & 0xF);
- if (level == 0) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
- } else if (level <= 2) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
- } else if (level <= 7) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
- } else {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
- }
+ joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
}
}
- SDL_memcpy(&ctx->last_state.PS4, packet, SDL_min(size, sizeof(ctx->last_state.PS4)));
-}
-
-static void
-HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS5StatePacket_t *packet)
-{
- Sint16 axis;
-
- if (ctx->last_state.PS5.rgucButtonsAndHat[0] != packet->rgucButtonsAndHat[0]) {
- {
- Uint8 data = (packet->rgucButtonsAndHat[0] >> 4);
-
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
- }
- {
- Uint8 data = (packet->rgucButtonsAndHat[0] & 0x0F);
- SDL_bool dpad_up = SDL_FALSE;
- SDL_bool dpad_down = SDL_FALSE;
- SDL_bool dpad_left = SDL_FALSE;
- SDL_bool dpad_right = SDL_FALSE;
-
- switch (data) {
- case 0:
- dpad_up = SDL_TRUE;
- break;
- case 1:
- dpad_up = SDL_TRUE;
- dpad_right = SDL_TRUE;
- break;
- case 2:
- dpad_right = SDL_TRUE;
- break;
- case 3:
- dpad_right = SDL_TRUE;
- dpad_down = SDL_TRUE;
- break;
- case 4:
- dpad_down = SDL_TRUE;
- break;
- case 5:
- dpad_left = SDL_TRUE;
- dpad_down = SDL_TRUE;
- break;
- case 6:
- dpad_left = SDL_TRUE;
- break;
- case 7:
- dpad_up = SDL_TRUE;
- dpad_left = SDL_TRUE;
- break;
- default:
- break;
- }
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
- }
- }
-
- if (ctx->last_state.PS5.rgucButtonsAndHat[1] != packet->rgucButtonsAndHat[1]) {
- Uint8 data = packet->rgucButtonsAndHat[1];
-
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
- }
-
- if (ctx->last_state.PS5.rgucButtonsAndHat[2] != packet->rgucButtonsAndHat[2]) {
- Uint8 data = (packet->rgucButtonsAndHat[2] & 0x03);
-
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
- SDL_PrivateJoystickButton(joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
- }
-
- axis = ((int)packet->ucTriggerLeft * 257) - 32768;
- SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
- axis = ((int)packet->ucTriggerRight * 257) - 32768;
- SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
- axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
- SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
- axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
- SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
- axis = ((int)packet->ucRightJoystickX * 257) - 32768;
- SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
- axis = ((int)packet->ucRightJoystickY * 257) - 32768;
- SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
-
- SDL_memcpy(&ctx->last_state.PS5, packet, sizeof(ctx->last_state.PS5));
+ SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
}
static SDL_bool
@@ -673,20 +520,13 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
-#ifdef DEBUG_PS4_PROTOCOL
- DumpPacket("PS4 packet: size = %d", data, size);
-#endif
switch (data[0]) {
case k_EPS4ReportIdUsbState:
- if (ctx->is_PS5 && size > 10) {
- HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[1]);
- } else {
- HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1], size - 1);
- }
+ HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1]);
break;
case k_EPS4ReportIdBluetoothState:
/* Bluetooth state packets have two additional bytes at the beginning */
- HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[3], size - 3);
+ HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[3]);
break;
default:
#ifdef DEBUG_JOYSTICK
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
new file mode 100644
index 000000000..f3910bf29
--- /dev/null
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -0,0 +1,437 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2020 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifdef SDL_JOYSTICK_HIDAPI
+
+#include "SDL_hints.h"
+#include "SDL_events.h"
+#include "SDL_joystick.h"
+#include "SDL_gamecontroller.h"
+#include "../SDL_sysjoystick.h"
+#include "SDL_hidapijoystick_c.h"
+
+
+#ifdef SDL_JOYSTICK_HIDAPI_PS5
+
+typedef struct
+{
+ Uint8 ucLeftJoystickX;
+ Uint8 ucLeftJoystickY;
+ Uint8 ucRightJoystickX;
+ Uint8 ucRightJoystickY;
+ Uint8 rgucButtonsHatAndCounter[ 3 ];
+ Uint8 ucTriggerLeft;
+ Uint8 ucTriggerRight;
+} PS5SimpleStatePacket_t;
+
+typedef struct
+{
+ Uint8 ucLeftJoystickX;
+ Uint8 ucLeftJoystickY;
+ Uint8 ucRightJoystickX;
+ Uint8 ucRightJoystickY;
+ Uint8 ucTriggerLeft;
+ Uint8 ucTriggerRight;
+ Uint8 ucCounter;
+ Uint8 rgucButtonsAndHat[ 3 ];
+ Uint8 rgucUnknown[ 53 ];
+} PS5StatePacket_t;
+
+typedef struct {
+ union
+ {
+ PS5SimpleStatePacket_t simple;
+ PS5StatePacket_t state;
+ } last_state;
+} SDL_DriverPS5_Context;
+
+
+/* Define this if you want to log all packets from the controller */
+/*#define DEBUG_PS5_PROTOCOL*/
+
+#ifdef DEBUG_PS5_PROTOCOL
+static void
+DumpPacket(const char *prefix, Uint8 *data, int size)
+{
+ int i;
+ char *buffer;
+ size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH) + 1 + 1;
+
+ buffer = (char *)SDL_malloc(length);
+ SDL_snprintf(buffer, length, prefix, size);
+ for (i = 0; i < size; ++i) {
+ if ((i % 8) == 0) {
+ SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
+ }
+ SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
+ }
+ SDL_strlcat(buffer, "\n", length);
+ SDL_Log("%s", buffer);
+ SDL_free(buffer);
+}
+#endif /* DEBUG_PS5_PROTOCOL */
+
+static SDL_bool
+HIDAPI_DriverPS5_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
+{
+ return (type == SDL_CONTROLLER_TYPE_PS5);
+}
+
+static const char *
+HIDAPI_DriverPS5_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
+{
+ if (vendor_id == USB_VENDOR_SONY) {
+ return "PS5 Controller";
+ }
+ return NULL;
+}
+
+static SDL_bool
+HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
+{
+ return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
+}
+
+static int
+HIDAPI_DriverPS5_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
+{
+ return -1;
+}
+
+static void
+HIDAPI_DriverPS5_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
+{
+}
+
+static SDL_bool
+HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
+{
+ SDL_DriverPS5_Context *ctx;
+
+ ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx));
+ if (!ctx) {
+ SDL_OutOfMemory();
+ return SDL_FALSE;
+ }
+
+ device->dev = hid_open_path(device->path, 0);
+ if (!device->dev) {
+ SDL_free(ctx);
+ SDL_SetError("Couldn't open %s", device->path);
+ return SDL_FALSE;
+ }
+ device->context = ctx;
+
+ /* Initialize the joystick capabilities */
+ joystick->nbuttons = 16;
+ joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
+
+ return SDL_TRUE;
+}
+
+static int
+HIDAPI_DriverPS5_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
+{
+ return SDL_Unsupported();
+}
+
+static SDL_bool
+HIDAPI_DriverPS5_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
+{
+ return SDL_FALSE;
+}
+
+static int
+HIDAPI_DriverPS5_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+ return SDL_Unsupported();
+}
+
+static void
+HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
+{
+ Sint16 axis;
+
+ if (ctx->last_state.simple.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
+ {
+ Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
+
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
+ }
+ {
+ Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
+ SDL_bool dpad_up = SDL_FALSE;
+ SDL_bool dpad_down = SDL_FALSE;
+ SDL_bool dpad_left = SDL_FALSE;
+ SDL_bool dpad_right = SDL_FALSE;
+
+ switch (data) {
+ case 0:
+ dpad_up = SDL_TRUE;
+ break;
+ case 1:
+ dpad_up = SDL_TRUE;
+ dpad_right = SDL_TRUE;
+ break;
+ case 2:
+ dpad_right = SDL_TRUE;
+ break;
+ case 3:
+ dpad_right = SDL_TRUE;
+ dpad_down = SDL_TRUE;
+ break;
+ case 4:
+ dpad_down = SDL_TRUE;
+ break;
+ case 5:
+ dpad_left = SDL_TRUE;
+ dpad_down = SDL_TRUE;
+ break;
+ case 6:
+ dpad_left = SDL_TRUE;
+ break;
+ case 7:
+ dpad_up = SDL_TRUE;
+ dpad_left = SDL_TRUE;
+ break;
+ default:
+ break;
+ }
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
+ }
+ }
+
+ if (ctx->last_state.simple.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
+ Uint8 data = packet->rgucButtonsHatAndCounter[1];
+
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
+ }
+
+ if (ctx->last_state.simple.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
+ Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
+
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
+ }
+
+ axis = ((int)packet->ucTriggerLeft * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
+ axis = ((int)packet->ucTriggerRight * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
+ axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
+ axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
+ axis = ((int)packet->ucRightJoystickX * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
+ axis = ((int)packet->ucRightJoystickY * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
+
+ SDL_memcpy(&ctx->last_state.simple, packet, sizeof(ctx->last_state.simple));
+}
+
+static void
+HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
+{
+ Sint16 axis;
+
+ if (ctx->last_state.state.rgucButtonsAndHat[0] != packet->rgucButtonsAndHat[0]) {
+ {
+ Uint8 data = (packet->rgucButtonsAndHat[0] >> 4);
+
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
+ }
+ {
+ Uint8 data = (packet->rgucButtonsAndHat[0] & 0x0F);
+ SDL_bool dpad_up = SDL_FALSE;
+ SDL_bool dpad_down = SDL_FALSE;
+ SDL_bool dpad_left = SDL_FALSE;
+ SDL_bool dpad_right = SDL_FALSE;
+
+ switch (data) {
+ case 0:
+ dpad_up = SDL_TRUE;
+ break;
+ case 1:
+ dpad_up = SDL_TRUE;
+ dpad_right = SDL_TRUE;
+ break;
+ case 2:
+ dpad_right = SDL_TRUE;
+ break;
+ case 3:
+ dpad_right = SDL_TRUE;
+ dpad_down = SDL_TRUE;
+ break;
+ case 4:
+ dpad_down = SDL_TRUE;
+ break;
+ case 5:
+ dpad_left = SDL_TRUE;
+ dpad_down = SDL_TRUE;
+ break;
+ case 6:
+ dpad_left = SDL_TRUE;
+ break;
+ case 7:
+ dpad_up = SDL_TRUE;
+ dpad_left = SDL_TRUE;
+ break;
+ default:
+ break;
+ }
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
+ }
+ }
+
+ if (ctx->last_state.state.rgucButtonsAndHat[1] != packet->rgucButtonsAndHat[1]) {
+ Uint8 data = packet->rgucButtonsAndHat[1];
+
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
+ }
+
+ if (ctx->last_state.state.rgucButtonsAndHat[2] != packet->rgucButtonsAndHat[2]) {
+ Uint8 data = (packet->rgucButtonsAndHat[2] & 0x03);
+
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
+ SDL_PrivateJoystickButton(joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
+ }
+
+ axis = ((int)packet->ucTriggerLeft * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
+ axis = ((int)packet->ucTriggerRight * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
+ axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
+ axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
+ axis = ((int)packet->ucRightJoystickX * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
+ axis = ((int)packet->ucRightJoystickY * 257) - 32768;
+ SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
+
+ SDL_memcpy(&ctx->last_state.state, packet, sizeof(ctx->last_state.state));
+}
+
+static SDL_bool
+HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
+{
+ SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
+ SDL_Joystick *joystick = NULL;
+ Uint8 data[USB_PACKET_LENGTH];
+ int size;
+
+ if (device->num_joysticks > 0) {
+ joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
+ }
+ if (!joystick) {
+ return SDL_FALSE;
+ }
+
+ while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
+#ifdef DEBUG_PS5_PROTOCOL
+ DumpPacket("PS5 packet: size = %d", data, size);
+#endif
+ switch (data[0]) {
+ case 0x01:
+ if (size == 10) {
+ HIDAPI_DriverPS5_HandleSimpleStatePacket(joystick, device->dev, ctx, (PS5SimpleStatePacket_t *)&data[1]);
+ } else {
+ HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[1]);
+ }
+ break;
+ default:
+#ifdef DEBUG_JOYSTICK
+ SDL_Log("Unknown PS5 packet: 0x%.2x\n", data[0]);
+#endif
+ break;
+ }
+ }
+
+ if (size < 0) {
+ /* Read error, device is disconnected */
+ HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
+ }
+ return (size >= 0);
+}
+
+static void
+HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
+{
+ hid_close(device->dev);
+ device->dev = NULL;
+
+ SDL_free(device->context);
+ device->context = NULL;
+}
+
+static void
+HIDAPI_DriverPS5_FreeDevice(SDL_HIDAPI_Device *device)
+{
+}
+
+SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
+{
+ SDL_HINT_JOYSTICK_HIDAPI_PS5,
+ SDL_TRUE,
+ HIDAPI_DriverPS5_IsSupportedDevice,
+ HIDAPI_DriverPS5_GetDeviceName,
+ HIDAPI_DriverPS5_InitDevice,
+ HIDAPI_DriverPS5_GetDevicePlayerIndex,
+ HIDAPI_DriverPS5_SetDevicePlayerIndex,
+ HIDAPI_DriverPS5_UpdateDevice,
+ HIDAPI_DriverPS5_OpenJoystick,
+ HIDAPI_DriverPS5_RumbleJoystick,
+ HIDAPI_DriverPS5_HasJoystickLED,
+ HIDAPI_DriverPS5_SetJoystickLED,
+ HIDAPI_DriverPS5_CloseJoystick,
+ HIDAPI_DriverPS5_FreeDevice,
+ NULL
+};
+
+#endif /* SDL_JOYSTICK_HIDAPI_PS5 */
+
+#endif /* SDL_JOYSTICK_HIDAPI */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index 2ce2f13de..3872b6a1c 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -63,6 +63,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
#ifdef SDL_JOYSTICK_HIDAPI_PS4
&SDL_HIDAPI_DriverPS4,
#endif
+#ifdef SDL_JOYSTICK_HIDAPI_PS5
+ &SDL_HIDAPI_DriverPS5,
+#endif
#ifdef SDL_JOYSTICK_HIDAPI_STEAM
&SDL_HIDAPI_DriverSteam,
#endif
diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h
index f88542be6..5b13c2007 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick_c.h
+++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h
@@ -32,6 +32,7 @@
/* This is the full set of HIDAPI drivers available */
#define SDL_JOYSTICK_HIDAPI_PS4
+#define SDL_JOYSTICK_HIDAPI_PS5
#define SDL_JOYSTICK_HIDAPI_SWITCH
#define SDL_JOYSTICK_HIDAPI_XBOX360
#define SDL_JOYSTICK_HIDAPI_XBOXONE
@@ -108,6 +109,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
/* HIDAPI device support */
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4;
+extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;