From 83ecf04450bbfd8ea0d6b5c523bb9a090c01f4b2 Mon Sep 17 00:00:00 2001 From: Mickael Istria Date: Wed, 1 Apr 2026 18:07:14 +0200 Subject: [PATCH] Read orientation and forward it as axes (Linux/Evdev gamepad) Reads orientation (from https://github.com/kitswas/VGP_Data_Exchange/pull/4) and uses it as input for another axes pair when using Linux Evdev with gamepad. Keyboard and Windows are not (yet?) supported. Part of https://github.com/kitswas/VirtualGamePad-Mobile/issues/18 --- VGP_Data_Exchange | 2 +- src/networking/executor.cpp | 5 ++++- src/simulation/gamepadSim.hpp | 8 ++++++++ src/simulation/linux/gamepadSim.cpp | 21 +++++++++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/VGP_Data_Exchange b/VGP_Data_Exchange index 23accf0a..f8767bdd 160000 --- a/VGP_Data_Exchange +++ b/VGP_Data_Exchange @@ -1 +1 @@ -Subproject commit 23accf0abbd147b3af416b49839fe866ece86277 +Subproject commit f8767bdda2449ad826477b21c1f1c6605c7e06a7 diff --git a/src/networking/executor.cpp b/src/networking/executor.cpp index 69b2fae6..e4a0c144 100644 --- a/src/networking/executor.cpp +++ b/src/networking/executor.cpp @@ -148,7 +148,9 @@ ParseResult parse_gamepad_state(const char *data, size_t len) << "\nLeft thumbstick x: " << result.reading.left_thumbstick_x << "\nLeft thumbstick y: " << result.reading.left_thumbstick_y << "\nRight thumbstick x: " << result.reading.right_thumbstick_x - << "\nRight thumbstick y: " << result.reading.right_thumbstick_y; + << "\nRight thumbstick y: " << result.reading.right_thumbstick_y + << "\nPitch: " << result.reading.pitch + << "\nRoll: " << result.reading.roll; #endif return result; @@ -432,6 +434,7 @@ bool GamepadExecutor::inject_gamepad_state(vgp_data_exchange_gamepad_reading con m_injector.setThumbsticks(reading.left_thumbstick_x, -reading.left_thumbstick_y, reading.right_thumbstick_x, -reading.right_thumbstick_y); m_injector.setTriggers(reading.left_trigger, reading.right_trigger); + m_injector.setOrientation(reading.pitch, reading.roll); // Handle button presses (mapping from our buttons to Linux input codes) if (reading.buttons_down & GamepadButtons_Menu) diff --git a/src/simulation/gamepadSim.hpp b/src/simulation/gamepadSim.hpp index 66e6ff95..3293cab2 100644 --- a/src/simulation/gamepadSim.hpp +++ b/src/simulation/gamepadSim.hpp @@ -88,6 +88,14 @@ class GamepadInjector */ void setTriggers(float leftTrigger, float rightTrigger); + /** + * @brief Sets orientation as axis value (Linux) + * + * @param pitch pitch (-PI/2 to PI) + * @param roll roll (-PI to PI) + */ + void setOrientation(float pitch, float roll); + /** * @brief Press a gamepad button (Linux). * diff --git a/src/simulation/linux/gamepadSim.cpp b/src/simulation/linux/gamepadSim.cpp index fe48787c..17cfa3df 100644 --- a/src/simulation/linux/gamepadSim.cpp +++ b/src/simulation/linux/gamepadSim.cpp @@ -100,6 +100,16 @@ GamepadInjector::GamepadInjector() libevdev_enable_event_code(dev.get(), EV_ABS, ABS_HAT2X, &absinfo); // Left trigger libevdev_enable_event_code(dev.get(), EV_ABS, ABS_HAT2Y, &absinfo); // Right trigger + // Orientation + absinfo.minimum = static_cast(-std::numbers::pi / 2 * 20000); + absinfo.maximum = static_cast(std::numbers::pi / 2 * 20000); + absinfo.fuzz = 0; + absinfo.flat = 0; + libevdev_enable_event_code(dev.get(), EV_ABS, ABS_HAT3X, &absinfo); // Pitch + absinfo.minimum = static_cast(-std::numbers::pi * 10000); + absinfo.maximum = static_cast(std::numbers::pi * 10000); + libevdev_enable_event_code(dev.get(), EV_ABS, ABS_HAT3Y, &absinfo); // Roll + // Create uinput device libevdev_uinput *rawUidev; int ret = @@ -153,6 +163,17 @@ void GamepadInjector::setTriggers(float leftTrigger, float rightTrigger) libevdev_uinput_write_event(uidev.get(), EV_ABS, ABS_HAT2Y, rightInt); } +void GamepadInjector::setOrientation(float pitch, float roll) +{ + qInfo() << pitch << "\n"; + // Convert from [-PI/2..PI/2] to int range defined earlier with libevdev_enable_event_code for this axis + int evdevPitch = static_cast(pitch * 20000); + // Convert from [-PI..PI] to int range defined earlier with libevdev_enable_event_code for this axis + int evdevRoll = static_cast(roll * 10000); + libevdev_uinput_write_event(uidev.get(), EV_ABS, ABS_HAT3X, evdevPitch); + libevdev_uinput_write_event(uidev.get(), EV_ABS, ABS_HAT3Y, evdevRoll); +} + void GamepadInjector::pressButton(int buttonCode) { libevdev_uinput_write_event(uidev.get(), EV_KEY, buttonCode, 1);