summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/CMakeLists.txt8
-rw-r--r--src/input_common/drivers/camera.cpp82
-rw-r--r--src/input_common/drivers/camera.h29
-rw-r--r--src/input_common/drivers/gc_adapter.cpp25
-rw-r--r--src/input_common/drivers/gc_adapter.h8
-rw-r--r--src/input_common/drivers/keyboard.cpp5
-rw-r--r--src/input_common/drivers/keyboard.h5
-rw-r--r--src/input_common/drivers/mouse.cpp7
-rw-r--r--src/input_common/drivers/mouse.h5
-rw-r--r--src/input_common/drivers/sdl_driver.cpp167
-rw-r--r--src/input_common/drivers/sdl_driver.h35
-rw-r--r--src/input_common/drivers/tas_input.cpp5
-rw-r--r--src/input_common/drivers/tas_input.h5
-rw-r--r--src/input_common/drivers/touch_screen.cpp94
-rw-r--r--src/input_common/drivers/touch_screen.h57
-rw-r--r--src/input_common/drivers/udp_client.cpp35
-rw-r--r--src/input_common/drivers/udp_client.h9
-rw-r--r--src/input_common/drivers/virtual_amiibo.cpp101
-rw-r--r--src/input_common/drivers/virtual_amiibo.h61
-rw-r--r--src/input_common/helpers/stick_from_buttons.cpp5
-rw-r--r--src/input_common/helpers/stick_from_buttons.h5
-rw-r--r--src/input_common/helpers/touch_from_buttons.cpp5
-rw-r--r--src/input_common/helpers/touch_from_buttons.h5
-rw-r--r--src/input_common/helpers/udp_protocol.cpp5
-rw-r--r--src/input_common/helpers/udp_protocol.h17
-rw-r--r--src/input_common/input_engine.cpp135
-rw-r--r--src/input_common/input_engine.h64
-rw-r--r--src/input_common/input_mapping.cpp5
-rw-r--r--src/input_common/input_mapping.h5
-rw-r--r--src/input_common/input_poller.cpp134
-rw-r--r--src/input_common/input_poller.h26
-rw-r--r--src/input_common/main.cpp77
-rw-r--r--src/input_common/main.h24
33 files changed, 1023 insertions, 232 deletions
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index d4fa69a77..2cf9eb97f 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -1,4 +1,9 @@
1# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
2# SPDX-License-Identifier: GPL-2.0-or-later
3
1add_library(input_common STATIC 4add_library(input_common STATIC
5 drivers/camera.cpp
6 drivers/camera.h
2 drivers/gc_adapter.cpp 7 drivers/gc_adapter.cpp
3 drivers/gc_adapter.h 8 drivers/gc_adapter.h
4 drivers/keyboard.cpp 9 drivers/keyboard.cpp
@@ -13,6 +18,8 @@ add_library(input_common STATIC
13 drivers/touch_screen.h 18 drivers/touch_screen.h
14 drivers/udp_client.cpp 19 drivers/udp_client.cpp
15 drivers/udp_client.h 20 drivers/udp_client.h
21 drivers/virtual_amiibo.cpp
22 drivers/virtual_amiibo.h
16 helpers/stick_from_buttons.cpp 23 helpers/stick_from_buttons.cpp
17 helpers/stick_from_buttons.h 24 helpers/stick_from_buttons.h
18 helpers/touch_from_buttons.cpp 25 helpers/touch_from_buttons.cpp
@@ -44,7 +51,6 @@ else()
44 -Werror 51 -Werror
45 -Werror=conversion 52 -Werror=conversion
46 -Werror=ignored-qualifiers 53 -Werror=ignored-qualifiers
47 -Werror=shadow
48 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 54 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
49 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 55 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
50 -Werror=unused-variable 56 -Werror=unused-variable
diff --git a/src/input_common/drivers/camera.cpp b/src/input_common/drivers/camera.cpp
new file mode 100644
index 000000000..dceea67e0
--- /dev/null
+++ b/src/input_common/drivers/camera.cpp
@@ -0,0 +1,82 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <fmt/format.h>
5
6#include "common/param_package.h"
7#include "input_common/drivers/camera.h"
8
9namespace InputCommon {
10constexpr PadIdentifier identifier = {
11 .guid = Common::UUID{},
12 .port = 0,
13 .pad = 0,
14};
15
16Camera::Camera(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
17 PreSetController(identifier);
18}
19
20void Camera::SetCameraData(std::size_t width, std::size_t height, std::vector<u32> data) {
21 const std::size_t desired_width = getImageWidth();
22 const std::size_t desired_height = getImageHeight();
23 status.data.resize(desired_width * desired_height);
24
25 // Resize image to desired format
26 for (std::size_t y = 0; y < desired_height; y++) {
27 for (std::size_t x = 0; x < desired_width; x++) {
28 const std::size_t pixel_index = y * desired_width + x;
29 const std::size_t old_x = width * x / desired_width;
30 const std::size_t old_y = height * y / desired_height;
31 const std::size_t data_pixel_index = old_y * width + old_x;
32 status.data[pixel_index] = static_cast<u8>(data[data_pixel_index] & 0xFF);
33 }
34 }
35
36 SetCamera(identifier, status);
37}
38
39std::size_t Camera::getImageWidth() const {
40 switch (status.format) {
41 case Common::Input::CameraFormat::Size320x240:
42 return 320;
43 case Common::Input::CameraFormat::Size160x120:
44 return 160;
45 case Common::Input::CameraFormat::Size80x60:
46 return 80;
47 case Common::Input::CameraFormat::Size40x30:
48 return 40;
49 case Common::Input::CameraFormat::Size20x15:
50 return 20;
51 case Common::Input::CameraFormat::None:
52 default:
53 return 0;
54 }
55}
56
57std::size_t Camera::getImageHeight() const {
58 switch (status.format) {
59 case Common::Input::CameraFormat::Size320x240:
60 return 240;
61 case Common::Input::CameraFormat::Size160x120:
62 return 120;
63 case Common::Input::CameraFormat::Size80x60:
64 return 60;
65 case Common::Input::CameraFormat::Size40x30:
66 return 30;
67 case Common::Input::CameraFormat::Size20x15:
68 return 15;
69 case Common::Input::CameraFormat::None:
70 default:
71 return 0;
72 }
73}
74
75Common::Input::CameraError Camera::SetCameraFormat(
76 [[maybe_unused]] const PadIdentifier& identifier_,
77 const Common::Input::CameraFormat camera_format) {
78 status.format = camera_format;
79 return Common::Input::CameraError::None;
80}
81
82} // namespace InputCommon
diff --git a/src/input_common/drivers/camera.h b/src/input_common/drivers/camera.h
new file mode 100644
index 000000000..b8a7c75e5
--- /dev/null
+++ b/src/input_common/drivers/camera.h
@@ -0,0 +1,29 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "input_common/input_engine.h"
7
8namespace InputCommon {
9
10/**
11 * A button device factory representing a keyboard. It receives keyboard events and forward them
12 * to all button devices it created.
13 */
14class Camera final : public InputEngine {
15public:
16 explicit Camera(std::string input_engine_);
17
18 void SetCameraData(std::size_t width, std::size_t height, std::vector<u32> data);
19
20 std::size_t getImageWidth() const;
21 std::size_t getImageHeight() const;
22
23 Common::Input::CameraError SetCameraFormat(const PadIdentifier& identifier_,
24 Common::Input::CameraFormat camera_format) override;
25
26 Common::Input::CameraStatus status{};
27};
28
29} // namespace InputCommon
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 155caae42..f4dd24e7d 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -1,6 +1,5 @@
1// Copyright 2014 Dolphin Emulator Project 1// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project
2// Licensed under GPLv2+ 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <fmt/format.h> 4#include <fmt/format.h>
6#include <libusb.h> 5#include <libusb.h>
@@ -91,7 +90,7 @@ GCAdapter::~GCAdapter() {
91 90
92void GCAdapter::AdapterInputThread(std::stop_token stop_token) { 91void GCAdapter::AdapterInputThread(std::stop_token stop_token) {
93 LOG_DEBUG(Input, "Input thread started"); 92 LOG_DEBUG(Input, "Input thread started");
94 Common::SetCurrentThreadName("yuzu:input:GCAdapter"); 93 Common::SetCurrentThreadName("GCAdapter");
95 s32 payload_size{}; 94 s32 payload_size{};
96 AdapterPayload adapter_payload{}; 95 AdapterPayload adapter_payload{};
97 96
@@ -215,7 +214,7 @@ void GCAdapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_
215} 214}
216 215
217void GCAdapter::AdapterScanThread(std::stop_token stop_token) { 216void GCAdapter::AdapterScanThread(std::stop_token stop_token) {
218 Common::SetCurrentThreadName("yuzu:input:ScanGCAdapter"); 217 Common::SetCurrentThreadName("ScanGCAdapter");
219 usb_adapter_handle = nullptr; 218 usb_adapter_handle = nullptr;
220 pads = {}; 219 pads = {};
221 while (!stop_token.stop_requested() && !Setup()) { 220 while (!stop_token.stop_requested() && !Setup()) {
@@ -524,4 +523,20 @@ Common::Input::ButtonNames GCAdapter::GetUIName(const Common::ParamPackage& para
524 return Common::Input::ButtonNames::Invalid; 523 return Common::Input::ButtonNames::Invalid;
525} 524}
526 525
526bool GCAdapter::IsStickInverted(const Common::ParamPackage& params) {
527 if (!params.Has("port")) {
528 return false;
529 }
530
531 const auto x_axis = static_cast<PadAxes>(params.Get("axis_x", 0));
532 const auto y_axis = static_cast<PadAxes>(params.Get("axis_y", 0));
533 if (x_axis != PadAxes::StickY && x_axis != PadAxes::SubstickY) {
534 return false;
535 }
536 if (y_axis != PadAxes::StickX && y_axis != PadAxes::SubstickX) {
537 return false;
538 }
539 return true;
540}
541
527} // namespace InputCommon 542} // namespace InputCommon
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index 7ce1912a3..8682da847 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -1,12 +1,10 @@
1// Copyright 2014 Dolphin Emulator Project 1// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project
2// Licensed under GPLv2+ 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
7#include <array> 6#include <array>
8#include <memory> 7#include <memory>
9#include <mutex>
10#include <stop_token> 8#include <stop_token>
11#include <string> 9#include <string>
12#include <thread> 10#include <thread>
@@ -36,6 +34,8 @@ public:
36 AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; 34 AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
37 Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; 35 Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
38 36
37 bool IsStickInverted(const Common::ParamPackage& params) override;
38
39private: 39private:
40 enum class PadButton { 40 enum class PadButton {
41 Undefined = 0x0000, 41 Undefined = 0x0000,
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp
index 59e3d9cc0..71e612fbf 100644
--- a/src/input_common/drivers/keyboard.cpp
+++ b/src/input_common/drivers/keyboard.cpp
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#include "common/param_package.h" 4#include "common/param_package.h"
6#include "common/settings_input.h" 5#include "common/settings_input.h"
diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h
index 3856c882c..62436dba4 100644
--- a/src/input_common/drivers/keyboard.h
+++ b/src/input_common/drivers/keyboard.h
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#pragma once 4#pragma once
6 5
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 3c9a4e747..98c3157a8 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#include <stop_token> 4#include <stop_token>
6#include <thread> 5#include <thread>
@@ -38,7 +37,7 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_))
38} 37}
39 38
40void Mouse::UpdateThread(std::stop_token stop_token) { 39void Mouse::UpdateThread(std::stop_token stop_token) {
41 Common::SetCurrentThreadName("yuzu:input:Mouse"); 40 Common::SetCurrentThreadName("Mouse");
42 constexpr int update_time = 10; 41 constexpr int update_time = 10;
43 while (!stop_token.stop_requested()) { 42 while (!stop_token.stop_requested()) {
44 if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { 43 if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index c5833b8ed..286ce1cf6 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#pragma once 4#pragma once
6 5
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 5cf1987ad..b72e4b397 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -1,6 +1,5 @@
1// Copyright 2018 Citra Emulator Project 1// SPDX-FileCopyrightText: 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include "common/logging/log.h" 4#include "common/logging/log.h"
6#include "common/math_util.h" 5#include "common/math_util.h"
@@ -13,11 +12,11 @@
13namespace InputCommon { 12namespace InputCommon {
14 13
15namespace { 14namespace {
16std::string GetGUID(SDL_Joystick* joystick) { 15Common::UUID GetGUID(SDL_Joystick* joystick) {
17 const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); 16 const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
18 char guid_str[33]; 17 std::array<u8, 16> data{};
19 SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); 18 std::memcpy(data.data(), guid.data, sizeof(data));
20 return guid_str; 19 return Common::UUID{data};
21} 20}
22} // Anonymous namespace 21} // Anonymous namespace
23 22
@@ -31,9 +30,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
31 30
32class SDLJoystick { 31class SDLJoystick {
33public: 32public:
34 SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, 33 SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick,
35 SDL_GameController* game_controller) 34 SDL_GameController* game_controller)
36 : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, 35 : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
37 sdl_controller{game_controller, &SDL_GameControllerClose} { 36 sdl_controller{game_controller, &SDL_GameControllerClose} {
38 EnableMotion(); 37 EnableMotion();
39 } 38 }
@@ -41,13 +40,13 @@ public:
41 void EnableMotion() { 40 void EnableMotion() {
42 if (sdl_controller) { 41 if (sdl_controller) {
43 SDL_GameController* controller = sdl_controller.get(); 42 SDL_GameController* controller = sdl_controller.get();
44 if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) { 43 has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL);
44 has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO);
45 if (has_accel) {
45 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); 46 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
46 has_accel = true;
47 } 47 }
48 if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) { 48 if (has_gyro) {
49 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); 49 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
50 has_gyro = true;
51 } 50 }
52 } 51 }
53 } 52 }
@@ -62,7 +61,7 @@ public:
62 61
63 bool UpdateMotion(SDL_ControllerSensorEvent event) { 62 bool UpdateMotion(SDL_ControllerSensorEvent event) {
64 constexpr float gravity_constant = 9.80665f; 63 constexpr float gravity_constant = 9.80665f;
65 std::lock_guard lock{mutex}; 64 std::scoped_lock lock{mutex};
66 const u64 time_difference = event.timestamp - last_motion_update; 65 const u64 time_difference = event.timestamp - last_motion_update;
67 last_motion_update = event.timestamp; 66 last_motion_update = event.timestamp;
68 switch (event.sensor) { 67 switch (event.sensor) {
@@ -120,7 +119,7 @@ public:
120 */ 119 */
121 const PadIdentifier GetPadIdentifier() const { 120 const PadIdentifier GetPadIdentifier() const {
122 return { 121 return {
123 .guid = Common::UUID{guid}, 122 .guid = guid,
124 .port = static_cast<std::size_t>(port), 123 .port = static_cast<std::size_t>(port),
125 .pad = 0, 124 .pad = 0,
126 }; 125 };
@@ -129,7 +128,7 @@ public:
129 /** 128 /**
130 * The guid of the joystick 129 * The guid of the joystick
131 */ 130 */
132 const std::string& GetGUID() const { 131 const Common::UUID& GetGUID() const {
133 return guid; 132 return guid;
134 } 133 }
135 134
@@ -175,22 +174,23 @@ public:
175 return false; 174 return false;
176 } 175 }
177 176
178 BatteryLevel GetBatteryLevel() { 177 Common::Input::BatteryLevel GetBatteryLevel() {
179 const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); 178 const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get());
180 switch (level) { 179 switch (level) {
181 case SDL_JOYSTICK_POWER_EMPTY: 180 case SDL_JOYSTICK_POWER_EMPTY:
182 return BatteryLevel::Empty; 181 return Common::Input::BatteryLevel::Empty;
183 case SDL_JOYSTICK_POWER_LOW: 182 case SDL_JOYSTICK_POWER_LOW:
184 return BatteryLevel::Low; 183 return Common::Input::BatteryLevel::Low;
185 case SDL_JOYSTICK_POWER_MEDIUM: 184 case SDL_JOYSTICK_POWER_MEDIUM:
186 return BatteryLevel::Medium; 185 return Common::Input::BatteryLevel::Medium;
187 case SDL_JOYSTICK_POWER_FULL: 186 case SDL_JOYSTICK_POWER_FULL:
188 case SDL_JOYSTICK_POWER_MAX: 187 case SDL_JOYSTICK_POWER_MAX:
189 return BatteryLevel::Full; 188 return Common::Input::BatteryLevel::Full;
190 case SDL_JOYSTICK_POWER_UNKNOWN:
191 case SDL_JOYSTICK_POWER_WIRED: 189 case SDL_JOYSTICK_POWER_WIRED:
190 return Common::Input::BatteryLevel::Charging;
191 case SDL_JOYSTICK_POWER_UNKNOWN:
192 default: 192 default:
193 return BatteryLevel::Charging; 193 return Common::Input::BatteryLevel::None;
194 } 194 }
195 } 195 }
196 196
@@ -227,7 +227,7 @@ public:
227 } 227 }
228 228
229private: 229private:
230 std::string guid; 230 Common::UUID guid;
231 int port; 231 int port;
232 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; 232 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
233 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; 233 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
@@ -239,8 +239,8 @@ private:
239 BasicMotion motion; 239 BasicMotion motion;
240}; 240};
241 241
242std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) { 242std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const Common::UUID& guid, int port) {
243 std::lock_guard lock{joystick_map_mutex}; 243 std::scoped_lock lock{joystick_map_mutex};
244 const auto it = joystick_map.find(guid); 244 const auto it = joystick_map.find(guid);
245 245
246 if (it != joystick_map.end()) { 246 if (it != joystick_map.end()) {
@@ -258,11 +258,15 @@ std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string&
258 return joystick_map[guid].emplace_back(std::move(joystick)); 258 return joystick_map[guid].emplace_back(std::move(joystick));
259} 259}
260 260
261std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) {
262 return GetSDLJoystickByGUID(Common::UUID{guid}, port);
263}
264
261std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { 265std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
262 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); 266 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
263 const std::string guid = GetGUID(sdl_joystick); 267 const auto guid = GetGUID(sdl_joystick);
264 268
265 std::lock_guard lock{joystick_map_mutex}; 269 std::scoped_lock lock{joystick_map_mutex};
266 const auto map_it = joystick_map.find(guid); 270 const auto map_it = joystick_map.find(guid);
267 271
268 if (map_it == joystick_map.end()) { 272 if (map_it == joystick_map.end()) {
@@ -294,13 +298,14 @@ void SDLDriver::InitJoystick(int joystick_index) {
294 return; 298 return;
295 } 299 }
296 300
297 const std::string guid = GetGUID(sdl_joystick); 301 const auto guid = GetGUID(sdl_joystick);
298 302
299 std::lock_guard lock{joystick_map_mutex}; 303 std::scoped_lock lock{joystick_map_mutex};
300 if (joystick_map.find(guid) == joystick_map.end()) { 304 if (joystick_map.find(guid) == joystick_map.end()) {
301 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); 305 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
302 PreSetController(joystick->GetPadIdentifier()); 306 PreSetController(joystick->GetPadIdentifier());
303 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); 307 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
308 joystick->EnableMotion();
304 joystick_map[guid].emplace_back(std::move(joystick)); 309 joystick_map[guid].emplace_back(std::move(joystick));
305 return; 310 return;
306 } 311 }
@@ -312,6 +317,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
312 317
313 if (joystick_it != joystick_guid_list.end()) { 318 if (joystick_it != joystick_guid_list.end()) {
314 (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); 319 (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
320 (*joystick_it)->EnableMotion();
315 return; 321 return;
316 } 322 }
317 323
@@ -319,13 +325,14 @@ void SDLDriver::InitJoystick(int joystick_index) {
319 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); 325 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
320 PreSetController(joystick->GetPadIdentifier()); 326 PreSetController(joystick->GetPadIdentifier());
321 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); 327 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
328 joystick->EnableMotion();
322 joystick_guid_list.emplace_back(std::move(joystick)); 329 joystick_guid_list.emplace_back(std::move(joystick));
323} 330}
324 331
325void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { 332void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) {
326 const std::string guid = GetGUID(sdl_joystick); 333 const auto guid = GetGUID(sdl_joystick);
327 334
328 std::lock_guard lock{joystick_map_mutex}; 335 std::scoped_lock lock{joystick_map_mutex};
329 // This call to guid is safe since the joystick is guaranteed to be in the map 336 // This call to guid is safe since the joystick is guaranteed to be in the map
330 const auto& joystick_guid_list = joystick_map[guid]; 337 const auto& joystick_guid_list = joystick_map[guid];
331 const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), 338 const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
@@ -351,6 +358,8 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
351 if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { 358 if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
352 const PadIdentifier identifier = joystick->GetPadIdentifier(); 359 const PadIdentifier identifier = joystick->GetPadIdentifier();
353 SetButton(identifier, event.jbutton.button, true); 360 SetButton(identifier, event.jbutton.button, true);
361 // Battery doesn't trigger an event so just update every button press
362 SetBattery(identifier, joystick->GetBatteryLevel());
354 } 363 }
355 break; 364 break;
356 } 365 }
@@ -389,7 +398,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
389} 398}
390 399
391void SDLDriver::CloseJoysticks() { 400void SDLDriver::CloseJoysticks() {
392 std::lock_guard lock{joystick_map_mutex}; 401 std::scoped_lock lock{joystick_map_mutex};
393 joystick_map.clear(); 402 joystick_map.clear();
394} 403}
395 404
@@ -427,13 +436,21 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
427 initialized = true; 436 initialized = true;
428 if (start_thread) { 437 if (start_thread) {
429 poll_thread = std::thread([this] { 438 poll_thread = std::thread([this] {
430 Common::SetCurrentThreadName("yuzu:input:SDL"); 439 Common::SetCurrentThreadName("SDL_MainLoop");
431 using namespace std::chrono_literals; 440 using namespace std::chrono_literals;
432 while (initialized) { 441 while (initialized) {
433 SDL_PumpEvents(); 442 SDL_PumpEvents();
434 std::this_thread::sleep_for(1ms); 443 std::this_thread::sleep_for(1ms);
435 } 444 }
436 }); 445 });
446 vibration_thread = std::thread([this] {
447 Common::SetCurrentThreadName("SDL_Vibration");
448 using namespace std::chrono_literals;
449 while (initialized) {
450 SendVibrations();
451 std::this_thread::sleep_for(10ms);
452 }
453 });
437 } 454 }
438 // Because the events for joystick connection happens before we have our event watcher added, we 455 // Because the events for joystick connection happens before we have our event watcher added, we
439 // can just open all the joysticks right here 456 // can just open all the joysticks right here
@@ -449,6 +466,7 @@ SDLDriver::~SDLDriver() {
449 initialized = false; 466 initialized = false;
450 if (start_thread) { 467 if (start_thread) {
451 poll_thread.join(); 468 poll_thread.join();
469 vibration_thread.join();
452 SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); 470 SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
453 } 471 }
454} 472}
@@ -466,7 +484,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
466 devices.emplace_back(Common::ParamPackage{ 484 devices.emplace_back(Common::ParamPackage{
467 {"engine", GetEngineName()}, 485 {"engine", GetEngineName()},
468 {"display", std::move(name)}, 486 {"display", std::move(name)},
469 {"guid", joystick->GetGUID()}, 487 {"guid", joystick->GetGUID().RawString()},
470 {"port", std::to_string(joystick->GetPort())}, 488 {"port", std::to_string(joystick->GetPort())},
471 }); 489 });
472 if (joystick->IsJoyconLeft()) { 490 if (joystick->IsJoyconLeft()) {
@@ -489,8 +507,8 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
489 devices.emplace_back(Common::ParamPackage{ 507 devices.emplace_back(Common::ParamPackage{
490 {"engine", GetEngineName()}, 508 {"engine", GetEngineName()},
491 {"display", std::move(name)}, 509 {"display", std::move(name)},
492 {"guid", joystick->GetGUID()}, 510 {"guid", joystick->GetGUID().RawString()},
493 {"guid2", joystick2->GetGUID()}, 511 {"guid2", joystick2->GetGUID().RawString()},
494 {"port", std::to_string(joystick->GetPort())}, 512 {"port", std::to_string(joystick->GetPort())},
495 }); 513 });
496 } 514 }
@@ -528,57 +546,75 @@ Common::Input::VibrationError SDLDriver::SetRumble(
528 .type = Common::Input::VibrationAmplificationType::Exponential, 546 .type = Common::Input::VibrationAmplificationType::Exponential,
529 }; 547 };
530 548
531 if (!joystick->RumblePlay(new_vibration)) { 549 if (vibration.type == Common::Input::VibrationAmplificationType::Test) {
532 return Common::Input::VibrationError::Unknown; 550 if (!joystick->RumblePlay(new_vibration)) {
551 return Common::Input::VibrationError::Unknown;
552 }
553 return Common::Input::VibrationError::None;
533 } 554 }
534 555
556 vibration_queue.Push(VibrationRequest{
557 .identifier = identifier,
558 .vibration = new_vibration,
559 });
560
535 return Common::Input::VibrationError::None; 561 return Common::Input::VibrationError::None;
536} 562}
537 563
538Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, 564void SDLDriver::SendVibrations() {
565 while (!vibration_queue.Empty()) {
566 VibrationRequest request;
567 vibration_queue.Pop(request);
568 const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(),
569 static_cast<int>(request.identifier.port));
570 joystick->RumblePlay(request.vibration);
571 }
572}
573
574Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, const Common::UUID& guid,
539 s32 axis, float value) const { 575 s32 axis, float value) const {
540 Common::ParamPackage params{}; 576 Common::ParamPackage params{};
541 params.Set("engine", GetEngineName()); 577 params.Set("engine", GetEngineName());
542 params.Set("port", port); 578 params.Set("port", port);
543 params.Set("guid", std::move(guid)); 579 params.Set("guid", guid.RawString());
544 params.Set("axis", axis); 580 params.Set("axis", axis);
545 params.Set("threshold", "0.5"); 581 params.Set("threshold", "0.5");
546 params.Set("invert", value < 0 ? "-" : "+"); 582 params.Set("invert", value < 0 ? "-" : "+");
547 return params; 583 return params;
548} 584}
549 585
550Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::string guid, 586Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, const Common::UUID& guid,
551 s32 button) const { 587 s32 button) const {
552 Common::ParamPackage params{}; 588 Common::ParamPackage params{};
553 params.Set("engine", GetEngineName()); 589 params.Set("engine", GetEngineName());
554 params.Set("port", port); 590 params.Set("port", port);
555 params.Set("guid", std::move(guid)); 591 params.Set("guid", guid.RawString());
556 params.Set("button", button); 592 params.Set("button", button);
557 return params; 593 return params;
558} 594}
559 595
560Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::string guid, s32 hat, 596Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, const Common::UUID& guid,
561 u8 value) const { 597 s32 hat, u8 value) const {
562 Common::ParamPackage params{}; 598 Common::ParamPackage params{};
563 params.Set("engine", GetEngineName()); 599 params.Set("engine", GetEngineName());
564 params.Set("port", port); 600 params.Set("port", port);
565 params.Set("guid", std::move(guid)); 601 params.Set("guid", guid.RawString());
566 params.Set("hat", hat); 602 params.Set("hat", hat);
567 params.Set("direction", GetHatButtonName(value)); 603 params.Set("direction", GetHatButtonName(value));
568 return params; 604 return params;
569} 605}
570 606
571Common::ParamPackage SDLDriver::BuildMotionParam(int port, std::string guid) const { 607Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& guid) const {
572 Common::ParamPackage params{}; 608 Common::ParamPackage params{};
573 params.Set("engine", GetEngineName()); 609 params.Set("engine", GetEngineName());
574 params.Set("motion", 0); 610 params.Set("motion", 0);
575 params.Set("port", port); 611 params.Set("port", port);
576 params.Set("guid", std::move(guid)); 612 params.Set("guid", guid.RawString());
577 return params; 613 return params;
578} 614}
579 615
580Common::ParamPackage SDLDriver::BuildParamPackageForBinding( 616Common::ParamPackage SDLDriver::BuildParamPackageForBinding(
581 int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const { 617 int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const {
582 switch (binding.bindType) { 618 switch (binding.bindType) {
583 case SDL_CONTROLLER_BINDTYPE_NONE: 619 case SDL_CONTROLLER_BINDTYPE_NONE:
584 break; 620 break;
@@ -931,4 +967,37 @@ u8 SDLDriver::GetHatButtonId(const std::string& direction_name) const {
931 return direction; 967 return direction;
932} 968}
933 969
970bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) {
971 if (!params.Has("guid") || !params.Has("port")) {
972 return false;
973 }
974 const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
975 if (joystick == nullptr) {
976 return false;
977 }
978 auto* controller = joystick->GetSDLGameController();
979 if (controller == nullptr) {
980 return false;
981 }
982
983 const auto& axis_x = params.Get("axis_x", 0);
984 const auto& axis_y = params.Get("axis_y", 0);
985 const auto& binding_left_x =
986 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
987 const auto& binding_right_x =
988 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
989 const auto& binding_left_y =
990 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
991 const auto& binding_right_y =
992 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
993
994 if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) {
995 return false;
996 }
997 if (axis_y != binding_left_x.value.axis && axis_y != binding_right_x.value.axis) {
998 return false;
999 }
1000 return true;
1001}
1002
934} // namespace InputCommon 1003} // namespace InputCommon
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index 4cde3606f..fc3a44572 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -1,6 +1,5 @@
1// Copyright 2018 Citra Emulator Project 1// SPDX-FileCopyrightText: 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
@@ -12,6 +11,7 @@
12#include <SDL.h> 11#include <SDL.h>
13 12
14#include "common/common_types.h" 13#include "common/common_types.h"
14#include "common/threadsafe_queue.h"
15#include "input_common/input_engine.h" 15#include "input_common/input_engine.h"
16 16
17union SDL_Event; 17union SDL_Event;
@@ -46,6 +46,7 @@ public:
46 * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so 46 * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so
47 * tie it to a SDLJoystick with the same guid and that port 47 * tie it to a SDLJoystick with the same guid and that port
48 */ 48 */
49 std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const Common::UUID& guid, int port);
49 std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port); 50 std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port);
50 51
51 std::vector<Common::ParamPackage> GetInputDevices() const override; 52 std::vector<Common::ParamPackage> GetInputDevices() const override;
@@ -58,28 +59,38 @@ public:
58 std::string GetHatButtonName(u8 direction_value) const override; 59 std::string GetHatButtonName(u8 direction_value) const override;
59 u8 GetHatButtonId(const std::string& direction_name) const override; 60 u8 GetHatButtonId(const std::string& direction_name) const override;
60 61
62 bool IsStickInverted(const Common::ParamPackage& params) override;
63
61 Common::Input::VibrationError SetRumble( 64 Common::Input::VibrationError SetRumble(
62 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; 65 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
63 66
64private: 67private:
68 struct VibrationRequest {
69 PadIdentifier identifier;
70 Common::Input::VibrationStatus vibration;
71 };
72
65 void InitJoystick(int joystick_index); 73 void InitJoystick(int joystick_index);
66 void CloseJoystick(SDL_Joystick* sdl_joystick); 74 void CloseJoystick(SDL_Joystick* sdl_joystick);
67 75
68 /// Needs to be called before SDL_QuitSubSystem. 76 /// Needs to be called before SDL_QuitSubSystem.
69 void CloseJoysticks(); 77 void CloseJoysticks();
70 78
71 Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, 79 /// Takes all vibrations from the queue and sends the command to the controller
72 float value = 0.1f) const; 80 void SendVibrations();
73 Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, 81
82 Common::ParamPackage BuildAnalogParamPackageForButton(int port, const Common::UUID& guid,
83 s32 axis, float value = 0.1f) const;
84 Common::ParamPackage BuildButtonParamPackageForButton(int port, const Common::UUID& guid,
74 s32 button) const; 85 s32 button) const;
75 86
76 Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, 87 Common::ParamPackage BuildHatParamPackageForButton(int port, const Common::UUID& guid, s32 hat,
77 u8 value) const; 88 u8 value) const;
78 89
79 Common::ParamPackage BuildMotionParam(int port, std::string guid) const; 90 Common::ParamPackage BuildMotionParam(int port, const Common::UUID& guid) const;
80 91
81 Common::ParamPackage BuildParamPackageForBinding( 92 Common::ParamPackage BuildParamPackageForBinding(
82 int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const; 93 int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const;
83 94
84 Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, 95 Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x,
85 int axis_y, float offset_x, 96 int axis_y, float offset_x,
@@ -105,13 +116,17 @@ private:
105 /// Returns true if the button is on the left joycon 116 /// Returns true if the button is on the left joycon
106 bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; 117 bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const;
107 118
119 /// Queue of vibration request to controllers
120 Common::SPSCQueue<VibrationRequest> vibration_queue;
121
108 /// Map of GUID of a list of corresponding virtual Joysticks 122 /// Map of GUID of a list of corresponding virtual Joysticks
109 std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; 123 std::unordered_map<Common::UUID, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
110 std::mutex joystick_map_mutex; 124 std::mutex joystick_map_mutex;
111 125
112 bool start_thread = false; 126 bool start_thread = false;
113 std::atomic<bool> initialized = false; 127 std::atomic<bool> initialized = false;
114 128
115 std::thread poll_thread; 129 std::thread poll_thread;
130 std::thread vibration_thread;
116}; 131};
117} // namespace InputCommon 132} // namespace InputCommon
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
index 944e141bf..21c6ed405 100644
--- a/src/input_common/drivers/tas_input.cpp
+++ b/src/input_common/drivers/tas_input.cpp
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2+ 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <cstring> 4#include <cstring>
6#include <fmt/format.h> 5#include <fmt/format.h>
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
index 4b4e6c417..38a27a230 100644
--- a/src/input_common/drivers/tas_input.h
+++ b/src/input_common/drivers/tas_input.h
@@ -1,6 +1,5 @@
1// Copyright 2020 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp
index 30c727df4..1753e0893 100644
--- a/src/input_common/drivers/touch_screen.cpp
+++ b/src/input_common/drivers/touch_screen.cpp
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#include "common/param_package.h" 4#include "common/param_package.h"
6#include "input_common/drivers/touch_screen.h" 5#include "input_common/drivers/touch_screen.h"
@@ -15,38 +14,93 @@ constexpr PadIdentifier identifier = {
15 14
16TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) { 15TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
17 PreSetController(identifier); 16 PreSetController(identifier);
17 ReleaseAllTouch();
18} 18}
19 19
20void TouchScreen::TouchMoved(float x, float y, std::size_t finger) { 20void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) {
21 if (finger >= 16) { 21 const auto index = GetIndexFromFingerId(finger_id);
22 if (!index) {
23 // Touch doesn't exist handle it as a new one
24 TouchPressed(x, y, finger_id);
22 return; 25 return;
23 } 26 }
24 TouchPressed(x, y, finger); 27 const auto i = index.value();
28 fingers[i].is_active = true;
29 SetButton(identifier, static_cast<int>(i), true);
30 SetAxis(identifier, static_cast<int>(i * 2), x);
31 SetAxis(identifier, static_cast<int>(i * 2 + 1), y);
25} 32}
26 33
27void TouchScreen::TouchPressed(float x, float y, std::size_t finger) { 34void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) {
28 if (finger >= 16) { 35 if (GetIndexFromFingerId(finger_id)) {
36 // Touch already exist. Just update the data
37 TouchMoved(x, y, finger_id);
29 return; 38 return;
30 } 39 }
31 SetButton(identifier, static_cast<int>(finger), true); 40 const auto index = GetNextFreeIndex();
32 SetAxis(identifier, static_cast<int>(finger * 2), x); 41 if (!index) {
33 SetAxis(identifier, static_cast<int>(finger * 2 + 1), y); 42 // No free entries. Ignore input
43 return;
44 }
45 const auto i = index.value();
46 fingers[i].is_enabled = true;
47 fingers[i].finger_id = finger_id;
48 TouchMoved(x, y, finger_id);
34} 49}
35 50
36void TouchScreen::TouchReleased(std::size_t finger) { 51void TouchScreen::TouchReleased(std::size_t finger_id) {
37 if (finger >= 16) { 52 const auto index = GetIndexFromFingerId(finger_id);
53 if (!index) {
38 return; 54 return;
39 } 55 }
40 SetButton(identifier, static_cast<int>(finger), false); 56 const auto i = index.value();
41 SetAxis(identifier, static_cast<int>(finger * 2), 0.0f); 57 fingers[i].is_enabled = false;
42 SetAxis(identifier, static_cast<int>(finger * 2 + 1), 0.0f); 58 SetButton(identifier, static_cast<int>(i), false);
59 SetAxis(identifier, static_cast<int>(i * 2), 0.0f);
60 SetAxis(identifier, static_cast<int>(i * 2 + 1), 0.0f);
61}
62
63std::optional<std::size_t> TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const {
64 for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) {
65 const auto& finger = fingers[index];
66 if (!finger.is_enabled) {
67 continue;
68 }
69 if (finger.finger_id == finger_id) {
70 return index;
71 }
72 }
73 return std::nullopt;
74}
75
76std::optional<std::size_t> TouchScreen::GetNextFreeIndex() const {
77 for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) {
78 if (!fingers[index].is_enabled) {
79 return index;
80 }
81 }
82 return std::nullopt;
83}
84
85void TouchScreen::ClearActiveFlag() {
86 for (auto& finger : fingers) {
87 finger.is_active = false;
88 }
89}
90
91void TouchScreen::ReleaseInactiveTouch() {
92 for (const auto& finger : fingers) {
93 if (!finger.is_active) {
94 TouchReleased(finger.finger_id);
95 }
96 }
43} 97}
44 98
45void TouchScreen::ReleaseAllTouch() { 99void TouchScreen::ReleaseAllTouch() {
46 for (int index = 0; index < 16; ++index) { 100 for (const auto& finger : fingers) {
47 SetButton(identifier, index, false); 101 if (finger.is_enabled) {
48 SetAxis(identifier, index * 2, 0.0f); 102 TouchReleased(finger.finger_id);
49 SetAxis(identifier, index * 2 + 1, 0.0f); 103 }
50 } 104 }
51} 105}
52 106
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h
index bf395c40b..f46036ffd 100644
--- a/src/input_common/drivers/touch_screen.h
+++ b/src/input_common/drivers/touch_screen.h
@@ -1,44 +1,67 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#pragma once 4#pragma once
6 5
6#include <optional>
7
7#include "input_common/input_engine.h" 8#include "input_common/input_engine.h"
8 9
9namespace InputCommon { 10namespace InputCommon {
10 11
11/** 12/**
12 * A button device factory representing a keyboard. It receives keyboard events and forward them 13 * A touch device factory representing a touch screen. It receives touch events and forward them
13 * to all button devices it created. 14 * to all touch devices it created.
14 */ 15 */
15class TouchScreen final : public InputEngine { 16class TouchScreen final : public InputEngine {
16public: 17public:
17 explicit TouchScreen(std::string input_engine_); 18 explicit TouchScreen(std::string input_engine_);
18 19
19 /** 20 /**
20 * Signals that mouse has moved. 21 * Signals that touch has moved and marks this touch point as active
21 * @param x the x-coordinate of the cursor 22 * @param x new horizontal position
22 * @param y the y-coordinate of the cursor 23 * @param y new vertical position
23 * @param center_x the x-coordinate of the middle of the screen 24 * @param finger_id of the touch point to be updated
24 * @param center_y the y-coordinate of the middle of the screen
25 */ 25 */
26 void TouchMoved(float x, float y, std::size_t finger); 26 void TouchMoved(float x, float y, std::size_t finger_id);
27 27
28 /** 28 /**
29 * Sets the status of all buttons bound with the key to pressed 29 * Signals and creates a new touch point with this finger id
30 * @param key_code the code of the key to press 30 * @param x starting horizontal position
31 * @param y starting vertical position
32 * @param finger_id to be assigned to the new touch point
31 */ 33 */
32 void TouchPressed(float x, float y, std::size_t finger); 34 void TouchPressed(float x, float y, std::size_t finger_id);
33 35
34 /** 36 /**
35 * Sets the status of all buttons bound with the key to released 37 * Signals and resets the touch point related to the this finger id
36 * @param key_code the code of the key to release 38 * @param finger_id to be released
37 */ 39 */
38 void TouchReleased(std::size_t finger); 40 void TouchReleased(std::size_t finger_id);
41
42 /// Resets the active flag for each touch point
43 void ClearActiveFlag();
44
45 /// Releases all touch that haven't been marked as active
46 void ReleaseInactiveTouch();
39 47
40 /// Resets all inputs to their initial value 48 /// Resets all inputs to their initial value
41 void ReleaseAllTouch(); 49 void ReleaseAllTouch();
50
51private:
52 static constexpr std::size_t MAX_FINGER_COUNT = 16;
53
54 struct TouchStatus {
55 std::size_t finger_id{};
56 bool is_enabled{};
57 bool is_active{};
58 };
59
60 std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const;
61
62 std::optional<std::size_t> GetNextFreeIndex() const;
63
64 std::array<TouchStatus, MAX_FINGER_COUNT> fingers{};
42}; 65};
43 66
44} // namespace InputCommon 67} // namespace InputCommon
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 64162f431..808b21069 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -1,6 +1,5 @@
1// Copyright 2018 Citra Emulator Project 1// SPDX-FileCopyrightText: 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <random> 4#include <random>
6#include <boost/asio.hpp> 5#include <boost/asio.hpp>
@@ -192,22 +191,22 @@ std::size_t UDPClient::GetClientNumber(std::string_view host, u16 port) const {
192 return MAX_UDP_CLIENTS; 191 return MAX_UDP_CLIENTS;
193} 192}
194 193
195BatteryLevel UDPClient::GetBatteryLevel(Response::Battery battery) const { 194Common::Input::BatteryLevel UDPClient::GetBatteryLevel(Response::Battery battery) const {
196 switch (battery) { 195 switch (battery) {
197 case Response::Battery::Dying: 196 case Response::Battery::Dying:
198 return BatteryLevel::Empty; 197 return Common::Input::BatteryLevel::Empty;
199 case Response::Battery::Low: 198 case Response::Battery::Low:
200 return BatteryLevel::Critical; 199 return Common::Input::BatteryLevel::Critical;
201 case Response::Battery::Medium: 200 case Response::Battery::Medium:
202 return BatteryLevel::Low; 201 return Common::Input::BatteryLevel::Low;
203 case Response::Battery::High: 202 case Response::Battery::High:
204 return BatteryLevel::Medium; 203 return Common::Input::BatteryLevel::Medium;
205 case Response::Battery::Full: 204 case Response::Battery::Full:
206 case Response::Battery::Charged: 205 case Response::Battery::Charged:
207 return BatteryLevel::Full; 206 return Common::Input::BatteryLevel::Full;
208 case Response::Battery::Charging: 207 case Response::Battery::Charging:
209 default: 208 default:
210 return BatteryLevel::Charging; 209 return Common::Input::BatteryLevel::Charging;
211 } 210 }
212} 211}
213 212
@@ -547,6 +546,22 @@ Common::Input::ButtonNames UDPClient::GetUIName(const Common::ParamPackage& para
547 return Common::Input::ButtonNames::Invalid; 546 return Common::Input::ButtonNames::Invalid;
548} 547}
549 548
549bool UDPClient::IsStickInverted(const Common::ParamPackage& params) {
550 if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
551 return false;
552 }
553
554 const auto x_axis = static_cast<PadAxes>(params.Get("axis_x", 0));
555 const auto y_axis = static_cast<PadAxes>(params.Get("axis_y", 0));
556 if (x_axis != PadAxes::LeftStickY && x_axis != PadAxes::RightStickY) {
557 return false;
558 }
559 if (y_axis != PadAxes::LeftStickX && y_axis != PadAxes::RightStickX) {
560 return false;
561 }
562 return true;
563}
564
550void TestCommunication(const std::string& host, u16 port, 565void TestCommunication(const std::string& host, u16 port,
551 const std::function<void()>& success_callback, 566 const std::function<void()>& success_callback,
552 const std::function<void()>& failure_callback) { 567 const std::function<void()>& failure_callback) {
diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h
index 76e32bd04..cea9f579a 100644
--- a/src/input_common/drivers/udp_client.h
+++ b/src/input_common/drivers/udp_client.h
@@ -1,6 +1,5 @@
1// Copyright 2018 Citra Emulator Project 1// SPDX-FileCopyrightText: 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
@@ -64,6 +63,8 @@ public:
64 MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; 63 MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override;
65 Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; 64 Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
66 65
66 bool IsStickInverted(const Common::ParamPackage& params) override;
67
67private: 68private:
68 enum class PadButton { 69 enum class PadButton {
69 Undefined = 0x0000, 70 Undefined = 0x0000,
@@ -141,7 +142,7 @@ private:
141 std::size_t GetClientNumber(std::string_view host, u16 port) const; 142 std::size_t GetClientNumber(std::string_view host, u16 port) const;
142 143
143 // Translates UDP battery level to input engine battery level 144 // Translates UDP battery level to input engine battery level
144 BatteryLevel GetBatteryLevel(Response::Battery battery) const; 145 Common::Input::BatteryLevel GetBatteryLevel(Response::Battery battery) const;
145 146
146 void OnVersion(Response::Version); 147 void OnVersion(Response::Version);
147 void OnPortInfo(Response::PortInfo); 148 void OnPortInfo(Response::PortInfo);
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp
new file mode 100644
index 000000000..0cd5129da
--- /dev/null
+++ b/src/input_common/drivers/virtual_amiibo.cpp
@@ -0,0 +1,101 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include <cstring>
5#include <fmt/format.h>
6
7#include "common/fs/file.h"
8#include "common/fs/fs.h"
9#include "common/fs/path_util.h"
10#include "common/logging/log.h"
11#include "common/settings.h"
12#include "input_common/drivers/virtual_amiibo.h"
13
14namespace InputCommon {
15constexpr PadIdentifier identifier = {
16 .guid = Common::UUID{},
17 .port = 0,
18 .pad = 0,
19};
20
21VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(input_engine_)) {}
22
23VirtualAmiibo::~VirtualAmiibo() = default;
24
25Common::Input::PollingError VirtualAmiibo::SetPollingMode(
26 [[maybe_unused]] const PadIdentifier& identifier_,
27 const Common::Input::PollingMode polling_mode_) {
28 polling_mode = polling_mode_;
29
30 if (polling_mode == Common::Input::PollingMode::NFC) {
31 if (state == State::Initialized) {
32 state = State::WaitingForAmiibo;
33 }
34 } else {
35 if (state == State::AmiiboIsOpen) {
36 CloseAmiibo();
37 }
38 }
39
40 return Common::Input::PollingError::None;
41}
42
43Common::Input::NfcState VirtualAmiibo::SupportsNfc(
44 [[maybe_unused]] const PadIdentifier& identifier_) const {
45 return Common::Input::NfcState::Success;
46}
47
48Common::Input::NfcState VirtualAmiibo::WriteNfcData(
49 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) {
50 const Common::FS::IOFile amiibo_file{file_path, Common::FS::FileAccessMode::ReadWrite,
51 Common::FS::FileType::BinaryFile};
52
53 if (!amiibo_file.IsOpen()) {
54 LOG_ERROR(Core, "Amiibo is already on use");
55 return Common::Input::NfcState::WriteFailed;
56 }
57
58 if (!amiibo_file.Write(data)) {
59 LOG_ERROR(Service_NFP, "Error writting to file");
60 return Common::Input::NfcState::WriteFailed;
61 }
62
63 return Common::Input::NfcState::Success;
64}
65
66VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
67 return state;
68}
69
70VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) {
71 const Common::FS::IOFile amiibo_file{filename, Common::FS::FileAccessMode::Read,
72 Common::FS::FileType::BinaryFile};
73
74 if (state != State::WaitingForAmiibo) {
75 return Info::WrongDeviceState;
76 }
77
78 if (!amiibo_file.IsOpen()) {
79 return Info::UnableToLoad;
80 }
81
82 amiibo_data.resize(amiibo_size);
83
84 if (amiibo_file.Read(amiibo_data) < amiibo_size_without_password) {
85 return Info::NotAnAmiibo;
86 }
87
88 file_path = filename;
89 state = State::AmiiboIsOpen;
90 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data});
91 return Info::Success;
92}
93
94VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
95 state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo
96 : State::Initialized;
97 SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}});
98 return Info::Success;
99}
100
101} // namespace InputCommon
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h
new file mode 100644
index 000000000..9eac07544
--- /dev/null
+++ b/src/input_common/drivers/virtual_amiibo.h
@@ -0,0 +1,61 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <string>
8#include <vector>
9
10#include "common/common_types.h"
11#include "input_common/input_engine.h"
12
13namespace Common::FS {
14class IOFile;
15}
16
17namespace InputCommon {
18
19class VirtualAmiibo final : public InputEngine {
20public:
21 enum class State {
22 Initialized,
23 WaitingForAmiibo,
24 AmiiboIsOpen,
25 };
26
27 enum class Info {
28 Success,
29 UnableToLoad,
30 NotAnAmiibo,
31 WrongDeviceState,
32 Unknown,
33 };
34
35 explicit VirtualAmiibo(std::string input_engine_);
36 ~VirtualAmiibo() override;
37
38 // Sets polling mode to a controller
39 Common::Input::PollingError SetPollingMode(
40 const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override;
41
42 Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override;
43
44 Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_,
45 const std::vector<u8>& data) override;
46
47 State GetCurrentState() const;
48
49 Info LoadAmiibo(const std::string& amiibo_file);
50 Info CloseAmiibo();
51
52private:
53 static constexpr std::size_t amiibo_size = 0x21C;
54 static constexpr std::size_t amiibo_size_without_password = amiibo_size - 0x8;
55
56 std::string file_path{};
57 State state{State::Initialized};
58 std::vector<u8> amiibo_data;
59 Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive};
60};
61} // namespace InputCommon
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 31e6f62ab..536d413a5 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -1,6 +1,5 @@
1// Copyright 2017 Citra Emulator Project 1// SPDX-FileCopyrightText: 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <chrono> 4#include <chrono>
6#include <cmath> 5#include <cmath>
diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h
index 437ace4f7..e8d865743 100644
--- a/src/input_common/helpers/stick_from_buttons.h
+++ b/src/input_common/helpers/stick_from_buttons.h
@@ -1,6 +1,5 @@
1// Copyright 2017 Citra Emulator Project 1// SPDX-FileCopyrightText: 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index f1b57d03a..da4a3dca5 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -1,6 +1,5 @@
1// Copyright 2020 Citra Emulator Project 1// SPDX-FileCopyrightText: 2020 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <algorithm> 4#include <algorithm>
6#include "common/settings.h" 5#include "common/settings.h"
diff --git a/src/input_common/helpers/touch_from_buttons.h b/src/input_common/helpers/touch_from_buttons.h
index 628f18215..c6cb3ab3c 100644
--- a/src/input_common/helpers/touch_from_buttons.h
+++ b/src/input_common/helpers/touch_from_buttons.h
@@ -1,6 +1,5 @@
1// Copyright 2020 Citra Emulator Project 1// SPDX-FileCopyrightText: 2020 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
diff --git a/src/input_common/helpers/udp_protocol.cpp b/src/input_common/helpers/udp_protocol.cpp
index cdeab7e11..994380d21 100644
--- a/src/input_common/helpers/udp_protocol.cpp
+++ b/src/input_common/helpers/udp_protocol.cpp
@@ -1,6 +1,5 @@
1// Copyright 2018 Citra Emulator Project 1// SPDX-FileCopyrightText: 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <cstddef> 4#include <cstddef>
6#include <cstring> 5#include <cstring>
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index 2d5d54ddb..d9643ffe0 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -1,6 +1,5 @@
1// Copyright 2018 Citra Emulator Project 1// SPDX-FileCopyrightText: 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
@@ -8,9 +7,17 @@
8#include <optional> 7#include <optional>
9#include <type_traits> 8#include <type_traits>
10 9
10#ifdef _MSC_VER
11#pragma warning(push)
12#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used
13#endif
14
11#include <boost/crc.hpp> 15#include <boost/crc.hpp>
12 16
13#include "common/bit_field.h" 17#ifdef _MSC_VER
18#pragma warning(pop)
19#endif
20
14#include "common/swap.h" 21#include "common/swap.h"
15 22
16namespace InputCommon::CemuhookUDP { 23namespace InputCommon::CemuhookUDP {
@@ -77,7 +84,7 @@ enum RegisterFlags : u8 {
77struct Version {}; 84struct Version {};
78/** 85/**
79 * Requests the server to send information about what controllers are plugged into the ports 86 * Requests the server to send information about what controllers are plugged into the ports
80 * In citra's case, we only have one controller, so for simplicity's sake, we can just send a 87 * In yuzu's case, we only have one controller, so for simplicity's sake, we can just send a
81 * request explicitly for the first controller port and leave it at that. In the future it would be 88 * request explicitly for the first controller port and leave it at that. In the future it would be
82 * nice to make this configurable 89 * nice to make this configurable
83 */ 90 */
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 65ae1b848..61cfd0911 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -1,45 +1,43 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#include "common/logging/log.h" 4#include "common/logging/log.h"
6#include "common/param_package.h"
7#include "input_common/input_engine.h" 5#include "input_common/input_engine.h"
8 6
9namespace InputCommon { 7namespace InputCommon {
10 8
11void InputEngine::PreSetController(const PadIdentifier& identifier) { 9void InputEngine::PreSetController(const PadIdentifier& identifier) {
12 std::lock_guard lock{mutex}; 10 std::scoped_lock lock{mutex};
13 controller_list.try_emplace(identifier); 11 controller_list.try_emplace(identifier);
14} 12}
15 13
16void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) { 14void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) {
17 std::lock_guard lock{mutex}; 15 std::scoped_lock lock{mutex};
18 ControllerData& controller = controller_list.at(identifier); 16 ControllerData& controller = controller_list.at(identifier);
19 controller.buttons.try_emplace(button, false); 17 controller.buttons.try_emplace(button, false);
20} 18}
21 19
22void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) { 20void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) {
23 std::lock_guard lock{mutex}; 21 std::scoped_lock lock{mutex};
24 ControllerData& controller = controller_list.at(identifier); 22 ControllerData& controller = controller_list.at(identifier);
25 controller.hat_buttons.try_emplace(button, u8{0}); 23 controller.hat_buttons.try_emplace(button, u8{0});
26} 24}
27 25
28void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) { 26void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) {
29 std::lock_guard lock{mutex}; 27 std::scoped_lock lock{mutex};
30 ControllerData& controller = controller_list.at(identifier); 28 ControllerData& controller = controller_list.at(identifier);
31 controller.axes.try_emplace(axis, 0.0f); 29 controller.axes.try_emplace(axis, 0.0f);
32} 30}
33 31
34void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) { 32void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) {
35 std::lock_guard lock{mutex}; 33 std::scoped_lock lock{mutex};
36 ControllerData& controller = controller_list.at(identifier); 34 ControllerData& controller = controller_list.at(identifier);
37 controller.motions.try_emplace(motion); 35 controller.motions.try_emplace(motion);
38} 36}
39 37
40void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) { 38void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) {
41 { 39 {
42 std::lock_guard lock{mutex}; 40 std::scoped_lock lock{mutex};
43 ControllerData& controller = controller_list.at(identifier); 41 ControllerData& controller = controller_list.at(identifier);
44 if (!configuring) { 42 if (!configuring) {
45 controller.buttons.insert_or_assign(button, value); 43 controller.buttons.insert_or_assign(button, value);
@@ -50,7 +48,7 @@ void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool va
50 48
51void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) { 49void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) {
52 { 50 {
53 std::lock_guard lock{mutex}; 51 std::scoped_lock lock{mutex};
54 ControllerData& controller = controller_list.at(identifier); 52 ControllerData& controller = controller_list.at(identifier);
55 if (!configuring) { 53 if (!configuring) {
56 controller.hat_buttons.insert_or_assign(button, value); 54 controller.hat_buttons.insert_or_assign(button, value);
@@ -61,7 +59,7 @@ void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 v
61 59
62void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { 60void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) {
63 { 61 {
64 std::lock_guard lock{mutex}; 62 std::scoped_lock lock{mutex};
65 ControllerData& controller = controller_list.at(identifier); 63 ControllerData& controller = controller_list.at(identifier);
66 if (!configuring) { 64 if (!configuring) {
67 controller.axes.insert_or_assign(axis, value); 65 controller.axes.insert_or_assign(axis, value);
@@ -70,9 +68,9 @@ void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value)
70 TriggerOnAxisChange(identifier, axis, value); 68 TriggerOnAxisChange(identifier, axis, value);
71} 69}
72 70
73void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value) { 71void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value) {
74 { 72 {
75 std::lock_guard lock{mutex}; 73 std::scoped_lock lock{mutex};
76 ControllerData& controller = controller_list.at(identifier); 74 ControllerData& controller = controller_list.at(identifier);
77 if (!configuring) { 75 if (!configuring) {
78 controller.battery = value; 76 controller.battery = value;
@@ -83,7 +81,7 @@ void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value
83 81
84void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) { 82void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) {
85 { 83 {
86 std::lock_guard lock{mutex}; 84 std::scoped_lock lock{mutex};
87 ControllerData& controller = controller_list.at(identifier); 85 ControllerData& controller = controller_list.at(identifier);
88 if (!configuring) { 86 if (!configuring) {
89 controller.motions.insert_or_assign(motion, value); 87 controller.motions.insert_or_assign(motion, value);
@@ -92,8 +90,31 @@ void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const B
92 TriggerOnMotionChange(identifier, motion, value); 90 TriggerOnMotionChange(identifier, motion, value);
93} 91}
94 92
93void InputEngine::SetCamera(const PadIdentifier& identifier,
94 const Common::Input::CameraStatus& value) {
95 {
96 std::scoped_lock lock{mutex};
97 ControllerData& controller = controller_list.at(identifier);
98 if (!configuring) {
99 controller.camera = value;
100 }
101 }
102 TriggerOnCameraChange(identifier, value);
103}
104
105void InputEngine::SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value) {
106 {
107 std::scoped_lock lock{mutex};
108 ControllerData& controller = controller_list.at(identifier);
109 if (!configuring) {
110 controller.nfc = value;
111 }
112 }
113 TriggerOnNfcChange(identifier, value);
114}
115
95bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { 116bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const {
96 std::lock_guard lock{mutex}; 117 std::scoped_lock lock{mutex};
97 const auto controller_iter = controller_list.find(identifier); 118 const auto controller_iter = controller_list.find(identifier);
98 if (controller_iter == controller_list.cend()) { 119 if (controller_iter == controller_list.cend()) {
99 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), 120 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
@@ -110,7 +131,7 @@ bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const {
110} 131}
111 132
112bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const { 133bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const {
113 std::lock_guard lock{mutex}; 134 std::scoped_lock lock{mutex};
114 const auto controller_iter = controller_list.find(identifier); 135 const auto controller_iter = controller_list.find(identifier);
115 if (controller_iter == controller_list.cend()) { 136 if (controller_iter == controller_list.cend()) {
116 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), 137 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
@@ -127,7 +148,7 @@ bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 d
127} 148}
128 149
129f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { 150f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const {
130 std::lock_guard lock{mutex}; 151 std::scoped_lock lock{mutex};
131 const auto controller_iter = controller_list.find(identifier); 152 const auto controller_iter = controller_list.find(identifier);
132 if (controller_iter == controller_list.cend()) { 153 if (controller_iter == controller_list.cend()) {
133 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), 154 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
@@ -143,20 +164,20 @@ f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const {
143 return axis_iter->second; 164 return axis_iter->second;
144} 165}
145 166
146BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const { 167Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const {
147 std::lock_guard lock{mutex}; 168 std::scoped_lock lock{mutex};
148 const auto controller_iter = controller_list.find(identifier); 169 const auto controller_iter = controller_list.find(identifier);
149 if (controller_iter == controller_list.cend()) { 170 if (controller_iter == controller_list.cend()) {
150 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), 171 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
151 identifier.pad, identifier.port); 172 identifier.pad, identifier.port);
152 return BatteryLevel::Charging; 173 return Common::Input::BatteryLevel::Charging;
153 } 174 }
154 const ControllerData& controller = controller_iter->second; 175 const ControllerData& controller = controller_iter->second;
155 return controller.battery; 176 return controller.battery;
156} 177}
157 178
158BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const { 179BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const {
159 std::lock_guard lock{mutex}; 180 std::scoped_lock lock{mutex};
160 const auto controller_iter = controller_list.find(identifier); 181 const auto controller_iter = controller_list.find(identifier);
161 if (controller_iter == controller_list.cend()) { 182 if (controller_iter == controller_list.cend()) {
162 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), 183 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
@@ -167,6 +188,30 @@ BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion)
167 return controller.motions.at(motion); 188 return controller.motions.at(motion);
168} 189}
169 190
191Common::Input::CameraStatus InputEngine::GetCamera(const PadIdentifier& identifier) const {
192 std::scoped_lock lock{mutex};
193 const auto controller_iter = controller_list.find(identifier);
194 if (controller_iter == controller_list.cend()) {
195 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
196 identifier.pad, identifier.port);
197 return {};
198 }
199 const ControllerData& controller = controller_iter->second;
200 return controller.camera;
201}
202
203Common::Input::NfcStatus InputEngine::GetNfc(const PadIdentifier& identifier) const {
204 std::scoped_lock lock{mutex};
205 const auto controller_iter = controller_list.find(identifier);
206 if (controller_iter == controller_list.cend()) {
207 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
208 identifier.pad, identifier.port);
209 return {};
210 }
211 const ControllerData& controller = controller_iter->second;
212 return controller.nfc;
213}
214
170void InputEngine::ResetButtonState() { 215void InputEngine::ResetButtonState() {
171 for (const auto& controller : controller_list) { 216 for (const auto& controller : controller_list) {
172 for (const auto& button : controller.second.buttons) { 217 for (const auto& button : controller.second.buttons) {
@@ -187,7 +232,7 @@ void InputEngine::ResetAnalogState() {
187} 232}
188 233
189void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) { 234void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) {
190 std::lock_guard lock{mutex_callback}; 235 std::scoped_lock lock{mutex_callback};
191 for (const auto& poller_pair : callback_list) { 236 for (const auto& poller_pair : callback_list) {
192 const InputIdentifier& poller = poller_pair.second; 237 const InputIdentifier& poller = poller_pair.second;
193 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) { 238 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) {
@@ -215,7 +260,7 @@ void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int but
215} 260}
216 261
217void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) { 262void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) {
218 std::lock_guard lock{mutex_callback}; 263 std::scoped_lock lock{mutex_callback};
219 for (const auto& poller_pair : callback_list) { 264 for (const auto& poller_pair : callback_list) {
220 const InputIdentifier& poller = poller_pair.second; 265 const InputIdentifier& poller = poller_pair.second;
221 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) { 266 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) {
@@ -244,7 +289,7 @@ void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int
244} 289}
245 290
246void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) { 291void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) {
247 std::lock_guard lock{mutex_callback}; 292 std::scoped_lock lock{mutex_callback};
248 for (const auto& poller_pair : callback_list) { 293 for (const auto& poller_pair : callback_list) {
249 const InputIdentifier& poller = poller_pair.second; 294 const InputIdentifier& poller = poller_pair.second;
250 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) { 295 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) {
@@ -270,8 +315,8 @@ void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis,
270} 315}
271 316
272void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, 317void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
273 [[maybe_unused]] BatteryLevel value) { 318 [[maybe_unused]] Common::Input::BatteryLevel value) {
274 std::lock_guard lock{mutex_callback}; 319 std::scoped_lock lock{mutex_callback};
275 for (const auto& poller_pair : callback_list) { 320 for (const auto& poller_pair : callback_list) {
276 const InputIdentifier& poller = poller_pair.second; 321 const InputIdentifier& poller = poller_pair.second;
277 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) { 322 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) {
@@ -285,7 +330,7 @@ void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
285 330
286void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion, 331void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
287 const BasicMotion& value) { 332 const BasicMotion& value) {
288 std::lock_guard lock{mutex_callback}; 333 std::scoped_lock lock{mutex_callback};
289 for (const auto& poller_pair : callback_list) { 334 for (const auto& poller_pair : callback_list) {
290 const InputIdentifier& poller = poller_pair.second; 335 const InputIdentifier& poller = poller_pair.second;
291 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) { 336 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) {
@@ -319,6 +364,34 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot
319 }); 364 });
320} 365}
321 366
367void InputEngine::TriggerOnCameraChange(const PadIdentifier& identifier,
368 [[maybe_unused]] const Common::Input::CameraStatus& value) {
369 std::scoped_lock lock{mutex_callback};
370 for (const auto& poller_pair : callback_list) {
371 const InputIdentifier& poller = poller_pair.second;
372 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Camera, 0)) {
373 continue;
374 }
375 if (poller.callback.on_change) {
376 poller.callback.on_change();
377 }
378 }
379}
380
381void InputEngine::TriggerOnNfcChange(const PadIdentifier& identifier,
382 [[maybe_unused]] const Common::Input::NfcStatus& value) {
383 std::scoped_lock lock{mutex_callback};
384 for (const auto& poller_pair : callback_list) {
385 const InputIdentifier& poller = poller_pair.second;
386 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Nfc, 0)) {
387 continue;
388 }
389 if (poller.callback.on_change) {
390 poller.callback.on_change();
391 }
392 }
393}
394
322bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, 395bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier,
323 const PadIdentifier& identifier, EngineInputType type, 396 const PadIdentifier& identifier, EngineInputType type,
324 int index) const { 397 int index) const {
@@ -347,18 +420,18 @@ const std::string& InputEngine::GetEngineName() const {
347} 420}
348 421
349int InputEngine::SetCallback(InputIdentifier input_identifier) { 422int InputEngine::SetCallback(InputIdentifier input_identifier) {
350 std::lock_guard lock{mutex_callback}; 423 std::scoped_lock lock{mutex_callback};
351 callback_list.insert_or_assign(last_callback_key, std::move(input_identifier)); 424 callback_list.insert_or_assign(last_callback_key, std::move(input_identifier));
352 return last_callback_key++; 425 return last_callback_key++;
353} 426}
354 427
355void InputEngine::SetMappingCallback(MappingCallback callback) { 428void InputEngine::SetMappingCallback(MappingCallback callback) {
356 std::lock_guard lock{mutex_callback}; 429 std::scoped_lock lock{mutex_callback};
357 mapping_callback = std::move(callback); 430 mapping_callback = std::move(callback);
358} 431}
359 432
360void InputEngine::DeleteCallback(int key) { 433void InputEngine::DeleteCallback(int key) {
361 std::lock_guard lock{mutex_callback}; 434 std::scoped_lock lock{mutex_callback};
362 const auto& iterator = callback_list.find(key); 435 const auto& iterator = callback_list.find(key);
363 if (iterator == callback_list.end()) { 436 if (iterator == callback_list.end()) {
364 LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); 437 LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index c6c027aef..cfbdb26bd 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#pragma once 4#pragma once
6 5
@@ -34,24 +33,16 @@ struct BasicMotion {
34 u64 delta_timestamp{}; 33 u64 delta_timestamp{};
35}; 34};
36 35
37// Stages of a battery charge
38enum class BatteryLevel {
39 Empty,
40 Critical,
41 Low,
42 Medium,
43 Full,
44 Charging,
45};
46
47// Types of input that are stored in the engine 36// Types of input that are stored in the engine
48enum class EngineInputType { 37enum class EngineInputType {
49 None, 38 None,
39 Analog,
40 Battery,
50 Button, 41 Button,
42 Camera,
51 HatButton, 43 HatButton,
52 Analog,
53 Motion, 44 Motion,
54 Battery, 45 Nfc,
55}; 46};
56 47
57namespace std { 48namespace std {
@@ -126,10 +117,29 @@ public:
126 // Sets polling mode to a controller 117 // Sets polling mode to a controller
127 virtual Common::Input::PollingError SetPollingMode( 118 virtual Common::Input::PollingError SetPollingMode(
128 [[maybe_unused]] const PadIdentifier& identifier, 119 [[maybe_unused]] const PadIdentifier& identifier,
129 [[maybe_unused]] const Common::Input::PollingMode vibration) { 120 [[maybe_unused]] const Common::Input::PollingMode polling_mode) {
130 return Common::Input::PollingError::NotSupported; 121 return Common::Input::PollingError::NotSupported;
131 } 122 }
132 123
124 // Sets camera format to a controller
125 virtual Common::Input::CameraError SetCameraFormat(
126 [[maybe_unused]] const PadIdentifier& identifier,
127 [[maybe_unused]] Common::Input::CameraFormat camera_format) {
128 return Common::Input::CameraError::NotSupported;
129 }
130
131 // Request nfc data from a controller
132 virtual Common::Input::NfcState SupportsNfc(
133 [[maybe_unused]] const PadIdentifier& identifier) const {
134 return Common::Input::NfcState::NotSupported;
135 }
136
137 // Writes data to an nfc tag
138 virtual Common::Input::NfcState WriteNfcData([[maybe_unused]] const PadIdentifier& identifier,
139 [[maybe_unused]] const std::vector<u8>& data) {
140 return Common::Input::NfcState::NotSupported;
141 }
142
133 // Returns the engine name 143 // Returns the engine name
134 [[nodiscard]] const std::string& GetEngineName() const; 144 [[nodiscard]] const std::string& GetEngineName() const;
135 145
@@ -167,6 +177,11 @@ public:
167 return 0; 177 return 0;
168 } 178 }
169 179
180 /// Returns true if axis of a stick aren't mapped in the correct direction
181 virtual bool IsStickInverted([[maybe_unused]] const Common::ParamPackage& params) {
182 return false;
183 }
184
170 void PreSetController(const PadIdentifier& identifier); 185 void PreSetController(const PadIdentifier& identifier);
171 void PreSetButton(const PadIdentifier& identifier, int button); 186 void PreSetButton(const PadIdentifier& identifier, int button);
172 void PreSetHatButton(const PadIdentifier& identifier, int button); 187 void PreSetHatButton(const PadIdentifier& identifier, int button);
@@ -178,8 +193,10 @@ public:
178 bool GetButton(const PadIdentifier& identifier, int button) const; 193 bool GetButton(const PadIdentifier& identifier, int button) const;
179 bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const; 194 bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const;
180 f32 GetAxis(const PadIdentifier& identifier, int axis) const; 195 f32 GetAxis(const PadIdentifier& identifier, int axis) const;
181 BatteryLevel GetBattery(const PadIdentifier& identifier) const; 196 Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const;
182 BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; 197 BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const;
198 Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const;
199 Common::Input::NfcStatus GetNfc(const PadIdentifier& identifier) const;
183 200
184 int SetCallback(InputIdentifier input_identifier); 201 int SetCallback(InputIdentifier input_identifier);
185 void SetMappingCallback(MappingCallback callback); 202 void SetMappingCallback(MappingCallback callback);
@@ -189,8 +206,10 @@ protected:
189 void SetButton(const PadIdentifier& identifier, int button, bool value); 206 void SetButton(const PadIdentifier& identifier, int button, bool value);
190 void SetHatButton(const PadIdentifier& identifier, int button, u8 value); 207 void SetHatButton(const PadIdentifier& identifier, int button, u8 value);
191 void SetAxis(const PadIdentifier& identifier, int axis, f32 value); 208 void SetAxis(const PadIdentifier& identifier, int axis, f32 value);
192 void SetBattery(const PadIdentifier& identifier, BatteryLevel value); 209 void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value);
193 void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); 210 void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value);
211 void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value);
212 void SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value);
194 213
195 virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { 214 virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const {
196 return "Unknown"; 215 return "Unknown";
@@ -202,15 +221,20 @@ private:
202 std::unordered_map<int, u8> hat_buttons; 221 std::unordered_map<int, u8> hat_buttons;
203 std::unordered_map<int, float> axes; 222 std::unordered_map<int, float> axes;
204 std::unordered_map<int, BasicMotion> motions; 223 std::unordered_map<int, BasicMotion> motions;
205 BatteryLevel battery{}; 224 Common::Input::BatteryLevel battery{};
225 Common::Input::CameraStatus camera{};
226 Common::Input::NfcStatus nfc{};
206 }; 227 };
207 228
208 void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); 229 void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value);
209 void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value); 230 void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value);
210 void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value); 231 void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value);
211 void TriggerOnBatteryChange(const PadIdentifier& identifier, BatteryLevel value); 232 void TriggerOnBatteryChange(const PadIdentifier& identifier, Common::Input::BatteryLevel value);
212 void TriggerOnMotionChange(const PadIdentifier& identifier, int motion, 233 void TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
213 const BasicMotion& value); 234 const BasicMotion& value);
235 void TriggerOnCameraChange(const PadIdentifier& identifier,
236 const Common::Input::CameraStatus& value);
237 void TriggerOnNfcChange(const PadIdentifier& identifier, const Common::Input::NfcStatus& value);
214 238
215 bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, 239 bool IsInputIdentifierEqual(const InputIdentifier& input_identifier,
216 const PadIdentifier& identifier, EngineInputType type, 240 const PadIdentifier& identifier, EngineInputType type,
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index fb78093b8..0fa4b1ddb 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#include "common/settings.h" 4#include "common/settings.h"
6#include "input_common/input_engine.h" 5#include "input_common/input_engine.h"
diff --git a/src/input_common/input_mapping.h b/src/input_common/input_mapping.h
index e0dfbc7ad..79bd083e0 100644
--- a/src/input_common/input_mapping.h
+++ b/src/input_common/input_mapping.h
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#pragma once 4#pragma once
6 5
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 7f3c08597..75705b67e 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#include "common/common_types.h" 4#include "common/common_types.h"
6#include "common/input.h" 5#include "common/input.h"
@@ -470,7 +469,7 @@ public:
470 } 469 }
471 470
472 Common::Input::BatteryStatus GetStatus() const { 471 Common::Input::BatteryStatus GetStatus() const {
473 return static_cast<Common::Input::BatteryLevel>(input_engine->GetBattery(identifier)); 472 return input_engine->GetBattery(identifier);
474 } 473 }
475 474
476 void ForceUpdate() override { 475 void ForceUpdate() override {
@@ -665,6 +664,88 @@ private:
665 InputEngine* input_engine; 664 InputEngine* input_engine;
666}; 665};
667 666
667class InputFromCamera final : public Common::Input::InputDevice {
668public:
669 explicit InputFromCamera(PadIdentifier identifier_, InputEngine* input_engine_)
670 : identifier(identifier_), input_engine(input_engine_) {
671 UpdateCallback engine_callback{[this]() { OnChange(); }};
672 const InputIdentifier input_identifier{
673 .identifier = identifier,
674 .type = EngineInputType::Camera,
675 .index = 0,
676 .callback = engine_callback,
677 };
678 callback_key = input_engine->SetCallback(input_identifier);
679 }
680
681 ~InputFromCamera() override {
682 input_engine->DeleteCallback(callback_key);
683 }
684
685 Common::Input::CameraStatus GetStatus() const {
686 return input_engine->GetCamera(identifier);
687 }
688
689 void ForceUpdate() override {
690 OnChange();
691 }
692
693 void OnChange() {
694 const Common::Input::CallbackStatus status{
695 .type = Common::Input::InputType::IrSensor,
696 .camera_status = GetStatus(),
697 };
698
699 TriggerOnChange(status);
700 }
701
702private:
703 const PadIdentifier identifier;
704 int callback_key;
705 InputEngine* input_engine;
706};
707
708class InputFromNfc final : public Common::Input::InputDevice {
709public:
710 explicit InputFromNfc(PadIdentifier identifier_, InputEngine* input_engine_)
711 : identifier(identifier_), input_engine(input_engine_) {
712 UpdateCallback engine_callback{[this]() { OnChange(); }};
713 const InputIdentifier input_identifier{
714 .identifier = identifier,
715 .type = EngineInputType::Nfc,
716 .index = 0,
717 .callback = engine_callback,
718 };
719 callback_key = input_engine->SetCallback(input_identifier);
720 }
721
722 ~InputFromNfc() override {
723 input_engine->DeleteCallback(callback_key);
724 }
725
726 Common::Input::NfcStatus GetStatus() const {
727 return input_engine->GetNfc(identifier);
728 }
729
730 void ForceUpdate() override {
731 OnChange();
732 }
733
734 void OnChange() {
735 const Common::Input::CallbackStatus status{
736 .type = Common::Input::InputType::Nfc,
737 .nfc_status = GetStatus(),
738 };
739
740 TriggerOnChange(status);
741 }
742
743private:
744 const PadIdentifier identifier;
745 int callback_key;
746 InputEngine* input_engine;
747};
748
668class OutputFromIdentifier final : public Common::Input::OutputDevice { 749class OutputFromIdentifier final : public Common::Input::OutputDevice {
669public: 750public:
670 explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) 751 explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_)
@@ -683,6 +764,18 @@ public:
683 return input_engine->SetPollingMode(identifier, polling_mode); 764 return input_engine->SetPollingMode(identifier, polling_mode);
684 } 765 }
685 766
767 Common::Input::CameraError SetCameraFormat(Common::Input::CameraFormat camera_format) override {
768 return input_engine->SetCameraFormat(identifier, camera_format);
769 }
770
771 Common::Input::NfcState SupportsNfc() const override {
772 return input_engine->SupportsNfc(identifier);
773 }
774
775 Common::Input::NfcState WriteNfcData(const std::vector<u8>& data) override {
776 return input_engine->WriteNfcData(identifier, data);
777 }
778
686private: 779private:
687 const PadIdentifier identifier; 780 const PadIdentifier identifier;
688 InputEngine* input_engine; 781 InputEngine* input_engine;
@@ -733,7 +826,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
733std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( 826std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(
734 const Common::ParamPackage& params) { 827 const Common::ParamPackage& params) {
735 const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f); 828 const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f);
736 const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); 829 const auto range = std::clamp(params.Get("range", 0.95f), 0.25f, 1.50f);
737 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); 830 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
738 const PadIdentifier identifier = { 831 const PadIdentifier identifier = {
739 .guid = Common::UUID{params.Get("guid", "")}, 832 .guid = Common::UUID{params.Get("guid", "")},
@@ -780,6 +873,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice(
780 .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), 873 .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
781 .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), 874 .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f),
782 .inverted = params.Get("invert", "+") == "-", 875 .inverted = params.Get("invert", "+") == "-",
876 .toggle = static_cast<bool>(params.Get("toggle", false)),
783 }; 877 };
784 input_engine->PreSetController(identifier); 878 input_engine->PreSetController(identifier);
785 input_engine->PreSetAxis(identifier, axis); 879 input_engine->PreSetAxis(identifier, axis);
@@ -921,6 +1015,30 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice(
921 properties_y, properties_z, input_engine.get()); 1015 properties_y, properties_z, input_engine.get());
922} 1016}
923 1017
1018std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateCameraDevice(
1019 const Common::ParamPackage& params) {
1020 const PadIdentifier identifier = {
1021 .guid = Common::UUID{params.Get("guid", "")},
1022 .port = static_cast<std::size_t>(params.Get("port", 0)),
1023 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
1024 };
1025
1026 input_engine->PreSetController(identifier);
1027 return std::make_unique<InputFromCamera>(identifier, input_engine.get());
1028}
1029
1030std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateNfcDevice(
1031 const Common::ParamPackage& params) {
1032 const PadIdentifier identifier = {
1033 .guid = Common::UUID{params.Get("guid", "")},
1034 .port = static_cast<std::size_t>(params.Get("port", 0)),
1035 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
1036 };
1037
1038 input_engine->PreSetController(identifier);
1039 return std::make_unique<InputFromNfc>(identifier, input_engine.get());
1040}
1041
924InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_) 1042InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
925 : input_engine(std::move(input_engine_)) {} 1043 : input_engine(std::move(input_engine_)) {}
926 1044
@@ -929,6 +1047,12 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::Create(
929 if (params.Has("battery")) { 1047 if (params.Has("battery")) {
930 return CreateBatteryDevice(params); 1048 return CreateBatteryDevice(params);
931 } 1049 }
1050 if (params.Has("camera")) {
1051 return CreateCameraDevice(params);
1052 }
1053 if (params.Has("nfc")) {
1054 return CreateNfcDevice(params);
1055 }
932 if (params.Has("button") && params.Has("axis")) { 1056 if (params.Has("button") && params.Has("axis")) {
933 return CreateTriggerDevice(params); 1057 return CreateTriggerDevice(params);
934 } 1058 }
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h
index 8a0977d58..d7db13ce4 100644
--- a/src/input_common/input_poller.h
+++ b/src/input_common/input_poller.h
@@ -1,6 +1,5 @@
1// Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included
4 3
5#pragma once 4#pragma once
6 5
@@ -212,6 +211,27 @@ private:
212 */ 211 */
213 std::unique_ptr<Common::Input::InputDevice> CreateMotionDevice(Common::ParamPackage params); 212 std::unique_ptr<Common::Input::InputDevice> CreateMotionDevice(Common::ParamPackage params);
214 213
214 /**
215 * Creates a camera device from the parameters given.
216 * @param params contains parameters for creating the device:
217 * - "guid": text string for identifying controllers
218 * - "port": port of the connected device
219 * - "pad": slot of the connected controller
220 * @returns a unique input device with the parameters specified
221 */
222 std::unique_ptr<Common::Input::InputDevice> CreateCameraDevice(
223 const Common::ParamPackage& params);
224
225 /**
226 * Creates a nfc device from the parameters given.
227 * @param params contains parameters for creating the device:
228 * - "guid": text string for identifying controllers
229 * - "port": port of the connected device
230 * - "pad": slot of the connected controller
231 * @returns a unique input device with the parameters specified
232 */
233 std::unique_ptr<Common::Input::InputDevice> CreateNfcDevice(const Common::ParamPackage& params);
234
215 std::shared_ptr<InputEngine> input_engine; 235 std::shared_ptr<InputEngine> input_engine;
216}; 236};
217} // namespace InputCommon 237} // namespace InputCommon
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index a4d7ed645..b2064ef95 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -1,17 +1,17 @@
1// Copyright 2017 Citra Emulator Project 1// SPDX-FileCopyrightText: 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#include <memory> 4#include <memory>
6#include <thread>
7#include "common/input.h" 5#include "common/input.h"
8#include "common/param_package.h" 6#include "common/param_package.h"
7#include "input_common/drivers/camera.h"
9#include "input_common/drivers/gc_adapter.h" 8#include "input_common/drivers/gc_adapter.h"
10#include "input_common/drivers/keyboard.h" 9#include "input_common/drivers/keyboard.h"
11#include "input_common/drivers/mouse.h" 10#include "input_common/drivers/mouse.h"
12#include "input_common/drivers/tas_input.h" 11#include "input_common/drivers/tas_input.h"
13#include "input_common/drivers/touch_screen.h" 12#include "input_common/drivers/touch_screen.h"
14#include "input_common/drivers/udp_client.h" 13#include "input_common/drivers/udp_client.h"
14#include "input_common/drivers/virtual_amiibo.h"
15#include "input_common/helpers/stick_from_buttons.h" 15#include "input_common/helpers/stick_from_buttons.h"
16#include "input_common/helpers/touch_from_buttons.h" 16#include "input_common/helpers/touch_from_buttons.h"
17#include "input_common/input_engine.h" 17#include "input_common/input_engine.h"
@@ -79,6 +79,24 @@ struct InputSubsystem::Impl {
79 Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(), 79 Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(),
80 tas_output_factory); 80 tas_output_factory);
81 81
82 camera = std::make_shared<Camera>("camera");
83 camera->SetMappingCallback(mapping_callback);
84 camera_input_factory = std::make_shared<InputFactory>(camera);
85 camera_output_factory = std::make_shared<OutputFactory>(camera);
86 Common::Input::RegisterFactory<Common::Input::InputDevice>(camera->GetEngineName(),
87 camera_input_factory);
88 Common::Input::RegisterFactory<Common::Input::OutputDevice>(camera->GetEngineName(),
89 camera_output_factory);
90
91 virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo");
92 virtual_amiibo->SetMappingCallback(mapping_callback);
93 virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo);
94 virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo);
95 Common::Input::RegisterFactory<Common::Input::InputDevice>(virtual_amiibo->GetEngineName(),
96 virtual_amiibo_input_factory);
97 Common::Input::RegisterFactory<Common::Input::OutputDevice>(virtual_amiibo->GetEngineName(),
98 virtual_amiibo_output_factory);
99
82#ifdef HAVE_SDL2 100#ifdef HAVE_SDL2
83 sdl = std::make_shared<SDLDriver>("sdl"); 101 sdl = std::make_shared<SDLDriver>("sdl");
84 sdl->SetMappingCallback(mapping_callback); 102 sdl->SetMappingCallback(mapping_callback);
@@ -242,6 +260,28 @@ struct InputSubsystem::Impl {
242 return Common::Input::ButtonNames::Invalid; 260 return Common::Input::ButtonNames::Invalid;
243 } 261 }
244 262
263 bool IsStickInverted(const Common::ParamPackage& params) {
264 const std::string engine = params.Get("engine", "");
265 if (engine == mouse->GetEngineName()) {
266 return mouse->IsStickInverted(params);
267 }
268 if (engine == gcadapter->GetEngineName()) {
269 return gcadapter->IsStickInverted(params);
270 }
271 if (engine == udp_client->GetEngineName()) {
272 return udp_client->IsStickInverted(params);
273 }
274 if (engine == tas_input->GetEngineName()) {
275 return tas_input->IsStickInverted(params);
276 }
277#ifdef HAVE_SDL2
278 if (engine == sdl->GetEngineName()) {
279 return sdl->IsStickInverted(params);
280 }
281#endif
282 return false;
283 }
284
245 bool IsController(const Common::ParamPackage& params) { 285 bool IsController(const Common::ParamPackage& params) {
246 const std::string engine = params.Get("engine", ""); 286 const std::string engine = params.Get("engine", "");
247 if (engine == mouse->GetEngineName()) { 287 if (engine == mouse->GetEngineName()) {
@@ -296,6 +336,8 @@ struct InputSubsystem::Impl {
296 std::shared_ptr<TouchScreen> touch_screen; 336 std::shared_ptr<TouchScreen> touch_screen;
297 std::shared_ptr<TasInput::Tas> tas_input; 337 std::shared_ptr<TasInput::Tas> tas_input;
298 std::shared_ptr<CemuhookUDP::UDPClient> udp_client; 338 std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
339 std::shared_ptr<Camera> camera;
340 std::shared_ptr<VirtualAmiibo> virtual_amiibo;
299 341
300 std::shared_ptr<InputFactory> keyboard_factory; 342 std::shared_ptr<InputFactory> keyboard_factory;
301 std::shared_ptr<InputFactory> mouse_factory; 343 std::shared_ptr<InputFactory> mouse_factory;
@@ -303,12 +345,16 @@ struct InputSubsystem::Impl {
303 std::shared_ptr<InputFactory> touch_screen_factory; 345 std::shared_ptr<InputFactory> touch_screen_factory;
304 std::shared_ptr<InputFactory> udp_client_input_factory; 346 std::shared_ptr<InputFactory> udp_client_input_factory;
305 std::shared_ptr<InputFactory> tas_input_factory; 347 std::shared_ptr<InputFactory> tas_input_factory;
348 std::shared_ptr<InputFactory> camera_input_factory;
349 std::shared_ptr<InputFactory> virtual_amiibo_input_factory;
306 350
307 std::shared_ptr<OutputFactory> keyboard_output_factory; 351 std::shared_ptr<OutputFactory> keyboard_output_factory;
308 std::shared_ptr<OutputFactory> mouse_output_factory; 352 std::shared_ptr<OutputFactory> mouse_output_factory;
309 std::shared_ptr<OutputFactory> gcadapter_output_factory; 353 std::shared_ptr<OutputFactory> gcadapter_output_factory;
310 std::shared_ptr<OutputFactory> udp_client_output_factory; 354 std::shared_ptr<OutputFactory> udp_client_output_factory;
311 std::shared_ptr<OutputFactory> tas_output_factory; 355 std::shared_ptr<OutputFactory> tas_output_factory;
356 std::shared_ptr<OutputFactory> camera_output_factory;
357 std::shared_ptr<OutputFactory> virtual_amiibo_output_factory;
312 358
313#ifdef HAVE_SDL2 359#ifdef HAVE_SDL2
314 std::shared_ptr<SDLDriver> sdl; 360 std::shared_ptr<SDLDriver> sdl;
@@ -361,6 +407,22 @@ const TasInput::Tas* InputSubsystem::GetTas() const {
361 return impl->tas_input.get(); 407 return impl->tas_input.get();
362} 408}
363 409
410Camera* InputSubsystem::GetCamera() {
411 return impl->camera.get();
412}
413
414const Camera* InputSubsystem::GetCamera() const {
415 return impl->camera.get();
416}
417
418VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() {
419 return impl->virtual_amiibo.get();
420}
421
422const VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() const {
423 return impl->virtual_amiibo.get();
424}
425
364std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { 426std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
365 return impl->GetInputDevices(); 427 return impl->GetInputDevices();
366} 428}
@@ -385,6 +447,13 @@ bool InputSubsystem::IsController(const Common::ParamPackage& params) const {
385 return impl->IsController(params); 447 return impl->IsController(params);
386} 448}
387 449
450bool InputSubsystem::IsStickInverted(const Common::ParamPackage& params) const {
451 if (params.Has("axis_x") && params.Has("axis_y")) {
452 return impl->IsStickInverted(params);
453 }
454 return false;
455}
456
388void InputSubsystem::ReloadInputDevices() { 457void InputSubsystem::ReloadInputDevices() {
389 impl->udp_client.get()->ReloadSockets(); 458 impl->udp_client.get()->ReloadSockets();
390} 459}
diff --git a/src/input_common/main.h b/src/input_common/main.h
index baf107e0f..ced252383 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -1,6 +1,5 @@
1// Copyright 2017 Citra Emulator Project 1// SPDX-FileCopyrightText: 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// SPDX-License-Identifier: GPL-2.0-or-later
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
@@ -30,9 +29,11 @@ enum Values : int;
30} 29}
31 30
32namespace InputCommon { 31namespace InputCommon {
32class Camera;
33class Keyboard; 33class Keyboard;
34class Mouse; 34class Mouse;
35class TouchScreen; 35class TouchScreen;
36class VirtualAmiibo;
36struct MappingData; 37struct MappingData;
37} // namespace InputCommon 38} // namespace InputCommon
38 39
@@ -92,9 +93,21 @@ public:
92 /// Retrieves the underlying tas input device. 93 /// Retrieves the underlying tas input device.
93 [[nodiscard]] TasInput::Tas* GetTas(); 94 [[nodiscard]] TasInput::Tas* GetTas();
94 95
95 /// Retrieves the underlying tas input device. 96 /// Retrieves the underlying tas input device.
96 [[nodiscard]] const TasInput::Tas* GetTas() const; 97 [[nodiscard]] const TasInput::Tas* GetTas() const;
97 98
99 /// Retrieves the underlying camera input device.
100 [[nodiscard]] Camera* GetCamera();
101
102 /// Retrieves the underlying camera input device.
103 [[nodiscard]] const Camera* GetCamera() const;
104
105 /// Retrieves the underlying virtual amiibo input device.
106 [[nodiscard]] VirtualAmiibo* GetVirtualAmiibo();
107
108 /// Retrieves the underlying virtual amiibo input device.
109 [[nodiscard]] const VirtualAmiibo* GetVirtualAmiibo() const;
110
98 /** 111 /**
99 * Returns all available input devices that this Factory can create a new device with. 112 * Returns all available input devices that this Factory can create a new device with.
100 * Each returned ParamPackage should have a `display` field used for display, a `engine` field 113 * Each returned ParamPackage should have a `display` field used for display, a `engine` field
@@ -119,6 +132,9 @@ public:
119 /// Returns true if device is a controller. 132 /// Returns true if device is a controller.
120 [[nodiscard]] bool IsController(const Common::ParamPackage& params) const; 133 [[nodiscard]] bool IsController(const Common::ParamPackage& params) const;
121 134
135 /// Returns true if axis of a stick aren't mapped in the correct direction
136 [[nodiscard]] bool IsStickInverted(const Common::ParamPackage& device) const;
137
122 /// Reloads the input devices. 138 /// Reloads the input devices.
123 void ReloadInputDevices(); 139 void ReloadInputDevices();
124 140