From ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 4 Jan 2024 20:37:43 -0600 Subject: hid_core: Move hid to it's own subproject --- src/hid_core/resource_manager.cpp | 362 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 src/hid_core/resource_manager.cpp (limited to 'src/hid_core/resource_manager.cpp') diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp new file mode 100644 index 000000000..17dacef6e --- /dev/null +++ b/src/hid_core/resource_manager.cpp @@ -0,0 +1,362 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/service/ipc_helpers.h" +#include "hid_core/hid_core.h" +#include "hid_core/resource_manager.h" + +#include "hid_core/resources/applet_resource.h" +#include "hid_core/resources/debug_pad/debug_pad.h" +#include "hid_core/resources/digitizer/digitizer.h" +#include "hid_core/resources/keyboard/keyboard.h" +#include "hid_core/resources/mouse/debug_mouse.h" +#include "hid_core/resources/mouse/mouse.h" +#include "hid_core/resources/npad/npad.h" +#include "hid_core/resources/palma/palma.h" +#include "hid_core/resources/shared_memory_format.h" +#include "hid_core/resources/six_axis/console_six_axis.h" +#include "hid_core/resources/six_axis/seven_six_axis.h" +#include "hid_core/resources/six_axis/six_axis.h" +#include "hid_core/resources/system_buttons/capture_button.h" +#include "hid_core/resources/system_buttons/home_button.h" +#include "hid_core/resources/system_buttons/sleep_button.h" +#include "hid_core/resources/touch_screen/gesture.h" +#include "hid_core/resources/touch_screen/touch_screen.h" +#include "hid_core/resources/unique_pad/unique_pad.h" + +namespace Service::HID { + +// Updating period for each HID device. +// Period time is obtained by measuring the number of samples in a second on HW using a homebrew +// Correct npad_update_ns is 4ms this is overclocked to lower input lag +constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) +constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) +constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) + +ResourceManager::ResourceManager(Core::System& system_) + : system{system_}, service_context{system_, "hid"} { + applet_resource = std::make_shared(system); +} + +ResourceManager::~ResourceManager() = default; + +void ResourceManager::Initialize() { + if (is_initialized) { + return; + } + + system.HIDCore().ReloadInputDevices(); + + InitializeHidCommonSampler(); + InitializeTouchScreenSampler(); + InitializeConsoleSixAxisSampler(); + InitializeAHidSampler(); + + is_initialized = true; +} + +std::shared_ptr ResourceManager::GetAppletResource() const { + return applet_resource; +} + +std::shared_ptr ResourceManager::GetCaptureButton() const { + return capture_button; +} + +std::shared_ptr ResourceManager::GetConsoleSixAxis() const { + return console_six_axis; +} + +std::shared_ptr ResourceManager::GetDebugMouse() const { + return debug_mouse; +} + +std::shared_ptr ResourceManager::GetDebugPad() const { + return debug_pad; +} + +std::shared_ptr ResourceManager::GetDigitizer() const { + return digitizer; +} + +std::shared_ptr ResourceManager::GetGesture() const { + return gesture; +} + +std::shared_ptr ResourceManager::GetHomeButton() const { + return home_button; +} + +std::shared_ptr ResourceManager::GetKeyboard() const { + return keyboard; +} + +std::shared_ptr ResourceManager::GetMouse() const { + return mouse; +} + +std::shared_ptr ResourceManager::GetNpad() const { + return npad; +} + +std::shared_ptr ResourceManager::GetPalma() const { + return palma; +} + +std::shared_ptr ResourceManager::GetSevenSixAxis() const { + return seven_six_axis; +} + +std::shared_ptr ResourceManager::GetSixAxis() const { + return six_axis; +} + +std::shared_ptr ResourceManager::GetSleepButton() const { + return sleep_button; +} + +std::shared_ptr ResourceManager::GetTouchScreen() const { + return touch_screen; +} + +std::shared_ptr ResourceManager::GetUniquePad() const { + return unique_pad; +} + +Result ResourceManager::CreateAppletResource(u64 aruid) { + if (aruid == SystemAruid) { + const auto result = RegisterCoreAppletResource(); + if (result.IsError()) { + return result; + } + return GetNpad()->ActivateNpadResource(); + } + + const auto result = CreateAppletResourceImpl(aruid); + if (result.IsError()) { + return result; + } + + // Homebrew doesn't try to activate some controllers, so we activate them by default + npad->Activate(); + six_axis->Activate(); + touch_screen->Activate(); + + return GetNpad()->ActivateNpadResource(aruid); +} + +Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { + std::scoped_lock lock{shared_mutex}; + return applet_resource->CreateAppletResource(aruid); +} + +void ResourceManager::InitializeHidCommonSampler() { + debug_pad = std::make_shared(system.HIDCore()); + mouse = std::make_shared(system.HIDCore()); + debug_mouse = std::make_shared(system.HIDCore()); + keyboard = std::make_shared(system.HIDCore()); + unique_pad = std::make_shared(system.HIDCore()); + npad = std::make_shared(system.HIDCore(), service_context); + gesture = std::make_shared(system.HIDCore()); + home_button = std::make_shared(system.HIDCore()); + sleep_button = std::make_shared(system.HIDCore()); + capture_button = std::make_shared(system.HIDCore()); + digitizer = std::make_shared(system.HIDCore()); + + palma = std::make_shared(system.HIDCore(), service_context); + six_axis = std::make_shared(system.HIDCore(), npad); + + debug_pad->SetAppletResource(applet_resource, &shared_mutex); + digitizer->SetAppletResource(applet_resource, &shared_mutex); + keyboard->SetAppletResource(applet_resource, &shared_mutex); + npad->SetNpadExternals(applet_resource, &shared_mutex); + six_axis->SetAppletResource(applet_resource, &shared_mutex); + mouse->SetAppletResource(applet_resource, &shared_mutex); + debug_mouse->SetAppletResource(applet_resource, &shared_mutex); + home_button->SetAppletResource(applet_resource, &shared_mutex); + sleep_button->SetAppletResource(applet_resource, &shared_mutex); + capture_button->SetAppletResource(applet_resource, &shared_mutex); +} + +void ResourceManager::InitializeTouchScreenSampler() { + gesture = std::make_shared(system.HIDCore()); + touch_screen = std::make_shared(system.HIDCore()); + + touch_screen->SetAppletResource(applet_resource, &shared_mutex); + gesture->SetAppletResource(applet_resource, &shared_mutex); +} + +void ResourceManager::InitializeConsoleSixAxisSampler() { + console_six_axis = std::make_shared(system.HIDCore()); + seven_six_axis = std::make_shared(system); + + console_six_axis->SetAppletResource(applet_resource, &shared_mutex); +} + +void ResourceManager::InitializeAHidSampler() { + // TODO +} + +Result ResourceManager::RegisterCoreAppletResource() { + std::scoped_lock lock{shared_mutex}; + return applet_resource->RegisterCoreAppletResource(); +} + +Result ResourceManager::UnregisterCoreAppletResource() { + std::scoped_lock lock{shared_mutex}; + return applet_resource->UnregisterCoreAppletResource(); +} + +Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) { + std::scoped_lock lock{shared_mutex}; + auto result = applet_resource->RegisterAppletResourceUserId(aruid, bool_value); + if (result.IsSuccess()) { + result = npad->RegisterAppletResourceUserId(aruid); + } + return result; +} + +void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) { + std::scoped_lock lock{shared_mutex}; + applet_resource->UnregisterAppletResourceUserId(aruid); +} + +Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { + std::scoped_lock lock{shared_mutex}; + return applet_resource->GetSharedMemoryHandle(out_handle, aruid); +} + +void ResourceManager::FreeAppletResourceId(u64 aruid) { + std::scoped_lock lock{shared_mutex}; + applet_resource->FreeAppletResourceId(aruid); +} + +void ResourceManager::EnableInput(u64 aruid, bool is_enabled) { + std::scoped_lock lock{shared_mutex}; + applet_resource->EnableInput(aruid, is_enabled); +} + +void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) { + std::scoped_lock lock{shared_mutex}; + applet_resource->EnableSixAxisSensor(aruid, is_enabled); +} + +void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) { + std::scoped_lock lock{shared_mutex}; + applet_resource->EnablePadInput(aruid, is_enabled); +} + +void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { + std::scoped_lock lock{shared_mutex}; + applet_resource->EnableTouchScreen(aruid, is_enabled); +} + +void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + debug_pad->OnUpdate(core_timing); + digitizer->OnUpdate(core_timing); + unique_pad->OnUpdate(core_timing); + gesture->OnUpdate(core_timing); + touch_screen->OnUpdate(core_timing); + palma->OnUpdate(core_timing); + home_button->OnUpdate(core_timing); + sleep_button->OnUpdate(core_timing); + capture_button->OnUpdate(core_timing); +} + +void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + npad->OnUpdate(core_timing); +} + +void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + mouse->OnUpdate(core_timing); + debug_mouse->OnUpdate(core_timing); + keyboard->OnUpdate(core_timing); +} + +void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + six_axis->OnUpdate(core_timing); + seven_six_axis->OnUpdate(core_timing); + console_six_axis->OnUpdate(core_timing); +} + +IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr resource, + u64 applet_resource_user_id) + : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id}, + resource_manager{resource} { + static const FunctionInfo functions[] = { + {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, + }; + RegisterHandlers(functions); + + // Register update callbacks + npad_update_event = Core::Timing::CreateEvent( + "HID::UpdatePadCallback", + [this, resource]( + s64 time, std::chrono::nanoseconds ns_late) -> std::optional { + const auto guard = LockService(); + resource->UpdateNpad(ns_late); + return std::nullopt; + }); + default_update_event = Core::Timing::CreateEvent( + "HID::UpdateDefaultCallback", + [this, resource]( + s64 time, std::chrono::nanoseconds ns_late) -> std::optional { + const auto guard = LockService(); + resource->UpdateControllers(ns_late); + return std::nullopt; + }); + mouse_keyboard_update_event = Core::Timing::CreateEvent( + "HID::UpdateMouseKeyboardCallback", + [this, resource]( + s64 time, std::chrono::nanoseconds ns_late) -> std::optional { + const auto guard = LockService(); + resource->UpdateMouseKeyboard(ns_late); + return std::nullopt; + }); + motion_update_event = Core::Timing::CreateEvent( + "HID::UpdateMotionCallback", + [this, resource]( + s64 time, std::chrono::nanoseconds ns_late) -> std::optional { + const auto guard = LockService(); + resource->UpdateMotion(ns_late); + return std::nullopt; + }); + + system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event); + system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns, + default_update_event); + system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, + mouse_keyboard_update_event); + system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, + motion_update_event); +} + +IAppletResource::~IAppletResource() { + system.CoreTiming().UnscheduleEvent(npad_update_event); + system.CoreTiming().UnscheduleEvent(default_update_event); + system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event); + system.CoreTiming().UnscheduleEvent(motion_update_event); + resource_manager->FreeAppletResourceId(aruid); +} + +void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { + Kernel::KSharedMemory* handle; + const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(result); + rb.PushCopyObjects(handle); +} + +} // namespace Service::HID -- cgit v1.2.3