From a22beef402b7375c72a7f3ef3634a51f9e0e0c4e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 5 Nov 2020 17:03:28 -0800 Subject: [PATCH] Moved the PS5 controller driver to a separate file, as the advanced feature protocol is very different from that of the PS4 --- VisualC/SDL/SDL.vcxproj | 1 + Xcode/SDL/SDL.xcodeproj/project.pbxproj | 20 + include/SDL_hints.h | 12 + src/joystick/controller_type.h | 4 + src/joystick/hidapi/SDL_hidapi_ps4.c | 208 ++-------- src/joystick/hidapi/SDL_hidapi_ps5.c | 437 +++++++++++++++++++++ src/joystick/hidapi/SDL_hidapijoystick.c | 3 + src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 + 8 files changed, 503 insertions(+), 184 deletions(-) create mode 100644 src/joystick/hidapi/SDL_hidapi_ps5.c 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;