๐ŸŽฎ Dualsense-Multiplatform

September 10, 2026 ยท View on GitHub

๐ŸŽฎ Dualsense-Multiplatform

The Ultimate Cross-Platform DualSense & DualShock API

Pure C++ โ€ข Zero Dependencies โ€ข Engine Agnostic

Build Status CodeQL License: MIT


Report Bug ยท Suggest a Feature ยท Documentation ยท Security Policy

Core Tech Stack
C++20 CMake

Supported Languages
C C++ C%23 Python Rust Go Java

Supported Platforms
Windows Linux macOS PlayStation

Microcontrollers & SBCs
Raspberry Pi ESP32 Pico W

Game Engine Ready
Unreal Engine Godot Unity O3DE


Works with any C++ project โ€” Game Engines, Emulators, Desktop Apps, and more

Features โ€ข Examples โ€ข Installation โ€ข Tests โ€ข Integration โ€ข Architecture โ€ข Contributing


Download the sample app on Steam, or watch the demonstration video on YouTube:

On Steam Watch YouTube


๐Ÿš€ What is Dualsense-Multiplatform?

Dualsense-Multiplatform is a high-performance, policy-based C++ library that unlocks the full potential of Sony's DualSense and DualShock 4 controllers through direct HID communication.

๐ŸŒ True Cross-Platform Architecture

Dualsense-Multiplatform is engine-agnostic by design. It is a pure C++ library that works anywhere C++20 is supported.

The library leverages policy-based design to abstract platform-specific details. This zero-cost abstraction makes it trivial to extend support to new platforms or custom hardware without touching the core logic.


๐ŸŽฎ Live Web

C++ WebAssembly TypeScript JavaScript

Experience the core C++ architecture running natively in your browser. This real-time debugger leverages WebAssembly (WASM) for high-performance execution, seamlessly integrated through a clean TypeScript and JavaScript binding layer.

๐Ÿงฉ Browser Extension

You can also use this tool as a dedicated browser extension for an integrated experience.

  • Status: Available now on the Chrome Web Store Add-ons.
  • Compatibility: Works natively on Google Chrome, Microsoft Edge, Brave, Opera, Firefox, and other browsers.

โœจ Features

  • ๐Ÿ—๏ธ Extensible Multi-Platform Architecture Engine-agnostic C++20 design. Supporting new hardware is as simple as implementing the core connection interface, making it suitable for any environmentโ€”from PC to embedded systems.
  • ๐Ÿ”Œ Dynamic Connection (Hot-Swap) Robust plug-and-play logic that automatically detects controller connection and disconnection in real-time.
  • โšก High-Performance & Low-Latency Optimized for minimal CPU overhead and memory footprint, ensuring zero impact on the main application loop.
  • ๐ŸŽฎ Transparent Integration Designed to coexist with existing system input managers without device conflicts or driver interference.
  • ๐ŸŽฏ Adaptive Triggers Precise low-level control over resistance, haptic effects, and vibration for R2/L2 triggers.
  • ๐Ÿ’ก Lightbar & LED Control Programmatic control over the controller's LED colors and player indicators.
  • ๐ŸŽค Smart Mute Logic Automatic handling of the microphone mute LED state based on device status.
  • ๐ŸŽฎ Multi-Controller Support Native support for DualSense (Standard/Edge) and DualShock 4. The model-agnostic architecture is prepared for legacy hardware expansion, such as PS1 and PS2 models.

๐Ÿ† Implementations & Integrations

1. Unreal Engine โ€” Middleware Unreal-Dualsense Pro | UE5 Controller Integration Plugin

๐ŸŒ unreal-dualsense-pro.valoto.games

๐Ÿ›’ Fab.com - Middleware Unreal-Dualsense PRO


2. Raspberry Pico W โ€” Microcontroller Integration

Demonstrating the extreme portability and architectural efficiency of the library, the same core logic used in AAA game engines runs perfectly on a Pico W (264KB RAM / 2MB Flash).

๐ŸŽฅ Watch the example video on YouTube

The Pico W implementation includes complete support for all advanced DualSense capabilities:

