diff options
| author | 2020-10-07 14:22:47 -0400 | |
|---|---|---|
| committer | 2020-11-15 23:33:20 -0500 | |
| commit | 07b81f57babcc7aa41fddfc892148688e841d96e (patch) | |
| tree | 1fc825c5a8e9b93ee1384f4713b3379ec4218931 | |
| parent | hid: Pop a struct of parameters instead of popping individual parameters (diff) | |
| download | yuzu-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.
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 45 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 55 |
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 | ||
| 670 | void Controller_NPad::VibrateController(const std::vector<u32>& controllers, | 670 | void 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 | ||
| 697 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | 703 | Controller_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 | ||
| 701 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 710 | std::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 | ||
| 1013 | void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | 1013 | void 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 | ||
| 1029 | void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { | 1037 | void 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 | ||
| 1043 | void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | 1059 | void 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 | ||