summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/frontend/input.h3
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp25
-rw-r--r--src/core/hle/service/hid/controllers/npad.h2
-rw-r--r--src/core/hle/service/hid/hid.cpp8
-rw-r--r--src/input_common/sdl/sdl_impl.cpp39
5 files changed, 63 insertions, 14 deletions
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/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 620386cd1..83c3beab6 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -609,20 +609,31 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode)
609 } 609 }
610} 610}
611 611
612void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, 612void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
613 const std::vector<Vibration>& vibrations) { 613 const std::vector<Vibration>& vibrations) {
614 LOG_DEBUG(Service_HID, "(STUBBED) called"); 614 LOG_TRACE(Service_HID, "called");
615 615
616 if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { 616 if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
617 return; 617 return;
618 } 618 }
619 for (std::size_t i = 0; i < controller_ids.size(); i++) { 619 bool success = true;
620 std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i)); 620 for (std::size_t i = 0; i < controllers.size(); ++i) {
621 if (connected_controllers[controller_pos].is_connected) { 621 if (!connected_controllers[i].is_connected) {
622 // TODO(ogniK): Vibrate the physical controller 622 continue;
623 }
624 using namespace Settings::NativeButton;
625 const auto& button_state = buttons[i];
626 if (button_state[A - BUTTON_HID_BEGIN]) {
627 if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
628 vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high,
629 vibrations[0].freq_low)) {
630 success = false;
631 }
623 } 632 }
624 } 633 }
625 last_processed_vibration = vibrations.back(); 634 if (success) {
635 last_processed_vibration = vibrations.back();
636 }
626} 637}
627 638
628Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { 639Controller_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 654d97c3f..0cff6821f 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -121,7 +121,7 @@ public:
121 121
122 void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); 122 void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
123 123
124 void VibrateController(const std::vector<u32>& controller_ids, 124 void VibrateController(const std::vector<u32>& controllers,
125 const std::vector<Vibration>& vibrations); 125 const std::vector<Vibration>& vibrations);
126 126
127 Vibration GetLastVibration() const; 127 Vibration GetLastVibration() const;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 395e83b3f..dc198791d 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -802,18 +802,18 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
802 802
803void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { 803void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
804 IPC::RequestParser rp{ctx}; 804 IPC::RequestParser rp{ctx};
805 const auto controller_id{rp.Pop<u32>()}; 805 const auto controller{rp.Pop<u32>()};
806 const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; 806 const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()};
807 const auto applet_resource_user_id{rp.Pop<u64>()}; 807 const auto applet_resource_user_id{rp.Pop<u64>()};
808 808
809 LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, 809 LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller,
810 applet_resource_user_id); 810 applet_resource_user_id);
811 811
812 IPC::ResponseBuilder rb{ctx, 2}; 812 IPC::ResponseBuilder rb{ctx, 2};
813 rb.Push(RESULT_SUCCESS); 813 rb.Push(RESULT_SUCCESS);
814 814
815 applet_resource->GetController<Controller_NPad>(HidController::NPad) 815 applet_resource->GetController<Controller_NPad>(HidController::NPad)
816 .VibrateController({controller_id}, {vibration_values}); 816 .VibrateController({controller}, {vibration_values});
817} 817}
818 818
819void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { 819void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
@@ -831,8 +831,6 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
831 831
832 std::memcpy(controller_list.data(), controllers.data(), controllers.size()); 832 std::memcpy(controller_list.data(), controllers.data(), controllers.size());
833 std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); 833 std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size());
834 std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(),
835 [](u32 controller_id) { return controller_id - 3; });
836 834
837 applet_resource->GetController<Controller_NPad>(HidController::NPad) 835 applet_resource->GetController<Controller_NPad>(HidController::NPad)
838 .VibrateController(controller_list, vibration_list); 836 .VibrateController(controller_list, vibration_list);
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;