InputOutput (Haptics & More)
Motion: Full 6-Axis Gyro & AccelAdaptive Triggers: Weapon, Feedback & Buzz modes
Touchpad: Multi-touch & CoordinatesHaptic Feedback: Dual independent motor control
System: Battery & Charging statusRGB Lightbar: Full color & Player LED control
Standard: All 17 buttons + Analog sticksArchitecture: Production-ready C++20

The Pico W implementation uses the exact same C++ core files as the Unreal and O3DE integrations, with zero logic changes.

๐Ÿ‘‰ Check out the Pico W implementation


3. FFI Integration โ€” Use from Any Language

Test quickly with a C# implementation or create an implementation for your preferred language. The C-compatible API is designed to integrate seamlessly with any language that supports FFI (Foreign Function Interface), including Python, Rust, Go, Java, and more.

๐Ÿ“ฅ Precompiled Binaries (Windows x64)

For quick integration without building from source, **download the precompiled .dll binary directly from the releases page. This shared library is ready to use with any compatible host application or game engine that supports C-compatible FFI (Foreign Function Interface).

๐ŸŒ C-API Repository: Gamepad-Core-Host

๐Ÿš€ Client Implementation Example

Check out the companion command-line application that consumes this API:


4. Other Prototypes & Mods


Prerequisites

  • CMake 3.20 or higher
  • C++20 compatible compiler (MSVC, GCC, Clang)
  • Ninja (recommended) or Make

๐Ÿ“ฆ Installation & Submodules

Depending on your project needs, you can clone Gamepad-Core in different ways. The library is designed to be modular, allowing you to include only what is necessary for your target environment.

1. ๐Ÿƒ Minimal Version (Core Only)

Ideal for: Embedded systems (ESP32, Raspberry Pi Pico W, etc.), OS-level applications, engine integrations, or resource-constrained environments where external audio libraries are not required.

  • Features: Basic HID communication, buttons, sticks, triggers (feedback/resistance), and lightbar control.

  • Engine & App Ready: Designed as a lightweight backend for custom engines (Unreal, Unity via Native C++) or standalone desktop applications.

  • Size: Very small footprint with zero external dependencies.

  • Flexibility: This core version serves as the foundation for all implementations; you can manually link your own OS-native audio API if needed.

git clone https://github.com/rafaelvaloto/Gamepad-Core.git

2. ๐Ÿ› ๏ธ Developer Version (Full + Tests)

Ideal for: Contributors, library development, or if you want to run the integration tests on your hardware.

  • Features: Everything in Standard + the complete Integration Test suite.
git clone --recursive https://github.com/rafaelvaloto/Gamepad-Core.git

If you have already cloned the repository without submodules, run:

git submodule update --init --recursive

๐Ÿงช Tests

The fastest way to verify Gamepad-Core on your hardware is by running the Integration Tests. This requires cloning the repository with all submodules.


# Configure and build
cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON
cmake --build cmake-build-release --target test-gamepad-outputs -j

# Run (make sure your DualSense/DualShock is connected)
./cmake-build-release/Tests/Integration/test-gamepad-inputs

๐ŸŽฎ Test Controls

Once the console application is running, use your DualSense to test the features:

Input Testing (test-gamepad-inputs)

The test-gamepad-inputs executable allows you to monitor controller data in real-time. To avoid log misalignment due to terminal width limits, it is highly recommended to test one parameter at a time.

Usage:

./cmake-build-release/Tests/Integration/test-gamepad-inputs [flags]

Available Flags:

FlagDescription
--buttonsDisplays digital button states (Cross, Circle, etc.)
--analogsDisplays stick and trigger positions (Default if no flags)
--touchDisplays detailed touchpad data (ID, Fingers, Position, Velocity)
--sensorsDisplays Motion Sensor data (Gyroscope and Accelerometer)

Note: When --touch or --sensors are passed, the respective hardware features are automatically enabled on the controller.


Output Testing (test-gamepad-outputs)

The test-gamepad-outputs executable allows you to test various controller feedback mechanisms, including vibrations, lightbar colors, and adaptive triggers.

