summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Morph2020-10-07 14:22:47 -0400
committerGravatar Morph2020-11-15 23:33:20 -0500
commit07b81f57babcc7aa41fddfc892148688e841d96e (patch)
tree1fc825c5a8e9b93ee1384f4713b3379ec4218931 /src
parenthid: Pop a struct of parameters instead of popping individual parameters (diff)
downloadyuzu-07b81f57babcc7aa41fddfc892148688e841d96e.tar.gz
yuzu-07b81f57babcc7aa41fddfc892148688e841d96e.tar.xz
yuzu-07b81f57babcc7aa41fddfc892148688e841d96e.zip
hid: Fix controller rumble based on new research
This fixes the issue where rumble is only sent to the first controller. Now, individual controllers can receive their own rumble commands.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp45
-rw-r--r--src/core/hle/service/hid/controllers/npad.h12
-rw-r--r--src/core/hle/service/hid/hid.cpp55
3 files changed, 69 insertions, 43 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index b330c5e40..8a5e5abcf 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -667,35 +667,44 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode)
667 } 667 }
668} 668}
669 669
670void Controller_NPad::VibrateController(const std::vector<u32>& controllers, 670void Controller_NPad::VibrateController(const std::vector<DeviceHandle>& vibration_device_handles,
671 const std::vector<Vibration>& vibrations) { 671 const std::vector<VibrationValue>& vibration_values) {
672 LOG_TRACE(Service_HID, "called"); 672 LOG_TRACE(Service_HID, "called");
673 673
674 if (!Settings::values.vibration_enabled.GetValue() || !can_controllers_vibrate) { 674 if (!Settings::values.vibration_enabled.GetValue() || !can_controllers_vibrate) {
675 return; 675 return;
676 } 676 }
677 bool success = true; 677
678 for (std::size_t i = 0; i < controllers.size(); ++i) { 678 ASSERT_MSG(vibration_device_handles.size() == vibration_values.size(),
679 if (!connected_controllers[i].is_connected) { 679 "The amount of device handles does not match with the amount of vibration values,"
680 "this is undefined behavior!");
681
682 for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
683 const auto npad_index = NPadIdToIndex(vibration_device_handles[i].npad_id);
684 const auto device_index =
685 static_cast<std::size_t>(vibration_device_handles[i].device_index);
686
687 if (!connected_controllers[npad_index].is_connected) {
680 continue; 688 continue;
681 } 689 }
690
682 using namespace Settings::NativeButton; 691 using namespace Settings::NativeButton;
683 const auto& button_state = buttons[i]; 692 const auto& button_state = buttons[npad_index];
684 if (button_state[A - BUTTON_HID_BEGIN]) { 693
685 if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( 694 // TODO: Vibrate left/right vibration motors independently if possible.
686 vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high, 695 button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
687 vibrations[0].freq_low)) { 696 vibration_values[i].amp_high, vibration_values[i].amp_low,
688 success = false; 697 vibration_values[i].freq_high, vibration_values[i].freq_low);
689 } 698
690 } 699 latest_vibration_values[npad_index][device_index] = vibration_values[i];
691 }
692 if (success) {
693 last_processed_vibration = vibrations.back();
694 } 700 }
695} 701}
696 702
697Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { 703Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
698 return last_processed_vibration; 704 const DeviceHandle& vibration_device_handle) const {
705 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
706 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
707 return latest_vibration_values[npad_index][device_index];
699} 708}
700 709
701std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { 710std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 35dd2bf5f..c1b19103a 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -109,13 +109,13 @@ public:
109 }; 109 };
110 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); 110 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
111 111
112 struct Vibration { 112 struct VibrationValue {
113 f32 amp_low; 113 f32 amp_low;
114 f32 freq_low; 114 f32 freq_low;
115 f32 amp_high; 115 f32 amp_high;
116 f32 freq_high; 116 f32 freq_high;
117 }; 117 };
118 static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); 118 static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
119 119
120 struct LedPattern { 120 struct LedPattern {
121 explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { 121 explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
@@ -148,10 +148,10 @@ public:
148 148
149 void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); 149 void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode);
150 150
151 void VibrateController(const std::vector<u32>& controllers, 151 void VibrateController(const std::vector<DeviceHandle>& vibration_device_handles,
152 const std::vector<Vibration>& vibrations); 152 const std::vector<VibrationValue>& vibration_values);
153 153
154 Vibration GetLastVibration() const; 154 VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const;
155 155
156 std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; 156 std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
157 void SignalStyleSetChangedEvent(u32 npad_id) const; 157 void SignalStyleSetChangedEvent(u32 npad_id) const;
@@ -410,7 +410,7 @@ private:
410 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; 410 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
411 // Each controller should have their own styleset changed event 411 // Each controller should have their own styleset changed event
412 std::array<Kernel::EventPair, 10> styleset_changed_events; 412 std::array<Kernel::EventPair, 10> styleset_changed_events;
413 Vibration last_processed_vibration{}; 413 std::array<std::array<VibrationValue, 3>, 10> latest_vibration_values;
414 std::array<ControllerHolder, 10> connected_controllers{}; 414 std::array<ControllerHolder, 10> connected_controllers{};
415 std::array<bool, 10> unintended_home_button_input_protection{}; 415 std::array<bool, 10> unintended_home_button_input_protection{};
416 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; 416 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index fdac598f0..b0390bdb2 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1012,15 +1012,23 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1012 1012
1013void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { 1013void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
1014 IPC::RequestParser rp{ctx}; 1014 IPC::RequestParser rp{ctx};
1015 const auto controller{rp.Pop<u32>()}; 1015 struct Parameters {
1016 const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; 1016 Controller_NPad::DeviceHandle vibration_device_handle{};
1017 const auto applet_resource_user_id{rp.Pop<u64>()}; 1017 Controller_NPad::VibrationValue vibration_value{};
1018 INSERT_PADDING_WORDS(1);
1019 u64 applet_resource_user_id{};
1020 };
1021
1022 const auto parameters{rp.PopRaw<Parameters>()};
1018 1023
1019 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1024 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1020 .VibrateController({controller}, {vibration_values}); 1025 .VibrateController({parameters.vibration_device_handle}, {parameters.vibration_value});
1021 1026
1022 LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, 1027 LOG_DEBUG(Service_HID,
1023 applet_resource_user_id); 1028 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1029 parameters.vibration_device_handle.npad_type,
1030 parameters.vibration_device_handle.npad_id,
1031 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1024 1032
1025 IPC::ResponseBuilder rb{ctx, 2}; 1033 IPC::ResponseBuilder rb{ctx, 2};
1026 rb.Push(RESULT_SUCCESS); 1034 rb.Push(RESULT_SUCCESS);
@@ -1028,16 +1036,24 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
1028 1036
1029void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { 1037void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
1030 IPC::RequestParser rp{ctx}; 1038 IPC::RequestParser rp{ctx};
1031 const auto controller_id{rp.Pop<u32>()}; 1039 struct Parameters {
1032 const auto applet_resource_user_id{rp.Pop<u64>()}; 1040 Controller_NPad::DeviceHandle vibration_device_handle{};
1041 INSERT_PADDING_WORDS(1);
1042 u64 applet_resource_user_id{};
1043 };
1033 1044
1034 LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, 1045 const auto parameters{rp.PopRaw<Parameters>()};
1035 applet_resource_user_id); 1046
1047 LOG_DEBUG(Service_HID,
1048 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1049 parameters.vibration_device_handle.npad_type,
1050 parameters.vibration_device_handle.npad_id,
1051 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1036 1052
1037 IPC::ResponseBuilder rb{ctx, 6}; 1053 IPC::ResponseBuilder rb{ctx, 6};
1038 rb.Push(RESULT_SUCCESS); 1054 rb.Push(RESULT_SUCCESS);
1039 rb.PushRaw( 1055 rb.PushRaw(applet_resource->GetController<Controller_NPad>(HidController::NPad)
1040 applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); 1056 .GetLastVibration(parameters.vibration_device_handle));
1041} 1057}
1042 1058
1043void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { 1059void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
@@ -1072,18 +1088,19 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
1072 IPC::RequestParser rp{ctx}; 1088 IPC::RequestParser rp{ctx};
1073 const auto applet_resource_user_id{rp.Pop<u64>()}; 1089 const auto applet_resource_user_id{rp.Pop<u64>()};
1074 1090
1075 const auto controllers = ctx.ReadBuffer(0); 1091 const auto handles = ctx.ReadBuffer(0);
1076 const auto vibrations = ctx.ReadBuffer(1); 1092 const auto vibrations = ctx.ReadBuffer(1);
1077 1093
1078 std::vector<u32> controller_list(controllers.size() / sizeof(u32)); 1094 std::vector<Controller_NPad::DeviceHandle> vibration_device_handles(
1079 std::vector<Controller_NPad::Vibration> vibration_list(vibrations.size() / 1095 handles.size() / sizeof(Controller_NPad::DeviceHandle));
1080 sizeof(Controller_NPad::Vibration)); 1096 std::vector<Controller_NPad::VibrationValue> vibration_values(
1097 vibrations.size() / sizeof(Controller_NPad::VibrationValue));
1081 1098
1082 std::memcpy(controller_list.data(), controllers.data(), controllers.size()); 1099 std::memcpy(vibration_device_handles.data(), handles.data(), handles.size());
1083 std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); 1100 std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size());
1084 1101
1085 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1102 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1086 .VibrateController(controller_list, vibration_list); 1103 .VibrateController(vibration_device_handles, vibration_values);
1087 1104
1088 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1105 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1089 1106