summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/core.h2
-rw-r--r--src/core/frontend/applets/controller.cpp8
-rw-r--r--src/core/frontend/applets/controller.h8
-rw-r--r--src/core/frontend/input.h3
-rw-r--r--src/core/hle/service/am/applets/applets.cpp3
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp132
-rw-r--r--src/core/hle/service/hid/controllers/npad.h2
-rw-r--r--src/core/hle/service/hid/hid.cpp23
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/input_common/sdl/sdl_impl.cpp39
-rw-r--r--src/input_common/udp/client.cpp8
11 files changed, 157 insertions, 72 deletions
diff --git a/src/core/core.h b/src/core/core.h
index 83ded63a5..27efe30bb 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -120,7 +120,7 @@ public:
120 * Gets the instance of the System singleton class. 120 * Gets the instance of the System singleton class.
121 * @returns Reference to the instance of the System singleton class. 121 * @returns Reference to the instance of the System singleton class.
122 */ 122 */
123 static System& GetInstance() { 123 [[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() {
124 return s_instance; 124 return s_instance;
125 } 125 }
126 126
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 4505da758..c5d65f2d0 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -4,7 +4,6 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h"
8#include "core/frontend/applets/controller.h" 7#include "core/frontend/applets/controller.h"
9#include "core/hle/service/hid/controllers/npad.h" 8#include "core/hle/service/hid/controllers/npad.h"
10#include "core/hle/service/hid/hid.h" 9#include "core/hle/service/hid/hid.h"
@@ -14,6 +13,9 @@ namespace Core::Frontend {
14 13
15ControllerApplet::~ControllerApplet() = default; 14ControllerApplet::~ControllerApplet() = default;
16 15
16DefaultControllerApplet::DefaultControllerApplet(Service::SM::ServiceManager& service_manager_)
17 : service_manager{service_manager_} {}
18
17DefaultControllerApplet::~DefaultControllerApplet() = default; 19DefaultControllerApplet::~DefaultControllerApplet() = default;
18 20
19void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, 21void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback,
@@ -21,9 +23,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
21 LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); 23 LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
22 24
23 auto& npad = 25 auto& npad =
24 Core::System::GetInstance() 26 service_manager.GetService<Service::HID::Hid>("hid")
25 .ServiceManager()
26 .GetService<Service::HID::Hid>("hid")
27 ->GetAppletResource() 27 ->GetAppletResource()
28 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); 28 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
29 29
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h
index a227f15cd..3e49cdbb9 100644
--- a/src/core/frontend/applets/controller.h
+++ b/src/core/frontend/applets/controller.h
@@ -8,6 +8,10 @@
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10 10
11namespace Service::SM {
12class ServiceManager;
13}
14
11namespace Core::Frontend { 15namespace Core::Frontend {
12 16
13using BorderColor = std::array<u8, 4>; 17using BorderColor = std::array<u8, 4>;
@@ -39,10 +43,14 @@ public:
39 43
40class DefaultControllerApplet final : public ControllerApplet { 44class DefaultControllerApplet final : public ControllerApplet {
41public: 45public:
46 explicit DefaultControllerApplet(Service::SM::ServiceManager& service_manager_);
42 ~DefaultControllerApplet() override; 47 ~DefaultControllerApplet() override;
43 48
44 void ReconfigureControllers(std::function<void()> callback, 49 void ReconfigureControllers(std::function<void()> callback,
45 ControllerParameters parameters) const override; 50 ControllerParameters parameters) const override;
51
52private:
53 Service::SM::ServiceManager& service_manager;
46}; 54};
47 55
48} // namespace Core::Frontend 56} // namespace Core::Frontend
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
index 9da0d2829..277b70e53 100644
--- a/src/core/frontend/input.h
+++ b/src/core/frontend/input.h
@@ -33,6 +33,9 @@ public:
33 virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { 33 virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
34 return {}; 34 return {};
35 } 35 }
36 virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const {
37 return {};
38 }
36}; 39};
37 40
38/// An abstract class template for a factory that can create input devices. 41/// An abstract class template for a factory that can create input devices.
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 4e0800f9a..2b626bb40 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -206,7 +206,8 @@ void AppletManager::SetDefaultAppletFrontendSet() {
206 206
207void AppletManager::SetDefaultAppletsIfMissing() { 207void AppletManager::SetDefaultAppletsIfMissing() {
208 if (frontend.controller == nullptr) { 208 if (frontend.controller == nullptr) {
209 frontend.controller = std::make_unique<Core::Frontend::DefaultControllerApplet>(); 209 frontend.controller =
210 std::make_unique<Core::Frontend::DefaultControllerApplet>(system.ServiceManager());
210 } 211 }
211 212
212 if (frontend.e_commerce == nullptr) { 213 if (frontend.e_commerce == nullptr) {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index e34ee519e..a03af8df4 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -260,7 +260,7 @@ void Controller_NPad::OnRelease() {}
260 260
261void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { 261void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
262 const auto controller_idx = NPadIdToIndex(npad_id); 262 const auto controller_idx = NPadIdToIndex(npad_id);
263 [[maybe_unused]] const auto controller_type = connected_controllers[controller_idx].type; 263 const auto controller_type = connected_controllers[controller_idx].type;
264 if (!connected_controllers[controller_idx].is_connected) { 264 if (!connected_controllers[controller_idx].is_connected) {
265 return; 265 return;
266 } 266 }
@@ -276,54 +276,63 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
276 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus(); 276 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
277 277
278 using namespace Settings::NativeButton; 278 using namespace Settings::NativeButton;
279 pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); 279 if (controller_type != NPadControllerType::JoyLeft) {
280 pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); 280 pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
281 pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); 281 pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
282 pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); 282 pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
283 pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); 283 pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
284 pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); 284 pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
285 pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); 285 pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
286 pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); 286 pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
287 pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); 287 pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
288 pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); 288
289 pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); 289 pad_state.r_stick_right.Assign(
290 pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); 290 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
291 291 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
292 pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); 292 pad_state.r_stick_left.Assign(
293 pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); 293 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
294 pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); 294 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
295 pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); 295 pad_state.r_stick_up.Assign(
296 296 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
297 pad_state.l_stick_right.Assign( 297 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
298 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 298 pad_state.r_stick_down.Assign(
299 Input::AnalogDirection::RIGHT)); 299 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
300 pad_state.l_stick_left.Assign( 300 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
301 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 301 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
302 Input::AnalogDirection::LEFT)); 302 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
303 pad_state.l_stick_up.Assign( 303 }
304 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 304
305 Input::AnalogDirection::UP)); 305 if (controller_type != NPadControllerType::JoyRight) {
306 pad_state.l_stick_down.Assign( 306 pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
307 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 307 pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
308 Input::AnalogDirection::DOWN)); 308 pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
309 309 pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
310 pad_state.r_stick_right.Assign( 310 pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
311 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 311 pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
312 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); 312 pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
313 pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 313 pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
314 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); 314
315 pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 315 pad_state.l_stick_right.Assign(
316 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); 316 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
317 pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 317 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
318 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); 318 pad_state.l_stick_left.Assign(
319 319 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
320 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); 320 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
321 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); 321 pad_state.l_stick_up.Assign(
322 322 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
323 lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); 323 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
324 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); 324 pad_state.l_stick_down.Assign(
325 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); 325 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
326 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); 326 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
327 lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
328 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
329 }
330
331 if (controller_type == NPadControllerType::JoyLeft ||
332 controller_type == NPadControllerType::JoyRight) {
333 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
334 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
335 }
327} 336}
328 337
329void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 338void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
@@ -665,20 +674,31 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode)
665 } 674 }
666} 675}
667 676
668void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, 677void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
669 const std::vector<Vibration>& vibrations) { 678 const std::vector<Vibration>& vibrations) {
670 LOG_DEBUG(Service_HID, "(STUBBED) called"); 679 LOG_TRACE(Service_HID, "called");
671 680
672 if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { 681 if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
673 return; 682 return;
674 } 683 }
675 for (std::size_t i = 0; i < controller_ids.size(); i++) { 684 bool success = true;
676 std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i)); 685 for (std::size_t i = 0; i < controllers.size(); ++i) {
677 if (connected_controllers[controller_pos].is_connected) { 686 if (!connected_controllers[i].is_connected) {
678 // TODO(ogniK): Vibrate the physical controller 687 continue;
679 } 688 }
689 using namespace Settings::NativeButton;
690 const auto& button_state = buttons[i];
691 if (button_state[A - BUTTON_HID_BEGIN]) {
692 if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
693 vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high,
694 vibrations[0].freq_low)) {
695 success = false;
696 }
697 }
698 }
699 if (success) {
700 last_processed_vibration = vibrations.back();
680 } 701 }
681 last_processed_vibration = vibrations.back();
682} 702}
683 703
684Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { 704Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 0fa7455ba..e65277c7b 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -125,7 +125,7 @@ public:
125 125
126 void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); 126 void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
127 127
128 void VibrateController(const std::vector<u32>& controller_ids, 128 void VibrateController(const std::vector<u32>& controllers,
129 const std::vector<Vibration>& vibrations); 129 const std::vector<Vibration>& vibrations);
130 130
131 Vibration GetLastVibration() const; 131 Vibration GetLastVibration() const;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 9a7e5e265..001427fd8 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -188,7 +188,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
188 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"}, 188 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
189 {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"}, 189 {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
190 {68, nullptr, "IsSixAxisSensorFusionEnabled"}, 190 {68, nullptr, "IsSixAxisSensorFusionEnabled"},
191 {69, nullptr, "EnableSixAxisSensorFusion"}, 191 {69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
192 {70, nullptr, "SetSixAxisSensorFusionParameters"}, 192 {70, nullptr, "SetSixAxisSensorFusionParameters"},
193 {71, nullptr, "GetSixAxisSensorFusionParameters"}, 193 {71, nullptr, "GetSixAxisSensorFusionParameters"},
194 {72, nullptr, "ResetSixAxisSensorFusionParameters"}, 194 {72, nullptr, "ResetSixAxisSensorFusionParameters"},
@@ -473,6 +473,19 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
473 rb.Push(RESULT_SUCCESS); 473 rb.Push(RESULT_SUCCESS);
474} 474}
475 475
476void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
477 IPC::RequestParser rp{ctx};
478 const auto enable{rp.Pop<bool>()};
479 const auto handle{rp.Pop<u32>()};
480 const auto applet_resource_user_id{rp.Pop<u64>()};
481
482 LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
483 applet_resource_user_id);
484
485 IPC::ResponseBuilder rb{ctx, 2};
486 rb.Push(RESULT_SUCCESS);
487}
488
476void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 489void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
477 IPC::RequestParser rp{ctx}; 490 IPC::RequestParser rp{ctx};
478 const auto handle{rp.Pop<u32>()}; 491 const auto handle{rp.Pop<u32>()};
@@ -817,18 +830,18 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
817 830
818void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { 831void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
819 IPC::RequestParser rp{ctx}; 832 IPC::RequestParser rp{ctx};
820 const auto controller_id{rp.Pop<u32>()}; 833 const auto controller{rp.Pop<u32>()};
821 const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; 834 const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()};
822 const auto applet_resource_user_id{rp.Pop<u64>()}; 835 const auto applet_resource_user_id{rp.Pop<u64>()};
823 836
824 LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, 837 LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller,
825 applet_resource_user_id); 838 applet_resource_user_id);
826 839
827 IPC::ResponseBuilder rb{ctx, 2}; 840 IPC::ResponseBuilder rb{ctx, 2};
828 rb.Push(RESULT_SUCCESS); 841 rb.Push(RESULT_SUCCESS);
829 842
830 applet_resource->GetController<Controller_NPad>(HidController::NPad) 843 applet_resource->GetController<Controller_NPad>(HidController::NPad)
831 .VibrateController({controller_id}, {vibration_values}); 844 .VibrateController({controller}, {vibration_values});
832} 845}
833 846
834void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { 847void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
@@ -846,8 +859,6 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
846 859
847 std::memcpy(controller_list.data(), controllers.data(), controllers.size()); 860 std::memcpy(controller_list.data(), controllers.data(), controllers.size());
848 std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); 861 std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size());
849 std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(),
850 [](u32 controller_id) { return controller_id - 3; });
851 862
852 applet_resource->GetController<Controller_NPad>(HidController::NPad) 863 applet_resource->GetController<Controller_NPad>(HidController::NPad)
853 .VibrateController(controller_list, vibration_list); 864 .VibrateController(controller_list, vibration_list);
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 3cfd72a51..1c7d39b67 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -99,6 +99,7 @@ private:
99 void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); 99 void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
100 void StartSixAxisSensor(Kernel::HLERequestContext& ctx); 100 void StartSixAxisSensor(Kernel::HLERequestContext& ctx);
101 void StopSixAxisSensor(Kernel::HLERequestContext& ctx); 101 void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
102 void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx);
102 void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 103 void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
103 void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 104 void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
104 void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 105 void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index a9e676f4b..27a96c18b 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -5,6 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6#include <array> 6#include <array>
7#include <atomic> 7#include <atomic>
8#include <chrono>
8#include <cmath> 9#include <cmath>
9#include <functional> 10#include <functional>
10#include <mutex> 11#include <mutex>
@@ -78,6 +79,33 @@ public:
78 return state.axes.at(axis) / (32767.0f * range); 79 return state.axes.at(axis) / (32767.0f * range);
79 } 80 }
80 81
82 bool RumblePlay(f32 amp_low, f32 amp_high, int time) {
83 const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF);
84 const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF);
85 // Lower drastically the number of state changes
86 if (raw_amp_low >> 11 == last_state_rumble_low >> 11 &&
87 raw_amp_high >> 11 == last_state_rumble_high >> 11) {
88 if (raw_amp_low + raw_amp_high != 0 ||
89 last_state_rumble_low + last_state_rumble_high == 0) {
90 return false;
91 }
92 }
93 // Don't change state if last vibration was < 20ms
94 const auto now = std::chrono::system_clock::now();
95 if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) <
96 std::chrono::milliseconds(20)) {
97 return raw_amp_low + raw_amp_high == 0;
98 }
99
100 last_vibration = now;
101 last_state_rumble_low = raw_amp_low;
102 last_state_rumble_high = raw_amp_high;
103 if (sdl_joystick) {
104 SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time);
105 }
106 return false;
107 }
108
81 std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const { 109 std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const {
82 float x = GetAxis(axis_x, range); 110 float x = GetAxis(axis_x, range);
83 float y = GetAxis(axis_y, range); 111 float y = GetAxis(axis_y, range);
@@ -139,6 +167,9 @@ private:
139 } state; 167 } state;
140 std::string guid; 168 std::string guid;
141 int port; 169 int port;
170 u16 last_state_rumble_high;
171 u16 last_state_rumble_low;
172 std::chrono::time_point<std::chrono::system_clock> last_vibration;
142 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; 173 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
143 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; 174 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
144 mutable std::mutex mutex; 175 mutable std::mutex mutex;
@@ -207,7 +238,7 @@ void SDLState::InitJoystick(int joystick_index) {
207 sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); 238 sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
208 } 239 }
209 if (!sdl_joystick) { 240 if (!sdl_joystick) {
210 LOG_ERROR(Input, "failed to open joystick {}", joystick_index); 241 LOG_ERROR(Input, "Failed to open joystick {}", joystick_index);
211 return; 242 return;
212 } 243 }
213 const std::string guid = GetGUID(sdl_joystick); 244 const std::string guid = GetGUID(sdl_joystick);
@@ -303,6 +334,12 @@ public:
303 return joystick->GetButton(button); 334 return joystick->GetButton(button);
304 } 335 }
305 336
337 bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
338 const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f));
339 const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f));
340 return joystick->RumblePlay(new_amp_low, new_amp_high, 250);
341 }
342
306private: 343private:
307 std::shared_ptr<SDLJoystick> joystick; 344 std::shared_ptr<SDLJoystick> joystick;
308 int button; 345 int button;
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index 2b6a68d4b..cf72f6fef 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -274,18 +274,22 @@ void Client::Reset() {
274 274
275void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 275void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
276 const Common::Vec3<float>& gyro, bool touch) { 276 const Common::Vec3<float>& gyro, bool touch) {
277 if (gyro.Length() > 0.2f) {
278 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {}), touch={}",
279 client, gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2], touch);
280 }
277 UDPPadStatus pad; 281 UDPPadStatus pad;
278 if (touch) { 282 if (touch) {
279 pad.touch = PadTouch::Click; 283 pad.touch = PadTouch::Click;
280 pad_queue[client].Push(pad); 284 pad_queue[client].Push(pad);
281 } 285 }
282 for (size_t i = 0; i < 3; ++i) { 286 for (size_t i = 0; i < 3; ++i) {
283 if (gyro[i] > 6.0f || gyro[i] < -6.0f) { 287 if (gyro[i] > 5.0f || gyro[i] < -5.0f) {
284 pad.motion = static_cast<PadMotion>(i); 288 pad.motion = static_cast<PadMotion>(i);
285 pad.motion_value = gyro[i]; 289 pad.motion_value = gyro[i];
286 pad_queue[client].Push(pad); 290 pad_queue[client].Push(pad);
287 } 291 }
288 if (acc[i] > 2.0f || acc[i] < -2.0f) { 292 if (acc[i] > 1.75f || acc[i] < -1.75f) {
289 pad.motion = static_cast<PadMotion>(i + 3); 293 pad.motion = static_cast<PadMotion>(i + 3);
290 pad.motion_value = acc[i]; 294 pad.motion_value = acc[i];
291 pad_queue[client].Push(pad); 295 pad_queue[client].Push(pad);