Usage:

./cmake-build-release/Tests/Integration/test-gamepad-outputs

[ FACE BUTTONS ]

ButtonActionEffect
โŒ CrossVibration/LEDHeavy Rumble + ๐Ÿ”ด Red Light
โญ• CircleVibration/LEDSoft Rumble + ๐Ÿ”ต Blue Light
๐ŸŸฅ SquareTrigger EffectActivates GameCube-style trigger snap on R2
๐Ÿ”บ TriangleResetStops all effects (Panic Button)

[ D-PAD & SHOULDERS (Trigger Mods) ]

ButtonHandEffect
L1L2Gallop Effect (Vibration on trigger)
R1R2Machine Gun Effect (Fast vibration)
โฌ†๏ธ UpL2Feedback (Rigid Resistance)
โฌ‡๏ธ DownR2Bow (String Tension)
โฌ…๏ธ LeftR2Weapon (Semi-Automatic)
โžก๏ธ RightR2Automatic Gun (Buzzing)

Break Changes v1.0.0

// Scan for connected devices
Registry->PlugAndPlay(DeltaTime);
auto* Gamepad = Registry->GetLibrary(0)

if (Gamepad->IsConnected())
{
    if (auto* Lightbar = Gamepad->GetIGamepadLightbar())
    {
       Lightbar->SetLightbar({0, 255, 0});
    }
    
    if (auto* Trigger = Gamepad->GetIGamepadTrigger())
    {
    }
    
    // โš ๏ธ REQUIRED: Update output to apply all changes
    gamepad->UpdateOutput();
}

// Available methods for retrieving interfaces.
IGamepadTouch* GetIGamepadTouch() override { return this; }
IGamepadTrigger* GetIGamepadTrigger() override { return this; }
IGamepadHaptics* GetIGamepadHaptics() override { return this; }
IGamepadLightbar* GetIGamepadLightbar() override { return this; }
IGamepadRumbles* GetIGamepadRumbles() override { return this; }
IGamepadSensors* GetIGamepadSensors() override { return this; }
IGamepadSettings* GetIGamepadSettings() override { return this; }

Minimal Example (Standalone C++)

#include "GCore/Templates/TBasicDeviceRegistry.h"

// 1. Choose your platform policy
#ifdef _WIN32
    #include "Platform/windows/windows_hardware_policy.h"
    using platform_hardware = windows_platform::windows_hardware;
#else
    #include "Platform/linux/linux_hardware_policy.h"
    using platform_hardware = linux_platform::linux_hardware;
#endif

// 2. Define your registry policy
#include "Examples/Adapters/Tests/test_device_registry_policy.h"
using DeviceRegistry = GamepadCore::TBasicDeviceRegistry<Test_DeviceRegistryPolicy>;

