From 2cacb9d48c98603176e52ecc94f2374a934797fb Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Wed, 10 Jan 2024 22:06:54 -0600 Subject: service: hid: Fully implement abstract vibration --- src/hid_core/resources/npad/npad.cpp | 292 +++++++++++++---------------------- 1 file changed, 106 insertions(+), 186 deletions(-) (limited to 'src/hid_core/resources/npad/npad.cpp') diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 97537a2e2..310fa8ba7 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -21,6 +21,7 @@ #include "hid_core/hid_util.h" #include "hid_core/resources/applet_resource.h" #include "hid_core/resources/npad/npad.h" +#include "hid_core/resources/npad/npad_vibration.h" #include "hid_core/resources/shared_memory_format.h" namespace Service::HID { @@ -31,10 +32,6 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { auto& controller = controller_data[aruid_index][i]; controller.device = hid_core.GetEmulatedControllerByIndex(i); - controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] - .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, @@ -43,6 +40,10 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service controller.callback_key = controller.device->SetCallback(engine_callback); } } + for (std::size_t i = 0; i < abstracted_pads.size(); ++i) { + abstracted_pads[i] = AbstractPad{}; + abstracted_pads[i].SetNpadId(IndexToNpadIdType(i)); + } } NPad::~NPad() { @@ -359,6 +360,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); WriteEmptyEntry(controller.shared_memory); hid_core.SetLastActiveController(npad_id); + abstracted_pads[NpadIdTypeToIndex(npad_id)].Update(); } void NPad::WriteEmptyEntry(NpadInternalState* npad) { @@ -740,171 +742,6 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID: return true; } -bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index, - const Core::HID::VibrationValue& vibration_value) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!controller.device->IsConnected()) { - return false; - } - - if (!controller.device->IsVibrationEnabled(device_index)) { - if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || - controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { - // Send an empty vibration to stop any vibrations. - Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; - controller.device->SetVibration(device_index, vibration); - // Then reset the vibration value to its default value. - controller.vibration[device_index].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - } - - return false; - } - - if (!Settings::values.enable_accurate_vibrations.GetValue()) { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::steady_clock; - - const auto now = steady_clock::now(); - - // Filter out non-zero vibrations that are within 15ms of each other. - if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && - duration_cast( - now - controller.vibration[device_index].last_vibration_timepoint) < - milliseconds(15)) { - return false; - } - - controller.vibration[device_index].last_vibration_timepoint = now; - } - - Core::HID::VibrationValue vibration{ - vibration_value.low_amplitude, vibration_value.low_frequency, - vibration_value.high_amplitude, vibration_value.high_frequency}; - return controller.device->SetVibration(device_index, vibration); -} - -void NPad::VibrateController(u64 aruid, - const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - - if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { - return; - } - - if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { - ASSERT_MSG(false, "DeviceIndex should never be None!"); - return; - } - - // Some games try to send mismatched parameters in the device handle, block these. - if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || - (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { - return; - } - - // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_value.low_amplitude == - controller.vibration[device_index].latest_vibration_value.low_amplitude && - vibration_value.high_amplitude == - controller.vibration[device_index].latest_vibration_value.high_amplitude) { - return; - } - - if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, - vibration_value)) { - controller.vibration[device_index].latest_vibration_value = vibration_value; - } -} - -void NPad::VibrateControllers( - u64 aruid, std::span vibration_device_handles, - std::span vibration_values) { - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - ASSERT_OR_EXECUTE_MSG( - vibration_device_handles.size() == vibration_values.size(), { return; }, - "The amount of device handles does not match with the amount of vibration values," - "this is undefined behavior!"); - - for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { - VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); - } -} - -Core::HID::VibrationValue NPad::GetLastVibration( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return {}; - } - - const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - return controller.vibration[device_index].latest_vibration_value; -} - -void NPad::InitializeVibrationDevice( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); - const auto npad_index = static_cast(vibration_device_handle.npad_id); - const auto device_index = static_cast(vibration_device_handle.device_index); - - if (aruid == 0) { - return; - } - - InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); -} - -void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!Settings::values.vibration_enabled.GetValue()) { - controller.vibration[device_index].device_mounted = false; - return; - } - - controller.vibration[device_index].device_mounted = - controller.device->IsVibrationEnabled(device_index); -} - -void NPad::SetPermitVibrationSession(bool permit_vibration_session) { - permit_vibration_session_enabled = permit_vibration_session; -} - -bool NPad::IsVibrationDeviceMounted( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return false; - } - - const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - return controller.vibration[device_index].device_mounted; -} - Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id) { std::scoped_lock lock{mutex}; @@ -936,11 +773,6 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { - // Send an empty vibration to stop any vibrations. - VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); - controller.vibration[device_idx].device_mounted = false; - } auto* shared_memory = controller.shared_memory; // Don't reset shared_memory->assignment_mode this value is persistent @@ -1236,22 +1068,17 @@ void NPad::UnregisterAppletResourceUserId(u64 aruid) { } void NPad::SetNpadExternals(std::shared_ptr resource, - std::recursive_mutex* shared_mutex) { + std::recursive_mutex* shared_mutex, + std::shared_ptr handheld_config) { applet_resource_holder.applet_resource = resource; applet_resource_holder.shared_mutex = shared_mutex; applet_resource_holder.shared_npad_resource = &npad_resource; -} + applet_resource_holder.handheld_config = handheld_config; -NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); -} - -const NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); + for (auto& abstract_pad : abstracted_pads) { + abstract_pad.SetExternals(&applet_resource_holder, nullptr, nullptr, nullptr, nullptr, + &vibration_handler, &hid_core); + } } NPad::NpadControllerData& NPad::GetControllerFromHandle( @@ -1389,4 +1216,97 @@ Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const { return ResultSuccess; } +NpadVibration* NPad::GetVibrationHandler() { + return &vibration_handler; +} + +std::vector NPad::GetAllVibrationDevices() { + std::vector vibration_devices; + + for (auto& abstract_pad : abstracted_pads) { + auto* left_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Left); + auto* right_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Right); + auto* n64_device = abstract_pad.GetGCVibrationDevice(); + auto* gc_device = abstract_pad.GetGCVibrationDevice(); + + if (left_device != nullptr) { + vibration_devices.emplace_back(left_device); + } + if (right_device != nullptr) { + vibration_devices.emplace_back(right_device); + } + if (n64_device != nullptr) { + vibration_devices.emplace_back(n64_device); + } + if (gc_device != nullptr) { + vibration_devices.emplace_back(gc_device); + } + } + + return vibration_devices; +} + +NpadVibrationBase* NPad::GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde == Core::HID::NpadStyleIndex::GameCube) { + return abstracted_pads[npad_index].GetGCVibrationDevice(); + } + if (style_inde == Core::HID::NpadStyleIndex::N64) { + return abstracted_pads[npad_index].GetN64VibrationDevice(); + } + return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); +} + +NpadN64VibrationDevice* NPad::GetN64VibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde != Core::HID::NpadStyleIndex::N64) { + return nullptr; + } + return abstracted_pads[npad_index].GetN64VibrationDevice(); +} + +NpadVibrationDevice* NPad::GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde == Core::HID::NpadStyleIndex::GameCube || + style_inde == Core::HID::NpadStyleIndex::N64) { + return nullptr; + } + + return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); +} + +NpadGcVibrationDevice* NPad::GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde != Core::HID::NpadStyleIndex::GameCube) { + return nullptr; + } + return abstracted_pads[npad_index].GetGCVibrationDevice(); +} + +void NPad::UpdateHandheldAbstractState() { + std::scoped_lock lock{mutex}; + abstracted_pads[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update(); +} + } // namespace Service::HID -- cgit v1.2.3