summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/CMakeLists.txt2
-rwxr-xr-xsrc/input_common/analog_from_button.cpp2
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp2
-rw-r--r--src/input_common/mouse/mouse_input.cpp2
-rw-r--r--src/input_common/mouse/mouse_poller.cpp2
-rw-r--r--src/input_common/sdl/sdl_impl.cpp28
-rw-r--r--src/input_common/sdl/sdl_impl.h4
-rw-r--r--src/input_common/settings.cpp47
-rw-r--r--src/input_common/settings.h372
-rw-r--r--src/input_common/touch_from_button.cpp2
-rw-r--r--src/input_common/udp/client.cpp149
-rw-r--r--src/input_common/udp/client.h44
12 files changed, 127 insertions, 529 deletions
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 38ab31898..c3cfe7efc 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -9,8 +9,6 @@ add_library(input_common STATIC
9 motion_from_button.h 9 motion_from_button.h
10 motion_input.cpp 10 motion_input.cpp
11 motion_input.h 11 motion_input.h
12 settings.cpp
13 settings.h
14 touch_from_button.cpp 12 touch_from_button.cpp
15 touch_from_button.h 13 touch_from_button.h
16 gcadapter/gc_adapter.cpp 14 gcadapter/gc_adapter.cpp
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 770893687..f8ec179d0 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -7,7 +7,7 @@
7#include <cmath> 7#include <cmath>
8#include <thread> 8#include <thread>
9#include "common/math_util.h" 9#include "common/math_util.h"
10#include "core/settings.h" 10#include "common/settings.h"
11#include "input_common/analog_from_button.h" 11#include "input_common/analog_from_button.h"
12 12
13namespace InputCommon { 13namespace InputCommon {
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index d80195c82..ec3167bea 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -16,8 +16,8 @@
16 16
17#include "common/logging/log.h" 17#include "common/logging/log.h"
18#include "common/param_package.h" 18#include "common/param_package.h"
19#include "common/settings_input.h"
19#include "input_common/gcadapter/gc_adapter.h" 20#include "input_common/gcadapter/gc_adapter.h"
20#include "input_common/settings.h"
21 21
22namespace GCAdapter { 22namespace GCAdapter {
23 23
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index 329e416c7..fff1c6b45 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/settings.h" 5#include "common/settings.h"
6#include "input_common/mouse/mouse_input.h" 6#include "input_common/mouse/mouse_input.h"
7 7
8namespace MouseInput { 8namespace MouseInput {
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 0e1db54fb..d96104a4e 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -5,8 +5,8 @@
5#include <mutex> 5#include <mutex>
6#include <utility> 6#include <utility>
7 7
8#include "common/settings.h"
8#include "common/threadsafe_queue.h" 9#include "common/threadsafe_queue.h"
9#include "core/settings.h"
10#include "input_common/mouse/mouse_input.h" 10#include "input_common/mouse/mouse_input.h"
11#include "input_common/mouse/mouse_poller.h" 11#include "input_common/mouse/mouse_poller.h"
12 12
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index f67de37e3..9418e78fa 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -20,11 +20,11 @@
20#include <SDL.h> 20#include <SDL.h>
21#include "common/logging/log.h" 21#include "common/logging/log.h"
22#include "common/param_package.h" 22#include "common/param_package.h"
23#include "common/settings_input.h"
23#include "common/threadsafe_queue.h" 24#include "common/threadsafe_queue.h"
24#include "core/frontend/input.h" 25#include "core/frontend/input.h"
25#include "input_common/motion_input.h" 26#include "input_common/motion_input.h"
26#include "input_common/sdl/sdl_impl.h" 27#include "input_common/sdl/sdl_impl.h"
27#include "input_common/settings.h"
28 28
29namespace InputCommon::SDL { 29namespace InputCommon::SDL {
30 30
@@ -761,7 +761,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
761 for (const auto& joystick : value) { 761 for (const auto& joystick : value) {
762 if (auto* const controller = joystick->GetSDLGameController()) { 762 if (auto* const controller = joystick->GetSDLGameController()) {
763 std::string name = 763 std::string name =
764 fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); 764 fmt::format("{} {}", GetControllerName(controller), joystick->GetPort());
765 devices.emplace_back(Common::ParamPackage{ 765 devices.emplace_back(Common::ParamPackage{
766 {"class", "sdl"}, 766 {"class", "sdl"},
767 {"display", std::move(name)}, 767 {"display", std::move(name)},
@@ -782,6 +782,17 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
782 return devices; 782 return devices;
783} 783}
784 784
785std::string SDLState::GetControllerName(SDL_GameController* controller) const {
786 switch (SDL_GameControllerGetType(controller)) {
787 case SDL_CONTROLLER_TYPE_XBOX360:
788 return "XBox 360 Controller";
789 case SDL_CONTROLLER_TYPE_XBOXONE:
790 return "XBox One Controller";
791 default:
792 return SDL_GameControllerName(controller);
793 }
794}
795
785namespace { 796namespace {
786Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, 797Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
787 float value = 0.1f) { 798 float value = 0.1f) {
@@ -930,16 +941,19 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa
930 return {}; 941 return {};
931 } 942 }
932 943
944 const bool invert =
945 SDL_GameControllerGetType(controller) != SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
946
933 // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. 947 // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
934 // We will add those afterwards 948 // We will add those afterwards
935 // This list also excludes Screenshot since theres not really a mapping for that 949 // This list also excludes Screenshot since theres not really a mapping for that
936 using ButtonBindings = 950 using ButtonBindings =
937 std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; 951 std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>;
938 static constexpr ButtonBindings switch_to_sdl_button{{ 952 const ButtonBindings switch_to_sdl_button{{
939 {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, 953 {Settings::NativeButton::A, invert ? SDL_CONTROLLER_BUTTON_B : SDL_CONTROLLER_BUTTON_A},
940 {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, 954 {Settings::NativeButton::B, invert ? SDL_CONTROLLER_BUTTON_A : SDL_CONTROLLER_BUTTON_B},
941 {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, 955 {Settings::NativeButton::X, invert ? SDL_CONTROLLER_BUTTON_Y : SDL_CONTROLLER_BUTTON_X},
942 {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, 956 {Settings::NativeButton::Y, invert ? SDL_CONTROLLER_BUTTON_X : SDL_CONTROLLER_BUTTON_Y},
943 {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, 957 {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
944 {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, 958 {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
945 {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, 959 {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index 08044b00d..8b7363f56 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -14,6 +14,7 @@
14#include "input_common/sdl/sdl.h" 14#include "input_common/sdl/sdl.h"
15 15
16union SDL_Event; 16union SDL_Event;
17using SDL_GameController = struct _SDL_GameController;
17using SDL_Joystick = struct _SDL_Joystick; 18using SDL_Joystick = struct _SDL_Joystick;
18using SDL_JoystickID = s32; 19using SDL_JoystickID = s32;
19 20
@@ -64,6 +65,9 @@ private:
64 /// Needs to be called before SDL_QuitSubSystem. 65 /// Needs to be called before SDL_QuitSubSystem.
65 void CloseJoysticks(); 66 void CloseJoysticks();
66 67
68 /// Returns a custom name for specific controllers because the default name is not correct
69 std::string GetControllerName(SDL_GameController* controller) const;
70
67 // Set to true if SDL supports game controller subsystem 71 // Set to true if SDL supports game controller subsystem
68 bool has_gamecontroller = false; 72 bool has_gamecontroller = false;
69 73
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp
deleted file mode 100644
index 557e7a9a0..000000000
--- a/src/input_common/settings.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "input_common/settings.h"
6
7namespace Settings {
8namespace NativeButton {
9const std::array<const char*, NumButtons> mapping = {{
10 "button_a", "button_b", "button_x", "button_y", "button_lstick",
11 "button_rstick", "button_l", "button_r", "button_zl", "button_zr",
12 "button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
13 "button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot",
14}};
15}
16
17namespace NativeAnalog {
18const std::array<const char*, NumAnalogs> mapping = {{
19 "lstick",
20 "rstick",
21}};
22}
23
24namespace NativeVibration {
25const std::array<const char*, NumVibrations> mapping = {{
26 "left_vibration_device",
27 "right_vibration_device",
28}};
29}
30
31namespace NativeMotion {
32const std::array<const char*, NumMotions> mapping = {{
33 "motionleft",
34 "motionright",
35}};
36}
37
38namespace NativeMouseButton {
39const std::array<const char*, NumMouseButtons> mapping = {{
40 "left",
41 "right",
42 "middle",
43 "forward",
44 "back",
45}};
46}
47} // namespace Settings
diff --git a/src/input_common/settings.h b/src/input_common/settings.h
deleted file mode 100644
index a59f5d461..000000000
--- a/src/input_common/settings.h
+++ /dev/null
@@ -1,372 +0,0 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <string>
9#include "common/common_types.h"
10
11namespace Settings {
12namespace NativeButton {
13enum Values : int {
14 A,
15 B,
16 X,
17 Y,
18 LStick,
19 RStick,
20 L,
21 R,
22 ZL,
23 ZR,
24 Plus,
25 Minus,
26
27 DLeft,
28 DUp,
29 DRight,
30 DDown,
31
32 SL,
33 SR,
34
35 Home,
36 Screenshot,
37
38 NumButtons,
39};
40
41constexpr int BUTTON_HID_BEGIN = A;
42constexpr int BUTTON_NS_BEGIN = Home;
43
44constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
45constexpr int BUTTON_NS_END = NumButtons;
46
47constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
48constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
49
50extern const std::array<const char*, NumButtons> mapping;
51
52} // namespace NativeButton
53
54namespace NativeAnalog {
55enum Values : int {
56 LStick,
57 RStick,
58
59 NumAnalogs,
60};
61
62constexpr int STICK_HID_BEGIN = LStick;
63constexpr int STICK_HID_END = NumAnalogs;
64constexpr int NUM_STICKS_HID = NumAnalogs;
65
66extern const std::array<const char*, NumAnalogs> mapping;
67} // namespace NativeAnalog
68
69namespace NativeVibration {
70enum Values : int {
71 LeftVibrationDevice,
72 RightVibrationDevice,
73
74 NumVibrations,
75};
76
77constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice;
78constexpr int VIBRATION_HID_END = NumVibrations;
79constexpr int NUM_VIBRATIONS_HID = NumVibrations;
80
81extern const std::array<const char*, NumVibrations> mapping;
82}; // namespace NativeVibration
83
84namespace NativeMotion {
85enum Values : int {
86 MotionLeft,
87 MotionRight,
88
89 NumMotions,
90};
91
92constexpr int MOTION_HID_BEGIN = MotionLeft;
93constexpr int MOTION_HID_END = NumMotions;
94constexpr int NUM_MOTIONS_HID = NumMotions;
95
96extern const std::array<const char*, NumMotions> mapping;
97} // namespace NativeMotion
98
99namespace NativeMouseButton {
100enum Values {
101 Left,
102 Right,
103 Middle,
104 Forward,
105 Back,
106
107 NumMouseButtons,
108};
109
110constexpr int MOUSE_HID_BEGIN = Left;
111constexpr int MOUSE_HID_END = NumMouseButtons;
112constexpr int NUM_MOUSE_HID = NumMouseButtons;
113
114extern const std::array<const char*, NumMouseButtons> mapping;
115} // namespace NativeMouseButton
116
117namespace NativeKeyboard {
118enum Keys {
119 None,
120 Error,
121
122 A = 4,
123 B,
124 C,
125 D,
126 E,
127 F,
128 G,
129 H,
130 I,
131 J,
132 K,
133 L,
134 M,
135 N,
136 O,
137 P,
138 Q,
139 R,
140 S,
141 T,
142 U,
143 V,
144 W,
145 X,
146 Y,
147 Z,
148 N1,
149 N2,
150 N3,
151 N4,
152 N5,
153 N6,
154 N7,
155 N8,
156 N9,
157 N0,
158 Enter,
159 Escape,
160 Backspace,
161 Tab,
162 Space,
163 Minus,
164 Equal,
165 LeftBrace,
166 RightBrace,
167 Backslash,
168 Tilde,
169 Semicolon,
170 Apostrophe,
171 Grave,
172 Comma,
173 Dot,
174 Slash,
175 CapsLockKey,
176
177 F1,
178 F2,
179 F3,
180 F4,
181 F5,
182 F6,
183 F7,
184 F8,
185 F9,
186 F10,
187 F11,
188 F12,
189
190 SystemRequest,
191 ScrollLockKey,
192 Pause,
193 Insert,
194 Home,
195 PageUp,
196 Delete,
197 End,
198 PageDown,
199 Right,
200 Left,
201 Down,
202 Up,
203
204 NumLockKey,
205 KPSlash,
206 KPAsterisk,
207 KPMinus,
208 KPPlus,
209 KPEnter,
210 KP1,
211 KP2,
212 KP3,
213 KP4,
214 KP5,
215 KP6,
216 KP7,
217 KP8,
218 KP9,
219 KP0,
220 KPDot,
221
222 Key102,
223 Compose,
224 Power,
225 KPEqual,
226
227 F13,
228 F14,
229 F15,
230 F16,
231 F17,
232 F18,
233 F19,
234 F20,
235 F21,
236 F22,
237 F23,
238 F24,
239
240 Open,
241 Help,
242 Properties,
243 Front,
244 Stop,
245 Repeat,
246 Undo,
247 Cut,
248 Copy,
249 Paste,
250 Find,
251 Mute,
252 VolumeUp,
253 VolumeDown,
254 CapsLockActive,
255 NumLockActive,
256 ScrollLockActive,
257 KPComma,
258
259 KPLeftParenthesis,
260 KPRightParenthesis,
261
262 LeftControlKey = 0xE0,
263 LeftShiftKey,
264 LeftAltKey,
265 LeftMetaKey,
266 RightControlKey,
267 RightShiftKey,
268 RightAltKey,
269 RightMetaKey,
270
271 MediaPlayPause,
272 MediaStopCD,
273 MediaPrevious,
274 MediaNext,
275 MediaEject,
276 MediaVolumeUp,
277 MediaVolumeDown,
278 MediaMute,
279 MediaWebsite,
280 MediaBack,
281 MediaForward,
282 MediaStop,
283 MediaFind,
284 MediaScrollUp,
285 MediaScrollDown,
286 MediaEdit,
287 MediaSleep,
288 MediaCoffee,
289 MediaRefresh,
290 MediaCalculator,
291
292 NumKeyboardKeys,
293};
294
295static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys.");
296
297enum Modifiers {
298 LeftControl,
299 LeftShift,
300 LeftAlt,
301 LeftMeta,
302 RightControl,
303 RightShift,
304 RightAlt,
305 RightMeta,
306 CapsLock,
307 ScrollLock,
308 NumLock,
309
310 NumKeyboardMods,
311};
312
313constexpr int KEYBOARD_KEYS_HID_BEGIN = None;
314constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys;
315constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys;
316
317constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl;
318constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods;
319constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
320
321} // namespace NativeKeyboard
322
323using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
324using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
325using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
326using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
327
328using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
329using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
330using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
331
332constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
333constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
334constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
335constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
336
337enum class ControllerType {
338 ProController,
339 DualJoyconDetached,
340 LeftJoycon,
341 RightJoycon,
342 Handheld,
343 GameCube,
344};
345
346struct PlayerInput {
347 bool connected;
348 ControllerType controller_type;
349 ButtonsRaw buttons;
350 AnalogsRaw analogs;
351 VibrationsRaw vibrations;
352 MotionsRaw motions;
353
354 bool vibration_enabled;
355 int vibration_strength;
356
357 u32 body_color_left;
358 u32 body_color_right;
359 u32 button_color_left;
360 u32 button_color_right;
361};
362
363struct TouchscreenInput {
364 bool enabled;
365 std::string device;
366
367 u32 finger;
368 u32 diameter_x;
369 u32 diameter_y;
370 u32 rotation_angle;
371};
372} // namespace Settings
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp
index ffbe4f2ed..e94ba197b 100644
--- a/src/input_common/touch_from_button.cpp
+++ b/src/input_common/touch_from_button.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/settings.h"
5#include "core/frontend/framebuffer_layout.h" 6#include "core/frontend/framebuffer_layout.h"
6#include "core/settings.h"
7#include "input_common/touch_from_button.h" 7#include "input_common/touch_from_button.h"
8 8
9namespace InputCommon { 9namespace InputCommon {
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index df73f9ff7..8a38a380d 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -9,7 +9,7 @@
9#include <thread> 9#include <thread>
10#include <boost/asio.hpp> 10#include <boost/asio.hpp>
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "core/settings.h" 12#include "common/settings.h"
13#include "input_common/udp/client.h" 13#include "input_common/udp/client.h"
14#include "input_common/udp/protocol.h" 14#include "input_common/udp/protocol.h"
15 15
@@ -27,11 +27,9 @@ class Socket {
27public: 27public:
28 using clock = std::chrono::system_clock; 28 using clock = std::chrono::system_clock;
29 29
30 explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, 30 explicit Socket(const std::string& host, u16 port, SocketCallback callback_)
31 SocketCallback callback_)
32 : callback(std::move(callback_)), timer(io_service), 31 : callback(std::move(callback_)), timer(io_service),
33 socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()), 32 socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) {
34 pad_index(pad_index_) {
35 boost::system::error_code ec{}; 33 boost::system::error_code ec{};
36 auto ipv4 = boost::asio::ip::make_address_v4(host, ec); 34 auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
37 if (ec.value() != boost::system::errc::success) { 35 if (ec.value() != boost::system::errc::success) {
@@ -99,15 +97,15 @@ private:
99 void HandleSend(const boost::system::error_code&) { 97 void HandleSend(const boost::system::error_code&) {
100 boost::system::error_code _ignored{}; 98 boost::system::error_code _ignored{};
101 // Send a request for getting port info for the pad 99 // Send a request for getting port info for the pad
102 const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; 100 const Request::PortInfo port_info{4, {0, 1, 2, 3}};
103 const auto port_message = Request::Create(port_info, client_id); 101 const auto port_message = Request::Create(port_info, client_id);
104 std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); 102 std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
105 socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); 103 socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
106 104
107 // Send a request for getting pad data for the pad 105 // Send a request for getting pad data for the pad
108 const Request::PadData pad_data{ 106 const Request::PadData pad_data{
109 Request::PadData::Flags::Id, 107 Request::PadData::Flags::AllPorts,
110 static_cast<u8>(pad_index), 108 0,
111 EMPTY_MAC_ADDRESS, 109 EMPTY_MAC_ADDRESS,
112 }; 110 };
113 const auto pad_message = Request::Create(pad_data, client_id); 111 const auto pad_message = Request::Create(pad_data, client_id);
@@ -122,7 +120,6 @@ private:
122 udp::socket socket; 120 udp::socket socket;
123 121
124 const u32 client_id; 122 const u32 client_id;
125 std::size_t pad_index{};
126 123
127 static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); 124 static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
128 static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); 125 static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
@@ -150,34 +147,32 @@ Client::~Client() {
150 Reset(); 147 Reset();
151} 148}
152 149
153Client::ClientData::ClientData() = default; 150Client::ClientConnection::ClientConnection() = default;
154 151
155Client::ClientData::~ClientData() = default; 152Client::ClientConnection::~ClientConnection() = default;
156 153
157std::vector<Common::ParamPackage> Client::GetInputDevices() const { 154std::vector<Common::ParamPackage> Client::GetInputDevices() const {
158 std::vector<Common::ParamPackage> devices; 155 std::vector<Common::ParamPackage> devices;
159 for (std::size_t client = 0; client < clients.size(); client++) { 156 for (std::size_t pad = 0; pad < pads.size(); pad++) {
160 if (!DeviceConnected(client)) { 157 if (!DeviceConnected(pad)) {
161 continue; 158 continue;
162 } 159 }
163 std::string name = fmt::format("UDP Controller {}", client); 160 std::string name = fmt::format("UDP Controller {}", pad);
164 devices.emplace_back(Common::ParamPackage{ 161 devices.emplace_back(Common::ParamPackage{
165 {"class", "cemuhookudp"}, 162 {"class", "cemuhookudp"},
166 {"display", std::move(name)}, 163 {"display", std::move(name)},
167 {"port", std::to_string(client)}, 164 {"port", std::to_string(pad)},
168 }); 165 });
169 } 166 }
170 return devices; 167 return devices;
171} 168}
172 169
173bool Client::DeviceConnected(std::size_t client) const { 170bool Client::DeviceConnected(std::size_t pad) const {
174 // Use last timestamp to detect if the socket has stopped sending data 171 // Use last timestamp to detect if the socket has stopped sending data
175 const auto now = std::chrono::steady_clock::now(); 172 const auto now = std::chrono::steady_clock::now();
176 const auto time_difference = 173 const auto time_difference = static_cast<u64>(
177 static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>( 174 std::chrono::duration_cast<std::chrono::milliseconds>(now - pads[pad].last_update).count());
178 now - clients[client].last_motion_update) 175 return time_difference < 1000 && pads[pad].connected;
179 .count());
180 return time_difference < 1000 && clients[client].active == 1;
181} 176}
182 177
183void Client::ReloadSockets() { 178void Client::ReloadSockets() {
@@ -202,25 +197,21 @@ void Client::ReloadSockets() {
202 continue; 197 continue;
203 } 198 }
204 199
205 for (std::size_t pad = 0; pad < 4; ++pad) { 200 const std::size_t client_number = GetClientNumber(udp_input_address, udp_input_port);
206 const std::size_t client_number = 201 if (client_number != MAX_UDP_CLIENTS) {
207 GetClientNumber(udp_input_address, udp_input_port, pad); 202 LOG_ERROR(Input, "Duplicated UDP servers found");
208 if (client_number != MAX_UDP_CLIENTS) { 203 continue;
209 LOG_ERROR(Input, "Duplicated UDP servers found");
210 continue;
211 }
212 StartCommunication(client++, udp_input_address, udp_input_port, pad);
213 } 204 }
205 StartCommunication(client++, udp_input_address, udp_input_port);
214 } 206 }
215} 207}
216 208
217std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t pad) const { 209std::size_t Client::GetClientNumber(std::string_view host, u16 port) const {
218 for (std::size_t client = 0; client < clients.size(); client++) { 210 for (std::size_t client = 0; client < clients.size(); client++) {
219 if (clients[client].active == -1) { 211 if (clients[client].active == -1) {
220 continue; 212 continue;
221 } 213 }
222 if (clients[client].host == host && clients[client].port == port && 214 if (clients[client].host == host && clients[client].port == port) {
223 clients[client].pad_index == pad) {
224 return client; 215 return client;
225 } 216 }
226 } 217 }
@@ -236,69 +227,75 @@ void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
236} 227}
237 228
238void Client::OnPadData(Response::PadData data, std::size_t client) { 229void Client::OnPadData(Response::PadData data, std::size_t client) {
239 // Accept packets only for the correct pad 230 const std::size_t pad_index = (client * PADS_PER_CLIENT) + data.info.id;
240 if (static_cast<u8>(clients[client].pad_index) != data.info.id) { 231
232 if (pad_index >= pads.size()) {
233 LOG_ERROR(Input, "Invalid pad id {}", data.info.id);
241 return; 234 return;
242 } 235 }
243 236
244 LOG_TRACE(Input, "PadData packet received"); 237 LOG_TRACE(Input, "PadData packet received");
245 if (data.packet_counter == clients[client].packet_sequence) { 238 if (data.packet_counter == pads[pad_index].packet_sequence) {
246 LOG_WARNING( 239 LOG_WARNING(
247 Input, 240 Input,
248 "PadData packet dropped because its stale info. Current count: {} Packet count: {}", 241 "PadData packet dropped because its stale info. Current count: {} Packet count: {}",
249 clients[client].packet_sequence, data.packet_counter); 242 pads[pad_index].packet_sequence, data.packet_counter);
243 pads[pad_index].connected = false;
250 return; 244 return;
251 } 245 }
252 clients[client].active = static_cast<s8>(data.info.is_pad_active); 246
253 clients[client].packet_sequence = data.packet_counter; 247 clients[client].active = 1;
248 pads[pad_index].connected = true;
249 pads[pad_index].packet_sequence = data.packet_counter;
250
254 const auto now = std::chrono::steady_clock::now(); 251 const auto now = std::chrono::steady_clock::now();
255 const auto time_difference = 252 const auto time_difference = static_cast<u64>(
256 static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( 253 std::chrono::duration_cast<std::chrono::microseconds>(now - pads[pad_index].last_update)
257 now - clients[client].last_motion_update) 254 .count());
258 .count()); 255 pads[pad_index].last_update = now;
259 clients[client].last_motion_update = now; 256
260 const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; 257 const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
261 clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); 258 pads[pad_index].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y});
262 // Gyroscope values are not it the correct scale from better joy. 259 // Gyroscope values are not it the correct scale from better joy.
263 // Dividing by 312 allows us to make one full turn = 1 turn 260 // Dividing by 312 allows us to make one full turn = 1 turn
264 // This must be a configurable valued called sensitivity 261 // This must be a configurable valued called sensitivity
265 clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f); 262 pads[pad_index].motion.SetGyroscope(raw_gyroscope / 312.0f);
266 clients[client].motion.UpdateRotation(time_difference); 263 pads[pad_index].motion.UpdateRotation(time_difference);
267 clients[client].motion.UpdateOrientation(time_difference); 264 pads[pad_index].motion.UpdateOrientation(time_difference);
268 265
269 { 266 {
270 std::lock_guard guard(clients[client].status.update_mutex); 267 std::lock_guard guard(pads[pad_index].status.update_mutex);
271 clients[client].status.motion_status = clients[client].motion.GetMotion(); 268 pads[pad_index].status.motion_status = pads[pad_index].motion.GetMotion();
272 269
273 for (std::size_t id = 0; id < data.touch.size(); ++id) { 270 for (std::size_t id = 0; id < data.touch.size(); ++id) {
274 UpdateTouchInput(data.touch[id], client, id); 271 UpdateTouchInput(data.touch[id], client, id);
275 } 272 }
276 273
277 if (configuring) { 274 if (configuring) {
278 const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope(); 275 const Common::Vec3f gyroscope = pads[pad_index].motion.GetGyroscope();
279 const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration(); 276 const Common::Vec3f accelerometer = pads[pad_index].motion.GetAcceleration();
280 UpdateYuzuSettings(client, accelerometer, gyroscope); 277 UpdateYuzuSettings(client, data.info.id, accelerometer, gyroscope);
281 } 278 }
282 } 279 }
283} 280}
284 281
285void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, 282void Client::StartCommunication(std::size_t client, const std::string& host, u16 port) {
286 std::size_t pad_index) {
287 SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, 283 SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
288 [this](Response::PortInfo info) { OnPortInfo(info); }, 284 [this](Response::PortInfo info) { OnPortInfo(info); },
289 [this, client](Response::PadData data) { OnPadData(data, client); }}; 285 [this, client](Response::PadData data) { OnPadData(data, client); }};
290 LOG_INFO(Input, "Starting communication with UDP input server on {}:{}:{}", host, port, 286 LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
291 pad_index);
292 clients[client].host = host; 287 clients[client].host = host;
293 clients[client].port = port; 288 clients[client].port = port;
294 clients[client].pad_index = pad_index;
295 clients[client].active = 0; 289 clients[client].active = 0;
296 clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback); 290 clients[client].socket = std::make_unique<Socket>(host, port, callback);
297 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; 291 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
292
298 // Set motion parameters 293 // Set motion parameters
299 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode 294 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
300 // Real HW values are unknown, 0.0001 is an approximate to Standard 295 // Real HW values are unknown, 0.0001 is an approximate to Standard
301 clients[client].motion.SetGyroThreshold(0.0001f); 296 for (std::size_t pad = 0; pad < PADS_PER_CLIENT; pad++) {
297 pads[client * PADS_PER_CLIENT + pad].motion.SetGyroThreshold(0.0001f);
298 }
302} 299}
303 300
304void Client::Reset() { 301void Client::Reset() {
@@ -311,8 +308,8 @@ void Client::Reset() {
311 } 308 }
312} 309}
313 310
314void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 311void Client::UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
315 const Common::Vec3<float>& gyro) { 312 const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro) {
316 if (gyro.Length() > 0.2f) { 313 if (gyro.Length() > 0.2f) {
317 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, 314 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client,
318 gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); 315 gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]);
@@ -320,7 +317,7 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a
320 UDPPadStatus pad{ 317 UDPPadStatus pad{
321 .host = clients[client].host, 318 .host = clients[client].host,
322 .port = clients[client].port, 319 .port = clients[client].port,
323 .pad_index = clients[client].pad_index, 320 .pad_index = pad_index,
324 }; 321 };
325 for (std::size_t i = 0; i < 3; ++i) { 322 for (std::size_t i = 0; i < 3; ++i) {
326 if (gyro[i] > 5.0f || gyro[i] < -5.0f) { 323 if (gyro[i] > 5.0f || gyro[i] < -5.0f) {
@@ -391,19 +388,19 @@ void Client::EndConfiguration() {
391} 388}
392 389
393DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { 390DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) {
394 const std::size_t client_number = GetClientNumber(host, port, pad); 391 const std::size_t client_number = GetClientNumber(host, port);
395 if (client_number == MAX_UDP_CLIENTS) { 392 if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) {
396 return clients[0].status; 393 return pads[0].status;
397 } 394 }
398 return clients[client_number].status; 395 return pads[(client_number * PADS_PER_CLIENT) + pad].status;
399} 396}
400 397
401const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { 398const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const {
402 const std::size_t client_number = GetClientNumber(host, port, pad); 399 const std::size_t client_number = GetClientNumber(host, port);
403 if (client_number == MAX_UDP_CLIENTS) { 400 if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) {
404 return clients[0].status; 401 return pads[0].status;
405 } 402 }
406 return clients[client_number].status; 403 return pads[(client_number * PADS_PER_CLIENT) + pad].status;
407} 404}
408 405
409Input::TouchStatus& Client::GetTouchState() { 406Input::TouchStatus& Client::GetTouchState() {
@@ -422,7 +419,7 @@ const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const {
422 return pad_queue; 419 return pad_queue;
423} 420}
424 421
425void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, 422void TestCommunication(const std::string& host, u16 port,
426 const std::function<void()>& success_callback, 423 const std::function<void()>& success_callback,
427 const std::function<void()>& failure_callback) { 424 const std::function<void()>& failure_callback) {
428 std::thread([=] { 425 std::thread([=] {
@@ -432,9 +429,10 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
432 .port_info = [](Response::PortInfo) {}, 429 .port_info = [](Response::PortInfo) {},
433 .pad_data = [&](Response::PadData) { success_event.Set(); }, 430 .pad_data = [&](Response::PadData) { success_event.Set(); },
434 }; 431 };
435 Socket socket{host, port, pad_index, std::move(callback)}; 432 Socket socket{host, port, std::move(callback)};
436 std::thread worker_thread{SocketLoop, &socket}; 433 std::thread worker_thread{SocketLoop, &socket};
437 const bool result = success_event.WaitFor(std::chrono::seconds(5)); 434 const bool result =
435 success_event.WaitUntil(std::chrono::steady_clock::now() + std::chrono::seconds(10));
438 socket.Stop(); 436 socket.Stop();
439 worker_thread.join(); 437 worker_thread.join();
440 if (result) { 438 if (result) {
@@ -446,8 +444,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
446} 444}
447 445
448CalibrationConfigurationJob::CalibrationConfigurationJob( 446CalibrationConfigurationJob::CalibrationConfigurationJob(
449 const std::string& host, u16 port, std::size_t pad_index, 447 const std::string& host, u16 port, std::function<void(Status)> status_callback,
450 std::function<void(Status)> status_callback,
451 std::function<void(u16, u16, u16, u16)> data_callback) { 448 std::function<void(u16, u16, u16, u16)> data_callback) {
452 449
453 std::thread([=, this] { 450 std::thread([=, this] {
@@ -491,7 +488,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
491 complete_event.Set(); 488 complete_event.Set();
492 } 489 }
493 }}; 490 }};
494 Socket socket{host, port, pad_index, std::move(callback)}; 491 Socket socket{host, port, std::move(callback)};
495 std::thread worker_thread{SocketLoop, &socket}; 492 std::thread worker_thread{SocketLoop, &socket};
496 complete_event.Wait(); 493 complete_event.Wait();
497 socket.Stop(); 494 socket.Stop();
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h
index e9e438e88..a11ea3068 100644
--- a/src/input_common/udp/client.h
+++ b/src/input_common/udp/client.h
@@ -84,7 +84,7 @@ public:
84 84
85 std::vector<Common::ParamPackage> GetInputDevices() const; 85 std::vector<Common::ParamPackage> GetInputDevices() const;
86 86
87 bool DeviceConnected(std::size_t client) const; 87 bool DeviceConnected(std::size_t pad) const;
88 void ReloadSockets(); 88 void ReloadSockets();
89 89
90 Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); 90 Common::SPSCQueue<UDPPadStatus>& GetPadQueue();
@@ -97,38 +97,40 @@ public:
97 const Input::TouchStatus& GetTouchState() const; 97 const Input::TouchStatus& GetTouchState() const;
98 98
99private: 99private:
100 struct ClientData { 100 struct PadData {
101 ClientData();
102 ~ClientData();
103
104 std::string host{"127.0.0.1"};
105 u16 port{26760};
106 std::size_t pad_index{}; 101 std::size_t pad_index{};
107 std::unique_ptr<Socket> socket; 102 bool connected{};
108 DeviceStatus status; 103 DeviceStatus status;
109 std::thread thread;
110 u64 packet_sequence{}; 104 u64 packet_sequence{};
111 s8 active{-1};
112 105
113 // Realtime values 106 // Realtime values
114 // motion is initalized with PID values for drift correction on joycons 107 // motion is initalized with PID values for drift correction on joycons
115 InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; 108 InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f};
116 std::chrono::time_point<std::chrono::steady_clock> last_motion_update; 109 std::chrono::time_point<std::chrono::steady_clock> last_update;
110 };
111
112 struct ClientConnection {
113 ClientConnection();
114 ~ClientConnection();
115 std::string host{"127.0.0.1"};
116 u16 port{26760};
117 s8 active{-1};
118 std::unique_ptr<Socket> socket;
119 std::thread thread;
117 }; 120 };
118 121
119 // For shutting down, clear all data, join all threads, release usb 122 // For shutting down, clear all data, join all threads, release usb
120 void Reset(); 123 void Reset();
121 124
122 // Translates configuration to client number 125 // Translates configuration to client number
123 std::size_t GetClientNumber(std::string_view host, u16 port, std::size_t pad) const; 126 std::size_t GetClientNumber(std::string_view host, u16 port) const;
124 127
125 void OnVersion(Response::Version); 128 void OnVersion(Response::Version);
126 void OnPortInfo(Response::PortInfo); 129 void OnPortInfo(Response::PortInfo);
127 void OnPadData(Response::PadData, std::size_t client); 130 void OnPadData(Response::PadData, std::size_t client);
128 void StartCommunication(std::size_t client, const std::string& host, u16 port, 131 void StartCommunication(std::size_t client, const std::string& host, u16 port);
129 std::size_t pad_index); 132 void UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
130 void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 133 const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro);
131 const Common::Vec3<float>& gyro);
132 134
133 // Returns an unused finger id, if there is no fingers available std::nullopt will be 135 // Returns an unused finger id, if there is no fingers available std::nullopt will be
134 // returned 136 // returned
@@ -140,10 +142,12 @@ private:
140 bool configuring = false; 142 bool configuring = false;
141 143
142 // Allocate clients for 8 udp servers 144 // Allocate clients for 8 udp servers
143 static constexpr std::size_t MAX_UDP_CLIENTS = 4 * 8; 145 static constexpr std::size_t MAX_UDP_CLIENTS = 8;
146 static constexpr std::size_t PADS_PER_CLIENT = 4;
144 // Each client can have up 2 touch inputs 147 // Each client can have up 2 touch inputs
145 static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; 148 static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2;
146 std::array<ClientData, MAX_UDP_CLIENTS> clients{}; 149 std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{};
150 std::array<ClientConnection, MAX_UDP_CLIENTS> clients{};
147 Common::SPSCQueue<UDPPadStatus> pad_queue{}; 151 Common::SPSCQueue<UDPPadStatus> pad_queue{};
148 Input::TouchStatus touch_status{}; 152 Input::TouchStatus touch_status{};
149 std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; 153 std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{};
@@ -164,7 +168,7 @@ public:
164 * @param status_callback Callback for job status updates 168 * @param status_callback Callback for job status updates
165 * @param data_callback Called when calibration data is ready 169 * @param data_callback Called when calibration data is ready
166 */ 170 */
167 explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index, 171 explicit CalibrationConfigurationJob(const std::string& host, u16 port,
168 std::function<void(Status)> status_callback, 172 std::function<void(Status)> status_callback,
169 std::function<void(u16, u16, u16, u16)> data_callback); 173 std::function<void(u16, u16, u16, u16)> data_callback);
170 ~CalibrationConfigurationJob(); 174 ~CalibrationConfigurationJob();
@@ -174,7 +178,7 @@ private:
174 Common::Event complete_event; 178 Common::Event complete_event;
175}; 179};
176 180
177void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, 181void TestCommunication(const std::string& host, u16 port,
178 const std::function<void()>& success_callback, 182 const std::function<void()>& success_callback,
179 const std::function<void()>& failure_callback); 183 const std::function<void()>& failure_callback);
180 184