int main() {
    // Initialize hardware layer
    auto Hardware = std::make_unique<HardwareInfo>();
    IPlatformHardwareInfo::SetInstance(std::move(Hardware));

    // Create device registry
    auto Registry = std::make_unique<DeviceRegistry>();

    // Game loop
    while (true) {
        float DeltaTime = 0.016f; // 60 FPS
        
        // Scan for connected devices
        Registry->PlugAndPlay(DeltaTime);

        // Get first connected gamepad
        if (auto* Gamepad = Registry->GetLibrary(0)) {
    if (Gamepad->IsConnected()) {
                // Update input state
                Gamepad->UpdateInput(DeltaTime);
                
                // Read button state
                auto Context = Gamepad->GetMutableDeviceContext();
                auto Input = Context->GetInputState();
                
                if (Input.bCross) {
                    // Trigger haptic feedback
                    Gamepad->GetIGamepadLightbar()->SetLightbar({255, 0, 0});
                    // Apply vibration
                    Gamepad->GetIGamepadRumbles()->SetRumble(255, 128);
                    
                    // โš ๏ธ REQUIRED: Update output to apply all changes
                    Gamepad->UpdateOutput();
                }
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds((int)(DeltaTime * 1000)));
    }
}

This design makes it trivial to support custom platforms (e.g., PlayStation SDK, proprietary embedded systems) without touching core logic.

๐Ÿงฉ Architecture

Gamepad-Core follows strict separation of concerns to ensure portability and extensibility:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    Your Application                         โ”‚
โ”‚              (Game Engine, Desktop App, Tool)               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚   Adapter Layer (Policy)      โ”‚  โ—„โ”€โ”€ You implement this
         โ”‚  (Engine-specific bindings)   โ”‚      (or use examples)
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚      GCore (Abstract)         โ”‚
         โ”‚  โ€ข Device Registry            โ”‚  โ—„โ”€โ”€ Pure C++, stable API
         โ”‚  โ€ข ISonyGamepad Interface     โ”‚
         โ”‚  โ€ข IGamepadTrigger Interface  โ”‚
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚   GImplementations (Drivers)  โ”‚
         โ”‚  โ€ข DualSense HID Protocol     โ”‚  โ—„โ”€โ”€ Hardware-specific
         โ”‚  โ€ข DualShock 4 HID Protocol   โ”‚
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚   Platform Policy (OS/HAL)    โ”‚  โ—„โ”€โ”€ OS-specific I/O
         โ”‚  โ€ข Windows (SetupAPI + HID)   โ”‚
         โ”‚  โ€ข Linux (HIDAPI)             โ”‚
         โ”‚  โ€ข macOS (IOKit)              โ”‚
         โ”‚  โ€ข Custom (PS5 SDK, etc.)     โ”‚
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐ŸŽต Audio Pipeline โ€” How It Works

Gamepad-Core provides a complete audio-to-haptics and audio-to-speaker pipeline. Here's how the data flows from your application to the DualSense hardware:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    YOUR APPLICATION                         โ”‚
โ”‚  โ€ข Captures audio (game sounds, music, etc.)                โ”‚
โ”‚  โ€ข Mixes audio channels                                     โ”‚
โ”‚  โ€ข Applies effects/filters                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚ (sends audio buffer)
                       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   GAMEPAD-CORE LIB                          โ”‚
โ”‚  โ€ข Receives audio buffer                                    โ”‚
โ”‚  โ€ข Converts to haptic commands (for haptics)                โ”‚
โ”‚  โ€ข Encodes for speaker output (for speaker)                 โ”‚
โ”‚  โ€ข Sends via HID (USB/Bluetooth)                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚ (HID commands)
                       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   DUALSENSE HARDWARE                        โ”‚
โ”‚  โ€ข Vibration motors (haptics)                               โ”‚
โ”‚  โ€ข Built-in speaker                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿค Contributing

  • Add support for a new platform (e.g., FreeBSD, Android)
  • Improve documentation or examples
  • Optimize HID communication
  • Report bugs or suggest features

Feel free to open an Issue or submit a Pull Request.

Guidelines

  1. Follow the existing code style (use clang-format)
  2. Test your changes with a physical controller
  3. Update documentation if you add new features
  4. Keep commits focused and well-described

โญ Credits and Acknowledgments

The foundation of this plugin was built upon the research and code from several amazing projects in the community:

Special thanks to the community members who helped improve this plugin:

  • yncat: For the extensive research and implementation logic regarding USB Audio Haptics, which was crucial for supporting high-fidelity haptics via USB (Issue #105).

This software is an independent project and is not affiliated with Sony Interactive Entertainment Inc., Epic Games, Unity Technologies, Godot Engine, or any of their subsidiaries.

Trademarks belong to their respective owners:

  • Sony: PlayStation, DualSense, DualShock are trademarks of Sony Interactive Entertainment Inc.
  • Microsoft: Windows, Xbox are trademarks of Microsoft Corporation
  • Apple: macOS is a trademark of Apple Inc.
  • Epic Games: Unreal Engine is a trademark of Epic Games, Inc.
  • Unity: Unity is a trademark of Unity Technologies
  • Godot: Godot and the Godot logo are trademarks of the Godot Engine project

โฌ† Back to Top


This project is licensed under the MIT License. See the LICENSE file for details.

Copyright (c) 2026 Rafael Valoto