From abfebe5cc4d297f7dff160686decedc377079aa9 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 10 Dec 2023 14:53:19 -0600 Subject: service: hid: Improve CreateAppletResource implementation and free resources --- .../service/hid/controllers/applet_resource.cpp | 89 ++++++++++++++++++++++ .../hle/service/hid/controllers/applet_resource.h | 6 ++ src/core/hle/service/hid/errors.h | 3 + src/core/hle/service/hid/hid_server.cpp | 10 +-- src/core/hle/service/hid/resource_manager.cpp | 45 +++++++++-- src/core/hle/service/hid/resource_manager.h | 9 ++- 6 files changed, 149 insertions(+), 13 deletions(-) diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp index ee60d8b44..435b86233 100644 --- a/src/core/hle/service/hid/controllers/applet_resource.cpp +++ b/src/core/hle/service/hid/controllers/applet_resource.cpp @@ -112,6 +112,19 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { } } +void AppletResource::FreeAppletResourceId(u64 aruid) { + u64 index = GetIndexFromAruid(aruid); + if (index >= AruidIndexMax) { + return; + } + + auto& aruid_data = data[index]; + if (aruid_data.flag.is_assigned) { + aruid_data.shared_memory_handle = nullptr; + aruid_data.flag.is_assigned.Assign(false); + } +} + u64 AppletResource::GetActiveAruid() { return active_aruid; } @@ -196,4 +209,80 @@ void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) { data[index].flag.enable_palma_boost_mode.Assign(is_enabled); } +Result AppletResource::RegisterCoreAppletResource() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultAppletResourceOverflow; + } + if (ref_counter == 0) { + const u64 index = GetIndexFromAruid(0); + if (index < AruidIndexMax) { + return ResultAruidAlreadyRegistered; + } + + std::size_t data_index = AruidIndexMax; + for (std::size_t i = 0; i < AruidIndexMax; i++) { + if (!data[i].flag.is_initialized) { + data_index = i; + break; + } + } + + if (data_index == AruidIndexMax) { + return ResultAruidNoAvailableEntries; + } + + AruidData& aruid_data = data[data_index]; + + aruid_data.aruid = 0; + aruid_data.flag.is_initialized.Assign(true); + aruid_data.flag.enable_pad_input.Assign(true); + aruid_data.flag.enable_six_axis_sensor.Assign(true); + aruid_data.flag.bit_18.Assign(true); + aruid_data.flag.enable_touchscreen.Assign(true); + + data_index = AruidIndexMax; + for (std::size_t i = 0; i < AruidIndexMax; i++) { + if (registration_list.flag[i] == RegistrationStatus::Initialized) { + if (registration_list.aruid[i] != 0) { + continue; + } + data_index = i; + break; + } + if (registration_list.flag[i] == RegistrationStatus::None) { + data_index = i; + break; + } + } + + Result result = ResultSuccess; + + if (data_index == AruidIndexMax) { + result = CreateAppletResource(0); + } else { + registration_list.flag[data_index] = RegistrationStatus::Initialized; + registration_list.aruid[data_index] = 0; + } + + if (result.IsError()) { + UnregisterAppletResourceUserId(0); + return result; + } + } + ref_counter++; + return ResultSuccess; +} + +Result AppletResource::UnregisterCoreAppletResource() { + if (ref_counter == 0) { + return ResultAppletResourceNotInitialized; + } + + if (--ref_counter == 0) { + UnregisterAppletResourceUserId(0); + } + + return ResultSuccess; +} + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h index 3dcec2898..62137db13 100644 --- a/src/core/hle/service/hid/controllers/applet_resource.h +++ b/src/core/hle/service/hid/controllers/applet_resource.h @@ -28,6 +28,8 @@ public: Result RegisterAppletResourceUserId(u64 aruid, bool enable_input); void UnregisterAppletResourceUserId(u64 aruid); + void FreeAppletResourceId(u64 aruid); + u64 GetActiveAruid(); Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); @@ -42,6 +44,9 @@ public: void SetIsPalmaConnectable(u64 aruid, bool is_connectable); void EnablePalmaBoostMode(u64 aruid, bool is_enabled); + Result RegisterCoreAppletResource(); + Result UnregisterCoreAppletResource(); + private: static constexpr std::size_t AruidIndexMax = 0x20; @@ -81,6 +86,7 @@ private: u64 active_aruid{}; AruidRegisterList registration_list{}; std::array data{}; + s32 ref_counter{}; Core::System& system; }; diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index f00cb831f..6dc976fe1 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h @@ -20,6 +20,9 @@ constexpr Result InvalidNpadId{ErrorModule::HID, 709}; constexpr Result NpadNotConnected{ErrorModule::HID, 710}; constexpr Result InvalidArraySize{ErrorModule::HID, 715}; +constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041}; +constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042}; +constexpr Result ResultSharedMemoryNotInitialized{ErrorModule::HID, 1043}; constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044}; constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046}; constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047}; diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index e0f4051aa..b06ea467e 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -222,16 +222,14 @@ void IHidServer::CreateAppletResource(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - Result result = GetResourceManager()->CreateAppletResource(applet_resource_user_id); - if (result.IsSuccess()) { - result = GetResourceManager()->GetNpad()->Activate(applet_resource_user_id); - } + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", + applet_resource_user_id, result.raw); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(result); - rb.PushIpcInterface(system, resource_manager); + rb.PushIpcInterface(system, resource_manager, applet_resource_user_id); } void IHidServer::ActivateDebugPad(HLERequestContext& ctx) { diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp index 60d4ef71f..89cdc19cc 100644 --- a/src/core/hle/service/hid/resource_manager.cpp +++ b/src/core/hle/service/hid/resource_manager.cpp @@ -146,10 +146,36 @@ std::shared_ptr ResourceManager::GetUniquePad() const { } Result ResourceManager::CreateAppletResource(u64 aruid) { + if (aruid == 0) { + const auto result = RegisterCoreAppletResource(); + if (result.IsError()) { + return result; + } + return GetNpad()->Activate(); + } + + const auto result = CreateAppletResourceImpl(aruid); + if (result.IsError()) { + return result; + } + return GetNpad()->Activate(aruid); +} + +Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { std::scoped_lock lock{shared_mutex}; return applet_resource->CreateAppletResource(aruid); } +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}; return applet_resource->RegisterAppletResourceUserId(aruid, bool_value); @@ -165,6 +191,11 @@ Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle 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); @@ -219,8 +250,10 @@ void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose console_six_axis->OnUpdate(core_timing); } -IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr resource) - : ServiceFramework{system_, "IAppletResource"}, resource_manager{resource} { +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"}, }; @@ -274,14 +307,14 @@ IAppletResource::~IAppletResource() { system.CoreTiming().UnscheduleEvent(default_update_event, 0); system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0); + resource_manager->FreeAppletResourceId(aruid); } void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_HID, "called"); - Kernel::KSharedMemory* handle; - const u64 applet_resource_user_id = resource_manager->GetAppletResource()->GetActiveAruid(); - const auto result = resource_manager->GetSharedMemoryHandle(&handle, applet_resource_user_id); + 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); diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h index a78e2b729..15c1beb1a 100644 --- a/src/core/hle/service/hid/resource_manager.h +++ b/src/core/hle/service/hid/resource_manager.h @@ -66,10 +66,13 @@ public: Result CreateAppletResource(u64 aruid); + Result RegisterCoreAppletResource(); + Result UnregisterCoreAppletResource(); Result RegisterAppletResourceUserId(u64 aruid, bool bool_value); void UnregisterAppletResourceUserId(u64 aruid); Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); + void FreeAppletResourceId(u64 aruid); void EnableInput(u64 aruid, bool is_enabled); void EnableSixAxisSensor(u64 aruid, bool is_enabled); @@ -82,6 +85,8 @@ public: void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); private: + Result CreateAppletResourceImpl(u64 aruid); + bool is_initialized{false}; mutable std::mutex shared_mutex; @@ -121,7 +126,8 @@ private: class IAppletResource final : public ServiceFramework { public: - explicit IAppletResource(Core::System& system_, std::shared_ptr resource); + explicit IAppletResource(Core::System& system_, std::shared_ptr resource, + u64 applet_resource_user_id); ~IAppletResource() override; private: @@ -132,6 +138,7 @@ private: std::shared_ptr mouse_keyboard_update_event; std::shared_ptr motion_update_event; + u64 aruid; std::shared_ptr resource_manager; }; -- cgit v1.2.3