This commit is contained in:
danprice142 2026-06-05 17:43:19 +01:00 committed by GitHub
commit 953e25f2e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1814 additions and 0 deletions

View file

@ -394,6 +394,7 @@ dep_option(SDL_HIDAPI_LIBUSB "Use libusb for low level joystick drivers" O
dep_option(SDL_HIDAPI_LIBUSB_SHARED "Dynamically load libusb support" ON "SDL_HIDAPI_LIBUSB;SDL_DEPS_SHARED" OFF)
dep_option(SDL_HIDAPI_JOYSTICK "Use HIDAPI for low level joystick drivers" ON SDL_HIDAPI OFF)
dep_option(SDL_VIRTUAL_JOYSTICK "Enable the virtual-joystick driver" ON SDL_HIDAPI OFF)
dep_option(SDL_DSU_JOYSTICK "Enable DSU client joystick support" ON SDL_JOYSTICK OFF)
set_option(SDL_LIBUDEV "Enable libudev support" ON)
set_option(SDL_ASAN "Use AddressSanitizer to detect memory errors" OFF)
set_option(SDL_CCACHE "Use Ccache to speed up build" OFF)
@ -1457,6 +1458,27 @@ if(SDL_JOYSTICK)
"${SDL3_SOURCE_DIR}/src/joystick/virtual/*.h"
)
endif()
# DSU (DualShock UDP) client support
# Supported on platforms with UDP socket support (BSD sockets or WinSock)
# Disabled on platforms without UDP support or where not yet implemented
if(SDL_DSU_JOYSTICK AND NOT (EMSCRIPTEN OR VITA OR PSP OR PS2 OR N3DS))
set(SDL_JOYSTICK_DSU 1)
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/joystick/dsu/*.c"
"${SDL3_SOURCE_DIR}/src/joystick/dsu/*.h"
)
# DSU requires network libraries
if(WIN32)
sdl_link_dependency(dsu LIBS ws2_32)
elseif(HAIKU)
sdl_link_dependency(dsu LIBS network)
elseif(QNX)
# QNX needs socket library
sdl_link_dependency(dsu LIBS socket)
endif()
endif()
endif()
if(SDL_VIDEO)

View file

@ -476,6 +476,8 @@
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\usb_ids.h" />
<ClInclude Include="..\..\src\joystick\dsu\SDL_dsuprotocol.h" />
<ClInclude Include="..\..\src\joystick\dsu\SDL_dsujoystick_c.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_rawinputjoystick_c.h" />
@ -750,6 +752,7 @@
<ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
<ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\..\src\joystick\dsu\SDL_dsujoystick.c" />
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />

View file

@ -511,6 +511,8 @@
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\usb_ids.h" />
<ClInclude Include="..\..\src\joystick\dsu\SDL_dsuprotocol.h" />
<ClInclude Include="..\..\src\joystick\dsu\SDL_dsujoystick_c.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_rawinputjoystick_c.h" />
@ -851,6 +853,7 @@
<ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
<ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\..\src\joystick\dsu\SDL_dsujoystick.c" />
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />

View file

@ -2489,6 +2489,56 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI"
/**
* A variable controlling whether the DSU (DualShock UDP) joystick driver should be used.
*
* This variable can be set to the following values:
*
* - "0": DSU driver is disabled
* - "1": DSU driver is enabled (default)
*
* The DSU driver allows SDL to connect to DSU servers (DS4Windows, BetterJoy, etc.)
* to receive controller data over UDP, including motion sensors and touchpad data.
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.2.0.
*/
#define SDL_HINT_JOYSTICK_DSU "SDL_JOYSTICK_DSU"
/**
* A variable controlling the DSU server address.
*
* The default value is "127.0.0.1"
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.2.0.
*/
#define SDL_HINT_DSU_SERVER "SDL_DSU_SERVER"
/**
* A variable controlling the DSU server port.
*
* The default value is "26760"
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.2.0.
*/
#define SDL_HINT_DSU_SERVER_PORT "SDL_DSU_SERVER_PORT"
/**
* A variable controlling the DSU client port.
*
* The default value is "0" (auto-select)
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.2.0.
*/
#define SDL_HINT_DSU_CLIENT_PORT "SDL_DSU_CLIENT_PORT"
/**
* A variable containing a list of wheel style controllers.
*

View file

@ -317,6 +317,7 @@
#cmakedefine SDL_JOYSTICK_RAWINPUT 1
#cmakedefine SDL_JOYSTICK_USBHID 1
#cmakedefine SDL_JOYSTICK_VIRTUAL 1
#cmakedefine SDL_JOYSTICK_DSU 1
#cmakedefine SDL_JOYSTICK_VITA 1
#cmakedefine SDL_JOYSTICK_WGI 1
#cmakedefine SDL_JOYSTICK_XINPUT 1

View file

@ -231,6 +231,7 @@ typedef unsigned int uintptr_t;
#define SDL_JOYSTICK_HIDAPI 1
#define SDL_JOYSTICK_RAWINPUT 1
#define SDL_JOYSTICK_VIRTUAL 1
#define SDL_JOYSTICK_DSU 1
#ifdef HAVE_WINDOWS_GAMING_INPUT_H
#define SDL_JOYSTICK_WGI 1
#endif

View file

@ -48,6 +48,10 @@
#include "./virtual/SDL_virtualjoystick_c.h"
#endif
#ifdef SDL_JOYSTICK_DSU
#include "./dsu/SDL_dsujoystick_c.h"
#endif
static SDL_JoystickDriver *SDL_joystick_drivers[] = {
#ifdef SDL_JOYSTICK_HIDAPI // Highest priority driver for supported devices
&SDL_HIDAPI_JoystickDriver,
@ -100,6 +104,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
#ifdef SDL_JOYSTICK_VIRTUAL
&SDL_VIRTUAL_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_DSU
&SDL_DSU_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_VITA
&SDL_VITA_JoystickDriver,
#endif

View file

@ -265,6 +265,7 @@ extern SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver;
extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
extern SDL_JoystickDriver SDL_DSU_JoystickDriver;
extern SDL_JoystickDriver SDL_WGI_JoystickDriver;
extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver;
extern SDL_JoystickDriver SDL_WINMM_JoystickDriver;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,138 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
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.
*/
#ifndef SDL_dsujoystick_c_h_
#define SDL_dsujoystick_c_h_
#include "SDL_internal.h"
#ifdef SDL_JOYSTICK_DSU
#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_mutex.h>
#include <SDL3/SDL_thread.h>
#include <SDL3/SDL_atomic.h>
#include "../SDL_sysjoystick.h"
#include "SDL_dsuprotocol.h"
/* DSU Joystick driver */
extern SDL_JoystickDriver SDL_DSU_JoystickDriver;
/* Socket type definitions - move these out to ensure visibility */
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <winsock2.h>
typedef SOCKET dsu_socket_t;
#else
typedef int dsu_socket_t;
#endif
/* Internal structures - always visible */
typedef struct DSU_ControllerSlot {
/* Connection state */
bool detected; /* Controller detected by DSU but not yet added to SDL */
bool connected; /* Controller added to SDL and visible */
SDL_JoystickID instance_id;
SDL_GUID guid;
char name[128];
/* DSU protocol data */
Uint8 slot_id;
Uint8 mac[6];
Uint8 battery;
DSU_DeviceModel model;
DSU_ConnectionType connection;
/* Controller state */
Uint16 buttons;
Sint16 axes[6]; /* LX, LY, RX, RY, L2, R2 */
Uint8 hat;
/* Motion data */
bool has_gyro;
bool has_accel;
bool sensors_enabled; /* Track if SDL enabled sensors */
float gyro[3]; /* Pitch, Yaw, Roll in rad/s */
float accel[3]; /* X, Y, Z in m/s² */
Uint64 motion_timestamp;
/* Touch data */
bool has_touchpad;
bool touch1_active;
bool touch2_active;
Uint8 touch1_id;
Uint8 touch2_id;
Uint16 touch1_x, touch1_y;
Uint16 touch2_x, touch2_y;
/* Timing */
Uint64 last_packet_time;
Uint32 packet_number;
/* Back-reference to parent server connection */
struct DSU_ServerConnection *parent_conn;
} DSU_ControllerSlot;
/* Maximum number of DSU servers that can be connected simultaneously */
#define DSU_MAX_SERVERS 4
/* Per-server connection state */
typedef struct DSU_ServerConnection {
/* Network */
dsu_socket_t socket;
SDL_Thread *receiver_thread;
SDL_AtomicInt running;
/* Server configuration */
char server_address[256];
Uint16 server_port;
Uint32 client_id;
/* Controller slots (4 max per DSU server) */
DSU_ControllerSlot slots[DSU_MAX_SLOTS];
/* Timing for periodic updates */
Uint64 last_request_time;
/* Back-reference to parent context */
struct DSU_Context_t *parent;
int server_index;
} DSU_ServerConnection;
typedef struct DSU_Context_t {
/* Server connections */
DSU_ServerConnection servers[DSU_MAX_SERVERS];
int server_count;
/* Client port (shared across all servers) */
Uint16 client_port;
/* Shared mutex for all slots */
SDL_Mutex *slots_mutex;
} DSU_Context;
#endif /* SDL_JOYSTICK_DSU */
#endif /* SDL_dsujoystick_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,201 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
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.
*/
#ifndef SDL_dsuprotocol_h_
#define SDL_dsuprotocol_h_
#include "SDL_internal.h"
/* DSU (DualShock UDP) Protocol Constants - Based on CemuHook */
#define DSU_PROTOCOL_VERSION 1001
#define DSU_SERVER_PORT_DEFAULT 26760
#define DSU_CLIENT_PORT_DEFAULT 26761
#define DSU_SERVER_ADDRESS_DEFAULT "127.0.0.1"
/* Magic strings */
#define DSU_MAGIC_CLIENT "DSUC"
#define DSU_MAGIC_SERVER "DSUS"
/* Message types */
typedef enum {
DSU_MSG_VERSION = 0x100000,
DSU_MSG_PORTS_INFO = 0x100001,
DSU_MSG_DATA = 0x100002,
DSU_MSG_RUMBLE_INFO = 0x110001, /* Unofficial */
DSU_MSG_RUMBLE = 0x110002 /* Unofficial */
} DSU_MessageType;
/* Controller states */
typedef enum {
DSU_STATE_DISCONNECTED = 0,
DSU_STATE_RESERVED = 1,
DSU_STATE_CONNECTED = 2
} DSU_SlotState;
/* Device models */
typedef enum {
DSU_MODEL_NONE = 0,
DSU_MODEL_PARTIAL_GYRO = 1,
DSU_MODEL_FULL_GYRO = 2, /* DS4, DS5 */
DSU_MODEL_NO_GYRO = 3
} DSU_DeviceModel;
/* Connection types */
typedef enum {
DSU_CONN_NONE = 0,
DSU_CONN_USB = 1,
DSU_CONN_BLUETOOTH = 2
} DSU_ConnectionType;
/* Battery states */
typedef enum {
DSU_BATTERY_NONE = 0x00,
DSU_BATTERY_DYING = 0x01, /* 0-10% */
DSU_BATTERY_LOW = 0x02, /* 10-40% */
DSU_BATTERY_MEDIUM = 0x03, /* 40-70% */
DSU_BATTERY_HIGH = 0x04, /* 70-100% */
DSU_BATTERY_FULL = 0x05, /* 100% */
DSU_BATTERY_CHARGING = 0xEE,
DSU_BATTERY_CHARGED = 0xEF
} DSU_BatteryState;
/* Packet structures */
#pragma pack(push, 1)
typedef struct {
char magic[4]; /* DSUC or DSUS */
Uint16 version; /* Protocol version (1001) */
Uint16 length; /* Packet length after header */
Uint32 crc32; /* CRC32 of packet (with this field zeroed) */
Uint32 client_id; /* Random client ID */
Uint32 message_type; /* Message type enum */
} DSU_Header;
typedef struct {
DSU_Header header;
Uint8 flags; /* Slot registration flags */
Uint8 slot_id; /* 0-3 for specific slot, 0xFF for all */
Uint8 mac[6]; /* MAC address filter (zeros for all) */
} DSU_PortRequest;
typedef struct {
Uint8 slot; /* Controller slot 0-3 */
Uint8 slot_state; /* DSU_SlotState */
Uint8 device_model; /* DSU_DeviceModel */
Uint8 connection_type; /* DSU_ConnectionType */
Uint8 mac[6]; /* Controller MAC address */
Uint8 battery; /* DSU_BatteryState */
Uint8 is_active; /* 0 or 1 */
} DSU_ControllerInfo;
typedef struct {
DSU_Header header;
Uint8 slot; /* Controller slot 0-3 */
Uint8 motor_left; /* Left/Low frequency motor intensity (0-255) */
Uint8 motor_right; /* Right/High frequency motor intensity (0-255) */
} DSU_RumblePacket;
typedef struct {
DSU_Header header;
DSU_ControllerInfo info;
/* Controller data */
Uint32 packet_number; /* Incremental counter */
/* Digital buttons */
Uint8 button_states_1; /* Share, L3, R3, Options, DPad */
Uint8 button_states_2; /* L2, R2, L1, R1, Triangle, Circle, Cross, Square */
Uint8 button_ps; /* PS/Home button */
Uint8 button_touch; /* Touchpad button */
/* Analog sticks (0-255, 128=center) */
Uint8 left_stick_x;
Uint8 left_stick_y;
Uint8 right_stick_x;
Uint8 right_stick_y;
/* Analog buttons (0-255, pressure sensitive) */
Uint8 analog_dpad_left;
Uint8 analog_dpad_down;
Uint8 analog_dpad_right;
Uint8 analog_dpad_up;
Uint8 analog_button_square;
Uint8 analog_button_cross;
Uint8 analog_button_circle;
Uint8 analog_button_triangle;
Uint8 analog_button_r1;
Uint8 analog_button_l1;
Uint8 analog_trigger_r2;
Uint8 analog_trigger_l2;
/* Touch data (2 points max) */
Uint8 touch1_active;
Uint8 touch1_id;
Uint16 touch1_x;
Uint16 touch1_y;
Uint8 touch2_active;
Uint8 touch2_id;
Uint16 touch2_x;
Uint16 touch2_y;
/* Motion data (optional) */
Uint64 motion_timestamp; /* Microseconds */
float accel_x; /* In g units */
float accel_y;
float accel_z;
float gyro_pitch; /* In degrees/second */
float gyro_yaw;
float gyro_roll;
} DSU_ControllerData;
#pragma pack(pop)
/* Button masks for button_states_1 */
#define DSU_BUTTON_SHARE 0x01
#define DSU_BUTTON_L3 0x02
#define DSU_BUTTON_R3 0x04
#define DSU_BUTTON_OPTIONS 0x08
#define DSU_BUTTON_DPAD_UP 0x10
#define DSU_BUTTON_DPAD_RIGHT 0x20
#define DSU_BUTTON_DPAD_DOWN 0x40
#define DSU_BUTTON_DPAD_LEFT 0x80
/* Button masks for button_states_2 */
#define DSU_BUTTON_L2 0x01
#define DSU_BUTTON_R2 0x02
#define DSU_BUTTON_L1 0x04
#define DSU_BUTTON_R1 0x08
#define DSU_BUTTON_TRIANGLE 0x10
#define DSU_BUTTON_CIRCLE 0x20
#define DSU_BUTTON_CROSS 0x40
#define DSU_BUTTON_SQUARE 0x80
/* Maximum number of DSU slots per server */
#define DSU_MAX_SLOTS 4
/* We can support up to 8 controllers by using 2 server connections */
#define DSU_MAX_CONTROLLERS 8
#endif /* SDL_dsuprotocol_h_ */
/* vi: set ts=4 sw=4 expandtab: */