summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/CMakeLists.txt4
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp6
-rw-r--r--src/input_common/gcadapter/gc_adapter.h4
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp52
-rw-r--r--src/input_common/gcadapter/gc_poller.h11
-rw-r--r--src/input_common/main.cpp15
-rw-r--r--src/input_common/motion_input.h23
-rw-r--r--src/input_common/sdl/sdl.h2
-rw-r--r--src/input_common/sdl/sdl_impl.cpp142
-rw-r--r--src/input_common/sdl/sdl_impl.h2
-rw-r--r--src/input_common/settings.cpp21
-rw-r--r--src/input_common/settings.h35
-rw-r--r--src/input_common/touch_from_button.cpp3
-rw-r--r--src/input_common/udp/client.cpp12
-rw-r--r--src/input_common/udp/protocol.h11
15 files changed, 214 insertions, 129 deletions
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 7b39a38c1..1d1b2e08a 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -31,6 +31,9 @@ add_library(input_common STATIC
31 31
32if (MSVC) 32if (MSVC)
33 target_compile_options(input_common PRIVATE 33 target_compile_options(input_common PRIVATE
34 /W4
35 /WX
36
34 # 'expression' : signed/unsigned mismatch 37 # 'expression' : signed/unsigned mismatch
35 /we4018 38 /we4018
36 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) 39 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
@@ -46,6 +49,7 @@ if (MSVC)
46 ) 49 )
47else() 50else()
48 target_compile_options(input_common PRIVATE 51 target_compile_options(input_common PRIVATE
52 -Werror
49 -Werror=conversion 53 -Werror=conversion
50 -Werror=ignored-qualifiers 54 -Werror=ignored-qualifiers
51 -Werror=implicit-fallthrough 55 -Werror=implicit-fallthrough
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index b912188b6..d80195c82 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -230,10 +230,8 @@ void Adapter::SendVibrations() {
230 vibration_changed = false; 230 vibration_changed = false;
231} 231}
232 232
233bool Adapter::RumblePlay(std::size_t port, f32 amplitude) { 233bool Adapter::RumblePlay(std::size_t port, u8 amplitude) {
234 amplitude = std::clamp(amplitude, 0.0f, 1.0f); 234 pads[port].rumble_amplitude = amplitude;
235 const auto raw_amp = static_cast<u8>(amplitude * 0x8);
236 pads[port].rumble_amplitude = raw_amp;
237 235
238 return rumble_enabled; 236 return rumble_enabled;
239} 237}
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index d28dcfad3..f1256c9da 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -77,8 +77,8 @@ public:
77 Adapter(); 77 Adapter();
78 ~Adapter(); 78 ~Adapter();
79 79
80 /// Request a vibration for a controlelr 80 /// Request a vibration for a controller
81 bool RumblePlay(std::size_t port, f32 amplitude); 81 bool RumblePlay(std::size_t port, u8 amplitude);
82 82
83 /// Used for polling 83 /// Used for polling
84 void BeginConfiguration(); 84 void BeginConfiguration();
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 6bd6f57fc..4d1052414 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -15,7 +15,7 @@ namespace InputCommon {
15 15
16class GCButton final : public Input::ButtonDevice { 16class GCButton final : public Input::ButtonDevice {
17public: 17public:
18 explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter) 18 explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter)
19 : port(port_), button(button_), gcadapter(adapter) {} 19 : port(port_), button(button_), gcadapter(adapter) {}
20 20
21 ~GCButton() override; 21 ~GCButton() override;
@@ -27,18 +27,10 @@ public:
27 return false; 27 return false;
28 } 28 }
29 29
30 bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
31 const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f;
32 const auto new_amp =
33 static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f)));
34
35 return gcadapter->RumblePlay(port, new_amp);
36 }
37
38private: 30private:
39 const u32 port; 31 const u32 port;
40 const s32 button; 32 const s32 button;
41 GCAdapter::Adapter* gcadapter; 33 const GCAdapter::Adapter* gcadapter;
42}; 34};
43 35
44class GCAxisButton final : public Input::ButtonDevice { 36class GCAxisButton final : public Input::ButtonDevice {
@@ -104,7 +96,6 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param
104 adapter.get()); 96 adapter.get());
105 } 97 }
106 98
107 UNREACHABLE();
108 return nullptr; 99 return nullptr;
109} 100}
110 101
@@ -299,4 +290,43 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
299 return params; 290 return params;
300} 291}
301 292
293class GCVibration final : public Input::VibrationDevice {
294public:
295 explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter)
296 : port(port_), gcadapter(adapter) {}
297
298 u8 GetStatus() const override {
299 return gcadapter->RumblePlay(port, 0);
300 }
301
302 bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
303 [[maybe_unused]] f32 freq_high) const override {
304 const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
305 const auto processed_amplitude =
306 static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
307
308 return gcadapter->RumblePlay(port, processed_amplitude);
309 }
310
311private:
312 const u32 port;
313 GCAdapter::Adapter* gcadapter;
314};
315
316/// An vibration device factory that creates vibration devices from GC Adapter
317GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
318 : adapter(std::move(adapter_)) {}
319
320/**
321 * Creates a vibration device from a joystick
322 * @param params contains parameters for creating the device:
323 * - "port": the nth gcpad on the adapter
324 */
325std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create(
326 const Common::ParamPackage& params) {
327 const auto port = static_cast<u32>(params.Get("port", 0));
328
329 return std::make_unique<GCVibration>(port, adapter.get());
330}
331
302} // namespace InputCommon 332} // namespace InputCommon
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h
index 0527f328f..d1271e3ea 100644
--- a/src/input_common/gcadapter/gc_poller.h
+++ b/src/input_common/gcadapter/gc_poller.h
@@ -64,4 +64,15 @@ private:
64 bool polling = false; 64 bool polling = false;
65}; 65};
66 66
67/// A vibration device factory creates vibration devices from GC Adapter
68class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
69public:
70 explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
71
72 std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override;
73
74private:
75 std::shared_ptr<GCAdapter::Adapter> adapter;
76};
77
67} // namespace InputCommon 78} // namespace InputCommon
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index d32fd8b81..e59ad4ff5 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -28,6 +28,8 @@ struct InputSubsystem::Impl {
28 Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); 28 Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
29 gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); 29 gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
30 Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); 30 Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
31 gcvibration = std::make_shared<GCVibrationFactory>(gcadapter);
32 Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration);
31 33
32 keyboard = std::make_shared<Keyboard>(); 34 keyboard = std::make_shared<Keyboard>();
33 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); 35 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
@@ -64,9 +66,11 @@ struct InputSubsystem::Impl {
64#endif 66#endif
65 Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); 67 Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
66 Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); 68 Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
69 Input::UnregisterFactory<Input::VibrationDevice>("gcpad");
67 70
68 gcbuttons.reset(); 71 gcbuttons.reset();
69 gcanalog.reset(); 72 gcanalog.reset();
73 gcvibration.reset();
70 74
71 Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); 75 Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
72 Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); 76 Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
@@ -78,7 +82,7 @@ struct InputSubsystem::Impl {
78 [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { 82 [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
79 std::vector<Common::ParamPackage> devices = { 83 std::vector<Common::ParamPackage> devices = {
80 Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, 84 Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
81 Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, 85 Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}},
82 }; 86 };
83#ifdef HAVE_SDL2 87#ifdef HAVE_SDL2
84 auto sdl_devices = sdl->GetInputDevices(); 88 auto sdl_devices = sdl->GetInputDevices();
@@ -96,10 +100,6 @@ struct InputSubsystem::Impl {
96 if (!params.Has("class") || params.Get("class", "") == "any") { 100 if (!params.Has("class") || params.Get("class", "") == "any") {
97 return {}; 101 return {};
98 } 102 }
99 if (params.Get("class", "") == "key") {
100 // TODO consider returning the SDL key codes for the default keybindings
101 return {};
102 }
103 if (params.Get("class", "") == "gcpad") { 103 if (params.Get("class", "") == "gcpad") {
104 return gcadapter->GetAnalogMappingForDevice(params); 104 return gcadapter->GetAnalogMappingForDevice(params);
105 } 105 }
@@ -116,10 +116,6 @@ struct InputSubsystem::Impl {
116 if (!params.Has("class") || params.Get("class", "") == "any") { 116 if (!params.Has("class") || params.Get("class", "") == "any") {
117 return {}; 117 return {};
118 } 118 }
119 if (params.Get("class", "") == "key") {
120 // TODO consider returning the SDL key codes for the default keybindings
121 return {};
122 }
123 if (params.Get("class", "") == "gcpad") { 119 if (params.Get("class", "") == "gcpad") {
124 return gcadapter->GetButtonMappingForDevice(params); 120 return gcadapter->GetButtonMappingForDevice(params);
125 } 121 }
@@ -150,6 +146,7 @@ struct InputSubsystem::Impl {
150#endif 146#endif
151 std::shared_ptr<GCButtonFactory> gcbuttons; 147 std::shared_ptr<GCButtonFactory> gcbuttons;
152 std::shared_ptr<GCAnalogFactory> gcanalog; 148 std::shared_ptr<GCAnalogFactory> gcanalog;
149 std::shared_ptr<GCVibrationFactory> gcvibration;
153 std::shared_ptr<UDPMotionFactory> udpmotion; 150 std::shared_ptr<UDPMotionFactory> udpmotion;
154 std::shared_ptr<UDPTouchFactory> udptouch; 151 std::shared_ptr<UDPTouchFactory> udptouch;
155 std::shared_ptr<CemuhookUDP::Client> udp; 152 std::shared_ptr<CemuhookUDP::Client> udp;
diff --git a/src/input_common/motion_input.h b/src/input_common/motion_input.h
index abb957f04..efe74cf19 100644
--- a/src/input_common/motion_input.h
+++ b/src/input_common/motion_input.h
@@ -13,7 +13,7 @@ namespace InputCommon {
13 13
14class MotionInput { 14class MotionInput {
15public: 15public:
16 MotionInput(f32 new_kp, f32 new_ki, f32 new_kd); 16 explicit MotionInput(f32 new_kp, f32 new_ki, f32 new_kd);
17 17
18 MotionInput(const MotionInput&) = default; 18 MotionInput(const MotionInput&) = default;
19 MotionInput& operator=(const MotionInput&) = default; 19 MotionInput& operator=(const MotionInput&) = default;
@@ -33,16 +33,17 @@ public:
33 void UpdateRotation(u64 elapsed_time); 33 void UpdateRotation(u64 elapsed_time);
34 void UpdateOrientation(u64 elapsed_time); 34 void UpdateOrientation(u64 elapsed_time);
35 35
36 std::array<Common::Vec3f, 3> GetOrientation() const; 36 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
37 Common::Vec3f GetAcceleration() const; 37 [[nodiscard]] Common::Vec3f GetAcceleration() const;
38 Common::Vec3f GetGyroscope() const; 38 [[nodiscard]] Common::Vec3f GetGyroscope() const;
39 Common::Vec3f GetRotations() const; 39 [[nodiscard]] Common::Vec3f GetRotations() const;
40 Common::Quaternion<f32> GetQuaternion() const; 40 [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
41 Input::MotionStatus GetMotion() const; 41 [[nodiscard]] Input::MotionStatus GetMotion() const;
42 Input::MotionStatus GetRandomMotion(int accel_magnitude, int gyro_magnitude) const; 42 [[nodiscard]] Input::MotionStatus GetRandomMotion(int accel_magnitude,
43 43 int gyro_magnitude) const;
44 bool IsMoving(f32 sensitivity) const; 44
45 bool IsCalibrated(f32 sensitivity) const; 45 [[nodiscard]] bool IsMoving(f32 sensitivity) const;
46 [[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
46 47
47private: 48private:
48 void ResetOrientation(); 49 void ResetOrientation();
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h
index f3554be9a..42bbf14d4 100644
--- a/src/input_common/sdl/sdl.h
+++ b/src/input_common/sdl/sdl.h
@@ -23,7 +23,7 @@ public:
23 /// Unregisters SDL device factories and shut them down. 23 /// Unregisters SDL device factories and shut them down.
24 virtual ~State() = default; 24 virtual ~State() = default;
25 25
26 virtual Pollers GetPollers(Polling::DeviceType type) { 26 virtual Pollers GetPollers(Polling::DeviceType) {
27 return {}; 27 return {};
28 } 28 }
29 29
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 10883e2d9..7827e324c 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -80,30 +80,13 @@ public:
80 return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); 80 return static_cast<float>(state.axes.at(axis)) / (32767.0f * range);
81 } 81 }
82 82
83 bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) { 83 bool RumblePlay(u16 amp_low, u16 amp_high) {
84 const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); 84 if (sdl_controller) {
85 const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); 85 return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0;
86 // Lower drastically the number of state changes 86 } else if (sdl_joystick) {
87 if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && 87 return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0;
88 raw_amp_high >> 11 == last_state_rumble_high >> 11) {
89 if (raw_amp_low + raw_amp_high != 0 ||
90 last_state_rumble_low + last_state_rumble_high == 0) {
91 return false;
92 }
93 }
94 // Don't change state if last vibration was < 20ms
95 const auto now = std::chrono::system_clock::now();
96 if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) <
97 std::chrono::milliseconds(20)) {
98 return raw_amp_low + raw_amp_high == 0;
99 } 88 }
100 89
101 last_vibration = now;
102 last_state_rumble_low = raw_amp_low;
103 last_state_rumble_high = raw_amp_high;
104 if (sdl_joystick) {
105 SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time);
106 }
107 return false; 90 return false;
108 } 91 }
109 92
@@ -172,9 +155,6 @@ private:
172 } state; 155 } state;
173 std::string guid; 156 std::string guid;
174 int port; 157 int port;
175 u16 last_state_rumble_high = 0;
176 u16 last_state_rumble_low = 0;
177 std::chrono::time_point<std::chrono::system_clock> last_vibration;
178 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; 158 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
179 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; 159 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
180 mutable std::mutex mutex; 160 mutable std::mutex mutex;
@@ -327,12 +307,6 @@ public:
327 return joystick->GetButton(button); 307 return joystick->GetButton(button);
328 } 308 }
329 309
330 bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
331 const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f));
332 const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f));
333 return joystick->RumblePlay(new_amp_low, new_amp_high, 250);
334 }
335
336private: 310private:
337 std::shared_ptr<SDLJoystick> joystick; 311 std::shared_ptr<SDLJoystick> joystick;
338 int button; 312 int button;
@@ -416,6 +390,32 @@ private:
416 const float range; 390 const float range;
417}; 391};
418 392
393class SDLVibration final : public Input::VibrationDevice {
394public:
395 explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_)
396 : joystick(std::move(joystick_)) {}
397
398 u8 GetStatus() const override {
399 joystick->RumblePlay(1, 1);
400 return joystick->RumblePlay(0, 0);
401 }
402
403 bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
404 [[maybe_unused]] f32 freq_high) const override {
405 const auto process_amplitude = [](f32 amplitude) {
406 return static_cast<u16>((amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF);
407 };
408
409 const auto processed_amp_low = process_amplitude(amp_low);
410 const auto processed_amp_high = process_amplitude(amp_high);
411
412 return joystick->RumblePlay(processed_amp_low, processed_amp_high);
413 }
414
415private:
416 std::shared_ptr<SDLJoystick> joystick;
417};
418
419class SDLDirectionMotion final : public Input::MotionDevice { 419class SDLDirectionMotion final : public Input::MotionDevice {
420public: 420public:
421 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) 421 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
@@ -558,7 +558,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
558public: 558public:
559 explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} 559 explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
560 /** 560 /**
561 * Creates analog device from joystick axes 561 * Creates an analog device from joystick axes
562 * @param params contains parameters for creating the device: 562 * @param params contains parameters for creating the device:
563 * - "guid": the guid of the joystick to bind 563 * - "guid": the guid of the joystick to bind
564 * - "port": the nth joystick of the same type 564 * - "port": the nth joystick of the same type
@@ -584,6 +584,26 @@ private:
584 SDLState& state; 584 SDLState& state;
585}; 585};
586 586
587/// An vibration device factory that creates vibration devices from SDL joystick
588class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
589public:
590 explicit SDLVibrationFactory(SDLState& state_) : state(state_) {}
591 /**
592 * Creates a vibration device from a joystick
593 * @param params contains parameters for creating the device:
594 * - "guid": the guid of the joystick to bind
595 * - "port": the nth joystick of the same type
596 */
597 std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override {
598 const std::string guid = params.Get("guid", "0");
599 const int port = params.Get("port", 0);
600 return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port));
601 }
602
603private:
604 SDLState& state;
605};
606
587/// A motion device factory that creates motion devices from SDL joystick 607/// A motion device factory that creates motion devices from SDL joystick
588class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { 608class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
589public: 609public:
@@ -650,11 +670,13 @@ private:
650 670
651SDLState::SDLState() { 671SDLState::SDLState() {
652 using namespace Input; 672 using namespace Input;
653 analog_factory = std::make_shared<SDLAnalogFactory>(*this);
654 button_factory = std::make_shared<SDLButtonFactory>(*this); 673 button_factory = std::make_shared<SDLButtonFactory>(*this);
674 analog_factory = std::make_shared<SDLAnalogFactory>(*this);
675 vibration_factory = std::make_shared<SDLVibrationFactory>(*this);
655 motion_factory = std::make_shared<SDLMotionFactory>(*this); 676 motion_factory = std::make_shared<SDLMotionFactory>(*this);
656 RegisterFactory<AnalogDevice>("sdl", analog_factory);
657 RegisterFactory<ButtonDevice>("sdl", button_factory); 677 RegisterFactory<ButtonDevice>("sdl", button_factory);
678 RegisterFactory<AnalogDevice>("sdl", analog_factory);
679 RegisterFactory<VibrationDevice>("sdl", vibration_factory);
658 RegisterFactory<MotionDevice>("sdl", motion_factory); 680 RegisterFactory<MotionDevice>("sdl", motion_factory);
659 681
660 // If the frontend is going to manage the event loop, then we don't start one here 682 // If the frontend is going to manage the event loop, then we don't start one here
@@ -676,7 +698,7 @@ SDLState::SDLState() {
676 using namespace std::chrono_literals; 698 using namespace std::chrono_literals;
677 while (initialized) { 699 while (initialized) {
678 SDL_PumpEvents(); 700 SDL_PumpEvents();
679 std::this_thread::sleep_for(5ms); 701 std::this_thread::sleep_for(1ms);
680 } 702 }
681 }); 703 });
682 } 704 }
@@ -691,6 +713,7 @@ SDLState::~SDLState() {
691 using namespace Input; 713 using namespace Input;
692 UnregisterFactory<ButtonDevice>("sdl"); 714 UnregisterFactory<ButtonDevice>("sdl");
693 UnregisterFactory<AnalogDevice>("sdl"); 715 UnregisterFactory<AnalogDevice>("sdl");
716 UnregisterFactory<VibrationDevice>("sdl");
694 UnregisterFactory<MotionDevice>("sdl"); 717 UnregisterFactory<MotionDevice>("sdl");
695 718
696 CloseJoysticks(); 719 CloseJoysticks();
@@ -842,6 +865,8 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve
842Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, 865Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
843 const SDL_GameControllerButtonBind& binding) { 866 const SDL_GameControllerButtonBind& binding) {
844 switch (binding.bindType) { 867 switch (binding.bindType) {
868 case SDL_CONTROLLER_BINDTYPE_NONE:
869 break;
845 case SDL_CONTROLLER_BINDTYPE_AXIS: 870 case SDL_CONTROLLER_BINDTYPE_AXIS:
846 return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); 871 return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
847 case SDL_CONTROLLER_BINDTYPE_BUTTON: 872 case SDL_CONTROLLER_BINDTYPE_BUTTON:
@@ -962,7 +987,7 @@ class SDLPoller : public InputCommon::Polling::DevicePoller {
962public: 987public:
963 explicit SDLPoller(SDLState& state_) : state(state_) {} 988 explicit SDLPoller(SDLState& state_) : state(state_) {}
964 989
965 void Start(const std::string& device_id) override { 990 void Start([[maybe_unused]] const std::string& device_id) override {
966 state.event_queue.Clear(); 991 state.event_queue.Clear();
967 state.polling = true; 992 state.polling = true;
968 } 993 }
@@ -1045,7 +1070,6 @@ public:
1045 1070
1046 void Start(const std::string& device_id) override { 1071 void Start(const std::string& device_id) override {
1047 SDLPoller::Start(device_id); 1072 SDLPoller::Start(device_id);
1048 // Load the game controller
1049 // Reset stored axes 1073 // Reset stored axes
1050 analog_x_axis = -1; 1074 analog_x_axis = -1;
1051 analog_y_axis = -1; 1075 analog_y_axis = -1;
@@ -1058,40 +1082,21 @@ public:
1058 if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { 1082 if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) {
1059 continue; 1083 continue;
1060 } 1084 }
1061 // Simplify controller config by testing if game controller support is enabled.
1062 if (event.type == SDL_JOYAXISMOTION) { 1085 if (event.type == SDL_JOYAXISMOTION) {
1063 const auto axis = event.jaxis.axis; 1086 const auto axis = event.jaxis.axis;
1064 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 1087 // In order to return a complete analog param, we need inputs for both axes.
1065 auto* const controller = joystick->GetSDLGameController()) { 1088 // First we take the x-axis (horizontal) input, then the y-axis (vertical) input.
1066 const auto axis_left_x = 1089 if (analog_x_axis == -1) {
1067 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) 1090 analog_x_axis = axis;
1068 .value.axis; 1091 } else if (analog_y_axis == -1 && analog_x_axis != axis) {
1069 const auto axis_left_y = 1092 analog_y_axis = axis;
1070 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) 1093 }
1071 .value.axis; 1094 } else {
1072 const auto axis_right_x = 1095 // If the press wasn't accepted as a joy axis, check for a button press
1073 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) 1096 auto button_press = button_poller.FromEvent(event);
1074 .value.axis; 1097 if (button_press) {
1075 const auto axis_right_y = 1098 return *button_press;
1076 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY)
1077 .value.axis;
1078
1079 if (axis == axis_left_x || axis == axis_left_y) {
1080 analog_x_axis = axis_left_x;
1081 analog_y_axis = axis_left_y;
1082 break;
1083 } else if (axis == axis_right_x || axis == axis_right_y) {
1084 analog_x_axis = axis_right_x;
1085 analog_y_axis = axis_right_y;
1086 break;
1087 }
1088 } 1099 }
1089 }
1090
1091 // If the press wasn't accepted as a joy axis, check for a button press
1092 auto button_press = button_poller.FromEvent(event);
1093 if (button_press) {
1094 return *button_press;
1095 } 1100 }
1096 } 1101 }
1097 1102
@@ -1104,6 +1109,7 @@ public:
1104 return params; 1109 return params;
1105 } 1110 }
1106 } 1111 }
1112
1107 return {}; 1113 return {};
1108 } 1114 }
1109 1115
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index b9bb4dc56..08044b00d 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -22,6 +22,7 @@ namespace InputCommon::SDL {
22class SDLAnalogFactory; 22class SDLAnalogFactory;
23class SDLButtonFactory; 23class SDLButtonFactory;
24class SDLMotionFactory; 24class SDLMotionFactory;
25class SDLVibrationFactory;
25class SDLJoystick; 26class SDLJoystick;
26 27
27class SDLState : public State { 28class SDLState : public State {
@@ -72,6 +73,7 @@ private:
72 73
73 std::shared_ptr<SDLButtonFactory> button_factory; 74 std::shared_ptr<SDLButtonFactory> button_factory;
74 std::shared_ptr<SDLAnalogFactory> analog_factory; 75 std::shared_ptr<SDLAnalogFactory> analog_factory;
76 std::shared_ptr<SDLVibrationFactory> vibration_factory;
75 std::shared_ptr<SDLMotionFactory> motion_factory; 77 std::shared_ptr<SDLMotionFactory> motion_factory;
76 78
77 bool start_thread = false; 79 bool start_thread = false;
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp
index b66c05856..557e7a9a0 100644
--- a/src/input_common/settings.cpp
+++ b/src/input_common/settings.cpp
@@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{
14}}; 14}};
15} 15}
16 16
17namespace NativeMotion {
18const std::array<const char*, NumMotions> mapping = {{
19 "motionleft",
20 "motionright",
21}};
22}
23
24namespace NativeAnalog { 17namespace NativeAnalog {
25const std::array<const char*, NumAnalogs> mapping = {{ 18const std::array<const char*, NumAnalogs> mapping = {{
26 "lstick", 19 "lstick",
@@ -28,6 +21,20 @@ const std::array<const char*, NumAnalogs> mapping = {{
28}}; 21}};
29} 22}
30 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
31namespace NativeMouseButton { 38namespace NativeMouseButton {
32const std::array<const char*, NumMouseButtons> mapping = {{ 39const std::array<const char*, NumMouseButtons> mapping = {{
33 "left", 40 "left",
diff --git a/src/input_common/settings.h b/src/input_common/settings.h
index f52d28540..75486554b 100644
--- a/src/input_common/settings.h
+++ b/src/input_common/settings.h
@@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs;
66extern const std::array<const char*, NumAnalogs> mapping; 66extern const std::array<const char*, NumAnalogs> mapping;
67} // namespace NativeAnalog 67} // namespace NativeAnalog
68 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
69namespace NativeMotion { 84namespace NativeMotion {
70enum Values : int { 85enum Values : int {
71 MOTIONLEFT, 86 MotionLeft,
72 MOTIONRIGHT, 87 MotionRight,
73 88
74 NumMotions, 89 NumMotions,
75}; 90};
76 91
77constexpr int MOTION_HID_BEGIN = MOTIONLEFT; 92constexpr int MOTION_HID_BEGIN = MotionLeft;
78constexpr int MOTION_HID_END = NumMotions; 93constexpr int MOTION_HID_END = NumMotions;
79constexpr int NUM_MOTION_HID = NumMotions; 94constexpr int NUM_MOTIONS_HID = NumMotions;
80 95
81extern const std::array<const char*, NumMotions> mapping; 96extern const std::array<const char*, NumMotions> mapping;
82} // namespace NativeMotion 97} // namespace NativeMotion
@@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
305 320
306} // namespace NativeKeyboard 321} // namespace NativeKeyboard
307 322
308using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
309using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; 323using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
310using MotionRaw = std::array<std::string, NativeMotion::NumMotions>; 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
311using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; 328using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
312using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; 329using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
313using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; 330using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
@@ -330,7 +347,11 @@ struct PlayerInput {
330 ControllerType controller_type; 347 ControllerType controller_type;
331 ButtonsRaw buttons; 348 ButtonsRaw buttons;
332 AnalogsRaw analogs; 349 AnalogsRaw analogs;
333 MotionRaw motions; 350 VibrationsRaw vibrations;
351 MotionsRaw motions;
352
353 bool vibration_enabled;
354 int vibration_strength;
334 355
335 u32 body_color_left; 356 u32 body_color_left;
336 u32 body_color_right; 357 u32 body_color_right;
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp
index c37716aae..a07124a86 100644
--- a/src/input_common/touch_from_button.cpp
+++ b/src/input_common/touch_from_button.cpp
@@ -44,8 +44,7 @@ private:
44 std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map; 44 std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map;
45}; 45};
46 46
47std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create( 47std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(const Common::ParamPackage&) {
48 const Common::ParamPackage& params) {
49 return std::make_unique<TouchFromButtonDevice>(); 48 return std::make_unique<TouchFromButtonDevice>();
50} 49}
51 50
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index 7039d6fc3..c0bb90048 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -63,7 +63,7 @@ public:
63 } 63 }
64 64
65private: 65private:
66 void HandleReceive(const boost::system::error_code& error, std::size_t bytes_transferred) { 66 void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) {
67 if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) { 67 if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) {
68 switch (*type) { 68 switch (*type) {
69 case Type::Version: { 69 case Type::Version: {
@@ -90,7 +90,7 @@ private:
90 StartReceive(); 90 StartReceive();
91 } 91 }
92 92
93 void HandleSend(const boost::system::error_code& error) { 93 void HandleSend(const boost::system::error_code&) {
94 boost::system::error_code _ignored{}; 94 boost::system::error_code _ignored{};
95 // Send a request for getting port info for the pad 95 // Send a request for getting port info for the pad
96 const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; 96 const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}};
@@ -189,11 +189,11 @@ void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_ind
189 StartCommunication(client, host, port, pad_index, client_id); 189 StartCommunication(client, host, port, pad_index, client_id);
190} 190}
191 191
192void Client::OnVersion(Response::Version data) { 192void Client::OnVersion([[maybe_unused]] Response::Version data) {
193 LOG_TRACE(Input, "Version packet received: {}", data.version); 193 LOG_TRACE(Input, "Version packet received: {}", data.version);
194} 194}
195 195
196void Client::OnPortInfo(Response::PortInfo data) { 196void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
197 LOG_TRACE(Input, "PortInfo packet received: {}", data.model); 197 LOG_TRACE(Input, "PortInfo packet received: {}", data.model);
198} 198}
199 199
@@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
344 }; 344 };
345 Socket socket{host, port, pad_index, client_id, std::move(callback)}; 345 Socket socket{host, port, pad_index, client_id, std::move(callback)};
346 std::thread worker_thread{SocketLoop, &socket}; 346 std::thread worker_thread{SocketLoop, &socket};
347 const bool result = success_event.WaitFor(std::chrono::seconds(8)); 347 const bool result = success_event.WaitFor(std::chrono::seconds(5));
348 socket.Stop(); 348 socket.Stop();
349 worker_thread.join(); 349 worker_thread.join();
350 if (result) { 350 if (result) {
@@ -369,7 +369,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
369 u16 max_y{}; 369 u16 max_y{};
370 370
371 Status current_status{Status::Initialized}; 371 Status current_status{Status::Initialized};
372 SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {}, 372 SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {},
373 [&](Response::PadData data) { 373 [&](Response::PadData data) {
374 if (current_status == Status::Initialized) { 374 if (current_status == Status::Initialized) {
375 // Receiving data means the communication is ready now 375 // Receiving data means the communication is ready now
diff --git a/src/input_common/udp/protocol.h b/src/input_common/udp/protocol.h
index 3ba4d1fc8..fc1aea4b9 100644
--- a/src/input_common/udp/protocol.h
+++ b/src/input_common/udp/protocol.h
@@ -7,7 +7,16 @@
7#include <array> 7#include <array>
8#include <optional> 8#include <optional>
9#include <type_traits> 9#include <type_traits>
10
11#ifdef _MSC_VER
12#pragma warning(push)
13#pragma warning(disable : 4701)
14#endif
10#include <boost/crc.hpp> 15#include <boost/crc.hpp>
16#ifdef _MSC_VER
17#pragma warning(pop)
18#endif
19
11#include "common/bit_field.h" 20#include "common/bit_field.h"
12#include "common/swap.h" 21#include "common/swap.h"
13 22
@@ -93,7 +102,7 @@ static_assert(std::is_trivially_copyable_v<PadData>,
93 102
94/** 103/**
95 * Creates a message with the proper header data that can be sent to the server. 104 * Creates a message with the proper header data that can be sent to the server.
96 * @param T data Request body to send 105 * @param data Request body to send
97 * @param client_id ID of the udp client (usually not checked on the server) 106 * @param client_id ID of the udp client (usually not checked on the server)
98 */ 107 */
99template <typename T> 108template <typename T>