diff options
Diffstat (limited to 'src/core/hle/service')
345 files changed, 10501 insertions, 7237 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 6d1084fd1..6c29cb613 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -15,7 +15,6 @@ #include "core/core_timing.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/acc/acc.h" #include "core/hle/service/acc/acc_aa.h" #include "core/hle/service/acc/acc_su.h" @@ -25,16 +24,12 @@ #include "core/hle/service/acc/errors.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/glue/glue_manager.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/loader/loader.h" namespace Service::Account { -constexpr Result ERR_INVALID_USER_ID{ErrorModule::Account, 20}; -constexpr Result ERR_INVALID_APPLICATION_ID{ErrorModule::Account, 22}; -constexpr Result ERR_INVALID_BUFFER{ErrorModule::Account, 30}; -constexpr Result ERR_INVALID_BUFFER_SIZE{ErrorModule::Account, 31}; -constexpr Result ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100}; - // Thumbnails are hard coded to be at least this size constexpr std::size_t THUMBNAIL_SIZE = 0x24000; @@ -76,6 +71,8 @@ public: {141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+ {142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+ {150, nullptr, "CreateAuthorizationRequest"}, + {160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"}, + {161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"}, }; // clang-format on @@ -136,7 +133,10 @@ public: {140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+ {141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+ {142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+ + {143, nullptr, "GetNetworkServiceLicenseCacheEx"}, {150, nullptr, "CreateAuthorizationRequest"}, + {160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"}, + {161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"}, {200, nullptr, "IsRegistered"}, {201, nullptr, "RegisterAsync"}, {202, nullptr, "UnregisterAsync"}, @@ -242,6 +242,7 @@ public: {100, nullptr, "GetRequestWithTheme"}, {101, nullptr, "IsNetworkServiceAccountReplaced"}, {199, nullptr, "GetUrlForIntroductionOfExtraMembership"}, // 2.0.0 - 5.1.0 + {200, nullptr, "ApplyAsyncWithAuthorizedToken"}, }; // clang-format on @@ -288,7 +289,7 @@ public: } protected: - void Get(Kernel::HLERequestContext& ctx) { + void Get(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString()); ProfileBase profile_base{}; UserData data{}; @@ -305,7 +306,7 @@ protected: } } - void GetBase(Kernel::HLERequestContext& ctx) { + void GetBase(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString()); ProfileBase profile_base{}; if (profile_manager.GetProfileBase(user_id, profile_base)) { @@ -319,7 +320,7 @@ protected: } } - void LoadImage(Kernel::HLERequestContext& ctx) { + void LoadImage(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -346,7 +347,7 @@ protected: rb.Push<u32>(size); } - void GetImageSize(Kernel::HLERequestContext& ctx) { + void GetImageSize(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -363,7 +364,7 @@ protected: } } - void Store(Kernel::HLERequestContext& ctx) { + void Store(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto base = rp.PopRaw<ProfileBase>(); @@ -377,7 +378,7 @@ protected: if (user_data.size() < sizeof(UserData)) { LOG_ERROR(Service_ACC, "UserData buffer too small!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_BUFFER); + rb.Push(Account::ResultInvalidArrayLength); return; } @@ -387,7 +388,7 @@ protected: if (!profile_manager.SetProfileBaseAndData(user_id, base, data)) { LOG_ERROR(Service_ACC, "Failed to update user data and base!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_FAILED_SAVE_DATA); + rb.Push(Account::ResultAccountUpdateFailed); return; } @@ -395,7 +396,7 @@ protected: rb.Push(ResultSuccess); } - void StoreWithImage(Kernel::HLERequestContext& ctx) { + void StoreWithImage(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto base = rp.PopRaw<ProfileBase>(); @@ -410,7 +411,7 @@ protected: if (user_data.size() < sizeof(UserData)) { LOG_ERROR(Service_ACC, "UserData buffer too small!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_BUFFER); + rb.Push(Account::ResultInvalidArrayLength); return; } @@ -425,7 +426,7 @@ protected: !profile_manager.SetProfileBaseAndData(user_id, base, data)) { LOG_ERROR(Service_ACC, "Failed to update profile data, base, and image!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_FAILED_SAVE_DATA); + rb.Push(Account::ResultAccountUpdateFailed); return; } @@ -492,7 +493,7 @@ public: } ~EnsureTokenIdCacheAsyncInterface() = default; - void LoadIdTokenCache(Kernel::HLERequestContext& ctx) { + void LoadIdTokenCache(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -535,14 +536,14 @@ public: } private: - void CheckAvailability(Kernel::HLERequestContext& ctx) { + void CheckAvailability(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(false); // TODO: Check when this is supposed to return true and when not } - void GetAccountId(Kernel::HLERequestContext& ctx) { + void GetAccountId(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -550,7 +551,7 @@ private: rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash()); } - void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) { + void EnsureIdTokenCacheAsync(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -558,13 +559,13 @@ private: rb.PushIpcInterface(ensure_token_id); } - void LoadIdTokenCache(Kernel::HLERequestContext& ctx) { + void LoadIdTokenCache(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); ensure_token_id->LoadIdTokenCache(ctx); } - void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) { + void GetNintendoAccountUserResourceCacheForApplication(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); std::vector<u8> nas_user_base_for_application(0x68); @@ -580,7 +581,7 @@ private: rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash()); } - void StoreOpenContext(Kernel::HLERequestContext& ctx) { + void StoreOpenContext(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); profile_manager->StoreOpenedUsers(); @@ -647,9 +648,11 @@ public: {0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, {1, nullptr, "LoadAuthenticationTokenCache"}, {2, nullptr, "InvalidateAuthenticationTokenCache"}, + {3, nullptr, "IsDeviceAuthenticationTokenCacheAvailable"}, {10, nullptr, "EnsureEdgeTokenCacheAsync"}, {11, nullptr, "LoadEdgeTokenCache"}, {12, nullptr, "InvalidateEdgeTokenCache"}, + {13, nullptr, "IsEdgeTokenCacheAvailable"}, {20, nullptr, "EnsureApplicationAuthenticationCacheAsync"}, {21, nullptr, "LoadApplicationAuthenticationTokenCache"}, {22, nullptr, "LoadApplicationNetworkServiceClientConfigCache"}, @@ -680,14 +683,14 @@ public: } }; -void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetUserCount(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push<u32>(static_cast<u32>(profile_manager->GetUserCount())); } -void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetUserExistence(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; Common::UUID user_id = rp.PopRaw<Common::UUID>(); LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString()); @@ -697,28 +700,28 @@ void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { rb.Push(profile_manager->UserExists(user_id)); } -void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) { +void Module::Interface::ListAllUsers(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); ctx.WriteBuffer(profile_manager->GetAllUsers()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) { +void Module::Interface::ListOpenUsers(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); ctx.WriteBuffer(profile_manager->GetOpenUsers()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetLastOpenedUser(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); rb.PushRaw<Common::UUID>(profile_manager->GetLastOpenedUser()); } -void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetProfile(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; Common::UUID user_id = rp.PopRaw<Common::UUID>(); LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString()); @@ -728,20 +731,20 @@ void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IProfile>(system, user_id, *profile_manager); } -void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx) { +void Module::Interface::IsUserRegistrationRequestPermitted(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(profile_manager->CanSystemRegisterUser()); } -void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { +void Module::Interface::InitializeApplicationInfo(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(InitializeApplicationInfoBase()); } -void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx) { +void Module::Interface::InitializeApplicationInfoRestricted(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(Partial implementation) called"); // TODO(ogniK): We require checking if the user actually owns the title and what not. As of @@ -755,18 +758,18 @@ void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestCo Result Module::Interface::InitializeApplicationInfoBase() { if (application_info) { LOG_ERROR(Service_ACC, "Application already initialized"); - return ERR_ACCOUNTINFO_ALREADY_INITIALIZED; + return Account::ResultApplicationInfoAlreadyInitialized; } // TODO(ogniK): This should be changed to reflect the target process for when we have multiple // processes emulated. As we don't actually have pid support we should assume we're just using // our own process const auto launch_property = - system.GetARPManager().GetLaunchProperty(system.GetCurrentProcessProgramID()); + system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID()); if (launch_property.Failed()) { LOG_ERROR(Service_ACC, "Failed to get launch property"); - return ERR_ACCOUNTINFO_BAD_APPLICATION; + return Account::ResultInvalidApplication; } switch (launch_property->base_game_storage_id) { @@ -782,23 +785,23 @@ Result Module::Interface::InitializeApplicationInfoBase() { default: LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", launch_property->base_game_storage_id); - return ERR_ACCOUNTINFO_BAD_APPLICATION; + return Account::ResultInvalidApplication; } LOG_WARNING(Service_ACC, "ApplicationInfo init required"); - // TODO(ogniK): Actual initalization here + // TODO(ogniK): Actual initialization here return ResultSuccess; } -void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetBaasAccountManagerForApplication(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IManagerForApplication>(system, profile_manager); } -void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) { +void Module::Interface::IsUserAccountSwitchLocked(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); FileSys::NACP nacp; const auto res = system.GetAppLoader().ReadControlData(nacp); @@ -806,7 +809,7 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx bool is_locked = false; if (res != Loader::ResultStatus::Success) { - const FileSys::PatchManager pm{system.GetCurrentProcessProgramID(), + const FileSys::PatchManager pm{system.GetApplicationProcessProgramID(), system.GetFileSystemController(), system.GetContentProvider()}; const auto nacp_unique = pm.GetControlMetadata().first; @@ -825,14 +828,14 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx rb.Push(is_locked); } -void Module::Interface::InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx) { +void Module::Interface::InitializeApplicationInfoV2(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetProfileEditor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; Common::UUID user_id = rp.PopRaw<Common::UUID>(); @@ -843,7 +846,7 @@ void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IProfileEditor>(system, user_id, *profile_manager); } -void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) { +void Module::Interface::ListQualifiedUsers(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); // All users should be qualified. We don't actually have parental control or anything to do with @@ -854,7 +857,7 @@ void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) { +void Module::Interface::ListOpenContextStoredUsers(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); ctx.WriteBuffer(profile_manager->GetStoredOpenedUsers()); @@ -862,7 +865,7 @@ void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ct rb.Push(ResultSuccess); } -void Module::Interface::StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx) { +void Module::Interface::StoreSaveDataThumbnailApplication(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto uuid = rp.PopRaw<Common::UUID>(); @@ -875,7 +878,7 @@ void Module::Interface::StoreSaveDataThumbnailApplication(Kernel::HLERequestCont StoreSaveDataThumbnail(ctx, uuid, tid); } -void Module::Interface::StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx) { +void Module::Interface::StoreSaveDataThumbnailSystem(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto uuid = rp.PopRaw<Common::UUID>(); const auto tid = rp.Pop<u64_le>(); @@ -884,26 +887,26 @@ void Module::Interface::StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& StoreSaveDataThumbnail(ctx, uuid, tid); } -void Module::Interface::StoreSaveDataThumbnail(Kernel::HLERequestContext& ctx, - const Common::UUID& uuid, const u64 tid) { +void Module::Interface::StoreSaveDataThumbnail(HLERequestContext& ctx, const Common::UUID& uuid, + const u64 tid) { IPC::ResponseBuilder rb{ctx, 2}; if (tid == 0) { LOG_ERROR(Service_ACC, "TitleID is not valid!"); - rb.Push(ERR_INVALID_APPLICATION_ID); + rb.Push(Account::ResultInvalidApplication); return; } if (uuid.IsInvalid()) { LOG_ERROR(Service_ACC, "User ID is not valid!"); - rb.Push(ERR_INVALID_USER_ID); + rb.Push(Account::ResultInvalidUserId); return; } const auto thumbnail_size = ctx.GetReadBufferSize(); if (thumbnail_size != THUMBNAIL_SIZE) { LOG_ERROR(Service_ACC, "Buffer size is empty! size={:X} expecting {:X}", thumbnail_size, THUMBNAIL_SIZE); - rb.Push(ERR_INVALID_BUFFER_SIZE); + rb.Push(Account::ResultInvalidArrayLength); return; } @@ -911,7 +914,7 @@ void Module::Interface::StoreSaveDataThumbnail(Kernel::HLERequestContext& ctx, rb.Push(ResultSuccess); } -void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) { +void Module::Interface::TrySelectUserWithoutInteraction(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); // A u8 is passed into this function which we can safely ignore. It's to determine if we have // access to use the network or not by the looks of it @@ -942,18 +945,20 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Module::Interface::~Interface() = default; -void InstallInterfaces(Core::System& system) { +void LoopProcess(Core::System& system) { auto module = std::make_shared<Module>(); auto profile_manager = std::make_shared<ProfileManager>(); - - std::make_shared<ACC_AA>(module, profile_manager, system) - ->InstallAsService(system.ServiceManager()); - std::make_shared<ACC_SU>(module, profile_manager, system) - ->InstallAsService(system.ServiceManager()); - std::make_shared<ACC_U0>(module, profile_manager, system) - ->InstallAsService(system.ServiceManager()); - std::make_shared<ACC_U1>(module, profile_manager, system) - ->InstallAsService(system.ServiceManager()); + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("acc:aa", + std::make_shared<ACC_AA>(module, profile_manager, system)); + server_manager->RegisterNamedService("acc:su", + std::make_shared<ACC_SU>(module, profile_manager, system)); + server_manager->RegisterNamedService("acc:u0", + std::make_shared<ACC_U0>(module, profile_manager, system)); + server_manager->RegisterNamedService("acc:u1", + std::make_shared<ACC_U1>(module, profile_manager, system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index 9411b0b92..6b4735c2f 100644 --- a/src/core/hle/service/acc/acc.h +++ b/src/core/hle/service/acc/acc.h @@ -20,28 +20,28 @@ public: const char* name); ~Interface() override; - void GetUserCount(Kernel::HLERequestContext& ctx); - void GetUserExistence(Kernel::HLERequestContext& ctx); - void ListAllUsers(Kernel::HLERequestContext& ctx); - void ListOpenUsers(Kernel::HLERequestContext& ctx); - void GetLastOpenedUser(Kernel::HLERequestContext& ctx); - void GetProfile(Kernel::HLERequestContext& ctx); - void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); - void InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx); - void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); - void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx); - void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx); - void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx); - void InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx); - void GetProfileEditor(Kernel::HLERequestContext& ctx); - void ListQualifiedUsers(Kernel::HLERequestContext& ctx); - void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx); - void StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx); - void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx); + void GetUserCount(HLERequestContext& ctx); + void GetUserExistence(HLERequestContext& ctx); + void ListAllUsers(HLERequestContext& ctx); + void ListOpenUsers(HLERequestContext& ctx); + void GetLastOpenedUser(HLERequestContext& ctx); + void GetProfile(HLERequestContext& ctx); + void InitializeApplicationInfo(HLERequestContext& ctx); + void InitializeApplicationInfoRestricted(HLERequestContext& ctx); + void GetBaasAccountManagerForApplication(HLERequestContext& ctx); + void IsUserRegistrationRequestPermitted(HLERequestContext& ctx); + void TrySelectUserWithoutInteraction(HLERequestContext& ctx); + void IsUserAccountSwitchLocked(HLERequestContext& ctx); + void InitializeApplicationInfoV2(HLERequestContext& ctx); + void GetProfileEditor(HLERequestContext& ctx); + void ListQualifiedUsers(HLERequestContext& ctx); + void ListOpenContextStoredUsers(HLERequestContext& ctx); + void StoreSaveDataThumbnailApplication(HLERequestContext& ctx); + void StoreSaveDataThumbnailSystem(HLERequestContext& ctx); private: Result InitializeApplicationInfoBase(); - void StoreSaveDataThumbnail(Kernel::HLERequestContext& ctx, const Common::UUID& uuid, + void StoreSaveDataThumbnail(HLERequestContext& ctx, const Common::UUID& uuid, const u64 tid); enum class ApplicationType : u32_le { @@ -67,7 +67,6 @@ public: }; }; -/// Registers all ACC services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index b6bfd6155..d9882ecd3 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp @@ -55,6 +55,10 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"}, {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, {299, nullptr, "SuspendBackgroundDaemon"}, + {900, nullptr, "SetUserUnqualifiedForDebug"}, + {901, nullptr, "UnsetUserUnqualifiedForDebug"}, + {902, nullptr, "ListUsersUnqualifiedForDebug"}, + {910, nullptr, "RefreshFirmwareSettingsForDebug"}, {997, nullptr, "DebugInvalidateTokenCacheForUser"}, {998, nullptr, "DebugSetUserStateClose"}, {999, nullptr, "DebugSetUserStateOpen"}, diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp index 713689d8f..c9e0af90c 100644 --- a/src/core/hle/service/acc/async_context.cpp +++ b/src/core/hle/service/acc/async_context.cpp @@ -2,9 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/acc/async_context.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Account { IAsyncContext::IAsyncContext(Core::System& system_) @@ -27,7 +27,7 @@ IAsyncContext::~IAsyncContext() { service_context.CloseEvent(completion_event); } -void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) { +void IAsyncContext::GetSystemEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -35,7 +35,7 @@ void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) { rb.PushCopyObjects(completion_event->GetReadableEvent()); } -void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) { +void IAsyncContext::Cancel(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); Cancel(); @@ -45,7 +45,7 @@ void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) { +void IAsyncContext::HasDone(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); is_complete.store(IsComplete()); @@ -55,7 +55,7 @@ void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) { rb.Push(is_complete.load()); } -void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) { +void IAsyncContext::GetResult(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/acc/async_context.h b/src/core/hle/service/acc/async_context.h index 26332d241..d7bffc055 100644 --- a/src/core/hle/service/acc/async_context.h +++ b/src/core/hle/service/acc/async_context.h @@ -18,10 +18,10 @@ public: explicit IAsyncContext(Core::System& system_); ~IAsyncContext() override; - void GetSystemEvent(Kernel::HLERequestContext& ctx); - void Cancel(Kernel::HLERequestContext& ctx); - void HasDone(Kernel::HLERequestContext& ctx); - void GetResult(Kernel::HLERequestContext& ctx); + void GetSystemEvent(HLERequestContext& ctx); + void Cancel(HLERequestContext& ctx); + void HasDone(HLERequestContext& ctx); + void GetResult(HLERequestContext& ctx); protected: virtual bool IsComplete() const = 0; diff --git a/src/core/hle/service/acc/errors.h b/src/core/hle/service/acc/errors.h index e9c16b951..433ebfe9d 100644 --- a/src/core/hle/service/acc/errors.h +++ b/src/core/hle/service/acc/errors.h @@ -7,7 +7,13 @@ namespace Service::Account { -constexpr Result ERR_ACCOUNTINFO_BAD_APPLICATION{ErrorModule::Account, 22}; -constexpr Result ERR_ACCOUNTINFO_ALREADY_INITIALIZED{ErrorModule::Account, 41}; +constexpr Result ResultCancelledByUser{ErrorModule::Account, 1}; +constexpr Result ResultNoNotifications{ErrorModule::Account, 15}; +constexpr Result ResultInvalidUserId{ErrorModule::Account, 20}; +constexpr Result ResultInvalidApplication{ErrorModule::Account, 22}; +constexpr Result ResultNullptr{ErrorModule::Account, 30}; +constexpr Result ResultInvalidArrayLength{ErrorModule::Account, 32}; +constexpr Result ResultApplicationInfoAlreadyInitialized{ErrorModule::Account, 41}; +constexpr Result ResultAccountUpdateFailed{ErrorModule::Account, 100}; } // namespace Service::Account diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 97f7c6688..5542d6cbc 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -46,6 +46,7 @@ ProfileManager::ProfileManager() { // Create an user if none are present if (user_count == 0) { CreateNewUser(UUID::MakeRandom(), "yuzu"); + WriteUserSaveFile(); } auto current = @@ -287,7 +288,7 @@ void ProfileManager::StoreOpenedUsers() { }); } -/// Return the users profile base and the unknown arbitary data. +/// Return the users profile base and the unknown arbitrary data. bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile, UserData& data) const { if (GetProfileBase(index, profile)) { @@ -297,13 +298,13 @@ bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, Pro return false; } -/// Return the users profile base and the unknown arbitary data. +/// Return the users profile base and the unknown arbitrary data. bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile, UserData& data) const { const auto idx = GetUserIndex(uuid); return GetProfileBaseAndData(idx, profile, data); } -/// Return the users profile base and the unknown arbitary data. +/// Return the users profile base and the unknown arbitrary data. bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile, UserData& data) const { return GetProfileBaseAndData(user.user_uuid, profile, data); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 22999c942..a2375508a 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -11,9 +11,9 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/savedata_factory.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/result.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" @@ -24,24 +24,25 @@ #include "core/hle/service/am/idle.h" #include "core/hle/service/am/omm.h" #include "core/hle/service/am/spsm.h" -#include "core/hle/service/am/tcap.h" #include "core/hle/service/apm/apm_controller.h" #include "core/hle/service/apm/apm_interface.h" #include "core/hle/service/bcat/backend/backend.h" #include "core/hle/service/caps/caps.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ns/ns.h" -#include "core/hle/service/nvflinger/nvflinger.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" #include "core/hle/service/pm/pm.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/vi/vi.h" #include "core/memory.h" namespace Service::AM { -constexpr Result ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 2}; -constexpr Result ERR_NO_MESSAGES{ErrorModule::AM, 3}; -constexpr Result ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 503}; +constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; +constexpr Result ResultNoMessages{ErrorModule::AM, 3}; +constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; enum class LaunchParameterKind : u32 { ApplicationSpecific = 1, @@ -78,8 +79,8 @@ IWindowController::IWindowController(Core::System& system_) IWindowController::~IWindowController() = default; -void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) { - const u64 process_id = system.CurrentProcess()->GetProcessID(); +void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { + const u64 process_id = system.ApplicationProcess()->GetProcessId(); LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id); @@ -88,7 +89,7 @@ void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) rb.Push<u64>(process_id); } -void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) { +void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -111,7 +112,7 @@ IAudioController::IAudioController(Core::System& system_) IAudioController::~IAudioController() = default; -void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) { +void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const float main_applet_volume_tmp = rp.Pop<float>(); const float library_applet_volume_tmp = rp.Pop<float>(); @@ -128,21 +129,21 @@ void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { +void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(main_applet_volume); } -void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { +void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(library_applet_volume); } -void IAudioController::ChangeMainAppletMasterVolume(Kernel::HLERequestContext& ctx) { +void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) { struct Parameters { float volume; s64 fade_time_ns; @@ -162,7 +163,7 @@ void IAudioController::ChangeMainAppletMasterVolume(Kernel::HLERequestContext& c rb.Push(ResultSuccess); } -void IAudioController::SetTransparentAudioRate(Kernel::HLERequestContext& ctx) { +void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const float transparent_volume_rate_tmp = rp.Pop<float>(); @@ -227,6 +228,8 @@ IDebugFunctions::IDebugFunctions(Core::System& system_) {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, {40, nullptr, "GetAppletResourceUsageInfo"}, + {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, + {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, {100, nullptr, "SetCpuBoostModeForApplet"}, {101, nullptr, "CancelCpuBoostModeForApplet"}, {110, nullptr, "PushToAppletBoundChannelForDebug"}, @@ -238,6 +241,8 @@ IDebugFunctions::IDebugFunctions(Core::System& system_) {131, nullptr, "FriendInvitationClearApplicationParameter"}, {132, nullptr, "FriendInvitationPushApplicationParameter"}, {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, + {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, + {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, }; // clang-format on @@ -247,10 +252,9 @@ IDebugFunctions::IDebugFunctions(Core::System& system_) IDebugFunctions::~IDebugFunctions() = default; -ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_) - : ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_}, service_context{ - system, - "ISelfController"} { +ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) + : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, + service_context{system, "ISelfController"} { // clang-format off static const FunctionInfo functions[] = { {0, &ISelfController::Exit, "Exit"}, @@ -324,7 +328,7 @@ ISelfController::~ISelfController() { service_context.CloseEvent(accumulated_suspended_tick_changed_event); } -void ISelfController::Exit(Kernel::HLERequestContext& ctx) { +void ISelfController::Exit(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -333,7 +337,7 @@ void ISelfController::Exit(Kernel::HLERequestContext& ctx) { system.Exit(); } -void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { +void ISelfController::LockExit(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); system.SetExitLock(true); @@ -342,7 +346,7 @@ void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { +void ISelfController::UnlockExit(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); system.SetExitLock(false); @@ -351,7 +355,7 @@ void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) { +void ISelfController::EnterFatalSection(HLERequestContext& ctx) { ++num_fatal_sections_entered; LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); @@ -359,7 +363,7 @@ void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) { +void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); // Entry and exit of fatal sections must be balanced. @@ -375,7 +379,7 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { +void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); launchable_event->Signal(); @@ -385,7 +389,7 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& rb.PushCopyObjects(launchable_event->GetReadableEvent()); } -void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { +void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto permission = rp.PopEnum<ScreenshotPermission>(); LOG_DEBUG(Service_AM, "called, permission={}", permission); @@ -396,7 +400,7 @@ void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { +void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; bool flag = rp.Pop<bool>(); @@ -406,7 +410,7 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont rb.Push(ResultSuccess); } -void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { +void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; bool flag = rp.Pop<bool>(); @@ -416,7 +420,7 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo rb.Push(ResultSuccess); } -void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { +void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { // Takes 3 input u8s with each field located immediately after the previous // u8, these are bool flags. No output. IPC::RequestParser rp{ctx}; @@ -435,14 +439,14 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { +void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { +void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { // Takes 3 input u8s with each field located immediately after the previous // u8, these are bool flags. No output. IPC::RequestParser rp{ctx}; @@ -454,27 +458,27 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& rb.Push(ResultSuccess); } -void ISelfController::SetAlbumImageOrientation(Kernel::HLERequestContext& ctx) { +void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { +void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); // TODO(Subv): Find out how AM determines the display to use, for now just // create the layer in the Default display. - const auto display_id = nvflinger.OpenDisplay("Default"); - const auto layer_id = nvflinger.CreateLayer(*display_id); + const auto display_id = nvnflinger.OpenDisplay("Default"); + const auto layer_id = nvnflinger.CreateLayer(*display_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(*layer_id); } -void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestContext& ctx) { +void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); // TODO(Subv): Find out how AM determines the display to use, for now just @@ -484,22 +488,22 @@ void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestConte // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse // side effects. // TODO: Support multiple layers - const auto display_id = nvflinger.OpenDisplay("Default"); - const auto layer_id = nvflinger.CreateLayer(*display_id); + const auto display_id = nvnflinger.OpenDisplay("Default"); + const auto layer_id = nvnflinger.CreateLayer(*display_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(*layer_id); } -void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) { +void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) { +void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; idle_time_detection_extension = rp.Pop<u32>(); LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}", @@ -509,7 +513,7 @@ void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& c rb.Push(ResultSuccess); } -void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) { +void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -517,14 +521,14 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c rb.Push<u32>(idle_time_detection_extension); } -void ISelfController::ReportUserIsActive(Kernel::HLERequestContext& ctx) { +void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ISelfController::SetAutoSleepDisabled(Kernel::HLERequestContext& ctx) { +void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; is_auto_sleep_disabled = rp.Pop<bool>(); @@ -544,7 +548,7 @@ void ISelfController::SetAutoSleepDisabled(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::IsAutoSleepDisabled(Kernel::HLERequestContext& ctx) { +void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); IPC::ResponseBuilder rb{ctx, 3}; @@ -552,7 +556,7 @@ void ISelfController::IsAutoSleepDisabled(Kernel::HLERequestContext& ctx) { rb.Push(is_auto_sleep_disabled); } -void ISelfController::GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx) { +void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); // This command returns the total number of system ticks since ISelfController creation @@ -563,7 +567,7 @@ void ISelfController::GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext rb.Push<u64>(0); } -void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx) { +void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -571,7 +575,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); } -void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) { +void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; // This service call sets an internal flag whether a notification is shown when an image is @@ -586,7 +590,7 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestCo rb.Push(ResultSuccess); } -void ISelfController::SaveCurrentScreenshot(Kernel::HLERequestContext& ctx) { +void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto album_report_option = rp.PopEnum<Capture::AlbumReportOption>(); @@ -597,7 +601,7 @@ void ISelfController::SaveCurrentScreenshot(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISelfController::SetRecordVolumeMuted(Kernel::HLERequestContext& ctx) { +void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto is_record_volume_muted = rp.Pop<bool>(); @@ -731,7 +735,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, ICommonStateGetter::~ICommonStateGetter() = default; -void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -739,7 +743,7 @@ void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) { rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode } -void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -747,7 +751,7 @@ void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) { rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent()); } -void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); const auto message = msg_queue->PopMessage(); @@ -755,7 +759,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { if (message == AppletMessageQueue::AppletMessage::None) { LOG_ERROR(Service_AM, "Message queue is empty"); - rb.Push(ERR_NO_MESSAGES); + rb.Push(AM::ResultNoMessages); rb.PushEnum<AppletMessageQueue::AppletMessage>(message); return; } @@ -764,7 +768,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { rb.PushEnum<AppletMessageQueue::AppletMessage>(message); } -void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -772,7 +776,7 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u8>(FocusState::InFocus)); } -void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -780,7 +784,7 @@ void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) { rb.Push(vr_mode_state); } -void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; vr_mode_state = rp.Pop<bool>(); @@ -790,7 +794,7 @@ void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); @@ -801,21 +805,21 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx rb.Push(ResultSuccess); } -void ICommonStateGetter::BeginVrModeEx(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -823,7 +827,7 @@ void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLEReque rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); } -void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -838,7 +842,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& } } -void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); const auto& sm = system.ServiceManager(); @@ -848,7 +852,7 @@ void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) { apm_sys->SetCpuBoostMode(ctx); } -void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto system_button{rp.PopEnum<SystemButtonType>()}; @@ -859,7 +863,7 @@ void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(Kernel::HLERequest } void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( - Kernel::HLERequestContext& ctx) { + HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -907,7 +911,7 @@ void IStorage::Register() { IStorage::~IStorage() = default; -void IStorage::Open(Kernel::HLERequestContext& ctx) { +void IStorage::Open(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -916,7 +920,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IStorageAccessor>(system, *this); } -void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()}; LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); @@ -925,7 +929,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); } -void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { +void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -942,7 +946,7 @@ public: {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, {10, &ILibraryAppletAccessor::Start, "Start"}, - {20, nullptr, "RequestExit"}, + {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, {25, nullptr, "Terminate"}, {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, @@ -965,7 +969,7 @@ public: } private: - void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { + void GetAppletStateChangedEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -973,7 +977,7 @@ private: rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); } - void IsCompleted(Kernel::HLERequestContext& ctx) { + void IsCompleted(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -981,21 +985,21 @@ private: rb.Push<u32>(applet->TransactionComplete()); } - void GetResult(Kernel::HLERequestContext& ctx) { + void GetResult(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(applet->GetStatus()); } - void PresetLibraryAppletGpuTimeSliceZero(Kernel::HLERequestContext& ctx) { + void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void Start(Kernel::HLERequestContext& ctx) { + void Start(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); ASSERT(applet != nullptr); @@ -1007,7 +1011,16 @@ private: rb.Push(ResultSuccess); } - void PushInData(Kernel::HLERequestContext& ctx) { + void RequestExit(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + ASSERT(applet != nullptr); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(applet->RequestExit()); + } + + void PushInData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::RequestParser rp{ctx}; @@ -1017,7 +1030,7 @@ private: rb.Push(ResultSuccess); } - void PopOutData(Kernel::HLERequestContext& ctx) { + void PopOutData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); auto storage = applet->GetBroker().PopNormalDataToGame(); @@ -1025,7 +1038,7 @@ private: LOG_DEBUG(Service_AM, "storage is a nullptr. There is no data in the current normal channel"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NO_DATA_IN_CHANNEL); + rb.Push(AM::ResultNoDataInChannel); return; } @@ -1034,7 +1047,7 @@ private: rb.PushIpcInterface<IStorage>(std::move(storage)); } - void PushInteractiveInData(Kernel::HLERequestContext& ctx) { + void PushInteractiveInData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::RequestParser rp{ctx}; @@ -1048,7 +1061,7 @@ private: rb.Push(ResultSuccess); } - void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { + void PopInteractiveOutData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); auto storage = applet->GetBroker().PopInteractiveDataToGame(); @@ -1056,7 +1069,7 @@ private: LOG_DEBUG(Service_AM, "storage is a nullptr. There is no data in the current interactive channel"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NO_DATA_IN_CHANNEL); + rb.Push(AM::ResultNoDataInChannel); return; } @@ -1065,7 +1078,7 @@ private: rb.PushIpcInterface<IStorage>(std::move(storage)); } - void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { + void GetPopOutDataEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -1073,7 +1086,7 @@ private: rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); } - void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { + void GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -1081,7 +1094,7 @@ private: rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); } - void GetIndirectLayerConsumerHandle(Kernel::HLERequestContext& ctx) { + void GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is @@ -1111,7 +1124,7 @@ IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_) IStorageAccessor::~IStorageAccessor() = default; -void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { +void IStorageAccessor::GetSize(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -1120,11 +1133,11 @@ void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u64>(backing.GetSize())); } -void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { +void IStorageAccessor::Write(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 offset{rp.Pop<u64>()}; - const std::vector<u8> data{ctx.ReadBuffer()}; + const auto data{ctx.ReadBuffer()}; const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)}; LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); @@ -1135,7 +1148,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { backing.GetSize(), size, offset); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_SIZE_OUT_OF_BOUNDS); + rb.Push(AM::ResultInvalidOffset); return; } @@ -1145,7 +1158,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { +void IStorageAccessor::Read(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 offset{rp.Pop<u64>()}; @@ -1158,7 +1171,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { backing.GetSize(), size, offset); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_SIZE_OUT_OF_BOUNDS); + rb.Push(AM::ResultInvalidOffset); return; } @@ -1183,7 +1196,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) ILibraryAppletCreator::~ILibraryAppletCreator() = default; -void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { +void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_id = rp.PopRaw<Applets::AppletId>(); @@ -1209,7 +1222,7 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); } -void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { +void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s64 size{rp.Pop<s64>()}; @@ -1230,7 +1243,7 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IStorage>(system, std::move(buffer)); } -void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { +void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { @@ -1252,7 +1265,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex } auto transfer_mem = - system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); + system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); if (transfer_mem.IsNull()) { LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); @@ -1261,16 +1274,16 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex return; } - const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress()); - const u8* const mem_end = mem_begin + transfer_mem->GetSize(); - std::vector<u8> memory{mem_begin, mem_end}; + std::vector<u8> memory(transfer_mem->GetSize()); + system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), + memory.size()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IStorage>(system, std::move(memory)); } -void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) { +void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s64 size{rp.Pop<s64>()}; @@ -1286,7 +1299,7 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) } auto transfer_mem = - system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); + system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); if (transfer_mem.IsNull()) { LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); @@ -1295,9 +1308,9 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) return; } - const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress()); - const u8* const mem_end = mem_begin + transfer_mem->GetSize(); - std::vector<u8> memory{mem_begin, mem_end}; + std::vector<u8> memory(transfer_mem->GetSize()); + system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), + memory.size()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -1323,7 +1336,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {24, nullptr, "GetLaunchStorageInfoForDebug"}, {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, - {27, nullptr, "CreateCacheStorage"}, + {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, {28, nullptr, "GetSaveDataSizeMax"}, {29, nullptr, "GetCacheStorageMax"}, {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, @@ -1393,29 +1406,28 @@ IApplicationFunctions::~IApplicationFunctions() { service_context.CloseEvent(health_warning_disappeared_system_event); } -void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer( - Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto is_visible = rp.Pop<bool>(); @@ -1425,37 +1437,35 @@ void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequest rb.Push(ResultSuccess); } -void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed( - Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed( - Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::BeginBlockingHomeButton(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto kind = rp.PopEnum<LaunchParameterKind>(); @@ -1465,11 +1475,12 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) { return system.GetFileSystemController().GetBCATDirectory(tid); }); - const auto build_id_full = system.GetCurrentProcessBuildID(); + const auto build_id_full = system.GetApplicationProcessBuildID(); u64 build_id{}; std::memcpy(&build_id, build_id_full.data(), sizeof(u64)); - auto data = backend->GetLaunchParameter({system.GetCurrentProcessProgramID(), build_id}); + auto data = + backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id}); if (data.has_value()) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -1503,25 +1514,24 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NO_DATA_IN_CHANNEL); + rb.Push(AM::ResultNoDataInChannel); } -void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest( - Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u128 user_id = rp.PopRaw<u128>(); LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); FileSys::SaveDataAttribute attribute{}; - attribute.title_id = system.GetCurrentProcessProgramID(); + attribute.title_id = system.GetApplicationProcessProgramID(); attribute.user_id = user_id; attribute.type = FileSys::SaveDataType::SaveData; const auto res = system.GetFileSystemController().CreateSaveData( @@ -1532,7 +1542,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { rb.Push<u64>(0); } -void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { // Takes an input u32 Result, no output. // For example, in some cases official apps use this with error 0x2A2 then // uses svcBreak. @@ -1545,13 +1555,13 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); std::array<u8, 0x10> version_string{}; const auto res = [this] { - const auto title_id = system.GetCurrentProcessProgramID(); + const auto title_id = system.GetApplicationProcessProgramID(); const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), system.GetContentProvider()}; @@ -1570,7 +1580,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { const auto& version = res.first->GetVersionString(); std::copy(version.begin(), version.end(), version_string.begin()); } else { - constexpr char default_version[]{"1.0.0"}; + static constexpr char default_version[]{"1.0.0"}; std::memcpy(version_string.data(), default_version, sizeof(default_version)); } @@ -1579,7 +1589,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { rb.PushRaw(version_string); } -void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { // TODO(bunnei): This should be configurable LOG_DEBUG(Service_AM, "called"); @@ -1588,7 +1598,7 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { u32 supported_languages = 0; const auto res = [this] { - const auto title_id = system.GetCurrentProcessProgramID(); + const auto title_id = system.GetApplicationProcessProgramID(); const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), system.GetContentProvider()}; @@ -1635,7 +1645,7 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { rb.Push(*res_code); } -void IApplicationFunctions::IsGamePlayRecordingSupported(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); constexpr bool gameplay_recording_supported = false; @@ -1645,21 +1655,21 @@ void IApplicationFunctions::IsGamePlayRecordingSupported(Kernel::HLERequestConte rb.Push(gameplay_recording_supported); } -void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -1667,7 +1677,7 @@ void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) { rb.Push<u8>(0); // Unknown, seems to be ignored by official processes } -void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 6}; @@ -1678,7 +1688,7 @@ void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) { rb.Push<u64>(0); } -void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { struct Parameters { FileSys::SaveDataType type; u128 user_id; @@ -1696,7 +1706,8 @@ void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) { static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); system.GetFileSystemController().WriteSaveDataSize( - type, system.GetCurrentProcessProgramID(), user_id, {new_normal_size, new_journal_size}); + type, system.GetApplicationProcessProgramID(), user_id, + {new_normal_size, new_journal_size}); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -1706,7 +1717,7 @@ void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) { rb.Push<u64>(0); } -void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { struct Parameters { FileSys::SaveDataType type; u128 user_id; @@ -1720,7 +1731,7 @@ void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) { user_id[0]); const auto size = system.GetFileSystemController().ReadSaveDataSize( - type, system.GetCurrentProcessProgramID(), user_id); + type, system.GetApplicationProcessProgramID(), user_id); IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); @@ -1728,7 +1739,37 @@ void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) { rb.Push(size.journal); } -void IApplicationFunctions::QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { + struct InputParameters { + u16 index; + s64 size; + s64 journal_size; + }; + static_assert(sizeof(InputParameters) == 24); + + struct OutputParameters { + u32 storage_target; + u64 required_size; + }; + static_assert(sizeof(OutputParameters) == 16); + + IPC::RequestParser rp{ctx}; + const auto params = rp.PopRaw<InputParameters>(); + + LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}", + params.index, params.size, params.journal_size); + + const OutputParameters resp{ + .storage_target = 1, + .required_size = 0, + }; + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.PushRaw(resp); +} + +void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -1736,7 +1777,7 @@ void IApplicationFunctions::QueryApplicationPlayStatistics(Kernel::HLERequestCon rb.Push<u32>(0); } -void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -1744,7 +1785,7 @@ void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLEReque rb.Push<u32>(0); } -void IApplicationFunctions::ExecuteProgram(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::RequestParser rp{ctx}; @@ -1758,21 +1799,21 @@ void IApplicationFunctions::ExecuteProgram(Kernel::HLERequestContext& ctx) { system.ExecuteProgram(program_index); } -void IApplicationFunctions::ClearUserChannel(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::UnpopToUserChannel(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -1780,7 +1821,7 @@ void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& c rb.Push<s32>(previous_program_index); } -void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -1788,7 +1829,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); } -void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -1796,15 +1837,14 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); } -void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( - Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); +void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NO_DATA_IN_CHANNEL); + rb.Push(AM::ResultNoDataInChannel); } -void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -1812,7 +1852,7 @@ void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLEReques rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent()); } -void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -1820,25 +1860,28 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERe rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); } -void IApplicationFunctions::PrepareForJit(Kernel::HLERequestContext& ctx) { +void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, - Core::System& system) { +void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { auto message_queue = std::make_shared<AppletMessageQueue>(system); // Needed on game boot message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); - std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager); - std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager); - std::make_shared<IdleSys>(system)->InstallAsService(service_manager); - std::make_shared<OMM>(system)->InstallAsService(service_manager); - std::make_shared<SPSM>(system)->InstallAsService(service_manager); - std::make_shared<TCAP>(system)->InstallAsService(service_manager); + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService( + "appletAE", std::make_shared<AppletAE>(nvnflinger, message_queue, system)); + server_manager->RegisterNamedService( + "appletOE", std::make_shared<AppletOE>(nvnflinger, message_queue, system)); + server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system)); + server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system)); + server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system)); + ServerManager::RunServer(std::move(server_manager)); } IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) @@ -1855,6 +1898,8 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) {31, nullptr, "GetWriterLockAccessorEx"}, {40, nullptr, "IsSleepEnabled"}, {41, nullptr, "IsRebootEnabled"}, + {50, nullptr, "LaunchSystemApplet"}, + {51, nullptr, "LaunchStarter"}, {100, nullptr, "PopRequestLaunchApplicationForDebug"}, {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, {200, nullptr, "LaunchDevMenu"}, @@ -1872,14 +1917,14 @@ IHomeMenuFunctions::~IHomeMenuFunctions() { service_context.CloseEvent(pop_from_general_channel_event); } -void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) { +void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx) { +void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index a0fbfcfc5..d4fd163da 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -12,11 +12,12 @@ namespace Kernel { class KernelCore; +class KReadableEvent; class KTransferMemory; } // namespace Kernel -namespace Service::NVFlinger { -class NVFlinger; +namespace Service::Nvnflinger { +class Nvnflinger; } namespace Service::AM { @@ -109,8 +110,8 @@ public: ~IWindowController() override; private: - void GetAppletResourceUserId(Kernel::HLERequestContext& ctx); - void AcquireForegroundRights(Kernel::HLERequestContext& ctx); + void GetAppletResourceUserId(HLERequestContext& ctx); + void AcquireForegroundRights(HLERequestContext& ctx); }; class IAudioController final : public ServiceFramework<IAudioController> { @@ -119,11 +120,11 @@ public: ~IAudioController() override; private: - void SetExpectedMasterVolume(Kernel::HLERequestContext& ctx); - void GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx); - void GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx); - void ChangeMainAppletMasterVolume(Kernel::HLERequestContext& ctx); - void SetTransparentAudioRate(Kernel::HLERequestContext& ctx); + void SetExpectedMasterVolume(HLERequestContext& ctx); + void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx); + void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx); + void ChangeMainAppletMasterVolume(HLERequestContext& ctx); + void SetTransparentAudioRate(HLERequestContext& ctx); static constexpr float min_allowed_volume = 0.0f; static constexpr float max_allowed_volume = 1.0f; @@ -153,36 +154,36 @@ public: class ISelfController final : public ServiceFramework<ISelfController> { public: - explicit ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_); + explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); ~ISelfController() override; private: - void Exit(Kernel::HLERequestContext& ctx); - void LockExit(Kernel::HLERequestContext& ctx); - void UnlockExit(Kernel::HLERequestContext& ctx); - void EnterFatalSection(Kernel::HLERequestContext& ctx); - void LeaveFatalSection(Kernel::HLERequestContext& ctx); - void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); - void SetScreenShotPermission(Kernel::HLERequestContext& ctx); - void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); - void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx); - void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); - void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); - void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); - void SetAlbumImageOrientation(Kernel::HLERequestContext& ctx); - void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); - void CreateManagedDisplaySeparableLayer(Kernel::HLERequestContext& ctx); - void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); - void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); - void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); - void ReportUserIsActive(Kernel::HLERequestContext& ctx); - void SetAutoSleepDisabled(Kernel::HLERequestContext& ctx); - void IsAutoSleepDisabled(Kernel::HLERequestContext& ctx); - void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); - void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); - void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx); - void SaveCurrentScreenshot(Kernel::HLERequestContext& ctx); - void SetRecordVolumeMuted(Kernel::HLERequestContext& ctx); + void Exit(HLERequestContext& ctx); + void LockExit(HLERequestContext& ctx); + void UnlockExit(HLERequestContext& ctx); + void EnterFatalSection(HLERequestContext& ctx); + void LeaveFatalSection(HLERequestContext& ctx); + void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx); + void SetScreenShotPermission(HLERequestContext& ctx); + void SetOperationModeChangedNotification(HLERequestContext& ctx); + void SetPerformanceModeChangedNotification(HLERequestContext& ctx); + void SetFocusHandlingMode(HLERequestContext& ctx); + void SetRestartMessageEnabled(HLERequestContext& ctx); + void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); + void SetAlbumImageOrientation(HLERequestContext& ctx); + void CreateManagedDisplayLayer(HLERequestContext& ctx); + void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); + void SetHandlesRequestToDisplay(HLERequestContext& ctx); + void SetIdleTimeDetectionExtension(HLERequestContext& ctx); + void GetIdleTimeDetectionExtension(HLERequestContext& ctx); + void ReportUserIsActive(HLERequestContext& ctx); + void SetAutoSleepDisabled(HLERequestContext& ctx); + void IsAutoSleepDisabled(HLERequestContext& ctx); + void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx); + void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx); + void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx); + void SaveCurrentScreenshot(HLERequestContext& ctx); + void SetRecordVolumeMuted(HLERequestContext& ctx); enum class ScreenshotPermission : u32 { Inherit = 0, @@ -190,7 +191,7 @@ private: Disable = 2, }; - NVFlinger::NVFlinger& nvflinger; + Nvnflinger::Nvnflinger& nvnflinger; KernelHelpers::ServiceContext service_context; @@ -235,22 +236,22 @@ private: CaptureButtonLongPressing, }; - void GetEventHandle(Kernel::HLERequestContext& ctx); - void ReceiveMessage(Kernel::HLERequestContext& ctx); - void GetCurrentFocusState(Kernel::HLERequestContext& ctx); - void GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx); - void GetOperationMode(Kernel::HLERequestContext& ctx); - void GetPerformanceMode(Kernel::HLERequestContext& ctx); - void GetBootMode(Kernel::HLERequestContext& ctx); - void IsVrModeEnabled(Kernel::HLERequestContext& ctx); - void SetVrModeEnabled(Kernel::HLERequestContext& ctx); - void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx); - void BeginVrModeEx(Kernel::HLERequestContext& ctx); - void EndVrModeEx(Kernel::HLERequestContext& ctx); - void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); - void SetCpuBoostMode(Kernel::HLERequestContext& ctx); - void PerformSystemButtonPressingIfInFocus(Kernel::HLERequestContext& ctx); - void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(Kernel::HLERequestContext& ctx); + void GetEventHandle(HLERequestContext& ctx); + void ReceiveMessage(HLERequestContext& ctx); + void GetCurrentFocusState(HLERequestContext& ctx); + void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); + void GetOperationMode(HLERequestContext& ctx); + void GetPerformanceMode(HLERequestContext& ctx); + void GetBootMode(HLERequestContext& ctx); + void IsVrModeEnabled(HLERequestContext& ctx); + void SetVrModeEnabled(HLERequestContext& ctx); + void SetLcdBacklighOffEnabled(HLERequestContext& ctx); + void BeginVrModeEx(HLERequestContext& ctx); + void EndVrModeEx(HLERequestContext& ctx); + void GetDefaultDisplayResolution(HLERequestContext& ctx); + void SetCpuBoostMode(HLERequestContext& ctx); + void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); + void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); std::shared_ptr<AppletMessageQueue> msg_queue; bool vr_mode_state{}; @@ -283,7 +284,7 @@ public: private: void Register(); - void Open(Kernel::HLERequestContext& ctx); + void Open(HLERequestContext& ctx); std::shared_ptr<IStorageImpl> impl; }; @@ -294,9 +295,9 @@ public: ~IStorageAccessor() override; private: - void GetSize(Kernel::HLERequestContext& ctx); - void Write(Kernel::HLERequestContext& ctx); - void Read(Kernel::HLERequestContext& ctx); + void GetSize(HLERequestContext& ctx); + void Write(HLERequestContext& ctx); + void Read(HLERequestContext& ctx); IStorage& backing; }; @@ -307,10 +308,10 @@ public: ~ILibraryAppletCreator() override; private: - void CreateLibraryApplet(Kernel::HLERequestContext& ctx); - void CreateStorage(Kernel::HLERequestContext& ctx); - void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); - void CreateHandleStorage(Kernel::HLERequestContext& ctx); + void CreateLibraryApplet(HLERequestContext& ctx); + void CreateStorage(HLERequestContext& ctx); + void CreateTransferMemoryStorage(HLERequestContext& ctx); + void CreateHandleStorage(HLERequestContext& ctx); }; class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { @@ -319,39 +320,40 @@ public: ~IApplicationFunctions() override; private: - void PopLaunchParameter(Kernel::HLERequestContext& ctx); - void CreateApplicationAndRequestToStartForQuest(Kernel::HLERequestContext& ctx); - void EnsureSaveData(Kernel::HLERequestContext& ctx); - void SetTerminateResult(Kernel::HLERequestContext& ctx); - void GetDisplayVersion(Kernel::HLERequestContext& ctx); - void GetDesiredLanguage(Kernel::HLERequestContext& ctx); - void IsGamePlayRecordingSupported(Kernel::HLERequestContext& ctx); - void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx); - void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx); - void NotifyRunning(Kernel::HLERequestContext& ctx); - void GetPseudoDeviceId(Kernel::HLERequestContext& ctx); - void ExtendSaveData(Kernel::HLERequestContext& ctx); - void GetSaveDataSize(Kernel::HLERequestContext& ctx); - void BeginBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx); - void EndBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx); - void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx); - void EndBlockingHomeButton(Kernel::HLERequestContext& ctx); - void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx); - void InitializeApplicationCopyrightFrameBuffer(Kernel::HLERequestContext& ctx); - void SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx); - void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx); - void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx); - void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx); - void ExecuteProgram(Kernel::HLERequestContext& ctx); - void ClearUserChannel(Kernel::HLERequestContext& ctx); - void UnpopToUserChannel(Kernel::HLERequestContext& ctx); - void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx); - void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); - void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); - void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); - void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx); - void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx); - void PrepareForJit(Kernel::HLERequestContext& ctx); + void PopLaunchParameter(HLERequestContext& ctx); + void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx); + void EnsureSaveData(HLERequestContext& ctx); + void SetTerminateResult(HLERequestContext& ctx); + void GetDisplayVersion(HLERequestContext& ctx); + void GetDesiredLanguage(HLERequestContext& ctx); + void IsGamePlayRecordingSupported(HLERequestContext& ctx); + void InitializeGamePlayRecording(HLERequestContext& ctx); + void SetGamePlayRecordingState(HLERequestContext& ctx); + void NotifyRunning(HLERequestContext& ctx); + void GetPseudoDeviceId(HLERequestContext& ctx); + void ExtendSaveData(HLERequestContext& ctx); + void GetSaveDataSize(HLERequestContext& ctx); + void CreateCacheStorage(HLERequestContext& ctx); + void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); + void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); + void BeginBlockingHomeButton(HLERequestContext& ctx); + void EndBlockingHomeButton(HLERequestContext& ctx); + void EnableApplicationCrashReport(HLERequestContext& ctx); + void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx); + void SetApplicationCopyrightImage(HLERequestContext& ctx); + void SetApplicationCopyrightVisibility(HLERequestContext& ctx); + void QueryApplicationPlayStatistics(HLERequestContext& ctx); + void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx); + void ExecuteProgram(HLERequestContext& ctx); + void ClearUserChannel(HLERequestContext& ctx); + void UnpopToUserChannel(HLERequestContext& ctx); + void GetPreviousProgramIndex(HLERequestContext& ctx); + void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx); + void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx); + void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx); + void GetNotificationStorageChannelEvent(HLERequestContext& ctx); + void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); + void PrepareForJit(HLERequestContext& ctx); KernelHelpers::ServiceContext service_context; @@ -370,8 +372,8 @@ public: ~IHomeMenuFunctions() override; private: - void RequestToGetForeground(Kernel::HLERequestContext& ctx); - void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); + void RequestToGetForeground(HLERequestContext& ctx); + void GetPopFromGeneralChannelEvent(HLERequestContext& ctx); KernelHelpers::ServiceContext service_context; @@ -396,8 +398,6 @@ public: ~IProcessWindingController() override; }; -/// Registers all AM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, - Core::System& system); +void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index d7719da35..2764f7ceb 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -3,20 +3,20 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" -#include "core/hle/service/nvflinger/nvflinger.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" namespace Service::AM { class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { public: - explicit ILibraryAppletProxy(NVFlinger::NVFlinger& nvflinger_, + explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) - : ServiceFramework{system_, "ILibraryAppletProxy"}, nvflinger{nvflinger_}, - msg_queue{std::move(msg_queue_)} { + : ServiceFramework{system_, "ILibraryAppletProxy"}, + nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -36,7 +36,7 @@ public: } private: - void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { + void GetCommonStateGetter(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -44,15 +44,15 @@ private: rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); } - void GetSelfController(Kernel::HLERequestContext& ctx) { + void GetSelfController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISelfController>(system, nvflinger); + rb.PushIpcInterface<ISelfController>(system, nvnflinger); } - void GetWindowController(Kernel::HLERequestContext& ctx) { + void GetWindowController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -60,7 +60,7 @@ private: rb.PushIpcInterface<IWindowController>(system); } - void GetAudioController(Kernel::HLERequestContext& ctx) { + void GetAudioController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -68,7 +68,7 @@ private: rb.PushIpcInterface<IAudioController>(system); } - void GetDisplayController(Kernel::HLERequestContext& ctx) { + void GetDisplayController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -76,7 +76,7 @@ private: rb.PushIpcInterface<IDisplayController>(system); } - void GetProcessWindingController(Kernel::HLERequestContext& ctx) { + void GetProcessWindingController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -84,7 +84,7 @@ private: rb.PushIpcInterface<IProcessWindingController>(system); } - void GetDebugFunctions(Kernel::HLERequestContext& ctx) { + void GetDebugFunctions(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -92,7 +92,7 @@ private: rb.PushIpcInterface<IDebugFunctions>(system); } - void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { + void GetLibraryAppletCreator(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -100,7 +100,7 @@ private: rb.PushIpcInterface<ILibraryAppletCreator>(system); } - void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { + void GetApplicationFunctions(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -108,17 +108,17 @@ private: rb.PushIpcInterface<IApplicationFunctions>(system); } - NVFlinger::NVFlinger& nvflinger; + Nvnflinger::Nvnflinger& nvnflinger; std::shared_ptr<AppletMessageQueue> msg_queue; }; class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { public: - explicit ISystemAppletProxy(NVFlinger::NVFlinger& nvflinger_, + explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) - : ServiceFramework{system_, "ISystemAppletProxy"}, nvflinger{nvflinger_}, - msg_queue{std::move(msg_queue_)} { + : ServiceFramework{system_, "ISystemAppletProxy"}, + nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -140,7 +140,7 @@ public: } private: - void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { + void GetCommonStateGetter(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -148,15 +148,15 @@ private: rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); } - void GetSelfController(Kernel::HLERequestContext& ctx) { + void GetSelfController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISelfController>(system, nvflinger); + rb.PushIpcInterface<ISelfController>(system, nvnflinger); } - void GetWindowController(Kernel::HLERequestContext& ctx) { + void GetWindowController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -164,7 +164,7 @@ private: rb.PushIpcInterface<IWindowController>(system); } - void GetAudioController(Kernel::HLERequestContext& ctx) { + void GetAudioController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -172,7 +172,7 @@ private: rb.PushIpcInterface<IAudioController>(system); } - void GetDisplayController(Kernel::HLERequestContext& ctx) { + void GetDisplayController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -180,7 +180,7 @@ private: rb.PushIpcInterface<IDisplayController>(system); } - void GetDebugFunctions(Kernel::HLERequestContext& ctx) { + void GetDebugFunctions(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -188,7 +188,7 @@ private: rb.PushIpcInterface<IDebugFunctions>(system); } - void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { + void GetLibraryAppletCreator(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -196,7 +196,7 @@ private: rb.PushIpcInterface<ILibraryAppletCreator>(system); } - void GetHomeMenuFunctions(Kernel::HLERequestContext& ctx) { + void GetHomeMenuFunctions(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -204,7 +204,7 @@ private: rb.PushIpcInterface<IHomeMenuFunctions>(system); } - void GetGlobalStateController(Kernel::HLERequestContext& ctx) { + void GetGlobalStateController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -212,7 +212,7 @@ private: rb.PushIpcInterface<IGlobalStateController>(system); } - void GetApplicationCreator(Kernel::HLERequestContext& ctx) { + void GetApplicationCreator(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -220,38 +220,38 @@ private: rb.PushIpcInterface<IApplicationCreator>(system); } - NVFlinger::NVFlinger& nvflinger; + Nvnflinger::Nvnflinger& nvnflinger; std::shared_ptr<AppletMessageQueue> msg_queue; }; -void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { +void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISystemAppletProxy>(nvflinger, msg_queue, system); + rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, msg_queue, system); } -void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) { +void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); + rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system); } -void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { +void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); + rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system); } -AppletAE::AppletAE(NVFlinger::NVFlinger& nvflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, - Core::System& system_) - : ServiceFramework{system_, "appletAE"}, nvflinger{nvflinger_}, msg_queue{ - std::move(msg_queue_)} { +AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) + : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, msg_queue{ + std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 2147976a6..538ce2903 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h @@ -12,8 +12,8 @@ namespace FileSystem { class FileSystemController; } -namespace NVFlinger { -class NVFlinger; +namespace Nvnflinger { +class Nvnflinger; } namespace AM { @@ -22,18 +22,18 @@ class AppletMessageQueue; class AppletAE final : public ServiceFramework<AppletAE> { public: - explicit AppletAE(NVFlinger::NVFlinger& nvflinger_, + explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_); ~AppletAE() override; const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; private: - void OpenSystemAppletProxy(Kernel::HLERequestContext& ctx); - void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx); - void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); + void OpenSystemAppletProxy(HLERequestContext& ctx); + void OpenLibraryAppletProxy(HLERequestContext& ctx); + void OpenLibraryAppletProxyOld(HLERequestContext& ctx); - NVFlinger::NVFlinger& nvflinger; + Nvnflinger::Nvnflinger& nvnflinger; std::shared_ptr<AppletMessageQueue> msg_queue; }; diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index 00fc4202c..d6c565d85 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -2,20 +2,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_oe.h" -#include "core/hle/service/nvflinger/nvflinger.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" namespace Service::AM { class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { public: - explicit IApplicationProxy(NVFlinger::NVFlinger& nvflinger_, + explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) - : ServiceFramework{system_, "IApplicationProxy"}, nvflinger{nvflinger_}, - msg_queue{std::move(msg_queue_)} { + : ServiceFramework{system_, "IApplicationProxy"}, + nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -34,7 +34,7 @@ public: } private: - void GetAudioController(Kernel::HLERequestContext& ctx) { + void GetAudioController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -42,7 +42,7 @@ private: rb.PushIpcInterface<IAudioController>(system); } - void GetDisplayController(Kernel::HLERequestContext& ctx) { + void GetDisplayController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -50,7 +50,7 @@ private: rb.PushIpcInterface<IDisplayController>(system); } - void GetDebugFunctions(Kernel::HLERequestContext& ctx) { + void GetDebugFunctions(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -58,7 +58,7 @@ private: rb.PushIpcInterface<IDebugFunctions>(system); } - void GetWindowController(Kernel::HLERequestContext& ctx) { + void GetWindowController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -66,15 +66,15 @@ private: rb.PushIpcInterface<IWindowController>(system); } - void GetSelfController(Kernel::HLERequestContext& ctx) { + void GetSelfController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISelfController>(system, nvflinger); + rb.PushIpcInterface<ISelfController>(system, nvnflinger); } - void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { + void GetCommonStateGetter(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -82,7 +82,7 @@ private: rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); } - void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { + void GetLibraryAppletCreator(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -90,7 +90,7 @@ private: rb.PushIpcInterface<ILibraryAppletCreator>(system); } - void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { + void GetApplicationFunctions(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -98,22 +98,22 @@ private: rb.PushIpcInterface<IApplicationFunctions>(system); } - NVFlinger::NVFlinger& nvflinger; + Nvnflinger::Nvnflinger& nvnflinger; std::shared_ptr<AppletMessageQueue> msg_queue; }; -void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { +void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system); + rb.PushIpcInterface<IApplicationProxy>(nvnflinger, msg_queue, system); } -AppletOE::AppletOE(NVFlinger::NVFlinger& nvflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, - Core::System& system_) - : ServiceFramework{system_, "appletOE"}, nvflinger{nvflinger_}, msg_queue{ - std::move(msg_queue_)} { +AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) + : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, msg_queue{ + std::move(msg_queue_)} { static const FunctionInfo functions[] = { {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, }; diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 8fea249f1..39eccc4ab 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -12,8 +12,8 @@ namespace FileSystem { class FileSystemController; } -namespace NVFlinger { -class NVFlinger; +namespace Nvnflinger { +class Nvnflinger; } namespace AM { @@ -22,16 +22,16 @@ class AppletMessageQueue; class AppletOE final : public ServiceFramework<AppletOE> { public: - explicit AppletOE(NVFlinger::NVFlinger& nvflinger_, + explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_); ~AppletOE() override; const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; private: - void OpenApplicationProxy(Kernel::HLERequestContext& ctx); + void OpenApplicationProxy(HLERequestContext& ctx); - NVFlinger::NVFlinger& nvflinger; + Nvnflinger::Nvnflinger& nvnflinger; std::shared_ptr<AppletMessageQueue> msg_queue; }; diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index d0969b0f1..19ed184e8 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -11,7 +11,7 @@ #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_cabinet.h" #include "core/hle/service/mii/mii_manager.h" -#include "core/hle/service/nfp/nfp_device.h" +#include "core/hle/service/nfc/common/device.h" namespace Service::AM::Applets { @@ -72,10 +72,10 @@ void Cabinet::Execute() { // TODO: listen on all controllers if (nfp_device == nullptr) { - nfp_device = std::make_shared<Service::NFP::NfpDevice>( + nfp_device = std::make_shared<Service::NFC::NfcDevice>( system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event); nfp_device->Initialize(); - nfp_device->StartDetection(Service::NFP::TagProtocol::All); + nfp_device->StartDetection(Service::NFC::NfcProtocol::All); } const Core::Frontend::CabinetParameters parameters{ @@ -106,20 +106,22 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) Cancel(); } - if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && - nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { + if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound && + nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) { Cancel(); } - if (nfp_device->GetCurrentState() == Service::NFP::DeviceState::TagFound) { - nfp_device->Mount(Service::NFP::MountTarget::All); + if (nfp_device->GetCurrentState() == Service::NFC::DeviceState::TagFound) { + nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All); } switch (applet_input_common.applet_mode) { case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { - Service::NFP::AmiiboName name{}; - std::memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1)); - nfp_device->SetNicknameAndOwner(name); + Service::NFP::RegisterInfoPrivate register_info{}; + std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(), + std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1)); + + nfp_device->SetRegisterInfoPrivate(register_info); break; } case Service::NFP::CabinetMode::StartGameDataEraser: @@ -129,7 +131,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) nfp_device->RestoreAmiibo(); break; case Service::NFP::CabinetMode::StartFormatter: - nfp_device->DeleteAllData(); + nfp_device->Format(); break; default: UNIMPLEMENTED_MSG("Unknown CabinetMode={}", applet_input_common.applet_mode); @@ -174,4 +176,9 @@ void Cabinet::Cancel() { broker.SignalStateChanged(); } +Result Cabinet::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h index 84197a807..b56427021 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.h +++ b/src/core/hle/service/am/applets/applet_cabinet.h @@ -19,8 +19,8 @@ namespace Core { class System; } // namespace Core -namespace Service::NFP { -class NfpDevice; +namespace Service::NFC { +class NfcDevice; } namespace Service::AM::Applets { @@ -89,13 +89,14 @@ public: void Execute() override; void DisplayCompleted(bool apply_changes, std::string_view amiibo_name); void Cancel(); + Result RequestExit() override; private: const Core::Frontend::CabinetApplet& frontend; Core::System& system; bool is_complete{false}; - std::shared_ptr<Service::NFP::NfpDevice> nfp_device; + std::shared_ptr<Service::NFC::NfcDevice> nfp_device; Kernel::KEvent* availability_change_event; KernelHelpers::ServiceContext service_context; StartParamForAmiiboSettings applet_input_common{}; diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index b418031de..9840d2547 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp @@ -19,10 +19,9 @@ namespace Service::AM::Applets { -// This error code (0x183ACA) is thrown when the applet fails to initialize. -[[maybe_unused]] constexpr Result ERR_CONTROLLER_APPLET_3101{ErrorModule::HID, 3101}; -// This error code (0x183CCA) is thrown when the u32 result in ControllerSupportResultInfo is 2. -[[maybe_unused]] constexpr Result ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102}; +[[maybe_unused]] constexpr Result ResultControllerSupportCanceled{ErrorModule::HID, 3101}; +[[maybe_unused]] constexpr Result ResultControllerSupportNotSupportedNpadStyle{ErrorModule::HID, + 3102}; static Core::Frontend::ControllerParameters ConvertToFrontendParameters( ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, @@ -225,7 +224,8 @@ void Controller::Execute() { parameters.allow_dual_joycons, parameters.allow_left_joycon, parameters.allow_right_joycon); - frontend.ReconfigureControllers([this] { ConfigurationComplete(); }, parameters); + frontend.ReconfigureControllers( + [this](bool is_success) { ConfigurationComplete(is_success); }, parameters); break; } case ControllerSupportMode::ShowControllerStrapGuide: @@ -233,16 +233,16 @@ void Controller::Execute() { case ControllerSupportMode::ShowControllerKeyRemappingForSystem: UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented", controller_private_arg.mode); - ConfigurationComplete(); + ConfigurationComplete(true); break; default: { - ConfigurationComplete(); + ConfigurationComplete(true); break; } } } -void Controller::ConfigurationComplete() { +void Controller::ConfigurationComplete(bool is_success) { ControllerSupportResultInfo result_info{}; // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. @@ -251,7 +251,8 @@ void Controller::ConfigurationComplete() { result_info.selected_id = static_cast<u32>(system.HIDCore().GetFirstNpadId()); - result_info.result = 0; + result_info.result = + is_success ? ControllerSupportResult::Success : ControllerSupportResult::Cancel; LOG_DEBUG(Service_HID, "Result Info: player_count={}, selected_id={}, result={}", result_info.player_count, result_info.selected_id, result_info.result); @@ -263,4 +264,9 @@ void Controller::ConfigurationComplete() { broker.SignalStateChanged(); } +Result Controller::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h index 1f9adec65..f6c64f633 100644 --- a/src/core/hle/service/am/applets/applet_controller.h +++ b/src/core/hle/service/am/applets/applet_controller.h @@ -48,6 +48,11 @@ enum class ControllerSupportCaller : u8 { MaxControllerSupportCaller, }; +enum class ControllerSupportResult : u32 { + Success = 0, + Cancel = 2, +}; + struct ControllerSupportArgPrivate { u32 arg_private_size{}; u32 arg_size{}; @@ -112,7 +117,7 @@ struct ControllerSupportResultInfo { s8 player_count{}; INSERT_PADDING_BYTES(3); u32 selected_id{}; - u32 result{}; + ControllerSupportResult result{}; }; static_assert(sizeof(ControllerSupportResultInfo) == 0xC, "ControllerSupportResultInfo has incorrect size."); @@ -129,8 +134,9 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; - void ConfigurationComplete(); + void ConfigurationComplete(bool is_success); private: const Core::Frontend::ControllerApplet& frontend; diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index bae0d99a6..b46ea840c 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp @@ -166,7 +166,7 @@ void Error::Execute() { } const auto callback = [this] { DisplayCompleted(); }; - const auto title_id = system.GetCurrentProcessProgramID(); + const auto title_id = system.GetApplicationProcessProgramID(); const auto& reporter{system.GetReporter()}; switch (mode) { @@ -209,4 +209,9 @@ void Error::DisplayCompleted() { broker.SignalStateChanged(); } +Result Error::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_error.h b/src/core/hle/service/am/applets/applet_error.h index d78d6f1d1..d822a32bb 100644 --- a/src/core/hle/service/am/applets/applet_error.h +++ b/src/core/hle/service/am/applets/applet_error.h @@ -34,6 +34,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void DisplayCompleted(); diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp index e50acdaf6..8b352020e 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/applets/applet_general_backend.cpp @@ -150,6 +150,11 @@ void Auth::AuthFinished(bool is_successful) { broker.SignalStateChanged(); } +Result Auth::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, const Core::Frontend::PhotoViewerApplet& frontend_) : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} @@ -186,7 +191,7 @@ void PhotoViewer::Execute() { const auto callback = [this] { ViewFinished(); }; switch (mode) { case PhotoViewerAppletMode::CurrentApp: - frontend.ShowPhotosForApplication(system.GetCurrentProcessProgramID(), callback); + frontend.ShowPhotosForApplication(system.GetApplicationProcessProgramID(), callback); break; case PhotoViewerAppletMode::AllApps: frontend.ShowAllPhotos(callback); @@ -202,6 +207,11 @@ void PhotoViewer::ViewFinished() { broker.SignalStateChanged(); } +Result PhotoViewer::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_) : Applet{system_, applet_mode_}, id{id_}, system{system_} {} @@ -250,4 +260,9 @@ void StubApplet::Execute() { broker.SignalStateChanged(); } +Result StubApplet::RequestExit() { + // Nothing to do. + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_general_backend.h b/src/core/hle/service/am/applets/applet_general_backend.h index a9f2535a2..34ecaebb9 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.h +++ b/src/core/hle/service/am/applets/applet_general_backend.h @@ -28,6 +28,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void AuthFinished(bool is_successful = true); @@ -59,6 +60,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void ViewFinished(); @@ -80,6 +82,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; private: AppletId id; diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp index ae80ef506..d1f652c09 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp @@ -135,4 +135,9 @@ void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result, broker.SignalStateChanged(); } +Result MiiEdit::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/applets/applet_mii_edit.h index d18dd3cf5..3f46fae1b 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.h +++ b/src/core/hle/service/am/applets/applet_mii_edit.h @@ -25,6 +25,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void MiiEditOutput(MiiEditResult result, s32 index); diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp index c738db028..89cb323e9 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.cpp +++ b/src/core/hle/service/am/applets/applet_profile_select.cpp @@ -7,13 +7,12 @@ #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/profile_select.h" +#include "core/hle/service/acc/errors.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_profile_select.h" namespace Service::AM::Applets { -constexpr Result ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; - ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, const Core::Frontend::ProfileSelectApplet& frontend_) : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} @@ -26,13 +25,29 @@ void ProfileSelect::Initialize() { final_data.clear(); Applet::Initialize(); + profile_select_version = ProfileSelectAppletVersion{common_args.library_version}; const auto user_config_storage = broker.PopNormalDataToApplet(); ASSERT(user_config_storage != nullptr); const auto& user_config = user_config_storage->GetData(); - ASSERT(user_config.size() >= sizeof(UserSelectionConfig)); - std::memcpy(&config, user_config.data(), sizeof(UserSelectionConfig)); + LOG_INFO(Service_AM, "Initializing Profile Select Applet with version={}", + profile_select_version); + + switch (profile_select_version) { + case ProfileSelectAppletVersion::Version1: + ASSERT(user_config.size() == sizeof(UiSettingsV1)); + std::memcpy(&config_old, user_config.data(), sizeof(UiSettingsV1)); + break; + case ProfileSelectAppletVersion::Version2: + case ProfileSelectAppletVersion::Version3: + ASSERT(user_config.size() == sizeof(UiSettings)); + std::memcpy(&config, user_config.data(), sizeof(UiSettings)); + break; + default: + UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version); + break; + } } bool ProfileSelect::TransactionComplete() const { @@ -53,25 +68,56 @@ void ProfileSelect::Execute() { return; } - frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); }); + Core::Frontend::ProfileSelectParameters parameters{}; + + switch (profile_select_version) { + case ProfileSelectAppletVersion::Version1: + parameters = { + .mode = config_old.mode, + .invalid_uid_list = config_old.invalid_uid_list, + .display_options = config_old.display_options, + .purpose = UserSelectionPurpose::General, + }; + break; + case ProfileSelectAppletVersion::Version2: + case ProfileSelectAppletVersion::Version3: + parameters = { + .mode = config.mode, + .invalid_uid_list = config.invalid_uid_list, + .display_options = config.display_options, + .purpose = config.purpose, + }; + break; + default: + UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version); + break; + } + + frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); }, + parameters); } void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { - UserSelectionOutput output{}; + UiReturnArg output{}; if (uuid.has_value() && uuid->IsValid()) { output.result = 0; output.uuid_selected = *uuid; } else { - status = ERR_USER_CANCELLED_SELECTION; - output.result = ERR_USER_CANCELLED_SELECTION.raw; + status = Account::ResultCancelledByUser; + output.result = Account::ResultCancelledByUser.raw; output.uuid_selected = Common::InvalidUUID; } - final_data = std::vector<u8>(sizeof(UserSelectionOutput)); + final_data = std::vector<u8>(sizeof(UiReturnArg)); std::memcpy(final_data.data(), &output, final_data.size()); broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); broker.SignalStateChanged(); } +Result ProfileSelect::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_profile_select.h b/src/core/hle/service/am/applets/applet_profile_select.h index b77f1d205..369f9250f 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.h +++ b/src/core/hle/service/am/applets/applet_profile_select.h @@ -16,19 +16,100 @@ class System; namespace Service::AM::Applets { -struct UserSelectionConfig { - // TODO(DarkLordZach): RE this structure - // It seems to be flags and the like that determine the UI of the applet on the switch... from - // my research this is safe to ignore for now. - INSERT_PADDING_BYTES(0xA0); +enum class ProfileSelectAppletVersion : u32 { + Version1 = 0x1, // 1.0.0+ + Version2 = 0x10000, // 2.0.0+ + Version3 = 0x20000, // 6.0.0+ }; -static_assert(sizeof(UserSelectionConfig) == 0xA0, "UserSelectionConfig has incorrect size."); -struct UserSelectionOutput { +// This is nn::account::UiMode +enum class UiMode { + UserSelector, + UserCreator, + EnsureNetworkServiceAccountAvailable, + UserIconEditor, + UserNicknameEditor, + UserCreatorForStarter, + NintendoAccountAuthorizationRequestContext, + IntroduceExternalNetworkServiceAccount, + IntroduceExternalNetworkServiceAccountForRegistration, + NintendoAccountNnidLinker, + LicenseRequirementsForNetworkService, + LicenseRequirementsForNetworkServiceWithUserContextImpl, + UserCreatorForImmediateNaLoginTest, + UserQualificationPromoter, +}; + +// This is nn::account::UserSelectionPurpose +enum class UserSelectionPurpose { + General, + GameCardRegistration, + EShopLaunch, + EShopItemShow, + PicturePost, + NintendoAccountLinkage, + SettingsUpdate, + SaveDataDeletion, + UserMigration, + SaveDataTransfer, +}; + +// This is nn::account::NintendoAccountStartupDialogType +enum class NintendoAccountStartupDialogType { + LoginAndCreate, + Login, + Create, +}; + +// This is nn::account::UserSelectionSettingsForSystemService +struct UserSelectionSettingsForSystemService { + UserSelectionPurpose purpose; + bool enable_user_creation; + INSERT_PADDING_BYTES(0x3); +}; +static_assert(sizeof(UserSelectionSettingsForSystemService) == 0x8, + "UserSelectionSettingsForSystemService has incorrect size."); + +struct UiSettingsDisplayOptions { + bool is_network_service_account_required; + bool is_skip_enabled; + bool is_system_or_launcher; + bool is_registration_permitted; + bool show_skip_button; + bool aditional_select; + bool show_user_selector; + bool is_unqualified_user_selectable; +}; +static_assert(sizeof(UiSettingsDisplayOptions) == 0x8, + "UiSettingsDisplayOptions has incorrect size."); + +struct UiSettingsV1 { + UiMode mode; + INSERT_PADDING_BYTES(0x4); + std::array<Common::UUID, 8> invalid_uid_list; + u64 application_id; + UiSettingsDisplayOptions display_options; +}; +static_assert(sizeof(UiSettingsV1) == 0x98, "UiSettings has incorrect size."); + +// This is nn::account::UiSettings +struct UiSettings { + UiMode mode; + INSERT_PADDING_BYTES(0x4); + std::array<Common::UUID, 8> invalid_uid_list; + u64 application_id; + UiSettingsDisplayOptions display_options; + UserSelectionPurpose purpose; + INSERT_PADDING_BYTES(0x4); +}; +static_assert(sizeof(UiSettings) == 0xA0, "UiSettings has incorrect size."); + +// This is nn::account::UiReturnArg +struct UiReturnArg { u64 result; Common::UUID uuid_selected; }; -static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has incorrect size."); +static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size."); class ProfileSelect final : public Applet { public: @@ -42,13 +123,17 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void SelectionComplete(std::optional<Common::UUID> uuid); private: const Core::Frontend::ProfileSelectApplet& frontend; - UserSelectionConfig config; + UiSettings config; + UiSettingsV1 config_old; + ProfileSelectAppletVersion profile_select_version; + bool complete = false; Result status = ResultSuccess; std::vector<u8> final_data; diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp index c18236045..4145bb84f 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp @@ -770,6 +770,11 @@ void SoftwareKeyboard::ExitKeyboard() { broker.SignalStateChanged(); } +Result SoftwareKeyboard::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + // Inline Software Keyboard Requests void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) { diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.h b/src/core/hle/service/am/applets/applet_software_keyboard.h index b01b31c98..2e919811b 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.h +++ b/src/core/hle/service/am/applets/applet_software_keyboard.h @@ -31,6 +31,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; /** * Submits the input text to the application. diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp index 14aa6f69e..2accf7898 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/applets/applet_web_browser.cpp @@ -363,6 +363,11 @@ void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url) broker.SignalStateChanged(); } +Result WebBrowser::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + bool WebBrowser::InputTLVExistsInMap(WebArgInputTLVType input_tlv_type) const { return web_arg_input_tlv_map.find(input_tlv_type) != web_arg_input_tlv_map.end(); } @@ -393,7 +398,7 @@ void WebBrowser::InitializeOffline() { switch (document_kind) { case DocumentKind::OfflineHtmlPage: default: - title_id = system.GetCurrentProcessProgramID(); + title_id = system.GetApplicationProcessProgramID(); nca_type = FileSys::ContentRecordType::HtmlDocument; additional_paths = "html-document"; break; diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h index fd727fac8..99fe18659 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.h +++ b/src/core/hle/service/am/applets/applet_web_browser.h @@ -35,6 +35,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void ExtractOfflineRomFS(); diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index a22eb62a8..12f374199 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -142,6 +142,7 @@ public: virtual Result GetStatus() const = 0; virtual void ExecuteInteractive() = 0; virtual void Execute() = 0; + virtual Result RequestExit() = 0; AppletDataBroker& GetBroker() { return broker; diff --git a/src/core/hle/service/am/tcap.cpp b/src/core/hle/service/am/tcap.cpp deleted file mode 100644 index 818420e22..000000000 --- a/src/core/hle/service/am/tcap.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/tcap.h" - -namespace Service::AM { - -TCAP::TCAP(Core::System& system_) : ServiceFramework{system_, "tcap"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetContinuousHighSkinTemperatureEvent"}, - {1, nullptr, "SetOperationMode"}, - {2, nullptr, "LoadAndApplySettings"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -TCAP::~TCAP() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/tcap.h b/src/core/hle/service/am/tcap.h deleted file mode 100644 index 6b2148c29..000000000 --- a/src/core/hle/service/am/tcap.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::AM { - -class TCAP final : public ServiceFramework<TCAP> { -public: - explicit TCAP(Core::System& system_); - ~TCAP() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 368ccd52f..38c2138e8 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -14,9 +14,10 @@ #include "core/file_sys/nca_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/aoc/aoc_u.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/loader/loader.h" namespace Service::AOC { @@ -68,7 +69,7 @@ public: } private: - void SetDefaultDeliveryTarget(Kernel::HLERequestContext& ctx) { + void SetDefaultDeliveryTarget(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto unknown_1 = rp.Pop<u64>(); @@ -80,7 +81,7 @@ private: rb.Push(ResultSuccess); } - void SetDeliveryTarget(Kernel::HLERequestContext& ctx) { + void SetDeliveryTarget(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto unknown_1 = rp.Pop<u64>(); @@ -92,7 +93,7 @@ private: rb.Push(ResultSuccess); } - void GetPurchasedEventReadableHandle(Kernel::HLERequestContext& ctx) { + void GetPurchasedEventReadableHandle(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -129,6 +130,9 @@ AOC_U::AOC_U(Core::System& system_) {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"}, {110, nullptr, "CreateContentsServiceManager"}, {200, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"}, + {300, nullptr, "SetupHostAddOnContent"}, + {301, nullptr, "GetRegisteredAddOnContentPath"}, + {302, nullptr, "UpdateCachedList"}, }; // clang-format on @@ -141,7 +145,7 @@ AOC_U::~AOC_U() { service_context.CloseEvent(aoc_change_event); } -void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { +void AOC_U::CountAddOnContent(HLERequestContext& ctx) { struct Parameters { u64 process_id; }; @@ -155,7 +159,7 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - const auto current = system.GetCurrentProcessProgramID(); + const auto current = system.GetApplicationProcessProgramID(); const auto& disabled = Settings::values.disabled_addons[current]; if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) { @@ -168,7 +172,7 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); }))); } -void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { +void AOC_U::ListAddOnContent(HLERequestContext& ctx) { struct Parameters { u32 offset; u32 count; @@ -182,7 +186,7 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, process_id); - const auto current = system.GetCurrentProcessProgramID(); + const auto current = system.GetApplicationProcessProgramID(); std::vector<u32> out; const auto& disabled = Settings::values.disabled_addons[current]; @@ -214,7 +218,7 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { rb.Push(out_count); } -void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { +void AOC_U::GetAddOnContentBaseId(HLERequestContext& ctx) { struct Parameters { u64 process_id; }; @@ -228,7 +232,7 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - const auto title_id = system.GetCurrentProcessProgramID(); + const auto title_id = system.GetApplicationProcessProgramID(); const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), system.GetContentProvider()}; @@ -241,7 +245,7 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { rb.Push(res.first->GetDLCBaseTitleId()); } -void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) { +void AOC_U::PrepareAddOnContent(HLERequestContext& ctx) { struct Parameters { s32 addon_index; u64 process_id; @@ -258,7 +262,7 @@ void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) { +void AOC_U::GetAddOnContentListChangedEvent(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -266,7 +270,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) { rb.PushCopyObjects(aoc_change_event->GetReadableEvent()); } -void AOC_U::GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestContext& ctx) { +void AOC_U::GetAddOnContentListChangedEventWithProcessId(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -274,28 +278,28 @@ void AOC_U::GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestConte rb.PushCopyObjects(aoc_change_event->GetReadableEvent()); } -void AOC_U::NotifyMountAddOnContent(Kernel::HLERequestContext& ctx) { +void AOC_U::NotifyMountAddOnContent(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void AOC_U::NotifyUnmountAddOnContent(Kernel::HLERequestContext& ctx) { +void AOC_U::NotifyUnmountAddOnContent(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void AOC_U::CheckAddOnContentMountStatus(Kernel::HLERequestContext& ctx) { +void AOC_U::CheckAddOnContentMountStatus(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { +void AOC_U::CreateEcPurchasedEventManager(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -303,7 +307,7 @@ void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IPurchaseEventManager>(system); } -void AOC_U::CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { +void AOC_U::CreatePermanentEcPurchasedEventManager(HLERequestContext& ctx) { LOG_WARNING(Service_AOC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -311,8 +315,10 @@ void AOC_U::CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ct rb.PushIpcInterface<IPurchaseEventManager>(system); } -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<AOC_U>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + server_manager->RegisterNamedService("aoc:u", std::make_shared<AOC_U>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::AOC diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h index 6c1ce601a..12ccfeb6a 100644 --- a/src/core/hle/service/aoc/aoc_u.h +++ b/src/core/hle/service/aoc/aoc_u.h @@ -22,17 +22,17 @@ public: ~AOC_U() override; private: - void CountAddOnContent(Kernel::HLERequestContext& ctx); - void ListAddOnContent(Kernel::HLERequestContext& ctx); - void GetAddOnContentBaseId(Kernel::HLERequestContext& ctx); - void PrepareAddOnContent(Kernel::HLERequestContext& ctx); - void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx); - void GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestContext& ctx); - void NotifyMountAddOnContent(Kernel::HLERequestContext& ctx); - void NotifyUnmountAddOnContent(Kernel::HLERequestContext& ctx); - void CheckAddOnContentMountStatus(Kernel::HLERequestContext& ctx); - void CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx); - void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx); + void CountAddOnContent(HLERequestContext& ctx); + void ListAddOnContent(HLERequestContext& ctx); + void GetAddOnContentBaseId(HLERequestContext& ctx); + void PrepareAddOnContent(HLERequestContext& ctx); + void GetAddOnContentListChangedEvent(HLERequestContext& ctx); + void GetAddOnContentListChangedEventWithProcessId(HLERequestContext& ctx); + void NotifyMountAddOnContent(HLERequestContext& ctx); + void NotifyUnmountAddOnContent(HLERequestContext& ctx); + void CheckAddOnContentMountStatus(HLERequestContext& ctx); + void CreateEcPurchasedEventManager(HLERequestContext& ctx); + void CreatePermanentEcPurchasedEventManager(HLERequestContext& ctx); std::vector<u64> add_on_content; KernelHelpers::ServiceContext service_context; @@ -40,7 +40,6 @@ private: Kernel::KEvent* aoc_change_event; }; -/// Registers all AOC services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::AOC diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp index 8a338d9b1..c23ff293d 100644 --- a/src/core/hle/service/apm/apm.cpp +++ b/src/core/hle/service/apm/apm.cpp @@ -4,22 +4,24 @@ #include "core/core.h" #include "core/hle/service/apm/apm.h" #include "core/hle/service/apm/apm_interface.h" +#include "core/hle/service/server_manager.h" namespace Service::APM { Module::Module() = default; Module::~Module() = default; -void InstallInterfaces(Core::System& system) { - auto module_ = std::make_shared<Module>(); - std::make_shared<APM>(system, module_, system.GetAPMController(), "apm") - ->InstallAsService(system.ServiceManager()); - std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:p") - ->InstallAsService(system.ServiceManager()); - std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:am") - ->InstallAsService(system.ServiceManager()); - std::make_shared<APM_Sys>(system, system.GetAPMController()) - ->InstallAsService(system.ServiceManager()); +void LoopProcess(Core::System& system) { + auto module = std::make_shared<Module>(); + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService( + "apm", std::make_shared<APM>(system, module, system.GetAPMController(), "apm")); + server_manager->RegisterNamedService( + "apm:am", std::make_shared<APM>(system, module, system.GetAPMController(), "apm:am")); + server_manager->RegisterNamedService( + "apm:sys", std::make_shared<APM_Sys>(system, system.GetAPMController())); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::APM diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h index 0fecc766a..e188b4e44 100644 --- a/src/core/hle/service/apm/apm.h +++ b/src/core/hle/service/apm/apm.h @@ -15,7 +15,6 @@ public: ~Module(); }; -/// Registers all AM services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::APM diff --git a/src/core/hle/service/apm/apm_controller.cpp b/src/core/hle/service/apm/apm_controller.cpp index d6de84066..227fdd0cf 100644 --- a/src/core/hle/service/apm/apm_controller.cpp +++ b/src/core/hle/service/apm/apm_controller.cpp @@ -56,7 +56,7 @@ void Controller::SetPerformanceConfiguration(PerformanceMode mode, } void Controller::SetFromCpuBoostMode(CpuBoostMode mode) { - constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{ + static constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{ PerformanceConfiguration::Config7, PerformanceConfiguration::Config13, PerformanceConfiguration::Config15, diff --git a/src/core/hle/service/apm/apm_interface.cpp b/src/core/hle/service/apm/apm_interface.cpp index 041fc16bd..d29051ee7 100644 --- a/src/core/hle/service/apm/apm_interface.cpp +++ b/src/core/hle/service/apm/apm_interface.cpp @@ -2,10 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/apm/apm.h" #include "core/hle/service/apm/apm_controller.h" #include "core/hle/service/apm/apm_interface.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::APM { @@ -22,7 +22,7 @@ public: } private: - void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { + void SetPerformanceConfiguration(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto mode = rp.PopEnum<PerformanceMode>(); @@ -35,7 +35,7 @@ private: rb.Push(ResultSuccess); } - void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { + void GetPerformanceConfiguration(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto mode = rp.PopEnum<PerformanceMode>(); @@ -46,7 +46,7 @@ private: rb.PushEnum(controller.GetCurrentPerformanceConfiguration(mode)); } - void SetCpuOverclockEnabled(Kernel::HLERequestContext& ctx) { + void SetCpuOverclockEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto cpu_overclock_enabled = rp.Pop<bool>(); @@ -74,7 +74,7 @@ APM::APM(Core::System& system_, std::shared_ptr<Module> apm_, Controller& contro APM::~APM() = default; -void APM::OpenSession(Kernel::HLERequestContext& ctx) { +void APM::OpenSession(HLERequestContext& ctx) { LOG_DEBUG(Service_APM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -82,14 +82,14 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<ISession>(system, controller); } -void APM::GetPerformanceMode(Kernel::HLERequestContext& ctx) { +void APM::GetPerformanceMode(HLERequestContext& ctx) { LOG_DEBUG(Service_APM, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.PushEnum(controller.GetCurrentPerformanceMode()); } -void APM::IsCpuOverclockEnabled(Kernel::HLERequestContext& ctx) { +void APM::IsCpuOverclockEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_APM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -117,7 +117,7 @@ APM_Sys::APM_Sys(Core::System& system_, Controller& controller_) APM_Sys::~APM_Sys() = default; -void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) { +void APM_Sys::GetPerformanceEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_APM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -125,7 +125,7 @@ void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<ISession>(system, controller); } -void APM_Sys::SetCpuBoostMode(Kernel::HLERequestContext& ctx) { +void APM_Sys::SetCpuBoostMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto mode = rp.PopEnum<CpuBoostMode>(); @@ -137,7 +137,7 @@ void APM_Sys::SetCpuBoostMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void APM_Sys::GetCurrentPerformanceConfiguration(Kernel::HLERequestContext& ctx) { +void APM_Sys::GetCurrentPerformanceConfiguration(HLERequestContext& ctx) { LOG_DEBUG(Service_APM, "called"); IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/apm/apm_interface.h b/src/core/hle/service/apm/apm_interface.h index 0740fd4ba..58718453b 100644 --- a/src/core/hle/service/apm/apm_interface.h +++ b/src/core/hle/service/apm/apm_interface.h @@ -17,9 +17,9 @@ public: ~APM() override; private: - void OpenSession(Kernel::HLERequestContext& ctx); - void GetPerformanceMode(Kernel::HLERequestContext& ctx); - void IsCpuOverclockEnabled(Kernel::HLERequestContext& ctx); + void OpenSession(HLERequestContext& ctx); + void GetPerformanceMode(HLERequestContext& ctx); + void IsCpuOverclockEnabled(HLERequestContext& ctx); std::shared_ptr<Module> apm; Controller& controller; @@ -30,11 +30,11 @@ public: explicit APM_Sys(Core::System& system_, Controller& controller); ~APM_Sys() override; - void SetCpuBoostMode(Kernel::HLERequestContext& ctx); + void SetCpuBoostMode(HLERequestContext& ctx); private: - void GetPerformanceEvent(Kernel::HLERequestContext& ctx); - void GetCurrentPerformanceConfiguration(Kernel::HLERequestContext& ctx); + void GetPerformanceEvent(HLERequestContext& ctx); + void GetCurrentPerformanceConfiguration(HLERequestContext& ctx); Controller& controller; }; diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index 5abf22ba4..7ad93be6b 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/audio/audctl.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Audio { @@ -72,7 +72,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { AudCtl::~AudCtl() = default; -void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) { +void AudCtl::GetTargetVolumeMin(HLERequestContext& ctx) { LOG_DEBUG(Audio, "called."); // This service function is currently hardcoded on the @@ -84,7 +84,7 @@ void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) { rb.Push(target_min_volume); } -void AudCtl::GetTargetVolumeMax(Kernel::HLERequestContext& ctx) { +void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) { LOG_DEBUG(Audio, "called."); // This service function is currently hardcoded on the diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h index a27ff6cfe..8e31ac237 100644 --- a/src/core/hle/service/audio/audctl.h +++ b/src/core/hle/service/audio/audctl.h @@ -17,8 +17,8 @@ public: ~AudCtl() override; private: - void GetTargetVolumeMin(Kernel::HLERequestContext& ctx); - void GetTargetVolumeMax(Kernel::HLERequestContext& ctx); + void GetTargetVolumeMin(HLERequestContext& ctx); + void GetTargetVolumeMax(HLERequestContext& ctx); }; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/auddbg.cpp b/src/core/hle/service/audio/auddbg.cpp deleted file mode 100644 index 5541af300..000000000 --- a/src/core/hle/service/audio/auddbg.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/auddbg.h" - -namespace Service::Audio { - -AudDbg::AudDbg(Core::System& system_, const char* name) : ServiceFramework{system_, name} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspendForDebug"}, - {1, nullptr, "RequestResumeForDebug"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudDbg::~AudDbg() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/auddbg.h b/src/core/hle/service/audio/auddbg.h deleted file mode 100644 index 8f26be5dc..000000000 --- a/src/core/hle/service/audio/auddbg.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudDbg final : public ServiceFramework<AudDbg> { -public: - explicit AudDbg(Core::System& system_, const char* name); - ~AudDbg() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp deleted file mode 100644 index 98f4a6048..000000000 --- a/src/core/hle/service/audio/audin_a.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/audin_a.h" - -namespace Service::Audio { - -AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspend"}, - {1, nullptr, "RequestResume"}, - {2, nullptr, "GetProcessMasterVolume"}, - {3, nullptr, "SetProcessMasterVolume"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudInA::~AudInA() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audin_a.h b/src/core/hle/service/audio/audin_a.h deleted file mode 100644 index 19a927de5..000000000 --- a/src/core/hle/service/audio/audin_a.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudInA final : public ServiceFramework<AudInA> { -public: - explicit AudInA(Core::System& system_); - ~AudInA() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 053e8f9dd..c8d574993 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -5,11 +5,12 @@ #include "audio_core/renderer/audio_device.h" #include "common/common_funcs.h" #include "common/logging/log.h" +#include "common/settings.h" #include "common/string_util.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/audio/audin_u.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Audio { using namespace AudioCore::AudioIn; @@ -61,7 +62,7 @@ public: } private: - void GetAudioInState(Kernel::HLERequestContext& ctx) { + void GetAudioInState(HLERequestContext& ctx) { const auto state = static_cast<u32>(impl->GetState()); LOG_DEBUG(Service_Audio, "called. State={}", state); @@ -71,7 +72,7 @@ private: rb.Push(state); } - void Start(Kernel::HLERequestContext& ctx) { + void Start(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto result = impl->StartSystem(); @@ -80,7 +81,7 @@ private: rb.Push(result); } - void Stop(Kernel::HLERequestContext& ctx) { + void Stop(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto result = impl->StopSystem(); @@ -89,7 +90,7 @@ private: rb.Push(result); } - void AppendAudioInBuffer(Kernel::HLERequestContext& ctx) { + void AppendAudioInBuffer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u64 tag = rp.PopRaw<u64>(); @@ -111,7 +112,7 @@ private: rb.Push(result); } - void RegisterBufferEvent(Kernel::HLERequestContext& ctx) { + void RegisterBufferEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto& buffer_event = impl->GetBufferEvent(); @@ -121,27 +122,21 @@ private: rb.PushCopyObjects(buffer_event); } - void GetReleasedAudioInBuffer(Kernel::HLERequestContext& ctx) { + void GetReleasedAudioInBuffer(HLERequestContext& ctx) { const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); - std::vector<u64> released_buffers(write_buffer_size); + tmp_buffer.resize_destructive(write_buffer_size); + tmp_buffer[0] = 0; - const auto count = impl->GetReleasedBuffers(released_buffers); + const auto count = impl->GetReleasedBuffers(tmp_buffer); - [[maybe_unused]] std::string tags{}; - for (u32 i = 0; i < count; i++) { - tags += fmt::format("{:08X}, ", released_buffers[i]); - } - [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()}; - LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count, - tags); + ctx.WriteBuffer(tmp_buffer); - ctx.WriteBuffer(released_buffers); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(count); } - void ContainsAudioInBuffer(Kernel::HLERequestContext& ctx) { + void ContainsAudioInBuffer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 tag{rp.Pop<u64>()}; @@ -154,7 +149,7 @@ private: rb.Push(buffer_queued); } - void GetAudioInBufferCount(Kernel::HLERequestContext& ctx) { + void GetAudioInBufferCount(HLERequestContext& ctx) { const auto buffer_count = impl->GetBufferCount(); LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); @@ -165,7 +160,7 @@ private: rb.Push(buffer_count); } - void SetDeviceGain(Kernel::HLERequestContext& ctx) { + void SetDeviceGain(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto volume{rp.Pop<f32>()}; @@ -177,7 +172,7 @@ private: rb.Push(ResultSuccess); } - void GetDeviceGain(Kernel::HLERequestContext& ctx) { + void GetDeviceGain(HLERequestContext& ctx) { auto volume{impl->GetVolume()}; LOG_DEBUG(Service_Audio, "called. Gain {}", volume); @@ -187,7 +182,7 @@ private: rb.Push(volume); } - void FlushAudioInBuffers(Kernel::HLERequestContext& ctx) { + void FlushAudioInBuffers(HLERequestContext& ctx) { bool flushed{impl->FlushAudioInBuffers()}; LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", flushed); @@ -200,12 +195,12 @@ private: KernelHelpers::ServiceContext service_context; Kernel::KEvent* event; std::shared_ptr<AudioCore::AudioIn::In> impl; + Common::ScratchBuffer<u64> tmp_buffer; }; AudInU::AudInU(Core::System& system_) - : ServiceFramework{system_, "audin:u", ServiceThreadType::CreateNew}, - service_context{system_, "AudInU"}, impl{std::make_unique<AudioCore::AudioIn::Manager>( - system_)} { + : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"}, + impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} { // clang-format off static const FunctionInfo functions[] = { {0, &AudInU::ListAudioIns, "ListAudioIns"}, @@ -222,7 +217,7 @@ AudInU::AudInU(Core::System& system_) AudInU::~AudInU() = default; -void AudInU::ListAudioIns(Kernel::HLERequestContext& ctx) { +void AudInU::ListAudioIns(HLERequestContext& ctx) { using namespace AudioCore::AudioRenderer; LOG_DEBUG(Service_Audio, "called"); @@ -242,7 +237,7 @@ void AudInU::ListAudioIns(Kernel::HLERequestContext& ctx) { rb.Push(out_count); } -void AudInU::ListAudioInsAutoFiltered(Kernel::HLERequestContext& ctx) { +void AudInU::ListAudioInsAutoFiltered(HLERequestContext& ctx) { using namespace AudioCore::AudioRenderer; LOG_DEBUG(Service_Audio, "called"); @@ -262,7 +257,7 @@ void AudInU::ListAudioInsAutoFiltered(Kernel::HLERequestContext& ctx) { rb.Push(out_count); } -void AudInU::OpenAudioIn(Kernel::HLERequestContext& ctx) { +void AudInU::OpenAudioIn(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto in_params{rp.PopRaw<AudioInParameter>()}; auto applet_resource_user_id{rp.PopRaw<u64>()}; @@ -312,7 +307,7 @@ void AudInU::OpenAudioIn(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IAudioIn>(audio_in); } -void AudInU::OpenAudioInProtocolSpecified(Kernel::HLERequestContext& ctx) { +void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto protocol_specified{rp.PopRaw<u64>()}; auto in_params{rp.PopRaw<AudioInParameter>()}; diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h index b45fda78a..51e770ff9 100644 --- a/src/core/hle/service/audio/audin_u.h +++ b/src/core/hle/service/audio/audin_u.h @@ -12,10 +12,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace AudioCore::AudioOut { class Manager; class In; @@ -29,11 +25,11 @@ public: ~AudInU() override; private: - void ListAudioIns(Kernel::HLERequestContext& ctx); - void ListAudioInsAutoFiltered(Kernel::HLERequestContext& ctx); - void OpenInOutImpl(Kernel::HLERequestContext& ctx); - void OpenAudioIn(Kernel::HLERequestContext& ctx); - void OpenAudioInProtocolSpecified(Kernel::HLERequestContext& ctx); + void ListAudioIns(HLERequestContext& ctx); + void ListAudioInsAutoFiltered(HLERequestContext& ctx); + void OpenInOutImpl(HLERequestContext& ctx); + void OpenAudioIn(HLERequestContext& ctx); + void OpenAudioInProtocolSpecified(HLERequestContext& ctx); KernelHelpers::ServiceContext service_context; std::unique_ptr<AudioCore::AudioIn::Manager> impl; diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp index 97da71dfa..dccd16309 100644 --- a/src/core/hle/service/audio/audio.cpp +++ b/src/core/hle/service/audio/audio.cpp @@ -1,40 +1,31 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/core.h" #include "core/hle/service/audio/audctl.h" -#include "core/hle/service/audio/auddbg.h" -#include "core/hle/service/audio/audin_a.h" #include "core/hle/service/audio/audin_u.h" #include "core/hle/service/audio/audio.h" -#include "core/hle/service/audio/audout_a.h" #include "core/hle/service/audio/audout_u.h" #include "core/hle/service/audio/audrec_a.h" #include "core/hle/service/audio/audrec_u.h" -#include "core/hle/service/audio/audren_a.h" #include "core/hle/service/audio/audren_u.h" -#include "core/hle/service/audio/codecctl.h" #include "core/hle/service/audio/hwopus.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::Audio { -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<AudCtl>(system)->InstallAsService(service_manager); - std::make_shared<AudOutA>(system)->InstallAsService(service_manager); - std::make_shared<AudOutU>(system)->InstallAsService(service_manager); - std::make_shared<AudInA>(system)->InstallAsService(service_manager); - std::make_shared<AudInU>(system)->InstallAsService(service_manager); - std::make_shared<AudRecA>(system)->InstallAsService(service_manager); - std::make_shared<AudRecU>(system)->InstallAsService(service_manager); - std::make_shared<AudRenA>(system)->InstallAsService(service_manager); - std::make_shared<AudRenU>(system)->InstallAsService(service_manager); - std::make_shared<CodecCtl>(system)->InstallAsService(service_manager); - std::make_shared<HwOpus>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); - std::make_shared<AudDbg>(system, "audin:d")->InstallAsService(service_manager); - std::make_shared<AudDbg>(system, "audout:d")->InstallAsService(service_manager); - std::make_shared<AudDbg>(system, "audrec:d")->InstallAsService(service_manager); - std::make_shared<AudDbg>(system, "audren:d")->InstallAsService(service_manager); + server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system)); + server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system)); + server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system)); + server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system)); + server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system)); + server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system)); + server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio.h b/src/core/hle/service/audio/audio.h index bbb2214e4..d70f022c7 100644 --- a/src/core/hle/service/audio/audio.h +++ b/src/core/hle/service/audio/audio.h @@ -13,7 +13,6 @@ class ServiceManager; namespace Service::Audio { -/// Registers all Audio services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp deleted file mode 100644 index 5ecb99236..000000000 --- a/src/core/hle/service/audio/audout_a.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/audout_a.h" - -namespace Service::Audio { - -AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspend"}, - {1, nullptr, "RequestResume"}, - {2, nullptr, "GetProcessMasterVolume"}, - {3, nullptr, "SetProcessMasterVolume"}, - {4, nullptr, "GetProcessRecordVolume"}, - {5, nullptr, "SetProcessRecordVolume"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudOutA::~AudOutA() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audout_a.h b/src/core/hle/service/audio/audout_a.h deleted file mode 100644 index f641cffeb..000000000 --- a/src/core/hle/service/audio/audout_a.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudOutA final : public ServiceFramework<AudOutA> { -public: - explicit AudOutA(Core::System& system_); - ~AudOutA() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 29751f075..032c8c11f 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -12,10 +12,10 @@ #include "common/string_util.h" #include "common/swap.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/audio/audout_u.h" #include "core/hle/service/audio/errors.h" +#include "core/hle/service/ipc_helpers.h" #include "core/memory.h" namespace Service::Audio { @@ -26,9 +26,8 @@ public: explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, size_t session_id, const std::string& device_name, const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) - : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, - service_context{system_, "IAudioOut"}, event{service_context.CreateEvent( - "AudioOutEvent")}, + : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, + event{service_context.CreateEvent("AudioOutEvent")}, impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { // clang-format off @@ -50,12 +49,6 @@ public: }; // clang-format on RegisterHandlers(functions); - - if (impl->GetSystem() - .Initialize(device_name, in_params, handle, applet_resource_user_id) - .IsError()) { - LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!"); - } } ~IAudioOut() override { @@ -68,7 +61,7 @@ public: } private: - void GetAudioOutState(Kernel::HLERequestContext& ctx) { + void GetAudioOutState(HLERequestContext& ctx) { const auto state = static_cast<u32>(impl->GetState()); LOG_DEBUG(Service_Audio, "called. State={}", state); @@ -78,7 +71,7 @@ private: rb.Push(state); } - void Start(Kernel::HLERequestContext& ctx) { + void Start(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto result = impl->StartSystem(); @@ -87,7 +80,7 @@ private: rb.Push(result); } - void Stop(Kernel::HLERequestContext& ctx) { + void Stop(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto result = impl->StopSystem(); @@ -96,7 +89,7 @@ private: rb.Push(result); } - void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) { + void AppendAudioOutBuffer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u64 tag = rp.PopRaw<u64>(); @@ -118,7 +111,7 @@ private: rb.Push(result); } - void RegisterBufferEvent(Kernel::HLERequestContext& ctx) { + void RegisterBufferEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto& buffer_event = impl->GetBufferEvent(); @@ -128,27 +121,21 @@ private: rb.PushCopyObjects(buffer_event); } - void GetReleasedAudioOutBuffers(Kernel::HLERequestContext& ctx) { + void GetReleasedAudioOutBuffers(HLERequestContext& ctx) { const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); - std::vector<u64> released_buffers(write_buffer_size); + tmp_buffer.resize_destructive(write_buffer_size); + tmp_buffer[0] = 0; - const auto count = impl->GetReleasedBuffers(released_buffers); + const auto count = impl->GetReleasedBuffers(tmp_buffer); - [[maybe_unused]] std::string tags{}; - for (u32 i = 0; i < count; i++) { - tags += fmt::format("{:08X}, ", released_buffers[i]); - } - [[maybe_unused]] const auto sessionid{impl->GetSystem().GetSessionId()}; - LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count, - tags); + ctx.WriteBuffer(tmp_buffer); - ctx.WriteBuffer(released_buffers); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(count); } - void ContainsAudioOutBuffer(Kernel::HLERequestContext& ctx) { + void ContainsAudioOutBuffer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 tag{rp.Pop<u64>()}; @@ -161,7 +148,7 @@ private: rb.Push(buffer_queued); } - void GetAudioOutBufferCount(Kernel::HLERequestContext& ctx) { + void GetAudioOutBufferCount(HLERequestContext& ctx) { const auto buffer_count = impl->GetBufferCount(); LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); @@ -172,7 +159,7 @@ private: rb.Push(buffer_count); } - void GetAudioOutPlayedSampleCount(Kernel::HLERequestContext& ctx) { + void GetAudioOutPlayedSampleCount(HLERequestContext& ctx) { const auto samples_played = impl->GetPlayedSampleCount(); LOG_DEBUG(Service_Audio, "called. Played samples={}", samples_played); @@ -183,7 +170,7 @@ private: rb.Push(samples_played); } - void FlushAudioOutBuffers(Kernel::HLERequestContext& ctx) { + void FlushAudioOutBuffers(HLERequestContext& ctx) { bool flushed{impl->FlushAudioOutBuffers()}; LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", flushed); @@ -193,7 +180,7 @@ private: rb.Push(flushed); } - void SetAudioOutVolume(Kernel::HLERequestContext& ctx) { + void SetAudioOutVolume(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto volume = rp.Pop<f32>(); @@ -205,7 +192,7 @@ private: rb.Push(ResultSuccess); } - void GetAudioOutVolume(Kernel::HLERequestContext& ctx) { + void GetAudioOutVolume(HLERequestContext& ctx) { const auto volume = impl->GetVolume(); LOG_DEBUG(Service_Audio, "called. Volume={}", volume); @@ -218,12 +205,12 @@ private: KernelHelpers::ServiceContext service_context; Kernel::KEvent* event; std::shared_ptr<AudioCore::AudioOut::Out> impl; + Common::ScratchBuffer<u64> tmp_buffer; }; AudOutU::AudOutU(Core::System& system_) - : ServiceFramework{system_, "audout:u", ServiceThreadType::CreateNew}, - service_context{system_, "AudOutU"}, impl{std::make_unique<AudioCore::AudioOut::Manager>( - system_)} { + : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"}, + impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} { // clang-format off static const FunctionInfo functions[] = { {0, &AudOutU::ListAudioOuts, "ListAudioOuts"}, @@ -238,7 +225,7 @@ AudOutU::AudOutU(Core::System& system_) AudOutU::~AudOutU() = default; -void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { +void AudOutU::ListAudioOuts(HLERequestContext& ctx) { using namespace AudioCore::AudioRenderer; std::scoped_lock l{impl->mutex}; @@ -260,7 +247,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { rb.Push<u32>(static_cast<u32>(device_names.size())); } -void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) { +void AudOutU::OpenAudioOut(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto in_params{rp.PopRaw<AudioOutParameter>()}; auto applet_resource_user_id{rp.PopRaw<u64>()}; @@ -289,6 +276,14 @@ void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) { auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params, handle, applet_resource_user_id); + result = audio_out->GetImpl()->GetSystem().Initialize(device_name, in_params, handle, + applet_resource_user_id); + if (result.IsError()) { + LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } impl->sessions[new_session_id] = audio_out->GetImpl(); impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h index fdc0ee754..8f288c6e0 100644 --- a/src/core/hle/service/audio/audout_u.h +++ b/src/core/hle/service/audio/audout_u.h @@ -12,10 +12,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace AudioCore::AudioOut { class Manager; class Out; @@ -31,8 +27,8 @@ public: ~AudOutU() override; private: - void ListAudioOuts(Kernel::HLERequestContext& ctx); - void OpenAudioOut(Kernel::HLERequestContext& ctx); + void ListAudioOuts(HLERequestContext& ctx); + void OpenAudioOut(HLERequestContext& ctx); KernelHelpers::ServiceContext service_context; std::unique_ptr<AudioCore::AudioOut::Manager> impl; diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp deleted file mode 100644 index e775ac3bf..000000000 --- a/src/core/hle/service/audio/audren_a.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/audren_a.h" - -namespace Service::Audio { - -AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspend"}, - {1, nullptr, "RequestResume"}, - {2, nullptr, "GetProcessMasterVolume"}, - {3, nullptr, "SetProcessMasterVolume"}, - {4, nullptr, "RegisterAppletResourceUserId"}, - {5, nullptr, "UnregisterAppletResourceUserId"}, - {6, nullptr, "GetProcessRecordVolume"}, - {7, nullptr, "SetProcessRecordVolume"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudRenA::~AudRenA() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audren_a.h b/src/core/hle/service/audio/audren_a.h deleted file mode 100644 index 9e08b4245..000000000 --- a/src/core/hle/service/audio/audren_a.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudRenA final : public ServiceFramework<AudRenA> { -public: - explicit AudRenA(Core::System& system_); - ~AudRenA() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 3a1c231b6..12845c23a 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -17,12 +17,12 @@ #include "common/polyfill_ranges.h" #include "common/string_util.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/service/audio/audren_u.h" #include "core/hle/service/audio/errors.h" +#include "core/hle/service/ipc_helpers.h" #include "core/memory.h" using namespace AudioCore::AudioRenderer; @@ -35,10 +35,9 @@ public: AudioCore::AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, u32 process_handle, u64 applet_resource_user_id, s32 session_id) - : ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew}, - service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent( - "IAudioRendererEvent")}, - manager{manager_}, impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { + : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, + rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, + impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, @@ -69,7 +68,7 @@ public: } private: - void GetSampleRate(Kernel::HLERequestContext& ctx) { + void GetSampleRate(HLERequestContext& ctx) { const auto sample_rate{impl->GetSystem().GetSampleRate()}; LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate); @@ -79,7 +78,7 @@ private: rb.Push(sample_rate); } - void GetSampleCount(Kernel::HLERequestContext& ctx) { + void GetSampleCount(HLERequestContext& ctx) { const auto sample_count{impl->GetSystem().GetSampleCount()}; LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count); @@ -89,7 +88,7 @@ private: rb.Push(sample_count); } - void GetState(Kernel::HLERequestContext& ctx) { + void GetState(HLERequestContext& ctx) { const u32 state{!impl->GetSystem().IsActive()}; LOG_DEBUG(Service_Audio, "called, state {}", state); @@ -99,7 +98,7 @@ private: rb.Push(state); } - void GetMixBufferCount(Kernel::HLERequestContext& ctx) { + void GetMixBufferCount(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); const auto buffer_count{impl->GetSystem().GetMixBufferCount()}; @@ -109,36 +108,34 @@ private: rb.Push(buffer_count); } - void RequestUpdate(Kernel::HLERequestContext& ctx) { + void RequestUpdate(HLERequestContext& ctx) { LOG_TRACE(Service_Audio, "called"); - std::vector<u8> input{ctx.ReadBuffer(0)}; + const auto input{ctx.ReadBuffer(0)}; // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for // checking size 0. Performance size is 0 for most games. - std::vector<u8> output{}; - std::vector<u8> performance{}; auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0}; if (is_buffer_b) { const auto buffersB{ctx.BufferDescriptorB()}; - output.resize(buffersB[0].Size(), 0); - performance.resize(buffersB[1].Size(), 0); + tmp_output.resize_destructive(buffersB[0].Size()); + tmp_performance.resize_destructive(buffersB[1].Size()); } else { const auto buffersC{ctx.BufferDescriptorC()}; - output.resize(buffersC[0].Size(), 0); - performance.resize(buffersC[1].Size(), 0); + tmp_output.resize_destructive(buffersC[0].Size()); + tmp_performance.resize_destructive(buffersC[1].Size()); } - auto result = impl->RequestUpdate(input, performance, output); + auto result = impl->RequestUpdate(input, tmp_performance, tmp_output); if (result.IsSuccess()) { if (is_buffer_b) { - ctx.WriteBufferB(output.data(), output.size(), 0); - ctx.WriteBufferB(performance.data(), performance.size(), 1); + ctx.WriteBufferB(tmp_output.data(), tmp_output.size(), 0); + ctx.WriteBufferB(tmp_performance.data(), tmp_performance.size(), 1); } else { - ctx.WriteBufferC(output.data(), output.size(), 0); - ctx.WriteBufferC(performance.data(), performance.size(), 1); + ctx.WriteBufferC(tmp_output.data(), tmp_output.size(), 0); + ctx.WriteBufferC(tmp_performance.data(), tmp_performance.size(), 1); } } else { LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); @@ -148,7 +145,7 @@ private: rb.Push(result); } - void Start(Kernel::HLERequestContext& ctx) { + void Start(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); impl->Start(); @@ -157,7 +154,7 @@ private: rb.Push(ResultSuccess); } - void Stop(Kernel::HLERequestContext& ctx) { + void Stop(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); impl->Stop(); @@ -166,12 +163,12 @@ private: rb.Push(ResultSuccess); } - void QuerySystemEvent(Kernel::HLERequestContext& ctx) { + void QuerySystemEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NOT_SUPPORTED); + rb.Push(Audio::ResultNotSupported); return; } @@ -180,7 +177,7 @@ private: rb.PushCopyObjects(rendered_event->GetReadableEvent()); } - void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { + void SetRenderingTimeLimit(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); IPC::RequestParser rp{ctx}; @@ -193,7 +190,7 @@ private: rb.Push(ResultSuccess); } - void GetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { + void GetRenderingTimeLimit(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto& system_ = impl->GetSystem(); @@ -204,11 +201,11 @@ private: rb.Push(time); } - void ExecuteAudioRendererRendering(Kernel::HLERequestContext& ctx) { + void ExecuteAudioRendererRendering(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); } - void SetVoiceDropParameter(Kernel::HLERequestContext& ctx) { + void SetVoiceDropParameter(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); IPC::RequestParser rp{ctx}; @@ -221,7 +218,7 @@ private: rb.Push(ResultSuccess); } - void GetVoiceDropParameter(Kernel::HLERequestContext& ctx) { + void GetVoiceDropParameter(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); auto& system_ = impl->GetSystem(); @@ -236,6 +233,8 @@ private: Kernel::KEvent* rendered_event; Manager& manager; std::unique_ptr<Renderer> impl; + Common::ScratchBuffer<u8> tmp_output; + Common::ScratchBuffer<u8> tmp_performance; }; class IAudioDevice final : public ServiceFramework<IAudioDevice> { @@ -243,10 +242,8 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> { public: explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision, u32 device_num) - : ServiceFramework{system_, "IAudioDevice", ServiceThreadType::CreateNew}, - service_context{system_, "IAudioDevice"}, impl{std::make_unique<AudioDevice>( - system_, applet_resource_user_id, - revision)}, + : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"}, + impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)}, event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} { static const FunctionInfo functions[] = { {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, @@ -274,7 +271,7 @@ public: } private: - void ListAudioDeviceName(Kernel::HLERequestContext& ctx) { + void ListAudioDeviceName(HLERequestContext& ctx) { const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>(); std::vector<AudioDevice::AudioDeviceName> out_names{}; @@ -302,7 +299,7 @@ private: rb.Push(out_count); } - void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) { + void SetAudioDeviceOutputVolume(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const f32 volume = rp.Pop<f32>(); @@ -319,7 +316,7 @@ private: rb.Push(ResultSuccess); } - void GetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) { + void GetAudioDeviceOutputVolume(HLERequestContext& ctx) { const auto device_name_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(device_name_buffer); @@ -335,7 +332,7 @@ private: rb.Push(volume); } - void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) { + void GetActiveAudioDeviceName(HLERequestContext& ctx) { const auto write_size = ctx.GetWriteBufferSize(); std::string out_name{"AudioTvOutput"}; @@ -349,7 +346,7 @@ private: rb.Push(ResultSuccess); } - void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { + void QueryAudioDeviceSystemEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "(STUBBED) called"); event->Signal(); @@ -359,7 +356,7 @@ private: rb.PushCopyObjects(event->GetReadableEvent()); } - void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { + void GetActiveChannelCount(HLERequestContext& ctx) { const auto& sink{system.AudioCore().GetOutputSink()}; u32 channel_count{sink.GetDeviceChannels()}; @@ -371,7 +368,7 @@ private: rb.Push<u32>(channel_count); } - void QueryAudioDeviceInputEvent(Kernel::HLERequestContext& ctx) { + void QueryAudioDeviceInputEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -379,7 +376,7 @@ private: rb.PushCopyObjects(event->GetReadableEvent()); } - void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { + void QueryAudioDeviceOutputEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -387,7 +384,7 @@ private: rb.PushCopyObjects(event->GetReadableEvent()); } - void ListAudioOutputDeviceName(Kernel::HLERequestContext& ctx) { + void ListAudioOutputDeviceName(HLERequestContext& ctx) { const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>(); std::vector<AudioDevice::AudioDeviceName> out_names{}; @@ -421,7 +418,7 @@ private: }; AudRenU::AudRenU(Core::System& system_) - : ServiceFramework{system_, "audren:u", ServiceThreadType::CreateNew}, + : ServiceFramework{system_, "audren:u"}, service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} { // clang-format off static const FunctionInfo functions[] = { @@ -438,7 +435,7 @@ AudRenU::AudRenU(Core::System& system_) AudRenU::~AudRenU() = default; -void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { +void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; AudioCore::AudioRendererParameterInternal params; @@ -451,11 +448,11 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) { LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_MAXIMUM_SESSIONS_REACHED); + rb.Push(Audio::ResultOutOfSessions); return; } - const auto& handle_table{system.CurrentProcess()->GetHandleTable()}; + const auto& handle_table{system.ApplicationProcess()->GetHandleTable()}; auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)}; auto transfer_memory{ process->GetHandleTable().GetObject<Kernel::KTransferMemory>(transfer_memory_handle)}; @@ -464,7 +461,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { if (session_id == -1) { LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_MAXIMUM_SESSIONS_REACHED); + rb.Push(Audio::ResultOutOfSessions); return; } @@ -478,7 +475,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { applet_resource_user_id, session_id); } -void AudRenU::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { +void AudRenU::GetWorkBufferSize(HLERequestContext& ctx) { AudioCore::AudioRendererParameterInternal params; IPC::RequestParser rp{ctx}; @@ -509,7 +506,7 @@ void AudRenU::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { rb.Push<u64>(size); } -void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { +void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id = rp.Pop<u64>(); @@ -523,11 +520,11 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++); } -void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { +void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); } -void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) { +void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) { struct Parameters { u32 revision; u64 applet_resource_user_id; diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 4384a9b3c..d8e9c8719 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h @@ -4,6 +4,7 @@ #pragma once #include "audio_core/audio_render_manager.h" +#include "common/scratch_buffer.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/service.h" @@ -11,10 +12,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace Service::Audio { class IAudioRenderer; @@ -24,11 +21,11 @@ public: ~AudRenU() override; private: - void OpenAudioRenderer(Kernel::HLERequestContext& ctx); - void GetWorkBufferSize(Kernel::HLERequestContext& ctx); - void GetAudioDeviceService(Kernel::HLERequestContext& ctx); - void OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx); - void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); + void OpenAudioRenderer(HLERequestContext& ctx); + void GetWorkBufferSize(HLERequestContext& ctx); + void GetAudioDeviceService(HLERequestContext& ctx); + void OpenAudioRendererForManualExecution(HLERequestContext& ctx); + void GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx); KernelHelpers::ServiceContext service_context; std::unique_ptr<AudioCore::AudioRenderer::Manager> impl; diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp deleted file mode 100644 index 81b956d7e..000000000 --- a/src/core/hle/service/audio/codecctl.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/codecctl.h" - -namespace Service::Audio { - -CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { - static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {1, nullptr, "Finalize"}, - {2, nullptr, "Sleep"}, - {3, nullptr, "Wake"}, - {4, nullptr, "SetVolume"}, - {5, nullptr, "GetVolumeMax"}, - {6, nullptr, "GetVolumeMin"}, - {7, nullptr, "SetActiveTarget"}, - {8, nullptr, "GetActiveTarget"}, - {9, nullptr, "BindHeadphoneMicJackInterrupt"}, - {10, nullptr, "IsHeadphoneMicJackInserted"}, - {11, nullptr, "ClearHeadphoneMicJackInterrupt"}, - {12, nullptr, "IsRequested"}, - }; - RegisterHandlers(functions); -} - -CodecCtl::~CodecCtl() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/codecctl.h b/src/core/hle/service/audio/codecctl.h deleted file mode 100644 index 34da98212..000000000 --- a/src/core/hle/service/audio/codecctl.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class CodecCtl final : public ServiceFramework<CodecCtl> { -public: - explicit CodecCtl(Core::System& system_); - ~CodecCtl() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/errors.h b/src/core/hle/service/audio/errors.h index d706978cb..3d3d3d97a 100644 --- a/src/core/hle/service/audio/errors.h +++ b/src/core/hle/service/audio/errors.h @@ -7,17 +7,17 @@ namespace Service::Audio { -constexpr Result ERR_INVALID_DEVICE_NAME{ErrorModule::Audio, 1}; -constexpr Result ERR_OPERATION_FAILED{ErrorModule::Audio, 2}; -constexpr Result ERR_INVALID_SAMPLE_RATE{ErrorModule::Audio, 3}; -constexpr Result ERR_INSUFFICIENT_BUFFER_SIZE{ErrorModule::Audio, 4}; -constexpr Result ERR_MAXIMUM_SESSIONS_REACHED{ErrorModule::Audio, 5}; -constexpr Result ERR_BUFFER_COUNT_EXCEEDED{ErrorModule::Audio, 8}; -constexpr Result ERR_INVALID_CHANNEL_COUNT{ErrorModule::Audio, 10}; -constexpr Result ERR_INVALID_UPDATE_DATA{ErrorModule::Audio, 41}; -constexpr Result ERR_POOL_MAPPING_FAILED{ErrorModule::Audio, 42}; -constexpr Result ERR_NOT_SUPPORTED{ErrorModule::Audio, 513}; -constexpr Result ERR_INVALID_PROCESS_HANDLE{ErrorModule::Audio, 1536}; -constexpr Result ERR_INVALID_REVISION{ErrorModule::Audio, 1537}; +constexpr Result ResultNotFound{ErrorModule::Audio, 1}; +constexpr Result ResultOperationFailed{ErrorModule::Audio, 2}; +constexpr Result ResultInvalidSampleRate{ErrorModule::Audio, 3}; +constexpr Result ResultInsufficientBuffer{ErrorModule::Audio, 4}; +constexpr Result ResultOutOfSessions{ErrorModule::Audio, 5}; +constexpr Result ResultBufferCountReached{ErrorModule::Audio, 8}; +constexpr Result ResultInvalidChannelCount{ErrorModule::Audio, 10}; +constexpr Result ResultInvalidUpdateInfo{ErrorModule::Audio, 41}; +constexpr Result ResultInvalidAddressInfo{ErrorModule::Audio, 42}; +constexpr Result ResultNotSupported{ErrorModule::Audio, 513}; +constexpr Result ResultInvalidHandle{ErrorModule::Audio, 1536}; +constexpr Result ResultInvalidRevision{ErrorModule::Audio, 1537}; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 825fb8bcc..c835f6cb7 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -11,8 +11,8 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/audio/hwopus.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Audio { namespace { @@ -53,7 +53,7 @@ public: // Decodes interleaved Opus packets. Optionally allows reporting time taken to // perform the decoding, as well as any relevant extra behavior. - void DecodeInterleaved(Kernel::HLERequestContext& ctx, PerfTime perf_time, + void DecodeInterleaved(HLERequestContext& ctx, PerfTime perf_time, ExtraBehavior extra_behavior) { if (perf_time == PerfTime::Disabled) { DecodeInterleavedHelper(ctx, nullptr, extra_behavior); @@ -64,17 +64,17 @@ public: } private: - void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance, + void DecodeInterleavedHelper(HLERequestContext& ctx, u64* performance, ExtraBehavior extra_behavior) { u32 consumed = 0; u32 sample_count = 0; - std::vector<opus_int16> samples(ctx.GetWriteBufferNumElements<opus_int16>()); + tmp_samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>()); if (extra_behavior == ExtraBehavior::ResetContext) { ResetDecoderContext(); } - if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) { + if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), tmp_samples, performance)) { LOG_ERROR(Audio, "Failed to decode opus data"); IPC::ResponseBuilder rb{ctx, 2}; // TODO(ogniK): Use correct error code @@ -90,11 +90,11 @@ private: if (performance) { rb.Push<u64>(*performance); } - ctx.WriteBuffer(samples); + ctx.WriteBuffer(tmp_samples); } - bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input, - std::vector<opus_int16>& output, u64* out_performance_time) const { + bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input, + std::span<opus_int16> output, u64* out_performance_time) const { const auto start_time = std::chrono::steady_clock::now(); const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); if (sizeof(OpusPacketHeader) > input.size()) { @@ -154,6 +154,7 @@ private: OpusDecoderPtr decoder; u32 sample_rate; u32 channel_count; + Common::ScratchBuffer<opus_int16> tmp_samples; }; class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { @@ -180,21 +181,21 @@ public: } private: - void DecodeInterleavedOld(Kernel::HLERequestContext& ctx) { + void DecodeInterleavedOld(HLERequestContext& ctx) { LOG_DEBUG(Audio, "called"); decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Disabled, OpusDecoderState::ExtraBehavior::None); } - void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) { + void DecodeInterleavedWithPerfOld(HLERequestContext& ctx) { LOG_DEBUG(Audio, "called"); decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, OpusDecoderState::ExtraBehavior::None); } - void DecodeInterleaved(Kernel::HLERequestContext& ctx) { + void DecodeInterleaved(HLERequestContext& ctx) { LOG_DEBUG(Audio, "called"); IPC::RequestParser rp{ctx}; @@ -231,7 +232,7 @@ std::array<u8, 2> CreateMappingTable(u32 channel_count) { } } // Anonymous namespace -void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { +void HwOpus::GetWorkBufferSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto sample_rate = rp.Pop<u32>(); const auto channel_count = rp.Pop<u32>(); @@ -251,11 +252,11 @@ void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { rb.Push<u32>(worker_buffer_sz); } -void HwOpus::GetWorkBufferSizeEx(Kernel::HLERequestContext& ctx) { +void HwOpus::GetWorkBufferSizeEx(HLERequestContext& ctx) { GetWorkBufferSize(ctx); } -void HwOpus::GetWorkBufferSizeForMultiStreamEx(Kernel::HLERequestContext& ctx) { +void HwOpus::GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx) { OpusMultiStreamParametersEx param; std::memcpy(¶m, ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); @@ -281,7 +282,7 @@ void HwOpus::GetWorkBufferSizeForMultiStreamEx(Kernel::HLERequestContext& ctx) { rb.Push<u32>(worker_buffer_sz); } -void HwOpus::OpenHardwareOpusDecoder(Kernel::HLERequestContext& ctx) { +void HwOpus::OpenHardwareOpusDecoder(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto sample_rate = rp.Pop<u32>(); const auto channel_count = rp.Pop<u32>(); @@ -319,7 +320,7 @@ void HwOpus::OpenHardwareOpusDecoder(Kernel::HLERequestContext& ctx) { system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); } -void HwOpus::OpenHardwareOpusDecoderEx(Kernel::HLERequestContext& ctx) { +void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto sample_rate = rp.Pop<u32>(); const auto channel_count = rp.Pop<u32>(); @@ -362,6 +363,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, + {8, nullptr, "GetWorkBufferSizeExEx"}, + {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h index e6092e290..ece65c02c 100644 --- a/src/core/hle/service/audio/hwopus.h +++ b/src/core/hle/service/audio/hwopus.h @@ -27,11 +27,11 @@ public: ~HwOpus() override; private: - void OpenHardwareOpusDecoder(Kernel::HLERequestContext& ctx); - void OpenHardwareOpusDecoderEx(Kernel::HLERequestContext& ctx); - void GetWorkBufferSize(Kernel::HLERequestContext& ctx); - void GetWorkBufferSizeEx(Kernel::HLERequestContext& ctx); - void GetWorkBufferSizeForMultiStreamEx(Kernel::HLERequestContext& ctx); + void OpenHardwareOpusDecoder(HLERequestContext& ctx); + void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); + void GetWorkBufferSize(HLERequestContext& ctx); + void GetWorkBufferSizeEx(HLERequestContext& ctx); + void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); }; } // namespace Service::Audio diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp index cbe690a5d..a6281913a 100644 --- a/src/core/hle/service/bcat/bcat_module.cpp +++ b/src/core/hle/service/bcat/bcat_module.cpp @@ -9,12 +9,13 @@ #include "common/string_util.h" #include "core/core.h" #include "core/file_sys/vfs.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/bcat/backend/backend.h" #include "core/hle/service/bcat/bcat.h" #include "core/hle/service/bcat/bcat_module.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" namespace Service::BCAT { @@ -50,8 +51,7 @@ BCATDigest DigestFile(const FileSys::VirtualFile& file) { // For a name to be valid it must be non-empty, must have a null terminating character as the final // char, can only contain numbers, letters, underscores and a hyphen if directory and a period if // file. -bool VerifyNameValidInternal(Kernel::HLERequestContext& ctx, std::array<char, 0x20> name, - char match_char) { +bool VerifyNameValidInternal(HLERequestContext& ctx, std::array<char, 0x20> name, char match_char) { const auto null_chars = std::count(name.begin(), name.end(), 0); const auto bad_chars = std::count_if(name.begin(), name.end(), [match_char](char c) { return !std::isalnum(static_cast<u8>(c)) && c != '_' && c != match_char && c != '\0'; @@ -66,11 +66,11 @@ bool VerifyNameValidInternal(Kernel::HLERequestContext& ctx, std::array<char, 0x return true; } -bool VerifyNameValidDir(Kernel::HLERequestContext& ctx, DirectoryName name) { +bool VerifyNameValidDir(HLERequestContext& ctx, DirectoryName name) { return VerifyNameValidInternal(ctx, name, '-'); } -bool VerifyNameValidFile(Kernel::HLERequestContext& ctx, FileName name) { +bool VerifyNameValidFile(HLERequestContext& ctx, FileName name) { return VerifyNameValidInternal(ctx, name, '.'); } @@ -98,7 +98,7 @@ public: } private: - void GetEvent(Kernel::HLERequestContext& ctx) { + void GetEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -106,7 +106,7 @@ private: rb.PushCopyObjects(event); } - void GetImpl(Kernel::HLERequestContext& ctx) { + void GetImpl(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); ctx.WriteBuffer(impl); @@ -173,11 +173,11 @@ private: progress_backend.GetImpl()); } - void RequestSyncDeliveryCache(Kernel::HLERequestContext& ctx) { + void RequestSyncDeliveryCache(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); - backend.Synchronize({system.GetCurrentProcessProgramID(), - GetCurrentBuildID(system.GetCurrentProcessBuildID())}, + backend.Synchronize({system.GetApplicationProcessProgramID(), + GetCurrentBuildID(system.GetApplicationProcessBuildID())}, GetProgressBackend(SyncType::Normal)); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -185,7 +185,7 @@ private: rb.PushIpcInterface(CreateProgressService(SyncType::Normal)); } - void RequestSyncDeliveryCacheWithDirectoryName(Kernel::HLERequestContext& ctx) { + void RequestSyncDeliveryCacheWithDirectoryName(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto name_raw = rp.PopRaw<DirectoryName>(); const auto name = @@ -193,8 +193,8 @@ private: LOG_DEBUG(Service_BCAT, "called, name={}", name); - backend.SynchronizeDirectory({system.GetCurrentProcessProgramID(), - GetCurrentBuildID(system.GetCurrentProcessBuildID())}, + backend.SynchronizeDirectory({system.GetApplicationProcessProgramID(), + GetCurrentBuildID(system.GetApplicationProcessBuildID())}, name, GetProgressBackend(SyncType::Directory)); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -202,7 +202,7 @@ private: rb.PushIpcInterface(CreateProgressService(SyncType::Directory)); } - void SetPassphrase(Kernel::HLERequestContext& ctx) { + void SetPassphrase(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); @@ -234,7 +234,7 @@ private: rb.Push(ResultSuccess); } - void ClearDeliveryCacheStorage(Kernel::HLERequestContext& ctx) { + void ClearDeliveryCacheStorage(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); @@ -270,7 +270,7 @@ private: std::array<ProgressServiceBackend, static_cast<size_t>(SyncType::Count)> progress; }; -void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateBcatService(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -295,7 +295,7 @@ public: } private: - void Open(Kernel::HLERequestContext& ctx) { + void Open(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto dir_name_raw = rp.PopRaw<DirectoryName>(); const auto file_name_raw = rp.PopRaw<FileName>(); @@ -339,7 +339,7 @@ private: rb.Push(ResultSuccess); } - void Read(Kernel::HLERequestContext& ctx) { + void Read(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto offset{rp.PopRaw<u64>()}; @@ -362,7 +362,7 @@ private: rb.Push<u64>(buffer.size()); } - void GetSize(Kernel::HLERequestContext& ctx) { + void GetSize(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); if (current_file == nullptr) { @@ -376,7 +376,7 @@ private: rb.Push<u64>(current_file->GetSize()); } - void GetDigest(Kernel::HLERequestContext& ctx) { + void GetDigest(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); if (current_file == nullptr) { @@ -411,7 +411,7 @@ public: } private: - void Open(Kernel::HLERequestContext& ctx) { + void Open(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto name_raw = rp.PopRaw<DirectoryName>(); const auto name = @@ -442,7 +442,7 @@ private: rb.Push(ResultSuccess); } - void Read(Kernel::HLERequestContext& ctx) { + void Read(HLERequestContext& ctx) { auto write_size = ctx.GetWriteBufferNumElements<DeliveryCacheDirectoryEntry>(); LOG_DEBUG(Service_BCAT, "called, write_size={:016X}", write_size); @@ -472,7 +472,7 @@ private: rb.Push(static_cast<u32>(write_size * sizeof(DeliveryCacheDirectoryEntry))); } - void GetCount(Kernel::HLERequestContext& ctx) { + void GetCount(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); if (current_dir == nullptr) { @@ -516,7 +516,7 @@ public: } private: - void CreateFileService(Kernel::HLERequestContext& ctx) { + void CreateFileService(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -524,7 +524,7 @@ private: rb.PushIpcInterface<IDeliveryCacheFileService>(system, root); } - void CreateDirectoryService(Kernel::HLERequestContext& ctx) { + void CreateDirectoryService(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -532,7 +532,7 @@ private: rb.PushIpcInterface<IDeliveryCacheDirectoryService>(system, root); } - void EnumerateDeliveryCacheDirectory(Kernel::HLERequestContext& ctx) { + void EnumerateDeliveryCacheDirectory(HLERequestContext& ctx) { auto size = ctx.GetWriteBufferNumElements<DirectoryName>(); LOG_DEBUG(Service_BCAT, "called, size={:016X}", size); @@ -551,17 +551,16 @@ private: u64 next_read_index = 0; }; -void Module::Interface::CreateDeliveryCacheStorageService(Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateDeliveryCacheStorageService(HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); - const auto title_id = system.GetCurrentProcessProgramID(); + const auto title_id = system.GetApplicationProcessProgramID(); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IDeliveryCacheStorageService>(system, fsc.GetBCATDirectory(title_id)); } -void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId( - Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); @@ -585,16 +584,23 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu Module::Interface::~Interface() = default; -void InstallInterfaces(Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); auto module = std::make_shared<Module>(); - std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a") - ->InstallAsService(system.ServiceManager()); - std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m") - ->InstallAsService(system.ServiceManager()); - std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u") - ->InstallAsService(system.ServiceManager()); - std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s") - ->InstallAsService(system.ServiceManager()); + + server_manager->RegisterNamedService( + "bcat:a", + std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a")); + server_manager->RegisterNamedService( + "bcat:m", + std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m")); + server_manager->RegisterNamedService( + "bcat:u", + std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u")); + server_manager->RegisterNamedService( + "bcat:s", + std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s")); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::BCAT diff --git a/src/core/hle/service/bcat/bcat_module.h b/src/core/hle/service/bcat/bcat_module.h index b2fcf9bfb..87576288b 100644 --- a/src/core/hle/service/bcat/bcat_module.h +++ b/src/core/hle/service/bcat/bcat_module.h @@ -27,9 +27,9 @@ public: FileSystem::FileSystemController& fsc_, const char* name); ~Interface() override; - void CreateBcatService(Kernel::HLERequestContext& ctx); - void CreateDeliveryCacheStorageService(Kernel::HLERequestContext& ctx); - void CreateDeliveryCacheStorageServiceWithApplicationId(Kernel::HLERequestContext& ctx); + void CreateBcatService(HLERequestContext& ctx); + void CreateDeliveryCacheStorageService(HLERequestContext& ctx); + void CreateDeliveryCacheStorageServiceWithApplicationId(HLERequestContext& ctx); protected: FileSystem::FileSystemController& fsc; @@ -39,8 +39,7 @@ public: }; }; -/// Registers all BCAT services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace BCAT diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp index 466163538..91b15e256 100644 --- a/src/core/hle/service/bpc/bpc.cpp +++ b/src/core/hle/service/bpc/bpc.cpp @@ -4,8 +4,8 @@ #include <memory> #include "core/hle/service/bpc/bpc.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::BPC { @@ -54,9 +54,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<BPC>(system)->InstallAsService(sm); - std::make_shared<BPC_R>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("bpc", std::make_shared<BPC>(system)); + server_manager->RegisterNamedService("bpc:r", std::make_shared<BPC_R>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::BPC diff --git a/src/core/hle/service/bpc/bpc.h b/src/core/hle/service/bpc/bpc.h index 8adc2f962..524391ddb 100644 --- a/src/core/hle/service/bpc/bpc.h +++ b/src/core/hle/service/bpc/bpc.h @@ -13,6 +13,6 @@ class ServiceManager; namespace Service::BPC { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::BPC diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index ec7e5320c..38cdd57ad 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp @@ -3,10 +3,11 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/btdrv/btdrv.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -40,7 +41,7 @@ public: } private: - void RegisterBleEvent(Kernel::HLERequestContext& ctx) { + void RegisterBleEvent(HLERequestContext& ctx) { LOG_WARNING(Service_BTM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -196,9 +197,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<BtDrv>(system)->InstallAsService(sm); - std::make_shared<Bt>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("btdrv", std::make_shared<BtDrv>(system)); + server_manager->RegisterNamedService("bt", std::make_shared<Bt>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::BtDrv diff --git a/src/core/hle/service/btdrv/btdrv.h b/src/core/hle/service/btdrv/btdrv.h index 9cbe2926f..42713860e 100644 --- a/src/core/hle/service/btdrv/btdrv.h +++ b/src/core/hle/service/btdrv/btdrv.h @@ -13,7 +13,6 @@ class System; namespace Service::BtDrv { -/// Registers all BtDrv services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::BtDrv diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index eebf85e03..8069f75b7 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -5,10 +5,11 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/btm/btm.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::BTM { @@ -69,35 +70,39 @@ public: } private: - void AcquireBleScanEvent(Kernel::HLERequestContext& ctx) { + void AcquireBleScanEvent(HLERequestContext& ctx) { LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; + IPC::ResponseBuilder rb{ctx, 3, 1}; rb.Push(ResultSuccess); + rb.Push(true); rb.PushCopyObjects(scan_event->GetReadableEvent()); } - void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) { + void AcquireBleConnectionEvent(HLERequestContext& ctx) { LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; + IPC::ResponseBuilder rb{ctx, 3, 1}; rb.Push(ResultSuccess); + rb.Push(true); rb.PushCopyObjects(connection_event->GetReadableEvent()); } - void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) { + void AcquireBleServiceDiscoveryEvent(HLERequestContext& ctx) { LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; + IPC::ResponseBuilder rb{ctx, 3, 1}; rb.Push(ResultSuccess); + rb.Push(true); rb.PushCopyObjects(service_discovery_event->GetReadableEvent()); } - void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) { + void AcquireBleMtuConfigEvent(HLERequestContext& ctx) { LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; + IPC::ResponseBuilder rb{ctx, 3, 1}; rb.Push(ResultSuccess); + rb.Push(true); rb.PushCopyObjects(config_event->GetReadableEvent()); } @@ -121,7 +126,7 @@ public: } private: - void GetCore(Kernel::HLERequestContext& ctx) { + void GetCore(HLERequestContext& ctx) { LOG_DEBUG(Service_BTM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -302,7 +307,7 @@ public: } private: - void GetCore(Kernel::HLERequestContext& ctx) { + void GetCore(HLERequestContext& ctx) { LOG_DEBUG(Service_BTM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -311,11 +316,14 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<BTM>(system)->InstallAsService(sm); - std::make_shared<BTM_DBG>(system)->InstallAsService(sm); - std::make_shared<BTM_SYS>(system)->InstallAsService(sm); - std::make_shared<BTM_USR>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("btm", std::make_shared<BTM>(system)); + server_manager->RegisterNamedService("btm:dbg", std::make_shared<BTM_DBG>(system)); + server_manager->RegisterNamedService("btm:sys", std::make_shared<BTM_SYS>(system)); + server_manager->RegisterNamedService("btm:u", std::make_shared<BTM_USR>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h index 9dcda1848..a99b34364 100644 --- a/src/core/hle/service/btm/btm.h +++ b/src/core/hle/service/btm/btm.h @@ -13,6 +13,6 @@ class System; namespace Service::BTM { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::BTM diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp index 13940a8c9..610fe9940 100644 --- a/src/core/hle/service/caps/caps.cpp +++ b/src/core/hle/service/caps/caps.cpp @@ -8,17 +8,21 @@ #include "core/hle/service/caps/caps_ss.h" #include "core/hle/service/caps/caps_su.h" #include "core/hle/service/caps/caps_u.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::Capture { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<CAPS_A>(system)->InstallAsService(sm); - std::make_shared<CAPS_C>(system)->InstallAsService(sm); - std::make_shared<CAPS_U>(system)->InstallAsService(sm); - std::make_shared<CAPS_SC>(system)->InstallAsService(sm); - std::make_shared<CAPS_SS>(system)->InstallAsService(sm); - std::make_shared<CAPS_SU>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("caps:a", std::make_shared<CAPS_A>(system)); + server_manager->RegisterNamedService("caps:c", std::make_shared<CAPS_C>(system)); + server_manager->RegisterNamedService("caps:u", std::make_shared<CAPS_U>(system)); + server_manager->RegisterNamedService("caps:sc", std::make_shared<CAPS_SC>(system)); + server_manager->RegisterNamedService("caps:ss", std::make_shared<CAPS_SS>(system)); + server_manager->RegisterNamedService("caps:su", std::make_shared<CAPS_SU>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h index 3e89c82cb..15f0ecfaa 100644 --- a/src/core/hle/service/caps/caps.h +++ b/src/core/hle/service/caps/caps.h @@ -90,7 +90,6 @@ struct ApplicationAlbumFileEntry { static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30, "ApplicationAlbumFileEntry has incorrect size."); -/// Registers all Capture services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h index 319c173d8..98a21a5ad 100644 --- a/src/core/hle/service/caps/caps_a.h +++ b/src/core/hle/service/caps/caps_a.h @@ -9,10 +9,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace Service::Capture { class CAPS_A final : public ServiceFramework<CAPS_A> { diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp index 725a2e3a7..fc77e35cd 100644 --- a/src/core/hle/service/caps/caps_c.cpp +++ b/src/core/hle/service/caps/caps_c.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/caps/caps_c.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Capture { @@ -74,7 +74,7 @@ CAPS_C::CAPS_C(Core::System& system_) : ServiceFramework{system_, "caps:c"} { CAPS_C::~CAPS_C() = default; -void CAPS_C::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) { +void CAPS_C::SetShimLibraryVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto library_version{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h index 983a4212d..537b3a2e3 100644 --- a/src/core/hle/service/caps/caps_c.h +++ b/src/core/hle/service/caps/caps_c.h @@ -9,10 +9,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace Service::Capture { class CAPS_C final : public ServiceFramework<CAPS_C> { @@ -21,7 +17,7 @@ public: ~CAPS_C() override; private: - void SetShimLibraryVersion(Kernel::HLERequestContext& ctx); + void SetShimLibraryVersion(HLERequestContext& ctx); }; } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp index fcb496756..3b11cc95c 100644 --- a/src/core/hle/service/caps/caps_su.cpp +++ b/src/core/hle/service/caps/caps_su.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/caps/caps_su.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Capture { @@ -23,7 +23,7 @@ CAPS_SU::CAPS_SU(Core::System& system_) : ServiceFramework{system_, "caps:su"} { CAPS_SU::~CAPS_SU() = default; -void CAPS_SU::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) { +void CAPS_SU::SetShimLibraryVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto library_version{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h index c9a1d507b..c6398858d 100644 --- a/src/core/hle/service/caps/caps_su.h +++ b/src/core/hle/service/caps/caps_su.h @@ -9,10 +9,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace Service::Capture { class CAPS_SU final : public ServiceFramework<CAPS_SU> { @@ -21,7 +17,7 @@ public: ~CAPS_SU() override; private: - void SetShimLibraryVersion(Kernel::HLERequestContext& ctx); + void SetShimLibraryVersion(HLERequestContext& ctx); }; } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp index 5fbba8673..bffe0f8d0 100644 --- a/src/core/hle/service/caps/caps_u.cpp +++ b/src/core/hle/service/caps/caps_u.cpp @@ -2,9 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/caps/caps.h" #include "core/hle/service/caps/caps_u.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Capture { @@ -52,7 +52,7 @@ CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} { CAPS_U::~CAPS_U() = default; -void CAPS_U::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) { +void CAPS_U::SetShimLibraryVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto library_version{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -64,7 +64,7 @@ void CAPS_U::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) { +void CAPS_U::GetAlbumContentsFileListForApplication(HLERequestContext& ctx) { // Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total // output entries (which is copied to a s32 by official SW). @@ -93,7 +93,7 @@ void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& c rb.Push(total_entries_2); } -void CAPS_U::GetAlbumFileList3AaeAruid(Kernel::HLERequestContext& ctx) { +void CAPS_U::GetAlbumFileList3AaeAruid(HLERequestContext& ctx) { GetAlbumContentsFileListForApplication(ctx); } diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h index c3d4b9cea..e8dd037d7 100644 --- a/src/core/hle/service/caps/caps_u.h +++ b/src/core/hle/service/caps/caps_u.h @@ -9,10 +9,6 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - namespace Service::Capture { class CAPS_U final : public ServiceFramework<CAPS_U> { @@ -21,9 +17,9 @@ public: ~CAPS_U() override; private: - void SetShimLibraryVersion(Kernel::HLERequestContext& ctx); - void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx); - void GetAlbumFileList3AaeAruid(Kernel::HLERequestContext& ctx); + void SetShimLibraryVersion(HLERequestContext& ctx); + void GetAlbumContentsFileListForApplication(HLERequestContext& ctx); + void GetAlbumFileList3AaeAruid(HLERequestContext& ctx); }; } // namespace Service::Capture diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index 923c0022a..3ea862fad 100644 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp @@ -4,6 +4,7 @@ #include <memory> #include "core/hle/service/erpt/erpt.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -52,9 +53,13 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<ErrorReportContext>(system)->InstallAsService(sm); - std::make_shared<ErrorReportSession>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("erpt:c", std::make_shared<ErrorReportContext>(system)); + server_manager->RegisterNamedService("erpt:r", std::make_shared<ErrorReportSession>(system)); + + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::ERPT diff --git a/src/core/hle/service/erpt/erpt.h b/src/core/hle/service/erpt/erpt.h index 507d626ec..60094f556 100644 --- a/src/core/hle/service/erpt/erpt.h +++ b/src/core/hle/service/erpt/erpt.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::ERPT { -/// Registers all ERPT services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::ERPT diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index d183e5829..446f46b3c 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp @@ -2,8 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/crypto/key_manager.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/es/es.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::ES { @@ -109,7 +110,7 @@ public: } private: - bool CheckRightsId(Kernel::HLERequestContext& ctx, const u128& rights_id) { + bool CheckRightsId(HLERequestContext& ctx, const u128& rights_id) { if (rights_id == u128{}) { LOG_ERROR(Service_ETicket, "The rights ID was invalid!"); IPC::ResponseBuilder rb{ctx, 2}; @@ -120,9 +121,9 @@ private: return true; } - void ImportTicket(Kernel::HLERequestContext& ctx) { + void ImportTicket(HLERequestContext& ctx) { const auto ticket = ctx.ReadBuffer(); - const auto cert = ctx.ReadBuffer(1); + [[maybe_unused]] const auto cert = ctx.ReadBuffer(1); if (ticket.size() < sizeof(Core::Crypto::Ticket)) { LOG_ERROR(Service_ETicket, "The input buffer is not large enough!"); @@ -145,7 +146,7 @@ private: rb.Push(ResultSuccess); } - void GetTitleKey(Kernel::HLERequestContext& ctx) { + void GetTitleKey(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto rights_id = rp.PopRaw<u128>(); @@ -171,7 +172,7 @@ private: rb.Push(ResultSuccess); } - void CountCommonTicket(Kernel::HLERequestContext& ctx) { + void CountCommonTicket(HLERequestContext& ctx) { LOG_DEBUG(Service_ETicket, "called"); const u32 count = static_cast<u32>(keys.GetCommonTickets().size()); @@ -181,7 +182,7 @@ private: rb.Push<u32>(count); } - void CountPersonalizedTicket(Kernel::HLERequestContext& ctx) { + void CountPersonalizedTicket(HLERequestContext& ctx) { LOG_DEBUG(Service_ETicket, "called"); const u32 count = static_cast<u32>(keys.GetPersonalizedTickets().size()); @@ -191,7 +192,7 @@ private: rb.Push<u32>(count); } - void ListCommonTicketRightsIds(Kernel::HLERequestContext& ctx) { + void ListCommonTicketRightsIds(HLERequestContext& ctx) { size_t out_entries = 0; if (!keys.GetCommonTickets().empty()) { out_entries = ctx.GetWriteBufferNumElements<u128>(); @@ -212,7 +213,7 @@ private: rb.Push<u32>(static_cast<u32>(out_entries)); } - void ListPersonalizedTicketRightsIds(Kernel::HLERequestContext& ctx) { + void ListPersonalizedTicketRightsIds(HLERequestContext& ctx) { size_t out_entries = 0; if (!keys.GetPersonalizedTickets().empty()) { out_entries = ctx.GetWriteBufferNumElements<u128>(); @@ -234,7 +235,7 @@ private: rb.Push<u32>(static_cast<u32>(out_entries)); } - void GetCommonTicketSize(Kernel::HLERequestContext& ctx) { + void GetCommonTicketSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto rights_id = rp.PopRaw<u128>(); @@ -250,7 +251,7 @@ private: rb.Push<u64>(ticket.GetSize()); } - void GetPersonalizedTicketSize(Kernel::HLERequestContext& ctx) { + void GetPersonalizedTicketSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto rights_id = rp.PopRaw<u128>(); @@ -266,7 +267,7 @@ private: rb.Push<u64>(ticket.GetSize()); } - void GetCommonTicketData(Kernel::HLERequestContext& ctx) { + void GetCommonTicketData(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto rights_id = rp.PopRaw<u128>(); @@ -285,7 +286,7 @@ private: rb.Push<u64>(write_size); } - void GetPersonalizedTicketData(Kernel::HLERequestContext& ctx) { + void GetPersonalizedTicketData(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto rights_id = rp.PopRaw<u128>(); @@ -307,8 +308,11 @@ private: Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<ETicket>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("es", std::make_shared<ETicket>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::ES diff --git a/src/core/hle/service/es/es.h b/src/core/hle/service/es/es.h index 530563550..317680625 100644 --- a/src/core/hle/service/es/es.h +++ b/src/core/hle/service/es/es.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::ES { -/// Registers all ES services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::ES diff --git a/src/core/hle/service/eupld/eupld.cpp b/src/core/hle/service/eupld/eupld.cpp index d1553ace0..3cf27513a 100644 --- a/src/core/hle/service/eupld/eupld.cpp +++ b/src/core/hle/service/eupld/eupld.cpp @@ -4,8 +4,8 @@ #include <memory> #include "core/hle/service/eupld/eupld.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::EUPLD { @@ -44,9 +44,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<ErrorUploadContext>(system)->InstallAsService(sm); - std::make_shared<ErrorUploadRequest>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("eupld:c", std::make_shared<ErrorUploadContext>(system)); + server_manager->RegisterNamedService("eupld:r", std::make_shared<ErrorUploadRequest>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::EUPLD diff --git a/src/core/hle/service/eupld/eupld.h b/src/core/hle/service/eupld/eupld.h index 5de8219be..8eb0a5b4f 100644 --- a/src/core/hle/service/eupld/eupld.h +++ b/src/core/hle/service/eupld/eupld.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::EUPLD { -/// Registers all EUPLD services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::EUPLD diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 27675615b..fe2ed8df8 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -9,10 +9,11 @@ #include "common/scm_rev.h" #include "common/swap.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/fatal/fatal.h" #include "core/hle/service/fatal/fatal_p.h" #include "core/hle/service/fatal/fatal_u.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/reporter.h" namespace Service::Fatal { @@ -63,7 +64,7 @@ enum class FatalType : u32 { }; static void GenerateErrorReport(Core::System& system, Result error_code, const FatalInfo& info) { - const auto title_id = system.GetCurrentProcessProgramID(); + const auto title_id = system.GetApplicationProcessProgramID(); std::string crash_report = fmt::format( "Yuzu {}-{} crash report\n" "Title ID: {:016x}\n" @@ -125,7 +126,7 @@ static void ThrowFatalError(Core::System& system, Result error_code, FatalType f } } -void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) { +void Module::Interface::ThrowFatal(HLERequestContext& ctx) { LOG_ERROR(Service_Fatal, "called"); IPC::RequestParser rp{ctx}; const auto error_code = rp.Pop<Result>(); @@ -135,7 +136,7 @@ void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) { +void Module::Interface::ThrowFatalWithPolicy(HLERequestContext& ctx) { LOG_ERROR(Service_Fatal, "called"); IPC::RequestParser rp(ctx); const auto error_code = rp.Pop<Result>(); @@ -147,7 +148,7 @@ void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) { +void Module::Interface::ThrowFatalWithCpuContext(HLERequestContext& ctx) { LOG_ERROR(Service_Fatal, "called"); IPC::RequestParser rp(ctx); const auto error_code = rp.Pop<Result>(); @@ -163,10 +164,13 @@ void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) rb.Push(ResultSuccess); } -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); auto module = std::make_shared<Module>(); - std::make_shared<Fatal_P>(module, system)->InstallAsService(service_manager); - std::make_shared<Fatal_U>(module, system)->InstallAsService(service_manager); + + server_manager->RegisterNamedService("fatal:p", std::make_shared<Fatal_P>(module, system)); + server_manager->RegisterNamedService("fatal:u", std::make_shared<Fatal_U>(module, system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Fatal diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h index a7a310f7b..f1c110406 100644 --- a/src/core/hle/service/fatal/fatal.h +++ b/src/core/hle/service/fatal/fatal.h @@ -19,15 +19,15 @@ public: const char* name); ~Interface() override; - void ThrowFatal(Kernel::HLERequestContext& ctx); - void ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx); - void ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx); + void ThrowFatal(HLERequestContext& ctx); + void ThrowFatalWithPolicy(HLERequestContext& ctx); + void ThrowFatalWithCpuContext(HLERequestContext& ctx); protected: std::shared_ptr<Module> module; }; }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Fatal diff --git a/src/core/hle/service/fgm/fgm.cpp b/src/core/hle/service/fgm/fgm.cpp index 7e9fb0385..6b3f77be2 100644 --- a/src/core/hle/service/fgm/fgm.cpp +++ b/src/core/hle/service/fgm/fgm.cpp @@ -3,8 +3,9 @@ #include <memory> -#include "core/hle/ipc_helpers.h" #include "core/hle/service/fgm/fgm.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -39,7 +40,7 @@ public: } private: - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { LOG_DEBUG(Service_FGM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -63,11 +64,14 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<FGM>(system, "fgm")->InstallAsService(sm); - std::make_shared<FGM>(system, "fgm:0")->InstallAsService(sm); - std::make_shared<FGM>(system, "fgm:9")->InstallAsService(sm); - std::make_shared<FGM_DBG>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("fgm", std::make_shared<FGM>(system, "fgm")); + server_manager->RegisterNamedService("fgm:0", std::make_shared<FGM>(system, "fgm:0")); + server_manager->RegisterNamedService("fgm:9", std::make_shared<FGM>(system, "fgm:9")); + server_manager->RegisterNamedService("fgm:dbg", std::make_shared<FGM_DBG>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::FGM diff --git a/src/core/hle/service/fgm/fgm.h b/src/core/hle/service/fgm/fgm.h index 077e48812..9d2465c0f 100644 --- a/src/core/hle/service/fgm/fgm.h +++ b/src/core/hle/service/fgm/fgm.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::FGM { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::FGM diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 11c604a0f..dfcdd3ada 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -23,6 +23,7 @@ #include "core/hle/service/filesystem/fsp_ldr.h" #include "core/hle/service/filesystem/fsp_pr.h" #include "core/hle/service/filesystem/fsp_srv.h" +#include "core/hle/service/server_manager.h" #include "core/loader/loader.h" namespace Service::FileSystem { @@ -317,7 +318,7 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess() return ResultUnknown; } - return romfs_factory->OpenCurrentProcess(system.GetCurrentProcessProgramID()); + return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID()); } ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS( @@ -502,7 +503,7 @@ FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataTy const auto res = system.GetAppLoader().ReadControlData(nacp); if (res != Loader::ResultStatus::Success) { - const FileSys::PatchManager pm{system.GetCurrentProcessProgramID(), + const FileSys::PatchManager pm{system.GetApplicationProcessProgramID(), system.GetFileSystemController(), system.GetContentProvider()}; const auto metadata = pm.GetControlMetadata(); @@ -796,10 +797,13 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove } } -void InstallInterfaces(Core::System& system) { - std::make_shared<FSP_LDR>(system)->InstallAsService(system.ServiceManager()); - std::make_shared<FSP_PR>(system)->InstallAsService(system.ServiceManager()); - std::make_shared<FSP_SRV>(system)->InstallAsService(system.ServiceManager()); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system)); + server_manager->RegisterNamedService("fsp:pr", std::make_shared<FSP_PR>(system)); + server_manager->RegisterNamedService("fsp-srv", std::make_shared<FSP_SRV>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 5b27de9fa..a5c1c9d3e 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -139,7 +139,7 @@ private: Core::System& system; }; -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); // A class that wraps a VfsDirectory with methods that return ResultVal and Result instead of // pointers and booleans. This makes using a VfsDirectory with switch services much easier and diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index fbb16a7da..427dbc8b3 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -24,9 +24,11 @@ #include "core/file_sys/savedata_factory.h" #include "core/file_sys/system_archive/system_archive.h" #include "core/file_sys/vfs.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/result.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" +#include "core/hle/service/hle_ipc.h" +#include "core/hle/service/ipc_helpers.h" #include "core/reporter.h" namespace Service::FileSystem { @@ -57,8 +59,7 @@ enum class FileSystemType : u8 { class IStorage final : public ServiceFramework<IStorage> { public: explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) - : ServiceFramework{system_, "IStorage", ServiceThreadType::CreateNew}, - backend(std::move(backend_)) { + : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, @@ -73,7 +74,7 @@ public: private: FileSys::VirtualFile backend; - void Read(Kernel::HLERequestContext& ctx) { + void Read(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s64 offset = rp.Pop<s64>(); const s64 length = rp.Pop<s64>(); @@ -103,7 +104,7 @@ private: rb.Push(ResultSuccess); } - void GetSize(Kernel::HLERequestContext& ctx) { + void GetSize(HLERequestContext& ctx) { const u64 size = backend->GetSize(); LOG_DEBUG(Service_FS, "called, size={}", size); @@ -116,8 +117,7 @@ private: class IFile final : public ServiceFramework<IFile> { public: explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) - : ServiceFramework{system_, "IFile", ServiceThreadType::CreateNew}, - backend(std::move(backend_)) { + : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, @@ -133,7 +133,7 @@ public: private: FileSys::VirtualFile backend; - void Read(Kernel::HLERequestContext& ctx) { + void Read(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 option = rp.Pop<u64>(); const s64 offset = rp.Pop<s64>(); @@ -167,7 +167,7 @@ private: rb.Push(static_cast<u64>(output.size())); } - void Write(Kernel::HLERequestContext& ctx) { + void Write(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 option = rp.Pop<u64>(); const s64 offset = rp.Pop<s64>(); @@ -190,7 +190,7 @@ private: return; } - const std::vector<u8> data = ctx.ReadBuffer(); + const auto data = ctx.ReadBuffer(); ASSERT_MSG( static_cast<s64>(data.size()) <= length, @@ -210,7 +210,7 @@ private: rb.Push(ResultSuccess); } - void Flush(Kernel::HLERequestContext& ctx) { + void Flush(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); // Exists for SDK compatibiltity -- No need to flush file. @@ -219,7 +219,7 @@ private: rb.Push(ResultSuccess); } - void SetSize(Kernel::HLERequestContext& ctx) { + void SetSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 size = rp.Pop<u64>(); LOG_DEBUG(Service_FS, "called, size={}", size); @@ -230,7 +230,7 @@ private: rb.Push(ResultSuccess); } - void GetSize(Kernel::HLERequestContext& ctx) { + void GetSize(HLERequestContext& ctx) { const u64 size = backend->GetSize(); LOG_DEBUG(Service_FS, "called, size={}", size); @@ -254,8 +254,7 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec class IDirectory final : public ServiceFramework<IDirectory> { public: explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_) - : ServiceFramework{system_, "IDirectory", ServiceThreadType::CreateNew}, - backend(std::move(backend_)) { + : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IDirectory::Read, "Read"}, {1, &IDirectory::GetEntryCount, "GetEntryCount"}, @@ -273,7 +272,7 @@ private: std::vector<FileSys::Entry> entries; u64 next_entry_index = 0; - void Read(Kernel::HLERequestContext& ctx) { + void Read(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called."); // Calculate how many entries we can fit in the output buffer @@ -297,7 +296,7 @@ private: rb.Push(actual_entries); } - void GetEntryCount(Kernel::HLERequestContext& ctx) { + void GetEntryCount(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); u64 count = entries.size() - next_entry_index; @@ -311,8 +310,8 @@ private: class IFileSystem final : public ServiceFramework<IFileSystem> { public: explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) - : ServiceFramework{system_, "IFileSystem", ServiceThreadType::CreateNew}, - backend{std::move(backend_)}, size{std::move(size_)} { + : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( + size_)} { static const FunctionInfo functions[] = { {0, &IFileSystem::CreateFile, "CreateFile"}, {1, &IFileSystem::DeleteFile, "DeleteFile"}, @@ -334,7 +333,7 @@ public: RegisterHandlers(functions); } - void CreateFile(Kernel::HLERequestContext& ctx) { + void CreateFile(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto file_buffer = ctx.ReadBuffer(); @@ -350,7 +349,7 @@ public: rb.Push(backend.CreateFile(name, file_size)); } - void DeleteFile(Kernel::HLERequestContext& ctx) { + void DeleteFile(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -360,7 +359,7 @@ public: rb.Push(backend.DeleteFile(name)); } - void CreateDirectory(Kernel::HLERequestContext& ctx) { + void CreateDirectory(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -370,7 +369,7 @@ public: rb.Push(backend.CreateDirectory(name)); } - void DeleteDirectory(Kernel::HLERequestContext& ctx) { + void DeleteDirectory(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -380,7 +379,7 @@ public: rb.Push(backend.DeleteDirectory(name)); } - void DeleteDirectoryRecursively(Kernel::HLERequestContext& ctx) { + void DeleteDirectoryRecursively(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -390,7 +389,7 @@ public: rb.Push(backend.DeleteDirectoryRecursively(name)); } - void CleanDirectoryRecursively(Kernel::HLERequestContext& ctx) { + void CleanDirectoryRecursively(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -400,12 +399,9 @@ public: rb.Push(backend.CleanDirectoryRecursively(name)); } - void RenameFile(Kernel::HLERequestContext& ctx) { - std::vector<u8> buffer = ctx.ReadBuffer(0); - const std::string src_name = Common::StringFromBuffer(buffer); - - buffer = ctx.ReadBuffer(1); - const std::string dst_name = Common::StringFromBuffer(buffer); + void RenameFile(HLERequestContext& ctx) { + const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0)); + const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1)); LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); @@ -413,7 +409,7 @@ public: rb.Push(backend.RenameFile(src_name, dst_name)); } - void OpenFile(Kernel::HLERequestContext& ctx) { + void OpenFile(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto file_buffer = ctx.ReadBuffer(); @@ -437,7 +433,7 @@ public: rb.PushIpcInterface<IFile>(std::move(file)); } - void OpenDirectory(Kernel::HLERequestContext& ctx) { + void OpenDirectory(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto file_buffer = ctx.ReadBuffer(); @@ -462,7 +458,7 @@ public: rb.PushIpcInterface<IDirectory>(std::move(directory)); } - void GetEntryType(Kernel::HLERequestContext& ctx) { + void GetEntryType(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -480,14 +476,14 @@ public: rb.Push<u32>(static_cast<u32>(*result)); } - void Commit(Kernel::HLERequestContext& ctx) { + void Commit(HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void GetFreeSpaceSize(Kernel::HLERequestContext& ctx) { + void GetFreeSpaceSize(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -495,7 +491,7 @@ public: rb.Push(size.get_free_size()); } - void GetTotalSpaceSize(Kernel::HLERequestContext& ctx) { + void GetTotalSpaceSize(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -503,7 +499,7 @@ public: rb.Push(size.get_total_size()); } - void GetFileTimeStampRaw(Kernel::HLERequestContext& ctx) { + void GetFileTimeStampRaw(HLERequestContext& ctx) { const auto file_buffer = ctx.ReadBuffer(); const std::string name = Common::StringFromBuffer(file_buffer); @@ -539,7 +535,7 @@ public: FindAllSaves(space); } - void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) { + void ReadSaveDataInfo(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); // Calculate how many entries we can fit in the output buffer @@ -558,9 +554,9 @@ public: // Write the data to memory ctx.WriteBuffer(begin, range_size); - IPC::ResponseBuilder rb{ctx, 3}; + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push<u32>(static_cast<u32>(actual_entries)); + rb.Push<u64>(actual_entries); } private: @@ -718,7 +714,7 @@ FSP_SRV::FSP_SRV(Core::System& system_) {59, nullptr, "WriteSaveDataFileSystemExtraData"}, {60, nullptr, "OpenSaveDataInfoReader"}, {61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, - {62, nullptr, "OpenCacheStorageList"}, + {62, &FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage, "OpenSaveDataInfoReaderOnlyCacheStorage"}, {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, {65, nullptr, "UpdateSaveDataMacForDebug"}, {66, nullptr, "WriteSaveDataFileSystemExtraData2"}, @@ -817,7 +813,7 @@ FSP_SRV::FSP_SRV(Core::System& system_) FSP_SRV::~FSP_SRV() = default; -void FSP_SRV::SetCurrentProcess(Kernel::HLERequestContext& ctx) { +void FSP_SRV::SetCurrentProcess(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; current_process_id = rp.Pop<u64>(); @@ -827,7 +823,7 @@ void FSP_SRV::SetCurrentProcess(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto type = rp.PopRaw<FileSystemType>(); @@ -838,7 +834,7 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) { rb.Push(ResultUnknown); } -void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); auto filesystem = @@ -850,7 +846,7 @@ void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IFileSystem>(std::move(filesystem)); } -void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) { +void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto save_struct = rp.PopRaw<FileSys::SaveDataAttribute>(); @@ -866,7 +862,7 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { @@ -911,12 +907,12 @@ void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IFileSystem>(std::move(filesystem)); } -void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); OpenSaveDataFileSystem(ctx); } -void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto space = rp.PopRaw<FileSys::SaveDataSpaceId>(); LOG_INFO(Service_FS, "called, space={}", space); @@ -927,15 +923,23 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& std::make_shared<ISaveDataInfoReader>(system, space, fsc)); } -void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<ISaveDataInfoReader>(system, FileSys::SaveDataSpaceId::TemporaryStorage, + fsc); +} + +void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called."); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( - Kernel::HLERequestContext& ctx) { +void FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { @@ -961,26 +965,30 @@ void FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( rb.Push(flags); } -void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - auto current_romfs = fsc.OpenRomFSCurrentProcess(); - if (current_romfs.Failed()) { - // TODO (bunnei): Find the right error code to use here - LOG_CRITICAL(Service_FS, "no file system interface available!"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + if (!romfs) { + auto current_romfs = fsc.OpenRomFSCurrentProcess(); + if (current_romfs.Failed()) { + // TODO (bunnei): Find the right error code to use here + LOG_CRITICAL(Service_FS, "no file system interface available!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + romfs = current_romfs.Unwrap(); } - auto storage = std::make_shared<IStorage>(system, std::move(current_romfs.Unwrap())); + auto storage = std::make_shared<IStorage>(system, romfs); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IStorage>(std::move(storage)); } -void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto storage_id = rp.PopRaw<FileSys::StorageId>(); const auto unknown = rp.PopRaw<u32>(); @@ -1020,7 +1028,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IStorage>(std::move(storage)); } -void FSP_SRV::OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenPatchDataStorageByCurrentProcess(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto storage_id = rp.PopRaw<FileSys::StorageId>(); @@ -1032,15 +1040,16 @@ void FSP_SRV::OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ct rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); } -void FSP_SRV::OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto program_index = rp.PopRaw<u8>(); LOG_DEBUG(Service_FS, "called, program_index={}", program_index); - auto patched_romfs = fsc.OpenPatchedRomFSWithProgramIndex( - system.GetCurrentProcessProgramID(), program_index, FileSys::ContentRecordType::Program); + auto patched_romfs = + fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, + FileSys::ContentRecordType::Program); if (patched_romfs.Failed()) { // TODO: Find the right error code to use here @@ -1058,7 +1067,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IStorage>(std::move(storage)); } -void FSP_SRV::DisableAutoSaveDataCreation(Kernel::HLERequestContext& ctx) { +void FSP_SRV::DisableAutoSaveDataCreation(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); fsc.SetAutoSaveDataCreation(false); @@ -1067,7 +1076,7 @@ void FSP_SRV::DisableAutoSaveDataCreation(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { +void FSP_SRV::SetGlobalAccessLogMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; access_log_mode = rp.PopEnum<AccessLogMode>(); @@ -1077,7 +1086,7 @@ void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { +void FSP_SRV::GetGlobalAccessLogMode(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -1085,8 +1094,8 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { rb.PushEnum(access_log_mode); } -void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { - const auto raw = ctx.ReadBuffer(); +void FSP_SRV::OutputAccessLogToSdCard(HLERequestContext& ctx) { + const auto raw = ctx.ReadBufferCopy(); auto log = Common::StringFromFixedZeroTerminatedBuffer( reinterpret_cast<const char*>(raw.data()), raw.size()); @@ -1098,7 +1107,7 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void FSP_SRV::GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx) { +void FSP_SRV::GetProgramIndexForAccessLog(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -1107,7 +1116,7 @@ void FSP_SRV::GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx) { rb.Push(access_log_program_index); } -void FSP_SRV::GetCacheStorageSize(Kernel::HLERequestContext& ctx) { +void FSP_SRV::GetCacheStorageSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto index{rp.Pop<s32>()}; @@ -1133,14 +1142,14 @@ public: private: FileSys::VirtualFile backend; - void Add(Kernel::HLERequestContext& ctx) { + void Add(HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void Commit(Kernel::HLERequestContext& ctx) { + void Commit(HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -1148,7 +1157,7 @@ private: } }; -void FSP_SRV::OpenMultiCommitManager(Kernel::HLERequestContext& ctx) { +void FSP_SRV::OpenMultiCommitManager(HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 3d88b97f9..4f3c2f6de 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -35,26 +35,27 @@ public: ~FSP_SRV() override; private: - void SetCurrentProcess(Kernel::HLERequestContext& ctx); - void OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx); - void OpenSdCardFileSystem(Kernel::HLERequestContext& ctx); - void CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx); - void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx); - void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); - void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); - void WriteSaveDataFileSystemExtraDataBySaveDataAttribute(Kernel::HLERequestContext& ctx); - void ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(Kernel::HLERequestContext& ctx); - void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); - void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); - void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); - void OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx); - void DisableAutoSaveDataCreation(Kernel::HLERequestContext& ctx); - void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); - void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); - void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); - void GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx); - void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); - void GetCacheStorageSize(Kernel::HLERequestContext& ctx); + void SetCurrentProcess(HLERequestContext& ctx); + void OpenFileSystemWithPatch(HLERequestContext& ctx); + void OpenSdCardFileSystem(HLERequestContext& ctx); + void CreateSaveDataFileSystem(HLERequestContext& ctx); + void OpenSaveDataFileSystem(HLERequestContext& ctx); + void OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx); + void OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx); + void OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx); + void WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx); + void ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(HLERequestContext& ctx); + void OpenDataStorageByCurrentProcess(HLERequestContext& ctx); + void OpenDataStorageByDataId(HLERequestContext& ctx); + void OpenPatchDataStorageByCurrentProcess(HLERequestContext& ctx); + void OpenDataStorageWithProgramIndex(HLERequestContext& ctx); + void DisableAutoSaveDataCreation(HLERequestContext& ctx); + void SetGlobalAccessLogMode(HLERequestContext& ctx); + void GetGlobalAccessLogMode(HLERequestContext& ctx); + void OutputAccessLogToSdCard(HLERequestContext& ctx); + void GetProgramIndexForAccessLog(HLERequestContext& ctx); + void OpenMultiCommitManager(HLERequestContext& ctx); + void GetCacheStorageSize(HLERequestContext& ctx); FileSystemController& fsc; const FileSys::ContentProvider& content_provider; diff --git a/src/core/hle/service/friend/errors.h b/src/core/hle/service/friend/errors.h deleted file mode 100644 index ff525d865..000000000 --- a/src/core/hle/service/friend/errors.h +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/result.h" - -namespace Service::Friend { - -constexpr Result ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15}; -} diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index fad532115..9d05f9801 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -5,12 +5,13 @@ #include "common/logging/log.h" #include "common/uuid.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" -#include "core/hle/service/friend/errors.h" +#include "core/hle/service/acc/errors.h" #include "core/hle/service/friend/friend.h" #include "core/hle/service/friend/friend_interface.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/server_manager.h" namespace Service::Friend { @@ -135,7 +136,7 @@ private: }; static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size"); - void GetCompletionEvent(Kernel::HLERequestContext& ctx) { + void GetCompletionEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Friend, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -143,7 +144,7 @@ private: rb.PushCopyObjects(completion_event->GetReadableEvent()); } - void GetBlockedUserListIds(Kernel::HLERequestContext& ctx) { + void GetBlockedUserListIds(HLERequestContext& ctx) { // This is safe to stub, as there should be no adverse consequences from reporting no // blocked users. LOG_WARNING(Service_Friend, "(STUBBED) called"); @@ -152,21 +153,21 @@ private: rb.Push<u32>(0); // Indicates there are no blocked users } - void DeclareCloseOnlinePlaySession(Kernel::HLERequestContext& ctx) { + void DeclareCloseOnlinePlaySession(HLERequestContext& ctx) { // Stub used by Splatoon 2 LOG_WARNING(Service_Friend, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void UpdateUserPresence(Kernel::HLERequestContext& ctx) { + void UpdateUserPresence(HLERequestContext& ctx) { // Stub used by Retro City Rampage LOG_WARNING(Service_Friend, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void GetPlayHistoryRegistrationKey(Kernel::HLERequestContext& ctx) { + void GetPlayHistoryRegistrationKey(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto local_play = rp.Pop<bool>(); const auto uuid = rp.PopRaw<Common::UUID>(); @@ -178,7 +179,7 @@ private: rb.Push(ResultSuccess); } - void GetFriendList(Kernel::HLERequestContext& ctx) { + void GetFriendList(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto friend_offset = rp.Pop<u32>(); const auto uuid = rp.PopRaw<Common::UUID>(); @@ -194,7 +195,7 @@ private: // TODO(ogniK): Return a buffer of u64s which are the "NetworkServiceAccountId" } - void CheckFriendListAvailability(Kernel::HLERequestContext& ctx) { + void CheckFriendListAvailability(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto uuid{rp.PopRaw<Common::UUID>()}; @@ -233,7 +234,7 @@ public: } private: - void GetEvent(Kernel::HLERequestContext& ctx) { + void GetEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_Friend, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -241,7 +242,7 @@ private: rb.PushCopyObjects(notification_event->GetReadableEvent()); } - void Clear(Kernel::HLERequestContext& ctx) { + void Clear(HLERequestContext& ctx) { LOG_DEBUG(Service_Friend, "called"); while (!notifications.empty()) { notifications.pop(); @@ -252,13 +253,13 @@ private: rb.Push(ResultSuccess); } - void Pop(Kernel::HLERequestContext& ctx) { + void Pop(HLERequestContext& ctx) { LOG_DEBUG(Service_Friend, "called"); if (notifications.empty()) { LOG_ERROR(Service_Friend, "No notifications in queue!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NO_NOTIFICATIONS); + rb.Push(Account::ResultNoNotifications); return; } @@ -311,14 +312,14 @@ private: States states{}; }; -void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateFriendService(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IFriendService>(system); LOG_DEBUG(Service_Friend, "called"); } -void Module::Interface::CreateNotificationService(Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateNotificationService(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto uuid = rp.PopRaw<Common::UUID>(); @@ -335,13 +336,22 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst Module::Interface::~Interface() = default; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); auto module = std::make_shared<Module>(); - std::make_shared<Friend>(module, system, "friend:a")->InstallAsService(service_manager); - std::make_shared<Friend>(module, system, "friend:m")->InstallAsService(service_manager); - std::make_shared<Friend>(module, system, "friend:s")->InstallAsService(service_manager); - std::make_shared<Friend>(module, system, "friend:u")->InstallAsService(service_manager); - std::make_shared<Friend>(module, system, "friend:v")->InstallAsService(service_manager); + + server_manager->RegisterNamedService("friend:a", + std::make_shared<Friend>(module, system, "friend:a")); + server_manager->RegisterNamedService("friend:m", + std::make_shared<Friend>(module, system, "friend:m")); + server_manager->RegisterNamedService("friend:s", + std::make_shared<Friend>(module, system, "friend:s")); + server_manager->RegisterNamedService("friend:u", + std::make_shared<Friend>(module, system, "friend:u")); + server_manager->RegisterNamedService("friend:v", + std::make_shared<Friend>(module, system, "friend:v")); + + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Friend diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h index 444da8b35..2824dc786 100644 --- a/src/core/hle/service/friend/friend.h +++ b/src/core/hle/service/friend/friend.h @@ -19,15 +19,14 @@ public: const char* name); ~Interface() override; - void CreateFriendService(Kernel::HLERequestContext& ctx); - void CreateNotificationService(Kernel::HLERequestContext& ctx); + void CreateFriendService(HLERequestContext& ctx); + void CreateNotificationService(HLERequestContext& ctx); protected: std::shared_ptr<Module> module; }; }; -/// Registers all Friend services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Friend diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 49b6d45fe..ed6fcb5f6 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -5,12 +5,12 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/kernel.h" #include "core/hle/service/glue/arp.h" #include "core/hle/service/glue/errors.h" #include "core/hle/service/glue/glue_manager.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Glue { @@ -18,14 +18,14 @@ namespace { std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) { const auto& list = system.Kernel().GetProcessList(); const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { - return process->GetProcessID() == process_id; + return process->GetProcessId() == process_id; }); if (iter == list.end()) { return std::nullopt; } - return (*iter)->GetProgramID(); + return (*iter)->GetProgramId(); } } // Anonymous namespace @@ -51,7 +51,7 @@ ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_) ARP_R::~ARP_R() = default; -void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { +void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw<u64>(); @@ -61,7 +61,7 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NOT_REGISTERED); + rb.Push(Glue::ResultProcessIdNotRegistered); return; } @@ -79,7 +79,7 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { rb.PushRaw(*res); } -void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { +void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); @@ -99,7 +99,7 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestCont rb.PushRaw(*res); } -void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { +void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw<u64>(); @@ -109,7 +109,7 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NOT_REGISTERED); + rb.Push(Glue::ResultProcessIdNotRegistered); return; } @@ -128,7 +128,7 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { +void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); @@ -169,7 +169,7 @@ public: } private: - void Issue(Kernel::HLERequestContext& ctx) { + void Issue(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw<u64>(); @@ -178,7 +178,7 @@ private: if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_PROCESS_ID); + rb.Push(Glue::ResultInvalidProcessId); return; } @@ -186,7 +186,7 @@ private: LOG_ERROR(Service_ARP, "Attempted to issue registrar, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_ACCESS); + rb.Push(Glue::ResultAlreadyBound); return; } @@ -197,7 +197,7 @@ private: rb.Push(ResultSuccess); } - void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { + void SetApplicationLaunchProperty(HLERequestContext& ctx) { LOG_DEBUG(Service_ARP, "called"); if (issued) { @@ -205,7 +205,7 @@ private: Service_ARP, "Attempted to set application launch property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_ACCESS); + rb.Push(Glue::ResultAlreadyBound); return; } @@ -216,7 +216,7 @@ private: rb.Push(ResultSuccess); } - void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) { + void SetApplicationControlProperty(HLERequestContext& ctx) { LOG_DEBUG(Service_ARP, "called"); if (issued) { @@ -224,11 +224,12 @@ private: Service_ARP, "Attempted to set application control property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_ACCESS); + rb.Push(Glue::ResultAlreadyBound); return; } - control = ctx.ReadBuffer(); + // TODO: Can this be a span? + control = ctx.ReadBufferCopy(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -255,14 +256,14 @@ ARP_W::ARP_W(Core::System& system_, ARPManager& manager_) ARP_W::~ARP_W() = default; -void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { +void ARP_W::AcquireRegistrar(HLERequestContext& ctx) { LOG_DEBUG(Service_ARP, "called"); registrar = std::make_shared<IRegistrar>( system, [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) { const auto res = GetTitleIDForProcessID(system, process_id); if (!res.has_value()) { - return ERR_NOT_REGISTERED; + return Glue::ResultProcessIdNotRegistered; } return manager.Register(*res, launch, std::move(control)); @@ -273,7 +274,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface(registrar); } -void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) { +void ARP_W::UnregisterApplicationInstance(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw<u64>(); @@ -282,7 +283,7 @@ void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) { if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_PROCESS_ID); + rb.Push(Glue::ResultInvalidProcessId); return; } @@ -291,7 +292,7 @@ void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "No title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NOT_REGISTERED); + rb.Push(Glue::ResultProcessIdNotRegistered); return; } diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h index 06c992e88..5bce80175 100644 --- a/src/core/hle/service/glue/arp.h +++ b/src/core/hle/service/glue/arp.h @@ -16,10 +16,10 @@ public: ~ARP_R() override; private: - void GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx); - void GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx); - void GetApplicationControlProperty(Kernel::HLERequestContext& ctx); - void GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx); + void GetApplicationLaunchProperty(HLERequestContext& ctx); + void GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx); + void GetApplicationControlProperty(HLERequestContext& ctx); + void GetApplicationControlPropertyWithApplicationId(HLERequestContext& ctx); const ARPManager& manager; }; @@ -30,8 +30,8 @@ public: ~ARP_W() override; private: - void AcquireRegistrar(Kernel::HLERequestContext& ctx); - void UnregisterApplicationInstance(Kernel::HLERequestContext& ctx); + void AcquireRegistrar(HLERequestContext& ctx); + void UnregisterApplicationInstance(HLERequestContext& ctx); ARPManager& manager; std::shared_ptr<IRegistrar> registrar; diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp index 3248091c3..ae22ac4f7 100644 --- a/src/core/hle/service/glue/bgtc.cpp +++ b/src/core/hle/service/glue/bgtc.cpp @@ -3,8 +3,8 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/glue/bgtc.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Glue { @@ -20,7 +20,7 @@ BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { BGTC_T::~BGTC_T() = default; -void BGTC_T::OpenTaskService(Kernel::HLERequestContext& ctx) { +void BGTC_T::OpenTaskService(HLERequestContext& ctx) { LOG_DEBUG(Service_BGTC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h index d6e2baec1..5a5d9c9a7 100644 --- a/src/core/hle/service/glue/bgtc.h +++ b/src/core/hle/service/glue/bgtc.h @@ -16,7 +16,7 @@ public: explicit BGTC_T(Core::System& system_); ~BGTC_T() override; - void OpenTaskService(Kernel::HLERequestContext& ctx); + void OpenTaskService(HLERequestContext& ctx); }; class ITaskService final : public ServiceFramework<ITaskService> { diff --git a/src/core/hle/service/glue/errors.h b/src/core/hle/service/glue/errors.h index d4ce7f44e..30feaa5c0 100644 --- a/src/core/hle/service/glue/errors.h +++ b/src/core/hle/service/glue/errors.h @@ -7,9 +7,8 @@ namespace Service::Glue { -constexpr Result ERR_INVALID_RESOURCE{ErrorModule::ARP, 30}; -constexpr Result ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 31}; -constexpr Result ERR_INVALID_ACCESS{ErrorModule::ARP, 42}; -constexpr Result ERR_NOT_REGISTERED{ErrorModule::ARP, 102}; +constexpr Result ResultInvalidProcessId{ErrorModule::ARP, 31}; +constexpr Result ResultAlreadyBound{ErrorModule::ARP, 42}; +constexpr Result ResultProcessIdNotRegistered{ErrorModule::ARP, 102}; } // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp index 717f2562b..993c3d21d 100644 --- a/src/core/hle/service/glue/glue.cpp +++ b/src/core/hle/service/glue/glue.cpp @@ -8,25 +8,30 @@ #include "core/hle/service/glue/ectx.h" #include "core/hle/service/glue/glue.h" #include "core/hle/service/glue/notif.h" +#include "core/hle/service/server_manager.h" namespace Service::Glue { -void InstallInterfaces(Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + // ARP - std::make_shared<ARP_R>(system, system.GetARPManager()) - ->InstallAsService(system.ServiceManager()); - std::make_shared<ARP_W>(system, system.GetARPManager()) - ->InstallAsService(system.ServiceManager()); + server_manager->RegisterNamedService("arp:r", + std::make_shared<ARP_R>(system, system.GetARPManager())); + server_manager->RegisterNamedService("arp:w", + std::make_shared<ARP_W>(system, system.GetARPManager())); // BackGround Task Controller - std::make_shared<BGTC_T>(system)->InstallAsService(system.ServiceManager()); - std::make_shared<BGTC_SC>(system)->InstallAsService(system.ServiceManager()); + server_manager->RegisterNamedService("bgtc:t", std::make_shared<BGTC_T>(system)); + server_manager->RegisterNamedService("bgtc:sc", std::make_shared<BGTC_SC>(system)); // Error Context - std::make_shared<ECTX_AW>(system)->InstallAsService(system.ServiceManager()); + server_manager->RegisterNamedService("ectx:aw", std::make_shared<ECTX_AW>(system)); // Notification Services for application - std::make_shared<NOTIF_A>(system)->InstallAsService(system.ServiceManager()); + server_manager->RegisterNamedService("notif:a", std::make_shared<NOTIF_A>(system)); + + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue.h b/src/core/hle/service/glue/glue.h index ae7c6d235..2a906f5ad 100644 --- a/src/core/hle/service/glue/glue.h +++ b/src/core/hle/service/glue/glue.h @@ -9,7 +9,6 @@ class System; namespace Service::Glue { -/// Registers all Glue services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue_manager.cpp b/src/core/hle/service/glue/glue_manager.cpp index 8a654cdca..4bf67921b 100644 --- a/src/core/hle/service/glue/glue_manager.cpp +++ b/src/core/hle/service/glue/glue_manager.cpp @@ -17,12 +17,12 @@ ARPManager::~ARPManager() = default; ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const { if (title_id == 0) { - return ERR_INVALID_PROCESS_ID; + return Glue::ResultInvalidProcessId; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NOT_REGISTERED; + return Glue::ResultProcessIdNotRegistered; } return iter->second.launch; @@ -30,12 +30,12 @@ ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { if (title_id == 0) { - return ERR_INVALID_PROCESS_ID; + return Glue::ResultInvalidProcessId; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NOT_REGISTERED; + return Glue::ResultProcessIdNotRegistered; } return iter->second.control; @@ -44,12 +44,12 @@ ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control) { if (title_id == 0) { - return ERR_INVALID_PROCESS_ID; + return Glue::ResultInvalidProcessId; } const auto iter = entries.find(title_id); if (iter != entries.end()) { - return ERR_INVALID_ACCESS; + return Glue::ResultAlreadyBound; } entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)}); @@ -58,12 +58,12 @@ Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, Result ARPManager::Unregister(u64 title_id) { if (title_id == 0) { - return ERR_INVALID_PROCESS_ID; + return Glue::ResultInvalidProcessId; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NOT_REGISTERED; + return Glue::ResultProcessIdNotRegistered; } entries.erase(iter); diff --git a/src/core/hle/service/glue/glue_manager.h b/src/core/hle/service/glue/glue_manager.h index cd0b092ac..1cf53d9d9 100644 --- a/src/core/hle/service/glue/glue_manager.h +++ b/src/core/hle/service/glue/glue_manager.h @@ -30,23 +30,23 @@ public: ~ARPManager(); // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was - // previously registered, otherwise ERR_NOT_REGISTERED if it was never registered or - // ERR_INVALID_PROCESS_ID if the title ID is 0. + // previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or + // ResultInvalidProcessId if the title ID is 0. ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const; // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to - // the provided title ID if it was previously registered, otherwise ERR_NOT_REGISTERED if it was - // never registered or ERR_INVALID_PROCESS_ID if the title ID is 0. + // the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered + // if it was never registered or ResultInvalidProcessId if the title ID is 0. ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const; // Adds a new entry to the internal database with the provided parameters, returning - // ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister - // step, and ERR_INVALID_PROCESS_ID if the title ID is 0. + // ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate + // Unregister step, and ResultInvalidProcessId if the title ID is 0. Result Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control); // Removes the registration for the provided title ID from the database, returning - // ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the - // title ID is 0. + // ResultProcessIdNotRegistered if it doesn't exist in the database and ResultInvalidProcessId + // if the title ID is 0. Result Unregister(u64 title_id); // Removes all entries from the database, always succeeds. Should only be used when resetting diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp index 3ace2dabd..fec4ad86c 100644 --- a/src/core/hle/service/glue/notif.cpp +++ b/src/core/hle/service/glue/notif.cpp @@ -6,8 +6,8 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/glue/notif.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Glue { @@ -28,7 +28,7 @@ NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} { NOTIF_A::~NOTIF_A() = default; -void NOTIF_A::RegisterAlarmSetting(Kernel::HLERequestContext& ctx) { +void NOTIF_A::RegisterAlarmSetting(HLERequestContext& ctx) { const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0); const auto application_parameter_size = ctx.GetReadBufferSize(1); @@ -63,7 +63,7 @@ void NOTIF_A::RegisterAlarmSetting(Kernel::HLERequestContext& ctx) { rb.Push(new_alarm.alarm_setting_id); } -void NOTIF_A::UpdateAlarmSetting(Kernel::HLERequestContext& ctx) { +void NOTIF_A::UpdateAlarmSetting(HLERequestContext& ctx) { const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0); const auto application_parameter_size = ctx.GetReadBufferSize(1); @@ -91,7 +91,7 @@ void NOTIF_A::UpdateAlarmSetting(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) { +void NOTIF_A::ListAlarmSettings(HLERequestContext& ctx) { LOG_INFO(Service_NOTIF, "called, alarm_count={}", alarms.size()); // TODO: Only return alarms of this game id @@ -102,7 +102,7 @@ void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u32>(alarms.size())); } -void NOTIF_A::LoadApplicationParameter(Kernel::HLERequestContext& ctx) { +void NOTIF_A::LoadApplicationParameter(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto alarm_setting_id{rp.Pop<AlarmSettingId>()}; @@ -126,7 +126,7 @@ void NOTIF_A::LoadApplicationParameter(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u32>(application_parameter.size())); } -void NOTIF_A::DeleteAlarmSetting(Kernel::HLERequestContext& ctx) { +void NOTIF_A::DeleteAlarmSetting(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto alarm_setting_id{rp.Pop<AlarmSettingId>()}; @@ -140,7 +140,7 @@ void NOTIF_A::DeleteAlarmSetting(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) { +void NOTIF_A::Initialize(HLERequestContext& ctx) { // TODO: Load previous alarms from config LOG_WARNING(Service_NOTIF, "(STUBBED) called"); diff --git a/src/core/hle/service/glue/notif.h b/src/core/hle/service/glue/notif.h index 4467e1f35..b1187f3a3 100644 --- a/src/core/hle/service/glue/notif.h +++ b/src/core/hle/service/glue/notif.h @@ -56,12 +56,12 @@ private: }; static_assert(sizeof(AlarmSetting) == 0x40, "AlarmSetting is an invalid size"); - void RegisterAlarmSetting(Kernel::HLERequestContext& ctx); - void UpdateAlarmSetting(Kernel::HLERequestContext& ctx); - void ListAlarmSettings(Kernel::HLERequestContext& ctx); - void LoadApplicationParameter(Kernel::HLERequestContext& ctx); - void DeleteAlarmSetting(Kernel::HLERequestContext& ctx); - void Initialize(Kernel::HLERequestContext& ctx); + void RegisterAlarmSetting(HLERequestContext& ctx); + void UpdateAlarmSetting(HLERequestContext& ctx); + void ListAlarmSettings(HLERequestContext& ctx); + void LoadApplicationParameter(HLERequestContext& ctx); + void DeleteAlarmSetting(HLERequestContext& ctx); + void Initialize(HLERequestContext& ctx); std::vector<AlarmSetting>::iterator GetAlarmFromId(AlarmSettingId alarm_setting_id); diff --git a/src/core/hle/service/grc/grc.cpp b/src/core/hle/service/grc/grc.cpp index 4b684f6d0..64275da36 100644 --- a/src/core/hle/service/grc/grc.cpp +++ b/src/core/hle/service/grc/grc.cpp @@ -4,8 +4,8 @@ #include <memory> #include "core/hle/service/grc/grc.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::GRC { @@ -26,8 +26,11 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<GRC>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("grc:c", std::make_shared<GRC>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::GRC diff --git a/src/core/hle/service/grc/grc.h b/src/core/hle/service/grc/grc.h index f8c2f8dab..a3f8a5b90 100644 --- a/src/core/hle/service/grc/grc.h +++ b/src/core/hle/service/grc/grc.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::GRC { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::GRC diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index bb3cba910..bcb272eaf 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -1,17 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/core.h" #include "core/core_timing.h" #include "core/hid/emulated_console.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/console_sixaxis.h" +#include "core/memory.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; -Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_, - u8* raw_shared_memory_) - : ControllerBase{hid_core_} { +Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_) + : ControllerBase{system_.HIDCore()}, system{system_} { console = hid_core.GetEmulatedConsole(); static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size, "ConsoleSharedMemory is bigger than the shared memory"); @@ -26,7 +27,7 @@ void Controller_ConsoleSixAxis::OnInit() {} void Controller_ConsoleSixAxis::OnRelease() {} void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!IsControllerActivated() || !is_transfer_memory_set) { + if (!IsControllerActivated() || transfer_memory == 0) { seven_sixaxis_lifo.buffer_count = 0; seven_sixaxis_lifo.buffer_tail = 0; return; @@ -59,11 +60,11 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti // Update seven six axis transfer memory seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); - std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); + system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, + sizeof(seven_sixaxis_lifo)); } -void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) { - is_transfer_memory_set = true; +void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { transfer_memory = t_mem; } diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index 2fd11538f..7015d924c 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -5,11 +5,15 @@ #include <array> -#include "common/common_types.h" #include "common/quaternion.h" +#include "common/typed_address.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" +namespace Core { +class System; +} // namespace Core + namespace Core::HID { class EmulatedConsole; } // namespace Core::HID @@ -17,7 +21,7 @@ class EmulatedConsole; namespace Service::HID { class Controller_ConsoleSixAxis final : public ControllerBase { public: - explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_); ~Controller_ConsoleSixAxis() override; // Called when the controller is initialized @@ -30,7 +34,7 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; // Called on InitializeSevenSixAxisSensor - void SetTransferMemoryPointer(u8* t_mem); + void SetTransferMemoryAddress(Common::ProcessAddress t_mem); // Called on ResetSevenSixAxisSensorTimestamp void ResetTimestamp(); @@ -62,12 +66,13 @@ private: static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); SevenSixAxisState next_seven_sixaxis_state{}; - u8* transfer_memory = nullptr; + Common::ProcessAddress transfer_memory{}; ConsoleSharedMemory* shared_memory = nullptr; Core::HID::EmulatedConsole* console = nullptr; - bool is_transfer_memory_set = false; u64 last_saved_timestamp{}; u64 last_global_timestamp{}; + + Core::System& system; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 32e0708ba..03432f7cb 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -55,7 +55,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); - // Only update if necesary + // Only update if necessary if (!ShouldUpdateGesture(gesture, time_difference)) { return; } @@ -65,6 +65,11 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { } void Controller_Gesture::ReadTouchInput() { + if (!Settings::values.touchscreen.enabled) { + fingers = {}; + return; + } + const auto touch_status = console->GetTouch(); for (std::size_t id = 0; id < fingers.size(); ++id) { fingers[id] = touch_status[id]; diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index b11cb438d..0afc66681 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -33,10 +33,11 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } + next_state = {}; + const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; - next_state.attribute.raw = 0; if (Settings::values.mouse_enabled) { const auto& mouse_button_state = emulated_devices->GetMouseButtons(); const auto& mouse_position_state = emulated_devices->GetMousePosition(); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 2f871de31..28818c813 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -70,7 +70,6 @@ Result Controller_NPad::VerifyValidSixAxisSensorHandle( const Core::HID::SixAxisSensorHandle& device_handle) { const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)); const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; - const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType; if (!npad_id) { return InvalidNpadId; @@ -78,10 +77,6 @@ Result Controller_NPad::VerifyValidSixAxisSensorHandle( if (!device_index) { return NpadDeviceIndexOutOfRange; } - // This doesn't get validated on nnsdk - if (!npad_type) { - return NpadInvalidHandle; - } return ResultSuccess; } @@ -272,6 +267,8 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { } break; case Core::HID::NpadStyleIndex::JoyconLeft: + shared_memory->fullkey_color.attribute = ColorAttribute::Ok; + shared_memory->fullkey_color.fullkey = body_colors.left; shared_memory->joycon_color.attribute = ColorAttribute::Ok; shared_memory->joycon_color.left = body_colors.left; shared_memory->battery_level_dual = battery_level.left.battery_level; @@ -285,6 +282,8 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); break; case Core::HID::NpadStyleIndex::JoyconRight: + shared_memory->fullkey_color.attribute = ColorAttribute::Ok; + shared_memory->fullkey_color.fullkey = body_colors.right; shared_memory->joycon_color.attribute = ColorAttribute::Ok; shared_memory->joycon_color.right = body_colors.right; shared_memory->battery_level_right = battery_level.right.battery_level; @@ -332,6 +331,20 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { controller.is_connected = true; controller.device->Connect(); + controller.device->SetLedPattern(); + if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) { + if (controller.is_dual_left_connected) { + controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex, + Common::Input::PollingMode::Active); + } + if (controller.is_dual_right_connected) { + controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); + } + } else { + controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, + Common::Input::PollingMode::Active); + } SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory); } @@ -410,6 +423,9 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { return; } + // This function is unique to yuzu for the turbo buttons and motion to work properly + controller.device->StatusUpdate(); + auto& pad_entry = controller.npad_pad_state; auto& trigger_entry = controller.npad_trigger_state; const auto button_state = controller.device->GetNpadButtons(); @@ -737,11 +753,20 @@ Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { return hid_core.GetSupportedStyleTag(); } -void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { +Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) { + constexpr std::size_t max_number_npad_ids = 0xa; + const auto length = data.size(); ASSERT(length > 0 && (length % sizeof(u32)) == 0); + const std::size_t elements = length / sizeof(u32); + + if (elements > max_number_npad_ids) { + return InvalidArraySize; + } + supported_npad_id_types.clear(); - supported_npad_id_types.resize(length / sizeof(u32)); - std::memcpy(supported_npad_id_types.data(), data, length); + supported_npad_id_types.resize(elements); + std::memcpy(supported_npad_id_types.data(), data.data(), length); + return ResultSuccess; } void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { @@ -789,12 +814,12 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode return communication_mode; } -Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, - NpadJoyAssignmentMode assignment_mode) { +bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_device_type, + NpadJoyAssignmentMode assignment_mode) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return InvalidNpadId; + return false; } auto& controller = GetControllerFromNpadIdType(npad_id); @@ -803,7 +828,7 @@ Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, } if (!controller.device->IsConnected()) { - return ResultSuccess; + return false; } if (assignment_mode == NpadJoyAssignmentMode::Dual) { @@ -812,52 +837,52 @@ Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, controller.is_dual_left_connected = true; controller.is_dual_right_connected = false; UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return ResultSuccess; + return false; } if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { DisconnectNpad(npad_id); controller.is_dual_left_connected = false; controller.is_dual_right_connected = true; UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return ResultSuccess; + return false; } - return ResultSuccess; + return false; } // This is for NpadJoyAssignmentMode::Single // Only JoyconDual get affected by this function if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { - return ResultSuccess; + return false; } if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { DisconnectNpad(npad_id); UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); - return ResultSuccess; + return false; } if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { DisconnectNpad(npad_id); UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); - return ResultSuccess; + return false; } // We have two controllers connected to the same npad_id we need to split them - const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId(); - auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); + new_npad_id = hid_core.GetFirstDisconnectedNpadId(); + auto& controller_2 = GetControllerFromNpadIdType(new_npad_id); DisconnectNpad(npad_id); if (npad_device_type == NpadJoyDeviceType::Left) { UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); controller_2.is_dual_left_connected = false; controller_2.is_dual_right_connected = true; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } else { UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); controller_2.is_dual_left_connected = true; controller_2.is_dual_right_connected = false; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } - return ResultSuccess; + return true; } bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, @@ -954,8 +979,8 @@ void Controller_NPad::VibrateController( } void Controller_NPad::VibrateControllers( - const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles, - const std::vector<Core::HID::VibrationValue>& vibration_values) { + std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, + std::span<const Core::HID::VibrationValue> vibration_values) { if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { return; } @@ -1101,8 +1126,10 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { WriteEmptyEntry(shared_memory); return ResultSuccess; } + Result Controller_NPad::SetGyroscopeZeroDriftMode( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) { + const Core::HID::SixAxisSensorHandle& sixaxis_handle, + Core::HID::GyroscopeZeroDriftMode drift_mode) { const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); if (is_valid.IsError()) { LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); @@ -1110,14 +1137,16 @@ Result Controller_NPad::SetGyroscopeZeroDriftMode( } auto& sixaxis = GetSixaxisState(sixaxis_handle); + auto& controller = GetControllerFromHandle(sixaxis_handle); sixaxis.gyroscope_zero_drift_mode = drift_mode; + controller.device->SetGyroscopeZeroDriftMode(drift_mode); return ResultSuccess; } Result Controller_NPad::GetGyroscopeZeroDriftMode( const Core::HID::SixAxisSensorHandle& sixaxis_handle, - GyroscopeZeroDriftMode& drift_mode) const { + Core::HID::GyroscopeZeroDriftMode& drift_mode) const { const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); if (is_valid.IsError()) { LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); @@ -1355,7 +1384,8 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, return NpadIsDualJoycon; } - // Disconnect the joycon at the second id and connect the dual joycon at the first index. + // Disconnect the joycons and connect them as dual joycon at the first index. + DisconnectNpad(npad_id_1); DisconnectNpad(npad_id_2); controller_1.is_dual_left_connected = true; controller_1.is_dual_right_connected = true; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 1a589cca2..776411261 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -6,6 +6,7 @@ #include <array> #include <atomic> #include <mutex> +#include <span> #include "common/bit_field.h" #include "common/common_types.h" @@ -51,13 +52,6 @@ public: // When the controller is requesting a motion update for the shared memory void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override; - // This is nn::hid::GyroscopeZeroDriftMode - enum class GyroscopeZeroDriftMode : u32 { - Loose = 0, - Standard = 1, - Tight = 2, - }; - // This is nn::hid::NpadJoyHoldType enum class NpadJoyHoldType : u64 { Vertical = 0, @@ -95,7 +89,7 @@ public: void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); Core::HID::NpadStyleTag GetSupportedStyleSet() const; - void SetSupportedNpadIdTypes(u8* data, std::size_t length); + Result SetSupportedNpadIdTypes(std::span<const u8> data); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); std::size_t GetSupportedNpadIdTypesSize() const; @@ -108,8 +102,8 @@ public: void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); NpadCommunicationMode GetNpadCommunicationMode() const; - Result SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, - NpadJoyAssignmentMode assignment_mode); + bool SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, const Core::HID::VibrationValue& vibration_value); @@ -118,8 +112,8 @@ public: const Core::HID::VibrationValue& vibration_value); void VibrateControllers( - const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles, - const std::vector<Core::HID::VibrationValue>& vibration_values); + std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, + std::span<const Core::HID::VibrationValue> vibration_values); Core::HID::VibrationValue GetLastVibration( const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; @@ -145,9 +139,9 @@ public: Result DisconnectNpad(Core::HID::NpadIdType npad_id); Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - GyroscopeZeroDriftMode drift_mode); + Core::HID::GyroscopeZeroDriftMode drift_mode); Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - GyroscopeZeroDriftMode& drift_mode) const; + Core::HID::GyroscopeZeroDriftMode& drift_mode) const; Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_at_rest) const; Result IsFirmwareUpdateAvailableForSixAxisSensor( @@ -488,7 +482,8 @@ private: Core::HID::SixAxisSensorFusionParameters fusion{}; Core::HID::SixAxisSensorCalibrationParameter calibration{}; Core::HID::SixAxisSensorIcInformation ic_information{}; - GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; + Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{ + Core::HID::GyroscopeZeroDriftMode::Standard}; }; struct NpadControllerData { diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp index 4564ea1e2..14c67e454 100644 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ b/src/core/hle/service/hid/controllers/palma.cpp @@ -152,7 +152,7 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl } Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, - u8* t_mem, u64 size) { + Common::ProcessAddress t_mem, u64 size) { if (handle.npad_id != active_handle.npad_id) { return InvalidPalmaHandle; } diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h index 1d7fc94e1..a0491a819 100644 --- a/src/core/hle/service/hid/controllers/palma.h +++ b/src/core/hle/service/hid/controllers/palma.h @@ -5,7 +5,7 @@ #include <array> #include "common/common_funcs.h" -#include "common/common_types.h" +#include "common/typed_address.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/errors.h" @@ -125,8 +125,8 @@ public: Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); - Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, u8* t_mem, - u64 size); + Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, + Common::ProcessAddress t_mem, u64 size); Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, s32 database_id_version_); Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index df9ee0c3f..9e2f3ab21 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -26,7 +26,7 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) { } CommonHeader header{}; - header.timestamp = core_timing.GetCPUTicks(); + header.timestamp = core_timing.GetGlobalTimeNs().count(); header.total_entry_count = 17; header.entry_count = 0; header.last_entry_index = 0; diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 1da8d3eb0..3ef91df4b 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -32,7 +32,7 @@ void Controller_Touchscreen::OnInit() {} void Controller_Touchscreen::OnRelease() {} void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - shared_memory->touch_screen_lifo.timestamp = core_timing.GetCPUTicks(); + shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); if (!IsControllerActivated()) { shared_memory->touch_screen_lifo.buffer_count = 0; @@ -58,6 +58,11 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin } if (!finger.pressed && current_touch.pressed) { + // Ignore all touch fingers if disabled + if (!Settings::values.touchscreen.enabled) { + continue; + } + finger.attribute.start_touch.Assign(1); finger.pressed = true; finger.position = current_touch.position; @@ -80,7 +85,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin const auto active_fingers_count = static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); - const u64 tick = core_timing.GetCPUTicks(); + const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count()); const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; @@ -97,8 +102,8 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; - touch_entry.delta_time = tick - active_fingers[id].last_touch; - fingers[active_fingers[id].id].last_touch = tick; + touch_entry.delta_time = timestamp - active_fingers[id].last_touch; + fingers[active_fingers[id].id].last_touch = timestamp; touch_entry.finger = active_fingers[id].id; touch_entry.attribute.raw = active_fingers[id].attribute.raw; } else { diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index 76208e9a4..9585bdaf0 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h @@ -18,6 +18,7 @@ constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; constexpr Result NpadIsSameType{ErrorModule::HID, 602}; constexpr Result InvalidNpadId{ErrorModule::HID, 709}; constexpr Result NpadNotConnected{ErrorModule::HID, 710}; +constexpr Result InvalidArraySize{ErrorModule::HID, 715}; constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302}; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index bf28440c6..2bf1d8a27 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -8,7 +8,6 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/hid/hid_core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_transfer_memory.h" @@ -18,6 +17,8 @@ #include "core/hle/service/hid/hidbus.h" #include "core/hle/service/hid/irs.h" #include "core/hle/service/hid/xcd.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/memory.h" #include "core/hle/service/hid/controllers/console_sixaxis.h" @@ -63,6 +64,7 @@ IAppletResource::IAppletResource(Core::System& system_, MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory); MakeController<Controller_Gesture>(HidController::Gesture, shared_memory); MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory); + MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory); MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory); // Homebrew doesn't try to activate some controllers, so we activate them by default @@ -74,6 +76,7 @@ IAppletResource::IAppletResource(Core::System& system_, GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000); GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200); GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00); + GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00); // Register update callbacks npad_update_event = Core::Timing::CreateEvent( @@ -135,7 +138,7 @@ IAppletResource::~IAppletResource() { system.CoreTiming().UnscheduleEvent(motion_update_event, 0); } -void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { +void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -200,7 +203,7 @@ public: } private: - void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { + void InitializeVibrationDevice(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; @@ -236,6 +239,7 @@ Hid::Hid(Core::System& system_) {1, &Hid::ActivateDebugPad, "ActivateDebugPad"}, {11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"}, {21, &Hid::ActivateMouse, "ActivateMouse"}, + {26, nullptr, "ActivateDebugMouse"}, {31, &Hid::ActivateKeyboard, "ActivateKeyboard"}, {32, &Hid::SendKeyboardLockKeyEvent, "SendKeyboardLockKeyEvent"}, {40, nullptr, "AcquireXpadIdEventHandle"}, @@ -298,7 +302,7 @@ Hid::Hid(Core::System& system_) {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, - {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, + {133, &Hid::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"}, {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"}, {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"}, {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"}, @@ -378,7 +382,7 @@ Hid::Hid(Core::System& system_) Hid::~Hid() = default; -void Hid::CreateAppletResource(Kernel::HLERequestContext& ctx) { +void Hid::CreateAppletResource(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -393,7 +397,7 @@ void Hid::CreateAppletResource(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IAppletResource>(applet_resource); } -void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { +void Hid::ActivateDebugPad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -405,7 +409,7 @@ void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { +void Hid::ActivateTouchScreen(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -417,7 +421,7 @@ void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { +void Hid::ActivateMouse(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -429,7 +433,7 @@ void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { +void Hid::ActivateKeyboard(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -441,7 +445,7 @@ void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { +void Hid::SendKeyboardLockKeyEvent(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto flags{rp.Pop<u32>()}; @@ -451,7 +455,7 @@ void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { +void Hid::ActivateXpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { u32 basic_xpad_id; @@ -471,7 +475,7 @@ void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { +void Hid::GetXpadIDs(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -482,7 +486,7 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { rb.Push(0); } -void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::ActivateSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { u32 basic_xpad_id; @@ -502,7 +506,7 @@ void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::DeactivateSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { u32 basic_xpad_id; @@ -522,7 +526,7 @@ void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StartSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -545,7 +549,7 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StopSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -568,7 +572,7 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::IsSixAxisSensorFusionEnabled(Kernel::HLERequestContext& ctx) { +void Hid::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -594,7 +598,7 @@ void Hid::IsSixAxisSensorFusionEnabled(Kernel::HLERequestContext& ctx) { rb.Push(is_enabled); } -void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { +void Hid::EnableSixAxisSensorFusion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool enable_sixaxis_sensor_fusion; @@ -621,7 +625,7 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { +void Hid::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -648,7 +652,7 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { +void Hid::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -675,7 +679,7 @@ void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { rb.PushRaw(fusion_parameters); } -void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { +void Hid::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -686,7 +690,7 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - // Since these parameters are unknow just use what HW outputs + // Since these parameters are unknown just use what HW outputs const Core::HID::SixAxisSensorFusionParameters fusion_parameters{ .parameter1 = 0.03f, .parameter2 = 0.4f, @@ -709,10 +713,10 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { rb.Push(result2); } -void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { +void Hid::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()}; - const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()}; + const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); @@ -728,7 +732,7 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { +void Hid::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -739,7 +743,7 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard}; + auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode); @@ -753,7 +757,7 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { rb.PushEnum(drift_mode); } -void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { +void Hid::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -764,7 +768,7 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - const auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard}; + const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode); @@ -777,7 +781,7 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { +void Hid::IsSixAxisSensorAtRest(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -802,7 +806,7 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { rb.Push(is_at_rest); } -void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -829,7 +833,7 @@ void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& c rb.Push(is_firmware_available); } -void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx) { +void Hid::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool enabled; @@ -855,7 +859,7 @@ void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx rb.Push(result); } -void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx) { +void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -882,7 +886,7 @@ void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& rb.Push(is_unaltered_sisxaxis_enabled); } -void Hid::LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx) { +void Hid::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -912,7 +916,7 @@ void Hid::LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx) rb.Push(result); } -void Hid::GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx) { +void Hid::GetSixAxisSensorIcInformation(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -942,7 +946,7 @@ void Hid::GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx) { +void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::SixAxisSensorHandle sixaxis_handle; @@ -967,7 +971,7 @@ void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx rb.Push(result); } -void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { +void Hid::ActivateGesture(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { u32 unknown; @@ -987,7 +991,7 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { +void Hid::SetSupportedNpadStyleSet(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadStyleSet supported_styleset; @@ -1008,7 +1012,7 @@ void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { +void Hid::GetSupportedNpadStyleSet(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1021,20 +1025,20 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { .raw); } -void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { +void Hid::SetSupportedNpadIdType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - applet_resource->GetController<Controller_NPad>(HidController::NPad) - .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); + const auto result = applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetSupportedNpadIdTypes(ctx.ReadBuffer()); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } -void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) { +void Hid::ActivateNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1046,7 +1050,7 @@ void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { +void Hid::DeactivateNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1058,7 +1062,7 @@ void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { +void Hid::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1083,7 +1087,7 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { .GetStyleSetChangedEvent(parameters.npad_id)); } -void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { +void Hid::DisconnectNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1104,7 +1108,7 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { +void Hid::GetPlayerLedPattern(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; @@ -1119,7 +1123,7 @@ void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { rb.Push(pattern.raw); } -void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { +void Hid::ActivateNpadWithRevision(HLERequestContext& ctx) { // Should have no effect with how our npad sets up the data IPC::RequestParser rp{ctx}; struct Parameters { @@ -1140,7 +1144,7 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadJoyHoldType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()}; @@ -1154,7 +1158,7 @@ void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { +void Hid::GetNpadJoyHoldType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1165,7 +1169,7 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad).GetHoldType()); } -void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1176,8 +1180,10 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx const auto parameters{rp.PopRaw<Parameters>()}; + Core::HID::NpadIdType new_npad_id{}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, + controller.SetNpadMode(new_npad_id, parameters.npad_id, + Controller_NPad::NpadJoyDeviceType::Left, Controller_NPad::NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, @@ -1187,7 +1193,7 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx rb.Push(ResultSuccess); } -void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1199,8 +1205,9 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; + Core::HID::NpadIdType new_npad_id{}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, + controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, Controller_NPad::NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", @@ -1211,7 +1218,7 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1222,8 +1229,10 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; + Core::HID::NpadIdType new_npad_id{}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); + controller.SetNpadMode(new_npad_id, parameters.npad_id, {}, + Controller_NPad::NpadJoyAssignmentMode::Dual); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); @@ -1232,7 +1241,7 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { +void Hid::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()}; const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; @@ -1248,7 +1257,7 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { +void Hid::StartLrAssignmentMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1260,7 +1269,7 @@ void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { +void Hid::StopLrAssignmentMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1272,7 +1281,7 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadHandheldActivationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()}; @@ -1287,7 +1296,7 @@ void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { +void Hid::GetNpadHandheldActivationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1299,7 +1308,7 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { .GetNpadHandheldActivationMode()); } -void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { +void Hid::SwapNpadAssignment(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()}; const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; @@ -1315,7 +1324,7 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { +void Hid::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1339,7 +1348,7 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext rb.Push(is_enabled); } -void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { +void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool unintended_home_button_input_protection; @@ -1365,7 +1374,35 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c rb.Push(result); } -void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Core::HID::NpadIdType npad_id; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + Controller_NPad::NpadJoyDeviceType npad_joy_device_type; + }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; + + Core::HID::NpadIdType new_npad_id{}; + auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); + const auto is_reassigned = + controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, + Controller_NPad::NpadJoyAssignmentMode::Single); + + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", + parameters.npad_id, parameters.applet_resource_user_id, + parameters.npad_joy_device_type); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(is_reassigned); + rb.PushEnum(new_npad_id); +} + +void Hid::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool analog_stick_use_center_clamp; @@ -1388,7 +1425,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadCaptureButtonAssignment(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadStyleSet npad_styleset; @@ -1408,7 +1445,7 @@ void Hid::SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) { +void Hid::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1419,7 +1456,7 @@ void Hid::ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { +void Hid::GetVibrationDeviceInfo(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; const auto& controller = @@ -1479,7 +1516,7 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { rb.PushRaw(vibration_device_info); } -void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { +void Hid::SendVibrationValue(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::VibrationDeviceHandle vibration_device_handle; @@ -1504,7 +1541,7 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { +void Hid::GetActualVibrationValue(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::VibrationDeviceHandle vibration_device_handle; @@ -1527,7 +1564,7 @@ void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { .GetLastVibration(parameters.vibration_device_handle)); } -void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { +void Hid::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -1535,7 +1572,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IActiveVibrationDeviceList>(system, applet_resource); } -void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { +void Hid::PermitVibration(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_vibrate{rp.Pop<bool>()}; @@ -1549,7 +1586,7 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { +void Hid::IsVibrationPermitted(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); // nnSDK checks if a float is greater than zero. We return the bool we stored earlier @@ -1560,20 +1597,20 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { rb.Push(is_enabled); } -void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { +void Hid::SendVibrationValues(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto handles = ctx.ReadBuffer(0); - const auto vibrations = ctx.ReadBuffer(1); + const auto handle_data = ctx.ReadBuffer(0); + const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0); + const auto vibration_data = ctx.ReadBuffer(1); + const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1); - std::vector<Core::HID::VibrationDeviceHandle> vibration_device_handles( - handles.size() / sizeof(Core::HID::VibrationDeviceHandle)); - std::vector<Core::HID::VibrationValue> vibration_values(vibrations.size() / - sizeof(Core::HID::VibrationValue)); - - std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); - std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); + auto vibration_device_handles = + std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()), + handle_count); + auto vibration_values = std::span( + reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); applet_resource->GetController<Controller_NPad>(HidController::NPad) .VibrateControllers(vibration_device_handles, vibration_values); @@ -1584,7 +1621,7 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { +void Hid::SendVibrationGcErmCommand(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::VibrationDeviceHandle vibration_device_handle; @@ -1645,7 +1682,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { +void Hid::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::VibrationDeviceHandle vibration_device_handle; @@ -1687,7 +1724,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { rb.PushEnum(gc_erm_command); } -void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { +void Hid::BeginPermitVibrationSession(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1700,7 +1737,7 @@ void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { +void Hid::EndPermitVibrationSession(HLERequestContext& ctx) { applet_resource->GetController<Controller_NPad>(HidController::NPad) .SetPermitVibrationSession(false); @@ -1710,7 +1747,7 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { +void Hid::IsVibrationDeviceMounted(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::VibrationDeviceHandle vibration_device_handle; @@ -1733,7 +1770,7 @@ void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { .IsVibrationDeviceMounted(parameters.vibration_device_handle)); } -void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1745,7 +1782,7 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StartConsoleSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle; @@ -1765,7 +1802,7 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StopConsoleSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle; @@ -1785,7 +1822,7 @@ void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::ActivateSevenSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1797,7 +1834,7 @@ void Hid::ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StartSevenSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1808,7 +1845,7 @@ void Hid::StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StopSevenSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1819,7 +1856,7 @@ void Hid::StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::InitializeSevenSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; const auto t_mem_1_size{rp.Pop<u64>()}; @@ -1830,7 +1867,7 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes"); ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes"); - auto t_mem_1 = system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( + auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( t_mem_1_handle); if (t_mem_1.IsNull()) { @@ -1840,7 +1877,7 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { return; } - auto t_mem_2 = system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( + auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( t_mem_2_handle); if (t_mem_2.IsNull()) { @@ -1858,7 +1895,7 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { .ActivateController(); applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) - .SetTransferMemoryPointer(system.Memory().GetPointer(t_mem_1->GetSourceAddress())); + .SetTransferMemoryAddress(t_mem_1->GetSourceAddress()); LOG_WARNING(Service_HID, "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, " @@ -1869,7 +1906,7 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::FinalizeSevenSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1880,7 +1917,7 @@ void Hid::FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx) { +void Hid::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -1893,7 +1930,7 @@ void Hid::ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::IsUsbFullKeyControllerEnabled(Kernel::HLERequestContext& ctx) { +void Hid::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; LOG_WARNING(Service_HID, "(STUBBED) called"); @@ -1903,7 +1940,7 @@ void Hid::IsUsbFullKeyControllerEnabled(Kernel::HLERequestContext& ctx) { rb.Push(false); } -void Hid::GetPalmaConnectionHandle(Kernel::HLERequestContext& ctx) { +void Hid::GetPalmaConnectionHandle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -1926,7 +1963,7 @@ void Hid::GetPalmaConnectionHandle(Kernel::HLERequestContext& ctx) { rb.PushRaw(handle); } -void Hid::InitializePalma(Kernel::HLERequestContext& ctx) { +void Hid::InitializePalma(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -1939,7 +1976,7 @@ void Hid::InitializePalma(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::AcquirePalmaOperationCompleteEvent(Kernel::HLERequestContext& ctx) { +void Hid::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -1952,7 +1989,7 @@ void Hid::AcquirePalmaOperationCompleteEvent(Kernel::HLERequestContext& ctx) { rb.PushCopyObjects(controller.AcquirePalmaOperationCompleteEvent(connection_handle)); } -void Hid::GetPalmaOperationInfo(Kernel::HLERequestContext& ctx) { +void Hid::GetPalmaOperationInfo(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -1974,7 +2011,7 @@ void Hid::GetPalmaOperationInfo(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u64>(operation_type)); } -void Hid::PlayPalmaActivity(Kernel::HLERequestContext& ctx) { +void Hid::PlayPalmaActivity(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; const auto palma_activity{rp.Pop<u64>()}; @@ -1989,7 +2026,7 @@ void Hid::PlayPalmaActivity(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::SetPalmaFrModeType(Kernel::HLERequestContext& ctx) { +void Hid::SetPalmaFrModeType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; const auto fr_mode{rp.PopEnum<Controller_Palma::PalmaFrModeType>()}; @@ -2004,7 +2041,7 @@ void Hid::SetPalmaFrModeType(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::ReadPalmaStep(Kernel::HLERequestContext& ctx) { +void Hid::ReadPalmaStep(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2017,7 +2054,7 @@ void Hid::ReadPalmaStep(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::EnablePalmaStep(Kernel::HLERequestContext& ctx) { +void Hid::EnablePalmaStep(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool is_enabled; @@ -2039,7 +2076,7 @@ void Hid::EnablePalmaStep(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::ResetPalmaStep(Kernel::HLERequestContext& ctx) { +void Hid::ResetPalmaStep(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2052,21 +2089,21 @@ void Hid::ResetPalmaStep(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::ReadPalmaApplicationSection(Kernel::HLERequestContext& ctx) { +void Hid::ReadPalmaApplicationSection(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::WritePalmaApplicationSection(Kernel::HLERequestContext& ctx) { +void Hid::WritePalmaApplicationSection(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::ReadPalmaUniqueCode(Kernel::HLERequestContext& ctx) { +void Hid::ReadPalmaUniqueCode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2079,7 +2116,7 @@ void Hid::ReadPalmaUniqueCode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetPalmaUniqueCodeInvalid(Kernel::HLERequestContext& ctx) { +void Hid::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2092,19 +2129,19 @@ void Hid::SetPalmaUniqueCodeInvalid(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::WritePalmaActivityEntry(Kernel::HLERequestContext& ctx) { +void Hid::WritePalmaActivityEntry(HLERequestContext& ctx) { LOG_CRITICAL(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::WritePalmaRgbLedPatternEntry(Kernel::HLERequestContext& ctx) { +void Hid::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; const auto unknown{rp.Pop<u64>()}; - const auto buffer = ctx.ReadBuffer(); + [[maybe_unused]] const auto buffer = ctx.ReadBuffer(); LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}", connection_handle.npad_id, unknown); @@ -2116,7 +2153,7 @@ void Hid::WritePalmaRgbLedPatternEntry(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::WritePalmaWaveEntry(Kernel::HLERequestContext& ctx) { +void Hid::WritePalmaWaveEntry(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; const auto wave_set{rp.PopEnum<Controller_Palma::PalmaWaveSet>()}; @@ -2127,8 +2164,8 @@ void Hid::WritePalmaWaveEntry(Kernel::HLERequestContext& ctx) { ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes"); - auto t_mem = - system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); + auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( + t_mem_handle); if (t_mem.IsNull()) { LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); @@ -2145,14 +2182,13 @@ void Hid::WritePalmaWaveEntry(Kernel::HLERequestContext& ctx) { connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size); applet_resource->GetController<Controller_Palma>(HidController::Palma) - .WritePalmaWaveEntry(connection_handle, wave_set, - system.Memory().GetPointer(t_mem->GetSourceAddress()), t_mem_size); + .WritePalmaWaveEntry(connection_handle, wave_set, t_mem->GetSourceAddress(), t_mem_size); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::SetPalmaDataBaseIdentificationVersion(Kernel::HLERequestContext& ctx) { +void Hid::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { s32 database_id_version; @@ -2174,7 +2210,7 @@ void Hid::SetPalmaDataBaseIdentificationVersion(Kernel::HLERequestContext& ctx) rb.Push(ResultSuccess); } -void Hid::GetPalmaDataBaseIdentificationVersion(Kernel::HLERequestContext& ctx) { +void Hid::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2187,14 +2223,14 @@ void Hid::GetPalmaDataBaseIdentificationVersion(Kernel::HLERequestContext& ctx) rb.Push(ResultSuccess); } -void Hid::SuspendPalmaFeature(Kernel::HLERequestContext& ctx) { +void Hid::SuspendPalmaFeature(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::GetPalmaOperationResult(Kernel::HLERequestContext& ctx) { +void Hid::GetPalmaOperationResult(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2207,21 +2243,21 @@ void Hid::GetPalmaOperationResult(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void Hid::ReadPalmaPlayLog(Kernel::HLERequestContext& ctx) { +void Hid::ReadPalmaPlayLog(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::ResetPalmaPlayLog(Kernel::HLERequestContext& ctx) { +void Hid::ResetPalmaPlayLog(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) { +void Hid::SetIsPalmaAllConnectable(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool is_palma_all_connectable; @@ -2243,14 +2279,14 @@ void Hid::SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetIsPalmaPairedConnectable(Kernel::HLERequestContext& ctx) { +void Hid::SetIsPalmaPairedConnectable(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::PairPalma(Kernel::HLERequestContext& ctx) { +void Hid::PairPalma(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; @@ -2263,7 +2299,7 @@ void Hid::PairPalma(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { +void Hid::SetPalmaBoostMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto palma_boost_mode{rp.Pop<bool>()}; @@ -2276,35 +2312,35 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::CancelWritePalmaWaveEntry(Kernel::HLERequestContext& ctx) { +void Hid::CancelWritePalmaWaveEntry(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::EnablePalmaBoostMode(Kernel::HLERequestContext& ctx) { +void Hid::EnablePalmaBoostMode(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::GetPalmaBluetoothAddress(Kernel::HLERequestContext& ctx) { +void Hid::GetPalmaBluetoothAddress(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::SetDisallowedPalmaConnection(Kernel::HLERequestContext& ctx) { +void Hid::SetDisallowedPalmaConnection(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { +void Hid::SetNpadCommunicationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()}; @@ -2319,7 +2355,7 @@ void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { +void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; LOG_WARNING(Service_HID, "(STUBBED) called"); @@ -2330,7 +2366,7 @@ void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { .GetNpadCommunicationMode()); } -void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) { +void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -2342,7 +2378,7 @@ void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Hid::IsFirmwareUpdateNeededForNotification(Kernel::HLERequestContext& ctx) { +void Hid::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { s32 unknown; @@ -2380,6 +2416,8 @@ public: {20, nullptr, "DeactivateMouse"}, {21, nullptr, "SetMouseAutoPilotState"}, {22, nullptr, "UnsetMouseAutoPilotState"}, + {25, nullptr, "SetDebugMouseAutoPilotState"}, + {26, nullptr, "UnsetDebugMouseAutoPilotState"}, {30, nullptr, "DeactivateKeyboard"}, {31, nullptr, "SetKeyboardAutoPilotState"}, {32, nullptr, "UnsetKeyboardAutoPilotState"}, @@ -2495,6 +2533,7 @@ public: {2000, nullptr, "DeactivateDigitizer"}, {2001, nullptr, "SetDigitizerAutoPilotState"}, {2002, nullptr, "UnsetDigitizerAutoPilotState"}, + {2002, nullptr, "ReloadFirmwareDebugSettings"}, }; // clang-format on @@ -2713,7 +2752,7 @@ public: } private: - void ApplyNpadSystemCommonPolicy(Kernel::HLERequestContext& ctx) { + void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) { // We already do this for homebrew so we can just stub it out LOG_WARNING(Service_HID, "called"); @@ -2721,7 +2760,7 @@ private: rb.Push(ResultSuccess); } - void GetUniquePadsFromNpad(Kernel::HLERequestContext& ctx) { + void GetUniquePadsFromNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()}; @@ -2734,30 +2773,20 @@ private: } }; -class HidTmp final : public ServiceFramework<HidTmp> { -public: - explicit HidTmp(Core::System& system_) : ServiceFramework{system_, "hid:tmp"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<Hid>(system)->InstallAsService(service_manager); - std::make_shared<HidBus>(system)->InstallAsService(service_manager); - std::make_shared<HidDbg>(system)->InstallAsService(service_manager); - std::make_shared<HidSys>(system)->InstallAsService(service_manager); - std::make_shared<HidTmp>(system)->InstallAsService(service_manager); + server_manager->RegisterNamedService("hid", std::make_shared<Hid>(system)); + server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system)); + server_manager->RegisterNamedService("hid:dbg", std::make_shared<HidDbg>(system)); + server_manager->RegisterNamedService("hid:sys", std::make_shared<HidSys>(system)); - std::make_shared<Service::IRS::IRS>(system)->InstallAsService(service_manager); - std::make_shared<Service::IRS::IRS_SYS>(system)->InstallAsService(service_manager); + server_manager->RegisterNamedService("irs", std::make_shared<Service::IRS::IRS>(system)); + server_manager->RegisterNamedService("irs:sys", + std::make_shared<Service::IRS::IRS_SYS>(system)); - std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager); + server_manager->RegisterNamedService("xcd:sys", std::make_shared<XCD_SYS>(system)); + system.RunServer(std::move(server_manager)); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index b7c2a23ef..f247b83c2 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -33,6 +33,7 @@ enum class HidController : std::size_t { NPad, Gesture, ConsoleSixAxisSensor, + DebugMouse, Palma, MaxControllers, @@ -60,16 +61,22 @@ public: private: template <typename T> void MakeController(HidController controller, u8* shared_memory) { - controllers[static_cast<std::size_t>(controller)] = - std::make_unique<T>(system.HIDCore(), shared_memory); + if constexpr (std::is_constructible_v<T, Core::System&, u8*>) { + controllers[static_cast<std::size_t>(controller)] = + std::make_unique<T>(system, shared_memory); + } else { + controllers[static_cast<std::size_t>(controller)] = + std::make_unique<T>(system.HIDCore(), shared_memory); + } } + template <typename T> void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) { controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system.HIDCore(), shared_memory, service_context); } - void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); + void GetSharedMemoryHandle(HLERequestContext& ctx); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); @@ -94,122 +101,122 @@ public: std::shared_ptr<IAppletResource> GetAppletResource(); private: - void CreateAppletResource(Kernel::HLERequestContext& ctx); - void ActivateDebugPad(Kernel::HLERequestContext& ctx); - void ActivateTouchScreen(Kernel::HLERequestContext& ctx); - void ActivateMouse(Kernel::HLERequestContext& ctx); - void ActivateKeyboard(Kernel::HLERequestContext& ctx); - void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); - void ActivateXpad(Kernel::HLERequestContext& ctx); - void GetXpadIDs(Kernel::HLERequestContext& ctx); - void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); - void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); - void StartSixAxisSensor(Kernel::HLERequestContext& ctx); - void StopSixAxisSensor(Kernel::HLERequestContext& ctx); - void IsSixAxisSensorFusionEnabled(Kernel::HLERequestContext& ctx); - void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); - void SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx); - void GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx); - void ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx); - void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); - void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); - void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); - void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); - void IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx); - void EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx); - void IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx); - void LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx); - void GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx); - void ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx); - void ActivateGesture(Kernel::HLERequestContext& ctx); - void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); - void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); - void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); - void ActivateNpad(Kernel::HLERequestContext& ctx); - void DeactivateNpad(Kernel::HLERequestContext& ctx); - void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); - void DisconnectNpad(Kernel::HLERequestContext& ctx); - void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); - void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); - void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); - void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); - void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); - void SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx); - void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx); - void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx); - void StartLrAssignmentMode(Kernel::HLERequestContext& ctx); - void StopLrAssignmentMode(Kernel::HLERequestContext& ctx); - void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); - void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); - void SwapNpadAssignment(Kernel::HLERequestContext& ctx); - void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); - void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); - void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx); - void SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx); - void ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx); - void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); - void SendVibrationValue(Kernel::HLERequestContext& ctx); - void GetActualVibrationValue(Kernel::HLERequestContext& ctx); - void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); - void PermitVibration(Kernel::HLERequestContext& ctx); - void IsVibrationPermitted(Kernel::HLERequestContext& ctx); - void SendVibrationValues(Kernel::HLERequestContext& ctx); - void SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx); - void GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx); - void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); - void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); - void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx); - void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); - void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); - void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); - void ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx); - void StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx); - void StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx); - void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); - void FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); - void ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx); - void IsUsbFullKeyControllerEnabled(Kernel::HLERequestContext& ctx); - void GetPalmaConnectionHandle(Kernel::HLERequestContext& ctx); - void InitializePalma(Kernel::HLERequestContext& ctx); - void AcquirePalmaOperationCompleteEvent(Kernel::HLERequestContext& ctx); - void GetPalmaOperationInfo(Kernel::HLERequestContext& ctx); - void PlayPalmaActivity(Kernel::HLERequestContext& ctx); - void SetPalmaFrModeType(Kernel::HLERequestContext& ctx); - void ReadPalmaStep(Kernel::HLERequestContext& ctx); - void EnablePalmaStep(Kernel::HLERequestContext& ctx); - void ResetPalmaStep(Kernel::HLERequestContext& ctx); - void ReadPalmaApplicationSection(Kernel::HLERequestContext& ctx); - void WritePalmaApplicationSection(Kernel::HLERequestContext& ctx); - void ReadPalmaUniqueCode(Kernel::HLERequestContext& ctx); - void SetPalmaUniqueCodeInvalid(Kernel::HLERequestContext& ctx); - void WritePalmaActivityEntry(Kernel::HLERequestContext& ctx); - void WritePalmaRgbLedPatternEntry(Kernel::HLERequestContext& ctx); - void WritePalmaWaveEntry(Kernel::HLERequestContext& ctx); - void SetPalmaDataBaseIdentificationVersion(Kernel::HLERequestContext& ctx); - void GetPalmaDataBaseIdentificationVersion(Kernel::HLERequestContext& ctx); - void SuspendPalmaFeature(Kernel::HLERequestContext& ctx); - void GetPalmaOperationResult(Kernel::HLERequestContext& ctx); - void ReadPalmaPlayLog(Kernel::HLERequestContext& ctx); - void ResetPalmaPlayLog(Kernel::HLERequestContext& ctx); - void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); - void SetIsPalmaPairedConnectable(Kernel::HLERequestContext& ctx); - void PairPalma(Kernel::HLERequestContext& ctx); - void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); - void CancelWritePalmaWaveEntry(Kernel::HLERequestContext& ctx); - void EnablePalmaBoostMode(Kernel::HLERequestContext& ctx); - void GetPalmaBluetoothAddress(Kernel::HLERequestContext& ctx); - void SetDisallowedPalmaConnection(Kernel::HLERequestContext& ctx); - void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx); - void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); - void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx); - void IsFirmwareUpdateNeededForNotification(Kernel::HLERequestContext& ctx); + void CreateAppletResource(HLERequestContext& ctx); + void ActivateDebugPad(HLERequestContext& ctx); + void ActivateTouchScreen(HLERequestContext& ctx); + void ActivateMouse(HLERequestContext& ctx); + void ActivateKeyboard(HLERequestContext& ctx); + void SendKeyboardLockKeyEvent(HLERequestContext& ctx); + void ActivateXpad(HLERequestContext& ctx); + void GetXpadIDs(HLERequestContext& ctx); + void ActivateSixAxisSensor(HLERequestContext& ctx); + void DeactivateSixAxisSensor(HLERequestContext& ctx); + void StartSixAxisSensor(HLERequestContext& ctx); + void StopSixAxisSensor(HLERequestContext& ctx); + void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx); + void EnableSixAxisSensorFusion(HLERequestContext& ctx); + void SetSixAxisSensorFusionParameters(HLERequestContext& ctx); + void GetSixAxisSensorFusionParameters(HLERequestContext& ctx); + void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx); + void SetGyroscopeZeroDriftMode(HLERequestContext& ctx); + void GetGyroscopeZeroDriftMode(HLERequestContext& ctx); + void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx); + void IsSixAxisSensorAtRest(HLERequestContext& ctx); + void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx); + void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx); + void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx); + void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx); + void GetSixAxisSensorIcInformation(HLERequestContext& ctx); + void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx); + void ActivateGesture(HLERequestContext& ctx); + void SetSupportedNpadStyleSet(HLERequestContext& ctx); + void GetSupportedNpadStyleSet(HLERequestContext& ctx); + void SetSupportedNpadIdType(HLERequestContext& ctx); + void ActivateNpad(HLERequestContext& ctx); + void DeactivateNpad(HLERequestContext& ctx); + void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx); + void DisconnectNpad(HLERequestContext& ctx); + void GetPlayerLedPattern(HLERequestContext& ctx); + void ActivateNpadWithRevision(HLERequestContext& ctx); + void SetNpadJoyHoldType(HLERequestContext& ctx); + void GetNpadJoyHoldType(HLERequestContext& ctx); + void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx); + void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx); + void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx); + void MergeSingleJoyAsDualJoy(HLERequestContext& ctx); + void StartLrAssignmentMode(HLERequestContext& ctx); + void StopLrAssignmentMode(HLERequestContext& ctx); + void SetNpadHandheldActivationMode(HLERequestContext& ctx); + void GetNpadHandheldActivationMode(HLERequestContext& ctx); + void SwapNpadAssignment(HLERequestContext& ctx); + void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx); + void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx); + void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx); + void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx); + void SetNpadCaptureButtonAssignment(HLERequestContext& ctx); + void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx); + void GetVibrationDeviceInfo(HLERequestContext& ctx); + void SendVibrationValue(HLERequestContext& ctx); + void GetActualVibrationValue(HLERequestContext& ctx); + void CreateActiveVibrationDeviceList(HLERequestContext& ctx); + void PermitVibration(HLERequestContext& ctx); + void IsVibrationPermitted(HLERequestContext& ctx); + void SendVibrationValues(HLERequestContext& ctx); + void SendVibrationGcErmCommand(HLERequestContext& ctx); + void GetActualVibrationGcErmCommand(HLERequestContext& ctx); + void BeginPermitVibrationSession(HLERequestContext& ctx); + void EndPermitVibrationSession(HLERequestContext& ctx); + void IsVibrationDeviceMounted(HLERequestContext& ctx); + void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); + void StartConsoleSixAxisSensor(HLERequestContext& ctx); + void StopConsoleSixAxisSensor(HLERequestContext& ctx); + void ActivateSevenSixAxisSensor(HLERequestContext& ctx); + void StartSevenSixAxisSensor(HLERequestContext& ctx); + void StopSevenSixAxisSensor(HLERequestContext& ctx); + void InitializeSevenSixAxisSensor(HLERequestContext& ctx); + void FinalizeSevenSixAxisSensor(HLERequestContext& ctx); + void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx); + void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx); + void GetPalmaConnectionHandle(HLERequestContext& ctx); + void InitializePalma(HLERequestContext& ctx); + void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx); + void GetPalmaOperationInfo(HLERequestContext& ctx); + void PlayPalmaActivity(HLERequestContext& ctx); + void SetPalmaFrModeType(HLERequestContext& ctx); + void ReadPalmaStep(HLERequestContext& ctx); + void EnablePalmaStep(HLERequestContext& ctx); + void ResetPalmaStep(HLERequestContext& ctx); + void ReadPalmaApplicationSection(HLERequestContext& ctx); + void WritePalmaApplicationSection(HLERequestContext& ctx); + void ReadPalmaUniqueCode(HLERequestContext& ctx); + void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx); + void WritePalmaActivityEntry(HLERequestContext& ctx); + void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx); + void WritePalmaWaveEntry(HLERequestContext& ctx); + void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx); + void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx); + void SuspendPalmaFeature(HLERequestContext& ctx); + void GetPalmaOperationResult(HLERequestContext& ctx); + void ReadPalmaPlayLog(HLERequestContext& ctx); + void ResetPalmaPlayLog(HLERequestContext& ctx); + void SetIsPalmaAllConnectable(HLERequestContext& ctx); + void SetIsPalmaPairedConnectable(HLERequestContext& ctx); + void PairPalma(HLERequestContext& ctx); + void SetPalmaBoostMode(HLERequestContext& ctx); + void CancelWritePalmaWaveEntry(HLERequestContext& ctx); + void EnablePalmaBoostMode(HLERequestContext& ctx); + void GetPalmaBluetoothAddress(HLERequestContext& ctx); + void SetDisallowedPalmaConnection(HLERequestContext& ctx); + void SetNpadCommunicationMode(HLERequestContext& ctx); + void GetNpadCommunicationMode(HLERequestContext& ctx); + void SetTouchScreenConfiguration(HLERequestContext& ctx); + void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx); std::shared_ptr<IAppletResource> applet_resource; KernelHelpers::ServiceContext service_context; }; -/// Registers all HID services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::HID diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index e5e50845f..80aac221b 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp @@ -5,9 +5,7 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/core_timing_util.h" #include "core/hid/hid_types.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" @@ -16,6 +14,7 @@ #include "core/hle/service/hid/hidbus/ringcon.h" #include "core/hle/service/hid/hidbus/starlink.h" #include "core/hle/service/hid/hidbus/stubbed.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/service.h" #include "core/memory.h" @@ -91,7 +90,7 @@ std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) co if (handle.abstracted_pad_id == device_handle.abstracted_pad_id && handle.internal_index == device_handle.internal_index && handle.player_number == device_handle.player_number && - handle.bus_type == device_handle.bus_type && + handle.bus_type_id == device_handle.bus_type_id && handle.is_valid == device_handle.is_valid) { return i; } @@ -99,7 +98,7 @@ std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) co return std::nullopt; } -void HidBus::GetBusHandle(Kernel::HLERequestContext& ctx) { +void HidBus::GetBusHandle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; @@ -123,7 +122,7 @@ void HidBus::GetBusHandle(Kernel::HLERequestContext& ctx) { continue; } if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id && - handle.bus_type == parameters.bus_type) { + handle.bus_type_id == static_cast<u8>(parameters.bus_type)) { is_handle_found = true; handle_index = i; break; @@ -140,7 +139,7 @@ void HidBus::GetBusHandle(Kernel::HLERequestContext& ctx) { .abstracted_pad_id = static_cast<u8>(i), .internal_index = static_cast<u8>(i), .player_number = static_cast<u8>(parameters.npad_id), - .bus_type = parameters.bus_type, + .bus_type_id = static_cast<u8>(parameters.bus_type), .is_valid = true, }; handle_index = i; @@ -165,14 +164,14 @@ void HidBus::GetBusHandle(Kernel::HLERequestContext& ctx) { rb.PushRaw(out_data); } -void HidBus::IsExternalDeviceConnected(Kernel::HLERequestContext& ctx) { +void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; LOG_INFO(Service_HID, "Called, abstracted_pad_id={}, bus_type={}, internal_index={}, " "player_number={}, is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -193,7 +192,7 @@ void HidBus::IsExternalDeviceConnected(Kernel::HLERequestContext& ctx) { return; } -void HidBus::Initialize(Kernel::HLERequestContext& ctx) { +void HidBus::Initialize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -201,7 +200,7 @@ void HidBus::Initialize(Kernel::HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, abstracted_pad_id={} bus_type={} internal_index={} " "player_number={} is_valid={}, applet_resource_user_id={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id); is_hidbus_enabled = true; @@ -245,7 +244,7 @@ void HidBus::Initialize(Kernel::HLERequestContext& ctx) { return; } -void HidBus::Finalize(Kernel::HLERequestContext& ctx) { +void HidBus::Finalize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -253,7 +252,7 @@ void HidBus::Finalize(Kernel::HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, " "player_number={}, is_valid={}, applet_resource_user_id={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -284,7 +283,7 @@ void HidBus::Finalize(Kernel::HLERequestContext& ctx) { return; } -void HidBus::EnableExternalDevice(Kernel::HLERequestContext& ctx) { +void HidBus::EnableExternalDevice(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool enable; @@ -297,13 +296,13 @@ void HidBus::EnableExternalDevice(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - LOG_INFO(Service_HID, - "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " - "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", - parameters.enable, parameters.bus_handle.abstracted_pad_id, - parameters.bus_handle.bus_type, parameters.bus_handle.internal_index, - parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval, - parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " + "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", + parameters.enable, parameters.bus_handle.abstracted_pad_id, + parameters.bus_handle.bus_type_id, parameters.bus_handle.internal_index, + parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval, + parameters.applet_resource_user_id); const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle); @@ -322,15 +321,15 @@ void HidBus::EnableExternalDevice(Kernel::HLERequestContext& ctx) { return; } -void HidBus::GetExternalDeviceId(Kernel::HLERequestContext& ctx) { +void HidBus::GetExternalDeviceId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; - LOG_INFO(Service_HID, - "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " - "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); + LOG_DEBUG(Service_HID, + "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " + "is_valid={}", + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, + bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -349,7 +348,7 @@ void HidBus::GetExternalDeviceId(Kernel::HLERequestContext& ctx) { return; } -void HidBus::SendCommandAsync(Kernel::HLERequestContext& ctx) { +void HidBus::SendCommandAsync(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto data = ctx.ReadBuffer(); const auto bus_handle_{rp.PopRaw<BusHandle>()}; @@ -357,7 +356,7 @@ void HidBus::SendCommandAsync(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " "player_number={}, is_valid={}", - data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type, + data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -377,14 +376,14 @@ void HidBus::SendCommandAsync(Kernel::HLERequestContext& ctx) { return; }; -void HidBus::GetSendCommandAsynceResult(Kernel::HLERequestContext& ctx) { +void HidBus::GetSendCommandAsynceResult(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; LOG_DEBUG(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -406,14 +405,14 @@ void HidBus::GetSendCommandAsynceResult(Kernel::HLERequestContext& ctx) { return; }; -void HidBus::SetEventForSendCommandAsycResult(Kernel::HLERequestContext& ctx) { +void HidBus::SetEventForSendCommandAsycResult(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; LOG_INFO(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -432,7 +431,7 @@ void HidBus::SetEventForSendCommandAsycResult(Kernel::HLERequestContext& ctx) { return; }; -void HidBus::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { +void HidBus::GetSharedMemoryHandle(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -440,7 +439,7 @@ void HidBus::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { rb.PushCopyObjects(&system.Kernel().GetHidBusSharedMem()); } -void HidBus::EnableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { +void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto t_mem_size{rp.Pop<u32>()}; const auto t_mem_handle{ctx.GetCopyHandle(0)}; @@ -449,8 +448,8 @@ void HidBus::EnableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes"); - auto t_mem = - system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); + auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( + t_mem_handle); if (t_mem.IsNull()) { LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); @@ -464,7 +463,7 @@ void HidBus::EnableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, t_mem_handle=0x{:08X}, polling_mode={}, abstracted_pad_id={}, bus_type={}, " "internal_index={}, player_number={}, is_valid={}", - t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type, + t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -472,7 +471,7 @@ void HidBus::EnableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { if (device_index) { auto& device = devices[device_index.value()].device; device->SetPollingMode(polling_mode_); - device->SetTransferMemoryPointer(system.Memory().GetPointer(t_mem->GetSourceAddress())); + device->SetTransferMemoryAddress(t_mem->GetSourceAddress()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -485,14 +484,14 @@ void HidBus::EnableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { return; } -void HidBus::DisableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { +void HidBus::DisableJoyPollingReceiveMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw<BusHandle>()}; LOG_INFO(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); @@ -512,7 +511,7 @@ void HidBus::DisableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx) { return; } -void HidBus::SetStatusManagerType(Kernel::HLERequestContext& ctx) { +void HidBus::SetStatusManagerType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto manager_type{rp.PopEnum<StatusManagerType>()}; diff --git a/src/core/hle/service/hid/hidbus.h b/src/core/hle/service/hid/hidbus.h index 8c687f678..c29b5e882 100644 --- a/src/core/hle/service/hid/hidbus.h +++ b/src/core/hle/service/hid/hidbus.h @@ -41,7 +41,7 @@ private: }; // This is nn::hidbus::BusType - enum class BusType : u8 { + enum class BusType : u32 { LeftJoyRail, RightJoyRail, InternalBus, // Lark microphone @@ -54,7 +54,7 @@ private: u32 abstracted_pad_id; u8 internal_index; u8 player_number; - BusType bus_type; + u8 bus_type_id; bool is_valid; }; static_assert(sizeof(BusHandle) == 0x8, "BusHandle is an invalid size"); @@ -94,19 +94,19 @@ private: std::unique_ptr<HidbusBase> device{nullptr}; }; - void GetBusHandle(Kernel::HLERequestContext& ctx); - void IsExternalDeviceConnected(Kernel::HLERequestContext& ctx); - void Initialize(Kernel::HLERequestContext& ctx); - void Finalize(Kernel::HLERequestContext& ctx); - void EnableExternalDevice(Kernel::HLERequestContext& ctx); - void GetExternalDeviceId(Kernel::HLERequestContext& ctx); - void SendCommandAsync(Kernel::HLERequestContext& ctx); - void GetSendCommandAsynceResult(Kernel::HLERequestContext& ctx); - void SetEventForSendCommandAsycResult(Kernel::HLERequestContext& ctx); - void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); - void EnableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx); - void DisableJoyPollingReceiveMode(Kernel::HLERequestContext& ctx); - void SetStatusManagerType(Kernel::HLERequestContext& ctx); + void GetBusHandle(HLERequestContext& ctx); + void IsExternalDeviceConnected(HLERequestContext& ctx); + void Initialize(HLERequestContext& ctx); + void Finalize(HLERequestContext& ctx); + void EnableExternalDevice(HLERequestContext& ctx); + void GetExternalDeviceId(HLERequestContext& ctx); + void SendCommandAsync(HLERequestContext& ctx); + void GetSendCommandAsynceResult(HLERequestContext& ctx); + void SetEventForSendCommandAsycResult(HLERequestContext& ctx); + void GetSharedMemoryHandle(HLERequestContext& ctx); + void EnableJoyPollingReceiveMode(HLERequestContext& ctx); + void DisableJoyPollingReceiveMode(HLERequestContext& ctx); + void SetStatusManagerType(HLERequestContext& ctx); void UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const; @@ -115,8 +115,7 @@ private: void MakeDevice(BusHandle handle) { const auto device_index = GetDeviceIndexFromHandle(handle); if (device_index) { - devices[device_index.value()].device = - std::make_unique<T>(system.HIDCore(), service_context); + devices[device_index.value()].device = std::make_unique<T>(system, service_context); } } diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp index b569b3c20..ee522c36e 100644 --- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp +++ b/src/core/hle/service/hid/hidbus/hidbus_base.cpp @@ -9,8 +9,8 @@ namespace Service::HID { -HidbusBase::HidbusBase(KernelHelpers::ServiceContext& service_context_) - : service_context(service_context_) { +HidbusBase::HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_) + : system(system_), service_context(service_context_) { send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent"); } HidbusBase::~HidbusBase() = default; @@ -59,8 +59,7 @@ void HidbusBase::DisablePollingMode() { polling_mode_enabled = false; } -void HidbusBase::SetTransferMemoryPointer(u8* t_mem) { - is_transfer_memory_set = true; +void HidbusBase::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { transfer_memory = t_mem; } diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h index d3960f506..ec41684e1 100644 --- a/src/core/hle/service/hid/hidbus/hidbus_base.h +++ b/src/core/hle/service/hid/hidbus/hidbus_base.h @@ -4,9 +4,14 @@ #pragma once #include <array> -#include "common/common_types.h" +#include <span> +#include "common/typed_address.h" #include "core/hle/result.h" +namespace Core { +class System; +} + namespace Kernel { class KEvent; class KReadableEvent; @@ -105,7 +110,7 @@ static_assert(sizeof(ButtonOnlyPollingDataAccessor) == 0x2F0, class HidbusBase { public: - explicit HidbusBase(KernelHelpers::ServiceContext& service_context_); + explicit HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_); virtual ~HidbusBase(); void ActivateDevice(); @@ -133,7 +138,7 @@ public: void DisablePollingMode(); // Called on EnableJoyPollingReceiveMode - void SetTransferMemoryPointer(u8* t_mem); + void SetTransferMemoryAddress(Common::ProcessAddress t_mem); Kernel::KReadableEvent& GetSendCommandAsycEvent() const; @@ -150,7 +155,7 @@ public: } // Assigns a command from data - virtual bool SetCommand(const std::vector<u8>& data) { + virtual bool SetCommand(std::span<const u8> data) { return {}; } @@ -169,9 +174,9 @@ protected: JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; ButtonOnlyPollingDataAccessor button_only_data{}; - u8* transfer_memory{nullptr}; - bool is_transfer_memory_set{}; + Common::ProcessAddress transfer_memory{}; + Core::System& system; Kernel::KEvent* send_command_async_event; KernelHelpers::ServiceContext& service_context; }; diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index 57f1a2a26..378108012 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -1,27 +1,33 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hid/emulated_devices.h" +#include "core/core.h" +#include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/hid/hidbus/ringcon.h" +#include "core/memory.h" namespace Service::HID { -RingController::RingController(Core::HID::HIDCore& hid_core_, +RingController::RingController(Core::System& system_, KernelHelpers::ServiceContext& service_context_) - : HidbusBase(service_context_) { - input = hid_core_.GetEmulatedDevices(); + : HidbusBase(system_, service_context_) { + input = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); } RingController::~RingController() = default; void RingController::OnInit() { + input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Ring); return; } void RingController::OnRelease() { + input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); return; }; @@ -34,7 +40,7 @@ void RingController::OnUpdate() { return; } - if (!polling_mode_enabled || !is_transfer_memory_set) { + if (!polling_mode_enabled || transfer_memory == 0) { return; } @@ -58,7 +64,8 @@ void RingController::OnUpdate() { curr_entry.polling_data.out_size = sizeof(ringcon_value); std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value)); - std::memcpy(transfer_memory, &enable_sixaxis_data, sizeof(enable_sixaxis_data)); + system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data, + sizeof(enable_sixaxis_data)); break; } default: @@ -112,7 +119,7 @@ std::vector<u8> RingController::GetReply() const { } } -bool RingController::SetCommand(const std::vector<u8>& data) { +bool RingController::SetCommand(std::span<const u8> data) { if (data.size() < 4) { LOG_ERROR(Service_HID, "Command size not supported {}", data.size()); command = RingConCommands::Error; diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h index b37df50ac..f42f3ea41 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.h +++ b/src/core/hle/service/hid/hidbus/ringcon.h @@ -4,20 +4,20 @@ #pragma once #include <array> +#include <span> #include "common/common_types.h" #include "core/hle/service/hid/hidbus/hidbus_base.h" namespace Core::HID { -class EmulatedDevices; +class EmulatedController; } // namespace Core::HID namespace Service::HID { class RingController final : public HidbusBase { public: - explicit RingController(Core::HID::HIDCore& hid_core_, - KernelHelpers::ServiceContext& service_context_); + explicit RingController(Core::System& system_, KernelHelpers::ServiceContext& service_context_); ~RingController() override; void OnInit() override; @@ -31,7 +31,7 @@ public: u8 GetDeviceId() const override; // Assigns a command from data - bool SetCommand(const std::vector<u8>& data) override; + bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command std::vector<u8> GetReply() const override; @@ -248,6 +248,6 @@ private: .zero = {.value = idle_value, .crc = 225}, }; - Core::HID::EmulatedDevices* input; + Core::HID::EmulatedController* input; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hidbus/starlink.cpp b/src/core/hle/service/hid/hidbus/starlink.cpp index dd439f60a..36573274e 100644 --- a/src/core/hle/service/hid/hidbus/starlink.cpp +++ b/src/core/hle/service/hid/hidbus/starlink.cpp @@ -8,8 +8,8 @@ namespace Service::HID { constexpr u8 DEVICE_ID = 0x28; -Starlink::Starlink(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) - : HidbusBase(service_context_) {} +Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_) + : HidbusBase(system_, service_context_) {} Starlink::~Starlink() = default; void Starlink::OnInit() { @@ -27,7 +27,7 @@ void Starlink::OnUpdate() { if (!device_enabled) { return; } - if (!polling_mode_enabled || !is_transfer_memory_set) { + if (!polling_mode_enabled || transfer_memory == 0) { return; } @@ -42,7 +42,7 @@ std::vector<u8> Starlink::GetReply() const { return {}; } -bool Starlink::SetCommand(const std::vector<u8>& data) { +bool Starlink::SetCommand(std::span<const u8> data) { LOG_ERROR(Service_HID, "Command not implemented"); return false; } diff --git a/src/core/hle/service/hid/hidbus/starlink.h b/src/core/hle/service/hid/hidbus/starlink.h index 0b1b7ba49..a276aa88f 100644 --- a/src/core/hle/service/hid/hidbus/starlink.h +++ b/src/core/hle/service/hid/hidbus/starlink.h @@ -14,8 +14,7 @@ namespace Service::HID { class Starlink final : public HidbusBase { public: - explicit Starlink(Core::HID::HIDCore& hid_core_, - KernelHelpers::ServiceContext& service_context_); + explicit Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_); ~Starlink() override; void OnInit() override; @@ -29,7 +28,7 @@ public: u8 GetDeviceId() const override; // Assigns a command from data - bool SetCommand(const std::vector<u8>& data) override; + bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command std::vector<u8> GetReply() const override; diff --git a/src/core/hle/service/hid/hidbus/stubbed.cpp b/src/core/hle/service/hid/hidbus/stubbed.cpp index e477443e3..8160b7218 100644 --- a/src/core/hle/service/hid/hidbus/stubbed.cpp +++ b/src/core/hle/service/hid/hidbus/stubbed.cpp @@ -8,9 +8,8 @@ namespace Service::HID { constexpr u8 DEVICE_ID = 0xFF; -HidbusStubbed::HidbusStubbed(Core::HID::HIDCore& hid_core_, - KernelHelpers::ServiceContext& service_context_) - : HidbusBase(service_context_) {} +HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_) + : HidbusBase(system_, service_context_) {} HidbusStubbed::~HidbusStubbed() = default; void HidbusStubbed::OnInit() { @@ -28,7 +27,7 @@ void HidbusStubbed::OnUpdate() { if (!device_enabled) { return; } - if (!polling_mode_enabled || !is_transfer_memory_set) { + if (!polling_mode_enabled || transfer_memory == 0) { return; } @@ -43,7 +42,7 @@ std::vector<u8> HidbusStubbed::GetReply() const { return {}; } -bool HidbusStubbed::SetCommand(const std::vector<u8>& data) { +bool HidbusStubbed::SetCommand(std::span<const u8> data) { LOG_ERROR(Service_HID, "Command not implemented"); return false; } diff --git a/src/core/hle/service/hid/hidbus/stubbed.h b/src/core/hle/service/hid/hidbus/stubbed.h index 91165ceff..2e58d42fc 100644 --- a/src/core/hle/service/hid/hidbus/stubbed.h +++ b/src/core/hle/service/hid/hidbus/stubbed.h @@ -14,8 +14,7 @@ namespace Service::HID { class HidbusStubbed final : public HidbusBase { public: - explicit HidbusStubbed(Core::HID::HIDCore& hid_core_, - KernelHelpers::ServiceContext& service_context_); + explicit HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_); ~HidbusStubbed() override; void OnInit() override; @@ -29,7 +28,7 @@ public: u8 GetDeviceId() const override; // Assigns a command from data - bool SetCommand(const std::vector<u8>& data) override; + bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command std::vector<u8> GetReply() const override; diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 6a3453457..221c33b86 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -8,7 +8,6 @@ #include "core/core_timing.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/kernel.h" @@ -20,6 +19,7 @@ #include "core/hle/service/hid/irsensor/moment_processor.h" #include "core/hle/service/hid/irsensor/pointing_processor.h" #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" +#include "core/hle/service/ipc_helpers.h" #include "core/memory.h" namespace Service::IRS { @@ -56,7 +56,7 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { } IRS::~IRS() = default; -void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { +void IRS::ActivateIrsensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -67,7 +67,7 @@ void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) { +void IRS::DeactivateIrsensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -78,7 +78,7 @@ void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) { +void IRS::GetIrsensorSharedMemoryHandle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; @@ -89,7 +89,7 @@ void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) { rb.PushCopyObjects(&system.Kernel().GetIrsSharedMem()); } -void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { +void IRS::StopImageProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -108,6 +108,8 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop Image processor + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); result = ResultSuccess; } @@ -115,7 +117,7 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunMomentProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -139,13 +141,15 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor<MomentProcessor>(parameters.camera_handle, device); auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunClusteringProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -170,13 +174,15 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor<ClusteringProcessor>(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunImageTransferProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -190,8 +196,8 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; const auto t_mem_handle{ctx.GetCopyHandle(0)}; - auto t_mem = - system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); + auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( + t_mem_handle); if (t_mem.IsNull()) { LOG_ERROR(Service_IRS, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); @@ -202,8 +208,6 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { ASSERT_MSG(t_mem->GetSize() == parameters.transfer_memory_size, "t_mem has incorrect size"); - u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress()); - LOG_INFO(Service_IRS, "called, npad_type={}, npad_id={}, transfer_memory_size={}, transfer_memory_size={}, " "applet_resource_user_id={}", @@ -218,14 +222,16 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); - image_transfer_processor.SetTransferMemoryPointer(transfer_memory); + image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress()); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { +void IRS::GetImageTransferProcessorState(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -266,7 +272,7 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { rb.PushRaw(state); } -void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunTeraPluginProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -294,13 +300,15 @@ void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor<TeraPluginProcessor>(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { +void IRS::GetNpadIrCameraHandle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; @@ -324,7 +332,7 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { rb.PushRaw(camera_handle); } -void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunPointingProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; const auto processor_config{rp.PopRaw<Core::IrSensor::PackedPointingProcessorConfig>()}; @@ -343,13 +351,15 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor<PointingProcessor>(camera_handle, device); auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle); image_transfer_processor.SetConfig(processor_config); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { +void IRS::SuspendImageProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -375,7 +385,7 @@ void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { +void IRS::CheckFirmwareVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; const auto mcu_version{rp.PopRaw<Core::IrSensor::PackedMcuVersion>()}; @@ -397,7 +407,7 @@ void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { +void IRS::SetFunctionLevel(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; const auto function_level{rp.PopRaw<Core::IrSensor::PackedFunctionLevel>()}; @@ -419,7 +429,7 @@ void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunImageTransferExProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -433,10 +443,8 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; const auto t_mem_handle{ctx.GetCopyHandle(0)}; - auto t_mem = - system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); - - u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress()); + auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( + t_mem_handle); LOG_INFO(Service_IRS, "called, npad_type={}, npad_id={}, transfer_memory_size={}, " @@ -452,14 +460,16 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); - image_transfer_processor.SetTransferMemoryPointer(transfer_memory); + image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress()); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { +void IRS::RunIrLedProcessor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; const auto processor_config{rp.PopRaw<Core::IrSensor::PackedIrLedProcessorConfig>()}; @@ -479,13 +489,15 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor<IrLedProcessor>(camera_handle, device); auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle); image_transfer_processor.SetConfig(processor_config); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { +void IRS::StopImageProcessorAsync(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::IrCameraHandle camera_handle; @@ -504,6 +516,8 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop image processor async + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); result = ResultSuccess; } @@ -511,7 +525,7 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { rb.Push(result); } -void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { +void IRS::ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { Core::IrSensor::PackedFunctionLevel function_level; diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index 2e6115c73..a8fa19025 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h @@ -38,24 +38,24 @@ private: }; static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size"); - void ActivateIrsensor(Kernel::HLERequestContext& ctx); - void DeactivateIrsensor(Kernel::HLERequestContext& ctx); - void GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx); - void StopImageProcessor(Kernel::HLERequestContext& ctx); - void RunMomentProcessor(Kernel::HLERequestContext& ctx); - void RunClusteringProcessor(Kernel::HLERequestContext& ctx); - void RunImageTransferProcessor(Kernel::HLERequestContext& ctx); - void GetImageTransferProcessorState(Kernel::HLERequestContext& ctx); - void RunTeraPluginProcessor(Kernel::HLERequestContext& ctx); - void GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx); - void RunPointingProcessor(Kernel::HLERequestContext& ctx); - void SuspendImageProcessor(Kernel::HLERequestContext& ctx); - void CheckFirmwareVersion(Kernel::HLERequestContext& ctx); - void SetFunctionLevel(Kernel::HLERequestContext& ctx); - void RunImageTransferExProcessor(Kernel::HLERequestContext& ctx); - void RunIrLedProcessor(Kernel::HLERequestContext& ctx); - void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); - void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); + void ActivateIrsensor(HLERequestContext& ctx); + void DeactivateIrsensor(HLERequestContext& ctx); + void GetIrsensorSharedMemoryHandle(HLERequestContext& ctx); + void StopImageProcessor(HLERequestContext& ctx); + void RunMomentProcessor(HLERequestContext& ctx); + void RunClusteringProcessor(HLERequestContext& ctx); + void RunImageTransferProcessor(HLERequestContext& ctx); + void GetImageTransferProcessorState(HLERequestContext& ctx); + void RunTeraPluginProcessor(HLERequestContext& ctx); + void GetNpadIrCameraHandle(HLERequestContext& ctx); + void RunPointingProcessor(HLERequestContext& ctx); + void SuspendImageProcessor(HLERequestContext& ctx); + void CheckFirmwareVersion(HLERequestContext& ctx); + void SetFunctionLevel(HLERequestContext& ctx); + void RunImageTransferExProcessor(HLERequestContext& ctx); + void RunIrLedProcessor(HLERequestContext& ctx); + void StopImageProcessorAsync(HLERequestContext& ctx); + void ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx); Result IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const; Core::IrSensor::DeviceFormat& GetIrCameraSharedMemoryDeviceEntry( @@ -80,7 +80,13 @@ private: LOG_CRITICAL(Service_IRS, "Invalid index {}", index); return; } - processors[index] = std::make_unique<T>(system.HIDCore(), device_state, index); + + if constexpr (std::is_constructible_v<T, Core::System&, Core::IrSensor::DeviceFormat&, + std::size_t>) { + processors[index] = std::make_unique<T>(system, device_state, index); + } else { + processors[index] = std::make_unique<T>(system.HIDCore(), device_state, index); + } } template <typename T> diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp index 98f0c579d..803a6277c 100644 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp +++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp @@ -1,16 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "core/core.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/irsensor/image_transfer_processor.h" +#include "core/memory.h" namespace Service::IRS { -ImageTransferProcessor::ImageTransferProcessor(Core::HID::HIDCore& hid_core_, +ImageTransferProcessor::ImageTransferProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index) - : device{device_format} { - npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); + : device{device_format}, system{system_} { + npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, @@ -43,27 +45,29 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType if (type != Core::HID::ControllerTriggerType::IrSensor) { return; } - if (!is_transfer_memory_set) { + if (transfer_memory == 0) { return; } const auto camera_data = npad_device->GetCamera(); - // This indicates how much ambient light is precent + // This indicates how much ambient light is present processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; processor_state.sampling_number = camera_data.sample; if (camera_data.format != current_config.origin_format) { LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, current_config.origin_format); - memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().ZeroBlock(transfer_memory, + GetDataSize(current_config.trimming_format)); return; } if (current_config.origin_format > current_config.trimming_format) { LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", current_config.origin_format, current_config.trimming_format); - memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().ZeroBlock(transfer_memory, + GetDataSize(current_config.trimming_format)); return; } @@ -80,7 +84,8 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", current_config.trimming_start_x, current_config.trimming_start_y, trimming_width, trimming_height, origin_width, origin_height); - memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().ZeroBlock(transfer_memory, + GetDataSize(current_config.trimming_format)); return; } @@ -94,7 +99,8 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType } } - memcpy(transfer_memory, window_data.data(), GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(), + GetDataSize(current_config.trimming_format)); if (!IsProcessorActive()) { StartProcessor(); @@ -134,8 +140,7 @@ void ImageTransferProcessor::SetConfig( npad_device->SetCameraFormat(current_config.origin_format); } -void ImageTransferProcessor::SetTransferMemoryPointer(u8* t_mem) { - is_transfer_memory_set = true; +void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { transfer_memory = t_mem; } @@ -143,7 +148,7 @@ Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( std::vector<u8>& data) const { const auto size = GetDataSize(current_config.trimming_format); data.resize(size); - memcpy(data.data(), transfer_memory, size); + system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); return processor_state; } diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.h b/src/core/hle/service/hid/irsensor/image_transfer_processor.h index 393df492d..7f42d8453 100644 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.h +++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.h @@ -3,10 +3,14 @@ #pragma once -#include "common/common_types.h" +#include "common/typed_address.h" #include "core/hid/irs_types.h" #include "core/hle/service/hid/irsensor/processor_base.h" +namespace Core { +class System; +} + namespace Core::HID { class EmulatedController; } // namespace Core::HID @@ -14,7 +18,7 @@ class EmulatedController; namespace Service::IRS { class ImageTransferProcessor final : public ProcessorBase { public: - explicit ImageTransferProcessor(Core::HID::HIDCore& hid_core_, + explicit ImageTransferProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index); ~ImageTransferProcessor() override; @@ -33,7 +37,7 @@ public: void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); // Transfer memory where the image data will be stored - void SetTransferMemoryPointer(u8* t_mem); + void SetTransferMemoryAddress(Common::ProcessAddress t_mem); Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; @@ -67,7 +71,7 @@ private: Core::HID::EmulatedController* npad_device; int callback_key{}; - u8* transfer_memory = nullptr; - bool is_transfer_memory_set = false; + Core::System& system; + Common::ProcessAddress transfer_memory{}; }; } // namespace Service::IRS diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp new file mode 100644 index 000000000..2290df705 --- /dev/null +++ b/src/core/hle/service/hle_ipc.cpp @@ -0,0 +1,531 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <algorithm> +#include <array> +#include <sstream> + +#include <boost/range/algorithm_ext/erase.hpp> + +#include "common/assert.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/logging/log.h" +#include "common/scratch_buffer.h" +#include "core/hle/kernel/k_auto_object.h" +#include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_server_port.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/service/hle_ipc.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/memory.h" + +namespace Service { + +SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_) + : kernel{kernel_} {} + +SessionRequestHandler::~SessionRequestHandler() = default; + +SessionRequestManager::SessionRequestManager(Kernel::KernelCore& kernel_, + ServerManager& server_manager_) + : kernel{kernel_}, server_manager{server_manager_} {} + +SessionRequestManager::~SessionRequestManager() = default; + +bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& context) const { + if (IsDomain() && context.HasDomainMessageHeader()) { + const auto& message_header = context.GetDomainMessageHeader(); + const auto object_id = message_header.object_id; + + if (object_id > DomainHandlerCount()) { + LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); + return false; + } + return !DomainHandler(object_id - 1).expired(); + } else { + return session_handler != nullptr; + } +} + +Result SessionRequestManager::CompleteSyncRequest(Kernel::KServerSession* server_session, + HLERequestContext& context) { + Result result = ResultSuccess; + + // If the session has been converted to a domain, handle the domain request + if (this->HasSessionRequestHandler(context)) { + if (IsDomain() && context.HasDomainMessageHeader()) { + result = HandleDomainSyncRequest(server_session, context); + // If there is no domain header, the regular session handler is used + } else if (this->HasSessionHandler()) { + // If this manager has an associated HLE handler, forward the request to it. + result = this->SessionHandler().HandleSyncRequest(*server_session, context); + } + } else { + ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); + IPC::ResponseBuilder rb(context, 2); + rb.Push(ResultSuccess); + } + + if (convert_to_domain) { + ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); + this->ConvertToDomain(); + convert_to_domain = false; + } + + return result; +} + +Result SessionRequestManager::HandleDomainSyncRequest(Kernel::KServerSession* server_session, + HLERequestContext& context) { + if (!context.HasDomainMessageHeader()) { + return ResultSuccess; + } + + // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs + ASSERT(context.GetManager().get() == this); + + // If there is a DomainMessageHeader, then this is CommandType "Request" + const auto& domain_message_header = context.GetDomainMessageHeader(); + const u32 object_id{domain_message_header.object_id}; + switch (domain_message_header.command) { + case IPC::DomainMessageHeader::CommandType::SendMessage: + if (object_id > this->DomainHandlerCount()) { + LOG_CRITICAL(IPC, + "object_id {} is too big! This probably means a recent service call " + "needed to return a new interface!", + object_id); + ASSERT(false); + return ResultSuccess; // Ignore error if asserts are off + } + if (auto strong_ptr = this->DomainHandler(object_id - 1).lock()) { + return strong_ptr->HandleSyncRequest(*server_session, context); + } else { + ASSERT(false); + return ResultSuccess; + } + + case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { + LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); + + this->CloseDomainHandler(object_id - 1); + + IPC::ResponseBuilder rb{context, 2}; + rb.Push(ResultSuccess); + return ResultSuccess; + } + } + + LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); + ASSERT(false); + return ResultSuccess; +} + +HLERequestContext::HLERequestContext(Kernel::KernelCore& kernel_, Core::Memory::Memory& memory_, + Kernel::KServerSession* server_session_, + Kernel::KThread* thread_) + : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { + cmd_buf[0] = 0; +} + +HLERequestContext::~HLERequestContext() = default; + +void HLERequestContext::ParseCommandBuffer(const Kernel::KHandleTable& handle_table, + u32_le* src_cmdbuf, bool incoming) { + IPC::RequestParser rp(src_cmdbuf); + command_header = rp.PopRaw<IPC::CommandHeader>(); + + if (command_header->IsCloseCommand()) { + // Close does not populate the rest of the IPC header + return; + } + + // If handle descriptor is present, add size of it + if (command_header->enable_handle_descriptor) { + handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); + if (handle_descriptor_header->send_current_pid) { + pid = rp.Pop<u64>(); + } + if (incoming) { + // Populate the object lists with the data in the IPC request. + incoming_copy_handles.reserve(handle_descriptor_header->num_handles_to_copy); + incoming_move_handles.reserve(handle_descriptor_header->num_handles_to_move); + + for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { + incoming_copy_handles.push_back(rp.Pop<Handle>()); + } + for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { + incoming_move_handles.push_back(rp.Pop<Handle>()); + } + } else { + // For responses we just ignore the handles, they're empty and will be populated when + // translating the response. + rp.Skip(handle_descriptor_header->num_handles_to_copy, false); + rp.Skip(handle_descriptor_header->num_handles_to_move, false); + } + } + + buffer_x_desciptors.reserve(command_header->num_buf_x_descriptors); + buffer_a_desciptors.reserve(command_header->num_buf_a_descriptors); + buffer_b_desciptors.reserve(command_header->num_buf_b_descriptors); + buffer_w_desciptors.reserve(command_header->num_buf_w_descriptors); + + for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { + buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); + } + for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { + buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); + } + for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { + buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); + } + for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { + buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); + } + + const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; + + if (!command_header->IsTipc()) { + // Padding to align to 16 bytes + rp.AlignWithPadding(); + + if (GetManager()->IsDomain() && + ((command_header->type == IPC::CommandType::Request || + command_header->type == IPC::CommandType::RequestWithContext) || + !incoming)) { + // If this is an incoming message, only CommandType "Request" has a domain header + // All outgoing domain messages have the domain header, if only incoming has it + if (incoming || domain_message_header) { + domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); + } else { + if (GetManager()->IsDomain()) { + LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); + } + } + } + + data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); + + data_payload_offset = rp.GetCurrentOffset(); + + if (domain_message_header && + domain_message_header->command == + IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { + // CloseVirtualHandle command does not have SFC* or any data + return; + } + + if (incoming) { + ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); + } else { + ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); + } + } + + rp.SetCurrentOffset(buffer_c_offset); + + // For Inline buffers, the response data is written directly to buffer_c_offset + // and in this case we don't have any BufferDescriptorC on the request. + if (command_header->buf_c_descriptor_flags > + IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) { + if (command_header->buf_c_descriptor_flags == + IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { + buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); + } else { + u32 num_buf_c_descriptors = + static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2; + + // This is used to detect possible underflows, in case something is broken + // with the two ifs above and the flags value is == 0 || == 1. + ASSERT(num_buf_c_descriptors < 14); + + for (u32 i = 0; i < num_buf_c_descriptors; ++i) { + buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); + } + } + } + + rp.SetCurrentOffset(data_payload_offset); + + command = rp.Pop<u32_le>(); + rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. +} + +Result HLERequestContext::PopulateFromIncomingCommandBuffer( + const Kernel::KHandleTable& handle_table, u32_le* src_cmdbuf) { + ParseCommandBuffer(handle_table, src_cmdbuf, true); + + if (command_header->IsCloseCommand()) { + // Close does not populate the rest of the IPC header + return ResultSuccess; + } + + std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin()); + + return ResultSuccess; +} + +Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread) { + auto current_offset = handles_offset; + auto& owner_process = *requesting_thread.GetOwnerProcess(); + auto& handle_table = owner_process.GetHandleTable(); + + for (auto& object : outgoing_copy_objects) { + Handle handle{}; + if (object) { + R_TRY(handle_table.Add(&handle, object)); + } + cmd_buf[current_offset++] = handle; + } + for (auto& object : outgoing_move_objects) { + Handle handle{}; + if (object) { + R_TRY(handle_table.Add(&handle, object)); + + // Close our reference to the object, as it is being moved to the caller. + object->Close(); + } + cmd_buf[current_offset++] = handle; + } + + // Write the domain objects to the command buffer, these go after the raw untranslated data. + // TODO(Subv): This completely ignores C buffers. + + if (GetManager()->IsDomain()) { + current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); + for (auto& object : outgoing_domain_objects) { + GetManager()->AppendDomainHandler(std::move(object)); + cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount()); + } + } + + // Copy the translated command buffer back into the thread's command buffer area. + memory.WriteBlock(requesting_thread.GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32)); + + return ResultSuccess; +} + +std::vector<u8> HLERequestContext::ReadBufferCopy(std::size_t buffer_index) const { + const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && + BufferDescriptorA()[buffer_index].Size()}; + if (is_buffer_a) { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorA().size() > buffer_index, { return {}; }, + "BufferDescriptorA invalid buffer_index {}", buffer_index); + std::vector<u8> buffer(BufferDescriptorA()[buffer_index].Size()); + memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); + return buffer; + } else { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorX().size() > buffer_index, { return {}; }, + "BufferDescriptorX invalid buffer_index {}", buffer_index); + std::vector<u8> buffer(BufferDescriptorX()[buffer_index].Size()); + memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); + return buffer; + } +} + +std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { + static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_a; + static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_x; + + const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && + BufferDescriptorA()[buffer_index].Size()}; + if (is_buffer_a) { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorA().size() > buffer_index, { return {}; }, + "BufferDescriptorA invalid buffer_index {}", buffer_index); + auto& read_buffer = read_buffer_a[buffer_index]; + read_buffer.resize_destructive(BufferDescriptorA()[buffer_index].Size()); + memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), read_buffer.data(), + read_buffer.size()); + return read_buffer; + } else { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorX().size() > buffer_index, { return {}; }, + "BufferDescriptorX invalid buffer_index {}", buffer_index); + auto& read_buffer = read_buffer_x[buffer_index]; + read_buffer.resize_destructive(BufferDescriptorX()[buffer_index].Size()); + memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), read_buffer.data(), + read_buffer.size()); + return read_buffer; + } +} + +std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, + std::size_t buffer_index) const { + if (size == 0) { + LOG_WARNING(Core, "skip empty buffer write"); + return 0; + } + + const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && + BufferDescriptorB()[buffer_index].Size()}; + const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; + if (size > buffer_size) { + LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, + buffer_size); + size = buffer_size; // TODO(bunnei): This needs to be HW tested + } + + if (is_buffer_b) { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorB().size() > buffer_index && + BufferDescriptorB()[buffer_index].Size() >= size, + { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size); + WriteBufferB(buffer, size, buffer_index); + } else { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorC().size() > buffer_index && + BufferDescriptorC()[buffer_index].Size() >= size, + { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size); + WriteBufferC(buffer, size, buffer_index); + } + + return size; +} + +std::size_t HLERequestContext::WriteBufferB(const void* buffer, std::size_t size, + std::size_t buffer_index) const { + if (buffer_index >= BufferDescriptorB().size() || size == 0) { + return 0; + } + + const auto buffer_size{BufferDescriptorB()[buffer_index].Size()}; + if (size > buffer_size) { + LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, + buffer_size); + size = buffer_size; // TODO(bunnei): This needs to be HW tested + } + + memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); + return size; +} + +std::size_t HLERequestContext::WriteBufferC(const void* buffer, std::size_t size, + std::size_t buffer_index) const { + if (buffer_index >= BufferDescriptorC().size() || size == 0) { + return 0; + } + + const auto buffer_size{BufferDescriptorC()[buffer_index].Size()}; + if (size > buffer_size) { + LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, + buffer_size); + size = buffer_size; // TODO(bunnei): This needs to be HW tested + } + + memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); + return size; +} + +std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const { + const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && + BufferDescriptorA()[buffer_index].Size()}; + if (is_buffer_a) { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorA().size() > buffer_index, { return 0; }, + "BufferDescriptorA invalid buffer_index {}", buffer_index); + return BufferDescriptorA()[buffer_index].Size(); + } else { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorX().size() > buffer_index, { return 0; }, + "BufferDescriptorX invalid buffer_index {}", buffer_index); + return BufferDescriptorX()[buffer_index].Size(); + } +} + +std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) const { + const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && + BufferDescriptorB()[buffer_index].Size()}; + if (is_buffer_b) { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorB().size() > buffer_index, { return 0; }, + "BufferDescriptorB invalid buffer_index {}", buffer_index); + return BufferDescriptorB()[buffer_index].Size(); + } else { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorC().size() > buffer_index, { return 0; }, + "BufferDescriptorC invalid buffer_index {}", buffer_index); + return BufferDescriptorC()[buffer_index].Size(); + } + return 0; +} + +bool HLERequestContext::CanReadBuffer(std::size_t buffer_index) const { + const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && + BufferDescriptorA()[buffer_index].Size()}; + + if (is_buffer_a) { + return BufferDescriptorA().size() > buffer_index; + } else { + return BufferDescriptorX().size() > buffer_index; + } +} + +bool HLERequestContext::CanWriteBuffer(std::size_t buffer_index) const { + const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && + BufferDescriptorB()[buffer_index].Size()}; + + if (is_buffer_b) { + return BufferDescriptorB().size() > buffer_index; + } else { + return BufferDescriptorC().size() > buffer_index; + } +} + +std::string HLERequestContext::Description() const { + if (!command_header) { + return "No command header available"; + } + std::ostringstream s; + s << "IPC::CommandHeader: Type:" << static_cast<u32>(command_header->type.Value()); + s << ", X(Pointer):" << command_header->num_buf_x_descriptors; + if (command_header->num_buf_x_descriptors) { + s << '['; + for (u64 i = 0; i < command_header->num_buf_x_descriptors; ++i) { + s << "0x" << std::hex << BufferDescriptorX()[i].Size(); + if (i < command_header->num_buf_x_descriptors - 1) + s << ", "; + } + s << ']'; + } + s << ", A(Send):" << command_header->num_buf_a_descriptors; + if (command_header->num_buf_a_descriptors) { + s << '['; + for (u64 i = 0; i < command_header->num_buf_a_descriptors; ++i) { + s << "0x" << std::hex << BufferDescriptorA()[i].Size(); + if (i < command_header->num_buf_a_descriptors - 1) + s << ", "; + } + s << ']'; + } + s << ", B(Receive):" << command_header->num_buf_b_descriptors; + if (command_header->num_buf_b_descriptors) { + s << '['; + for (u64 i = 0; i < command_header->num_buf_b_descriptors; ++i) { + s << "0x" << std::hex << BufferDescriptorB()[i].Size(); + if (i < command_header->num_buf_b_descriptors - 1) + s << ", "; + } + s << ']'; + } + s << ", C(ReceiveList):" << BufferDescriptorC().size(); + if (!BufferDescriptorC().empty()) { + s << '['; + for (u64 i = 0; i < BufferDescriptorC().size(); ++i) { + s << "0x" << std::hex << BufferDescriptorC()[i].Size(); + if (i < BufferDescriptorC().size() - 1) + s << ", "; + } + s << ']'; + } + s << ", data_size:" << command_header->data_size.Value(); + + return s.str(); +} + +} // namespace Service diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h new file mode 100644 index 000000000..4bd24c899 --- /dev/null +++ b/src/core/hle/service/hle_ipc.h @@ -0,0 +1,408 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <array> +#include <functional> +#include <memory> +#include <optional> +#include <span> +#include <string> +#include <type_traits> +#include <vector> + +#include "common/assert.h" +#include "common/common_types.h" +#include "common/concepts.h" +#include "common/swap.h" +#include "core/hle/ipc.h" +#include "core/hle/kernel/svc_common.h" + +union Result; + +namespace Core::Memory { +class Memory; +} + +namespace IPC { +class ResponseBuilder; +} + +namespace Service { +class ServiceFrameworkBase; +class ServerManager; +} // namespace Service + +namespace Kernel { +class KAutoObject; +class KernelCore; +class KHandleTable; +class KServerSession; +class KThread; +} // namespace Kernel + +namespace Service { + +using Handle = Kernel::Handle; + +class HLERequestContext; + +/** + * Interface implemented by HLE Session handlers. + * This can be provided to a ServerSession in order to hook into several relevant events + * (such as a new connection or a SyncRequest) so they can be implemented in the emulator. + */ +class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { +public: + SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_); + virtual ~SessionRequestHandler(); + + /** + * Handles a sync request from the emulated application. + * @param server_session The ServerSession that was triggered for this sync request, + * it should be used to differentiate which client (As in ClientSession) we're answering to. + * TODO(Subv): Use a wrapper structure to hold all the information relevant to + * this request (ServerSession, Originator thread, Translated command buffer, etc). + * @returns Result the result code of the translate operation. + */ + virtual Result HandleSyncRequest(Kernel::KServerSession& session, + HLERequestContext& context) = 0; + +protected: + Kernel::KernelCore& kernel; +}; + +using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>; +using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; + +/** + * Manages the underlying HLE requests for a session, and whether (or not) the session should be + * treated as a domain. This is managed separately from server sessions, as this state is shared + * when objects are cloned. + */ +class SessionRequestManager final { +public: + explicit SessionRequestManager(Kernel::KernelCore& kernel, + Service::ServerManager& server_manager); + ~SessionRequestManager(); + + bool IsDomain() const { + return is_domain; + } + + void ConvertToDomain() { + domain_handlers = {session_handler}; + is_domain = true; + } + + void ConvertToDomainOnRequestEnd() { + convert_to_domain = true; + } + + std::size_t DomainHandlerCount() const { + return domain_handlers.size(); + } + + bool HasSessionHandler() const { + return session_handler != nullptr; + } + + SessionRequestHandler& SessionHandler() { + return *session_handler; + } + + const SessionRequestHandler& SessionHandler() const { + return *session_handler; + } + + void CloseDomainHandler(std::size_t index) { + if (index < DomainHandlerCount()) { + domain_handlers[index] = nullptr; + } else { + ASSERT_MSG(false, "Unexpected handler index {}", index); + } + } + + SessionRequestHandlerWeakPtr DomainHandler(std::size_t index) const { + ASSERT_MSG(index < DomainHandlerCount(), "Unexpected handler index {}", index); + return domain_handlers.at(index); + } + + void AppendDomainHandler(SessionRequestHandlerPtr&& handler) { + domain_handlers.emplace_back(std::move(handler)); + } + + void SetSessionHandler(SessionRequestHandlerPtr&& handler) { + session_handler = std::move(handler); + } + + bool HasSessionRequestHandler(const HLERequestContext& context) const; + + Result HandleDomainSyncRequest(Kernel::KServerSession* server_session, + HLERequestContext& context); + Result CompleteSyncRequest(Kernel::KServerSession* server_session, HLERequestContext& context); + + Service::ServerManager& GetServerManager() { + return server_manager; + } + + // TODO: remove this when sm: is implemented with the proper IUserInterface + // abstraction, creating a new C++ handler object for each session: + + bool GetIsInitializedForSm() const { + return is_initialized_for_sm; + } + + void SetIsInitializedForSm() { + is_initialized_for_sm = true; + } + +private: + bool convert_to_domain{}; + bool is_domain{}; + bool is_initialized_for_sm{}; + SessionRequestHandlerPtr session_handler; + std::vector<SessionRequestHandlerPtr> domain_handlers; + +private: + Kernel::KernelCore& kernel; + Service::ServerManager& server_manager; +}; + +/** + * Class containing information about an in-flight IPC request being handled by an HLE service + * implementation. + */ +class HLERequestContext { +public: + explicit HLERequestContext(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, + Kernel::KServerSession* session, Kernel::KThread* thread); + ~HLERequestContext(); + + /// Returns a pointer to the IPC command buffer for this request. + [[nodiscard]] u32* CommandBuffer() { + return cmd_buf.data(); + } + + /** + * Returns the session through which this request was made. This can be used as a map key to + * access per-client data on services. + */ + [[nodiscard]] Kernel::KServerSession* Session() { + return server_session; + } + + /// Populates this context with data from the requesting process/thread. + Result PopulateFromIncomingCommandBuffer(const Kernel::KHandleTable& handle_table, + u32_le* src_cmdbuf); + + /// Writes data from this context back to the requesting process/thread. + Result WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread); + + [[nodiscard]] u32_le GetHipcCommand() const { + return command; + } + + [[nodiscard]] u32_le GetTipcCommand() const { + return static_cast<u32_le>(command_header->type.Value()) - + static_cast<u32_le>(IPC::CommandType::TIPC_CommandRegion); + } + + [[nodiscard]] u32_le GetCommand() const { + return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand(); + } + + [[nodiscard]] bool IsTipc() const { + return command_header->IsTipc(); + } + + [[nodiscard]] IPC::CommandType GetCommandType() const { + return command_header->type; + } + + [[nodiscard]] u64 GetPID() const { + return pid; + } + + [[nodiscard]] u32 GetDataPayloadOffset() const { + return data_payload_offset; + } + + [[nodiscard]] const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const { + return buffer_x_desciptors; + } + + [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const { + return buffer_a_desciptors; + } + + [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const { + return buffer_b_desciptors; + } + + [[nodiscard]] const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { + return buffer_c_desciptors; + } + + [[nodiscard]] const IPC::DomainMessageHeader& GetDomainMessageHeader() const { + return domain_message_header.value(); + } + + [[nodiscard]] bool HasDomainMessageHeader() const { + return domain_message_header.has_value(); + } + + /// Helper function to get a span of a buffer using the appropriate buffer descriptor + [[nodiscard]] std::span<const u8> ReadBuffer(std::size_t buffer_index = 0) const; + + /// Helper function to read a copy of a buffer using the appropriate buffer descriptor + [[nodiscard]] std::vector<u8> ReadBufferCopy(std::size_t buffer_index = 0) const; + + /// Helper function to write a buffer using the appropriate buffer descriptor + std::size_t WriteBuffer(const void* buffer, std::size_t size, + std::size_t buffer_index = 0) const; + + /// Helper function to write buffer B + std::size_t WriteBufferB(const void* buffer, std::size_t size, + std::size_t buffer_index = 0) const; + + /// Helper function to write buffer C + std::size_t WriteBufferC(const void* buffer, std::size_t size, + std::size_t buffer_index = 0) const; + + /* Helper function to write a buffer using the appropriate buffer descriptor + * + * @tparam T an arbitrary container that satisfies the + * ContiguousContainer concept in the C++ standard library or a trivially copyable type. + * + * @param data The container/data to write into a buffer. + * @param buffer_index The buffer in particular to write to. + */ + template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>> + std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const { + if constexpr (Common::IsContiguousContainer<T>) { + using ContiguousType = typename T::value_type; + static_assert(std::is_trivially_copyable_v<ContiguousType>, + "Container to WriteBuffer must contain trivially copyable objects"); + return WriteBuffer(std::data(data), std::size(data) * sizeof(ContiguousType), + buffer_index); + } else { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); + return WriteBuffer(&data, sizeof(T), buffer_index); + } + } + + /// Helper function to get the size of the input buffer + [[nodiscard]] std::size_t GetReadBufferSize(std::size_t buffer_index = 0) const; + + /// Helper function to get the size of the output buffer + [[nodiscard]] std::size_t GetWriteBufferSize(std::size_t buffer_index = 0) const; + + /// Helper function to derive the number of elements able to be contained in the read buffer + template <typename T> + [[nodiscard]] std::size_t GetReadBufferNumElements(std::size_t buffer_index = 0) const { + return GetReadBufferSize(buffer_index) / sizeof(T); + } + + /// Helper function to derive the number of elements able to be contained in the write buffer + template <typename T> + [[nodiscard]] std::size_t GetWriteBufferNumElements(std::size_t buffer_index = 0) const { + return GetWriteBufferSize(buffer_index) / sizeof(T); + } + + /// Helper function to test whether the input buffer at buffer_index can be read + [[nodiscard]] bool CanReadBuffer(std::size_t buffer_index = 0) const; + + /// Helper function to test whether the output buffer at buffer_index can be written + [[nodiscard]] bool CanWriteBuffer(std::size_t buffer_index = 0) const; + + [[nodiscard]] Handle GetCopyHandle(std::size_t index) const { + return incoming_copy_handles.at(index); + } + + [[nodiscard]] Handle GetMoveHandle(std::size_t index) const { + return incoming_move_handles.at(index); + } + + void AddMoveObject(Kernel::KAutoObject* object) { + outgoing_move_objects.emplace_back(object); + } + + void AddCopyObject(Kernel::KAutoObject* object) { + outgoing_copy_objects.emplace_back(object); + } + + void AddDomainObject(SessionRequestHandlerPtr object) { + outgoing_domain_objects.emplace_back(std::move(object)); + } + + template <typename T> + std::shared_ptr<T> GetDomainHandler(std::size_t index) const { + return std::static_pointer_cast<T>(GetManager()->DomainHandler(index).lock()); + } + + void SetSessionRequestManager(std::weak_ptr<SessionRequestManager> manager_) { + manager = manager_; + } + + [[nodiscard]] std::string Description() const; + + [[nodiscard]] Kernel::KThread& GetThread() { + return *thread; + } + + [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const { + return manager.lock(); + } + + bool GetIsDeferred() const { + return is_deferred; + } + + void SetIsDeferred(bool is_deferred_ = true) { + is_deferred = is_deferred_; + } + +private: + friend class IPC::ResponseBuilder; + + void ParseCommandBuffer(const Kernel::KHandleTable& handle_table, u32_le* src_cmdbuf, + bool incoming); + + std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; + Kernel::KServerSession* server_session{}; + Kernel::KThread* thread; + + std::vector<Handle> incoming_move_handles; + std::vector<Handle> incoming_copy_handles; + + std::vector<Kernel::KAutoObject*> outgoing_move_objects; + std::vector<Kernel::KAutoObject*> outgoing_copy_objects; + std::vector<SessionRequestHandlerPtr> outgoing_domain_objects; + + std::optional<IPC::CommandHeader> command_header; + std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; + std::optional<IPC::DataPayloadHeader> data_payload_header; + std::optional<IPC::DomainMessageHeader> domain_message_header; + std::vector<IPC::BufferDescriptorX> buffer_x_desciptors; + std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; + std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; + std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; + std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; + + u32_le command{}; + u64 pid{}; + u32 write_size{}; + u32 data_payload_offset{}; + u32 handles_offset{}; + u32 domain_offset{}; + + std::weak_ptr<SessionRequestManager> manager{}; + bool is_deferred{false}; + + Kernel::KernelCore& kernel; + Core::Memory::Memory& memory; +}; + +} // namespace Service diff --git a/src/core/hle/service/ipc_helpers.h b/src/core/hle/service/ipc_helpers.h new file mode 100644 index 000000000..0e222362e --- /dev/null +++ b/src/core/hle/service/ipc_helpers.h @@ -0,0 +1,506 @@ +// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <cstring> +#include <memory> +#include <type_traits> +#include <utility> +#include "common/assert.h" +#include "common/common_types.h" +#include "core/hle/ipc.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_resource_limit.h" +#include "core/hle/kernel/k_session.h" +#include "core/hle/result.h" +#include "core/hle/service/hle_ipc.h" +#include "core/hle/service/server_manager.h" + +namespace IPC { + +constexpr Result ResultSessionClosed{ErrorModule::HIPC, 301}; + +class RequestHelperBase { +protected: + Service::HLERequestContext* context = nullptr; + u32* cmdbuf; + u32 index = 0; + +public: + explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} + + explicit RequestHelperBase(Service::HLERequestContext& ctx) + : context(&ctx), cmdbuf(ctx.CommandBuffer()) {} + + void Skip(u32 size_in_words, bool set_to_null) { + if (set_to_null) { + memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); + } + index += size_in_words; + } + + /** + * Aligns the current position forward to a 16-byte boundary, padding with zeros. + */ + void AlignWithPadding() { + if (index & 3) { + Skip(static_cast<u32>(4 - (index & 3)), true); + } + } + + u32 GetCurrentOffset() const { + return index; + } + + void SetCurrentOffset(u32 offset) { + index = offset; + } +}; + +class ResponseBuilder : public RequestHelperBase { +public: + /// Flags used for customizing the behavior of ResponseBuilder + enum class Flags : u32 { + None = 0, + /// Uses move handles to move objects in the response, even when in a domain. This is + /// required when PushMoveObjects is used. + AlwaysMoveHandles = 1, + }; + + explicit ResponseBuilder(Service::HLERequestContext& ctx, u32 normal_params_size_, + u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0, + Flags flags = Flags::None) + : RequestHelperBase(ctx), normal_params_size(normal_params_size_), + num_handles_to_copy(num_handles_to_copy_), + num_objects_to_move(num_objects_to_move_), kernel{ctx.kernel} { + + memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); + + IPC::CommandHeader header{}; + + // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory + // padding. + u32 raw_data_size = ctx.write_size = + ctx.IsTipc() ? normal_params_size - 1 : normal_params_size; + u32 num_handles_to_move{}; + u32 num_domain_objects{}; + const bool always_move_handles{ + (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; + if (!ctx.GetManager()->IsDomain() || always_move_handles) { + num_handles_to_move = num_objects_to_move; + } else { + num_domain_objects = num_objects_to_move; + } + + if (ctx.GetManager()->IsDomain()) { + raw_data_size += + static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); + ctx.write_size += num_domain_objects; + } + + if (ctx.IsTipc()) { + header.type.Assign(ctx.GetCommandType()); + } else { + raw_data_size += static_cast<u32>(sizeof(IPC::DataPayloadHeader) / sizeof(u32) + 4 + + normal_params_size); + } + + header.data_size.Assign(raw_data_size); + if (num_handles_to_copy || num_handles_to_move) { + header.enable_handle_descriptor.Assign(1); + } + PushRaw(header); + + if (header.enable_handle_descriptor) { + IPC::HandleDescriptorHeader handle_descriptor_header{}; + handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy_); + handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); + PushRaw(handle_descriptor_header); + + ctx.handles_offset = index; + + Skip(num_handles_to_copy + num_handles_to_move, true); + } + + if (!ctx.IsTipc()) { + AlignWithPadding(); + + if (ctx.GetManager()->IsDomain() && ctx.HasDomainMessageHeader()) { + IPC::DomainMessageHeader domain_header{}; + domain_header.num_objects = num_domain_objects; + PushRaw(domain_header); + } + + IPC::DataPayloadHeader data_payload_header{}; + data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); + PushRaw(data_payload_header); + } + + data_payload_index = index; + + ctx.data_payload_offset = index; + ctx.write_size += index; + ctx.domain_offset = static_cast<u32>(index + raw_data_size / sizeof(u32)); + } + + template <class T> + void PushIpcInterface(std::shared_ptr<T> iface) { + auto manager{context->GetManager()}; + + if (manager->IsDomain()) { + context->AddDomainObject(std::move(iface)); + } else { + kernel.ApplicationProcess()->GetResourceLimit()->Reserve( + Kernel::LimitableResource::SessionCountMax, 1); + + auto* session = Kernel::KSession::Create(kernel); + session->Initialize(nullptr, 0); + Kernel::KSession::Register(kernel, session); + + auto next_manager = std::make_shared<Service::SessionRequestManager>( + kernel, manager->GetServerManager()); + next_manager->SetSessionHandler(iface); + manager->GetServerManager().RegisterSession(&session->GetServerSession(), next_manager); + + context->AddMoveObject(&session->GetClientSession()); + } + } + + template <class T, class... Args> + void PushIpcInterface(Args&&... args) { + PushIpcInterface<T>(std::make_shared<T>(std::forward<Args>(args)...)); + } + + void PushImpl(s8 value); + void PushImpl(s16 value); + void PushImpl(s32 value); + void PushImpl(s64 value); + void PushImpl(u8 value); + void PushImpl(u16 value); + void PushImpl(u32 value); + void PushImpl(u64 value); + void PushImpl(float value); + void PushImpl(double value); + void PushImpl(bool value); + void PushImpl(Result value); + + template <typename T> + void Push(T value) { + return PushImpl(value); + } + + template <typename First, typename... Other> + void Push(const First& first_value, const Other&... other_values); + + /** + * Helper function for pushing strongly-typed enumeration values. + * + * @tparam Enum The enumeration type to be pushed + * + * @param value The value to push. + * + * @note The underlying size of the enumeration type is the size of the + * data that gets pushed. e.g. "enum class SomeEnum : u16" will + * push a u16-sized amount of data. + */ + template <typename Enum> + void PushEnum(Enum value) { + static_assert(std::is_enum_v<Enum>, "T must be an enum type within a PushEnum call."); + static_assert(!std::is_convertible_v<Enum, int>, + "enum type in PushEnum must be a strongly typed enum."); + Push(static_cast<std::underlying_type_t<Enum>>(value)); + } + + /** + * @brief Copies the content of the given trivially copyable class to the buffer as a normal + * param + * @note: The input class must be correctly packed/padded to fit hardware layout. + */ + template <typename T> + void PushRaw(const T& value); + + template <typename... O> + void PushMoveObjects(O*... pointers); + + template <typename... O> + void PushMoveObjects(O&... pointers); + + template <typename... O> + void PushCopyObjects(O*... pointers); + + template <typename... O> + void PushCopyObjects(O&... pointers); + +private: + u32 normal_params_size{}; + u32 num_handles_to_copy{}; + u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent + u32 data_payload_index{}; + Kernel::KernelCore& kernel; +}; + +/// Push /// + +inline void ResponseBuilder::PushImpl(s32 value) { + cmdbuf[index++] = value; +} + +inline void ResponseBuilder::PushImpl(u32 value) { + cmdbuf[index++] = value; +} + +template <typename T> +void ResponseBuilder::PushRaw(const T& value) { + static_assert(std::is_trivially_copyable_v<T>, + "It's undefined behavior to use memcpy with non-trivially copyable objects"); + std::memcpy(cmdbuf + index, &value, sizeof(T)); + index += (sizeof(T) + 3) / 4; // round up to word length +} + +inline void ResponseBuilder::PushImpl(Result value) { + // Result codes are actually 64-bit in the IPC buffer, but only the high part is discarded. + Push(value.raw); + Push<u32>(0); +} + +inline void ResponseBuilder::PushImpl(s8 value) { + PushRaw(value); +} + +inline void ResponseBuilder::PushImpl(s16 value) { + PushRaw(value); +} + +inline void ResponseBuilder::PushImpl(s64 value) { + PushImpl(static_cast<u32>(value)); + PushImpl(static_cast<u32>(value >> 32)); +} + +inline void ResponseBuilder::PushImpl(u8 value) { + PushRaw(value); +} + +inline void ResponseBuilder::PushImpl(u16 value) { + PushRaw(value); +} + +inline void ResponseBuilder::PushImpl(u64 value) { + PushImpl(static_cast<u32>(value)); + PushImpl(static_cast<u32>(value >> 32)); +} + +inline void ResponseBuilder::PushImpl(float value) { + u32 integral; + std::memcpy(&integral, &value, sizeof(u32)); + PushImpl(integral); +} + +inline void ResponseBuilder::PushImpl(double value) { + u64 integral; + std::memcpy(&integral, &value, sizeof(u64)); + PushImpl(integral); +} + +inline void ResponseBuilder::PushImpl(bool value) { + PushImpl(static_cast<u8>(value)); +} + +template <typename First, typename... Other> +void ResponseBuilder::Push(const First& first_value, const Other&... other_values) { + Push(first_value); + Push(other_values...); +} + +template <typename... O> +inline void ResponseBuilder::PushCopyObjects(O*... pointers) { + auto objects = {pointers...}; + for (auto& object : objects) { + context->AddCopyObject(object); + } +} + +template <typename... O> +inline void ResponseBuilder::PushCopyObjects(O&... pointers) { + auto objects = {&pointers...}; + for (auto& object : objects) { + context->AddCopyObject(object); + } +} + +template <typename... O> +inline void ResponseBuilder::PushMoveObjects(O*... pointers) { + auto objects = {pointers...}; + for (auto& object : objects) { + context->AddMoveObject(object); + } +} + +template <typename... O> +inline void ResponseBuilder::PushMoveObjects(O&... pointers) { + auto objects = {&pointers...}; + for (auto& object : objects) { + context->AddMoveObject(object); + } +} + +class RequestParser : public RequestHelperBase { +public: + explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} + + explicit RequestParser(Service::HLERequestContext& ctx) : RequestHelperBase(ctx) { + // TIPC does not have data payload offset + if (!ctx.IsTipc()) { + ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete"); + Skip(ctx.GetDataPayloadOffset(), false); + } + + // Skip the u64 command id, it's already stored in the context + static constexpr u32 CommandIdSize = 2; + Skip(CommandIdSize, false); + } + + template <typename T> + T Pop(); + + template <typename T> + void Pop(T& value); + + template <typename First, typename... Other> + void Pop(First& first_value, Other&... other_values); + + template <typename T> + T PopEnum() { + static_assert(std::is_enum_v<T>, "T must be an enum type within a PopEnum call."); + static_assert(!std::is_convertible_v<T, int>, + "enum type in PopEnum must be a strongly typed enum."); + return static_cast<T>(Pop<std::underlying_type_t<T>>()); + } + + /** + * @brief Reads the next normal parameters as a struct, by copying it + * @note: The output class must be correctly packed/padded to fit hardware layout. + */ + template <typename T> + void PopRaw(T& value); + + /** + * @brief Reads the next normal parameters as a struct, by copying it into a new value + * @note: The output class must be correctly packed/padded to fit hardware layout. + */ + template <typename T> + T PopRaw(); + + template <class T> + std::weak_ptr<T> PopIpcInterface() { + ASSERT(context->GetManager()->IsDomain()); + ASSERT(context->GetDomainMessageHeader().input_object_count > 0); + return context->GetDomainHandler<T>(Pop<u32>() - 1); + } +}; + +/// Pop /// + +template <> +inline u32 RequestParser::Pop() { + return cmdbuf[index++]; +} + +template <> +inline s32 RequestParser::Pop() { + return static_cast<s32>(Pop<u32>()); +} + +// Ignore the -Wclass-memaccess warning on memcpy for non-trivially default constructible objects. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif +template <typename T> +void RequestParser::PopRaw(T& value) { + static_assert(std::is_trivially_copyable_v<T>, + "It's undefined behavior to use memcpy with non-trivially copyable objects"); + std::memcpy(&value, cmdbuf + index, sizeof(T)); + index += (sizeof(T) + 3) / 4; // round up to word length +} +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic pop +#endif + +template <typename T> +T RequestParser::PopRaw() { + T value; + PopRaw(value); + return value; +} + +template <> +inline u8 RequestParser::Pop() { + return PopRaw<u8>(); +} + +template <> +inline u16 RequestParser::Pop() { + return PopRaw<u16>(); +} + +template <> +inline u64 RequestParser::Pop() { + const u64 lsw = Pop<u32>(); + const u64 msw = Pop<u32>(); + return msw << 32 | lsw; +} + +template <> +inline s8 RequestParser::Pop() { + return static_cast<s8>(Pop<u8>()); +} + +template <> +inline s16 RequestParser::Pop() { + return static_cast<s16>(Pop<u16>()); +} + +template <> +inline s64 RequestParser::Pop() { + return static_cast<s64>(Pop<u64>()); +} + +template <> +inline float RequestParser::Pop() { + const u32 value = Pop<u32>(); + float real; + std::memcpy(&real, &value, sizeof(real)); + return real; +} + +template <> +inline double RequestParser::Pop() { + const u64 value = Pop<u64>(); + double real; + std::memcpy(&real, &value, sizeof(real)); + return real; +} + +template <> +inline bool RequestParser::Pop() { + return Pop<u8>() != 0; +} + +template <> +inline Result RequestParser::Pop() { + return Result{Pop<u32>()}; +} + +template <typename T> +void RequestParser::Pop(T& value) { + value = Pop<T>(); +} + +template <typename First, typename... Other> +void RequestParser::Pop(First& first_value, Other&... other_values) { + first_value = Pop<First>(); + Pop(other_values...); +} + +} // namespace IPC diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 8f2920c51..be996870f 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -3,12 +3,13 @@ #include "core/arm/symbols.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_code_memory.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/result.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/jit/jit.h" #include "core/hle/service/jit/jit_context.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/memory.h" @@ -23,8 +24,8 @@ class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { public: explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, CodeRange user_ro) - : ServiceFramework{system_, "IJitEnvironment", ServiceThreadType::CreateNew}, - process{&process_}, context{system_.Memory()} { + : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, + context{system_.ApplicationMemory()} { // clang-format off static const FunctionInfo functions[] = { {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, @@ -43,7 +44,7 @@ public: configuration.sys_rx_memory = user_rx; } - void GenerateCode(Kernel::HLERequestContext& ctx) { + void GenerateCode(HLERequestContext& ctx) { LOG_DEBUG(Service_JIT, "called"); struct InputParameters { @@ -62,7 +63,7 @@ public: const auto parameters{rp.PopRaw<InputParameters>()}; // Optional input/output buffers - std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; + const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()}; std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); // Function call prototype: @@ -125,14 +126,14 @@ public: } }; - void Control(Kernel::HLERequestContext& ctx) { + void Control(HLERequestContext& ctx) { LOG_DEBUG(Service_JIT, "called"); IPC::RequestParser rp{ctx}; const auto command{rp.PopRaw<u64>()}; // Optional input/output buffers - std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; + const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()}; std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); // Function call prototype: @@ -170,7 +171,7 @@ public: } } - void LoadPlugin(Kernel::HLERequestContext& ctx) { + void LoadPlugin(HLERequestContext& ctx) { LOG_DEBUG(Service_JIT, "called"); IPC::RequestParser rp{ctx}; @@ -194,7 +195,7 @@ public: } // Set up the configuration with the required TransferMemory address - configuration.transfer_memory.offset = tmem->GetSourceAddress(); + configuration.transfer_memory.offset = GetInteger(tmem->GetSourceAddress()); configuration.transfer_memory.size = tmem_size; // Gather up all the callbacks from the loaded plugin @@ -276,7 +277,7 @@ public: rb.Push(ResultSuccess); } - void GetCodeAddress(Kernel::HLERequestContext& ctx) { + void GetCodeAddress(HLERequestContext& ctx) { LOG_DEBUG(Service_JIT, "called"); IPC::ResponseBuilder rb{ctx, 6}; @@ -332,7 +333,7 @@ public: RegisterHandlers(functions); } - void CreateJitEnvironment(Kernel::HLERequestContext& ctx) { + void CreateJitEnvironment(HLERequestContext& ctx) { LOG_DEBUG(Service_JIT, "called"); struct Parameters { @@ -353,9 +354,9 @@ public: return; } - // Fetch using the handle table for the current process here, + // Fetch using the handle table for the application process here, // since we are not multiprocess yet. - const auto& handle_table{system.CurrentProcess()->GetHandleTable()}; + const auto& handle_table{system.ApplicationProcess()->GetHandleTable()}; auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)}; if (process.IsNull()) { @@ -382,12 +383,12 @@ public: } const CodeRange user_rx{ - .offset = rx_mem->GetSourceAddress(), + .offset = GetInteger(rx_mem->GetSourceAddress()), .size = parameters.rx_size, }; const CodeRange user_ro{ - .offset = ro_mem->GetSourceAddress(), + .offset = GetInteger(ro_mem->GetSourceAddress()), .size = parameters.ro_size, }; @@ -397,8 +398,11 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<JITU>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("jit:u", std::make_shared<JITU>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::JIT diff --git a/src/core/hle/service/jit/jit.h b/src/core/hle/service/jit/jit.h index af0f5b4f3..19014c75a 100644 --- a/src/core/hle/service/jit/jit.h +++ b/src/core/hle/service/jit/jit.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::JIT { -/// Registers all JIT services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::JIT diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index 42991928e..6a313a03b 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -15,17 +15,27 @@ namespace Service::KernelHelpers { ServiceContext::ServiceContext(Core::System& system_, std::string name_) : kernel(system_.Kernel()) { + if (process = Kernel::GetCurrentProcessPointer(kernel); process != nullptr) { + return; + } + // Create the process. process = Kernel::KProcess::Create(kernel); ASSERT(Kernel::KProcess::Initialize(process, system_, std::move(name_), Kernel::KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()) .IsSuccess()); + + // Register the process. + Kernel::KProcess::Register(kernel, process); + process_created = true; } ServiceContext::~ServiceContext() { - process->Close(); - process = nullptr; + if (process_created) { + process->Close(); + process = nullptr; + } } Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { diff --git a/src/core/hle/service/kernel_helpers.h b/src/core/hle/service/kernel_helpers.h index 6415838e5..eca9aefb5 100644 --- a/src/core/hle/service/kernel_helpers.h +++ b/src/core/hle/service/kernel_helpers.h @@ -29,6 +29,7 @@ public: private: Kernel::KernelCore& kernel; Kernel::KProcess* process{}; + bool process_created{false}; }; } // namespace Service::KernelHelpers diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp index c8415e0bf..98a79365d 100644 --- a/src/core/hle/service/lbl/lbl.cpp +++ b/src/core/hle/service/lbl/lbl.cpp @@ -5,8 +5,9 @@ #include <memory> #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/lbl/lbl.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -59,7 +60,7 @@ private: On = 1, }; - void SetCurrentBrightnessSetting(Kernel::HLERequestContext& ctx) { + void SetCurrentBrightnessSetting(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto brightness = rp.Pop<float>(); @@ -77,7 +78,7 @@ private: rb.Push(ResultSuccess); } - void GetCurrentBrightnessSetting(Kernel::HLERequestContext& ctx) { + void GetCurrentBrightnessSetting(HLERequestContext& ctx) { auto brightness = current_brightness; if (!std::isfinite(brightness)) { LOG_ERROR(Service_LBL, "Brightness is infinite!"); @@ -91,7 +92,7 @@ private: rb.Push(brightness); } - void SwitchBacklightOn(Kernel::HLERequestContext& ctx) { + void SwitchBacklightOn(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto fade_time = rp.Pop<u64_le>(); LOG_WARNING(Service_LBL, "(STUBBED) called, fade_time={}", fade_time); @@ -102,7 +103,7 @@ private: rb.Push(ResultSuccess); } - void SwitchBacklightOff(Kernel::HLERequestContext& ctx) { + void SwitchBacklightOff(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto fade_time = rp.Pop<u64_le>(); LOG_WARNING(Service_LBL, "(STUBBED) called, fade_time={}", fade_time); @@ -113,7 +114,7 @@ private: rb.Push(ResultSuccess); } - void GetBacklightSwitchStatus(Kernel::HLERequestContext& ctx) { + void GetBacklightSwitchStatus(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -122,7 +123,7 @@ private: : BacklightSwitchStatus::Off); } - void EnableDimming(Kernel::HLERequestContext& ctx) { + void EnableDimming(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); dimming = true; @@ -131,7 +132,7 @@ private: rb.Push(ResultSuccess); } - void DisableDimming(Kernel::HLERequestContext& ctx) { + void DisableDimming(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); dimming = false; @@ -140,7 +141,7 @@ private: rb.Push(ResultSuccess); } - void IsDimmingEnabled(Kernel::HLERequestContext& ctx) { + void IsDimmingEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -148,7 +149,7 @@ private: rb.Push(dimming); } - void EnableAutoBrightnessControl(Kernel::HLERequestContext& ctx) { + void EnableAutoBrightnessControl(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); auto_brightness = true; update_instantly = true; @@ -157,7 +158,7 @@ private: rb.Push(ResultSuccess); } - void DisableAutoBrightnessControl(Kernel::HLERequestContext& ctx) { + void DisableAutoBrightnessControl(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); auto_brightness = false; @@ -165,7 +166,7 @@ private: rb.Push(ResultSuccess); } - void IsAutoBrightnessControlEnabled(Kernel::HLERequestContext& ctx) { + void IsAutoBrightnessControlEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -173,7 +174,7 @@ private: rb.Push(auto_brightness); } - void SetAmbientLightSensorValue(Kernel::HLERequestContext& ctx) { + void SetAmbientLightSensorValue(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto light_value = rp.Pop<float>(); @@ -185,7 +186,7 @@ private: rb.Push(ResultSuccess); } - void GetAmbientLightSensorValue(Kernel::HLERequestContext& ctx) { + void GetAmbientLightSensorValue(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -193,7 +194,7 @@ private: rb.Push(ambient_light_value); } - void SetBrightnessReflectionDelayLevel(Kernel::HLERequestContext& ctx) { + void SetBrightnessReflectionDelayLevel(HLERequestContext& ctx) { // This is Intentional, this function does absolutely nothing LOG_DEBUG(Service_LBL, "called"); @@ -201,7 +202,7 @@ private: rb.Push(ResultSuccess); } - void GetBrightnessReflectionDelayLevel(Kernel::HLERequestContext& ctx) { + void GetBrightnessReflectionDelayLevel(HLERequestContext& ctx) { // This is intentional, the function is hard coded to return 0.0f on hardware LOG_DEBUG(Service_LBL, "called"); @@ -210,7 +211,7 @@ private: rb.Push(0.0f); } - void SetCurrentBrightnessMapping(Kernel::HLERequestContext& ctx) { + void SetCurrentBrightnessMapping(HLERequestContext& ctx) { // This is Intentional, this function does absolutely nothing LOG_DEBUG(Service_LBL, "called"); @@ -218,7 +219,7 @@ private: rb.Push(ResultSuccess); } - void GetCurrentBrightnessMapping(Kernel::HLERequestContext& ctx) { + void GetCurrentBrightnessMapping(HLERequestContext& ctx) { // This is Intentional, this function does absolutely nothing LOG_DEBUG(Service_LBL, "called"); @@ -227,7 +228,7 @@ private: // This function is suppose to return something but it seems like it doesn't } - void SetCurrentAmbientLightSensorMapping(Kernel::HLERequestContext& ctx) { + void SetCurrentAmbientLightSensorMapping(HLERequestContext& ctx) { // This is Intentional, this function does absolutely nothing LOG_DEBUG(Service_LBL, "called"); @@ -235,7 +236,7 @@ private: rb.Push(ResultSuccess); } - void GetCurrentAmbientLightSensorMapping(Kernel::HLERequestContext& ctx) { + void GetCurrentAmbientLightSensorMapping(HLERequestContext& ctx) { // This is Intentional, this function does absolutely nothing LOG_DEBUG(Service_LBL, "called"); @@ -244,7 +245,7 @@ private: // This function is suppose to return something but it seems like it doesn't } - void IsAmbientLightSensorAvailable(Kernel::HLERequestContext& ctx) { + void IsAmbientLightSensorAvailable(HLERequestContext& ctx) { LOG_WARNING(Service_LBL, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -252,7 +253,7 @@ private: rb.Push(true); } - void SetCurrentBrightnessSettingForVrMode(Kernel::HLERequestContext& ctx) { + void SetCurrentBrightnessSettingForVrMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto brightness = rp.Pop<float>(); @@ -269,7 +270,7 @@ private: rb.Push(ResultSuccess); } - void GetCurrentBrightnessSettingForVrMode(Kernel::HLERequestContext& ctx) { + void GetCurrentBrightnessSettingForVrMode(HLERequestContext& ctx) { auto brightness = current_vr_brightness; if (!std::isfinite(brightness)) { LOG_ERROR(Service_LBL, "Brightness is infinite!"); @@ -283,7 +284,7 @@ private: rb.Push(brightness); } - void EnableVrMode(Kernel::HLERequestContext& ctx) { + void EnableVrMode(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -292,7 +293,7 @@ private: vr_mode_enabled = true; } - void DisableVrMode(Kernel::HLERequestContext& ctx) { + void DisableVrMode(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -301,7 +302,7 @@ private: vr_mode_enabled = false; } - void IsVrModeEnabled(Kernel::HLERequestContext& ctx) { + void IsVrModeEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_LBL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -319,8 +320,11 @@ private: bool auto_brightness = false; // TODO(ogniK): Move to system settings }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<LBL>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("lbl", std::make_shared<LBL>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::LBL diff --git a/src/core/hle/service/lbl/lbl.h b/src/core/hle/service/lbl/lbl.h index 6484105c2..e47759c01 100644 --- a/src/core/hle/service/lbl/lbl.h +++ b/src/core/hle/service/lbl/lbl.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::LBL { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::LBL diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index c49c61cff..9d149a7cd 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -8,6 +8,7 @@ #include "core/hle/service/ldn/ldn.h" #include "core/hle/service/ldn/ldn_results.h" #include "core/hle/service/ldn/ldn_types.h" +#include "core/hle/service/server_manager.h" #include "core/internal_network/network.h" #include "core/internal_network/network_interface.h" #include "network/network.h" @@ -49,7 +50,7 @@ public: RegisterHandlers(functions); } - void CreateMonitorService(Kernel::HLERequestContext& ctx) { + void CreateMonitorService(HLERequestContext& ctx) { LOG_DEBUG(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -106,7 +107,7 @@ class IUserLocalCommunicationService final : public ServiceFramework<IUserLocalCommunicationService> { public: explicit IUserLocalCommunicationService(Core::System& system_) - : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew}, + : ServiceFramework{system_, "IUserLocalCommunicationService"}, service_context{system, "IUserLocalCommunicationService"}, room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} { // clang-format off @@ -168,7 +169,7 @@ public: state_change_event->Signal(); } - void GetState(Kernel::HLERequestContext& ctx) { + void GetState(HLERequestContext& ctx) { State state = State::Error; if (is_initialized) { @@ -180,7 +181,7 @@ public: rb.PushEnum(state); } - void GetNetworkInfo(Kernel::HLERequestContext& ctx) { + void GetNetworkInfo(HLERequestContext& ctx) { const auto write_buffer_size = ctx.GetWriteBufferSize(); if (write_buffer_size != sizeof(NetworkInfo)) { @@ -204,7 +205,7 @@ public: rb.Push(ResultSuccess); } - void GetIpv4Address(Kernel::HLERequestContext& ctx) { + void GetIpv4Address(HLERequestContext& ctx) { const auto network_interface = Network::GetSelectedNetworkInterface(); if (!network_interface) { @@ -233,13 +234,13 @@ public: rb.PushRaw(subnet_mask); } - void GetDisconnectReason(Kernel::HLERequestContext& ctx) { + void GetDisconnectReason(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.PushEnum(lan_discovery.GetDisconnectReason()); } - void GetSecurityParameter(Kernel::HLERequestContext& ctx) { + void GetSecurityParameter(HLERequestContext& ctx) { SecurityParameter security_parameter{}; NetworkInfo info{}; const Result rc = lan_discovery.GetNetworkInfo(info); @@ -260,7 +261,7 @@ public: rb.PushRaw<SecurityParameter>(security_parameter); } - void GetNetworkConfig(Kernel::HLERequestContext& ctx) { + void GetNetworkConfig(HLERequestContext& ctx) { NetworkConfig config{}; NetworkInfo info{}; const Result rc = lan_discovery.GetNetworkInfo(info); @@ -282,7 +283,7 @@ public: rb.PushRaw<NetworkConfig>(config); } - void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) { + void AttachStateChangeEvent(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -290,7 +291,7 @@ public: rb.PushCopyObjects(state_change_event->GetReadableEvent()); } - void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) { + void GetNetworkInfoLatestUpdate(HLERequestContext& ctx) { const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0); const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1); @@ -320,15 +321,15 @@ public: rb.Push(ResultSuccess); } - void Scan(Kernel::HLERequestContext& ctx) { + void Scan(HLERequestContext& ctx) { ScanImpl(ctx); } - void ScanPrivate(Kernel::HLERequestContext& ctx) { + void ScanPrivate(HLERequestContext& ctx) { ScanImpl(ctx, true); } - void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) { + void ScanImpl(HLERequestContext& ctx, bool is_private = false) { IPC::RequestParser rp{ctx}; const auto channel{rp.PopEnum<WifiChannel>()}; const auto scan_filter{rp.PopRaw<ScanFilter>()}; @@ -357,40 +358,40 @@ public: rb.Push<u32>(count); } - void SetWirelessControllerRestriction(Kernel::HLERequestContext& ctx) { + void SetWirelessControllerRestriction(HLERequestContext& ctx) { LOG_WARNING(Service_LDN, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void OpenAccessPoint(Kernel::HLERequestContext& ctx) { + void OpenAccessPoint(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.OpenAccessPoint()); } - void CloseAccessPoint(Kernel::HLERequestContext& ctx) { + void CloseAccessPoint(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.CloseAccessPoint()); } - void CreateNetwork(Kernel::HLERequestContext& ctx) { + void CreateNetwork(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); CreateNetworkImpl(ctx); } - void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) { + void CreateNetworkPrivate(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); CreateNetworkImpl(ctx, true); } - void CreateNetworkImpl(Kernel::HLERequestContext& ctx, bool is_private = false) { + void CreateNetworkImpl(HLERequestContext& ctx, bool is_private = false) { IPC::RequestParser rp{ctx}; const auto security_config{rp.PopRaw<SecurityConfig>()}; @@ -404,49 +405,49 @@ public: rb.Push(lan_discovery.CreateNetwork(security_config, user_config, network_Config)); } - void DestroyNetwork(Kernel::HLERequestContext& ctx) { + void DestroyNetwork(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.DestroyNetwork()); } - void SetAdvertiseData(Kernel::HLERequestContext& ctx) { - std::vector<u8> read_buffer = ctx.ReadBuffer(); + void SetAdvertiseData(HLERequestContext& ctx) { + const auto read_buffer = ctx.ReadBuffer(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.SetAdvertiseData(read_buffer)); } - void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) { + void SetStationAcceptPolicy(HLERequestContext& ctx) { LOG_WARNING(Service_LDN, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) { + void AddAcceptFilterEntry(HLERequestContext& ctx) { LOG_WARNING(Service_LDN, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void OpenStation(Kernel::HLERequestContext& ctx) { + void OpenStation(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.OpenStation()); } - void CloseStation(Kernel::HLERequestContext& ctx) { + void CloseStation(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.CloseStation()); } - void Connect(Kernel::HLERequestContext& ctx) { + void Connect(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { SecurityConfig security_config; @@ -464,7 +465,7 @@ public: parameters.security_config.passphrase_size, parameters.security_config.security_mode, parameters.local_communication_version); - const std::vector<u8> read_buffer = ctx.ReadBuffer(); + const auto read_buffer = ctx.ReadBuffer(); if (read_buffer.size() != sizeof(NetworkInfo)) { LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!"); IPC::ResponseBuilder rb{ctx, 2}; @@ -480,14 +481,14 @@ public: static_cast<u16>(parameters.local_communication_version))); } - void Disconnect(Kernel::HLERequestContext& ctx) { + void Disconnect(HLERequestContext& ctx) { LOG_INFO(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.Disconnect()); } - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { const auto rc = InitializeImpl(ctx); if (rc.IsError()) { LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw); @@ -497,7 +498,7 @@ public: rb.Push(rc); } - void Finalize(Kernel::HLERequestContext& ctx) { + void Finalize(HLERequestContext& ctx) { if (auto room_member = room_network.GetRoomMember().lock()) { room_member->Unbind(ldn_packet_received); } @@ -508,7 +509,7 @@ public: rb.Push(lan_discovery.Finalize()); } - void Initialize2(Kernel::HLERequestContext& ctx) { + void Initialize2(HLERequestContext& ctx) { const auto rc = InitializeImpl(ctx); if (rc.IsError()) { LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw); @@ -518,7 +519,7 @@ public: rb.Push(rc); } - Result InitializeImpl(Kernel::HLERequestContext& ctx) { + Result InitializeImpl(HLERequestContext& ctx) { const auto network_interface = Network::GetSelectedNetworkInterface(); if (!network_interface) { LOG_ERROR(Service_LDN, "No network interface is set"); @@ -561,7 +562,7 @@ public: RegisterHandlers(functions); } - void CreateSystemLocalCommunicationService(Kernel::HLERequestContext& ctx) { + void CreateSystemLocalCommunicationService(HLERequestContext& ctx) { LOG_DEBUG(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -582,7 +583,7 @@ public: RegisterHandlers(functions); } - void CreateUserLocalCommunicationService(Kernel::HLERequestContext& ctx) { + void CreateUserLocalCommunicationService(HLERequestContext& ctx) { LOG_DEBUG(Service_LDN, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -646,7 +647,7 @@ public: RegisterHandlers(functions); } - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { LOG_WARNING(Service_LDN, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -667,7 +668,7 @@ public: RegisterHandlers(functions); } - void CreateNetworkervice(Kernel::HLERequestContext& ctx) { + void CreateNetworkervice(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 reserved_input = rp.Pop<u64>(); const u32 input = rp.Pop<u32>(); @@ -680,7 +681,7 @@ public: rb.PushIpcInterface<INetworkService>(system); } - void CreateMonitorService(Kernel::HLERequestContext& ctx) { + void CreateMonitorService(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 reserved_input = rp.Pop<u64>(); @@ -705,7 +706,7 @@ public: RegisterHandlers(functions); } - void CreateNetworkervice(Kernel::HLERequestContext& ctx) { + void CreateNetworkervice(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 reserved_input = rp.Pop<u64>(); const u32 input = rp.Pop<u32>(); @@ -718,7 +719,7 @@ public: rb.PushIpcInterface<INetworkService>(system); } - void CreateMonitorService(Kernel::HLERequestContext& ctx) { + void CreateMonitorService(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 reserved_input = rp.Pop<u64>(); @@ -730,12 +731,15 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<LDNM>(system)->InstallAsService(sm); - std::make_shared<LDNS>(system)->InstallAsService(sm); - std::make_shared<LDNU>(system)->InstallAsService(sm); - std::make_shared<LP2PAPP>(system)->InstallAsService(sm); - std::make_shared<LP2PSYS>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system)); + server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system)); + server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system)); + server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system)); + server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::LDN diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h index 6afe2ea6f..f4a319168 100644 --- a/src/core/hle/service/ldn/ldn.h +++ b/src/core/hle/service/ldn/ldn.h @@ -3,9 +3,9 @@ #pragma once -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/result.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/sm/sm.h" @@ -13,13 +13,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::LDN { -/// Registers all LDN services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::LDN diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 652441bc2..c42489ff9 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -9,11 +9,12 @@ #include "common/hex_util.h" #include "common/scope_exit.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_types.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ldr/ldr.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/loader/nro.h" #include "core/memory.h" @@ -159,8 +160,7 @@ public: class RelocatableObject final : public ServiceFramework<RelocatableObject> { public: - explicit RelocatableObject(Core::System& system_) - : ServiceFramework{system_, "ldr:ro", ServiceThreadType::CreateNew} { + explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} { // clang-format off static const FunctionInfo functions[] = { {0, &RelocatableObject::LoadModule, "LoadModule"}, @@ -175,7 +175,7 @@ public: RegisterHandlers(functions); } - void RegisterModuleInfo(Kernel::HLERequestContext& ctx) { + void RegisterModuleInfo(HLERequestContext& ctx) { struct Parameters { u64_le process_id; u64_le nrr_address; @@ -225,7 +225,7 @@ public: // Read NRR data from memory std::vector<u8> nrr_data(nrr_size); - system.Memory().ReadBlock(nrr_address, nrr_data.data(), nrr_size); + system.ApplicationMemory().ReadBlock(nrr_address, nrr_data.data(), nrr_size); NRRHeader header; std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader)); @@ -246,7 +246,7 @@ public: return; } - if (system.GetCurrentProcessProgramID() != header.application_id) { + if (system.GetApplicationProcessProgramID() != header.application_id) { LOG_ERROR(Service_LDR, "Attempting to load NRR with title ID other than current process. (actual " "{:016X})!", @@ -272,7 +272,7 @@ public: rb.Push(ResultSuccess); } - void UnregisterModuleInfo(Kernel::HLERequestContext& ctx) { + void UnregisterModuleInfo(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto pid = rp.Pop<u64>(); const auto nrr_address = rp.Pop<VAddr>(); @@ -314,7 +314,7 @@ public: const auto is_region_available = [&](VAddr addr) { const auto end_addr = addr + size; while (addr < end_addr) { - if (system.Memory().IsValidVirtualAddress(addr)) { + if (system.ApplicationMemory().IsValidVirtualAddress(addr)) { return false; } @@ -337,7 +337,7 @@ public: bool succeeded = false; const auto map_region_end = - page_table.GetAliasCodeRegionStart() + page_table.GetAliasCodeRegionSize(); + GetInteger(page_table.GetAliasCodeRegionStart()) + page_table.GetAliasCodeRegionSize(); while (current_map_addr < map_region_end) { if (is_region_available(current_map_addr)) { succeeded = true; @@ -427,8 +427,8 @@ public: const VAddr bss_end_addr{ Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)}; - const auto CopyCode = [this, process](VAddr src_addr, VAddr dst_addr, u64 size) { - system.Memory().CopyBlock(*process, dst_addr, src_addr, size); + const auto CopyCode = [this](VAddr src_addr, VAddr dst_addr, u64 size) { + system.ApplicationMemory().CopyBlock(dst_addr, src_addr, size); }; CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start, nro_header.segment_headers[TEXT_INDEX].memory_size); @@ -446,7 +446,7 @@ public: data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite); } - void LoadModule(Kernel::HLERequestContext& ctx) { + void LoadModule(HLERequestContext& ctx) { struct Parameters { u64_le process_id; u64_le image_address; @@ -506,7 +506,7 @@ public: // Read NRO data from memory std::vector<u8> nro_data(nro_size); - system.Memory().ReadBlock(nro_address, nro_data.data(), nro_size); + system.ApplicationMemory().ReadBlock(nro_address, nro_data.data(), nro_size); SHA256Hash hash{}; mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0); @@ -542,15 +542,16 @@ public: } // Map memory for the NRO - const auto map_result{MapNro(system.CurrentProcess(), nro_address, nro_size, bss_address, - bss_size, nro_size + bss_size)}; + const auto map_result{MapNro(system.ApplicationProcess(), nro_address, nro_size, + bss_address, bss_size, nro_size + bss_size)}; if (map_result.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(map_result.Code()); } // Load the NRO into the mapped memory - if (const auto result{LoadNro(system.CurrentProcess(), header, nro_address, *map_result)}; + if (const auto result{ + LoadNro(system.ApplicationProcess(), header, nro_address, *map_result)}; result.IsError()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(map_result.Code()); @@ -570,7 +571,7 @@ public: Result UnmapNro(const NROInfo& info) { // Each region must be unmapped separately to validate memory state - auto& page_table{system.CurrentProcess()->PageTable()}; + auto& page_table{system.ApplicationProcess()->PageTable()}; if (info.bss_size != 0) { CASCADE_CODE(page_table.UnmapCodeMemory( @@ -591,7 +592,7 @@ public: return ResultSuccess; } - void UnloadModule(Kernel::HLERequestContext& ctx) { + void UnloadModule(HLERequestContext& ctx) { if (!initialized) { LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!"); IPC::ResponseBuilder rb{ctx, 2}; @@ -637,11 +638,12 @@ public: rb.Push(result); } - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { LOG_WARNING(Service_LDR, "(STUBBED) called"); initialized = true; - current_map_addr = system.CurrentProcess()->PageTable().GetAliasCodeRegionStart(); + current_map_addr = + GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -681,11 +683,15 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<DebugMonitor>(system)->InstallAsService(sm); - std::make_shared<ProcessManager>(system)->InstallAsService(sm); - std::make_shared<Shell>(system)->InstallAsService(sm); - std::make_shared<RelocatableObject>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("ldr:dmnt", std::make_shared<DebugMonitor>(system)); + server_manager->RegisterNamedService("ldr:pm", std::make_shared<ProcessManager>(system)); + server_manager->RegisterNamedService("ldr:shel", std::make_shared<Shell>(system)); + server_manager->RegisterNamedService("ldr:ro", std::make_shared<RelocatableObject>(system)); + + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::LDR diff --git a/src/core/hle/service/ldr/ldr.h b/src/core/hle/service/ldr/ldr.h index 25ffd8442..c9281dbfb 100644 --- a/src/core/hle/service/ldr/ldr.h +++ b/src/core/hle/service/ldr/ldr.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::LDR { -/// Registers all LDR services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::LDR diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index ef4b54046..20df00233 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -8,8 +8,9 @@ #include <boost/container_hash/hash.hpp> #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/lm/lm.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::LM { @@ -92,7 +93,7 @@ public: } private: - void Log(Kernel::HLERequestContext& ctx) { + void Log(HLERequestContext& ctx) { std::size_t offset{}; const auto data = ctx.ReadBuffer(); @@ -147,7 +148,7 @@ private: } } - void SetDestination(Kernel::HLERequestContext& ctx) { + void SetDestination(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto log_destination = rp.PopEnum<LogDestination>(); @@ -342,7 +343,7 @@ public: } private: - void OpenLogger(Kernel::HLERequestContext& ctx) { + void OpenLogger(HLERequestContext& ctx) { LOG_DEBUG(Service_LM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -351,8 +352,11 @@ private: } }; -void InstallInterfaces(Core::System& system) { - std::make_shared<LM>(system)->InstallAsService(system.ServiceManager()); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("lm", std::make_shared<LM>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::LM diff --git a/src/core/hle/service/lm/lm.h b/src/core/hle/service/lm/lm.h index 266019c30..0d7c39cbc 100644 --- a/src/core/hle/service/lm/lm.h +++ b/src/core/hle/service/lm/lm.h @@ -9,7 +9,6 @@ class System; namespace Service::LM { -/// Registers all LM services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::LM diff --git a/src/core/hle/service/mig/mig.cpp b/src/core/hle/service/mig/mig.cpp index b9fe0cecd..082e470ab 100644 --- a/src/core/hle/service/mig/mig.cpp +++ b/src/core/hle/service/mig/mig.cpp @@ -4,8 +4,8 @@ #include <memory> #include "core/hle/service/mig/mig.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::Migration { @@ -32,8 +32,11 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<MIG_USR>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("mig:user", std::make_shared<MIG_USR>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Migration diff --git a/src/core/hle/service/mig/mig.h b/src/core/hle/service/mig/mig.h index f1641a521..c8ed732a5 100644 --- a/src/core/hle/service/mig/mig.h +++ b/src/core/hle/service/mig/mig.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::Migration { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Migration diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 390514fdc..5c7adf97d 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -4,11 +4,11 @@ #include <memory> #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/mii/mii.h" #include "core/hle/service/mii/mii_manager.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::Mii { @@ -65,7 +65,7 @@ private: return out; } - void IsUpdated(Kernel::HLERequestContext& ctx) { + void IsUpdated(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto source_flag{rp.PopRaw<SourceFlag>()}; @@ -76,7 +76,7 @@ private: rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter)); } - void IsFullDatabase(Kernel::HLERequestContext& ctx) { + void IsFullDatabase(HLERequestContext& ctx) { LOG_DEBUG(Service_Mii, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -84,7 +84,7 @@ private: rb.Push(manager.IsFullDatabase()); } - void GetCount(Kernel::HLERequestContext& ctx) { + void GetCount(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto source_flag{rp.PopRaw<SourceFlag>()}; @@ -95,7 +95,7 @@ private: rb.Push<u32>(manager.GetCount(source_flag)); } - void Get(Kernel::HLERequestContext& ctx) { + void Get(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto source_flag{rp.PopRaw<SourceFlag>()}; @@ -117,7 +117,7 @@ private: rb.Push<u32>(static_cast<u32>(result->size())); } - void Get1(Kernel::HLERequestContext& ctx) { + void Get1(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto source_flag{rp.PopRaw<SourceFlag>()}; @@ -142,7 +142,7 @@ private: rb.Push<u32>(static_cast<u32>(result->size())); } - void UpdateLatest(Kernel::HLERequestContext& ctx) { + void UpdateLatest(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto info{rp.PopRaw<CharInfo>()}; const auto source_flag{rp.PopRaw<SourceFlag>()}; @@ -161,7 +161,7 @@ private: rb.PushRaw<CharInfo>(*result); } - void BuildRandom(Kernel::HLERequestContext& ctx) { + void BuildRandom(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto age{rp.PopRaw<Age>()}; @@ -196,7 +196,7 @@ private: rb.PushRaw<CharInfo>(manager.BuildRandom(age, gender, race)); } - void BuildDefault(Kernel::HLERequestContext& ctx) { + void BuildDefault(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto index{rp.Pop<u32>()}; @@ -215,7 +215,7 @@ private: rb.PushRaw<CharInfo>(manager.BuildDefault(index)); } - void GetIndex(Kernel::HLERequestContext& ctx) { + void GetIndex(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto info{rp.PopRaw<CharInfo>()}; @@ -227,7 +227,7 @@ private: rb.Push(index); } - void SetInterfaceVersion(Kernel::HLERequestContext& ctx) { + void SetInterfaceVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; current_interface_version = rp.PopRaw<u32>(); @@ -239,7 +239,7 @@ private: rb.Push(ResultSuccess); } - void Convert(Kernel::HLERequestContext& ctx) { + void Convert(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto mii_v3{rp.PopRaw<Ver3StoreData>()}; @@ -275,7 +275,7 @@ public: } private: - void GetDatabaseService(Kernel::HLERequestContext& ctx) { + void GetDatabaseService(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IDatabaseService>(system); @@ -310,11 +310,13 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<MiiDBModule>(system, "mii:e")->InstallAsService(sm); - std::make_shared<MiiDBModule>(system, "mii:u")->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); - std::make_shared<MiiImg>(system)->InstallAsService(sm); + server_manager->RegisterNamedService("mii:e", std::make_shared<MiiDBModule>(system, "mii:e")); + server_manager->RegisterNamedService("mii:u", std::make_shared<MiiDBModule>(system, "mii:u")); + server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Mii diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h index 009d80d58..ed4e3f62b 100644 --- a/src/core/hle/service/mii/mii.h +++ b/src/core/hle/service/mii/mii.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::Mii { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Mii diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 3a2fe938f..c920650f5 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -510,7 +510,7 @@ CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { return mii; } -Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { +Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const { Service::Mii::MiiManager manager; Ver3StoreData mii_v3{}; @@ -534,16 +534,13 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.region_information.character_set.Assign(mii.font_region); mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type); - mii_v3.appearance_bits1.skin_color.Assign(mii.faceline_color); mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle); mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make); mii_v3.hair_style = mii.hair_type; - mii_v3.appearance_bits3.hair_color.Assign(mii.hair_color); mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip); mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type); - mii_v3.appearance_bits4.eye_color.Assign(mii.eye_color); mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale); mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect); mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate); @@ -551,7 +548,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y); mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type); - mii_v3.appearance_bits5.eyebrow_color.Assign(mii.eyebrow_color); mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale); mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect); mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate); @@ -563,7 +559,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y); mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type); - mii_v3.appearance_bits7.mouth_color.Assign(mii.mouth_color); mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale); mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect); mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y); @@ -573,10 +568,7 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y); mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type); - mii_v3.appearance_bits9.facial_hair_color.Assign(mii.beard_color); - mii_v3.appearance_bits10.glasses_type.Assign(mii.glasses_type); - mii_v3.appearance_bits10.glasses_color.Assign(mii.glasses_color); mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale); mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y); @@ -585,11 +577,36 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x); mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y); + // These types are converted to V3 from a table + mii_v3.appearance_bits1.skin_color.Assign(Ver3FacelineColorTable[mii.faceline_color]); + mii_v3.appearance_bits3.hair_color.Assign(Ver3HairColorTable[mii.hair_color]); + mii_v3.appearance_bits4.eye_color.Assign(Ver3EyeColorTable[mii.eye_color]); + mii_v3.appearance_bits5.eyebrow_color.Assign(Ver3HairColorTable[mii.eyebrow_color]); + mii_v3.appearance_bits7.mouth_color.Assign(Ver3MouthlineColorTable[mii.mouth_color]); + mii_v3.appearance_bits9.facial_hair_color.Assign(Ver3HairColorTable[mii.beard_color]); + mii_v3.appearance_bits10.glasses_color.Assign(Ver3GlassColorTable[mii.glasses_color]); + mii_v3.appearance_bits10.glasses_type.Assign(Ver3GlassTypeTable[mii.glasses_type]); + + mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16)); + // TODO: Validate mii_v3 data return mii_v3; } +NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { + return { + .faceline_color = static_cast<u8>(mii.faceline_color & 0xf), + .hair_color = static_cast<u8>(mii.hair_color & 0x7f), + .eye_color = static_cast<u8>(mii.eyebrow_color & 0x7f), + .eyebrow_color = static_cast<u8>(mii.eyebrow_color & 0x7f), + .mouth_color = static_cast<u8>(mii.mouth_color & 0x7f), + .beard_color = static_cast<u8>(mii.beard_color & 0x7f), + .glass_color = static_cast<u8>(mii.glasses_color & 0x7f), + .glass_type = static_cast<u8>(mii.glasses_type & 0x1f), + }; +} + bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { bool is_valid = mii_v3.version == 0 || mii_v3.version == 3; diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 83ad3d343..5525fcd1c 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h @@ -23,11 +23,16 @@ public: CharInfo BuildRandom(Age age, Gender gender, Race race); CharInfo BuildDefault(std::size_t index); CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; - Ver3StoreData ConvertCharInfoToV3(const CharInfo& mii) const; bool ValidateV3Info(const Ver3StoreData& mii_v3) const; ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); Result GetIndex(const CharInfo& info, u32& index); + // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData + Ver3StoreData BuildFromStoreData(const CharInfo& mii) const; + + // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData + NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; + private: const Common::UUID user_id{}; u64 update_counter{}; diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h index 9e3247397..c48d08d79 100644 --- a/src/core/hle/service/mii/types.h +++ b/src/core/hle/service/mii/types.h @@ -365,10 +365,68 @@ struct Ver3StoreData { } appearance_bits11; std::array<u16_le, 0xA> author_name; - INSERT_PADDING_BYTES(0x4); + INSERT_PADDING_BYTES(0x2); + u16_be crc; }; static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size"); +struct NfpStoreDataExtension { + u8 faceline_color; + u8 hair_color; + u8 eye_color; + u8 eyebrow_color; + u8 mouth_color; + u8 beard_color; + u8 glass_color; + u8 glass_type; +}; +static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size"); + +constexpr std::array<u8, 0x10> Ver3FacelineColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5, +}; + +constexpr std::array<u8, 100> Ver3HairColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0, + 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4, +}; + +constexpr std::array<u8, 100> Ver3EyeColorTable{ + 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4, + 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, + 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, +}; + +constexpr std::array<u8, 100> Ver3MouthlineColorTable{ + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4, + 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4, + 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, + 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, + 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, + 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3, +}; + +constexpr std::array<u8, 100> Ver3GlassColorTable{ + 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3, + 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, +}; + +constexpr std::array<u8, 20> Ver3GlassTypeTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, + 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7, +}; + struct MiiStoreData { using Name = std::array<char16_t, 10>; diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index ba8c0e230..6f43b1968 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp @@ -2,8 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/mm/mm_u.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/sm/sm.h" namespace Service::MM { @@ -28,21 +29,21 @@ public: } private: - void InitializeOld(Kernel::HLERequestContext& ctx) { + void InitializeOld(HLERequestContext& ctx) { LOG_WARNING(Service_MM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void FinalizeOld(Kernel::HLERequestContext& ctx) { + void FinalizeOld(HLERequestContext& ctx) { LOG_WARNING(Service_MM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void SetAndWaitOld(Kernel::HLERequestContext& ctx) { + void SetAndWaitOld(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; min = rp.Pop<u32>(); max = rp.Pop<u32>(); @@ -53,7 +54,7 @@ private: rb.Push(ResultSuccess); } - void GetOld(Kernel::HLERequestContext& ctx) { + void GetOld(HLERequestContext& ctx) { LOG_DEBUG(Service_MM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -61,7 +62,7 @@ private: rb.Push(current); } - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { LOG_WARNING(Service_MM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -69,14 +70,14 @@ private: rb.Push<u32>(id); // Any non zero value } - void Finalize(Kernel::HLERequestContext& ctx) { + void Finalize(HLERequestContext& ctx) { LOG_WARNING(Service_MM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void SetAndWait(Kernel::HLERequestContext& ctx) { + void SetAndWait(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u32 input_id = rp.Pop<u32>(); min = rp.Pop<u32>(); @@ -89,7 +90,7 @@ private: rb.Push(ResultSuccess); } - void Get(Kernel::HLERequestContext& ctx) { + void Get(HLERequestContext& ctx) { LOG_DEBUG(Service_MM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -103,8 +104,11 @@ private: u32 id{1}; }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<MM_U>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("mm:u", std::make_shared<MM_U>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::MM diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h index b40941e35..43117c9b1 100644 --- a/src/core/hle/service/mm/mm_u.h +++ b/src/core/hle/service/mm/mm_u.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::MM { -/// Registers all MM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::MM diff --git a/src/core/hle/service/mnpp/mnpp_app.cpp b/src/core/hle/service/mnpp/mnpp_app.cpp index c3aad5714..b11a92056 100644 --- a/src/core/hle/service/mnpp/mnpp_app.cpp +++ b/src/core/hle/service/mnpp/mnpp_app.cpp @@ -2,9 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/mnpp/mnpp_app.h" -#include "core/hle/service/sm/sm.h" +#include "core/hle/service/server_manager.h" +#include "core/hle/service/service.h" namespace Service::MNPP { @@ -22,14 +23,14 @@ public: } private: - void Unknown0(Kernel::HLERequestContext& ctx) { + void Unknown0(HLERequestContext& ctx) { LOG_WARNING(Service_MNPP, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void Unknown1(Kernel::HLERequestContext& ctx) { + void Unknown1(HLERequestContext& ctx) { LOG_WARNING(Service_MNPP, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -37,8 +38,11 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<MNPP_APP>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("mnpp:app", std::make_shared<MNPP_APP>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::MNPP diff --git a/src/core/hle/service/mnpp/mnpp_app.h b/src/core/hle/service/mnpp/mnpp_app.h index eec75fe0e..40d0395bd 100644 --- a/src/core/hle/service/mnpp/mnpp_app.h +++ b/src/core/hle/service/mnpp/mnpp_app.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::MNPP { -/// Registers all MNPP services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::MNPP diff --git a/src/core/hle/service/mutex.cpp b/src/core/hle/service/mutex.cpp new file mode 100644 index 000000000..b0ff71d1b --- /dev/null +++ b/src/core/hle/service/mutex.cpp @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/service/mutex.h" + +namespace Service { + +Mutex::Mutex(Core::System& system) : m_system(system) { + m_event = Kernel::KEvent::Create(system.Kernel()); + m_event->Initialize(nullptr); + + // Register the event. + Kernel::KEvent::Register(system.Kernel(), m_event); + + ASSERT(R_SUCCEEDED(m_event->Signal())); +} + +Mutex::~Mutex() { + m_event->GetReadableEvent().Close(); + m_event->Close(); +} + +void Mutex::lock() { + // Infinitely retry until we successfully clear the event. + while (R_FAILED(m_event->GetReadableEvent().Reset())) { + s32 index; + Kernel::KSynchronizationObject* obj = &m_event->GetReadableEvent(); + + // The event was already cleared! + // Wait for it to become signaled again. + ASSERT(R_SUCCEEDED( + Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &index, &obj, 1, -1))); + } + + // We successfully cleared the event, and now have exclusive ownership. +} + +void Mutex::unlock() { + // Unlock. + ASSERT(R_SUCCEEDED(m_event->Signal())); +} + +} // namespace Service diff --git a/src/core/hle/service/mutex.h b/src/core/hle/service/mutex.h new file mode 100644 index 000000000..95ac9b117 --- /dev/null +++ b/src/core/hle/service/mutex.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KEvent; +} + +namespace Service { + +class Mutex { +public: + explicit Mutex(Core::System& system); + ~Mutex(); + + void lock(); + void unlock(); + +private: + Core::System& m_system; + Kernel::KEvent* m_event{}; +}; + +} // namespace Service diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp index 68210a108..650666d6b 100644 --- a/src/core/hle/service/ncm/ncm.cpp +++ b/src/core/hle/service/ncm/ncm.cpp @@ -4,10 +4,10 @@ #include <memory> #include "core/file_sys/romfs_factory.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ncm/ncm.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::NCM { @@ -124,6 +124,7 @@ public: {12, nullptr, "InactivateContentMetaDatabase"}, {13, nullptr, "InvalidateRightsIdCache"}, {14, nullptr, "GetMemoryReport"}, + {15, nullptr, "ActivateFsContentStorage"}, }; // clang-format on @@ -131,9 +132,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<LR>(system)->InstallAsService(sm); - std::make_shared<NCM>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("lr", std::make_shared<LR>(system)); + server_manager->RegisterNamedService("ncm", std::make_shared<NCM>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NCM diff --git a/src/core/hle/service/ncm/ncm.h b/src/core/hle/service/ncm/ncm.h index de3971437..b78efdcd7 100644 --- a/src/core/hle/service/ncm/ncm.h +++ b/src/core/hle/service/ncm/ncm.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::NCM { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::NCM diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp index ffb2f959c..bc232c334 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.cpp +++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp @@ -12,7 +12,7 @@ #include "common/fs/fs.h" #include "common/fs/path_util.h" #include "common/logging/log.h" -#include "core/hle/service/nfp/amiibo_crypto.h" +#include "core/hle/service/nfc/common/amiibo_crypto.h" namespace Service::NFP::AmiiboCrypto { @@ -36,12 +36,12 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { // Validate UUID constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3` - if ((CT ^ ntag_file.uuid.uid[0] ^ ntag_file.uuid.uid[1] ^ ntag_file.uuid.uid[2]) != - ntag_file.uuid.uid[3]) { + if ((CT ^ ntag_file.uuid.part1[0] ^ ntag_file.uuid.part1[1] ^ ntag_file.uuid.part1[2]) != + ntag_file.uuid.crc_check1) { return false; } - if ((ntag_file.uuid.uid[4] ^ ntag_file.uuid.uid[5] ^ ntag_file.uuid.uid[6] ^ - ntag_file.uuid.nintendo_id) != ntag_file.uuid.lock_bytes[0]) { + if ((ntag_file.uuid.part2[0] ^ ntag_file.uuid.part2[1] ^ ntag_file.uuid.part2[2] ^ + ntag_file.uuid.nintendo_id) != ntag_file.uuid_crc_check2) { return false; } @@ -52,10 +52,7 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { if (ntag_file.compability_container != 0xEEFF10F1U) { return false; } - if (amiibo_data.constant_value != 0xA5) { - return false; - } - if (amiibo_data.model_info.tag_type != PackedTagType::Type2) { + if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) { return false; } if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) { @@ -70,26 +67,34 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { return true; } +bool IsAmiiboValid(const NTAG215File& ntag_file) { + return IsAmiiboValid(EncodedDataToNfcData(ntag_file)); +} + NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { NTAG215File encoded_data{}; - encoded_data.uid = nfc_data.uuid.uid; - encoded_data.nintendo_id = nfc_data.uuid.nintendo_id; + encoded_data.uid = nfc_data.uuid; + encoded_data.uid_crc_check2 = nfc_data.uuid_crc_check2; + encoded_data.internal_number = nfc_data.internal_number; encoded_data.static_lock = nfc_data.static_lock; encoded_data.compability_container = nfc_data.compability_container; encoded_data.hmac_data = nfc_data.user_memory.hmac_data; encoded_data.constant_value = nfc_data.user_memory.constant_value; encoded_data.write_counter = nfc_data.user_memory.write_counter; + encoded_data.amiibo_version = nfc_data.user_memory.amiibo_version; encoded_data.settings = nfc_data.user_memory.settings; encoded_data.owner_mii = nfc_data.user_memory.owner_mii; - encoded_data.title_id = nfc_data.user_memory.title_id; - encoded_data.applicaton_write_counter = nfc_data.user_memory.applicaton_write_counter; + encoded_data.application_id = nfc_data.user_memory.application_id; + encoded_data.application_write_counter = nfc_data.user_memory.application_write_counter; encoded_data.application_area_id = nfc_data.user_memory.application_area_id; + encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte; encoded_data.unknown = nfc_data.user_memory.unknown; + encoded_data.mii_extension = nfc_data.user_memory.mii_extension; encoded_data.unknown2 = nfc_data.user_memory.unknown2; + encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; encoded_data.application_area = nfc_data.user_memory.application_area; encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; - encoded_data.lock_bytes = nfc_data.uuid.lock_bytes; encoded_data.model_info = nfc_data.user_memory.model_info; encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt; encoded_data.dynamic_lock = nfc_data.dynamic_lock; @@ -103,21 +108,25 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { EncryptedNTAG215File nfc_data{}; - nfc_data.uuid.uid = encoded_data.uid; - nfc_data.uuid.nintendo_id = encoded_data.nintendo_id; - nfc_data.uuid.lock_bytes = encoded_data.lock_bytes; + nfc_data.uuid = encoded_data.uid; + nfc_data.uuid_crc_check2 = encoded_data.uid_crc_check2; + nfc_data.internal_number = encoded_data.internal_number; nfc_data.static_lock = encoded_data.static_lock; nfc_data.compability_container = encoded_data.compability_container; nfc_data.user_memory.hmac_data = encoded_data.hmac_data; nfc_data.user_memory.constant_value = encoded_data.constant_value; nfc_data.user_memory.write_counter = encoded_data.write_counter; + nfc_data.user_memory.amiibo_version = encoded_data.amiibo_version; nfc_data.user_memory.settings = encoded_data.settings; nfc_data.user_memory.owner_mii = encoded_data.owner_mii; - nfc_data.user_memory.title_id = encoded_data.title_id; - nfc_data.user_memory.applicaton_write_counter = encoded_data.applicaton_write_counter; + nfc_data.user_memory.application_id = encoded_data.application_id; + nfc_data.user_memory.application_write_counter = encoded_data.application_write_counter; nfc_data.user_memory.application_area_id = encoded_data.application_area_id; + nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte; nfc_data.user_memory.unknown = encoded_data.unknown; + nfc_data.user_memory.mii_extension = encoded_data.mii_extension; nfc_data.user_memory.unknown2 = encoded_data.unknown2; + nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc; nfc_data.user_memory.application_area = encoded_data.application_area; nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag; nfc_data.user_memory.model_info = encoded_data.model_info; @@ -130,23 +139,12 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { return nfc_data; } -u32 GetTagPassword(const TagUuid& uuid) { - // Verifiy that the generated password is correct - u32 password = 0xAA ^ (uuid.uid[1] ^ uuid.uid[3]); - password &= (0x55 ^ (uuid.uid[2] ^ uuid.uid[4])) << 8; - password &= (0xAA ^ (uuid.uid[3] ^ uuid.uid[5])) << 16; - password &= (0x55 ^ (uuid.uid[4] ^ uuid.uid[6])) << 24; - return password; -} - HashSeed GetSeed(const NTAG215File& data) { HashSeed seed{ .magic = data.write_counter, .padding = {}, .uid_1 = data.uid, - .nintendo_id_1 = data.nintendo_id, .uid_2 = data.uid, - .nintendo_id_2 = data.nintendo_id, .keygen_salt = data.keygen_salt, }; @@ -168,10 +166,11 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed output.insert(output.end(), key.magic_bytes.begin(), key.magic_bytes.begin() + key.magic_length); - output.insert(output.end(), seed.uid_1.begin(), seed.uid_1.end()); - output.emplace_back(seed.nintendo_id_1); - output.insert(output.end(), seed.uid_2.begin(), seed.uid_2.end()); - output.emplace_back(seed.nintendo_id_2); + std::array<u8, sizeof(NFP::TagUuid)> seed_uuid{}; + memcpy(seed_uuid.data(), &seed.uid_1, sizeof(NFP::TagUuid)); + output.insert(output.end(), seed_uuid.begin(), seed_uuid.end()); + memcpy(seed_uuid.data(), &seed.uid_2, sizeof(NFP::TagUuid)); + output.insert(output.end(), seed_uuid.begin(), seed_uuid.end()); for (std::size_t i = 0; i < sizeof(seed.keygen_salt); i++) { output.emplace_back(static_cast<u8>(seed.keygen_salt[i] ^ key.xor_pad[i])); @@ -255,8 +254,8 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou // Copy the rest of the data directly out_data.uid = in_data.uid; - out_data.nintendo_id = in_data.nintendo_id; - out_data.lock_bytes = in_data.lock_bytes; + out_data.uid_crc_check2 = in_data.uid_crc_check2; + out_data.internal_number = in_data.internal_number; out_data.static_lock = in_data.static_lock; out_data.compability_container = in_data.compability_container; diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h index 1fa61174e..6a3e0841e 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.h +++ b/src/core/hle/service/nfc/common/amiibo_crypto.h @@ -24,10 +24,8 @@ using DrgbOutput = std::array<u8, 0x20>; struct HashSeed { u16_be magic; std::array<u8, 0xE> padding; - UniqueSerialNumber uid_1; - u8 nintendo_id_1; - UniqueSerialNumber uid_2; - u8 nintendo_id_2; + TagUuid uid_1; + TagUuid uid_2; std::array<u8, 0x20> keygen_salt; }; static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size"); @@ -60,15 +58,15 @@ static_assert(sizeof(DerivedKeys) == 0x30, "DerivedKeys is an invalid size"); /// Validates that the amiibo file is not corrupted bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file); +/// Validates that the amiibo file is not corrupted +bool IsAmiiboValid(const NTAG215File& ntag_file); + /// Converts from encrypted file format to encoded file format NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data); /// Converts from encoded file format to encrypted file format EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data); -/// Returns password needed to allow write access to protected memory -u32 GetTagPassword(const TagUuid& uuid); - // Generates Seed needed for key derivation HashSeed GetSeed(const NTAG215File& data); @@ -94,7 +92,7 @@ bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info); /// Returns true if key_retail.bin exist bool IsKeyAvailable(); -/// Decodes encripted amiibo data returns true if output is valid +/// Decodes encrypted amiibo data returns true if output is valid bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data); /// Encodes plain amiibo data returns true if output is valid diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp new file mode 100644 index 000000000..5bf289818 --- /dev/null +++ b/src/core/hle/service/nfc/common/device.cpp @@ -0,0 +1,1483 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used +#endif + +#include <boost/crc.hpp> + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include <fmt/format.h> + +#include "common/fs/file.h" +#include "common/fs/fs.h" +#include "common/fs/path_util.h" +#include "common/input.h" +#include "common/logging/log.h" +#include "common/string_util.h" +#include "common/tiny_mt.h" +#include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/mii/mii_manager.h" +#include "core/hle/service/mii/types.h" +#include "core/hle/service/nfc/common/amiibo_crypto.h" +#include "core/hle/service/nfc/common/device.h" +#include "core/hle/service/nfc/mifare_result.h" +#include "core/hle/service/nfc/nfc_result.h" +#include "core/hle/service/time/time_manager.h" +#include "core/hle/service/time/time_zone_content_manager.h" +#include "core/hle/service/time/time_zone_types.h" + +namespace Service::NFC { +NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, + KernelHelpers::ServiceContext& service_context_, + Kernel::KEvent* availability_change_event_) + : npad_id{npad_id_}, system{system_}, service_context{service_context_}, + availability_change_event{availability_change_event_} { + activate_event = service_context.CreateEvent("NFC:ActivateEvent"); + deactivate_event = service_context.CreateEvent("NFC:DeactivateEvent"); + npad_device = system.HIDCore().GetEmulatedController(npad_id); + + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); }, + .is_npad_service = false, + }; + is_controller_set = true; + callback_key = npad_device->SetCallback(engine_callback); +} + +NfcDevice::~NfcDevice() { + service_context.CloseEvent(activate_event); + service_context.CloseEvent(deactivate_event); + if (!is_controller_set) { + return; + } + npad_device->DeleteCallback(callback_key); + is_controller_set = false; +}; + +void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { + if (!is_initalized) { + return; + } + + if (type == Core::HID::ControllerTriggerType::Connected) { + Initialize(); + availability_change_event->Signal(); + return; + } + + if (type == Core::HID::ControllerTriggerType::Disconnected) { + device_state = DeviceState::Unavailable; + availability_change_event->Signal(); + return; + } + + if (type != Core::HID::ControllerTriggerType::Nfc) { + return; + } + + if (!npad_device->IsConnected()) { + return; + } + + const auto nfc_status = npad_device->GetNfc(); + switch (nfc_status.state) { + case Common::Input::NfcState::NewAmiibo: + LoadNfcTag(nfc_status.protocol, nfc_status.tag_type, nfc_status.uuid_length, + nfc_status.uuid); + break; + case Common::Input::NfcState::AmiiboRemoved: + if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { + break; + } + if (device_state != DeviceState::SearchingForTag) { + CloseNfcTag(); + } + break; + default: + break; + } +} + +bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid) { + if (device_state != DeviceState::SearchingForTag) { + LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state); + return false; + } + + if ((protocol & static_cast<u8>(allowed_protocols)) == 0) { + LOG_ERROR(Service_NFC, "Protocol not supported {}", protocol); + return false; + } + + real_tag_info = { + .uuid = uuid, + .uuid_length = uuid_length, + .protocol = static_cast<NfcProtocol>(protocol), + .tag_type = static_cast<TagType>(tag_type), + }; + + device_state = DeviceState::TagFound; + deactivate_event->GetReadableEvent().Clear(); + activate_event->Signal(); + return true; +} + +bool NfcDevice::LoadAmiiboData() { + std::vector<u8> data{}; + + if (!npad_device->ReadAmiiboData(data)) { + return false; + } + + if (data.size() < sizeof(NFP::EncryptedNTAG215File)) { + LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); + return false; + } + + memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data); + is_write_protected = false; + + // Fallback for plain amiibos + if (is_plain_amiibo) { + LOG_INFO(Service_NFP, "Using plain amiibo"); + encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(tag_data); + return true; + } + + // Fallback for encrypted amiibos without keys + if (!NFP::AmiiboCrypto::IsKeyAvailable()) { + LOG_INFO(Service_NFC, "Loading amiibo without keys"); + memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + BuildAmiiboWithoutKeys(tag_data, encrypted_tag_data); + is_plain_amiibo = true; + is_write_protected = true; + return true; + } + + LOG_INFO(Service_NFP, "Using encrypted amiibo"); + tag_data = {}; + memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + return true; +} + +void NfcDevice::CloseNfcTag() { + LOG_INFO(Service_NFC, "Remove nfc tag"); + + if (device_state == DeviceState::TagMounted) { + Unmount(); + } + + device_state = DeviceState::TagRemoved; + encrypted_tag_data = {}; + tag_data = {}; + activate_event->GetReadableEvent().Clear(); + deactivate_event->Signal(); +} + +Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { + return activate_event->GetReadableEvent(); +} + +Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const { + return deactivate_event->GetReadableEvent(); +} + +void NfcDevice::Initialize() { + device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable; + encrypted_tag_data = {}; + tag_data = {}; + + if (device_state != DeviceState::Initialized) { + return; + } + + is_initalized = npad_device->AddNfcHandle(); +} + +void NfcDevice::Finalize() { + if (device_state == DeviceState::TagMounted) { + Unmount(); + } + if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { + StopDetection(); + } + + if (device_state != DeviceState::Unavailable) { + npad_device->RemoveNfcHandle(); + } + + device_state = DeviceState::Unavailable; + is_initalized = false; +} + +Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) { + if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + return ResultWrongDeviceState; + } + + if (!npad_device->StartNfcPolling()) { + LOG_ERROR(Service_NFC, "Nfc polling not supported"); + return ResultNfcDisabled; + } + + device_state = DeviceState::SearchingForTag; + allowed_protocols = allowed_protocol; + return ResultSuccess; +} + +Result NfcDevice::StopDetection() { + if (device_state == DeviceState::Initialized) { + return ResultSuccess; + } + + if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { + CloseNfcTag(); + } + + if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { + npad_device->StopNfcPolling(); + device_state = DeviceState::Initialized; + return ResultSuccess; + } + + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + return ResultWrongDeviceState; +} + +Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const { + if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + tag_info = real_tag_info; + + // Generate random UUID to bypass amiibo load limits + if (real_tag_info.tag_type == TagType::Type2 && Settings::values.random_amiibo_id) { + Common::TinyMT rng{}; + rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); + rng.GenerateRandomBytes(tag_info.uuid.data(), tag_info.uuid_length); + } + + return ResultSuccess; +} + +Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameters, + std::span<MifareReadBlockData> read_block_data) const { + if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + Result result = ResultSuccess; + + TagInfo tag_info{}; + result = GetTagInfo(tag_info); + + if (result.IsError()) { + return result; + } + + if (tag_info.protocol != NfcProtocol::TypeA || tag_info.tag_type != TagType::Mifare) { + return ResultInvalidTagType; + } + + if (parameters.size() == 0) { + return ResultInvalidArgument; + } + + Common::Input::MifareRequest request{}; + Common::Input::MifareRequest out_data{}; + const auto unknown = parameters[0].sector_key.unknown; + for (std::size_t i = 0; i < parameters.size(); i++) { + if (unknown != parameters[i].sector_key.unknown) { + return ResultInvalidArgument; + } + } + + for (std::size_t i = 0; i < parameters.size(); i++) { + if (parameters[i].sector_key.command == MifareCmd::None) { + continue; + } + request.data[i].command = static_cast<u8>(parameters[i].sector_key.command); + request.data[i].sector = parameters[i].sector_number; + memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(), + sizeof(KeyData)); + } + + if (!npad_device->ReadMifareData(request, out_data)) { + return ResultMifareError288; + } + + for (std::size_t i = 0; i < read_block_data.size(); i++) { + if (static_cast<MifareCmd>(out_data.data[i].command) == MifareCmd::None) { + continue; + } + + read_block_data[i] = { + .data = out_data.data[i].data, + .sector_number = out_data.data[i].sector, + }; + } + + return ResultSuccess; +} + +Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> parameters) { + Result result = ResultSuccess; + + TagInfo tag_info{}; + result = GetTagInfo(tag_info); + + if (result.IsError()) { + return result; + } + + if (tag_info.protocol != NfcProtocol::TypeA || tag_info.tag_type != TagType::Mifare) { + return ResultInvalidTagType; + } + + if (parameters.size() == 0) { + return ResultInvalidArgument; + } + + const auto unknown = parameters[0].sector_key.unknown; + for (std::size_t i = 0; i < parameters.size(); i++) { + if (unknown != parameters[i].sector_key.unknown) { + return ResultInvalidArgument; + } + } + + Common::Input::MifareRequest request{}; + for (std::size_t i = 0; i < parameters.size(); i++) { + if (parameters[i].sector_key.command == MifareCmd::None) { + continue; + } + request.data[i].command = static_cast<u8>(parameters[i].sector_key.command); + request.data[i].sector = parameters[i].sector_number; + memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(), + sizeof(KeyData)); + memcpy(request.data[i].data.data(), parameters[i].data.data(), sizeof(KeyData)); + } + + if (!npad_device->WriteMifareData(request)) { + return ResultMifareError288; + } + + return result; +} + +Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout, + std::span<const u8> command_data, + std::span<u8> out_data) { + // Not implemented + return ResultSuccess; +} + +Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { + if (device_state != DeviceState::TagFound) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + return ResultWrongDeviceState; + } + + if (!LoadAmiiboData()) { + LOG_ERROR(Service_NFP, "Not an amiibo"); + return ResultInvalidTagType; + } + + if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { + LOG_ERROR(Service_NFP, "Not an amiibo"); + return ResultInvalidTagType; + } + + // The loaded amiibo is not encrypted + if (is_plain_amiibo) { + std::vector<u8> data(sizeof(NFP::NTAG215File)); + memcpy(data.data(), &tag_data, sizeof(tag_data)); + WriteBackupData(tag_data.uid, data); + + device_state = DeviceState::TagMounted; + mount_target = mount_target_; + return ResultSuccess; + } + + if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { + bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); + LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); + return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; + } + + std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); + memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); + WriteBackupData(encrypted_tag_data.uuid, data); + + device_state = DeviceState::TagMounted; + mount_target = mount_target_; + return ResultSuccess; +} + +Result NfcDevice::Unmount() { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + // Save data before unloading the amiibo + if (is_data_moddified) { + Flush(); + } + + device_state = DeviceState::TagFound; + mount_target = NFP::MountTarget::None; + is_app_area_open = false; + + return ResultSuccess; +} + +Result NfcDevice::Flush() { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + auto& settings = tag_data.settings; + + const auto& current_date = GetAmiiboDate(GetCurrentPosixTime()); + if (settings.write_date.raw_date != current_date.raw_date) { + settings.write_date = current_date; + UpdateSettingsCrc(); + } + + tag_data.write_counter++; + + const auto result = FlushWithBreak(NFP::BreakType::Normal); + + is_data_moddified = false; + + return result; +} + +Result NfcDevice::FlushDebug() { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + tag_data.write_counter++; + + const auto result = FlushWithBreak(NFP::BreakType::Normal); + + is_data_moddified = false; + + return result; +} + +Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) { + if (break_type != NFP::BreakType::Normal) { + LOG_ERROR(Service_NFC, "Break type not implemented {}", break_type); + return ResultWrongDeviceState; + } + + if (is_write_protected) { + LOG_ERROR(Service_NFP, "No keys available skipping write request"); + return ResultSuccess; + } + + std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); + if (is_plain_amiibo) { + memcpy(data.data(), &tag_data, sizeof(tag_data)); + WriteBackupData(tag_data.uid, data); + } else { + if (!NFP::AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { + LOG_ERROR(Service_NFP, "Failed to encode data"); + return ResultWriteAmiiboFailed; + } + + memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); + WriteBackupData(encrypted_tag_data.uuid, data); + } + + if (!npad_device->WriteNfc(data)) { + LOG_ERROR(Service_NFP, "Error writing to file"); + return ResultWriteAmiiboFailed; + } + + return ResultSuccess; +} + +Result NfcDevice::Restore() { + if (device_state != DeviceState::TagFound) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + NFC::TagInfo tag_info{}; + std::array<u8, sizeof(NFP::EncryptedNTAG215File)> data{}; + Result result = GetTagInfo(tag_info); + + if (result.IsError()) { + return result; + } + + result = ReadBackupData(tag_info.uuid, tag_info.uuid_length, data); + + if (result.IsError()) { + return result; + } + + NFP::NTAG215File temporary_tag_data{}; + NFP::EncryptedNTAG215File temporary_encrypted_tag_data{}; + + // Fallback for encrypted amiibos without keys + if (is_write_protected) { + return ResultWriteAmiiboFailed; + } + + // Fallback for plain amiibos + if (is_plain_amiibo) { + LOG_INFO(Service_NFP, "Restoring backup of plain amiibo"); + memcpy(&temporary_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + temporary_encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(temporary_tag_data); + } + + if (!is_plain_amiibo) { + LOG_INFO(Service_NFP, "Restoring backup of encrypted amiibo"); + temporary_tag_data = {}; + memcpy(&temporary_encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + } + + if (!NFP::AmiiboCrypto::IsAmiiboValid(temporary_encrypted_tag_data)) { + return ResultInvalidTagType; + } + + if (!is_plain_amiibo) { + if (!NFP::AmiiboCrypto::DecodeAmiibo(temporary_encrypted_tag_data, temporary_tag_data)) { + LOG_ERROR(Service_NFP, "Can't decode amiibo"); + return ResultCorruptedData; + } + } + + // Overwrite tag contents with backup and mount the tag + tag_data = temporary_tag_data; + encrypted_tag_data = temporary_encrypted_tag_data; + device_state = DeviceState::TagMounted; + mount_target = NFP::MountTarget::All; + is_data_moddified = true; + + return ResultSuccess; +} + +Result NfcDevice::GetCommonInfo(NFP::CommonInfo& common_info) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + const auto& settings = tag_data.settings; + + // TODO: Validate this data + common_info = { + .last_write_date = settings.write_date.GetWriteDate(), + .write_counter = tag_data.application_write_counter, + .version = tag_data.amiibo_version, + .application_area_size = sizeof(NFP::ApplicationArea), + }; + return ResultSuccess; +} + +Result NfcDevice::GetModelInfo(NFP::ModelInfo& model_info) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + const auto& model_info_data = encrypted_tag_data.user_memory.model_info; + + model_info = { + .character_id = model_info_data.character_id, + .character_variant = model_info_data.character_variant, + .amiibo_type = model_info_data.amiibo_type, + .model_number = model_info_data.model_number, + .series = model_info_data.series, + }; + return ResultSuccess; +} + +Result NfcDevice::GetRegisterInfo(NFP::RegisterInfo& register_info) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.amiibo_initialized == 0) { + return ResultRegistrationIsNotInitialized; + } + + Service::Mii::MiiManager manager; + const auto& settings = tag_data.settings; + + // TODO: Validate this data + register_info = { + .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii), + .creation_date = settings.init_date.GetWriteDate(), + .amiibo_name = GetAmiiboName(settings), + .font_region = settings.settings.font_region, + }; + + return ResultSuccess; +} + +Result NfcDevice::GetRegisterInfoPrivate(NFP::RegisterInfoPrivate& register_info) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.amiibo_initialized == 0) { + return ResultRegistrationIsNotInitialized; + } + + Service::Mii::MiiManager manager; + const auto& settings = tag_data.settings; + + // TODO: Validate and complete this data + register_info = { + .mii_store_data = {}, + .creation_date = settings.init_date.GetWriteDate(), + .amiibo_name = GetAmiiboName(settings), + .font_region = settings.settings.font_region, + }; + + return ResultSuccess; +} + +Result NfcDevice::GetAdminInfo(NFP::AdminInfo& admin_info) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + u8 flags = static_cast<u8>(tag_data.settings.settings.raw >> 0x4); + if (tag_data.settings.settings.amiibo_initialized == 0) { + flags = flags & 0xfe; + } + + u64 application_id = 0; + u32 application_area_id = 0; + NFP::AppAreaVersion app_area_version = NFP::AppAreaVersion::NotSet; + if (tag_data.settings.settings.appdata_initialized != 0) { + application_id = tag_data.application_id; + app_area_version = static_cast<NFP::AppAreaVersion>( + application_id >> NFP::application_id_version_offset & 0xf); + + // Restore application id to original value + if (application_id >> 0x38 != 0) { + const u8 application_byte = tag_data.application_id_byte & 0xf; + application_id = + RemoveVersionByte(application_id) | + (static_cast<u64>(application_byte) << NFP::application_id_version_offset); + } + + application_area_id = tag_data.application_area_id; + } + + // TODO: Validate this data + admin_info = { + .application_id = application_id, + .application_area_id = application_area_id, + .crc_change_counter = tag_data.settings.crc_counter, + .flags = flags, + .tag_type = PackedTagType::Type2, + .app_area_version = app_area_version, + }; + + return ResultSuccess; +} + +Result NfcDevice::DeleteRegisterInfo() { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.amiibo_initialized == 0) { + return ResultRegistrationIsNotInitialized; + } + + Common::TinyMT rng{}; + rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); + rng.GenerateRandomBytes(&tag_data.owner_mii, sizeof(tag_data.owner_mii)); + rng.GenerateRandomBytes(&tag_data.settings.amiibo_name, sizeof(tag_data.settings.amiibo_name)); + rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8)); + rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32)); + rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32)); + rng.GenerateRandomBytes(&tag_data.register_info_crc, sizeof(u32)); + rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32)); + tag_data.settings.settings.font_region.Assign(0); + tag_data.settings.settings.amiibo_initialized.Assign(0); + + return Flush(); +} + +Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + Service::Mii::MiiManager manager; + const auto mii = manager.BuildDefault(0); + auto& settings = tag_data.settings; + + if (tag_data.settings.settings.amiibo_initialized == 0) { + settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); + settings.write_date.raw_date = 0; + } + + SetAmiiboName(settings, register_info.amiibo_name); + tag_data.owner_mii = manager.BuildFromStoreData(mii); + tag_data.mii_extension = manager.SetFromStoreData(mii); + tag_data.unknown = 0; + tag_data.unknown2 = {}; + settings.country_code_id = 0; + settings.settings.font_region.Assign(0); + settings.settings.amiibo_initialized.Assign(1); + + UpdateRegisterInfoCrc(); + + return Flush(); +} + +Result NfcDevice::RestoreAmiibo() { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + // TODO: Load amiibo from backup on system + LOG_ERROR(Service_NFP, "Not Implemented"); + return ResultSuccess; +} + +Result NfcDevice::Format() { + auto result1 = DeleteApplicationArea(); + auto result2 = DeleteRegisterInfo(); + + if (result1.IsError()) { + return result1; + } + + if (result2.IsError()) { + return result2; + } + + return Flush(); +} + +Result NfcDevice::OpenApplicationArea(u32 access_id) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized.Value() == 0) { + LOG_WARNING(Service_NFP, "Application area is not initialized"); + return ResultApplicationAreaIsNotInitialized; + } + + if (tag_data.application_area_id != access_id) { + LOG_WARNING(Service_NFP, "Wrong application area id"); + return ResultWrongApplicationAreaId; + } + + is_app_area_open = true; + + return ResultSuccess; +} + +Result NfcDevice::GetApplicationAreaId(u32& application_area_id) const { + application_area_id = {}; + + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized.Value() == 0) { + LOG_WARNING(Service_NFP, "Application area is not initialized"); + return ResultApplicationAreaIsNotInitialized; + } + + application_area_id = tag_data.application_area_id; + + return ResultSuccess; +} + +Result NfcDevice::GetApplicationArea(std::span<u8> data) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (!is_app_area_open) { + LOG_ERROR(Service_NFP, "Application area is not open"); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized.Value() == 0) { + LOG_ERROR(Service_NFP, "Application area is not initialized"); + return ResultApplicationAreaIsNotInitialized; + } + + memcpy(data.data(), tag_data.application_area.data(), + std::min(data.size(), sizeof(NFP::ApplicationArea))); + + return ResultSuccess; +} + +Result NfcDevice::SetApplicationArea(std::span<const u8> data) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (!is_app_area_open) { + LOG_ERROR(Service_NFP, "Application area is not open"); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized.Value() == 0) { + LOG_ERROR(Service_NFP, "Application area is not initialized"); + return ResultApplicationAreaIsNotInitialized; + } + + if (data.size() > sizeof(NFP::ApplicationArea)) { + LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); + return ResultUnknown; + } + + Common::TinyMT rng{}; + rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); + std::memcpy(tag_data.application_area.data(), data.data(), data.size()); + // Fill remaining data with random numbers + rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), + sizeof(NFP::ApplicationArea) - data.size()); + + if (tag_data.application_write_counter != NFP::counter_limit) { + tag_data.application_write_counter++; + } + + is_data_moddified = true; + + return ResultSuccess; +} + +Result NfcDevice::CreateApplicationArea(u32 access_id, std::span<const u8> data) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized.Value() != 0) { + LOG_ERROR(Service_NFP, "Application area already exist"); + return ResultApplicationAreaExist; + } + + return RecreateApplicationArea(access_id, data); +} + +Result NfcDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> data) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (is_app_area_open) { + LOG_ERROR(Service_NFP, "Application area is open"); + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (data.size() > sizeof(NFP::ApplicationArea)) { + LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); + return ResultWrongApplicationAreaSize; + } + + Common::TinyMT rng{}; + rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); + std::memcpy(tag_data.application_area.data(), data.data(), data.size()); + // Fill remaining data with random numbers + rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), + sizeof(NFP::ApplicationArea) - data.size()); + + if (tag_data.application_write_counter != NFP::counter_limit) { + tag_data.application_write_counter++; + } + + const u64 application_id = system.GetApplicationProcessProgramID(); + + tag_data.application_id_byte = + static_cast<u8>(application_id >> NFP::application_id_version_offset & 0xf); + tag_data.application_id = + RemoveVersionByte(application_id) | (static_cast<u64>(NFP::AppAreaVersion::NintendoSwitch) + << NFP::application_id_version_offset); + tag_data.settings.settings.appdata_initialized.Assign(1); + tag_data.application_area_id = access_id; + tag_data.unknown = {}; + tag_data.unknown2 = {}; + + UpdateRegisterInfoCrc(); + + return Flush(); +} + +Result NfcDevice::DeleteApplicationArea() { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized == 0) { + return ResultApplicationAreaIsNotInitialized; + } + + if (tag_data.application_write_counter != NFP::counter_limit) { + tag_data.application_write_counter++; + } + + Common::TinyMT rng{}; + rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); + rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(NFP::ApplicationArea)); + rng.GenerateRandomBytes(&tag_data.application_id, sizeof(u64)); + rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32)); + rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8)); + tag_data.settings.settings.appdata_initialized.Assign(0); + tag_data.unknown = {}; + tag_data.unknown2 = {}; + is_app_area_open = false; + + UpdateRegisterInfoCrc(); + + return Flush(); +} + +Result NfcDevice::ExistsApplicationArea(bool& has_application_area) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0; + + return ResultSuccess; +} + +Result NfcDevice::GetAll(NFP::NfpData& data) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + NFP::CommonInfo common_info{}; + const u64 application_id = tag_data.application_id; + + GetCommonInfo(common_info); + + data = { + .magic = tag_data.constant_value, + .write_counter = tag_data.write_counter, + .settings_crc = tag_data.settings.crc, + .common_info = common_info, + .mii_char_info = tag_data.owner_mii, + .mii_store_data_extension = tag_data.mii_extension, + .creation_date = tag_data.settings.init_date.GetWriteDate(), + .amiibo_name = tag_data.settings.amiibo_name, + .amiibo_name_null_terminated = 0, + .settings = tag_data.settings.settings, + .unknown1 = tag_data.unknown, + .register_info_crc = tag_data.register_info_crc, + .unknown2 = tag_data.unknown2, + .application_id = application_id, + .access_id = tag_data.application_area_id, + .settings_crc_counter = tag_data.settings.crc_counter, + .font_region = tag_data.settings.settings.font_region, + .tag_type = PackedTagType::Type2, + .console_type = static_cast<NFP::AppAreaVersion>( + application_id >> NFP::application_id_version_offset & 0xf), + .application_id_byte = tag_data.application_id_byte, + .application_area = tag_data.application_area, + }; + + return ResultSuccess; +} + +Result NfcDevice::SetAll(const NFP::NfpData& data) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + tag_data.constant_value = data.magic; + tag_data.write_counter = data.write_counter; + tag_data.settings.crc = data.settings_crc; + tag_data.settings.write_date.SetWriteDate(data.common_info.last_write_date); + tag_data.write_counter = data.common_info.write_counter; + tag_data.amiibo_version = data.common_info.version; + tag_data.owner_mii = data.mii_char_info; + tag_data.mii_extension = data.mii_store_data_extension; + tag_data.settings.init_date.SetWriteDate(data.creation_date); + tag_data.settings.amiibo_name = data.amiibo_name; + tag_data.settings.settings = data.settings; + tag_data.unknown = data.unknown1; + tag_data.register_info_crc = data.register_info_crc; + tag_data.unknown2 = data.unknown2; + tag_data.application_id = data.application_id; + tag_data.application_area_id = data.access_id; + tag_data.settings.crc_counter = data.settings_crc_counter; + tag_data.settings.settings.font_region.Assign(data.font_region); + tag_data.application_id_byte = data.application_id_byte; + tag_data.application_area = data.application_area; + + return ResultSuccess; +} + +Result NfcDevice::BreakTag(NFP::BreakType break_type) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + // TODO: Complete this implementation + + return FlushWithBreak(break_type); +} + +Result NfcDevice::HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const { + ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size"); + constexpr auto backup_dir = "backup"; + const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); + const auto file_name = + fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, "")); + + if (!Common::FS::Exists(yuzu_amiibo_dir / backup_dir / file_name)) { + return ResultUnableToAccessBackupFile; + } + + return ResultSuccess; +} + +Result NfcDevice::HasBackup(const NFP::TagUuid& tag_uid) const { + UniqueSerialNumber uuid{}; + memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid)); + return HasBackup(uuid, sizeof(NFP::TagUuid)); +} + +Result NfcDevice::ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, + std::span<u8> data) const { + ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size"); + constexpr auto backup_dir = "backup"; + const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); + const auto file_name = + fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, "")); + + const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name, + Common::FS::FileAccessMode::Read, + Common::FS::FileType::BinaryFile}; + + if (!keys_file.IsOpen()) { + LOG_ERROR(Service_NFP, "Failed to open amiibo backup"); + return ResultUnableToAccessBackupFile; + } + + if (keys_file.Read(data) != data.size()) { + LOG_ERROR(Service_NFP, "Failed to read amiibo backup"); + return ResultUnableToAccessBackupFile; + } + + return ResultSuccess; +} + +Result NfcDevice::ReadBackupData(const NFP::TagUuid& tag_uid, std::span<u8> data) const { + UniqueSerialNumber uuid{}; + memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid)); + return ReadBackupData(uuid, sizeof(NFP::TagUuid), data); +} + +Result NfcDevice::WriteBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, + std::span<const u8> data) { + ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size"); + constexpr auto backup_dir = "backup"; + const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); + const auto file_name = + fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, "")); + + if (HasBackup(uid, uuid_size).IsError()) { + if (!Common::FS::CreateDir(yuzu_amiibo_dir / backup_dir)) { + return ResultBackupPathAlreadyExist; + } + + if (!Common::FS::NewFile(yuzu_amiibo_dir / backup_dir / file_name)) { + return ResultBackupPathAlreadyExist; + } + } + + const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name, + Common::FS::FileAccessMode::ReadWrite, + Common::FS::FileType::BinaryFile}; + + if (!keys_file.IsOpen()) { + LOG_ERROR(Service_NFP, "Failed to open amiibo backup"); + return ResultUnableToAccessBackupFile; + } + + if (keys_file.Write(data) != data.size()) { + LOG_ERROR(Service_NFP, "Failed to write amiibo backup"); + return ResultUnableToAccessBackupFile; + } + + return ResultSuccess; +} + +Result NfcDevice::WriteBackupData(const NFP::TagUuid& tag_uid, std::span<const u8> data) { + UniqueSerialNumber uuid{}; + memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid)); + return WriteBackupData(uuid, sizeof(NFP::TagUuid), data); +} + +Result NfcDevice::WriteNtf(std::span<const u8> data) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return ResultTagRemoved; + } + return ResultWrongDeviceState; + } + + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); + return ResultWrongDeviceState; + } + + // Not implemented + + return ResultSuccess; +} + +NFP::AmiiboName NfcDevice::GetAmiiboName(const NFP::AmiiboSettings& settings) const { + std::array<char16_t, NFP::amiibo_name_length> settings_amiibo_name{}; + NFP::AmiiboName amiibo_name{}; + + // Convert from big endian to little endian + for (std::size_t i = 0; i < NFP::amiibo_name_length; i++) { + settings_amiibo_name[i] = static_cast<u16>(settings.amiibo_name[i]); + } + + // Convert from utf16 to utf8 + const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data()); + memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size()); + + return amiibo_name; +} + +void NfcDevice::SetAmiiboName(NFP::AmiiboSettings& settings, + const NFP::AmiiboName& amiibo_name) const { + std::array<char16_t, NFP::amiibo_name_length> settings_amiibo_name{}; + + // Convert from utf8 to utf16 + const auto amiibo_name_utf16 = Common::UTF8ToUTF16(amiibo_name.data()); + memcpy(settings_amiibo_name.data(), amiibo_name_utf16.data(), + amiibo_name_utf16.size() * sizeof(char16_t)); + + // Convert from little endian to big endian + for (std::size_t i = 0; i < NFP::amiibo_name_length; i++) { + settings.amiibo_name[i] = static_cast<u16_be>(settings_amiibo_name[i]); + } +} + +NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const { + const auto& time_zone_manager = + system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager(); + Time::TimeZone::CalendarInfo calendar_info{}; + NFP::AmiiboDate amiibo_date{}; + + amiibo_date.SetYear(2000); + amiibo_date.SetMonth(1); + amiibo_date.SetDay(1); + + if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) { + amiibo_date.SetYear(calendar_info.time.year); + amiibo_date.SetMonth(calendar_info.time.month); + amiibo_date.SetDay(calendar_info.time.day); + } + + return amiibo_date; +} + +u64 NfcDevice::GetCurrentPosixTime() const { + auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()}; + return standard_steady_clock.GetCurrentTimePoint(system).time_point; +} + +u64 NfcDevice::RemoveVersionByte(u64 application_id) const { + return application_id & ~(0xfULL << NFP::application_id_version_offset); +} + +void NfcDevice::UpdateSettingsCrc() { + auto& settings = tag_data.settings; + + if (settings.crc_counter != NFP::counter_limit) { + settings.crc_counter++; + } + + // TODO: this reads data from a global, find what it is + std::array<u8, 8> unknown_input{}; + boost::crc_32_type crc; + crc.process_bytes(&unknown_input, sizeof(unknown_input)); + settings.crc = crc.checksum(); +} + +void NfcDevice::UpdateRegisterInfoCrc() { +#pragma pack(push, 1) + struct CrcData { + Mii::Ver3StoreData mii; + u8 application_id_byte; + u8 unknown; + Mii::NfpStoreDataExtension mii_extension; + std::array<u32, 0x5> unknown2; + }; + static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size"); +#pragma pack(pop) + + const CrcData crc_data{ + .mii = tag_data.owner_mii, + .application_id_byte = tag_data.application_id_byte, + .unknown = tag_data.unknown, + .mii_extension = tag_data.mii_extension, + .unknown2 = tag_data.unknown2, + }; + + boost::crc_32_type crc; + crc.process_bytes(&crc_data, sizeof(CrcData)); + tag_data.register_info_crc = crc.checksum(); +} + +void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, + const NFP::EncryptedNTAG215File& encrypted_file) const { + Service::Mii::MiiManager manager; + auto& settings = stubbed_tag_data.settings; + + stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file); + + // Common info + stubbed_tag_data.write_counter = 0; + stubbed_tag_data.amiibo_version = 0; + settings.write_date = GetAmiiboDate(GetCurrentPosixTime()); + + // Register info + SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'}); + settings.settings.font_region.Assign(0); + settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); + stubbed_tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildDefault(0)); + + // Admin info + settings.settings.amiibo_initialized.Assign(1); + settings.settings.appdata_initialized.Assign(0); +} + +u64 NfcDevice::GetHandle() const { + // Generate a handle based of the npad id + return static_cast<u64>(npad_id); +} + +DeviceState NfcDevice::GetCurrentState() const { + return device_state; +} + +Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const { + out_npad_id = npad_id; + return ResultSuccess; +} + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h new file mode 100644 index 000000000..0ed1ff34c --- /dev/null +++ b/src/core/hle/service/nfc/common/device.h @@ -0,0 +1,146 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <span> + +#include "common/common_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nfc/mifare_types.h" +#include "core/hle/service/nfc/nfc_types.h" +#include "core/hle/service/nfp/nfp_types.h" +#include "core/hle/service/service.h" +#include "core/hle/service/time/clock_types.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} // namespace Core + +namespace Core::HID { +class EmulatedController; +enum class ControllerTriggerType; +enum class NpadIdType : u32; +} // namespace Core::HID + +namespace Service::NFC { +class NfcDevice { +public: + NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, + KernelHelpers::ServiceContext& service_context_, + Kernel::KEvent* availability_change_event_); + ~NfcDevice(); + + void Initialize(); + void Finalize(); + + Result StartDetection(NfcProtocol allowed_protocol); + Result StopDetection(); + + Result GetTagInfo(TagInfo& tag_info) const; + + Result ReadMifare(std::span<const MifareReadBlockParameter> parameters, + std::span<MifareReadBlockData> read_block_data) const; + + Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters); + + Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout, + std::span<const u8> command_data, std::span<u8> out_data); + + Result Mount(NFP::ModelType model_type, NFP::MountTarget mount_target); + Result Unmount(); + + Result Flush(); + Result FlushDebug(); + Result FlushWithBreak(NFP::BreakType break_type); + Result Restore(); + + Result GetCommonInfo(NFP::CommonInfo& common_info) const; + Result GetModelInfo(NFP::ModelInfo& model_info) const; + Result GetRegisterInfo(NFP::RegisterInfo& register_info) const; + Result GetRegisterInfoPrivate(NFP::RegisterInfoPrivate& register_info) const; + Result GetAdminInfo(NFP::AdminInfo& admin_info) const; + + Result DeleteRegisterInfo(); + Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info); + Result RestoreAmiibo(); + Result Format(); + + Result OpenApplicationArea(u32 access_id); + Result GetApplicationAreaId(u32& application_area_id) const; + Result GetApplicationArea(std::span<u8> data) const; + Result SetApplicationArea(std::span<const u8> data); + Result CreateApplicationArea(u32 access_id, std::span<const u8> data); + Result RecreateApplicationArea(u32 access_id, std::span<const u8> data); + Result DeleteApplicationArea(); + Result ExistsApplicationArea(bool& has_application_area) const; + + Result GetAll(NFP::NfpData& data) const; + Result SetAll(const NFP::NfpData& data); + Result BreakTag(NFP::BreakType break_type); + Result HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const; + Result HasBackup(const NFP::TagUuid& tag_uid) const; + Result ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, + std::span<u8> data) const; + Result ReadBackupData(const NFP::TagUuid& tag_uid, std::span<u8> data) const; + Result WriteBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, + std::span<const u8> data); + Result WriteBackupData(const NFP::TagUuid& tag_uid, std::span<const u8> data); + Result WriteNtf(std::span<const u8> data); + + u64 GetHandle() const; + DeviceState GetCurrentState() const; + Result GetNpadId(Core::HID::NpadIdType& out_npad_id) const; + + Kernel::KReadableEvent& GetActivateEvent() const; + Kernel::KReadableEvent& GetDeactivateEvent() const; + +private: + void NpadUpdate(Core::HID::ControllerTriggerType type); + bool LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid); + bool LoadAmiiboData(); + void CloseNfcTag(); + + NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const; + void SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name) const; + NFP::AmiiboDate GetAmiiboDate(s64 posix_time) const; + u64 GetCurrentPosixTime() const; + u64 RemoveVersionByte(u64 application_id) const; + void UpdateSettingsCrc(); + void UpdateRegisterInfoCrc(); + + void BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, + const NFP::EncryptedNTAG215File& encrypted_file) const; + + bool is_controller_set{}; + int callback_key; + const Core::HID::NpadIdType npad_id; + Core::System& system; + Core::HID::EmulatedController* npad_device = nullptr; + KernelHelpers::ServiceContext& service_context; + Kernel::KEvent* activate_event = nullptr; + Kernel::KEvent* deactivate_event = nullptr; + Kernel::KEvent* availability_change_event = nullptr; + + bool is_initalized{}; + NfcProtocol allowed_protocols{}; + DeviceState device_state{DeviceState::Unavailable}; + + // NFP data + bool is_data_moddified{}; + bool is_app_area_open{}; + bool is_plain_amiibo{}; + bool is_write_protected{}; + NFP::MountTarget mount_target{NFP::MountTarget::None}; + + TagInfo real_tag_info{}; + NFP::NTAG215File tag_data{}; + NFP::EncryptedNTAG215File encrypted_tag_data{}; +}; + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp new file mode 100644 index 000000000..562f3a28e --- /dev/null +++ b/src/core/hle/service/nfc/common/device_manager.cpp @@ -0,0 +1,708 @@ +// 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/hid/hid_types.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nfc/common/device.h" +#include "core/hle/service/nfc/common/device_manager.h" +#include "core/hle/service/nfc/nfc_result.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::NFC { + +DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContext& service_context_) + : system{system_}, service_context{service_context_} { + + availability_change_event = + service_context.CreateEvent("Nfc:DeviceManager:AvailabilityChangeEvent"); + + for (u32 device_index = 0; device_index < devices.size(); device_index++) { + devices[device_index] = + std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, + service_context, availability_change_event); + } + + is_initialized = false; +} + +DeviceManager ::~DeviceManager() { + if (is_initialized) { + Finalize(); + } + service_context.CloseEvent(availability_change_event); +} + +Result DeviceManager::Initialize() { + for (auto& device : devices) { + device->Initialize(); + } + is_initialized = true; + return ResultSuccess; +} + +Result DeviceManager::Finalize() { + for (auto& device : devices) { + device->Finalize(); + } + is_initialized = false; + return ResultSuccess; +} + +Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, + std::size_t max_allowed_devices) const { + for (auto& device : devices) { + if (nfp_devices.size() >= max_allowed_devices) { + continue; + } + if (device->GetCurrentState() != DeviceState::Unavailable) { + nfp_devices.push_back(device->GetHandle()); + } + } + + if (nfp_devices.empty()) { + return ResultDeviceNotFound; + } + + return ResultSuccess; +} + +DeviceState DeviceManager::GetDeviceState(u64 device_handle) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + const auto result = GetDeviceFromHandle(device_handle, device, false); + + if (result.IsSuccess()) { + return device->GetCurrentState(); + } + + return DeviceState::Unavailable; +} + +Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetNpadId(npad_id); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Kernel::KReadableEvent& DeviceManager::AttachAvailabilityChangeEvent() const { + return availability_change_event->GetReadableEvent(); +} + +Result DeviceManager::StartDetection(u64 device_handle, NfcProtocol tag_protocol) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->StartDetection(tag_protocol); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::StopDetection(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->StopDetection(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetTagInfo(tag_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Kernel::KReadableEvent& DeviceManager::AttachActivateEvent(u64 device_handle) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + GetDeviceFromHandle(device_handle, device, false); + + // TODO: Return proper error code on failure + return device->GetActivateEvent(); +} + +Kernel::KReadableEvent& DeviceManager::AttachDeactivateEvent(u64 device_handle) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + GetDeviceFromHandle(device_handle, device, false); + + // TODO: Return proper error code on failure + return device->GetDeactivateEvent(); +} + +Result DeviceManager::ReadMifare(u64 device_handle, + std::span<const MifareReadBlockParameter> read_parameters, + std::span<MifareReadBlockData> read_data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->ReadMifare(read_parameters, read_data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::WriteMifare(u64 device_handle, + std::span<const MifareWriteBlockParameter> write_parameters) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->WriteMifare(write_parameters); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::SendCommandByPassThrough(u64 device_handle, + const Time::Clock::TimeSpanType& timeout, + std::span<const u8> command_data, + std::span<u8> out_data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->SendCommandByPassThrough(timeout, command_data, out_data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::Mount(u64 device_handle, NFP::ModelType model_type, + NFP::MountTarget mount_target) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->Mount(model_type, mount_target); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::Unmount(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->Unmount(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::OpenApplicationArea(u64 device_handle, u32 access_id) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->OpenApplicationArea(access_id); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetApplicationArea(data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::SetApplicationArea(u64 device_handle, std::span<const u8> data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->SetApplicationArea(data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::Flush(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->Flush(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::Restore(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->Restore(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::CreateApplicationArea(u64 device_handle, u32 access_id, + std::span<const u8> data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->CreateApplicationArea(access_id, data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetRegisterInfo(register_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetCommonInfo(common_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetModelInfo(model_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +u32 DeviceManager::GetApplicationAreaSize() const { + return sizeof(NFP::ApplicationArea); +} + +Result DeviceManager::RecreateApplicationArea(u64 device_handle, u32 access_id, + std::span<const u8> data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->RecreateApplicationArea(access_id, data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::Format(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->Format(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetAdminInfo(admin_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle, + NFP::RegisterInfoPrivate& register_info) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetRegisterInfoPrivate(register_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::SetRegisterInfoPrivate(u64 device_handle, + const NFP::RegisterInfoPrivate& register_info) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->SetRegisterInfoPrivate(register_info); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::DeleteRegisterInfo(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->DeleteRegisterInfo(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::DeleteApplicationArea(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->DeleteApplicationArea(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->ExistsApplicationArea(has_application_area); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->GetAll(nfp_data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::SetAll(u64 device_handle, const NFP::NfpData& nfp_data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->SetAll(nfp_data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::FlushDebug(u64 device_handle) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->FlushDebug(); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::BreakTag(u64 device_handle, NFP::BreakType break_type) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->BreakTag(break_type); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) const { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + NFC::TagInfo tag_info{}; + + if (result.IsSuccess()) { + result = device->GetTagInfo(tag_info); + } + + if (result.IsSuccess()) { + result = device->ReadBackupData(tag_info.uuid, tag_info.uuid_length, data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + NFC::TagInfo tag_info{}; + + if (result.IsSuccess()) { + result = device->GetTagInfo(tag_info); + } + + if (result.IsSuccess()) { + result = device->WriteBackupData(tag_info.uuid, tag_info.uuid_length, data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data) { + std::scoped_lock lock{mutex}; + + std::shared_ptr<NfcDevice> device = nullptr; + auto result = GetDeviceHandle(device_handle, device); + + if (result.IsSuccess()) { + result = device->WriteNtf(data); + result = VerifyDeviceResult(device, result); + } + + return result; +} + +Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device, + bool check_state) const { + if (check_state) { + const Result is_parameter_set = IsNfcParameterSet(); + if (is_parameter_set.IsError()) { + return is_parameter_set; + } + const Result is_enabled = IsNfcEnabled(); + if (is_enabled.IsError()) { + return is_enabled; + } + const Result is_nfc_initialized = IsNfcInitialized(); + if (is_nfc_initialized.IsError()) { + return is_nfc_initialized; + } + } + + for (auto& device : devices) { + if (device->GetHandle() == handle) { + nfc_device = device; + return ResultSuccess; + } + } + + return ResultDeviceNotFound; +} + +std::optional<std::shared_ptr<NfcDevice>> DeviceManager::GetNfcDevice(u64 handle) { + for (auto& device : devices) { + if (device->GetHandle() == handle) { + return device; + } + } + return std::nullopt; +} + +const std::optional<std::shared_ptr<NfcDevice>> DeviceManager::GetNfcDevice(u64 handle) const { + for (auto& device : devices) { + if (device->GetHandle() == handle) { + return device; + } + } + return std::nullopt; +} + +Result DeviceManager::GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const { + const auto result = GetDeviceFromHandle(handle, device, true); + if (result.IsError()) { + return result; + } + return CheckDeviceState(device); +} + +Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device, + Result operation_result) const { + if (operation_result.IsSuccess()) { + return operation_result; + } + + const Result is_parameter_set = IsNfcParameterSet(); + if (is_parameter_set.IsError()) { + return is_parameter_set; + } + const Result is_enabled = IsNfcEnabled(); + if (is_enabled.IsError()) { + return is_enabled; + } + const Result is_nfc_initialized = IsNfcInitialized(); + if (is_nfc_initialized.IsError()) { + return is_nfc_initialized; + } + const Result device_state = CheckDeviceState(device); + if (device_state.IsError()) { + return device_state; + } + + return operation_result; +} + +Result DeviceManager::CheckDeviceState(std::shared_ptr<NfcDevice> device) const { + if (device == nullptr) { + return ResultInvalidArgument; + } + + return ResultSuccess; +} + +Result DeviceManager::IsNfcEnabled() const { + // TODO: This calls nn::settings::detail::GetNfcEnableFlag + const bool is_enabled = true; + if (!is_enabled) { + return ResultNfcDisabled; + } + return ResultSuccess; +} + +Result DeviceManager::IsNfcParameterSet() const { + // TODO: This calls checks against a bool on offset 0x450 + const bool is_set = true; + if (!is_set) { + return ResultUnknown76; + } + return ResultSuccess; +} + +Result DeviceManager::IsNfcInitialized() const { + if (!is_initialized) { + return ResultNfcNotInitialized; + } + return ResultSuccess; +} + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h new file mode 100644 index 000000000..c61ba0cf3 --- /dev/null +++ b/src/core/hle/service/nfc/common/device_manager.h @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> +#include <memory> +#include <optional> +#include <span> + +#include "core/hid/hid_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nfc/mifare_types.h" +#include "core/hle/service/nfc/nfc_types.h" +#include "core/hle/service/nfp/nfp_types.h" +#include "core/hle/service/service.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::NFC { +class NfcDevice; + +class DeviceManager { +public: + explicit DeviceManager(Core::System& system_, KernelHelpers::ServiceContext& service_context_); + ~DeviceManager(); + + // Nfc device manager + Result Initialize(); + Result Finalize(); + Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices) const; + DeviceState GetDeviceState(u64 device_handle) const; + Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const; + Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const; + Result StartDetection(u64 device_handle, NfcProtocol tag_protocol); + Result StopDetection(u64 device_handle); + Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const; + Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const; + Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const; + Result ReadMifare(u64 device_handle, + const std::span<const MifareReadBlockParameter> read_parameters, + std::span<MifareReadBlockData> read_data); + Result WriteMifare(u64 device_handle, + std::span<const MifareWriteBlockParameter> write_parameters); + Result SendCommandByPassThrough(u64 device_handle, const Time::Clock::TimeSpanType& timeout, + std::span<const u8> command_data, std::span<u8> out_data); + + // Nfp device manager + Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target); + Result Unmount(u64 device_handle); + Result OpenApplicationArea(u64 device_handle, u32 access_id); + Result GetApplicationArea(u64 device_handle, std::span<u8> data) const; + Result SetApplicationArea(u64 device_handle, std::span<const u8> data); + Result Flush(u64 device_handle); + Result Restore(u64 device_handle); + Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data); + Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const; + Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const; + Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const; + u32 GetApplicationAreaSize() const; + Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data); + Result Format(u64 device_handle); + Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const; + Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info) const; + Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info); + Result DeleteRegisterInfo(u64 device_handle); + Result DeleteApplicationArea(u64 device_handle); + Result ExistsApplicationArea(u64 device_handle, bool& has_application_area) const; + Result GetAll(u64 device_handle, NFP::NfpData& nfp_data) const; + Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data); + Result FlushDebug(u64 device_handle); + Result BreakTag(u64 device_handle, NFP::BreakType break_type); + Result ReadBackupData(u64 device_handle, std::span<u8> data) const; + Result WriteBackupData(u64 device_handle, std::span<const u8> data); + Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data); + +private: + Result IsNfcEnabled() const; + Result IsNfcParameterSet() const; + Result IsNfcInitialized() const; + + Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device, + bool check_state) const; + + Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const; + Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result) const; + Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const; + + std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); + const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const; + + bool is_initialized = false; + mutable std::mutex mutex; + std::array<std::shared_ptr<NfcDevice>, 10> devices{}; + + Core::System& system; + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* availability_change_event; +}; + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/mifare_result.h b/src/core/hle/service/nfc/mifare_result.h new file mode 100644 index 000000000..16a9171e6 --- /dev/null +++ b/src/core/hle/service/nfc/mifare_result.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/result.h" + +namespace Service::NFC::Mifare { + +constexpr Result ResultDeviceNotFound(ErrorModule::NFCMifare, 64); +constexpr Result ResultInvalidArgument(ErrorModule::NFCMifare, 65); +constexpr Result ResultWrongDeviceState(ErrorModule::NFCMifare, 73); +constexpr Result ResultNfcDisabled(ErrorModule::NFCMifare, 80); +constexpr Result ResultTagRemoved(ErrorModule::NFCMifare, 97); +constexpr Result ResultNotAMifare(ErrorModule::NFCMifare, 288); + +} // namespace Service::NFC::Mifare diff --git a/src/core/hle/service/nfc/mifare_types.h b/src/core/hle/service/nfc/mifare_types.h new file mode 100644 index 000000000..467937399 --- /dev/null +++ b/src/core/hle/service/nfc/mifare_types.h @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> + +#include "common/common_funcs.h" +#include "common/common_types.h" + +namespace Service::NFC { + +enum class MifareCmd : u8 { + None = 0x00, + Read = 0x30, + AuthA = 0x60, + AuthB = 0x61, + Write = 0xA0, + Transfer = 0xB0, + Decrement = 0xC0, + Increment = 0xC1, + Store = 0xC2 +}; + +using DataBlock = std::array<u8, 0x10>; +using KeyData = std::array<u8, 0x6>; + +struct SectorKey { + MifareCmd command; + u8 unknown; // Usually 1 + INSERT_PADDING_BYTES(0x6); + KeyData sector_key; + INSERT_PADDING_BYTES(0x2); +}; +static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size"); + +// This is nn::nfc::MifareReadBlockParameter +struct MifareReadBlockParameter { + u8 sector_number{}; + INSERT_PADDING_BYTES(0x7); + SectorKey sector_key{}; +}; +static_assert(sizeof(MifareReadBlockParameter) == 0x18, + "MifareReadBlockParameter is an invalid size"); + +// This is nn::nfc::MifareReadBlockData +struct MifareReadBlockData { + DataBlock data{}; + u8 sector_number{}; + INSERT_PADDING_BYTES(0x7); +}; +static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size"); + +// This is nn::nfc::MifareWriteBlockParameter +struct MifareWriteBlockParameter { + DataBlock data; + u8 sector_number; + INSERT_PADDING_BYTES(0x7); + SectorKey sector_key; +}; +static_assert(sizeof(MifareWriteBlockParameter) == 0x28, + "MifareWriteBlockParameter is an invalid size"); + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/mifare_user.cpp b/src/core/hle/service/nfc/mifare_user.cpp deleted file mode 100644 index 51523a3ae..000000000 --- a/src/core/hle/service/nfc/mifare_user.cpp +++ /dev/null @@ -1,400 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/nfc/mifare_user.h" -#include "core/hle/service/nfc/nfc_device.h" -#include "core/hle/service/nfc/nfc_result.h" - -namespace Service::NFC { - -MFIUser::MFIUser(Core::System& system_) - : ServiceFramework{system_, "NFC::MFIUser"}, service_context{system_, service_name} { - static const FunctionInfo functions[] = { - {0, &MFIUser::Initialize, "Initialize"}, - {1, &MFIUser::Finalize, "Finalize"}, - {2, &MFIUser::ListDevices, "ListDevices"}, - {3, &MFIUser::StartDetection, "StartDetection"}, - {4, &MFIUser::StopDetection, "StopDetection"}, - {5, &MFIUser::Read, "Read"}, - {6, &MFIUser::Write, "Write"}, - {7, &MFIUser::GetTagInfo, "GetTagInfo"}, - {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"}, - {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"}, - {10, &MFIUser::GetState, "GetState"}, - {11, &MFIUser::GetDeviceState, "GetDeviceState"}, - {12, &MFIUser::GetNpadId, "GetNpadId"}, - {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"}, - }; - RegisterHandlers(functions); - - availability_change_event = service_context.CreateEvent("MFIUser:AvailabilityChangeEvent"); - - for (u32 device_index = 0; device_index < 10; device_index++) { - devices[device_index] = - std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, - service_context, availability_change_event); - } -} - -MFIUser ::~MFIUser() { - availability_change_event->Close(); -} - -void MFIUser::Initialize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2, 0}; - rb.Push(ResultSuccess); -} - -void MFIUser::Finalize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void MFIUser::ListDevices(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareInvalidArgument); - return; - } - - if (ctx.GetWriteBufferSize() == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareInvalidArgument); - return; - } - - std::vector<u64> nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); - - for (const auto& device : devices) { - if (nfp_devices.size() >= max_allowed_devices) { - continue; - } - if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); - } - } - - if (nfp_devices.empty()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - ctx.WriteBuffer(nfp_devices); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<s32>(nfp_devices.size())); -} - -void MFIUser::StartDetection(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - const auto result = device.value()->StartDetection(NFP::TagProtocol::All); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::StopDetection(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - const auto result = device.value()->StopDetection(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::Read(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto buffer{ctx.ReadBuffer()}; - const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareReadBlockParameter>()}; - std::vector<NFP::MifareReadBlockParameter> read_commands(number_of_commands); - - memcpy(read_commands.data(), buffer.data(), - number_of_commands * sizeof(NFP::MifareReadBlockParameter)); - - LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}", - device_handle, number_of_commands); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - Result result = ResultSuccess; - std::vector<NFP::MifareReadBlockData> out_data(number_of_commands); - for (std::size_t i = 0; i < number_of_commands; i++) { - result = device.value()->MifareRead(read_commands[i], out_data[i]); - if (result.IsError()) { - break; - } - } - - ctx.WriteBuffer(out_data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::Write(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto buffer{ctx.ReadBuffer()}; - const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareWriteBlockParameter>()}; - std::vector<NFP::MifareWriteBlockParameter> write_commands(number_of_commands); - - memcpy(write_commands.data(), buffer.data(), - number_of_commands * sizeof(NFP::MifareWriteBlockParameter)); - - LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}", - device_handle, number_of_commands); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - Result result = ResultSuccess; - std::vector<NFP::MifareReadBlockData> out_data(number_of_commands); - for (std::size_t i = 0; i < number_of_commands; i++) { - result = device.value()->MifareWrite(write_commands[i]); - if (result.IsError()) { - break; - } - } - - if (result.IsSuccess()) { - result = device.value()->Flush(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::GetTagInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - NFP::TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info, true); - ctx.WriteBuffer(tag_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::GetActivateEventHandle(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetActivateEvent()); -} - -void MFIUser::GetDeactivateEventHandle(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetDeactivateEvent()); -} - -void MFIUser::GetState(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void MFIUser::GetDeviceState(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetCurrentState()); -} - -void MFIUser::GetNpadId(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetNpadId()); -} - -void MFIUser::GetAvailabilityChangeEventHandle(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(availability_change_event->GetReadableEvent()); -} - -std::optional<std::shared_ptr<NfcDevice>> MFIUser::GetNfcDevice(u64 handle) { - for (auto& device : devices) { - if (device->GetHandle() == handle) { - return device; - } - } - return std::nullopt; -} - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/mifare_user.h b/src/core/hle/service/nfc/mifare_user.h deleted file mode 100644 index 0e0638cb6..000000000 --- a/src/core/hle/service/nfc/mifare_user.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <memory> -#include <optional> - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::NFC { -class NfcDevice; - -class MFIUser final : public ServiceFramework<MFIUser> { -public: - explicit MFIUser(Core::System& system_); - ~MFIUser(); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - void Initialize(Kernel::HLERequestContext& ctx); - void Finalize(Kernel::HLERequestContext& ctx); - void ListDevices(Kernel::HLERequestContext& ctx); - void StartDetection(Kernel::HLERequestContext& ctx); - void StopDetection(Kernel::HLERequestContext& ctx); - void Read(Kernel::HLERequestContext& ctx); - void Write(Kernel::HLERequestContext& ctx); - void GetTagInfo(Kernel::HLERequestContext& ctx); - void GetActivateEventHandle(Kernel::HLERequestContext& ctx); - void GetDeactivateEventHandle(Kernel::HLERequestContext& ctx); - void GetState(Kernel::HLERequestContext& ctx); - void GetDeviceState(Kernel::HLERequestContext& ctx); - void GetNpadId(Kernel::HLERequestContext& ctx); - void GetAvailabilityChangeEventHandle(Kernel::HLERequestContext& ctx); - - std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); - - KernelHelpers::ServiceContext service_context; - - std::array<std::shared_ptr<NfcDevice>, 10> devices{}; - - State state{State::NonInitialized}; - Kernel::KEvent* availability_change_event; -}; - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index b17b18ab9..30ae989b9 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -5,15 +5,116 @@ #include "common/logging/log.h" #include "common/settings.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/service/nfc/mifare_user.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nfc/nfc.h" -#include "core/hle/service/nfc/nfc_user.h" +#include "core/hle/service/nfc/nfc_interface.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::NFC { +class IUser final : public NfcInterface { +public: + explicit IUser(Core::System& system_) : NfcInterface(system_, "NFC::IUser", BackendType::Nfc) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &NfcInterface::Initialize, "InitializeOld"}, + {1, &NfcInterface::Finalize, "FinalizeOld"}, + {2, &NfcInterface::GetState, "GetStateOld"}, + {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"}, + {400, &NfcInterface::Initialize, "Initialize"}, + {401, &NfcInterface::Finalize, "Finalize"}, + {402, &NfcInterface::GetState, "GetState"}, + {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"}, + {404, &NfcInterface::ListDevices, "ListDevices"}, + {405, &NfcInterface::GetDeviceState, "GetDeviceState"}, + {406, &NfcInterface::GetNpadId, "GetNpadId"}, + {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, + {408, &NfcInterface::StartDetection, "StartDetection"}, + {409, &NfcInterface::StopDetection, "StopDetection"}, + {410, &NfcInterface::GetTagInfo, "GetTagInfo"}, + {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"}, + {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"}, + {1000, &NfcInterface::ReadMifare, "ReadMifare"}, + {1001, &NfcInterface::WriteMifare ,"WriteMifare"}, + {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"}, + {1301, nullptr, "KeepPassThroughSession"}, + {1302, nullptr, "ReleasePassThroughSession"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class ISystem final : public NfcInterface { +public: + explicit ISystem(Core::System& system_) + : NfcInterface{system_, "NFC::ISystem", BackendType::Nfc} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &NfcInterface::Initialize, "InitializeOld"}, + {1, &NfcInterface::Finalize, "FinalizeOld"}, + {2, &NfcInterface::GetState, "GetStateOld"}, + {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"}, + {100, nullptr, "SetNfcEnabledOld"}, + {400, &NfcInterface::Initialize, "Initialize"}, + {401, &NfcInterface::Finalize, "Finalize"}, + {402, &NfcInterface::GetState, "GetState"}, + {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"}, + {404, &NfcInterface::ListDevices, "ListDevices"}, + {405, &NfcInterface::GetDeviceState, "GetDeviceState"}, + {406, &NfcInterface::GetNpadId, "GetNpadId"}, + {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, + {408, &NfcInterface::StartDetection, "StartDetection"}, + {409, &NfcInterface::StopDetection, "StopDetection"}, + {410, &NfcInterface::GetTagInfo, "GetTagInfo"}, + {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"}, + {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"}, + {500, nullptr, "SetNfcEnabled"}, + {510, nullptr, "OutputTestWave"}, + {1000, &NfcInterface::ReadMifare, "ReadMifare"}, + {1001, &NfcInterface::WriteMifare, "WriteMifare"}, + {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"}, + {1301, nullptr, "KeepPassThroughSession"}, + {1302, nullptr, "ReleasePassThroughSession"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +// MFInterface has an unique interface but it's identical to NfcInterface so we can keep the code +// simpler +using MFInterface = NfcInterface; +class MFIUser final : public MFInterface { +public: + explicit MFIUser(Core::System& system_) + : MFInterface{system_, "NFC::MFInterface", BackendType::Mifare} { + // clang-format off + static const FunctionInfoTyped<MFIUser> functions[] = { + {0, &MFIUser::Initialize, "Initialize"}, + {1, &MFIUser::Finalize, "Finalize"}, + {2, &MFIUser::ListDevices, "ListDevices"}, + {3, &MFIUser::StartDetection, "StartDetection"}, + {4, &MFIUser::StopDetection, "StopDetection"}, + {5, &MFIUser::ReadMifare, "Read"}, + {6, &MFIUser::WriteMifare, "Write"}, + {7, &MFIUser::GetTagInfo, "GetTagInfo"}, + {8, &MFIUser::AttachActivateEvent, "GetActivateEventHandle"}, + {9, &MFIUser::AttachDeactivateEvent, "GetDeactivateEventHandle"}, + {10, &MFIUser::GetState, "GetState"}, + {11, &MFIUser::GetDeviceState, "GetDeviceState"}, + {12, &MFIUser::GetNpadId, "GetNpadId"}, + {13, &MFIUser::AttachAvailabilityChangeEvent, "GetAvailabilityChangeEventHandle"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + class IAm final : public ServiceFramework<IAm> { public: explicit IAm(Core::System& system_) : ServiceFramework{system_, "NFC::IAm"} { @@ -34,7 +135,7 @@ public: explicit NFC_AM(Core::System& system_) : ServiceFramework{system_, "nfc:am"} { // clang-format off static const FunctionInfo functions[] = { - {0, &NFC_AM::CreateAmInterface, "CreateAmInterface"}, + {0, &NFC_AM::CreateAmNfcInterface, "CreateAmNfcInterface"}, }; // clang-format on @@ -42,7 +143,7 @@ public: } private: - void CreateAmInterface(Kernel::HLERequestContext& ctx) { + void CreateAmNfcInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -56,7 +157,7 @@ public: explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} { // clang-format off static const FunctionInfo functions[] = { - {0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"}, + {0, &NFC_MF_U::CreateUserNfcInterface, "CreateUserNfcInterface"}, }; // clang-format on @@ -64,7 +165,7 @@ public: } private: - void CreateUserInterface(Kernel::HLERequestContext& ctx) { + void CreateUserNfcInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -78,7 +179,7 @@ public: explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} { // clang-format off static const FunctionInfo functions[] = { - {0, &NFC_U::CreateUserInterface, "CreateUserInterface"}, + {0, &NFC_U::CreateUserNfcInterface, "CreateUserNfcInterface"}, }; // clang-format on @@ -86,7 +187,7 @@ public: } private: - void CreateUserInterface(Kernel::HLERequestContext& ctx) { + void CreateUserNfcInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -95,49 +196,12 @@ private: } }; -class ISystem final : public ServiceFramework<ISystem> { -public: - explicit ISystem(Core::System& system_) : ServiceFramework{system_, "ISystem"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {1, nullptr, "Finalize"}, - {2, nullptr, "GetStateOld"}, - {3, nullptr, "IsNfcEnabledOld"}, - {100, nullptr, "SetNfcEnabledOld"}, - {400, nullptr, "InitializeSystem"}, - {401, nullptr, "FinalizeSystem"}, - {402, nullptr, "GetState"}, - {403, nullptr, "IsNfcEnabled"}, - {404, nullptr, "ListDevices"}, - {405, nullptr, "GetDeviceState"}, - {406, nullptr, "GetNpadId"}, - {407, nullptr, "AttachAvailabilityChangeEvent"}, - {408, nullptr, "StartDetection"}, - {409, nullptr, "StopDetection"}, - {410, nullptr, "GetTagInfo"}, - {411, nullptr, "AttachActivateEvent"}, - {412, nullptr, "AttachDeactivateEvent"}, - {500, nullptr, "SetNfcEnabled"}, - {510, nullptr, "OutputTestWave"}, - {1000, nullptr, "ReadMifare"}, - {1001, nullptr, "WriteMifare"}, - {1300, nullptr, "SendCommandByPassThrough"}, - {1301, nullptr, "KeepPassThroughSession"}, - {1302, nullptr, "ReleasePassThroughSession"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - class NFC_SYS final : public ServiceFramework<NFC_SYS> { public: explicit NFC_SYS(Core::System& system_) : ServiceFramework{system_, "nfc:sys"} { // clang-format off static const FunctionInfo functions[] = { - {0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"}, + {0, &NFC_SYS::CreateSystemNfcInterface, "CreateSystemNfcInterface"}, }; // clang-format on @@ -145,7 +209,7 @@ public: } private: - void CreateSystemInterface(Kernel::HLERequestContext& ctx) { + void CreateSystemNfcInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -154,11 +218,15 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<NFC_AM>(system)->InstallAsService(sm); - std::make_shared<NFC_MF_U>(system)->InstallAsService(sm); - std::make_shared<NFC_U>(system)->InstallAsService(sm); - std::make_shared<NFC_SYS>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("nfc:am", std::make_shared<NFC_AM>(system)); + server_manager->RegisterNamedService("nfc:mf:u", std::make_shared<NFC_MF_U>(system)); + server_manager->RegisterNamedService("nfc:user", std::make_shared<NFC_U>(system)); + server_manager->RegisterNamedService("nfc:sys", std::make_shared<NFC_SYS>(system)); + + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h index 0107b696c..d15955b75 100644 --- a/src/core/hle/service/nfc/nfc.h +++ b/src/core/hle/service/nfc/nfc.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::NFC { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp deleted file mode 100644 index 78578f723..000000000 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/input.h" -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/nfc/nfc_device.h" -#include "core/hle/service/nfc/nfc_result.h" -#include "core/hle/service/nfc/nfc_user.h" - -namespace Service::NFC { -NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_) - : npad_id{npad_id_}, system{system_}, service_context{service_context_}, - availability_change_event{availability_change_event_} { - activate_event = service_context.CreateEvent("IUser:NFCActivateEvent"); - deactivate_event = service_context.CreateEvent("IUser:NFCDeactivateEvent"); - npad_device = system.HIDCore().GetEmulatedController(npad_id); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); }, - .is_npad_service = false, - }; - is_controller_set = true; - callback_key = npad_device->SetCallback(engine_callback); -} - -NfcDevice::~NfcDevice() { - activate_event->Close(); - deactivate_event->Close(); - if (!is_controller_set) { - return; - } - npad_device->DeleteCallback(callback_key); - is_controller_set = false; -}; - -void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Connected || - type == Core::HID::ControllerTriggerType::Disconnected) { - availability_change_event->Signal(); - return; - } - - if (type != Core::HID::ControllerTriggerType::Nfc) { - return; - } - - if (!npad_device->IsConnected()) { - return; - } - - const auto nfc_status = npad_device->GetNfc(); - switch (nfc_status.state) { - case Common::Input::NfcState::NewAmiibo: - LoadNfcTag(nfc_status.data); - break; - case Common::Input::NfcState::AmiiboRemoved: - if (device_state != NFP::DeviceState::SearchingForTag) { - CloseNfcTag(); - } - break; - default: - break; - } -} - -bool NfcDevice::LoadNfcTag(std::span<const u8> data) { - if (device_state != NFP::DeviceState::SearchingForTag) { - LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state); - return false; - } - - if (data.size() < sizeof(NFP::EncryptedNTAG215File)) { - LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); - return false; - } - - tag_data.resize(data.size()); - memcpy(tag_data.data(), data.data(), data.size()); - memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); - - device_state = NFP::DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(); - activate_event->Signal(); - return true; -} - -void NfcDevice::CloseNfcTag() { - LOG_INFO(Service_NFC, "Remove nfc tag"); - - device_state = NFP::DeviceState::TagRemoved; - encrypted_tag_data = {}; - activate_event->GetReadableEvent().Clear(); - deactivate_event->Signal(); -} - -Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { - return activate_event->GetReadableEvent(); -} - -Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const { - return deactivate_event->GetReadableEvent(); -} - -void NfcDevice::Initialize() { - device_state = - npad_device->HasNfc() ? NFP::DeviceState::Initialized : NFP::DeviceState::Unavailable; - encrypted_tag_data = {}; -} - -void NfcDevice::Finalize() { - if (device_state == NFP::DeviceState::SearchingForTag || - device_state == NFP::DeviceState::TagRemoved) { - StopDetection(); - } - device_state = NFP::DeviceState::Unavailable; -} - -Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { - if (device_state != NFP::DeviceState::Initialized && - device_state != NFP::DeviceState::TagRemoved) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - return WrongDeviceState; - } - - if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) { - LOG_ERROR(Service_NFC, "Nfc not supported"); - return NfcDisabled; - } - - device_state = NFP::DeviceState::SearchingForTag; - allowed_protocols = allowed_protocol; - return ResultSuccess; -} - -Result NfcDevice::StopDetection() { - npad_device->SetPollingMode(Common::Input::PollingMode::Active); - - if (device_state == NFP::DeviceState::Initialized) { - return ResultSuccess; - } - - if (device_state == NFP::DeviceState::TagFound || - device_state == NFP::DeviceState::TagMounted) { - CloseNfcTag(); - return ResultSuccess; - } - if (device_state == NFP::DeviceState::SearchingForTag || - device_state == NFP::DeviceState::TagRemoved) { - device_state = NFP::DeviceState::Initialized; - return ResultSuccess; - } - - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - return WrongDeviceState; -} - -Result NfcDevice::Flush() { - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (!npad_device->WriteNfc(tag_data)) { - LOG_ERROR(Service_NFP, "Error writing to file"); - return MifareReadError; - } - - return ResultSuccess; -} - -Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (is_mifare) { - tag_info = { - .uuid = encrypted_tag_data.uuid.uid, - .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()), - .protocol = NFP::TagProtocol::TypeA, - .tag_type = NFP::TagType::Type4, - }; - return ResultSuccess; - } - - // Protocol and tag type may change here - tag_info = { - .uuid = encrypted_tag_data.uuid.uid, - .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()), - .protocol = NFP::TagProtocol::TypeA, - .tag_type = NFP::TagType::Type2, - }; - - return ResultSuccess; -} - -Result NfcDevice::MifareRead(const NFP::MifareReadBlockParameter& parameter, - NFP::MifareReadBlockData& read_block_data) { - const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock); - read_block_data.sector_number = parameter.sector_number; - - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) { - return MifareReadError; - } - - // TODO: Use parameter.sector_key to read encrypted data - memcpy(read_block_data.data.data(), tag_data.data() + sector_index, sizeof(NFP::DataBlock)); - - return ResultSuccess; -} - -Result NfcDevice::MifareWrite(const NFP::MifareWriteBlockParameter& parameter) { - const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock); - - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) { - return MifareReadError; - } - - // TODO: Use parameter.sector_key to encrypt the data - memcpy(tag_data.data() + sector_index, parameter.data.data(), sizeof(NFP::DataBlock)); - - return ResultSuccess; -} - -u64 NfcDevice::GetHandle() const { - // Generate a handle based of the npad id - return static_cast<u64>(npad_id); -} - -NFP::DeviceState NfcDevice::GetCurrentState() const { - return device_state; -} - -Core::HID::NpadIdType NfcDevice::GetNpadId() const { - return npad_id; -} - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h deleted file mode 100644 index a6e114d36..000000000 --- a/src/core/hle/service/nfc/nfc_device.h +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nfp/nfp_types.h" -#include "core/hle/service/service.h" - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Core { -class System; -} // namespace Core - -namespace Core::HID { -class EmulatedController; -enum class ControllerTriggerType; -enum class NpadIdType : u32; -} // namespace Core::HID - -namespace Service::NFC { -class NfcDevice { -public: - NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_); - ~NfcDevice(); - - void Initialize(); - void Finalize(); - - Result StartDetection(NFP::TagProtocol allowed_protocol); - Result StopDetection(); - Result Flush(); - - Result GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const; - - Result MifareRead(const NFP::MifareReadBlockParameter& parameter, - NFP::MifareReadBlockData& read_block_data); - - Result MifareWrite(const NFP::MifareWriteBlockParameter& parameter); - - u64 GetHandle() const; - NFP::DeviceState GetCurrentState() const; - Core::HID::NpadIdType GetNpadId() const; - - Kernel::KReadableEvent& GetActivateEvent() const; - Kernel::KReadableEvent& GetDeactivateEvent() const; - -private: - void NpadUpdate(Core::HID::ControllerTriggerType type); - bool LoadNfcTag(std::span<const u8> data); - void CloseNfcTag(); - - bool is_controller_set{}; - int callback_key; - const Core::HID::NpadIdType npad_id; - Core::System& system; - Core::HID::EmulatedController* npad_device = nullptr; - KernelHelpers::ServiceContext& service_context; - Kernel::KEvent* activate_event = nullptr; - Kernel::KEvent* deactivate_event = nullptr; - Kernel::KEvent* availability_change_event = nullptr; - - NFP::TagProtocol allowed_protocols{}; - NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; - - NFP::EncryptedNTAG215File encrypted_tag_data{}; - std::vector<u8> tag_data{}; -}; - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp new file mode 100644 index 000000000..e7ca7582e --- /dev/null +++ b/src/core/hle/service/nfc/nfc_interface.cpp @@ -0,0 +1,394 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/hid/hid_types.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nfc/common/device.h" +#include "core/hle/service/nfc/common/device_manager.h" +#include "core/hle/service/nfc/mifare_result.h" +#include "core/hle/service/nfc/mifare_types.h" +#include "core/hle/service/nfc/nfc_interface.h" +#include "core/hle/service/nfc/nfc_result.h" +#include "core/hle/service/nfc/nfc_types.h" +#include "core/hle/service/nfp/nfp_result.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::NFC { + +NfcInterface::NfcInterface(Core::System& system_, const char* name, BackendType service_backend) + : ServiceFramework{system_, name}, service_context{system_, service_name}, + backend_type{service_backend} {} + +NfcInterface ::~NfcInterface() = default; + +void NfcInterface::Initialize(HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + auto manager = GetManager(); + auto result = manager->Initialize(); + + if (result.IsSuccess()) { + state = State::Initialized; + } else { + manager->Finalize(); + } + + IPC::ResponseBuilder rb{ctx, 2, 0}; + rb.Push(result); +} + +void NfcInterface::Finalize(HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + if (state != State::NonInitialized) { + if (GetBackendType() != BackendType::None) { + GetManager()->Finalize(); + } + device_manager = nullptr; + state = State::NonInitialized; + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void NfcInterface::GetState(HLERequestContext& ctx) { + LOG_DEBUG(Service_NFC, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(state); +} + +void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) { + LOG_DEBUG(Service_NFC, "called"); + + // TODO: This calls nn::settings::detail::GetNfcEnableFlag + const bool is_enabled = true; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(is_enabled); +} + +void NfcInterface::ListDevices(HLERequestContext& ctx) { + std::vector<u64> nfp_devices; + const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); + LOG_DEBUG(Service_NFC, "called"); + + auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices); + result = TranslateResultToServiceError(result); + + if (result.IsError()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + ctx.WriteBuffer(nfp_devices); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<s32>(nfp_devices.size())); +} + +void NfcInterface::GetDeviceState(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + const auto device_state = GetManager()->GetDeviceState(device_handle); + + if (device_state > DeviceState::Finalized) { + ASSERT_MSG(false, "Invalid device state"); + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(device_state); +} + +void NfcInterface::GetNpadId(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + Core::HID::NpadIdType npad_id{}; + auto result = GetManager()->GetNpadId(device_handle, npad_id); + result = TranslateResultToServiceError(result); + + if (result.IsError()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(npad_id); +} + +void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(GetManager()->AttachAvailabilityChangeEvent()); +} + +void NfcInterface::StartDetection(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + auto tag_protocol{NfcProtocol::All}; + + if (backend_type == BackendType::Nfc) { + tag_protocol = rp.PopEnum<NfcProtocol>(); + } + + LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol); + auto result = GetManager()->StartDetection(device_handle, tag_protocol); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void NfcInterface::StopDetection(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); + + auto result = GetManager()->StopDetection(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void NfcInterface::GetTagInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); + + TagInfo tag_info{}; + auto result = GetManager()->GetTagInfo(device_handle, tag_info); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(tag_info); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle)); +} + +void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle)); +} + +void NfcInterface::ReadMifare(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto buffer{ctx.ReadBuffer()}; + const auto number_of_commands{ctx.GetReadBufferNumElements<MifareReadBlockParameter>()}; + std::vector<MifareReadBlockParameter> read_commands(number_of_commands); + + memcpy(read_commands.data(), buffer.data(), + number_of_commands * sizeof(MifareReadBlockParameter)); + + LOG_INFO(Service_NFC, "called, device_handle={}, read_commands_size={}", device_handle, + number_of_commands); + + std::vector<MifareReadBlockData> out_data(number_of_commands); + auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(out_data); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void NfcInterface::WriteMifare(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto buffer{ctx.ReadBuffer()}; + const auto number_of_commands{ctx.GetReadBufferNumElements<MifareWriteBlockParameter>()}; + std::vector<MifareWriteBlockParameter> write_commands(number_of_commands); + + memcpy(write_commands.data(), buffer.data(), + number_of_commands * sizeof(MifareWriteBlockParameter)); + + LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}", + device_handle, number_of_commands); + + auto result = GetManager()->WriteMifare(device_handle, write_commands); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()}; + const auto command_data{ctx.ReadBuffer()}; + LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", + device_handle, timeout.ToSeconds(), command_data.size()); + + std::vector<u8> out_data(1); + auto result = + GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data); + result = TranslateResultToServiceError(result); + + if (result.IsError()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + ctx.WriteBuffer(out_data); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<u32>(out_data.size())); +} + +std::shared_ptr<DeviceManager> NfcInterface::GetManager() { + if (device_manager == nullptr) { + device_manager = std::make_shared<DeviceManager>(system, service_context); + } + return device_manager; +} + +BackendType NfcInterface::GetBackendType() const { + return backend_type; +} + +Result NfcInterface::TranslateResultToServiceError(Result result) const { + const auto backend = GetBackendType(); + + if (result.IsSuccess()) { + return result; + } + + if (result.module != ErrorModule::NFC) { + return result; + } + + switch (backend) { + case BackendType::Mifare: + return TranslateResultToNfp(result); + case BackendType::Nfp: { + return TranslateResultToNfp(result); + } + default: + if (result != ResultBackupPathAlreadyExist) { + return result; + } + return ResultUnknown74; + } +} + +Result NfcInterface::TranslateResultToNfp(Result result) const { + if (result == ResultDeviceNotFound) { + return NFP::ResultDeviceNotFound; + } + if (result == ResultInvalidArgument) { + return NFP::ResultInvalidArgument; + } + if (result == ResultWrongApplicationAreaSize) { + return NFP::ResultWrongApplicationAreaSize; + } + if (result == ResultWrongDeviceState) { + return NFP::ResultWrongDeviceState; + } + if (result == ResultUnknown74) { + return NFP::ResultUnknown74; + } + if (result == ResultNfcDisabled) { + return NFP::ResultNfcDisabled; + } + if (result == ResultNfcNotInitialized) { + return NFP::ResultNfcDisabled; + } + if (result == ResultWriteAmiiboFailed) { + return NFP::ResultWriteAmiiboFailed; + } + if (result == ResultTagRemoved) { + return NFP::ResultTagRemoved; + } + if (result == ResultRegistrationIsNotInitialized) { + return NFP::ResultRegistrationIsNotInitialized; + } + if (result == ResultApplicationAreaIsNotInitialized) { + return NFP::ResultApplicationAreaIsNotInitialized; + } + if (result == ResultCorruptedDataWithBackup) { + return NFP::ResultCorruptedDataWithBackup; + } + if (result == ResultCorruptedData) { + return NFP::ResultCorruptedData; + } + if (result == ResultWrongApplicationAreaId) { + return NFP::ResultWrongApplicationAreaId; + } + if (result == ResultApplicationAreaExist) { + return NFP::ResultApplicationAreaExist; + } + if (result == ResultInvalidTagType) { + return NFP::ResultNotAnAmiibo; + } + if (result == ResultUnableToAccessBackupFile) { + return NFP::ResultUnableToAccessBackupFile; + } + LOG_WARNING(Service_NFC, "Result conversion not handled"); + return result; +} + +Result NfcInterface::TranslateResultToMifare(Result result) const { + if (result == ResultDeviceNotFound) { + return Mifare::ResultDeviceNotFound; + } + if (result == ResultInvalidArgument) { + return Mifare::ResultInvalidArgument; + } + if (result == ResultWrongDeviceState) { + return Mifare::ResultWrongDeviceState; + } + if (result == ResultNfcDisabled) { + return Mifare::ResultNfcDisabled; + } + if (result == ResultTagRemoved) { + return Mifare::ResultTagRemoved; + } + if (result == ResultInvalidTagType) { + return Mifare::ResultNotAMifare; + } + LOG_WARNING(Service_NFC, "Result conversion not handled"); + return result; +} + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_interface.h b/src/core/hle/service/nfc/nfc_interface.h new file mode 100644 index 000000000..08be174d8 --- /dev/null +++ b/src/core/hle/service/nfc/nfc_interface.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nfc/nfc_types.h" +#include "core/hle/service/service.h" + +namespace Service::NFC { +class DeviceManager; + +class NfcInterface : public ServiceFramework<NfcInterface> { +public: + explicit NfcInterface(Core::System& system_, const char* name, BackendType service_backend); + ~NfcInterface(); + + void Initialize(HLERequestContext& ctx); + void Finalize(HLERequestContext& ctx); + void GetState(HLERequestContext& ctx); + void IsNfcEnabled(HLERequestContext& ctx); + void ListDevices(HLERequestContext& ctx); + void GetDeviceState(HLERequestContext& ctx); + void GetNpadId(HLERequestContext& ctx); + void AttachAvailabilityChangeEvent(HLERequestContext& ctx); + void StartDetection(HLERequestContext& ctx); + void StopDetection(HLERequestContext& ctx); + void GetTagInfo(HLERequestContext& ctx); + void AttachActivateEvent(HLERequestContext& ctx); + void AttachDeactivateEvent(HLERequestContext& ctx); + void ReadMifare(HLERequestContext& ctx); + void WriteMifare(HLERequestContext& ctx); + void SendCommandByPassThrough(HLERequestContext& ctx); + +protected: + std::shared_ptr<DeviceManager> GetManager(); + BackendType GetBackendType() const; + Result TranslateResultToServiceError(Result result) const; + Result TranslateResultToNfp(Result result) const; + Result TranslateResultToMifare(Result result) const; + + KernelHelpers::ServiceContext service_context; + + BackendType backend_type; + State state{State::NonInitialized}; + std::shared_ptr<DeviceManager> device_manager = nullptr; +}; + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h index 146b8ba61..715c0e80c 100644 --- a/src/core/hle/service/nfc/nfc_result.h +++ b/src/core/hle/service/nfc/nfc_result.h @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later #pragma once @@ -7,17 +7,25 @@ namespace Service::NFC { -constexpr Result DeviceNotFound(ErrorModule::NFC, 64); -constexpr Result InvalidArgument(ErrorModule::NFC, 65); -constexpr Result WrongDeviceState(ErrorModule::NFC, 73); -constexpr Result NfcDisabled(ErrorModule::NFC, 80); -constexpr Result TagRemoved(ErrorModule::NFC, 97); - -constexpr Result MifareDeviceNotFound(ErrorModule::NFCMifare, 64); -constexpr Result MifareInvalidArgument(ErrorModule::NFCMifare, 65); -constexpr Result MifareWrongDeviceState(ErrorModule::NFCMifare, 73); -constexpr Result MifareNfcDisabled(ErrorModule::NFCMifare, 80); -constexpr Result MifareTagRemoved(ErrorModule::NFCMifare, 97); -constexpr Result MifareReadError(ErrorModule::NFCMifare, 288); +constexpr Result ResultDeviceNotFound(ErrorModule::NFC, 64); +constexpr Result ResultInvalidArgument(ErrorModule::NFC, 65); +constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFC, 68); +constexpr Result ResultWrongDeviceState(ErrorModule::NFC, 73); +constexpr Result ResultUnknown74(ErrorModule::NFC, 74); +constexpr Result ResultUnknown76(ErrorModule::NFC, 76); +constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77); +constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80); +constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88); +constexpr Result ResultTagRemoved(ErrorModule::NFC, 97); +constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113); +constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120); +constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128); +constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136); +constexpr Result ResultCorruptedData(ErrorModule::NFC, 144); +constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFC, 152); +constexpr Result ResultApplicationAreaExist(ErrorModule::NFC, 168); +constexpr Result ResultInvalidTagType(ErrorModule::NFC, 178); +constexpr Result ResultBackupPathAlreadyExist(ErrorModule::NFC, 216); +constexpr Result ResultMifareError288(ErrorModule::NFC, 288); } // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_types.h b/src/core/hle/service/nfc/nfc_types.h new file mode 100644 index 000000000..68e724442 --- /dev/null +++ b/src/core/hle/service/nfc/nfc_types.h @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> + +#include "common/common_funcs.h" +#include "common/common_types.h" + +namespace Service::NFC { +enum class BackendType : u32 { + None, + Nfc, + Nfp, + Mifare, +}; + +// This is nn::nfc::DeviceState +enum class DeviceState : u32 { + Initialized, + SearchingForTag, + TagFound, + TagRemoved, + TagMounted, + Unavailable, + Finalized, +}; + +// This is nn::nfc::State +enum class State : u32 { + NonInitialized, + Initialized, +}; + +// This is nn::nfc::TagType +enum class TagType : u32 { + None = 0, + Type1 = 1U << 0, // ISO14443A RW. Topaz + Type2 = 1U << 1, // ISO14443A RW. Ultralight, NTAGX, ST25TN + Type3 = 1U << 2, // ISO14443A RW/RO. Sony FeliCa + Type4A = 1U << 3, // ISO14443A RW/RO. DESFire + Type4B = 1U << 4, // ISO14443B RW/RO. DESFire + Type5 = 1U << 5, // ISO15693 RW/RO. SLI, SLIX, ST25TV + Mifare = 1U << 6, // Mifare classic. Skylanders + All = 0xFFFFFFFF, +}; + +enum class PackedTagType : u8 { + None = 0, + Type1 = 1U << 0, // ISO14443A RW. Topaz + Type2 = 1U << 1, // ISO14443A RW. Ultralight, NTAGX, ST25TN + Type3 = 1U << 2, // ISO14443A RW/RO. Sony FeliCa + Type4A = 1U << 3, // ISO14443A RW/RO. DESFire + Type4B = 1U << 4, // ISO14443B RW/RO. DESFire + Type5 = 1U << 5, // ISO15693 RW/RO. SLI, SLIX, ST25TV + Mifare = 1U << 6, // Mifare classic. Skylanders + All = 0xFF, +}; + +// This is nn::nfc::NfcProtocol +enum class NfcProtocol : u32 { + None, + TypeA = 1U << 0, // ISO14443A + TypeB = 1U << 1, // ISO14443B + TypeF = 1U << 2, // Sony FeliCa + All = 0xFFFFFFFFU, +}; + +// this is nn::nfc::TestWaveType +enum class TestWaveType : u32 { + Unknown, +}; + +using UniqueSerialNumber = std::array<u8, 10>; + +// This is nn::nfc::DeviceHandle +using DeviceHandle = u64; + +// This is nn::nfc::TagInfo +struct TagInfo { + UniqueSerialNumber uuid; + u8 uuid_length; + INSERT_PADDING_BYTES(0x15); + NfcProtocol protocol; + TagType tag_type; + INSERT_PADDING_BYTES(0x30); +}; +static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size"); + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_user.cpp b/src/core/hle/service/nfc/nfc_user.cpp deleted file mode 100644 index 89aa6b3f5..000000000 --- a/src/core/hle/service/nfc/nfc_user.cpp +++ /dev/null @@ -1,365 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/nfc/nfc_device.h" -#include "core/hle/service/nfc/nfc_result.h" -#include "core/hle/service/nfc/nfc_user.h" -#include "core/hle/service/time/clock_types.h" - -namespace Service::NFC { - -IUser::IUser(Core::System& system_) - : ServiceFramework{system_, "NFC::IUser"}, service_context{system_, service_name} { - static const FunctionInfo functions[] = { - {0, &IUser::Initialize, "InitializeOld"}, - {1, &IUser::Finalize, "FinalizeOld"}, - {2, &IUser::GetState, "GetStateOld"}, - {3, &IUser::IsNfcEnabled, "IsNfcEnabledOld"}, - {400, &IUser::Initialize, "Initialize"}, - {401, &IUser::Finalize, "Finalize"}, - {402, &IUser::GetState, "GetState"}, - {403, &IUser::IsNfcEnabled, "IsNfcEnabled"}, - {404, &IUser::ListDevices, "ListDevices"}, - {405, &IUser::GetDeviceState, "GetDeviceState"}, - {406, &IUser::GetNpadId, "GetNpadId"}, - {407, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, - {408, &IUser::StartDetection, "StartDetection"}, - {409, &IUser::StopDetection, "StopDetection"}, - {410, &IUser::GetTagInfo, "GetTagInfo"}, - {411, &IUser::AttachActivateEvent, "AttachActivateEvent"}, - {412, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, - {1000, nullptr, "ReadMifare"}, - {1001, nullptr, "WriteMifare"}, - {1300, &IUser::SendCommandByPassThrough, "SendCommandByPassThrough"}, - {1301, nullptr, "KeepPassThroughSession"}, - {1302, nullptr, "ReleasePassThroughSession"}, - }; - RegisterHandlers(functions); - - availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent"); - - for (u32 device_index = 0; device_index < 10; device_index++) { - devices[device_index] = - std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, - service_context, availability_change_event); - } -} - -IUser ::~IUser() { - availability_change_event->Close(); -} - -void IUser::Initialize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2, 0}; - rb.Push(ResultSuccess); -} - -void IUser::Finalize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IUser::GetState(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void IUser::IsNfcEnabled(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(state != State::NonInitialized); -} - -void IUser::ListDevices(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - if (ctx.GetWriteBufferSize() == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - std::vector<u64> nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); - - for (auto& device : devices) { - if (nfp_devices.size() >= max_allowed_devices) { - continue; - } - if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); - } - } - - if (nfp_devices.empty()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - ctx.WriteBuffer(nfp_devices); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<s32>(nfp_devices.size())); -} - -void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetCurrentState()); -} - -void IUser::GetNpadId(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetNpadId()); -} - -void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(availability_change_event->GetReadableEvent()); -} - -void IUser::StartDetection(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto nfp_protocol{rp.PopEnum<NFP::TagProtocol>()}; - LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StartDetection(nfp_protocol); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::StopDetection(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StopDetection(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - NFP::TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info, false); - ctx.WriteBuffer(tag_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetActivateEvent()); -} - -void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetDeactivateEvent()); -} - -void IUser::SendCommandByPassThrough(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()}; - const auto command_data{ctx.ReadBuffer()}; - - LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", - device_handle, timeout.ToSeconds(), command_data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - std::vector<u8> out_data(1); - // TODO: Request data from nfc device - ctx.WriteBuffer(out_data); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(out_data.size())); -} - -std::optional<std::shared_ptr<NfcDevice>> IUser::GetNfcDevice(u64 handle) { - for (auto& device : devices) { - if (device->GetHandle() == handle) { - return device; - } - } - return std::nullopt; -} - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_user.h b/src/core/hle/service/nfc/nfc_user.h deleted file mode 100644 index a5a4f12f9..000000000 --- a/src/core/hle/service/nfc/nfc_user.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <memory> -#include <optional> - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::NFC { -class NfcDevice; - -class IUser final : public ServiceFramework<IUser> { -public: - explicit IUser(Core::System& system_); - ~IUser(); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - void Initialize(Kernel::HLERequestContext& ctx); - void Finalize(Kernel::HLERequestContext& ctx); - void GetState(Kernel::HLERequestContext& ctx); - void IsNfcEnabled(Kernel::HLERequestContext& ctx); - void ListDevices(Kernel::HLERequestContext& ctx); - void GetDeviceState(Kernel::HLERequestContext& ctx); - void GetNpadId(Kernel::HLERequestContext& ctx); - void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx); - void StartDetection(Kernel::HLERequestContext& ctx); - void StopDetection(Kernel::HLERequestContext& ctx); - void GetTagInfo(Kernel::HLERequestContext& ctx); - void AttachActivateEvent(Kernel::HLERequestContext& ctx); - void AttachDeactivateEvent(Kernel::HLERequestContext& ctx); - void SendCommandByPassThrough(Kernel::HLERequestContext& ctx); - - std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); - - KernelHelpers::ServiceContext service_context; - - std::array<std::shared_ptr<NfcDevice>, 10> devices{}; - - State state{State::NonInitialized}; - Kernel::KEvent* availability_change_event; -}; - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 0cb55ca49..2eeabc138 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -2,12 +2,140 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nfp/nfp.h" -#include "core/hle/service/nfp/nfp_user.h" +#include "core/hle/service/nfp/nfp_interface.h" +#include "core/hle/service/server_manager.h" namespace Service::NFP { +class IUser final : public Interface { +public: + explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") { + // clang-format off + static const FunctionInfoTyped<IUser> functions[] = { + {0, &IUser::Initialize, "Initialize"}, + {1, &IUser::Finalize, "Finalize"}, + {2, &IUser::ListDevices, "ListDevices"}, + {3, &IUser::StartDetection, "StartDetection"}, + {4, &IUser::StopDetection, "StopDetection"}, + {5, &IUser::Mount, "Mount"}, + {6, &IUser::Unmount, "Unmount"}, + {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, + {8, &IUser::GetApplicationArea, "GetApplicationArea"}, + {9, &IUser::SetApplicationArea, "SetApplicationArea"}, + {10, &IUser::Flush, "Flush"}, + {11, &IUser::Restore, "Restore"}, + {12, &IUser::CreateApplicationArea, "CreateApplicationArea"}, + {13, &IUser::GetTagInfo, "GetTagInfo"}, + {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, + {15, &IUser::GetCommonInfo, "GetCommonInfo"}, + {16, &IUser::GetModelInfo, "GetModelInfo"}, + {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, + {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, + {19, &IUser::GetState, "GetState"}, + {20, &IUser::GetDeviceState, "GetDeviceState"}, + {21, &IUser::GetNpadId, "GetNpadId"}, + {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, + {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, + {24, &IUser::RecreateApplicationArea, "RecreateApplicationArea"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class ISystem final : public Interface { +public: + explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") { + // clang-format off + static const FunctionInfoTyped<ISystem> functions[] = { + {0, &ISystem::InitializeSystem, "InitializeSystem"}, + {1, &ISystem::FinalizeSystem, "FinalizeSystem"}, + {2, &ISystem::ListDevices, "ListDevices"}, + {3, &ISystem::StartDetection, "StartDetection"}, + {4, &ISystem::StopDetection, "StopDetection"}, + {5, &ISystem::Mount, "Mount"}, + {6, &ISystem::Unmount, "Unmount"}, + {10, &ISystem::Flush, "Flush"}, + {11, &ISystem::Restore, "Restore"}, + {12, &ISystem::CreateApplicationArea, "CreateApplicationArea"}, + {13, &ISystem::GetTagInfo, "GetTagInfo"}, + {14, &ISystem::GetRegisterInfo, "GetRegisterInfo"}, + {15, &ISystem::GetCommonInfo, "GetCommonInfo"}, + {16, &ISystem::GetModelInfo, "GetModelInfo"}, + {17, &ISystem::AttachActivateEvent, "AttachActivateEvent"}, + {18, &ISystem::AttachDeactivateEvent, "AttachDeactivateEvent"}, + {19, &ISystem::GetState, "GetState"}, + {20, &ISystem::GetDeviceState, "GetDeviceState"}, + {21, &ISystem::GetNpadId, "GetNpadId"}, + {23, &ISystem::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, + {100, &ISystem::Format, "Format"}, + {101, &ISystem::GetAdminInfo, "GetAdminInfo"}, + {102, &ISystem::GetRegisterInfoPrivate, "GetRegisterInfoPrivate"}, + {103, &ISystem::SetRegisterInfoPrivate, "SetRegisterInfoPrivate"}, + {104, &ISystem::DeleteRegisterInfo, "DeleteRegisterInfo"}, + {105, &ISystem::DeleteApplicationArea, "DeleteApplicationArea"}, + {106, &ISystem::ExistsApplicationArea, "ExistsApplicationArea"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class IDebug final : public Interface { +public: + explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") { + // clang-format off + static const FunctionInfoTyped<IDebug> functions[] = { + {0, &IDebug::InitializeDebug, "InitializeDebug"}, + {1, &IDebug::FinalizeDebug, "FinalizeDebug"}, + {2, &IDebug::ListDevices, "ListDevices"}, + {3, &IDebug::StartDetection, "StartDetection"}, + {4, &IDebug::StopDetection, "StopDetection"}, + {5, &IDebug::Mount, "Mount"}, + {6, &IDebug::Unmount, "Unmount"}, + {7, &IDebug::OpenApplicationArea, "OpenApplicationArea"}, + {8, &IDebug::GetApplicationArea, "GetApplicationArea"}, + {9, &IDebug::SetApplicationArea, "SetApplicationArea"}, + {10, &IDebug::Flush, "Flush"}, + {11, &IDebug::Restore, "Restore"}, + {12, &IDebug::CreateApplicationArea, "CreateApplicationArea"}, + {13, &IDebug::GetTagInfo, "GetTagInfo"}, + {14, &IDebug::GetRegisterInfo, "GetRegisterInfo"}, + {15, &IDebug::GetCommonInfo, "GetCommonInfo"}, + {16, &IDebug::GetModelInfo, "GetModelInfo"}, + {17, &IDebug::AttachActivateEvent, "AttachActivateEvent"}, + {18, &IDebug::AttachDeactivateEvent, "AttachDeactivateEvent"}, + {19, &IDebug::GetState, "GetState"}, + {20, &IDebug::GetDeviceState, "GetDeviceState"}, + {21, &IDebug::GetNpadId, "GetNpadId"}, + {22, &IDebug::GetApplicationAreaSize, "GetApplicationAreaSize"}, + {23, &IDebug::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, + {24, &IDebug::RecreateApplicationArea, "RecreateApplicationArea"}, + {100, &IDebug::Format, "Format"}, + {101, &IDebug::GetAdminInfo, "GetAdminInfo"}, + {102, &IDebug::GetRegisterInfoPrivate, "GetRegisterInfoPrivate"}, + {103, &IDebug::SetRegisterInfoPrivate, "SetRegisterInfoPrivate"}, + {104, &IDebug::DeleteRegisterInfo, "DeleteRegisterInfo"}, + {105, &IDebug::DeleteApplicationArea, "DeleteApplicationArea"}, + {106, &IDebug::ExistsApplicationArea, "ExistsApplicationArea"}, + {200, &IDebug::GetAll, "GetAll"}, + {201, &IDebug::SetAll, "SetAll"}, + {202, &IDebug::FlushDebug, "FlushDebug"}, + {203, &IDebug::BreakTag, "BreakTag"}, + {204, &IDebug::ReadBackupData, "ReadBackupData"}, + {205, &IDebug::WriteBackupData, "WriteBackupData"}, + {206, &IDebug::WriteNtf, "WriteNtf"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + class IUserManager final : public ServiceFramework<IUserManager> { public: explicit IUserManager(Core::System& system_) : ServiceFramework{system_, "nfp:user"} { @@ -21,23 +149,66 @@ public: } private: - void CreateUserInterface(Kernel::HLERequestContext& ctx) { + void CreateUserInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFP, "called"); - if (user_interface == nullptr) { - user_interface = std::make_shared<IUser>(system); - } + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IUser>(system); + } +}; + +class ISystemManager final : public ServiceFramework<ISystemManager> { +public: + explicit ISystemManager(Core::System& system_) : ServiceFramework{system_, "nfp:sys"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ISystemManager::CreateSystemInterface, "CreateSystemInterface"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void CreateSystemInterface(HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<IUser>(user_interface); + rb.PushIpcInterface<ISystem>(system); + } +}; + +class IDebugManager final : public ServiceFramework<IDebugManager> { +public: + explicit IDebugManager(Core::System& system_) : ServiceFramework{system_, "nfp:dbg"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IDebugManager::CreateDebugInterface, "CreateDebugInterface"}, + }; + // clang-format on + + RegisterHandlers(functions); } - std::shared_ptr<IUser> user_interface; +private: + void CreateDebugInterface(HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IDebug>(system); + } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<IUserManager>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("nfp:user", std::make_shared<IUserManager>(system)); + server_manager->RegisterNamedService("nfp:sys", std::make_shared<ISystemManager>(system)); + server_manager->RegisterNamedService("nfp:dbg", std::make_shared<IDebugManager>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h index a25c362b8..a5aac710b 100644 --- a/src/core/hle/service/nfp/nfp.h +++ b/src/core/hle/service/nfp/nfp.h @@ -7,6 +7,6 @@ namespace Service::NFP { -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp deleted file mode 100644 index c860fd1a1..000000000 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ /dev/null @@ -1,719 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <array> - -#include "common/input.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "common/tiny_mt.h" -#include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/mii/mii_manager.h" -#include "core/hle/service/mii/types.h" -#include "core/hle/service/nfp/amiibo_crypto.h" -#include "core/hle/service/nfp/nfp_device.h" -#include "core/hle/service/nfp/nfp_result.h" -#include "core/hle/service/nfp/nfp_user.h" -#include "core/hle/service/time/time_manager.h" -#include "core/hle/service/time/time_zone_content_manager.h" -#include "core/hle/service/time/time_zone_types.h" - -namespace Service::NFP { -NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_) - : npad_id{npad_id_}, system{system_}, service_context{service_context_}, - availability_change_event{availability_change_event_} { - activate_event = service_context.CreateEvent("IUser:NFPActivateEvent"); - deactivate_event = service_context.CreateEvent("IUser:NFPDeactivateEvent"); - npad_device = system.HIDCore().GetEmulatedController(npad_id); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); }, - .is_npad_service = false, - }; - is_controller_set = true; - callback_key = npad_device->SetCallback(engine_callback); - - auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()}; - current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point; -} - -NfpDevice::~NfpDevice() { - activate_event->Close(); - deactivate_event->Close(); - if (!is_controller_set) { - return; - } - npad_device->DeleteCallback(callback_key); - is_controller_set = false; -}; - -void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Connected || - type == Core::HID::ControllerTriggerType::Disconnected) { - availability_change_event->Signal(); - return; - } - - if (type != Core::HID::ControllerTriggerType::Nfc) { - return; - } - - if (!npad_device->IsConnected()) { - return; - } - - const auto nfc_status = npad_device->GetNfc(); - switch (nfc_status.state) { - case Common::Input::NfcState::NewAmiibo: - LoadAmiibo(nfc_status.data); - break; - case Common::Input::NfcState::AmiiboRemoved: - if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { - break; - } - if (device_state != DeviceState::SearchingForTag) { - CloseAmiibo(); - } - break; - default: - break; - } -} - -bool NfpDevice::LoadAmiibo(std::span<const u8> data) { - if (device_state != DeviceState::SearchingForTag) { - LOG_ERROR(Service_NFP, "Game is not looking for amiibos, current state {}", device_state); - return false; - } - - if (data.size() != sizeof(EncryptedNTAG215File)) { - LOG_ERROR(Service_NFP, "Not an amiibo, size={}", data.size()); - return false; - } - - // TODO: Filter by allowed_protocols here - - memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); - - device_state = DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(); - activate_event->Signal(); - return true; -} - -void NfpDevice::CloseAmiibo() { - LOG_INFO(Service_NFP, "Remove amiibo"); - - if (device_state == DeviceState::TagMounted) { - Unmount(); - } - - device_state = DeviceState::TagRemoved; - encrypted_tag_data = {}; - tag_data = {}; - activate_event->GetReadableEvent().Clear(); - deactivate_event->Signal(); -} - -Kernel::KReadableEvent& NfpDevice::GetActivateEvent() const { - return activate_event->GetReadableEvent(); -} - -Kernel::KReadableEvent& NfpDevice::GetDeactivateEvent() const { - return deactivate_event->GetReadableEvent(); -} - -void NfpDevice::Initialize() { - device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable; - encrypted_tag_data = {}; - tag_data = {}; -} - -void NfpDevice::Finalize() { - if (device_state == DeviceState::TagMounted) { - Unmount(); - } - if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { - StopDetection(); - } - device_state = DeviceState::Unavailable; -} - -Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { - if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; - } - - if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) { - LOG_ERROR(Service_NFP, "Nfc not supported"); - return NfcDisabled; - } - - device_state = DeviceState::SearchingForTag; - allowed_protocols = allowed_protocol; - return ResultSuccess; -} - -Result NfpDevice::StopDetection() { - npad_device->SetPollingMode(Common::Input::PollingMode::Active); - - if (device_state == DeviceState::Initialized) { - return ResultSuccess; - } - - if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { - CloseAmiibo(); - return ResultSuccess; - } - if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { - device_state = DeviceState::Initialized; - return ResultSuccess; - } - - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; -} - -Result NfpDevice::Flush() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - auto& settings = tag_data.settings; - - const auto& current_date = GetAmiiboDate(current_posix_time); - if (settings.write_date.raw_date != current_date.raw_date) { - settings.write_date = current_date; - settings.crc_counter++; - // TODO: Find how to calculate the crc check - // settings.crc = CalculateCRC(settings); - } - - tag_data.write_counter++; - - if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { - LOG_ERROR(Service_NFP, "Failed to encode data"); - return WriteAmiiboFailed; - } - - std::vector<u8> data(sizeof(encrypted_tag_data)); - memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); - - if (!npad_device->WriteNfc(data)) { - LOG_ERROR(Service_NFP, "Error writing to file"); - return WriteAmiiboFailed; - } - - is_data_moddified = false; - - return ResultSuccess; -} - -Result NfpDevice::Mount(MountTarget mount_target_) { - if (device_state != DeviceState::TagFound) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; - } - - if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { - LOG_ERROR(Service_NFP, "Not an amiibo"); - return NotAnAmiibo; - } - - // Mark amiibos as read only when keys are missing - if (!AmiiboCrypto::IsKeyAvailable()) { - LOG_ERROR(Service_NFP, "No keys detected"); - device_state = DeviceState::TagMounted; - mount_target = MountTarget::Rom; - return ResultSuccess; - } - - if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { - LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state); - return CorruptedData; - } - - device_state = DeviceState::TagMounted; - mount_target = mount_target_; - return ResultSuccess; -} - -Result NfpDevice::Unmount() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - // Save data before unloading the amiibo - if (is_data_moddified) { - Flush(); - } - - device_state = DeviceState::TagFound; - mount_target = MountTarget::None; - is_app_area_open = false; - - return ResultSuccess; -} - -Result NfpDevice::GetTagInfo(TagInfo& tag_info) const { - if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - tag_info = { - .uuid = encrypted_tag_data.uuid.uid, - .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()), - .protocol = TagProtocol::TypeA, - .tag_type = TagType::Type2, - }; - - return ResultSuccess; -} - -Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - const auto& settings = tag_data.settings; - - // TODO: Validate this data - common_info = { - .last_write_date = settings.write_date.GetWriteDate(), - .write_counter = tag_data.write_counter, - .version = 0, - .application_area_size = sizeof(ApplicationArea), - }; - return ResultSuccess; -} - -Result NfpDevice::GetModelInfo(ModelInfo& model_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - const auto& model_info_data = encrypted_tag_data.user_memory.model_info; - model_info = { - .character_id = model_info_data.character_id, - .character_variant = model_info_data.character_variant, - .amiibo_type = model_info_data.amiibo_type, - .model_number = model_info_data.model_number, - .series = model_info_data.series, - }; - return ResultSuccess; -} - -Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; - } - - Service::Mii::MiiManager manager; - const auto& settings = tag_data.settings; - - // TODO: Validate this data - register_info = { - .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii), - .creation_date = settings.init_date.GetWriteDate(), - .amiibo_name = GetAmiiboName(settings), - .font_region = {}, - }; - - return ResultSuccess; -} - -Result NfpDevice::SetNicknameAndOwner(const AmiiboName& amiibo_name) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - Service::Mii::MiiManager manager; - auto& settings = tag_data.settings; - - settings.init_date = GetAmiiboDate(current_posix_time); - settings.write_date = GetAmiiboDate(current_posix_time); - settings.crc_counter++; - // TODO: Find how to calculate the crc check - // settings.crc = CalculateCRC(settings); - - SetAmiiboName(settings, amiibo_name); - tag_data.owner_mii = manager.ConvertCharInfoToV3(manager.BuildDefault(0)); - settings.settings.amiibo_initialized.Assign(1); - - return Flush(); -} - -Result NfpDevice::RestoreAmiibo() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - // TODO: Load amiibo from backup on system - LOG_ERROR(Service_NFP, "Not Implemented"); - return ResultSuccess; -} - -Result NfpDevice::DeleteAllData() { - const auto result = DeleteApplicationArea(); - if (result.IsError()) { - return result; - } - - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - Common::TinyMT rng{}; - rng.GenerateRandomBytes(&tag_data.owner_mii, sizeof(tag_data.owner_mii)); - tag_data.settings.settings.amiibo_initialized.Assign(0); - - return Flush(); -} - -Result NfpDevice::OpenApplicationArea(u32 access_id) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_WARNING(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - if (tag_data.application_area_id != access_id) { - LOG_WARNING(Service_NFP, "Wrong application area id"); - return WrongApplicationAreaId; - } - - is_app_area_open = true; - - return ResultSuccess; -} - -Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { - application_area_id = {}; - - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_WARNING(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - application_area_id = tag_data.application_area_id; - - return ResultSuccess; -} - -Result NfpDevice::GetApplicationArea(std::vector<u8>& data) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (!is_app_area_open) { - LOG_ERROR(Service_NFP, "Application area is not open"); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_ERROR(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - if (data.size() > sizeof(ApplicationArea)) { - data.resize(sizeof(ApplicationArea)); - } - - memcpy(data.data(), tag_data.application_area.data(), data.size()); - - return ResultSuccess; -} - -Result NfpDevice::SetApplicationArea(std::span<const u8> data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (!is_app_area_open) { - LOG_ERROR(Service_NFP, "Application area is not open"); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_ERROR(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - if (data.size() > sizeof(ApplicationArea)) { - LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); - return ResultUnknown; - } - - Common::TinyMT rng{}; - std::memcpy(tag_data.application_area.data(), data.data(), data.size()); - // Fill remaining data with random numbers - rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), - sizeof(ApplicationArea) - data.size()); - - tag_data.applicaton_write_counter++; - is_data_moddified = true; - - return ResultSuccess; -} - -Result NfpDevice::CreateApplicationArea(u32 access_id, std::span<const u8> data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() != 0) { - LOG_ERROR(Service_NFP, "Application area already exist"); - return ApplicationAreaExist; - } - - return RecreateApplicationArea(access_id, data); -} - -Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (data.size() > sizeof(ApplicationArea)) { - LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); - return WrongApplicationAreaSize; - } - - Common::TinyMT rng{}; - std::memcpy(tag_data.application_area.data(), data.data(), data.size()); - // Fill remaining data with random numbers - rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), - sizeof(ApplicationArea) - data.size()); - - // TODO: Investigate why the title id needs to be moddified - tag_data.title_id = system.GetCurrentProcessProgramID(); - tag_data.title_id = tag_data.title_id | 0x30000000ULL; - tag_data.settings.settings.appdata_initialized.Assign(1); - tag_data.application_area_id = access_id; - tag_data.applicaton_write_counter++; - tag_data.unknown = {}; - - return Flush(); -} - -Result NfpDevice::DeleteApplicationArea() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - Common::TinyMT rng{}; - rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(ApplicationArea)); - rng.GenerateRandomBytes(&tag_data.title_id, sizeof(u64)); - rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32)); - tag_data.settings.settings.appdata_initialized.Assign(0); - tag_data.applicaton_write_counter++; - tag_data.unknown = {}; - - return Flush(); -} - -u64 NfpDevice::GetHandle() const { - // Generate a handle based of the npad id - return static_cast<u64>(npad_id); -} - -u32 NfpDevice::GetApplicationAreaSize() const { - return sizeof(ApplicationArea); -} - -DeviceState NfpDevice::GetCurrentState() const { - return device_state; -} - -Core::HID::NpadIdType NfpDevice::GetNpadId() const { - return npad_id; -} - -AmiiboName NfpDevice::GetAmiiboName(const AmiiboSettings& settings) const { - std::array<char16_t, amiibo_name_length> settings_amiibo_name{}; - AmiiboName amiibo_name{}; - - // Convert from big endian to little endian - for (std::size_t i = 0; i < amiibo_name_length; i++) { - settings_amiibo_name[i] = static_cast<u16>(settings.amiibo_name[i]); - } - - // Convert from utf16 to utf8 - const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data()); - memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size()); - - return amiibo_name; -} - -void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name) { - std::array<char16_t, amiibo_name_length> settings_amiibo_name{}; - - // Convert from utf8 to utf16 - const auto amiibo_name_utf16 = Common::UTF8ToUTF16(amiibo_name.data()); - memcpy(settings_amiibo_name.data(), amiibo_name_utf16.data(), - amiibo_name_utf16.size() * sizeof(char16_t)); - - // Convert from little endian to big endian - for (std::size_t i = 0; i < amiibo_name_length; i++) { - settings.amiibo_name[i] = static_cast<u16_be>(settings_amiibo_name[i]); - } -} - -AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const { - const auto& time_zone_manager = - system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager(); - Time::TimeZone::CalendarInfo calendar_info{}; - AmiiboDate amiibo_date{}; - - amiibo_date.SetYear(2000); - amiibo_date.SetMonth(1); - amiibo_date.SetDay(1); - - if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) { - amiibo_date.SetYear(calendar_info.time.year); - amiibo_date.SetMonth(calendar_info.time.month); - amiibo_date.SetDay(calendar_info.time.day); - } - - return amiibo_date; -} - -} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h deleted file mode 100644 index b6a46f2ac..000000000 --- a/src/core/hle/service/nfp/nfp_device.h +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <span> -#include <vector> - -#include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nfp/nfp_types.h" -#include "core/hle/service/service.h" - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Core { -class System; -} // namespace Core - -namespace Core::HID { -class EmulatedController; -enum class ControllerTriggerType; -enum class NpadIdType : u32; -} // namespace Core::HID - -namespace Service::NFP { -class NfpDevice { -public: - NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_); - ~NfpDevice(); - - void Initialize(); - void Finalize(); - - Result StartDetection(TagProtocol allowed_protocol); - Result StopDetection(); - Result Mount(MountTarget mount_target); - Result Unmount(); - Result Flush(); - - Result GetTagInfo(TagInfo& tag_info) const; - Result GetCommonInfo(CommonInfo& common_info) const; - Result GetModelInfo(ModelInfo& model_info) const; - Result GetRegisterInfo(RegisterInfo& register_info) const; - - Result SetNicknameAndOwner(const AmiiboName& amiibo_name); - Result RestoreAmiibo(); - Result DeleteAllData(); - - Result OpenApplicationArea(u32 access_id); - Result GetApplicationAreaId(u32& application_area_id) const; - Result GetApplicationArea(std::vector<u8>& data) const; - Result SetApplicationArea(std::span<const u8> data); - Result CreateApplicationArea(u32 access_id, std::span<const u8> data); - Result RecreateApplicationArea(u32 access_id, std::span<const u8> data); - Result DeleteApplicationArea(); - - u64 GetHandle() const; - u32 GetApplicationAreaSize() const; - DeviceState GetCurrentState() const; - Core::HID::NpadIdType GetNpadId() const; - - Kernel::KReadableEvent& GetActivateEvent() const; - Kernel::KReadableEvent& GetDeactivateEvent() const; - -private: - void NpadUpdate(Core::HID::ControllerTriggerType type); - bool LoadAmiibo(std::span<const u8> data); - void CloseAmiibo(); - - AmiiboName GetAmiiboName(const AmiiboSettings& settings) const; - void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name); - AmiiboDate GetAmiiboDate(s64 posix_time) const; - - bool is_controller_set{}; - int callback_key; - const Core::HID::NpadIdType npad_id; - Core::System& system; - Core::HID::EmulatedController* npad_device = nullptr; - KernelHelpers::ServiceContext& service_context; - Kernel::KEvent* activate_event = nullptr; - Kernel::KEvent* deactivate_event = nullptr; - Kernel::KEvent* availability_change_event = nullptr; - - bool is_data_moddified{}; - bool is_app_area_open{}; - TagProtocol allowed_protocols{}; - s64 current_posix_time{}; - MountTarget mount_target{MountTarget::None}; - DeviceState device_state{DeviceState::Unavailable}; - - NTAG215File tag_data{}; - EncryptedNTAG215File encrypted_tag_data{}; -}; - -} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_interface.cpp b/src/core/hle/service/nfp/nfp_interface.cpp new file mode 100644 index 000000000..34ef9d82d --- /dev/null +++ b/src/core/hle/service/nfp/nfp_interface.cpp @@ -0,0 +1,438 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/hid/hid_types.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nfc/common/device.h" +#include "core/hle/service/nfc/common/device_manager.h" +#include "core/hle/service/nfc/nfc_types.h" +#include "core/hle/service/nfp/nfp_interface.h" +#include "core/hle/service/nfp/nfp_result.h" +#include "core/hle/service/nfp/nfp_types.h" + +namespace Service::NFP { + +Interface::Interface(Core::System& system_, const char* name) + : NfcInterface{system_, name, NFC::BackendType::Nfp} {} + +Interface::~Interface() = default; + +void Interface::InitializeSystem(HLERequestContext& ctx) { + Initialize(ctx); +} + +void Interface::InitializeDebug(HLERequestContext& ctx) { + Initialize(ctx); +} + +void Interface::FinalizeSystem(HLERequestContext& ctx) { + Finalize(ctx); +} + +void Interface::FinalizeDebug(HLERequestContext& ctx) { + Finalize(ctx); +} + +void Interface::Mount(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto model_type{rp.PopEnum<ModelType>()}; + const auto mount_target{rp.PopEnum<MountTarget>()}; + LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle, + model_type, mount_target); + + auto result = GetManager()->Mount(device_handle, model_type, mount_target); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::Unmount(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->Unmount(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::OpenApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto access_id{rp.Pop<u32>()}; + LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id); + + auto result = GetManager()->OpenApplicationArea(device_handle, access_id); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto data_size = ctx.GetWriteBufferSize(); + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + std::vector<u8> data(data_size); + auto result = GetManager()->GetApplicationArea(device_handle, data); + result = TranslateResultToServiceError(result); + + if (result.IsError()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + ctx.WriteBuffer(data); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(result); + rb.Push(static_cast<u32>(data_size)); +} + +void Interface::SetApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto data{ctx.ReadBuffer()}; + LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size()); + + auto result = GetManager()->SetApplicationArea(device_handle, data); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::Flush(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->Flush(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::Restore(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->Restore(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::CreateApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto access_id{rp.Pop<u32>()}; + const auto data{ctx.ReadBuffer()}; + LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, + access_id, data.size()); + + auto result = GetManager()->CreateApplicationArea(device_handle, access_id, data); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetRegisterInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + RegisterInfo register_info{}; + auto result = GetManager()->GetRegisterInfo(device_handle, register_info); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(register_info); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetCommonInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + CommonInfo common_info{}; + auto result = GetManager()->GetCommonInfo(device_handle, common_info); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(common_info); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetModelInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + ModelInfo model_info{}; + auto result = GetManager()->GetModelInfo(device_handle, model_info); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(model_info); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetApplicationAreaSize(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(GetManager()->GetApplicationAreaSize()); +} + +void Interface::RecreateApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto access_id{rp.Pop<u32>()}; + const auto data{ctx.ReadBuffer()}; + LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, + access_id, data.size()); + + auto result = GetManager()->RecreateApplicationArea(device_handle, access_id, data); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::Format(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->Format(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetAdminInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + AdminInfo admin_info{}; + auto result = GetManager()->GetAdminInfo(device_handle, admin_info); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(admin_info); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetRegisterInfoPrivate(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + RegisterInfoPrivate register_info{}; + auto result = GetManager()->GetRegisterInfoPrivate(device_handle, register_info); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(register_info); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto register_info_buffer{ctx.ReadBuffer()}; + LOG_INFO(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle, + register_info_buffer.size()); + + RegisterInfoPrivate register_info{}; + memcpy(®ister_info, register_info_buffer.data(), sizeof(RegisterInfoPrivate)); + auto result = GetManager()->SetRegisterInfoPrivate(device_handle, register_info); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::DeleteRegisterInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->DeleteRegisterInfo(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::DeleteApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->DeleteApplicationArea(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::ExistsApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + bool has_application_area = false; + auto result = GetManager()->ExistsApplicationArea(device_handle, has_application_area); + result = TranslateResultToServiceError(result); + + if (result.IsError()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(result); + rb.Push(has_application_area); +} + +void Interface::GetAll(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + NfpData nfp_data{}; + auto result = GetManager()->GetAll(device_handle, nfp_data); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(nfp_data); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::SetAll(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto nfp_data_buffer{ctx.ReadBuffer()}; + + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + NfpData nfp_data{}; + memcpy(&nfp_data, nfp_data_buffer.data(), sizeof(NfpData)); + auto result = GetManager()->SetAll(device_handle, nfp_data); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::FlushDebug(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->FlushDebug(device_handle); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::BreakTag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto break_type{rp.PopEnum<BreakType>()}; + LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}, break_type={}", device_handle, + break_type); + + auto result = GetManager()->BreakTag(device_handle, break_type); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::ReadBackupData(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + std::vector<u8> backup_data{}; + auto result = GetManager()->ReadBackupData(device_handle, backup_data); + result = TranslateResultToServiceError(result); + + if (result.IsSuccess()) { + ctx.WriteBuffer(backup_data); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::WriteBackupData(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto backup_data_buffer{ctx.ReadBuffer()}; + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + + auto result = GetManager()->WriteBackupData(device_handle, backup_data_buffer); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::WriteNtf(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto write_type{rp.PopEnum<WriteType>()}; + const auto ntf_data_buffer{ctx.ReadBuffer()}; + LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); + + auto result = GetManager()->WriteNtf(device_handle, write_type, ntf_data_buffer); + result = TranslateResultToServiceError(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_interface.h b/src/core/hle/service/nfp/nfp_interface.h new file mode 100644 index 000000000..fa985b068 --- /dev/null +++ b/src/core/hle/service/nfp/nfp_interface.h @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nfc/nfc_interface.h" +#include "core/hle/service/service.h" + +namespace Service::NFP { + +class Interface : public NFC::NfcInterface { +public: + explicit Interface(Core::System& system_, const char* name); + ~Interface() override; + + void InitializeSystem(HLERequestContext& ctx); + void InitializeDebug(HLERequestContext& ctx); + void FinalizeSystem(HLERequestContext& ctx); + void FinalizeDebug(HLERequestContext& ctx); + void Mount(HLERequestContext& ctx); + void Unmount(HLERequestContext& ctx); + void OpenApplicationArea(HLERequestContext& ctx); + void GetApplicationArea(HLERequestContext& ctx); + void SetApplicationArea(HLERequestContext& ctx); + void Flush(HLERequestContext& ctx); + void Restore(HLERequestContext& ctx); + void CreateApplicationArea(HLERequestContext& ctx); + void GetRegisterInfo(HLERequestContext& ctx); + void GetCommonInfo(HLERequestContext& ctx); + void GetModelInfo(HLERequestContext& ctx); + void GetApplicationAreaSize(HLERequestContext& ctx); + void RecreateApplicationArea(HLERequestContext& ctx); + void Format(HLERequestContext& ctx); + void GetAdminInfo(HLERequestContext& ctx); + void GetRegisterInfoPrivate(HLERequestContext& ctx); + void SetRegisterInfoPrivate(HLERequestContext& ctx); + void DeleteRegisterInfo(HLERequestContext& ctx); + void DeleteApplicationArea(HLERequestContext& ctx); + void ExistsApplicationArea(HLERequestContext& ctx); + void GetAll(HLERequestContext& ctx); + void SetAll(HLERequestContext& ctx); + void FlushDebug(HLERequestContext& ctx); + void BreakTag(HLERequestContext& ctx); + void ReadBackupData(HLERequestContext& ctx); + void WriteBackupData(HLERequestContext& ctx); + void WriteNtf(HLERequestContext& ctx); +}; + +} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_result.h b/src/core/hle/service/nfp/nfp_result.h index d8e4cf094..618533843 100644 --- a/src/core/hle/service/nfp/nfp_result.h +++ b/src/core/hle/service/nfp/nfp_result.h @@ -1,5 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -7,18 +7,21 @@ namespace Service::NFP { -constexpr Result DeviceNotFound(ErrorModule::NFP, 64); -constexpr Result InvalidArgument(ErrorModule::NFP, 65); -constexpr Result WrongApplicationAreaSize(ErrorModule::NFP, 68); -constexpr Result WrongDeviceState(ErrorModule::NFP, 73); -constexpr Result NfcDisabled(ErrorModule::NFP, 80); -constexpr Result WriteAmiiboFailed(ErrorModule::NFP, 88); -constexpr Result TagRemoved(ErrorModule::NFP, 97); -constexpr Result RegistrationIsNotInitialized(ErrorModule::NFP, 120); -constexpr Result ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); -constexpr Result CorruptedData(ErrorModule::NFP, 144); -constexpr Result WrongApplicationAreaId(ErrorModule::NFP, 152); -constexpr Result ApplicationAreaExist(ErrorModule::NFP, 168); -constexpr Result NotAnAmiibo(ErrorModule::NFP, 178); +constexpr Result ResultDeviceNotFound(ErrorModule::NFP, 64); +constexpr Result ResultInvalidArgument(ErrorModule::NFP, 65); +constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFP, 68); +constexpr Result ResultWrongDeviceState(ErrorModule::NFP, 73); +constexpr Result ResultUnknown74(ErrorModule::NFC, 74); +constexpr Result ResultNfcDisabled(ErrorModule::NFP, 80); +constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88); +constexpr Result ResultTagRemoved(ErrorModule::NFP, 97); +constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120); +constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); +constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFP, 136); +constexpr Result ResultCorruptedData(ErrorModule::NFP, 144); +constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152); +constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168); +constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178); +constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFP, 200); } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index fc228c2b2..aed12a7f8 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -7,30 +7,19 @@ #include "common/swap.h" #include "core/hle/service/mii/types.h" +#include "core/hle/service/nfc/nfc_types.h" namespace Service::NFP { static constexpr std::size_t amiibo_name_length = 0xA; +static constexpr std::size_t application_id_version_offset = 0x1c; +static constexpr std::size_t counter_limit = 0xffff; -enum class ServiceType : u32 { - User, - Debug, - System, -}; - -enum class DeviceState : u32 { - Initialized, - SearchingForTag, - TagFound, - TagRemoved, - TagMounted, - Unavailable, - Finalized, -}; - +// This is nn::nfp::ModelType enum class ModelType : u32 { Amiibo, }; +// This is nn::nfp::MountTarget enum class MountTarget : u32 { None, Rom, @@ -70,33 +59,23 @@ enum class AmiiboSeries : u8 { Diablo, }; -enum class TagType : u32 { - None, - Type1, // ISO14443A RW 96-2k bytes 106kbit/s - Type2, // ISO14443A RW/RO 540 bytes 106kbit/s - Type3, // Sony Felica RW/RO 2k bytes 212kbit/s - Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s - Type5, // ISO15693 RW/RO 540 bytes 106kbit/s +enum class AppAreaVersion : u8 { + Nintendo3DS = 0, + NintendoWiiU = 1, + Nintendo3DSv2 = 2, + NintendoSwitch = 3, + NotSet = 0xFF, }; -enum class PackedTagType : u8 { - None, - Type1, // ISO14443A RW 96-2k bytes 106kbit/s - Type2, // ISO14443A RW/RO 540 bytes 106kbit/s - Type3, // Sony Felica RW/RO 2k bytes 212kbit/s - Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s - Type5, // ISO15693 RW/RO 540 bytes 106kbit/s +enum class BreakType : u32 { + Normal, + Unknown1, + Unknown2, }; -// Verify this enum. It might be completely wrong default protocol is 0x48 -enum class TagProtocol : u32 { - None, - TypeA = 1U << 0, // ISO14443A - TypeB = 1U << 1, // ISO14443B - TypeF = 1U << 2, // Sony Felica - Unknown1 = 1U << 3, - Unknown2 = 1U << 5, - All = 0xFFFFFFFFU, +enum class WriteType : u32 { + Unknown0, + Unknown1, }; enum class CabinetMode : u8 { @@ -106,31 +85,28 @@ enum class CabinetMode : u8 { StartFormatter, }; -enum class MifareCmd : u8 { - AuthA = 0x60, - AuthB = 0x61, - Read = 0x30, - Write = 0xA0, - Transfer = 0xB0, - Decrement = 0xC0, - Increment = 0xC1, - Store = 0xC2 -}; - -using UniqueSerialNumber = std::array<u8, 7>; -using LockBytes = std::array<u8, 2>; +using UuidPart = std::array<u8, 3>; using HashData = std::array<u8, 0x20>; using ApplicationArea = std::array<u8, 0xD8>; using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; -using DataBlock = std::array<u8, 0x10>; -using KeyData = std::array<u8, 0x6>; + +// This is nn::nfp::TagInfo +using TagInfo = NFC::TagInfo; + +struct NtagTagUuid { + UuidPart part1; + UuidPart part2; + u8 nintendo_id; +}; +static_assert(sizeof(NtagTagUuid) == 7, "NtagTagUuid is an invalid size"); struct TagUuid { - UniqueSerialNumber uid; + UuidPart part1; + u8 crc_check1; + UuidPart part2; u8 nintendo_id; - LockBytes lock_bytes; }; -static_assert(sizeof(TagUuid) == 10, "TagUuid is an invalid size"); +static_assert(sizeof(TagUuid) == 8, "TagUuid is an invalid size"); struct WriteDate { u16 year; @@ -171,6 +147,12 @@ struct AmiiboDate { }; } + void SetWriteDate(const WriteDate& write_date) { + SetYear(write_date.year); + SetMonth(write_date.month); + SetDay(write_date.day); + } + void SetYear(u16 year) { const u16 year_converted = static_cast<u16>((year - 2000) << 9); raw_date = Common::swap16((GetValue() & ~0xFE00) | year_converted); @@ -197,6 +179,7 @@ struct Settings { union { u8 raw{}; + BitField<0, 4, u8> font_region; BitField<4, 1, u8> amiibo_initialized; BitField<5, 1, u8> appdata_initialized; }; @@ -220,7 +203,7 @@ struct AmiiboModelInfo { AmiiboType amiibo_type; u16_be model_number; AmiiboSeries series; - PackedTagType tag_type; + NFC::PackedTagType tag_type; INSERT_PADDING_BYTES(0x4); // Unknown }; static_assert(sizeof(AmiiboModelInfo) == 0xC, "AmiiboModelInfo is an invalid size"); @@ -236,41 +219,47 @@ static_assert(sizeof(NTAG215Password) == 0x8, "NTAG215Password is an invalid siz struct EncryptedAmiiboFile { u8 constant_value; // Must be A5 u16_be write_counter; // Number of times the amiibo has been written? - INSERT_PADDING_BYTES(0x1); // Unknown 1 + u8 amiibo_version; // Amiibo file version AmiiboSettings settings; // Encrypted amiibo settings HashData hmac_tag; // Hash AmiiboModelInfo model_info; // Encrypted amiibo model info HashData keygen_salt; // Salt HashData hmac_data; // Hash Service::Mii::Ver3StoreData owner_mii; // Encrypted Mii data - u64_be title_id; // Encrypted Game id - u16_be applicaton_write_counter; // Encrypted Counter + u64_be application_id; // Encrypted Game id + u16_be application_write_counter; // Encrypted Counter u32_be application_area_id; // Encrypted Game id - std::array<u8, 0x2> unknown; - std::array<u32, 0x8> unknown2; + u8 application_id_byte; + u8 unknown; + Service::Mii::NfpStoreDataExtension mii_extension; + std::array<u32, 0x5> unknown2; + u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data }; static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); struct NTAG215File { - LockBytes lock_bytes; // Tag UUID + u8 uid_crc_check2; + u8 internal_number; u16 static_lock; // Set defined pages as read only u32 compability_container; // Defines available memory HashData hmac_data; // Hash u8 constant_value; // Must be A5 u16_be write_counter; // Number of times the amiibo has been written? - INSERT_PADDING_BYTES(0x1); // Unknown 1 + u8 amiibo_version; // Amiibo file version AmiiboSettings settings; - Service::Mii::Ver3StoreData owner_mii; // Encrypted Mii data - u64_be title_id; - u16_be applicaton_write_counter; // Encrypted Counter + Service::Mii::Ver3StoreData owner_mii; // Mii data + u64_be application_id; // Game id + u16_be application_write_counter; // Counter u32_be application_area_id; - std::array<u8, 0x2> unknown; - std::array<u32, 0x8> unknown2; + u8 application_id_byte; + u8 unknown; + Service::Mii::NfpStoreDataExtension mii_extension; + std::array<u32, 0x5> unknown2; + u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data HashData hmac_tag; // Hash - UniqueSerialNumber uid; // Unique serial number - u8 nintendo_id; // Tag UUID + TagUuid uid; AmiiboModelInfo model_info; HashData keygen_salt; // Salt u32 dynamic_lock; // Dynamic lock @@ -283,7 +272,9 @@ static_assert(std::is_trivially_copyable_v<NTAG215File>, "NTAG215File must be tr #pragma pack() struct EncryptedNTAG215File { - TagUuid uuid; // Unique serial number + TagUuid uuid; + u8 uuid_crc_check2; + u8 internal_number; u16 static_lock; // Set defined pages as read only u32 compability_container; // Defines available memory EncryptedAmiiboFile user_memory; // Writable data @@ -292,21 +283,12 @@ struct EncryptedNTAG215File { u32 CFG1; // Defines number of verification attempts NTAG215Password password; // Password data }; -static_assert(sizeof(EncryptedNTAG215File) == 0x21C, "EncryptedNTAG215File is an invalid size"); +static_assert(sizeof(EncryptedNTAG215File) == sizeof(NTAG215File), + "EncryptedNTAG215File is an invalid size"); static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>, "EncryptedNTAG215File must be trivially copyable."); -struct TagInfo { - UniqueSerialNumber uuid; - INSERT_PADDING_BYTES(0x3); - u8 uuid_length; - INSERT_PADDING_BYTES(0x15); - TagProtocol protocol; - TagType tag_type; - INSERT_PADDING_BYTES(0x30); -}; -static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size"); - +// This is nn::nfp::CommonInfo struct CommonInfo { WriteDate last_write_date; u16 write_counter; @@ -317,6 +299,7 @@ struct CommonInfo { }; static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size"); +// This is nn::nfp::ModelInfo struct ModelInfo { u16 character_id; u8 character_variant; @@ -327,6 +310,7 @@ struct ModelInfo { }; static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); +// This is nn::nfp::RegisterInfo struct RegisterInfo { Service::Mii::CharInfo mii_char_info; WriteDate creation_date; @@ -336,37 +320,60 @@ struct RegisterInfo { }; static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); -struct SectorKey { - MifareCmd command; - u8 unknown; // Usually 1 - INSERT_PADDING_BYTES(0x6); - KeyData sector_key; - INSERT_PADDING_BYTES(0x2); -}; -static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size"); - -struct MifareReadBlockParameter { - u8 sector_number; - INSERT_PADDING_BYTES(0x7); - SectorKey sector_key; +// This is nn::nfp::RegisterInfoPrivate +struct RegisterInfoPrivate { + Service::Mii::MiiStoreData mii_store_data; + WriteDate creation_date; + AmiiboName amiibo_name; + u8 font_region; + INSERT_PADDING_BYTES(0x8E); }; -static_assert(sizeof(MifareReadBlockParameter) == 0x18, - "MifareReadBlockParameter is an invalid size"); - -struct MifareReadBlockData { - DataBlock data; - u8 sector_number; +static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size"); + +// This is nn::nfp::AdminInfo +struct AdminInfo { + u64 application_id; + u32 application_area_id; + u16 crc_change_counter; + u8 flags; + NFC::PackedTagType tag_type; + AppAreaVersion app_area_version; INSERT_PADDING_BYTES(0x7); + INSERT_PADDING_BYTES(0x28); }; -static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size"); +static_assert(sizeof(AdminInfo) == 0x40, "AdminInfo is an invalid size"); -struct MifareWriteBlockParameter { - DataBlock data; - u8 sector_number; - INSERT_PADDING_BYTES(0x7); - SectorKey sector_key; +#pragma pack(1) +// This is nn::nfp::NfpData +struct NfpData { + u8 magic; + INSERT_PADDING_BYTES(0x1); + u8 write_counter; + INSERT_PADDING_BYTES(0x1); + u32 settings_crc; + INSERT_PADDING_BYTES(0x38); + CommonInfo common_info; + Service::Mii::Ver3StoreData mii_char_info; + Service::Mii::NfpStoreDataExtension mii_store_data_extension; + WriteDate creation_date; + std::array<u16_be, amiibo_name_length> amiibo_name; + u16 amiibo_name_null_terminated; + Settings settings; + u8 unknown1; + u32 register_info_crc; + std::array<u32, 5> unknown2; + INSERT_PADDING_BYTES(0x64); + u64 application_id; + u32 access_id; + u16 settings_crc_counter; + u8 font_region; + NFC::PackedTagType tag_type; + AppAreaVersion console_type; + u8 application_id_byte; + INSERT_PADDING_BYTES(0x2E); + ApplicationArea application_area; }; -static_assert(sizeof(MifareWriteBlockParameter) == 0x28, - "MifareWriteBlockParameter is an invalid size"); +static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size"); +#pragma pack() } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp deleted file mode 100644 index a4d3d1bc7..000000000 --- a/src/core/hle/service/nfp/nfp_user.cpp +++ /dev/null @@ -1,672 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/nfp/nfp_device.h" -#include "core/hle/service/nfp/nfp_result.h" -#include "core/hle/service/nfp/nfp_user.h" - -namespace Service::NFP { - -IUser::IUser(Core::System& system_) - : ServiceFramework{system_, "NFP::IUser"}, service_context{system_, service_name} { - static const FunctionInfo functions[] = { - {0, &IUser::Initialize, "Initialize"}, - {1, &IUser::Finalize, "Finalize"}, - {2, &IUser::ListDevices, "ListDevices"}, - {3, &IUser::StartDetection, "StartDetection"}, - {4, &IUser::StopDetection, "StopDetection"}, - {5, &IUser::Mount, "Mount"}, - {6, &IUser::Unmount, "Unmount"}, - {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, - {8, &IUser::GetApplicationArea, "GetApplicationArea"}, - {9, &IUser::SetApplicationArea, "SetApplicationArea"}, - {10, &IUser::Flush, "Flush"}, - {11, &IUser::Restore, "Restore"}, - {12, &IUser::CreateApplicationArea, "CreateApplicationArea"}, - {13, &IUser::GetTagInfo, "GetTagInfo"}, - {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, - {15, &IUser::GetCommonInfo, "GetCommonInfo"}, - {16, &IUser::GetModelInfo, "GetModelInfo"}, - {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, - {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, - {19, &IUser::GetState, "GetState"}, - {20, &IUser::GetDeviceState, "GetDeviceState"}, - {21, &IUser::GetNpadId, "GetNpadId"}, - {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, - {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, - {24, &IUser::RecreateApplicationArea, "RecreateApplicationArea"}, - }; - RegisterHandlers(functions); - - availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent"); - - for (u32 device_index = 0; device_index < 10; device_index++) { - devices[device_index] = - std::make_shared<NfpDevice>(Core::HID::IndexToNpadIdType(device_index), system, - service_context, availability_change_event); - } -} - -IUser ::~IUser() { - availability_change_event->Close(); -} - -void IUser::Initialize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IUser::Finalize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IUser::ListDevices(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFP, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - if (ctx.GetWriteBufferSize() == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - std::vector<u64> nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); - - for (const auto& device : devices) { - if (nfp_devices.size() >= max_allowed_devices) { - continue; - } - if (device->GetCurrentState() != DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); - } - } - - if (nfp_devices.empty()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - ctx.WriteBuffer(nfp_devices); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<s32>(nfp_devices.size())); -} - -void IUser::StartDetection(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto nfp_protocol{rp.PopEnum<TagProtocol>()}; - LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StartDetection(nfp_protocol); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::StopDetection(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StopDetection(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Mount(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto model_type{rp.PopEnum<ModelType>()}; - const auto mount_target{rp.PopEnum<MountTarget>()}; - LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle, - model_type, mount_target); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->Mount(mount_target); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Unmount(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->Unmount(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::OpenApplicationArea(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto access_id{rp.Pop<u32>()}; - LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->OpenApplicationArea(access_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto data_size = ctx.GetWriteBufferSize(); - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - std::vector<u8> data(data_size); - const auto result = device.value()->GetApplicationArea(data); - ctx.WriteBuffer(data); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(static_cast<u32>(data_size)); -} - -void IUser::SetApplicationArea(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto data{ctx.ReadBuffer()}; - LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanReadBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->SetApplicationArea(data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Flush(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->Flush(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Restore(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->RestoreAmiibo(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::CreateApplicationArea(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto access_id{rp.Pop<u32>()}; - const auto data{ctx.ReadBuffer()}; - LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, - access_id, data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanReadBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->CreateApplicationArea(access_id, data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info); - ctx.WriteBuffer(tag_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetRegisterInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - RegisterInfo register_info{}; - const auto result = device.value()->GetRegisterInfo(register_info); - ctx.WriteBuffer(register_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetCommonInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - CommonInfo common_info{}; - const auto result = device.value()->GetCommonInfo(common_info); - ctx.WriteBuffer(common_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetModelInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - ModelInfo model_info{}; - const auto result = device.value()->GetModelInfo(model_info); - ctx.WriteBuffer(model_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetActivateEvent()); -} - -void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetDeactivateEvent()); -} - -void IUser::GetState(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFP, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetCurrentState()); -} - -void IUser::GetNpadId(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetNpadId()); -} - -void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(device.value()->GetApplicationAreaSize()); -} - -void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(availability_change_event->GetReadableEvent()); -} - -void IUser::RecreateApplicationArea(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop<u64>()}; - const auto access_id{rp.Pop<u32>()}; - const auto data{ctx.ReadBuffer()}; - LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, - access_id, data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->RecreateApplicationArea(access_id, data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -std::optional<std::shared_ptr<NfpDevice>> IUser::GetNfpDevice(u64 handle) { - for (auto& device : devices) { - if (device->GetHandle() == handle) { - return device; - } - } - return std::nullopt; -} - -} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h deleted file mode 100644 index 7e9a90af8..000000000 --- a/src/core/hle/service/nfp/nfp_user.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <memory> -#include <optional> - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::NFP { -class NfpDevice; - -class IUser final : public ServiceFramework<IUser> { -public: - explicit IUser(Core::System& system_); - ~IUser(); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - void Initialize(Kernel::HLERequestContext& ctx); - void Finalize(Kernel::HLERequestContext& ctx); - void ListDevices(Kernel::HLERequestContext& ctx); - void StartDetection(Kernel::HLERequestContext& ctx); - void StopDetection(Kernel::HLERequestContext& ctx); - void Mount(Kernel::HLERequestContext& ctx); - void Unmount(Kernel::HLERequestContext& ctx); - void OpenApplicationArea(Kernel::HLERequestContext& ctx); - void GetApplicationArea(Kernel::HLERequestContext& ctx); - void SetApplicationArea(Kernel::HLERequestContext& ctx); - void Flush(Kernel::HLERequestContext& ctx); - void Restore(Kernel::HLERequestContext& ctx); - void CreateApplicationArea(Kernel::HLERequestContext& ctx); - void GetTagInfo(Kernel::HLERequestContext& ctx); - void GetRegisterInfo(Kernel::HLERequestContext& ctx); - void GetCommonInfo(Kernel::HLERequestContext& ctx); - void GetModelInfo(Kernel::HLERequestContext& ctx); - void AttachActivateEvent(Kernel::HLERequestContext& ctx); - void AttachDeactivateEvent(Kernel::HLERequestContext& ctx); - void GetState(Kernel::HLERequestContext& ctx); - void GetDeviceState(Kernel::HLERequestContext& ctx); - void GetNpadId(Kernel::HLERequestContext& ctx); - void GetApplicationAreaSize(Kernel::HLERequestContext& ctx); - void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx); - void RecreateApplicationArea(Kernel::HLERequestContext& ctx); - - std::optional<std::shared_ptr<NfpDevice>> GetNfpDevice(u64 handle); - - KernelHelpers::ServiceContext service_context; - - std::array<std::shared_ptr<NfpDevice>, 10> devices{}; - - State state{State::NonInitialized}; - Kernel::KEvent* availability_change_event; -}; - -} // namespace Service::NFP diff --git a/src/core/hle/service/ngct/ngct.cpp b/src/core/hle/service/ngct/ngct.cpp index 8af8a835d..493c80ed2 100644 --- a/src/core/hle/service/ngct/ngct.cpp +++ b/src/core/hle/service/ngct/ngct.cpp @@ -3,8 +3,9 @@ #include "common/string_util.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ngct/ngct.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::NGCT { @@ -23,7 +24,7 @@ public: } private: - void Match(Kernel::HLERequestContext& ctx) { + void Match(HLERequestContext& ctx) { const auto buffer = ctx.ReadBuffer(); const auto text = Common::StringFromFixedZeroTerminatedBuffer( reinterpret_cast<const char*>(buffer.data()), buffer.size()); @@ -36,7 +37,7 @@ private: rb.Push(false); } - void Filter(Kernel::HLERequestContext& ctx) { + void Filter(HLERequestContext& ctx) { const auto buffer = ctx.ReadBuffer(); const auto text = Common::StringFromFixedZeroTerminatedBuffer( reinterpret_cast<const char*>(buffer.data()), buffer.size()); @@ -51,8 +52,11 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<IService>(system)->InstallAsService(system.ServiceManager()); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("ngct:u", std::make_shared<IService>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NGCT diff --git a/src/core/hle/service/ngct/ngct.h b/src/core/hle/service/ngct/ngct.h index 370bd4a25..27c34dad4 100644 --- a/src/core/hle/service/ngct/ngct.h +++ b/src/core/hle/service/ngct/ngct.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::NGCT { -/// Registers all NGCT services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::NGCT diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 5d32adf64..91d42853e 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -2,10 +2,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nifm/nifm.h" +#include "core/hle/service/server_manager.h" namespace { @@ -216,8 +217,8 @@ public: } private: - void Submit(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NIFM, "(STUBBED) called"); + void Submit(HLERequestContext& ctx) { + LOG_DEBUG(Service_NIFM, "(STUBBED) called"); if (state == RequestState::NotSubmitted) { UpdateState(RequestState::OnHold); @@ -227,16 +228,16 @@ private: rb.Push(ResultSuccess); } - void GetRequestState(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NIFM, "(STUBBED) called"); + void GetRequestState(HLERequestContext& ctx) { + LOG_DEBUG(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.PushEnum(state); } - void GetResult(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NIFM, "(STUBBED) called"); + void GetResult(HLERequestContext& ctx) { + LOG_DEBUG(Service_NIFM, "(STUBBED) called"); const auto result = [this] { const auto has_connection = Network::GetHostIPv4Address().has_value(); @@ -260,7 +261,7 @@ private: rb.Push(result); } - void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { + void GetSystemEventReadableHandles(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 2}; @@ -268,21 +269,21 @@ private: rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent()); } - void Cancel(Kernel::HLERequestContext& ctx) { + void Cancel(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void SetConnectionConfirmationOption(Kernel::HLERequestContext& ctx) { + void SetConnectionConfirmationOption(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void GetAppletInfo(Kernel::HLERequestContext& ctx) { + void GetAppletInfo(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); std::vector<u8> out_buffer(ctx.GetWriteBufferSize()); @@ -321,7 +322,7 @@ public: } }; -void IGeneralService::GetClientId(Kernel::HLERequestContext& ctx) { +void IGeneralService::GetClientId(HLERequestContext& ctx) { static constexpr u32 client_id = 1; LOG_WARNING(Service_NIFM, "(STUBBED) called"); @@ -330,7 +331,7 @@ void IGeneralService::GetClientId(Kernel::HLERequestContext& ctx) { rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid } -void IGeneralService::CreateScanRequest(Kernel::HLERequestContext& ctx) { +void IGeneralService::CreateScanRequest(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -339,7 +340,7 @@ void IGeneralService::CreateScanRequest(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IScanRequest>(system); } -void IGeneralService::CreateRequest(Kernel::HLERequestContext& ctx) { +void IGeneralService::CreateRequest(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -348,7 +349,7 @@ void IGeneralService::CreateRequest(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IRequest>(system); } -void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { +void IGeneralService::GetCurrentNetworkProfile(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); const auto net_iface = Network::GetSelectedNetworkInterface(); @@ -407,14 +408,14 @@ void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IGeneralService::RemoveNetworkProfile(Kernel::HLERequestContext& ctx) { +void IGeneralService::RemoveNetworkProfile(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void IGeneralService::GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { +void IGeneralService::GetCurrentIpAddress(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); auto ipv4 = Network::GetHostIPv4Address(); @@ -435,7 +436,7 @@ void IGeneralService::GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { rb.PushRaw(*ipv4); } -void IGeneralService::CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { +void IGeneralService::CreateTemporaryNetworkProfile(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, "SfNetworkProfileData is not the correct size"); @@ -450,7 +451,7 @@ void IGeneralService::CreateTemporaryNetworkProfile(Kernel::HLERequestContext& c rb.PushRaw<u128>(uuid); } -void IGeneralService::GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { +void IGeneralService::GetCurrentIpConfigInfo(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); struct IpConfigInfo { @@ -494,7 +495,7 @@ void IGeneralService::GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { rb.PushRaw<IpConfigInfo>(ip_config_info); } -void IGeneralService::IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) { +void IGeneralService::IsWirelessCommunicationEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -502,7 +503,7 @@ void IGeneralService::IsWirelessCommunicationEnabled(Kernel::HLERequestContext& rb.Push<u8>(1); } -void IGeneralService::GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) { +void IGeneralService::GetInternetConnectionStatus(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); struct Output { @@ -519,7 +520,7 @@ void IGeneralService::GetInternetConnectionStatus(Kernel::HLERequestContext& ctx rb.PushRaw(out); } -void IGeneralService::IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) { +void IGeneralService::IsEthernetCommunicationEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -531,7 +532,7 @@ void IGeneralService::IsEthernetCommunicationEnabled(Kernel::HLERequestContext& } } -void IGeneralService::IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { +void IGeneralService::IsAnyInternetRequestAccepted(HLERequestContext& ctx) { LOG_ERROR(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -609,7 +610,7 @@ public: } private: - void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) { + void CreateGeneralServiceOld(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -617,7 +618,7 @@ private: rb.PushIpcInterface<IGeneralService>(system); } - void CreateGeneralService(Kernel::HLERequestContext& ctx) { + void CreateGeneralService(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -626,10 +627,16 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<NetworkInterface>("nifm:a", system)->InstallAsService(service_manager); - std::make_shared<NetworkInterface>("nifm:s", system)->InstallAsService(service_manager); - std::make_shared<NetworkInterface>("nifm:u", system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("nifm:a", + std::make_shared<NetworkInterface>("nifm:a", system)); + server_manager->RegisterNamedService("nifm:s", + std::make_shared<NetworkInterface>("nifm:s", system)); + server_manager->RegisterNamedService("nifm:u", + std::make_shared<NetworkInterface>("nifm:u", system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NIFM diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h index 48161be28..9b20e6823 100644 --- a/src/core/hle/service/nifm/nifm.h +++ b/src/core/hle/service/nifm/nifm.h @@ -12,14 +12,9 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::NIFM { -/// Registers all NIFM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); class IGeneralService final : public ServiceFramework<IGeneralService> { public: @@ -27,18 +22,18 @@ public: ~IGeneralService() override; private: - void GetClientId(Kernel::HLERequestContext& ctx); - void CreateScanRequest(Kernel::HLERequestContext& ctx); - void CreateRequest(Kernel::HLERequestContext& ctx); - void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx); - void RemoveNetworkProfile(Kernel::HLERequestContext& ctx); - void GetCurrentIpAddress(Kernel::HLERequestContext& ctx); - void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx); - void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx); - void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx); - void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx); - void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx); - void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx); + void GetClientId(HLERequestContext& ctx); + void CreateScanRequest(HLERequestContext& ctx); + void CreateRequest(HLERequestContext& ctx); + void GetCurrentNetworkProfile(HLERequestContext& ctx); + void RemoveNetworkProfile(HLERequestContext& ctx); + void GetCurrentIpAddress(HLERequestContext& ctx); + void CreateTemporaryNetworkProfile(HLERequestContext& ctx); + void GetCurrentIpConfigInfo(HLERequestContext& ctx); + void IsWirelessCommunicationEnabled(HLERequestContext& ctx); + void GetInternetConnectionStatus(HLERequestContext& ctx); + void IsEthernetCommunicationEnabled(HLERequestContext& ctx); + void IsAnyInternetRequestAccepted(HLERequestContext& ctx); Network::RoomNetwork& network; }; diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 5a8a91e0b..42de87f9a 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -4,12 +4,12 @@ #include <chrono> #include <ctime> #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nim/nim.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::NIM { @@ -46,7 +46,7 @@ public: } private: - void CreateAsyncInterface(Kernel::HLERequestContext& ctx) { + void CreateAsyncInterface(HLERequestContext& ctx) { LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -68,7 +68,7 @@ public: } private: - void CreateAccessorInterface(Kernel::HLERequestContext& ctx) { + void CreateAccessorInterface(HLERequestContext& ctx) { LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -239,14 +239,14 @@ public: } private: - void CreateServerInterface(Kernel::HLERequestContext& ctx) { + void CreateServerInterface(HLERequestContext& ctx) { LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IShopServiceAccessServer>(system); } - void IsLargeResourceAvailable(Kernel::HLERequestContext& ctx) { + void IsLargeResourceAvailable(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto unknown{rp.Pop<u64>()}; @@ -325,7 +325,7 @@ public: } private: - void StartTask(Kernel::HLERequestContext& ctx) { + void StartTask(HLERequestContext& ctx) { // No need to connect to the internet, just finish the task straight away. LOG_DEBUG(Service_NIM, "called"); finished_event->Signal(); @@ -333,7 +333,7 @@ private: rb.Push(ResultSuccess); } - void GetFinishNotificationEvent(Kernel::HLERequestContext& ctx) { + void GetFinishNotificationEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -341,21 +341,21 @@ private: rb.PushCopyObjects(finished_event->GetReadableEvent()); } - void GetResult(Kernel::HLERequestContext& ctx) { + void GetResult(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void Cancel(Kernel::HLERequestContext& ctx) { + void Cancel(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); finished_event->Clear(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void IsProcessing(Kernel::HLERequestContext& ctx) { + void IsProcessing(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -363,7 +363,7 @@ private: rb.PushRaw<u32>(0); // We instantly process the request } - void GetServerTime(Kernel::HLERequestContext& ctx) { + void GetServerTime(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); const s64 server_time{std::chrono::duration_cast<std::chrono::seconds>( @@ -394,7 +394,7 @@ public: } private: - void OpenEnsureNetworkClockAvailabilityService(Kernel::HLERequestContext& ctx) { + void OpenEnsureNetworkClockAvailabilityService(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -403,14 +403,14 @@ private: } // TODO(ogniK): Do we need these? - void SuspendAutonomicTimeCorrection(Kernel::HLERequestContext& ctx) { + void SuspendAutonomicTimeCorrection(HLERequestContext& ctx) { LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void ResumeAutonomicTimeCorrection(Kernel::HLERequestContext& ctx) { + void ResumeAutonomicTimeCorrection(HLERequestContext& ctx) { LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -418,11 +418,14 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<NIM>(system)->InstallAsService(sm); - std::make_shared<NIM_ECA>(system)->InstallAsService(sm); - std::make_shared<NIM_SHP>(system)->InstallAsService(sm); - std::make_shared<NTC>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("nim", std::make_shared<NIM>(system)); + server_manager->RegisterNamedService("nim:eca", std::make_shared<NIM_ECA>(system)); + server_manager->RegisterNamedService("nim:shp", std::make_shared<NIM_SHP>(system)); + server_manager->RegisterNamedService("ntc", std::make_shared<NTC>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NIM diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h index 8f6ff28e8..e7d599908 100644 --- a/src/core/hle/service/nim/nim.h +++ b/src/core/hle/service/nim/nim.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::NIM { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::NIM diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp index 8133711c2..a162e5c54 100644 --- a/src/core/hle/service/npns/npns.cpp +++ b/src/core/hle/service/npns/npns.cpp @@ -4,8 +4,8 @@ #include <memory> #include "core/hle/service/npns/npns.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::NPNS { @@ -94,9 +94,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<NPNS_S>(system)->InstallAsService(sm); - std::make_shared<NPNS_U>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("npns:s", std::make_shared<NPNS_S>(system)); + server_manager->RegisterNamedService("npns:u", std::make_shared<NPNS_U>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NPNS diff --git a/src/core/hle/service/npns/npns.h b/src/core/hle/service/npns/npns.h index 84e6ec437..0019fca76 100644 --- a/src/core/hle/service/npns/npns.h +++ b/src/core/hle/service/npns/npns.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::NPNS { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::NPNS diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/errors.h index 8a7621798..16d2ea6f7 100644 --- a/src/core/hle/service/ns/errors.h +++ b/src/core/hle/service/ns/errors.h @@ -7,5 +7,6 @@ namespace Service::NS { -constexpr Result ERR_APPLICATION_LANGUAGE_NOT_FOUND{ErrorModule::NS, 300}; -}
\ No newline at end of file +constexpr Result ResultApplicationLanguageNotFound{ErrorModule::NS, 300}; + +} diff --git a/src/core/hle/service/ns/iplatform_service_manager.cpp b/src/core/hle/service/ns/iplatform_service_manager.cpp index 1fab2f0dd..6c2f5e70b 100644 --- a/src/core/hle/service/ns/iplatform_service_manager.cpp +++ b/src/core/hle/service/ns/iplatform_service_manager.cpp @@ -15,11 +15,11 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs.h" #include "core/file_sys/system_archive/system_archive.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_memory.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ns/iplatform_service_manager.h" namespace Service::NS { @@ -119,7 +119,7 @@ struct IPlatformServiceManager::Impl { break; } - // Derive key withing inverse xor + // Derive key within inverse xor const u32 KEY = GetU32Swapped(input.data() + cur_offset) ^ EXPECTED_MAGIC; const u32 SIZE = GetU32Swapped(input.data() + cur_offset + 4) ^ KEY; shared_font_regions.push_back(FontRegion{cur_offset + 8, SIZE}); @@ -208,7 +208,7 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch IPlatformServiceManager::~IPlatformServiceManager() = default; -void IPlatformServiceManager::RequestLoad(Kernel::HLERequestContext& ctx) { +void IPlatformServiceManager::RequestLoad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 shared_font_type{rp.Pop<u32>()}; // Games don't call this so all fonts should be loaded @@ -218,7 +218,7 @@ void IPlatformServiceManager::RequestLoad(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IPlatformServiceManager::GetLoadState(Kernel::HLERequestContext& ctx) { +void IPlatformServiceManager::GetLoadState(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 font_id{rp.Pop<u32>()}; LOG_DEBUG(Service_NS, "called, font_id={}", font_id); @@ -228,7 +228,7 @@ void IPlatformServiceManager::GetLoadState(Kernel::HLERequestContext& ctx) { rb.Push<u32>(static_cast<u32>(LoadState::Done)); } -void IPlatformServiceManager::GetSize(Kernel::HLERequestContext& ctx) { +void IPlatformServiceManager::GetSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 font_id{rp.Pop<u32>()}; LOG_DEBUG(Service_NS, "called, font_id={}", font_id); @@ -238,7 +238,7 @@ void IPlatformServiceManager::GetSize(Kernel::HLERequestContext& ctx) { rb.Push<u32>(impl->GetSharedFontRegion(font_id).size); } -void IPlatformServiceManager::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) { +void IPlatformServiceManager::GetSharedMemoryAddressOffset(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 font_id{rp.Pop<u32>()}; LOG_DEBUG(Service_NS, "called, font_id={}", font_id); @@ -248,7 +248,7 @@ void IPlatformServiceManager::GetSharedMemoryAddressOffset(Kernel::HLERequestCon rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset); } -void IPlatformServiceManager::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { +void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx) { // Map backing memory for the font data LOG_DEBUG(Service_NS, "called"); @@ -261,7 +261,7 @@ void IPlatformServiceManager::GetSharedMemoryNativeHandle(Kernel::HLERequestCont rb.PushCopyObjects(&kernel.GetFontSharedMem()); } -void IPlatformServiceManager::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) { +void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code); diff --git a/src/core/hle/service/ns/iplatform_service_manager.h b/src/core/hle/service/ns/iplatform_service_manager.h index ed6eda89f..03071e02b 100644 --- a/src/core/hle/service/ns/iplatform_service_manager.h +++ b/src/core/hle/service/ns/iplatform_service_manager.h @@ -42,12 +42,12 @@ public: ~IPlatformServiceManager() override; private: - void RequestLoad(Kernel::HLERequestContext& ctx); - void GetLoadState(Kernel::HLERequestContext& ctx); - void GetSize(Kernel::HLERequestContext& ctx); - void GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx); - void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); - void GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx); + void RequestLoad(HLERequestContext& ctx); + void GetLoadState(HLERequestContext& ctx); + void GetSize(HLERequestContext& ctx); + void GetSharedMemoryAddressOffset(HLERequestContext& ctx); + void GetSharedMemoryNativeHandle(HLERequestContext& ctx); + void GetSharedFontInOrderOfPriority(HLERequestContext& ctx); struct Impl; std::unique_ptr<Impl> impl; diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index f59a1a63d..376067a95 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -7,13 +7,14 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/vfs.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/glue/glue_manager.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ns/errors.h" #include "core/hle/service/ns/iplatform_service_manager.h" #include "core/hle/service/ns/language.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/ns/pdm_qry.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/set/set.h" namespace Service::NS { @@ -159,6 +160,8 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {606, nullptr, "GetContentMetaStorage"}, {607, nullptr, "ListAvailableAddOnContent"}, {609, nullptr, "ListAvailabilityAssuredAddOnContent"}, + {610, nullptr, "GetInstalledContentMetaStorage"}, + {611, nullptr, "PrepareAddOnContent"}, {700, nullptr, "PushDownloadTaskList"}, {701, nullptr, "ClearTaskStatusList"}, {702, nullptr, "RequestDownloadTaskList"}, @@ -228,6 +231,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {1900, nullptr, "IsActiveAccount"}, {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, {1902, nullptr, "GetApplicationTicketInfo"}, + {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"}, {2000, nullptr, "GetSystemDeliveryInfo"}, {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, {2002, nullptr, "VerifyDeliveryProtocolVersion"}, @@ -276,8 +280,11 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {2352, nullptr, "RequestResolveNoDownloadRightsError"}, {2353, nullptr, "GetApplicationDownloadTaskInfo"}, {2354, nullptr, "PrioritizeApplicationBackgroundTask"}, - {2355, nullptr, "Unknown2355"}, - {2356, nullptr, "Unknown2356"}, + {2355, nullptr, "PreferStorageEfficientUpdate"}, + {2356, nullptr, "RequestStorageEfficientUpdatePreferable"}, + {2357, nullptr, "EnableMultiCoreDownload"}, + {2358, nullptr, "DisableMultiCoreDownload"}, + {2359, nullptr, "IsMultiCoreDownloadEnabled"}, {2400, nullptr, "GetPromotionInfo"}, {2401, nullptr, "CountPromotionInfo"}, {2402, nullptr, "ListPromotionInfo"}, @@ -295,6 +302,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {2519, nullptr, "IsQualificationTransitionSupported"}, {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"}, {2521, nullptr, "GetRightsUserChangedEvent"}, + {2522, nullptr, "IsRomRedirectionAvailable"}, {2800, nullptr, "GetApplicationIdOfPreomia"}, {3000, nullptr, "RegisterDeviceLockKey"}, {3001, nullptr, "UnregisterDeviceLockKey"}, @@ -311,6 +319,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {3012, nullptr, "IsApplicationTitleHidden"}, {3013, nullptr, "IsGameCardEnabled"}, {3014, nullptr, "IsLocalContentShareEnabled"}, + {3050, nullptr, "ListAssignELicenseTaskResult"}, {9999, nullptr, "GetApplicationCertificate"}, }; // clang-format on @@ -320,7 +329,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ IApplicationManagerInterface::~IApplicationManagerInterface() = default; -void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestContext& ctx) { +void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto flag = rp.PopRaw<u64>(); LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); @@ -379,7 +388,7 @@ void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestC rb.Push<u32>(static_cast<u32>(out.size())); } -void IApplicationManagerInterface::GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx) { +void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto supported_languages = rp.Pop<u32>(); @@ -407,14 +416,14 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( if (application_language == std::nullopt) { LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", language_code); - return ERR_APPLICATION_LANGUAGE_NOT_FOUND; + return Service::NS::ResultApplicationLanguageNotFound; } const auto priority_list = GetApplicationLanguagePriorityList(*application_language); if (!priority_list) { LOG_ERROR(Service_NS, "Could not find application language priorities! application_language={}", *application_language); - return ERR_APPLICATION_LANGUAGE_NOT_FOUND; + return Service::NS::ResultApplicationLanguageNotFound; } // Try to find a valid language. @@ -427,11 +436,11 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}", supported_languages); - return ERR_APPLICATION_LANGUAGE_NOT_FOUND; + return Service::NS::ResultApplicationLanguageNotFound; } void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( - Kernel::HLERequestContext& ctx) { + HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto application_language = rp.Pop<u8>(); @@ -452,7 +461,7 @@ ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguag ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); if (language_code == std::nullopt) { LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language); - return ERR_APPLICATION_LANGUAGE_NOT_FOUND; + return Service::NS::ResultApplicationLanguageNotFound; } return static_cast<u64>(*language_code); @@ -595,8 +604,7 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; -void IReadOnlyApplicationControlDataInterface::GetApplicationControlData( - Kernel::HLERequestContext& ctx) { +void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) { enum class ApplicationControlSource : u8 { CacheOnly, Storage, @@ -744,7 +752,7 @@ public: } private: - void OpenSystemUpdateControl(Kernel::HLERequestContext& ctx) { + void OpenSystemUpdateControl(HLERequestContext& ctx) { LOG_DEBUG(Service_NS, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -768,7 +776,7 @@ public: } private: - void NeedsUpdateVulnerability(Kernel::HLERequestContext& ctx) { + void NeedsUpdateVulnerability(HLERequestContext& ctx) { LOG_WARNING(Service_NS, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -777,23 +785,26 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - - std::make_shared<NS>("ns:am2", system)->InstallAsService(service_manager); - std::make_shared<NS>("ns:ec", system)->InstallAsService(service_manager); - std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); - std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); - std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); - std::make_shared<NS>("ns:ro", system)->InstallAsService(service_manager); - - std::make_shared<NS_DEV>(system)->InstallAsService(service_manager); - std::make_shared<NS_SU>(system)->InstallAsService(service_manager); - std::make_shared<NS_VM>(system)->InstallAsService(service_manager); - - std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager); - - std::make_shared<IPlatformServiceManager>(system, "pl:s")->InstallAsService(service_manager); - std::make_shared<IPlatformServiceManager>(system, "pl:u")->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system)); + server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system)); + server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system)); + server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system)); + server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system)); + server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system)); + + server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system)); + server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system)); + server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system)); + server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system)); + + server_manager->RegisterNamedService("pl:s", + std::make_shared<IPlatformServiceManager>(system, "pl:s")); + server_manager->RegisterNamedService("pl:u", + std::make_shared<IPlatformServiceManager>(system, "pl:u")); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::NS diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 9c18e935c..203388e1f 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -32,9 +32,9 @@ public: ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language); private: - void GetApplicationControlData(Kernel::HLERequestContext& ctx); - void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx); - void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx); + void GetApplicationControlData(HLERequestContext& ctx); + void GetApplicationDesiredLanguage(HLERequestContext& ctx); + void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx); }; class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { @@ -80,7 +80,7 @@ public: ~IReadOnlyApplicationControlDataInterface() override; private: - void GetApplicationControlData(Kernel::HLERequestContext& ctx); + void GetApplicationControlData(HLERequestContext& ctx); }; class NS final : public ServiceFramework<NS> { @@ -92,7 +92,7 @@ public: private: template <typename T, typename... Args> - void PushInterface(Kernel::HLERequestContext& ctx) { + void PushInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NS, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -100,7 +100,7 @@ private: rb.PushIpcInterface<T>(system); } - void PushIApplicationManagerInterface(Kernel::HLERequestContext& ctx) { + void PushIApplicationManagerInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NS, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -110,15 +110,14 @@ private: template <typename T, typename... Args> std::shared_ptr<T> GetInterface(Args&&... args) const { - static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, + static_assert(std::is_base_of_v<SessionRequestHandler, T>, "Not a base of ServiceFrameworkBase"); return std::make_shared<T>(std::forward<Args>(args)...); } }; -/// Registers all NS services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace NS } // namespace Service diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp index aac8f573f..ce0ee30e0 100644 --- a/src/core/hle/service/ns/pdm_qry.cpp +++ b/src/core/hle/service/ns/pdm_qry.cpp @@ -5,7 +5,7 @@ #include "common/logging/log.h" #include "common/uuid.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ns/pdm_qry.h" #include "core/hle/service/service.h" @@ -42,7 +42,7 @@ PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} { PDM_QRY::~PDM_QRY() = default; -void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(Kernel::HLERequestContext& ctx) { +void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto unknown = rp.Pop<bool>(); rp.Pop<u8>(); // Padding diff --git a/src/core/hle/service/ns/pdm_qry.h b/src/core/hle/service/ns/pdm_qry.h index abcc3bef3..c98e01660 100644 --- a/src/core/hle/service/ns/pdm_qry.h +++ b/src/core/hle/service/ns/pdm_qry.h @@ -26,7 +26,7 @@ public: ~PDM_QRY() override; private: - void QueryPlayStatisticsByApplicationIdAndUserAccountId(Kernel::HLERequestContext& ctx); + void QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx); }; } // namespace Service::NS diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp index aba51d280..c4c4c2593 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp @@ -64,7 +64,7 @@ void SyncpointManager::FreeSyncpoint(u32 id) { } bool SyncpointManager::IsSyncpointAllocated(u32 id) const { - return (id <= SyncpointCount) && syncpoints[id].reserved; + return (id < SyncpointCount) && syncpoints[id].reserved; } bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const { diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.h b/src/core/hle/service/nvdrv/core/syncpoint_manager.h index 4f2cefae5..7728ff596 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.h @@ -124,7 +124,7 @@ private: //!< value }; - constexpr static std::size_t SyncpointCount{192}; + static constexpr std::size_t SyncpointCount{192}; std::array<SyncpointInfo, SyncpointCount> syncpoints{}; std::mutex reservation_lock; diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 204b0e757..a04538d5d 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -3,7 +3,9 @@ #pragma once +#include <span> #include <vector> + #include "common/common_types.h" #include "core/hle/service/nvdrv/nvdata.h" @@ -31,8 +33,8 @@ public: * @param output A buffer where the output data will be written to. * @returns The result code of the ioctl. */ - virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) = 0; + virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) = 0; /** * Handles an ioctl2 request. @@ -42,8 +44,8 @@ public: * @param output A buffer where the output data will be written to. * @returns The result code of the ioctl. */ - virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) = 0; + virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) = 0; /** * Handles an ioctl3 request. @@ -53,11 +55,11 @@ public: * @param inline_output A buffer where the inlined output data will be written to. * @returns The result code of the ioctl. */ - virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) = 0; + virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) = 0; /** - * Called once a device is openned + * Called once a device is opened * @param fd The device fd */ virtual void OnOpen(DeviceFD fd) = 0; diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 4122fc98d..05a43d8dc 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -17,20 +17,20 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core) : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {} nvdisp_disp0::~nvdisp_disp0() = default; -NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } @@ -51,8 +51,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat form stride, format, transform, crop_rect}; system.GPU().RequestSwapBuffers(&framebuffer, fences, num_fences); - system.GetPerfStats().EndSystemFrame(); system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); + system.GetPerfStats().EndSystemFrame(); system.GetPerfStats().BeginSystemFrame(); } diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 04217ab12..daee05fe8 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -8,8 +8,8 @@ #include "common/common_types.h" #include "common/math_util.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" -#include "core/hle/service/nvflinger/buffer_transform_flags.h" -#include "core/hle/service/nvflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/buffer_transform_flags.h" +#include "core/hle/service/nvnflinger/pixel_format.h" namespace Service::Nvidia::NvCore { class Container; @@ -25,12 +25,12 @@ public: explicit nvdisp_disp0(Core::System& system_, NvCore::Container& core); ~nvdisp_disp0() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index b635e6ed1..07e570a9f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -27,8 +27,8 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, Module& module_, NvCore::Con nvhost_as_gpu::~nvhost_as_gpu() = default; -NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 'A': switch (command.cmd) { @@ -60,14 +60,14 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8> return NvResult::NotImplemented; } -NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { switch (command.group) { case 'A': switch (command.cmd) { @@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8> void nvhost_as_gpu::OnOpen(DeviceFD fd) {} void nvhost_as_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) { IoctlAllocAsEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) { IoctlAllocSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -220,7 +220,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) { mapping_map.erase(offset); } -NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) { IoctlFreeSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -266,15 +266,14 @@ NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) { const auto num_entries = input.size() / sizeof(IoctlRemapEntry); LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); - std::vector<IoctlRemapEntry> entries(num_entries); - std::memcpy(entries.data(), input.data(), input.size()); - std::scoped_lock lock(mutex); + entries.resize_destructive(num_entries); + std::memcpy(entries.data(), input.data(), input.size()); if (!vm.initialised) { return NvResult::BadValue; @@ -320,7 +319,7 @@ NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& out return NvResult::Success; } -NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) { IoctlMapBufferEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -424,7 +423,7 @@ NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8 return NvResult::Success; } -NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { IoctlUnmapBuffer params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -463,7 +462,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8 return NvResult::Success; } -NvResult nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) { IoctlBindChannel params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); @@ -492,7 +491,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) { }; } -NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) { IoctlGetVaRegions params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -511,8 +510,8 @@ NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u return NvResult::Success; } -NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& inline_output) { +NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) { IoctlGetVaRegions params{}; std::memcpy(¶ms, input.data(), input.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 86fe71c75..2af3e1260 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -15,6 +15,7 @@ #include "common/address_space.h" #include "common/common_funcs.h" #include "common/common_types.h" +#include "common/scratch_buffer.h" #include "common/swap.h" #include "core/hle/service/nvdrv/core/nvmap.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" @@ -47,12 +48,12 @@ public: explicit nvhost_as_gpu(Core::System& system_, Module& module, NvCore::Container& core); ~nvhost_as_gpu() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -138,18 +139,18 @@ private: static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, "IoctlGetVaRegions is incorrect size"); - NvResult AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output); - NvResult AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); - NvResult Remap(const std::vector<u8>& input, std::vector<u8>& output); - NvResult MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); - NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - NvResult FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); - NvResult BindChannel(const std::vector<u8>& input, std::vector<u8>& output); + NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output); + NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output); + NvResult Remap(std::span<const u8> input, std::span<u8> output); + NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output); + NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); + NvResult FreeSpace(std::span<const u8> input, std::span<u8> output); + NvResult BindChannel(std::span<const u8> input, std::span<u8> output); void GetVARegionsImpl(IoctlGetVaRegions& params); - NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& inline_output); + NvResult GetVARegions(std::span<const u8> input, std::span<u8> output); + NvResult GetVARegions(std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output); void FreeMappingLocked(u64 offset); @@ -212,6 +213,7 @@ private: bool initialised{}; } vm; std::shared_ptr<Tegra::MemoryManager> gmmu; + Common::ScratchBuffer<IoctlRemapEntry> entries; // s32 channel{}; // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index eee11fab8..4d55554b4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -34,8 +34,8 @@ nvhost_ctrl::~nvhost_ctrl() { } } -NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 0x0: switch (command.cmd) { @@ -63,14 +63,14 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& return NvResult::NotImplemented; } -NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_outpu) { +NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_outpu) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } @@ -79,7 +79,7 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {} void nvhost_ctrl::OnClose(DeviceFD fd) {} -NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) { IocGetConfigParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), @@ -87,7 +87,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector return NvResult::ConfigVarNotFound; // Returns error on production mode } -NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation) { IocCtrlEventWaitParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -150,9 +150,9 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector const auto check_failing = [&]() { if (events[slot].fails > 2) { { - auto lk = system.StallProcesses(); + auto lk = system.StallApplication(); host1x_syncpoint_manager.WaitHost(fence_id, target_value); - system.UnstallProcesses(); + system.UnstallApplication(); } params.value.raw = target_value; return true; @@ -231,7 +231,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) { return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) { IocCtrlEventRegisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id; @@ -252,8 +252,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::ve return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) { IocCtrlEventUnregisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id & 0x00FF; @@ -263,8 +262,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, return FreeEvent(event_id); } -NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) { IocCtrlEventUnregisterBatchParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); u64 event_mask = params.user_events; @@ -282,7 +280,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input, return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) { IocCtrlEventClearParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 0b56d7070..2efed4862 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -25,12 +25,12 @@ public: NvCore::Container& core); ~nvhost_ctrl() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -186,13 +186,12 @@ private: static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, "IocCtrlEventKill is incorrect size"); - NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, - bool is_allocation); - NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlEventUnregisterBatch(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); + NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output); + NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation); + NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output); + NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output); + NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output); + NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output); NvResult FreeEvent(u32 slot); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index b97813fbc..6081d92e9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -21,8 +21,8 @@ nvhost_ctrl_gpu::~nvhost_ctrl_gpu() { events_interface.FreeEvent(unknown_event); } -NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 'G': switch (command.cmd) { @@ -53,14 +53,14 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u return NvResult::NotImplemented; } -NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { switch (command.group) { case 'G': switch (command.cmd) { @@ -82,8 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlCharacteristics params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -128,8 +127,8 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& inline_output) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlCharacteristics params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -176,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std:: return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) { IoctlGpuGetTpcMasksArgs params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); @@ -187,8 +186,8 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& inline_output) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) { IoctlGpuGetTpcMasksArgs params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); @@ -200,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlActiveSlotMask params{}; @@ -213,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::v return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlZcullGetCtxSize params{}; @@ -225,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vec return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlNvgpuGpuZcullGetInfoArgs params{}; @@ -248,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcSetTable params{}; @@ -264,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcQueryTable params{}; @@ -274,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vecto return NvResult::Success; } -NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlFlushL2 params{}; @@ -284,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlGetGpuTime params{}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 1e8f254e2..97995551c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -21,12 +21,12 @@ public: explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_); ~nvhost_ctrl_gpu() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -151,21 +151,21 @@ private: }; static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); - NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& inline_output); - - NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& inline_output); - - NvResult GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); - NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output); + NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output); + + NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output); + NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output); + + NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output); + NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output); + NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output); + NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output); + NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output); + NvResult FlushL2(std::span<const u8> input, std::span<u8> output); + NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output); EventInterface& events_interface; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index e123564c6..46a25fcab 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -46,8 +46,8 @@ nvhost_gpu::~nvhost_gpu() { syncpoint_manager.FreeSyncpoint(channel_syncpoint); } -NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 0x0: switch (command.cmd) { @@ -98,8 +98,8 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i return NvResult::NotImplemented; }; -NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { switch (command.group) { case 'H': switch (command.cmd) { @@ -112,8 +112,8 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& i return NvResult::NotImplemented; } -NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } @@ -121,7 +121,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i void nvhost_gpu::OnOpen(DeviceFD fd) {} void nvhost_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); @@ -130,7 +130,7 @@ NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& o return NvResult::Success; } -NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; @@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8> return NvResult::Success; } -NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; @@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8> return NvResult::Success; } -NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) { std::memcpy(&zcull_params, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, zcull_params.mode); @@ -158,7 +158,7 @@ NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& ou return NvResult::Success; } -NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) { IoctlSetErrorNotifier params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, @@ -168,14 +168,14 @@ NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) { std::memcpy(&channel_priority, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); return NvResult::Success; } -NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) { IoctlAllocGpfifoEx2 params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, @@ -197,7 +197,7 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8 return NvResult::Success; } -NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) { IoctlAllocObjCtx params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, @@ -208,7 +208,8 @@ NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::ve return NvResult::Success; } -static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) { +static boost::container::small_vector<Tegra::CommandHeader, 512> BuildWaitCommandList( + NvFence fence) { return { Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1, Tegra::SubmissionMode::Increasing), @@ -219,35 +220,35 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) { }; } -static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence) { - std::vector<Tegra::CommandHeader> result{ +static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementCommandList( + NvFence fence) { + boost::container::small_vector<Tegra::CommandHeader, 512> result{ Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1, Tegra::SubmissionMode::Increasing), {}}; for (u32 count = 0; count < 2; ++count) { - result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1, - Tegra::SubmissionMode::Increasing)); - result.emplace_back( + result.push_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1, + Tegra::SubmissionMode::Increasing)); + result.push_back( BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Increment, fence.id)); } return result; } -static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence) { - std::vector<Tegra::CommandHeader> result{ +static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementWithWfiCommandList( + NvFence fence) { + boost::container::small_vector<Tegra::CommandHeader, 512> result{ Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForIdle, 1, Tegra::SubmissionMode::Increasing), {}}; - const std::vector<Tegra::CommandHeader> increment{BuildIncrementCommandList(fence)}; - - result.insert(result.end(), increment.begin(), increment.end()); - + auto increment_list{BuildIncrementCommandList(fence)}; + result.insert(result.end(), increment_list.begin(), increment_list.end()); return result; } -NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, +NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, Tegra::CommandList&& entries) { LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, params.num_entries, params.flags.raw); @@ -293,7 +294,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8> return NvResult::Success; } -NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, bool kickoff) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); @@ -304,8 +305,8 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector< Tegra::CommandList entries(params.num_entries); if (kickoff) { - system.Memory().ReadBlock(params.address, entries.command_lists.data(), - params.num_entries * sizeof(Tegra::CommandListHeader)); + system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), + params.num_entries * sizeof(Tegra::CommandListHeader)); } else { std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], params.num_entries * sizeof(Tegra::CommandListHeader)); @@ -314,9 +315,8 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector< return SubmitGPFIFOImpl(params, output, std::move(entries)); } -NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, - const std::vector<u8>& input_inline, - std::vector<u8>& output) { +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, + std::span<u8> output) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); return NvResult::InvalidSize; @@ -328,7 +328,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, return SubmitGPFIFOImpl(params, output, std::move(entries)); } -NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) { IoctlGetWaitbase params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); @@ -338,7 +338,7 @@ NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) { IoctlChannelSetTimeout params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); @@ -346,7 +346,7 @@ NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector return NvResult::Success; } -NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) { IoctlSetTimeslice params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 1e4ecd55b..529c20526 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -40,12 +40,12 @@ public: NvCore::Container& core); ~nvhost_gpu() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -186,23 +186,23 @@ private: u32_le channel_priority{}; u32_le channel_timeslice{}; - NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetClientData(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetClientData(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); - NvResult AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); - NvResult AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, + NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); + NvResult SetClientData(std::span<const u8> input, std::span<u8> output); + NvResult GetClientData(std::span<const u8> input, std::span<u8> output); + NvResult ZCullBind(std::span<const u8> input, std::span<u8> output); + NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output); + NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output); + NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output); + NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output); + NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, Tegra::CommandList&& entries); - NvResult SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, + NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, bool kickoff = false); - NvResult SubmitGPFIFOBase(const std::vector<u8>& input, const std::vector<u8>& input_inline, - std::vector<u8>& output); - NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, + std::span<u8> output); + NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); + NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output); + NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output); EventInterface& events_interface; NvCore::Container& core; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 1703f9cc3..a174442a6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -15,8 +15,8 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core_) : nvhost_nvdec_common{system_, core_, NvCore::ChannelType::NvDec} {} nvhost_nvdec::~nvhost_nvdec() = default; -NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 0x0: switch (command.cmd) { @@ -55,21 +55,21 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& return NvResult::NotImplemented; } -NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } void nvhost_nvdec::OnOpen(DeviceFD fd) { LOG_INFO(Service_NVDRV, "NVDEC video stream started"); - system.AudioCore().SetNVDECActive(true); + system.SetNVDECActive(true); } void nvhost_nvdec::OnClose(DeviceFD fd) { @@ -79,7 +79,7 @@ void nvhost_nvdec::OnClose(DeviceFD fd) { if (iter != host1x_file.fd_to_id.end()) { system.GPU().ClearCdmaInstance(iter->second); } - system.AudioCore().SetNVDECActive(false); + system.SetNVDECActive(false); } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index c1b4e53e8..ad2233c49 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -13,12 +13,12 @@ public: explicit nvhost_nvdec(Core::System& system_, NvCore::Container& core); ~nvhost_nvdec() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 99eede702..61649aa4a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -23,7 +23,7 @@ namespace { // Copies count amount of type T from the input vector into the dst vector. // Returns the number of bytes written into dst. template <typename T> -std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, +std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::size_t count, std::size_t offset) { if (dst.empty()) { return 0; @@ -36,7 +36,7 @@ std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std: // Writes the data in src to an offset into the dst vector. The offset is specified in bytes // Returns the number of bytes written into dst. template <typename T> -std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { +std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size_t offset) { if (src.empty()) { return 0; } @@ -63,7 +63,7 @@ nvhost_nvdec_common::~nvhost_nvdec_common() { core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); } -NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { +NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); @@ -72,8 +72,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { return NvResult::Success; } -NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) { IoctlSubmit params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); @@ -105,8 +104,8 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, const auto object = nvmap.GetHandle(cmd_buffer.memory_id); ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); - system.Memory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), - cmdlist.size() * sizeof(u32)); + system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), + cmdlist.size() * sizeof(u32)); gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); } std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); @@ -121,7 +120,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, return NvResult::Success; } -NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) { IoctlGetSyncpoint params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); @@ -133,7 +132,7 @@ NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::ve return NvResult::Success; } -NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) { IoctlGetWaitbase params{}; LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); @@ -142,7 +141,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vec return NvResult::Success; } -NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -159,7 +158,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto return NvResult::Success; } -NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -173,8 +172,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec return NvResult::Success; } -NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) { std::memcpy(&submit_timeout, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called"); return NvResult::Success; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index fe76100c8..9bb573bfe 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -107,13 +107,13 @@ protected: static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); /// Ioctl command implementations - NvResult SetNVMAPfd(const std::vector<u8>& input); - NvResult Submit(DeviceFD fd, const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); - NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(std::span<const u8> input); + NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output); + NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output); + NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); + NvResult MapBuffer(std::span<const u8> input, std::span<u8> output); + NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); + NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output); Kernel::KEvent* QueryEvent(u32 event_id) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index bdbc2f9e1..a05c8cdae 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -12,8 +12,8 @@ namespace Service::Nvidia::Devices { nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {} nvhost_nvjpg::~nvhost_nvjpg() = default; -NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 'H': switch (command.cmd) { @@ -31,14 +31,14 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& return NvResult::NotImplemented; } -NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } @@ -46,7 +46,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& void nvhost_nvjpg::OnOpen(DeviceFD fd) {} void nvhost_nvjpg::OnClose(DeviceFD fd) {} -NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 440e7d371..5623e0d47 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -15,12 +15,12 @@ public: explicit nvhost_nvjpg(Core::System& system_); ~nvhost_nvjpg() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -33,7 +33,7 @@ private: s32_le nvmap_fd{}; - NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 73f97136e..c0b8684c3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -15,8 +15,8 @@ nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core_) nvhost_vic::~nvhost_vic() = default; -NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 0x0: switch (command.cmd) { @@ -55,14 +55,14 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i return NvResult::NotImplemented; } -NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output, std::span<u8> inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index f164caafb..cadbcb0a5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -12,12 +12,12 @@ public: explicit nvhost_vic(Core::System& system_, NvCore::Container& core); ~nvhost_vic(); - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index fa29db758..e7f7e273b 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -25,8 +25,8 @@ nvmap::nvmap(Core::System& system_, NvCore::Container& container_) nvmap::~nvmap() = default; -NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { switch (command.group) { case 0x1: switch (command.cmd) { @@ -54,14 +54,14 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, return NvResult::NotImplemented; } -NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } @@ -69,7 +69,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, void nvmap::OnOpen(DeviceFD fd) {} void nvmap::OnClose(DeviceFD fd) {} -NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) { IocCreateParams params; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); @@ -89,7 +89,7 @@ NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { IocAllocParams params; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); @@ -127,7 +127,7 @@ NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) return result; } bool is_out_io{}; - ASSERT(system.CurrentProcess() + ASSERT(system.ApplicationProcess() ->PageTable() .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address, handle_description->size, @@ -137,7 +137,7 @@ NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) return result; } -NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) { IocGetIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) { IocFromIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) { enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; IocParamParams params; @@ -241,7 +241,7 @@ NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { IocFreeParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -254,7 +254,7 @@ NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { if (auto freeInfo{file.FreeHandle(params.handle, false)}) { if (freeInfo->can_unlock) { - ASSERT(system.CurrentProcess() + ASSERT(system.ApplicationProcess() ->PageTable() .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) .IsSuccess()); @@ -264,7 +264,7 @@ NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { params.flags.raw = 0; params.flags.map_uncached.Assign(freeInfo->was_uncached); } else { - // This is possible when there's internel dups or other duplicates. + // This is possible when there's internal dups or other duplicates. } std::memcpy(output.data(), ¶ms, sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index e9bfd0358..40c65b430 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -26,12 +26,12 @@ public: nvmap(const nvmap&) = delete; nvmap& operator=(const nvmap&) = delete; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -106,12 +106,12 @@ private: }; static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); - NvResult IocCreate(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocGetId(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocFromId(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocParam(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocFree(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCreate(std::span<const u8> input, std::span<u8> output); + NvResult IocAlloc(std::span<const u8> input, std::span<u8> output); + NvResult IocGetId(std::span<const u8> input, std::span<u8> output); + NvResult IocFromId(std::span<const u8> input, std::span<u8> output); + NvResult IocParam(std::span<const u8> input, std::span<u8> output); + NvResult IocFree(std::span<const u8> input, std::span<u8> output); NvCore::Container& container; NvCore::NvMap& file; diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 6fc8565c0..9e46ee8dd 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -6,8 +6,8 @@ #include <fmt/format.h> #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" @@ -23,7 +23,8 @@ #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvdrv/nvdrv_interface.h" #include "core/hle/service/nvdrv/nvmemp.h" -#include "core/hle/service/nvflinger/nvflinger.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/server_manager.h" #include "video_core/gpu.h" namespace Service::Nvidia { @@ -41,15 +42,19 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) { module.service_context.CloseEvent(event); } -void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, - Core::System& system) { - auto module_ = std::make_shared<Module>(system); - std::make_shared<NVDRV>(system, module_, "nvdrv")->InstallAsService(service_manager); - std::make_shared<NVDRV>(system, module_, "nvdrv:a")->InstallAsService(service_manager); - std::make_shared<NVDRV>(system, module_, "nvdrv:s")->InstallAsService(service_manager); - std::make_shared<NVDRV>(system, module_, "nvdrv:t")->InstallAsService(service_manager); - std::make_shared<NVMEMP>(system)->InstallAsService(service_manager); - nvflinger.SetNVDrvInstance(module_); +void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + auto module = std::make_shared<Module>(system); + server_manager->RegisterNamedService("nvdrv", std::make_shared<NVDRV>(system, module, "nvdrv")); + server_manager->RegisterNamedService("nvdrv:a", + std::make_shared<NVDRV>(system, module, "nvdrv:a")); + server_manager->RegisterNamedService("nvdrv:s", + std::make_shared<NVDRV>(system, module, "nvdrv:s")); + server_manager->RegisterNamedService("nvdrv:t", + std::make_shared<NVDRV>(system, module, "nvdrv:t")); + server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); + nvnflinger.SetNVDrvInstance(module); + ServerManager::RunServer(std::move(server_manager)); } Module::Module(Core::System& system) @@ -124,8 +129,8 @@ DeviceFD Module::Open(const std::string& device_name) { return fd; } -NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<u8> output) { if (fd < 0) { LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); return NvResult::InvalidState; @@ -141,8 +146,8 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input return itr->second->Ioctl1(fd, command, input, output); } -NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output) { if (fd < 0) { LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); return NvResult::InvalidState; @@ -158,8 +163,8 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input return itr->second->Ioctl2(fd, command, input, inline_input, output); } -NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output) { if (fd < 0) { LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); return NvResult::InvalidState; diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index f3c81bd88..d8622b3ca 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -7,6 +7,7 @@ #include <functional> #include <list> #include <memory> +#include <span> #include <string> #include <unordered_map> #include <vector> @@ -15,7 +16,7 @@ #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvflinger/ui/fence.h" +#include "core/hle/service/nvnflinger/ui/fence.h" #include "core/hle/service/service.h" namespace Core { @@ -26,8 +27,8 @@ namespace Kernel { class KEvent; } -namespace Service::NVFlinger { -class NVFlinger; +namespace Service::Nvnflinger { +class Nvnflinger; } namespace Service::Nvidia { @@ -79,14 +80,13 @@ public: DeviceFD Open(const std::string& device_name); /// Sends an ioctl command to the specified file descriptor. - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output); + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output); - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output); + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::span<u8> output); - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output); + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, + std::span<u8> inline_output); /// Closes a device file descriptor and returns operation success. NvResult Close(DeviceFD fd); @@ -95,7 +95,7 @@ public: private: friend class EventInterface; - friend class Service::NVFlinger::NVFlinger; + friend class Service::Nvnflinger::Nvnflinger; /// Manages syncpoints on the host NvCore::Container container; @@ -114,8 +114,6 @@ private: std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders; }; -/// Registers all NVDRV services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, - Core::System& system); +void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index edbdfee43..348207e25 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -5,16 +5,16 @@ #include <cinttypes> #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvdrv/nvdrv_interface.h" namespace Service::Nvidia { -void NVDRV::Open(Kernel::HLERequestContext& ctx) { +void NVDRV::Open(HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -44,13 +44,13 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) { rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); } -void NVDRV::ServiceError(Kernel::HLERequestContext& ctx, NvResult result) { +void NVDRV::ServiceError(HLERequestContext& ctx, NvResult result) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.PushEnum(result); } -void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) { +void NVDRV::Ioctl1(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto fd = rp.Pop<DeviceFD>(); const auto command = rp.PopRaw<Ioctl>(); @@ -63,12 +63,12 @@ void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) { } // Check device - std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); + tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); const auto input_buffer = ctx.ReadBuffer(0); - const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer); + const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output); if (command.is_out != 0) { - ctx.WriteBuffer(output_buffer); + ctx.WriteBuffer(tmp_output); } IPC::ResponseBuilder rb{ctx, 3}; @@ -76,7 +76,7 @@ void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) { rb.PushEnum(nv_result); } -void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { +void NVDRV::Ioctl2(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto fd = rp.Pop<DeviceFD>(); const auto command = rp.PopRaw<Ioctl>(); @@ -90,12 +90,12 @@ void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { const auto input_buffer = ctx.ReadBuffer(0); const auto input_inlined_buffer = ctx.ReadBuffer(1); - std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); + tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); const auto nv_result = - nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer); + nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, tmp_output); if (command.is_out != 0) { - ctx.WriteBuffer(output_buffer); + ctx.WriteBuffer(tmp_output); } IPC::ResponseBuilder rb{ctx, 3}; @@ -103,7 +103,7 @@ void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { rb.PushEnum(nv_result); } -void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { +void NVDRV::Ioctl3(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto fd = rp.Pop<DeviceFD>(); const auto command = rp.PopRaw<Ioctl>(); @@ -116,14 +116,12 @@ void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { } const auto input_buffer = ctx.ReadBuffer(0); - std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); - std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1)); - - const auto nv_result = - nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline); + tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); + tmp_output_inline.resize_destructive(ctx.GetWriteBufferSize(1)); + const auto nv_result = nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output_inline); if (command.is_out != 0) { - ctx.WriteBuffer(output_buffer, 0); - ctx.WriteBuffer(output_buffer_inline, 1); + ctx.WriteBuffer(tmp_output, 0); + ctx.WriteBuffer(tmp_output_inline, 1); } IPC::ResponseBuilder rb{ctx, 3}; @@ -131,7 +129,7 @@ void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { rb.PushEnum(nv_result); } -void NVDRV::Close(Kernel::HLERequestContext& ctx) { +void NVDRV::Close(HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); if (!is_initialized) { @@ -149,7 +147,7 @@ void NVDRV::Close(Kernel::HLERequestContext& ctx) { rb.PushEnum(result); } -void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { +void NVDRV::Initialize(HLERequestContext& ctx) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); is_initialized = true; @@ -159,7 +157,7 @@ void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { rb.PushEnum(NvResult::Success); } -void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { +void NVDRV::QueryEvent(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto fd = rp.Pop<DeviceFD>(); const auto event_id = rp.Pop<u32>(); @@ -187,7 +185,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { } } -void NVDRV::SetAruid(Kernel::HLERequestContext& ctx) { +void NVDRV::SetAruid(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; pid = rp.Pop<u64>(); LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid=0x{:X}", pid); @@ -197,14 +195,14 @@ void NVDRV::SetAruid(Kernel::HLERequestContext& ctx) { rb.PushEnum(NvResult::Success); } -void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx) { +void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) { +void NVDRV::GetStatus(HLERequestContext& ctx) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -212,7 +210,7 @@ void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) { rb.PushEnum(NvResult::Success); } -void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { +void NVDRV::DumpGraphicsMemoryInfo(HLERequestContext& ctx) { // According to SwitchBrew, this has no inputs and no outputs, so effectively does nothing on // retail hardware. LOG_DEBUG(Service_NVDRV, "called"); @@ -222,7 +220,7 @@ void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { } NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name) - : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, nvdrv{std::move(nvdrv_)} { + : ServiceFramework{system_, name}, nvdrv{std::move(nvdrv_)} { static const FunctionInfo functions[] = { {0, &NVDRV::Open, "Open"}, {1, &NVDRV::Ioctl1, "Ioctl"}, diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index 5ac06ee30..4b593ff90 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h @@ -4,6 +4,7 @@ #pragma once #include <memory> +#include "common/scratch_buffer.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/service.h" @@ -15,24 +16,26 @@ public: ~NVDRV() override; private: - void Open(Kernel::HLERequestContext& ctx); - void Ioctl1(Kernel::HLERequestContext& ctx); - void Ioctl2(Kernel::HLERequestContext& ctx); - void Ioctl3(Kernel::HLERequestContext& ctx); - void Close(Kernel::HLERequestContext& ctx); - void Initialize(Kernel::HLERequestContext& ctx); - void QueryEvent(Kernel::HLERequestContext& ctx); - void SetAruid(Kernel::HLERequestContext& ctx); - void SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx); - void GetStatus(Kernel::HLERequestContext& ctx); - void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx); - - void ServiceError(Kernel::HLERequestContext& ctx, NvResult result); + void Open(HLERequestContext& ctx); + void Ioctl1(HLERequestContext& ctx); + void Ioctl2(HLERequestContext& ctx); + void Ioctl3(HLERequestContext& ctx); + void Close(HLERequestContext& ctx); + void Initialize(HLERequestContext& ctx); + void QueryEvent(HLERequestContext& ctx); + void SetAruid(HLERequestContext& ctx); + void SetGraphicsFirmwareMemoryMarginEnabled(HLERequestContext& ctx); + void GetStatus(HLERequestContext& ctx); + void DumpGraphicsMemoryInfo(HLERequestContext& ctx); + + void ServiceError(HLERequestContext& ctx, NvResult result); std::shared_ptr<Module> nvdrv; u64 pid{}; bool is_initialized{}; + Common::ScratchBuffer<u8> tmp_output; + Common::ScratchBuffer<u8> tmp_output_inline; }; } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp index e433580b1..fc10f6406 100644 --- a/src/core/hle/service/nvdrv/nvmemp.cpp +++ b/src/core/hle/service/nvdrv/nvmemp.cpp @@ -17,11 +17,11 @@ NVMEMP::NVMEMP(Core::System& system_) : ServiceFramework{system_, "nvmemp"} { NVMEMP::~NVMEMP() = default; -void NVMEMP::Open(Kernel::HLERequestContext& ctx) { +void NVMEMP::Open(HLERequestContext& ctx) { UNIMPLEMENTED(); } -void NVMEMP::GetAruid(Kernel::HLERequestContext& ctx) { +void NVMEMP::GetAruid(HLERequestContext& ctx) { UNIMPLEMENTED(); } diff --git a/src/core/hle/service/nvdrv/nvmemp.h b/src/core/hle/service/nvdrv/nvmemp.h index 3d4276327..85e3053a8 100644 --- a/src/core/hle/service/nvdrv/nvmemp.h +++ b/src/core/hle/service/nvdrv/nvmemp.h @@ -17,8 +17,8 @@ public: ~NVMEMP() override; private: - void Open(Kernel::HLERequestContext& ctx); - void GetAruid(Kernel::HLERequestContext& ctx); + void Open(HLERequestContext& ctx); + void GetAruid(HLERequestContext& ctx); }; } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvflinger/parcel.h b/src/core/hle/service/nvflinger/parcel.h deleted file mode 100644 index f3fa2587d..000000000 --- a/src/core/hle/service/nvflinger/parcel.h +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <memory> -#include <vector> - -#include "common/alignment.h" -#include "common/assert.h" -#include "common/common_types.h" - -namespace Service::android { - -class Parcel final { -public: - static constexpr std::size_t DefaultBufferSize = 0x40; - - Parcel() : buffer(DefaultBufferSize) {} - - template <typename T> - explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) { - Write(out_data); - } - - explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) { - DeserializeHeader(); - [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); - } - - template <typename T> - void Read(T& val) { - static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); - ASSERT(read_index + sizeof(T) <= buffer.size()); - - std::memcpy(&val, buffer.data() + read_index, sizeof(T)); - read_index += sizeof(T); - read_index = Common::AlignUp(read_index, 4); - } - - template <typename T> - T Read() { - T val; - Read(val); - return val; - } - - template <typename T> - void ReadFlattened(T& val) { - const auto flattened_size = Read<s64>(); - ASSERT(sizeof(T) == flattened_size); - Read(val); - } - - template <typename T> - T ReadFlattened() { - T val; - ReadFlattened(val); - return val; - } - - template <typename T> - T ReadUnaligned() { - static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); - ASSERT(read_index + sizeof(T) <= buffer.size()); - - T val; - std::memcpy(&val, buffer.data() + read_index, sizeof(T)); - read_index += sizeof(T); - return val; - } - - template <typename T> - const std::shared_ptr<T> ReadObject() { - static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); - - const auto is_valid{Read<bool>()}; - - if (is_valid) { - auto result = std::make_shared<T>(); - ReadFlattened(*result); - return result; - } - - return {}; - } - - std::u16string ReadInterfaceToken() { - [[maybe_unused]] const u32 unknown = Read<u32>(); - const u32 length = Read<u32>(); - - std::u16string token; - token.reserve(length + 1); - - for (u32 ch = 0; ch < length + 1; ++ch) { - token.push_back(ReadUnaligned<u16>()); - } - - read_index = Common::AlignUp(read_index, 4); - - return token; - } - - template <typename T> - void Write(const T& val) { - static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); - - if (buffer.size() < write_index + sizeof(T)) { - buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize); - } - - std::memcpy(buffer.data() + write_index, &val, sizeof(T)); - write_index += sizeof(T); - write_index = Common::AlignUp(write_index, 4); - } - - template <typename T> - void WriteObject(const T* ptr) { - static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); - - if (!ptr) { - Write<u32>(0); - return; - } - - Write<u32>(1); - Write<s64>(sizeof(T)); - Write(*ptr); - } - - template <typename T> - void WriteObject(const std::shared_ptr<T> ptr) { - WriteObject(ptr.get()); - } - - void DeserializeHeader() { - ASSERT(buffer.size() > sizeof(Header)); - - Header header{}; - std::memcpy(&header, buffer.data(), sizeof(Header)); - - read_index = header.data_offset; - } - - std::vector<u8> Serialize() const { - ASSERT(read_index == 0); - - Header header{}; - header.data_size = static_cast<u32>(write_index - sizeof(Header)); - header.data_offset = sizeof(Header); - header.objects_size = 4; - header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size); - std::memcpy(buffer.data(), &header, sizeof(Header)); - - return buffer; - } - -private: - struct Header { - u32 data_size; - u32 data_offset; - u32 objects_size; - u32 objects_offset; - }; - static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size"); - - mutable std::vector<u8> buffer; - std::size_t read_index = 0; - std::size_t write_index = sizeof(Header); -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h index 157333ff8..aef1477e3 100644 --- a/src/core/hle/service/nvflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h @@ -9,10 +9,13 @@ #include "common/common_types.h" namespace Kernel { -class HLERequestContext; class KReadableEvent; } // namespace Kernel +namespace Service { +class HLERequestContext; +} + namespace Service::android { enum class TransactionId { @@ -35,8 +38,7 @@ enum class TransactionId { class IBinder { public: virtual ~IBinder() = default; - virtual void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, - u32 flags) = 0; + virtual void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 0; virtual Kernel::KReadableEvent& GetNativeHandle() = 0; }; diff --git a/src/core/hle/service/nvflinger/buffer_item.h b/src/core/hle/service/nvnflinger/buffer_item.h index f73dec4f1..7fd808f54 100644 --- a/src/core/hle/service/nvflinger/buffer_item.h +++ b/src/core/hle/service/nvnflinger/buffer_item.h @@ -10,8 +10,8 @@ #include "common/common_types.h" #include "common/math_util.h" -#include "core/hle/service/nvflinger/ui/fence.h" -#include "core/hle/service/nvflinger/window.h" +#include "core/hle/service/nvnflinger/ui/fence.h" +#include "core/hle/service/nvnflinger/window.h" namespace Service::android { diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp index 152bb5bdf..cf151ea3a 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp @@ -6,9 +6,9 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_item_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" +#include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/buffer_item_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" namespace Service::android { @@ -25,7 +25,7 @@ Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseco if (const auto status = AcquireBufferLocked(item, present_when); status != Status::NoError) { if (status != Status::NoBufferAvailable) { - LOG_ERROR(Service_NVFlinger, "Failed to acquire buffer: {}", status); + LOG_ERROR(Service_Nvnflinger, "Failed to acquire buffer: {}", status); } return status; } @@ -44,12 +44,12 @@ Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, const Fence& re if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence); status != Status::NoError) { - LOG_ERROR(Service_NVFlinger, "Failed to add fence: {}", status); + LOG_ERROR(Service_Nvnflinger, "Failed to add fence: {}", status); } if (const auto status = ReleaseBufferLocked(item.buf, item.graphic_buffer); status != Status::NoError) { - LOG_WARNING(Service_NVFlinger, "Failed to release buffer: {}", status); + LOG_WARNING(Service_Nvnflinger, "Failed to release buffer: {}", status); return status; } diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.h b/src/core/hle/service/nvnflinger/buffer_item_consumer.h index a5c655d9e..e0c6b3604 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.h @@ -10,8 +10,8 @@ #include <memory> #include "common/common_types.h" -#include "core/hle/service/nvflinger/consumer_base.h" -#include "core/hle/service/nvflinger/status.h" +#include "core/hle/service/nvnflinger/consumer_base.h" +#include "core/hle/service/nvnflinger/status.h" namespace Service::android { diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index 0767e548d..51291539d 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -6,11 +6,11 @@ #include "common/logging/log.h" #include "core/hle/service/nvdrv/core/nvmap.h" -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/producer_listener.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" +#include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/producer_listener.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" namespace Service::android { @@ -31,7 +31,7 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, }))}; if (num_acquired_buffers >= core->max_acquired_buffer_count + 1) { - LOG_ERROR(Service_NVFlinger, "max acquired buffer count reached: {} (max {})", + LOG_ERROR(Service_Nvnflinger, "max acquired buffer count reached: {} (max {})", num_acquired_buffers, core->max_acquired_buffer_count); return Status::InvalidOperation; } @@ -57,12 +57,12 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, if (desired_present < expected_present.count() - MAX_REASONABLE_NSEC || desired_present > expected_present.count()) { // This buffer is set to display in the near future, or desired_present is garbage. - LOG_DEBUG(Service_NVFlinger, "nodrop desire={} expect={}", desired_present, + LOG_DEBUG(Service_Nvnflinger, "nodrop desire={} expect={}", desired_present, expected_present.count()); break; } - LOG_DEBUG(Service_NVFlinger, "drop desire={} expect={} size={}", desired_present, + LOG_DEBUG(Service_Nvnflinger, "drop desire={} expect={} size={}", desired_present, expected_present.count(), core->queue.size()); if (core->StillTracking(*front)) { @@ -78,19 +78,19 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, const auto desired_present = front->timestamp; if (desired_present > expected_present.count() && desired_present < expected_present.count() + MAX_REASONABLE_NSEC) { - LOG_DEBUG(Service_NVFlinger, "defer desire={} expect={}", desired_present, + LOG_DEBUG(Service_Nvnflinger, "defer desire={} expect={}", desired_present, expected_present.count()); return Status::PresentLater; } - LOG_DEBUG(Service_NVFlinger, "accept desire={} expect={}", desired_present, + LOG_DEBUG(Service_Nvnflinger, "accept desire={} expect={}", desired_present, expected_present.count()); } const auto slot = front->slot; *out_buffer = *front; - LOG_DEBUG(Service_NVFlinger, "acquiring slot={}", slot); + LOG_DEBUG(Service_Nvnflinger, "acquiring slot={}", slot); // If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to // avoid unnecessarily remapping this buffer on the consumer side. @@ -109,7 +109,7 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence) { if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot {} out of range", slot); + LOG_ERROR(Service_Nvnflinger, "slot {} out of range", slot); return Status::BadValue; } @@ -127,7 +127,7 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc auto current(core->queue.begin()); while (current != core->queue.end()) { if (current->slot == slot) { - LOG_ERROR(Service_NVFlinger, "buffer slot {} pending release is currently queued", + LOG_ERROR(Service_Nvnflinger, "buffer slot {} pending release is currently queued", slot); return Status::BadValue; } @@ -140,7 +140,7 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc listener = core->connected_producer_listener; - LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot); + LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); core->SignalDequeueCondition(); } @@ -156,16 +156,16 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app) { if (consumer_listener == nullptr) { - LOG_ERROR(Service_NVFlinger, "consumer_listener may not be nullptr"); + LOG_ERROR(Service_Nvnflinger, "consumer_listener may not be nullptr"); return Status::BadValue; } - LOG_DEBUG(Service_NVFlinger, "controlled_by_app={}", controlled_by_app); + LOG_DEBUG(Service_Nvnflinger, "controlled_by_app={}", controlled_by_app); std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } @@ -177,14 +177,14 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { if (out_slot_mask == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_slot_mask may not be nullptr"); + LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr"); return Status::BadValue; } std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } @@ -205,7 +205,7 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { ++current; } - LOG_DEBUG(Service_NVFlinger, "returning mask {}", mask); + LOG_DEBUG(Service_Nvnflinger, "returning mask {}", mask); *out_slot_mask = mask; return Status::NoError; } diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h index 4ec06ca13..50ed0bb5f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h @@ -10,8 +10,8 @@ #include <memory> #include "common/common_types.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/status.h" +#include "core/hle/service/nvnflinger/buffer_queue_defs.h" +#include "core/hle/service/nvnflinger/status.h" namespace Service::Nvidia::NvCore { class NvMap; diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp index 3d1338e66..2dbe29616 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp @@ -6,7 +6,7 @@ #include "common/assert.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" namespace Service::android { @@ -82,7 +82,7 @@ s32 BufferQueueCore::GetPreallocatedBufferCountLocked() const { } void BufferQueueCore::FreeBufferLocked(s32 slot) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); slots[slot].graphic_buffer.reset(); diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h index 85b3bc4c1..9164f08a0 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h @@ -13,11 +13,11 @@ #include <set> #include <vector> -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/pixel_format.h" -#include "core/hle/service/nvflinger/status.h" -#include "core/hle/service/nvflinger/window.h" +#include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/buffer_queue_defs.h" +#include "core/hle/service/nvnflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/status.h" +#include "core/hle/service/nvnflinger/window.h" namespace Service::android { diff --git a/src/core/hle/service/nvflinger/buffer_queue_defs.h b/src/core/hle/service/nvnflinger/buffer_queue_defs.h index 334445213..6fd3156f4 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_defs.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_defs.h @@ -9,7 +9,7 @@ #include <array> #include "common/common_types.h" -#include "core/hle/service/nvflinger/buffer_slot.h" +#include "core/hle/service/nvnflinger/buffer_slot.h" namespace Service::android::BufferQueueDefs { diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index e601b5da1..b16f9933f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -8,18 +8,18 @@ #include "common/logging/log.h" #include "common/settings.h" #include "core/core.h" -#include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/service/hle_ipc.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvdrv/core/nvmap.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/buffer_queue_producer.h" -#include "core/hle/service/nvflinger/consumer_listener.h" -#include "core/hle/service/nvflinger/parcel.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" -#include "core/hle/service/nvflinger/window.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/consumer_listener.h" +#include "core/hle/service/nvnflinger/parcel.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" +#include "core/hle/service/nvnflinger/window.h" #include "core/hle/service/vi/vi.h" namespace Service::android { @@ -37,20 +37,20 @@ BufferQueueProducer::~BufferQueueProducer() { } Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot index {} out of range [0, {})", slot, BufferQueueDefs::NUM_BUFFER_SLOTS); return Status::BadValue; } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot {} is not owned by the producer (state = {})", slot, slots[slot].buffer_state); return Status::BadValue; } @@ -62,7 +62,7 @@ Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffe } Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { - LOG_DEBUG(Service_NVFlinger, "count = {}", buffer_count); + LOG_DEBUG(Service_Nvnflinger, "count = {}", buffer_count); std::shared_ptr<IConsumerListener> listener; { @@ -70,12 +70,12 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { core->WaitWhileAllocatingLocked(); if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } if (buffer_count > BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "buffer_count {} too large (max {})", buffer_count, + LOG_ERROR(Service_Nvnflinger, "buffer_count {} too large (max {})", buffer_count, BufferQueueDefs::NUM_BUFFER_SLOTS); return Status::BadValue; } @@ -83,7 +83,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { // There must be no dequeued buffers when changing the buffer count. for (s32 s{}; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { if (slots[s].buffer_state == BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "buffer owned by producer"); + LOG_ERROR(Service_Nvnflinger, "buffer owned by producer"); return Status::BadValue; } } @@ -96,7 +96,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { const s32 min_buffer_slots = core->GetMinMaxBufferCountLocked(false); if (buffer_count < min_buffer_slots) { - LOG_ERROR(Service_NVFlinger, "requested buffer count {} is less than minimum {}", + LOG_ERROR(Service_Nvnflinger, "requested buffer count {} is less than minimum {}", buffer_count, min_buffer_slots); return Status::BadValue; } @@ -127,14 +127,14 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St while (try_again) { if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } const s32 max_buffer_count = core->GetMaxBufferCountLocked(async); if (async && core->override_max_buffer_count) { if (core->override_max_buffer_count < max_buffer_count) { - LOG_ERROR(Service_NVFlinger, "async mode is invalid with buffer count override"); + LOG_ERROR(Service_Nvnflinger, "async mode is invalid with buffer count override"); return Status::BadValue; } } @@ -176,7 +176,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St // Producers are not allowed to dequeue more than one buffer if they did not set a buffer // count if (!core->override_max_buffer_count && dequeued_count) { - LOG_ERROR(Service_NVFlinger, + LOG_ERROR(Service_Nvnflinger, "can't dequeue multiple buffers without setting the buffer count"); return Status::InvalidOperation; } @@ -188,7 +188,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St const s32 new_undequeued_count = max_buffer_count - (dequeued_count + 1); const s32 min_undequeued_count = core->GetMinUndequeuedBufferCountLocked(async); if (new_undequeued_count < min_undequeued_count) { - LOG_ERROR(Service_NVFlinger, + LOG_ERROR(Service_Nvnflinger, "min undequeued buffer count({}) exceeded (dequeued={} undequeued={})", min_undequeued_count, dequeued_count, new_undequeued_count); return Status::InvalidOperation; @@ -200,7 +200,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St // outrun the consumer. Wait here if it looks like we have too many buffers queued up. const bool too_many_buffers = core->queue.size() > static_cast<size_t>(max_buffer_count); if (too_many_buffers) { - LOG_ERROR(Service_NVFlinger, "queue size is {}, waiting", core->queue.size()); + LOG_ERROR(Service_Nvnflinger, "queue size is {}, waiting", core->queue.size()); } // If no buffer is found, or if the queue has too many buffers outstanding, wait for a @@ -226,11 +226,11 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool async, u32 width, u32 height, PixelFormat format, u32 usage) { - LOG_DEBUG(Service_NVFlinger, "async={} w={} h={} format={}, usage={}", async ? "true" : "false", - width, height, format, usage); + LOG_DEBUG(Service_Nvnflinger, "async={} w={} h={} format={}, usage={}", + async ? "true" : "false", width, height, format, usage); if ((width != 0 && height == 0) || (width == 0 && height != 0)) { - LOG_ERROR(Service_NVFlinger, "invalid size: w={} h={}", width, height); + LOG_ERROR(Service_Nvnflinger, "invalid size: w={} h={}", width, height); return Status::BadValue; } @@ -255,7 +255,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool // This should not happen if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { - LOG_ERROR(Service_NVFlinger, "no available buffer slots"); + LOG_ERROR(Service_Nvnflinger, "no available buffer slots"); return Status::Busy; } @@ -287,11 +287,11 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool } if ((return_flags & Status::BufferNeedsReallocation) != Status::None) { - LOG_DEBUG(Service_NVFlinger, "allocating a new buffer for slot {}", *out_slot); + LOG_DEBUG(Service_Nvnflinger, "allocating a new buffer for slot {}", *out_slot); auto graphic_buffer = std::make_shared<GraphicBuffer>(width, height, format, usage); if (graphic_buffer == nullptr) { - LOG_ERROR(Service_NVFlinger, "creating GraphicBuffer failed"); + LOG_ERROR(Service_Nvnflinger, "creating GraphicBuffer failed"); return Status::NoMemory; } @@ -299,7 +299,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } @@ -312,32 +312,32 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool return_flags |= Status::BufferNeedsReallocation; } - LOG_DEBUG(Service_NVFlinger, "returning slot={} frame={}, flags={}", *out_slot, + LOG_DEBUG(Service_Nvnflinger, "returning slot={} frame={}, flags={}", *out_slot, slots[*out_slot].frame_number, return_flags); return return_flags; } Status BufferQueueProducer::DetachBuffer(s32 slot) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot {} out of range [0, {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot {} out of range [0, {})", slot, BufferQueueDefs::NUM_BUFFER_SLOTS); return Status::BadValue; } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot {} is not owned by the producer (state = {})", slot, slots[slot].buffer_state); return Status::BadValue; } else if (!slots[slot].request_buffer_called) { - LOG_ERROR(Service_NVFlinger, "buffer in slot {} has not been requested", slot); + LOG_ERROR(Service_Nvnflinger, "buffer in slot {} has not been requested", slot); return Status::BadValue; } @@ -350,10 +350,10 @@ Status BufferQueueProducer::DetachBuffer(s32 slot) { Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out_buffer, Fence* out_fence) { if (out_buffer == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_buffer must not be nullptr"); + LOG_ERROR(Service_Nvnflinger, "out_buffer must not be nullptr"); return Status::BadValue; } else if (out_fence == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_fence must not be nullptr"); + LOG_ERROR(Service_Nvnflinger, "out_fence must not be nullptr"); return Status::BadValue; } @@ -361,7 +361,7 @@ Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out core->WaitWhileAllocatingLocked(); if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } @@ -380,7 +380,7 @@ Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out return Status::NoMemory; } - LOG_DEBUG(Service_NVFlinger, "Detached slot {}", found); + LOG_DEBUG(Service_Nvnflinger, "Detached slot {}", found); *out_buffer = slots[found].graphic_buffer; *out_fence = slots[found].fence; @@ -393,10 +393,10 @@ Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out Status BufferQueueProducer::AttachBuffer(s32* out_slot, const std::shared_ptr<GraphicBuffer>& buffer) { if (out_slot == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_slot must not be nullptr"); + LOG_ERROR(Service_Nvnflinger, "out_slot must not be nullptr"); return Status::BadValue; } else if (buffer == nullptr) { - LOG_ERROR(Service_NVFlinger, "Cannot attach nullptr buffer"); + LOG_ERROR(Service_Nvnflinger, "Cannot attach nullptr buffer"); return Status::BadValue; } @@ -413,13 +413,13 @@ Status BufferQueueProducer::AttachBuffer(s32* out_slot, // This should not happen if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { - LOG_ERROR(Service_NVFlinger, "No available buffer slots"); + LOG_ERROR(Service_Nvnflinger, "No available buffer slots"); return Status::Busy; } *out_slot = found; - LOG_DEBUG(Service_NVFlinger, "Returning slot {} flags={}", *out_slot, return_flags); + LOG_DEBUG(Service_Nvnflinger, "Returning slot {} flags={}", *out_slot, return_flags); slots[*out_slot].graphic_buffer = buffer; slots[*out_slot].buffer_state = BufferState::Dequeued; @@ -451,7 +451,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, case NativeWindowScalingMode::NoScaleCrop: break; default: - LOG_ERROR(Service_NVFlinger, "unknown scaling mode {}", scaling_mode); + LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode); return Status::BadValue; } @@ -464,38 +464,38 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } const s32 max_buffer_count = core->GetMaxBufferCountLocked(async); if (async && core->override_max_buffer_count) { if (core->override_max_buffer_count < max_buffer_count) { - LOG_ERROR(Service_NVFlinger, "async mode is invalid with " - "buffer count override"); + LOG_ERROR(Service_Nvnflinger, "async mode is invalid with " + "buffer count override"); return Status::BadValue; } } if (slot < 0 || slot >= max_buffer_count) { - LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot index {} out of range [0, {})", slot, max_buffer_count); return Status::BadValue; } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, + LOG_ERROR(Service_Nvnflinger, "slot {} is not owned by the producer " "(state = {})", slot, slots[slot].buffer_state); return Status::BadValue; } else if (!slots[slot].request_buffer_called) { - LOG_ERROR(Service_NVFlinger, + LOG_ERROR(Service_Nvnflinger, "slot {} was queued without requesting " "a buffer", slot); return Status::BadValue; } - LOG_DEBUG(Service_NVFlinger, + LOG_DEBUG(Service_Nvnflinger, "slot={} frame={} time={} crop=[{},{},{},{}] transform={} scale={}", slot, core->frame_counter + 1, timestamp, crop.Left(), crop.Top(), crop.Right(), crop.Bottom(), transform, scaling_mode); @@ -506,7 +506,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, [[maybe_unused]] const bool unused = crop.Intersect(buffer_rect, &cropped_rect); if (cropped_rect != crop) { - LOG_ERROR(Service_NVFlinger, "crop rect is not contained within the buffer in slot {}", + LOG_ERROR(Service_Nvnflinger, "crop rect is not contained within the buffer in slot {}", slot); return Status::BadValue; } @@ -598,21 +598,21 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, } void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); std::scoped_lock lock{core->mutex}; if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return; } if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot index {} out of range [0, {})", slot, BufferQueueDefs::NUM_BUFFER_SLOTS); return; } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot, + LOG_ERROR(Service_Nvnflinger, "slot {} is not owned by the producer (state = {})", slot, slots[slot].buffer_state); return; } @@ -629,12 +629,12 @@ Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { std::scoped_lock lock{core->mutex}; if (out_value == nullptr) { - LOG_ERROR(Service_NVFlinger, "outValue was nullptr"); + LOG_ERROR(Service_Nvnflinger, "outValue was nullptr"); return Status::BadValue; } if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } @@ -666,7 +666,7 @@ Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { return Status::BadValue; } - LOG_DEBUG(Service_NVFlinger, "what = {}, value = {}", what, value); + LOG_DEBUG(Service_Nvnflinger, "what = {}, value = {}", what, value); *out_value = static_cast<s32>(value); @@ -678,26 +678,26 @@ Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& li QueueBufferOutput* output) { std::scoped_lock lock{core->mutex}; - LOG_DEBUG(Service_NVFlinger, "api = {} producer_controlled_by_app = {}", api, + LOG_DEBUG(Service_Nvnflinger, "api = {} producer_controlled_by_app = {}", api, producer_controlled_by_app); if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has been abandoned"); return Status::NoInit; } if (core->consumer_listener == nullptr) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has no consumer"); + LOG_ERROR(Service_Nvnflinger, "BufferQueue has no consumer"); return Status::NoInit; } if (output == nullptr) { - LOG_ERROR(Service_NVFlinger, "output was nullptr"); + LOG_ERROR(Service_Nvnflinger, "output was nullptr"); return Status::BadValue; } if (core->connected_api != NativeWindowApi::NoConnectedApi) { - LOG_ERROR(Service_NVFlinger, "already connected (cur = {} req = {})", core->connected_api, + LOG_ERROR(Service_Nvnflinger, "already connected (cur = {} req = {})", core->connected_api, api); return Status::BadValue; } @@ -714,7 +714,7 @@ Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& li core->connected_producer_listener = listener; break; default: - LOG_ERROR(Service_NVFlinger, "unknown api = {}", api); + LOG_ERROR(Service_Nvnflinger, "unknown api = {}", api); status = Status::BadValue; break; } @@ -727,7 +727,7 @@ Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& li } Status BufferQueueProducer::Disconnect(NativeWindowApi api) { - LOG_DEBUG(Service_NVFlinger, "api = {}", api); + LOG_DEBUG(Service_Nvnflinger, "api = {}", api); Status status = Status::NoError; std::shared_ptr<IConsumerListener> listener; @@ -762,13 +762,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { buffer_wait_event->Signal(); listener = core->consumer_listener; } else { - LOG_ERROR(Service_NVFlinger, "still connected to another api (cur = {} req = {})", + LOG_ERROR(Service_Nvnflinger, "still connected to another api (cur = {} req = {})", core->connected_api, api); status = Status::BadValue; } break; default: - LOG_ERROR(Service_NVFlinger, "unknown api = {}", api); + LOG_ERROR(Service_Nvnflinger, "unknown api = {}", api); status = Status::BadValue; break; } @@ -784,7 +784,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { return Status::BadValue; @@ -793,6 +793,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, std::scoped_lock lock{core->mutex}; slots[slot] = {}; + slots[slot].fence = Fence::NoFence(); slots[slot].graphic_buffer = buffer; slots[slot].frame_number = 0; @@ -813,10 +814,10 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, return Status::NoError; } -void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) { +void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) { Status status{Status::NoError}; - Parcel parcel_in{ctx.ReadBuffer()}; - Parcel parcel_out{}; + InputParcel parcel_in{ctx.ReadBuffer()}; + OutputParcel parcel_out{}; switch (code) { case TransactionId::Connect: { @@ -854,7 +855,7 @@ void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId status = DequeueBuffer(&slot, &fence, is_async, width, height, pixel_format, usage); parcel_out.Write(slot); - parcel_out.WriteObject(&fence); + parcel_out.WriteFlattenedObject(&fence); break; } case TransactionId::RequestBuffer: { @@ -864,7 +865,7 @@ void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId status = RequestBuffer(slot, &buf); - parcel_out.WriteObject(buf); + parcel_out.WriteFlattenedObject(buf); break; } case TransactionId::QueueBuffer: { @@ -914,7 +915,7 @@ void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId break; } case TransactionId::GetBufferHistory: - LOG_WARNING(Service_NVFlinger, "(STUBBED) called, transaction=GetBufferHistory"); + LOG_WARNING(Service_Nvnflinger, "(STUBBED) called, transaction=GetBufferHistory"); break; default: ASSERT_MSG(false, "Unimplemented TransactionId {}", code); diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 1d380480f..d4201c104 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -12,13 +12,13 @@ #include "common/common_funcs.h" #include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvflinger/binder.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/buffer_slot.h" -#include "core/hle/service/nvflinger/graphic_buffer_producer.h" -#include "core/hle/service/nvflinger/pixel_format.h" -#include "core/hle/service/nvflinger/status.h" -#include "core/hle/service/nvflinger/window.h" +#include "core/hle/service/nvnflinger/binder.h" +#include "core/hle/service/nvnflinger/buffer_queue_defs.h" +#include "core/hle/service/nvnflinger/buffer_slot.h" +#include "core/hle/service/nvnflinger/graphic_buffer_producer.h" +#include "core/hle/service/nvnflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/status.h" +#include "core/hle/service/nvnflinger/window.h" namespace Kernel { class KernelCore; @@ -46,7 +46,7 @@ public: Service::Nvidia::NvCore::NvMap& nvmap_); ~BufferQueueProducer(); - void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override; + void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) override; Kernel::KReadableEvent& GetNativeHandle() override; diff --git a/src/core/hle/service/nvflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index 0cd0e9964..d25bca049 100644 --- a/src/core/hle/service/nvflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h @@ -9,7 +9,7 @@ #include <memory> #include "common/common_types.h" -#include "core/hle/service/nvflinger/ui/fence.h" +#include "core/hle/service/nvnflinger/ui/fence.h" namespace Service::android { diff --git a/src/core/hle/service/nvflinger/buffer_transform_flags.h b/src/core/hle/service/nvnflinger/buffer_transform_flags.h index 67aa5dad6..67aa5dad6 100644 --- a/src/core/hle/service/nvflinger/buffer_transform_flags.h +++ b/src/core/hle/service/nvnflinger/buffer_transform_flags.h diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp index 982531e2d..4dcda8dac 100644 --- a/src/core/hle/service/nvflinger/consumer_base.cpp +++ b/src/core/hle/service/nvnflinger/consumer_base.cpp @@ -6,11 +6,11 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/consumer_base.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" +#include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/consumer_base.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" namespace Service::android { @@ -28,7 +28,7 @@ void ConsumerBase::Connect(bool controlled_by_app) { } void ConsumerBase::FreeBufferLocked(s32 slot_index) { - LOG_DEBUG(Service_NVFlinger, "slot_index={}", slot_index); + LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index); slots[slot_index].graphic_buffer = nullptr; slots[slot_index].fence = Fence::NoFence(); @@ -36,17 +36,17 @@ void ConsumerBase::FreeBufferLocked(s32 slot_index) { } void ConsumerBase::OnFrameAvailable(const BufferItem& item) { - LOG_DEBUG(Service_NVFlinger, "called"); + LOG_DEBUG(Service_Nvnflinger, "called"); } void ConsumerBase::OnFrameReplaced(const BufferItem& item) { - LOG_DEBUG(Service_NVFlinger, "called"); + LOG_DEBUG(Service_Nvnflinger, "called"); } void ConsumerBase::OnBuffersReleased() { std::scoped_lock lock{mutex}; - LOG_DEBUG(Service_NVFlinger, "called"); + LOG_DEBUG(Service_Nvnflinger, "called"); if (is_abandoned) { // Nothing to do if we're already abandoned. @@ -77,7 +77,7 @@ Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseco slots[item->slot].frame_number = item->frame_number; slots[item->slot].fence = item->fence; - LOG_DEBUG(Service_NVFlinger, "slot={}", item->slot); + LOG_DEBUG(Service_Nvnflinger, "slot={}", item->slot); return Status::NoError; } @@ -85,7 +85,7 @@ Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseco Status ConsumerBase::AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer, const Fence& fence) { - LOG_DEBUG(Service_NVFlinger, "slot={}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot={}", slot); // If consumer no longer tracks this graphic_buffer, we can safely // drop this fence, as it will never be received by the producer. @@ -109,7 +109,7 @@ Status ConsumerBase::ReleaseBufferLocked(s32 slot, return Status::NoError; } - LOG_DEBUG(Service_NVFlinger, "slot={}", slot); + LOG_DEBUG(Service_Nvnflinger, "slot={}", slot); Status err = consumer->ReleaseBuffer(slot, slots[slot].frame_number, slots[slot].fence); if (err == Status::StaleBufferSlot) { FreeBufferLocked(slot); diff --git a/src/core/hle/service/nvflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h index 9a8a5f6bb..264829414 100644 --- a/src/core/hle/service/nvflinger/consumer_base.h +++ b/src/core/hle/service/nvnflinger/consumer_base.h @@ -12,9 +12,9 @@ #include <mutex> #include "common/common_types.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/consumer_listener.h" -#include "core/hle/service/nvflinger/status.h" +#include "core/hle/service/nvnflinger/buffer_queue_defs.h" +#include "core/hle/service/nvnflinger/consumer_listener.h" +#include "core/hle/service/nvnflinger/status.h" namespace Service::android { diff --git a/src/core/hle/service/nvflinger/consumer_listener.h b/src/core/hle/service/nvnflinger/consumer_listener.h index 74a193988..74a193988 100644 --- a/src/core/hle/service/nvflinger/consumer_listener.h +++ b/src/core/hle/service/nvnflinger/consumer_listener.h diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp b/src/core/hle/service/nvnflinger/graphic_buffer_producer.cpp index 4043c91f1..d72b49a8e 100644 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp +++ b/src/core/hle/service/nvnflinger/graphic_buffer_producer.cpp @@ -4,12 +4,12 @@ // Parts of this implementation were based on: // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/IGraphicBufferProducer.cpp -#include "core/hle/service/nvflinger/graphic_buffer_producer.h" -#include "core/hle/service/nvflinger/parcel.h" +#include "core/hle/service/nvnflinger/graphic_buffer_producer.h" +#include "core/hle/service/nvnflinger/parcel.h" namespace Service::android { -QueueBufferInput::QueueBufferInput(Parcel& parcel) { +QueueBufferInput::QueueBufferInput(InputParcel& parcel) { parcel.ReadFlattened(*this); } diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.h b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h index 6ea327bbe..21d7b31f3 100644 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.h +++ b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h @@ -9,16 +9,16 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/math_util.h" -#include "core/hle/service/nvflinger/ui/fence.h" -#include "core/hle/service/nvflinger/window.h" +#include "core/hle/service/nvnflinger/ui/fence.h" +#include "core/hle/service/nvnflinger/window.h" namespace Service::android { -class Parcel; +class InputParcel; #pragma pack(push, 1) struct QueueBufferInput final { - explicit QueueBufferInput(Parcel& parcel); + explicit QueueBufferInput(InputParcel& parcel); void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp index dc9b2a9ec..b86a79ec9 100644 --- a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp @@ -4,9 +4,9 @@ #include <mutex> #include "common/common_types.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -namespace Service::NVFlinger { +namespace Service::Nvnflinger { HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) : service_context(system_, "HosBinderDriverServer") {} @@ -33,4 +33,4 @@ android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { return {}; } -} // namespace Service::NVFlinger +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h index 8fddc1206..58bb9469a 100644 --- a/src/core/hle/service/nvflinger/hos_binder_driver_server.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h @@ -9,13 +9,13 @@ #include "common/common_types.h" #include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvflinger/binder.h" +#include "core/hle/service/nvnflinger/binder.h" namespace Core { class System; } -namespace Service::NVFlinger { +namespace Service::Nvnflinger { class HosBinderDriverServer final { public: @@ -34,4 +34,4 @@ private: u64 last_id{}; }; -} // namespace Service::NVFlinger +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index f4416f5b2..5f55cd31e 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -15,11 +15,11 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" #include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvflinger/buffer_item_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvflinger/nvflinger.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" +#include "core/hle/service/nvnflinger/buffer_item_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" #include "core/hle/service/vi/display/vi_display.h" #include "core/hle/service/vi/layer/vi_layer.h" #include "core/hle/service/vi/vi_results.h" @@ -27,11 +27,11 @@ #include "video_core/host1x/host1x.h" #include "video_core/host1x/syncpoint_manager.h" -namespace Service::NVFlinger { +namespace Service::Nvnflinger { constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; -void NVFlinger::SplitVSync(std::stop_token stop_token) { +void Nvnflinger::SplitVSync(std::stop_token stop_token) { system.RegisterHostThread(); std::string name = "VSyncThread"; MicroProfileOnThreadCreate(name.c_str()); @@ -43,19 +43,15 @@ void NVFlinger::SplitVSync(std::stop_token stop_token) { Common::SetCurrentThreadPriority(Common::ThreadPriority::High); while (!stop_token.stop_requested()) { - vsync_signal.wait(false); - vsync_signal.store(false); - - guard->lock(); + vsync_signal.Wait(); + const auto lock_guard = Lock(); Compose(); - - guard->unlock(); } } -NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_) - : system(system_), service_context(system_, "nvflinger"), +Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_) + : system(system_), service_context(system_, "nvnflinger"), hos_binder_driver_server(hos_binder_driver_server_) { displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system); displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system); @@ -69,8 +65,8 @@ NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_dr "ScreenComposition", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - vsync_signal.store(true); - vsync_signal.notify_all(); + { const auto lock_guard = Lock(); } + vsync_signal.Set(); return std::chrono::nanoseconds(GetNextTicks()); }); @@ -92,12 +88,11 @@ NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_dr } } -NVFlinger::~NVFlinger() { +Nvnflinger::~Nvnflinger() { if (system.IsMulticore()) { system.CoreTiming().UnscheduleEvent(multi_composition_event, {}); vsync_thread.request_stop(); - vsync_signal.store(true); - vsync_signal.notify_all(); + vsync_signal.Set(); } else { system.CoreTiming().UnscheduleEvent(single_composition_event, {}); } @@ -109,7 +104,7 @@ NVFlinger::~NVFlinger() { } } -void NVFlinger::ShutdownLayers() { +void Nvnflinger::ShutdownLayers() { for (auto& display : displays) { for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { display.GetLayer(layer).Core().NotifyShutdown(); @@ -117,15 +112,15 @@ void NVFlinger::ShutdownLayers() { } } -void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { +void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { nvdrv = std::move(instance); disp_fd = nvdrv->Open("/dev/nvdisp_disp0"); } -std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { +std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { const auto lock_guard = Lock(); - LOG_DEBUG(Service_NVFlinger, "Opening \"{}\" display", name); + LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name); const auto itr = std::find_if(displays.begin(), displays.end(), @@ -138,7 +133,7 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { return itr->GetID(); } -bool NVFlinger::CloseDisplay(u64 display_id) { +bool Nvnflinger::CloseDisplay(u64 display_id) { const auto lock_guard = Lock(); auto* const display = FindDisplay(display_id); @@ -151,7 +146,7 @@ bool NVFlinger::CloseDisplay(u64 display_id) { return true; } -std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { +std::optional<u64> Nvnflinger::CreateLayer(u64 display_id) { const auto lock_guard = Lock(); auto* const display = FindDisplay(display_id); @@ -164,12 +159,12 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { return layer_id; } -void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { +void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { const auto buffer_id = next_buffer_queue_id++; display.CreateLayer(layer_id, buffer_id, nvdrv->container); } -void NVFlinger::CloseLayer(u64 layer_id) { +void Nvnflinger::CloseLayer(u64 layer_id) { const auto lock_guard = Lock(); for (auto& display : displays) { @@ -177,7 +172,7 @@ void NVFlinger::CloseLayer(u64 layer_id) { } } -std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) { +std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) { const auto lock_guard = Lock(); const auto* const layer = FindOrCreateLayer(display_id, layer_id); @@ -188,7 +183,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) { return layer->GetBinderId(); } -ResultVal<Kernel::KReadableEvent*> NVFlinger::FindVsyncEvent(u64 display_id) { +ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) { const auto lock_guard = Lock(); auto* const display = FindDisplay(display_id); @@ -199,7 +194,7 @@ ResultVal<Kernel::KReadableEvent*> NVFlinger::FindVsyncEvent(u64 display_id) { return display->GetVSyncEvent(); } -VI::Display* NVFlinger::FindDisplay(u64 display_id) { +VI::Display* Nvnflinger::FindDisplay(u64 display_id) { const auto itr = std::find_if(displays.begin(), displays.end(), [&](const VI::Display& display) { return display.GetID() == display_id; }); @@ -211,7 +206,7 @@ VI::Display* NVFlinger::FindDisplay(u64 display_id) { return &*itr; } -const VI::Display* NVFlinger::FindDisplay(u64 display_id) const { +const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const { const auto itr = std::find_if(displays.begin(), displays.end(), [&](const VI::Display& display) { return display.GetID() == display_id; }); @@ -223,7 +218,7 @@ const VI::Display* NVFlinger::FindDisplay(u64 display_id) const { return &*itr; } -VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) { +VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) { auto* const display = FindDisplay(display_id); if (display == nullptr) { @@ -233,7 +228,7 @@ VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) { return display->FindLayer(layer_id); } -const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { +const VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) const { const auto* const display = FindDisplay(display_id); if (display == nullptr) { @@ -243,7 +238,7 @@ const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { return display->FindLayer(layer_id); } -VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { +VI::Layer* Nvnflinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { auto* const display = FindDisplay(display_id); if (display == nullptr) { @@ -253,7 +248,7 @@ VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { auto* layer = display->FindLayer(layer_id); if (layer == nullptr) { - LOG_DEBUG(Service_NVFlinger, "Layer at id {} not found. Trying to create it.", layer_id); + LOG_DEBUG(Service_Nvnflinger, "Layer at id {} not found. Trying to create it.", layer_id); CreateLayerAtId(*display, layer_id); return display->FindLayer(layer_id); } @@ -261,7 +256,7 @@ VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { return layer; } -void NVFlinger::Compose() { +void Nvnflinger::Compose() { for (auto& display : displays) { // Trigger vsync for this display at the end of drawing SCOPE_EXIT({ display.SignalVSyncEvent(); }); @@ -311,7 +306,7 @@ void NVFlinger::Compose() { } } -s64 NVFlinger::GetNextTicks() const { +s64 Nvnflinger::GetNextTicks() const { const auto& settings = Settings::values; auto speed_scale = 1.f; if (settings.use_multi_core.GetValue()) { @@ -324,6 +319,10 @@ s64 NVFlinger::GetNextTicks() const { speed_scale = 0.01f; } } + if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { + // Run at intended presentation rate during video playback. + speed_scale = 1.f; + } // As an extension, treat nonpositive swap interval as framerate multiplier. const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval) @@ -332,4 +331,4 @@ s64 NVFlinger::GetNextTicks() const { return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); } -} // namespace Service::NVFlinger +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 3828cf272..ef236303a 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -12,6 +12,7 @@ #include "common/common_types.h" #include "common/polyfill_thread.h" +#include "common/thread.h" #include "core/hle/result.h" #include "core/hle/service/kernel_helpers.h" @@ -42,12 +43,12 @@ class BufferQueueCore; class BufferQueueProducer; } // namespace Service::android -namespace Service::NVFlinger { +namespace Service::Nvnflinger { -class NVFlinger final { +class Nvnflinger final { public: - explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); - ~NVFlinger(); + explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); + ~Nvnflinger(); void ShutdownLayers(); @@ -143,7 +144,7 @@ private: Core::System& system; - std::atomic<bool> vsync_signal; + Common::Event vsync_signal; std::jthread vsync_thread; @@ -152,4 +153,4 @@ private: HosBinderDriverServer& hos_binder_driver_server; }; -} // namespace Service::NVFlinger +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/parcel.h b/src/core/hle/service/nvnflinger/parcel.h new file mode 100644 index 000000000..23ba315a0 --- /dev/null +++ b/src/core/hle/service/nvnflinger/parcel.h @@ -0,0 +1,184 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <memory> +#include <span> +#include <vector> +#include <boost/container/small_vector.hpp> + +#include "common/alignment.h" +#include "common/assert.h" +#include "common/common_types.h" + +namespace Service::android { + +struct ParcelHeader { + u32 data_size; + u32 data_offset; + u32 objects_size; + u32 objects_offset; +}; +static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size"); + +class InputParcel final { +public: + explicit InputParcel(std::span<const u8> in_data) : read_buffer(std::move(in_data)) { + DeserializeHeader(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); + } + + template <typename T> + void Read(T& val) { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); + ASSERT(read_index + sizeof(T) <= read_buffer.size()); + + std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); + read_index += sizeof(T); + read_index = Common::AlignUp(read_index, 4); + } + + template <typename T> + T Read() { + T val; + Read(val); + return val; + } + + template <typename T> + void ReadFlattened(T& val) { + const auto flattened_size = Read<s64>(); + ASSERT(sizeof(T) == flattened_size); + Read(val); + } + + template <typename T> + T ReadFlattened() { + T val; + ReadFlattened(val); + return val; + } + + template <typename T> + T ReadUnaligned() { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); + ASSERT(read_index + sizeof(T) <= read_buffer.size()); + + T val; + std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); + read_index += sizeof(T); + return val; + } + + template <typename T> + const std::shared_ptr<T> ReadObject() { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); + + const auto is_valid{Read<bool>()}; + + if (is_valid) { + auto result = std::make_shared<T>(); + ReadFlattened(*result); + return result; + } + + return {}; + } + + std::u16string ReadInterfaceToken() { + [[maybe_unused]] const u32 unknown = Read<u32>(); + const u32 length = Read<u32>(); + + std::u16string token; + token.reserve(length + 1); + + for (u32 ch = 0; ch < length + 1; ++ch) { + token.push_back(ReadUnaligned<u16>()); + } + + read_index = Common::AlignUp(read_index, 4); + + return token; + } + + void DeserializeHeader() { + ASSERT(read_buffer.size() > sizeof(ParcelHeader)); + + ParcelHeader header{}; + std::memcpy(&header, read_buffer.data(), sizeof(ParcelHeader)); + + read_index = header.data_offset; + } + +private: + std::span<const u8> read_buffer; + std::size_t read_index = 0; +}; + +class OutputParcel final { +public: + OutputParcel() = default; + + template <typename T> + void Write(const T& val) { + this->WriteImpl(val, m_data_buffer); + } + + template <typename T> + void WriteFlattenedObject(const T* ptr) { + if (!ptr) { + this->Write<u32>(0); + return; + } + + this->Write<u32>(1); + this->Write<s64>(sizeof(T)); + this->Write(*ptr); + } + + template <typename T> + void WriteFlattenedObject(const std::shared_ptr<T> ptr) { + this->WriteFlattenedObject(ptr.get()); + } + + template <typename T> + void WriteInterface(const T& val) { + this->WriteImpl(val, m_data_buffer); + this->WriteImpl(0U, m_object_buffer); + } + + std::vector<u8> Serialize() const { + std::vector<u8> output_buffer(sizeof(ParcelHeader) + m_data_buffer.size() + + m_object_buffer.size()); + + ParcelHeader header{}; + header.data_size = static_cast<u32>(m_data_buffer.size()); + header.data_offset = sizeof(ParcelHeader); + header.objects_size = static_cast<u32>(m_object_buffer.size()); + header.objects_offset = header.data_offset + header.data_size; + + std::memcpy(output_buffer.data(), &header, sizeof(header)); + std::ranges::copy(m_data_buffer, output_buffer.data() + header.data_offset); + std::ranges::copy(m_object_buffer, output_buffer.data() + header.objects_offset); + + return output_buffer; + } + +private: + template <typename T> + requires(std::is_trivially_copyable_v<T>) + void WriteImpl(const T& val, boost::container::small_vector<u8, 0x200>& buffer) { + const size_t aligned_size = Common::AlignUp(sizeof(T), 4); + const size_t old_size = buffer.size(); + buffer.resize(old_size + aligned_size); + + std::memcpy(buffer.data() + old_size, &val, sizeof(T)); + } + +private: + boost::container::small_vector<u8, 0x200> m_data_buffer; + boost::container::small_vector<u8, 0x200> m_object_buffer; +}; + +} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/pixel_format.h b/src/core/hle/service/nvnflinger/pixel_format.h index f77d0acfb..f77d0acfb 100644 --- a/src/core/hle/service/nvflinger/pixel_format.h +++ b/src/core/hle/service/nvnflinger/pixel_format.h diff --git a/src/core/hle/service/nvflinger/producer_listener.h b/src/core/hle/service/nvnflinger/producer_listener.h index 6bf8aaf1e..6bf8aaf1e 100644 --- a/src/core/hle/service/nvflinger/producer_listener.h +++ b/src/core/hle/service/nvnflinger/producer_listener.h diff --git a/src/core/hle/service/nvflinger/status.h b/src/core/hle/service/nvnflinger/status.h index 7af166c40..7af166c40 100644 --- a/src/core/hle/service/nvflinger/status.h +++ b/src/core/hle/service/nvnflinger/status.h diff --git a/src/core/hle/service/nvflinger/ui/fence.h b/src/core/hle/service/nvnflinger/ui/fence.h index 536e8156d..536e8156d 100644 --- a/src/core/hle/service/nvflinger/ui/fence.h +++ b/src/core/hle/service/nvnflinger/ui/fence.h diff --git a/src/core/hle/service/nvflinger/ui/graphic_buffer.h b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h index 9a27f8f02..75d1705a8 100644 --- a/src/core/hle/service/nvflinger/ui/graphic_buffer.h +++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h @@ -8,7 +8,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" -#include "core/hle/service/nvflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/pixel_format.h" namespace Service::android { diff --git a/src/core/hle/service/nvflinger/window.h b/src/core/hle/service/nvnflinger/window.h index 61cca5b01..61cca5b01 100644 --- a/src/core/hle/service/nvflinger/window.h +++ b/src/core/hle/service/nvnflinger/window.h diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp index 530e1be3b..14ba67b4c 100644 --- a/src/core/hle/service/olsc/olsc.cpp +++ b/src/core/hle/service/olsc/olsc.cpp @@ -1,10 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/olsc/olsc.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::OLSC { @@ -42,7 +42,7 @@ public: } private: - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { LOG_WARNING(Service_OLSC, "(STUBBED) called"); initialized = true; @@ -51,7 +51,7 @@ private: rb.Push(ResultSuccess); } - void GetSaveDataBackupSetting(Kernel::HLERequestContext& ctx) { + void GetSaveDataBackupSetting(HLERequestContext& ctx) { LOG_WARNING(Service_OLSC, "(STUBBED) called"); // backup_setting is set to 0 since real value is unknown @@ -62,7 +62,7 @@ private: rb.Push(backup_setting); } - void SetSaveDataBackupSettingEnabled(Kernel::HLERequestContext& ctx) { + void SetSaveDataBackupSettingEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_OLSC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -72,8 +72,11 @@ private: bool initialized{}; }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<OLSC>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::OLSC diff --git a/src/core/hle/service/olsc/olsc.h b/src/core/hle/service/olsc/olsc.h index 1522d8d32..620b634fa 100644 --- a/src/core/hle/service/olsc/olsc.h +++ b/src/core/hle/service/olsc/olsc.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::OLSC { -/// Registers all SSL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::OLSC diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp index 79501b9f9..c6da6eb51 100644 --- a/src/core/hle/service/pcie/pcie.cpp +++ b/src/core/hle/service/pcie/pcie.cpp @@ -4,8 +4,8 @@ #include <memory> #include "core/hle/service/pcie/pcie.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::PCIe { @@ -59,8 +59,11 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<PCIe>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("pcie", std::make_shared<PCIe>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PCIe diff --git a/src/core/hle/service/pcie/pcie.h b/src/core/hle/service/pcie/pcie.h index cebfd9042..5c2d4b805 100644 --- a/src/core/hle/service/pcie/pcie.h +++ b/src/core/hle/service/pcie/pcie.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::PCIe { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PCIe diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp index 2a123b42d..f966c5c8b 100644 --- a/src/core/hle/service/pctl/pctl_module.cpp +++ b/src/core/hle/service/pctl/pctl_module.cpp @@ -5,9 +5,10 @@ #include "core/core.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/pctl/pctl.h" #include "core/hle/service/pctl/pctl_module.h" +#include "core/hle/service/server_manager.h" namespace Service::PCTL { @@ -176,7 +177,7 @@ private: settings.is_stero_vision_restricted = is_restricted; } - void Initialize(Kernel::HLERequestContext& ctx) { + void Initialize(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -187,7 +188,7 @@ private: // TODO(ogniK): Recovery flag initialization for pctl:r - const auto tid = system.GetCurrentProcessProgramID(); + const auto tid = system.GetApplicationProcessProgramID(); if (tid != 0) { const FileSys::PatchManager pm{tid, system.GetFileSystemController(), system.GetContentProvider()}; @@ -214,7 +215,7 @@ private: rb.Push(ResultSuccess); } - void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { + void CheckFreeCommunicationPermission(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -227,7 +228,7 @@ private: states.free_communication = true; } - void ConfirmStereoVisionPermission(Kernel::HLERequestContext& ctx) { + void ConfirmStereoVisionPermission(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); states.stereo_vision = true; @@ -235,14 +236,14 @@ private: rb.Push(ResultSuccess); } - void EndFreeCommunication(Kernel::HLERequestContext& ctx) { + void EndFreeCommunication(HLERequestContext& ctx) { LOG_WARNING(Service_PCTL, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void IsFreeCommunicationAvailable(Kernel::HLERequestContext& ctx) { + void IsFreeCommunicationAvailable(HLERequestContext& ctx) { LOG_WARNING(Service_PCTL, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -253,7 +254,7 @@ private: } } - void IsRestrictionEnabled(Kernel::HLERequestContext& ctx) { + void IsRestrictionEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -267,7 +268,7 @@ private: rb.Push(pin_code[0] != '\0'); } - void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) { + void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -286,7 +287,7 @@ private: rb.Push(ResultSuccess); } - void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) { + void IsStereoVisionPermitted(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -299,7 +300,7 @@ private: } } - void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { + void SetStereoVisionRestriction(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_use = rp.Pop<bool>(); LOG_DEBUG(Service_PCTL, "called, can_use={}", can_use); @@ -315,7 +316,7 @@ private: rb.Push(ResultSuccess); } - void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { + void GetStereoVisionRestriction(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -330,7 +331,7 @@ private: rb.Push(settings.is_stero_vision_restricted); } - void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) { + void ResetConfirmedStereoVisionPermission(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); states.stereo_vision = false; @@ -369,7 +370,7 @@ private: Capability capability{}; }; -void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateService(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -379,7 +380,7 @@ void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IParentalControlService>(system, capability); } -void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { +void Module::Interface::CreateServiceWithoutInitialize(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -393,19 +394,22 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu Module::Interface::~Interface() = default; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + auto module = std::make_shared<Module>(); - std::make_shared<PCTL>(system, module, "pctl", - Capability::Application | Capability::SnsPost | Capability::Status | - Capability::StereoVision) - ->InstallAsService(service_manager); + server_manager->RegisterNamedService( + "pctl", std::make_shared<PCTL>(system, module, "pctl", + Capability::Application | Capability::SnsPost | + Capability::Status | Capability::StereoVision)); // TODO(ogniK): Implement remaining capabilities - std::make_shared<PCTL>(system, module, "pctl:a", Capability::None) - ->InstallAsService(service_manager); - std::make_shared<PCTL>(system, module, "pctl:r", Capability::None) - ->InstallAsService(service_manager); - std::make_shared<PCTL>(system, module, "pctl:s", Capability::None) - ->InstallAsService(service_manager); + server_manager->RegisterNamedService( + "pctl:a", std::make_shared<PCTL>(system, module, "pctl:a", Capability::None)); + server_manager->RegisterNamedService( + "pctl:r", std::make_shared<PCTL>(system, module, "pctl:r", Capability::None)); + server_manager->RegisterNamedService( + "pctl:s", std::make_shared<PCTL>(system, module, "pctl:s", Capability::None)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PCTL diff --git a/src/core/hle/service/pctl/pctl_module.h b/src/core/hle/service/pctl/pctl_module.h index 6f584530d..dff0d3f08 100644 --- a/src/core/hle/service/pctl/pctl_module.h +++ b/src/core/hle/service/pctl/pctl_module.h @@ -31,8 +31,8 @@ public: const char* name_, Capability capability_); ~Interface() override; - void CreateService(Kernel::HLERequestContext& ctx); - void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx); + void CreateService(HLERequestContext& ctx); + void CreateServiceWithoutInitialize(HLERequestContext& ctx); protected: std::shared_ptr<Module> module; @@ -42,7 +42,6 @@ public: }; }; -/// Registers all PCTL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PCTL diff --git a/src/core/hle/service/pcv/pcv.cpp b/src/core/hle/service/pcv/pcv.cpp index f7a497a14..c13ffa6f6 100644 --- a/src/core/hle/service/pcv/pcv.cpp +++ b/src/core/hle/service/pcv/pcv.cpp @@ -3,10 +3,10 @@ #include <memory> -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/pcv/pcv.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::PCV { @@ -52,32 +52,6 @@ public: } }; -class PCV_ARB final : public ServiceFramework<PCV_ARB> { -public: - explicit PCV_ARB(Core::System& system_) : ServiceFramework{system_, "pcv:arb"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "ReleaseControl"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class PCV_IMM final : public ServiceFramework<PCV_IMM> { -public: - explicit PCV_IMM(Core::System& system_) : ServiceFramework{system_, "pcv:imm"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "SetClockRate"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - class IClkrstSession final : public ServiceFramework<IClkrstSession> { public: explicit IClkrstSession(Core::System& system_, DeviceCode deivce_code_) @@ -102,7 +76,7 @@ public: } private: - void SetClockRate(Kernel::HLERequestContext& ctx) { + void SetClockRate(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; clock_rate = rp.Pop<u32>(); LOG_DEBUG(Service_PCV, "(STUBBED) called, clock_rate={}", clock_rate); @@ -111,7 +85,7 @@ private: rb.Push(ResultSuccess); } - void GetClockRate(Kernel::HLERequestContext& ctx) { + void GetClockRate(HLERequestContext& ctx) { LOG_DEBUG(Service_PCV, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -141,7 +115,7 @@ public: } private: - void OpenSession(Kernel::HLERequestContext& ctx) { + void OpenSession(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto device_code = static_cast<DeviceCode>(rp.Pop<u32>()); const auto unkonwn_input = rp.Pop<u32>(); @@ -167,13 +141,14 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<PCV>(system)->InstallAsService(sm); - std::make_shared<PCV_ARB>(system)->InstallAsService(sm); - std::make_shared<PCV_IMM>(system)->InstallAsService(sm); - std::make_shared<CLKRST>(system, "clkrst")->InstallAsService(sm); - std::make_shared<CLKRST>(system, "clkrst:i")->InstallAsService(sm); - std::make_shared<CLKRST_A>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("pcv", std::make_shared<PCV>(system)); + server_manager->RegisterNamedService("clkrst", std::make_shared<CLKRST>(system, "clkrst")); + server_manager->RegisterNamedService("clkrst:i", std::make_shared<CLKRST>(system, "clkrst:i")); + server_manager->RegisterNamedService("clkrst:a", std::make_shared<CLKRST_A>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PCV diff --git a/src/core/hle/service/pcv/pcv.h b/src/core/hle/service/pcv/pcv.h index 6b26b6fa7..bf541e6fe 100644 --- a/src/core/hle/service/pcv/pcv.h +++ b/src/core/hle/service/pcv/pcv.h @@ -7,10 +7,6 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::PCV { enum class DeviceCode : u32 { @@ -104,6 +100,6 @@ enum class DeviceCode : u32 { OscClk = 0x40000080 }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PCV diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index b10e86c8f..f9cf2dda3 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -2,10 +2,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/pm/pm.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::PM { @@ -33,15 +34,15 @@ std::optional<Kernel::KProcess*> SearchProcessList( return *iter; } -void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, +void GetApplicationPidGeneric(HLERequestContext& ctx, const std::vector<Kernel::KProcess*>& process_list) { const auto process = SearchProcessList(process_list, [](const auto& proc) { - return proc->GetProcessID() == Kernel::KProcess::ProcessIDMin; + return proc->GetProcessId() == Kernel::KProcess::ProcessIDMin; }); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process.has_value() ? (*process)->GetProcessID() : NO_PROCESS_FOUND_PID); + rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID); } } // Anonymous namespace @@ -57,7 +58,7 @@ public: } private: - void GetBootMode(Kernel::HLERequestContext& ctx) { + void GetBootMode(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -65,7 +66,7 @@ private: rb.PushEnum(boot_mode); } - void SetMaintenanceBoot(Kernel::HLERequestContext& ctx) { + void SetMaintenanceBoot(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); boot_mode = SystemBootMode::Maintenance; @@ -99,7 +100,7 @@ public: } private: - void GetProcessId(Kernel::HLERequestContext& ctx) { + void GetProcessId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto program_id = rp.PopRaw<u64>(); @@ -107,7 +108,7 @@ private: const auto process = SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { - return proc->GetProgramID() == program_id; + return proc->GetProgramId() == program_id; }); if (!process.has_value()) { @@ -118,15 +119,15 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push((*process)->GetProcessID()); + rb.Push((*process)->GetProcessId()); } - void GetApplicationProcessId(Kernel::HLERequestContext& ctx) { + void GetApplicationProcessId(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); GetApplicationPidGeneric(ctx, kernel.GetProcessList()); } - void AtmosphereGetProcessInfo(Kernel::HLERequestContext& ctx) { + void AtmosphereGetProcessInfo(HLERequestContext& ctx) { // https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/pm/source/impl/pm_process_manager.cpp#L614 // This implementation is incomplete; only a handle to the process is returned. IPC::RequestParser rp{ctx}; @@ -135,7 +136,7 @@ private: LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) { - return proc->GetProcessID() == pid; + return proc->GetProcessId() == pid; }); if (!process.has_value()) { @@ -158,7 +159,7 @@ private: OverrideStatus override_status{}; ProgramLocation program_location{ - .program_id = (*process)->GetProgramID(), + .program_id = (*process)->GetProgramId(), .storage_id = 0, }; @@ -186,14 +187,14 @@ public: } private: - void GetProgramId(Kernel::HLERequestContext& ctx) { + void GetProgramId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw<u64>(); LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { - return proc->GetProcessID() == process_id; + return proc->GetProcessId() == process_id; }); if (!process.has_value()) { @@ -204,17 +205,17 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push((*process)->GetProgramID()); + rb.Push((*process)->GetProgramId()); } - void AtmosphereGetProcessId(Kernel::HLERequestContext& ctx) { + void AtmosphereGetProcessId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto program_id = rp.PopRaw<u64>(); LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { - return proc->GetProgramID() == program_id; + return proc->GetProgramId() == program_id; }); if (!process.has_value()) { @@ -225,7 +226,7 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push((*process)->GetProcessID()); + rb.Push((*process)->GetProcessId()); } const std::vector<Kernel::KProcess*>& process_list; @@ -254,7 +255,7 @@ public: } private: - void GetApplicationProcessIdForShell(Kernel::HLERequestContext& ctx) { + void GetApplicationProcessIdForShell(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); GetApplicationPidGeneric(ctx, kernel.GetProcessList()); } @@ -262,12 +263,15 @@ private: const Kernel::KernelCore& kernel; }; -void InstallInterfaces(Core::System& system) { - std::make_shared<BootMode>(system)->InstallAsService(system.ServiceManager()); - std::make_shared<DebugMonitor>(system)->InstallAsService(system.ServiceManager()); - std::make_shared<Info>(system, system.Kernel().GetProcessList()) - ->InstallAsService(system.ServiceManager()); - std::make_shared<Shell>(system)->InstallAsService(system.ServiceManager()); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system)); + server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); + server_manager->RegisterNamedService( + "pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList())); + server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PM diff --git a/src/core/hle/service/pm/pm.h b/src/core/hle/service/pm/pm.h index 060103928..5d4a1a171 100644 --- a/src/core/hle/service/pm/pm.h +++ b/src/core/hle/service/pm/pm.h @@ -14,7 +14,6 @@ enum class SystemBootMode { Maintenance, }; -/// Registers all PM services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PM diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index 78f897d3e..ec4a84989 100644 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp @@ -4,9 +4,10 @@ #include "common/hex_util.h" #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/prepo/prepo.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/reporter.h" @@ -53,7 +54,7 @@ public: private: template <Core::Reporter::PlayReportType Type> - void SaveReport(Kernel::HLERequestContext& ctx) { + void SaveReport(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw<u64>(); @@ -63,7 +64,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, @@ -71,7 +72,7 @@ private: Type, process_id, data1.size(), data2.size()); const auto& reporter{system.GetReporter()}; - reporter.SavePlayReport(Type, system.GetCurrentProcessProgramID(), {data1, data2}, + reporter.SavePlayReport(Type, system.GetApplicationProcessProgramID(), {data1, data2}, process_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -79,7 +80,7 @@ private: } template <Core::Reporter::PlayReportType Type> - void SaveReportWithUser(Kernel::HLERequestContext& ctx) { + void SaveReportWithUser(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto user_id = rp.PopRaw<u128>(); const auto process_id = rp.PopRaw<u64>(); @@ -90,7 +91,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, @@ -99,21 +100,21 @@ private: Type, user_id[1], user_id[0], process_id, data1.size(), data2.size()); const auto& reporter{system.GetReporter()}; - reporter.SavePlayReport(Type, system.GetCurrentProcessProgramID(), {data1, data2}, + reporter.SavePlayReport(Type, system.GetApplicationProcessProgramID(), {data1, data2}, process_id, user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void RequestImmediateTransmission(Kernel::HLERequestContext& ctx) { + void RequestImmediateTransmission(HLERequestContext& ctx) { LOG_WARNING(Service_PREPO, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void GetTransmissionStatus(Kernel::HLERequestContext& ctx) { + void GetTransmissionStatus(HLERequestContext& ctx) { LOG_WARNING(Service_PREPO, "(STUBBED) called"); constexpr s32 status = 0; @@ -123,7 +124,7 @@ private: rb.Push(status); } - void GetSystemSessionId(Kernel::HLERequestContext& ctx) { + void GetSystemSessionId(HLERequestContext& ctx) { LOG_WARNING(Service_PREPO, "(STUBBED) called"); constexpr u64 system_session_id = 0; @@ -132,7 +133,7 @@ private: rb.Push(system_session_id); } - void SaveSystemReport(Kernel::HLERequestContext& ctx) { + void SaveSystemReport(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); @@ -142,7 +143,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, "called, title_id={:016X}, data1_size={:016X}, data2_size={:016X}", @@ -155,7 +156,7 @@ private: rb.Push(ResultSuccess); } - void SaveSystemReportWithUser(Kernel::HLERequestContext& ctx) { + void SaveSystemReportWithUser(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto user_id = rp.PopRaw<u128>(); const auto title_id = rp.PopRaw<u64>(); @@ -166,7 +167,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, @@ -183,12 +184,20 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<PlayReport>("prepo:a", system)->InstallAsService(service_manager); - std::make_shared<PlayReport>("prepo:a2", system)->InstallAsService(service_manager); - std::make_shared<PlayReport>("prepo:m", system)->InstallAsService(service_manager); - std::make_shared<PlayReport>("prepo:s", system)->InstallAsService(service_manager); - std::make_shared<PlayReport>("prepo:u", system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("prepo:a", + std::make_shared<PlayReport>("prepo:a", system)); + server_manager->RegisterNamedService("prepo:a2", + std::make_shared<PlayReport>("prepo:a2", system)); + server_manager->RegisterNamedService("prepo:m", + std::make_shared<PlayReport>("prepo:m", system)); + server_manager->RegisterNamedService("prepo:s", + std::make_shared<PlayReport>("prepo:s", system)); + server_manager->RegisterNamedService("prepo:u", + std::make_shared<PlayReport>("prepo:u", system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PlayReport diff --git a/src/core/hle/service/prepo/prepo.h b/src/core/hle/service/prepo/prepo.h index 37ea5afad..2c2462f93 100644 --- a/src/core/hle/service/prepo/prepo.h +++ b/src/core/hle/service/prepo/prepo.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::PlayReport { -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PlayReport diff --git a/src/core/hle/service/psc/psc.cpp b/src/core/hle/service/psc/psc.cpp index 3a9412cf5..cd0cc9287 100644 --- a/src/core/hle/service/psc/psc.cpp +++ b/src/core/hle/service/psc/psc.cpp @@ -4,16 +4,16 @@ #include <memory> #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/psc.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" namespace Service::PSC { -class PSC_C final : public ServiceFramework<PSC_C> { +class IPmControl final : public ServiceFramework<IPmControl> { public: - explicit PSC_C(Core::System& system_) : ServiceFramework{system_, "psc:c"} { + explicit IPmControl(Core::System& system_) : ServiceFramework{system_, "psc:c"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -23,8 +23,8 @@ public: {4, nullptr, "Cancel"}, {5, nullptr, "PrintModuleInformation"}, {6, nullptr, "GetModuleInformation"}, - {10, nullptr, "Unknown10"}, - {11, nullptr, "Unknown11"}, + {10, nullptr, "AcquireStateLock"}, + {11, nullptr, "HasStateLock"}, }; // clang-format on @@ -49,12 +49,12 @@ public: } }; -class PSC_M final : public ServiceFramework<PSC_M> { +class IPmService final : public ServiceFramework<IPmService> { public: - explicit PSC_M(Core::System& system_) : ServiceFramework{system_, "psc:m"} { + explicit IPmService(Core::System& system_) : ServiceFramework{system_, "psc:m"} { // clang-format off static const FunctionInfo functions[] = { - {0, &PSC_M::GetPmModule, "GetPmModule"}, + {0, &IPmService::GetPmModule, "GetPmModule"}, }; // clang-format on @@ -62,7 +62,7 @@ public: } private: - void GetPmModule(Kernel::HLERequestContext& ctx) { + void GetPmModule(HLERequestContext& ctx) { LOG_DEBUG(Service_PSC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -71,9 +71,12 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<PSC_C>(system)->InstallAsService(sm); - std::make_shared<PSC_M>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("psc:c", std::make_shared<IPmControl>(system)); + server_manager->RegisterNamedService("psc:m", std::make_shared<IPmService>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PSC diff --git a/src/core/hle/service/psc/psc.h b/src/core/hle/service/psc/psc.h index d248372c2..459137f42 100644 --- a/src/core/hle/service/psc/psc.h +++ b/src/core/hle/service/psc/psc.h @@ -13,6 +13,6 @@ class ServiceManager; namespace Service::PSC { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PSC diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 1ac97fe31..136313d7b 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -5,8 +5,8 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/ptm/psm.h" @@ -54,7 +54,7 @@ public: } private: - void BindStateChangeEvent(Kernel::HLERequestContext& ctx) { + void BindStateChangeEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_PTM, "called"); should_signal = true; @@ -64,7 +64,7 @@ private: rb.PushCopyObjects(state_change_event->GetReadableEvent()); } - void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) { + void UnbindStateChangeEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_PTM, "called"); should_signal = false; @@ -73,7 +73,7 @@ private: rb.Push(ResultSuccess); } - void SetChargerTypeChangeEventEnabled(Kernel::HLERequestContext& ctx) { + void SetChargerTypeChangeEventEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto state = rp.Pop<bool>(); LOG_DEBUG(Service_PTM, "called, state={}", state); @@ -84,7 +84,7 @@ private: rb.Push(ResultSuccess); } - void SetPowerSupplyChangeEventEnabled(Kernel::HLERequestContext& ctx) { + void SetPowerSupplyChangeEventEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto state = rp.Pop<bool>(); LOG_DEBUG(Service_PTM, "called, state={}", state); @@ -95,7 +95,7 @@ private: rb.Push(ResultSuccess); } - void SetBatteryVoltageStateChangeEventEnabled(Kernel::HLERequestContext& ctx) { + void SetBatteryVoltageStateChangeEventEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto state = rp.Pop<bool>(); LOG_DEBUG(Service_PTM, "called, state={}", state); @@ -145,7 +145,7 @@ PSM::PSM(Core::System& system_) : ServiceFramework{system_, "psm"} { PSM::~PSM() = default; -void PSM::GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) { +void PSM::GetBatteryChargePercentage(HLERequestContext& ctx) { LOG_DEBUG(Service_PTM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -153,7 +153,7 @@ void PSM::GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) { rb.Push<u32>(battery_charge_percentage); } -void PSM::GetChargerType(Kernel::HLERequestContext& ctx) { +void PSM::GetChargerType(HLERequestContext& ctx) { LOG_DEBUG(Service_PTM, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -161,7 +161,7 @@ void PSM::GetChargerType(Kernel::HLERequestContext& ctx) { rb.PushEnum(charger_type); } -void PSM::OpenSession(Kernel::HLERequestContext& ctx) { +void PSM::OpenSession(HLERequestContext& ctx) { LOG_DEBUG(Service_PTM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; diff --git a/src/core/hle/service/ptm/psm.h b/src/core/hle/service/ptm/psm.h index f674ba8bc..fa47919e5 100644 --- a/src/core/hle/service/ptm/psm.h +++ b/src/core/hle/service/ptm/psm.h @@ -20,9 +20,9 @@ private: Unknown = 3, }; - void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx); - void GetChargerType(Kernel::HLERequestContext& ctx); - void OpenSession(Kernel::HLERequestContext& ctx); + void GetBatteryChargePercentage(HLERequestContext& ctx); + void GetChargerType(HLERequestContext& ctx); + void OpenSession(HLERequestContext& ctx); u32 battery_charge_percentage{100}; ChargerType charger_type{ChargerType::RegularCharger}; diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 4bea995c6..6f0cfe04b 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -7,12 +7,16 @@ #include "core/hle/service/ptm/psm.h" #include "core/hle/service/ptm/ptm.h" #include "core/hle/service/ptm/ts.h" +#include "core/hle/service/server_manager.h" namespace Service::PTM { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<PSM>(system)->InstallAsService(sm); - std::make_shared<TS>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("psm", std::make_shared<PSM>(system)); + server_manager->RegisterNamedService("ts", std::make_shared<TS>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::PTM diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 06224a24e..a0ae03d28 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::PTM { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::PTM diff --git a/src/core/hle/service/ptm/ts.cpp b/src/core/hle/service/ptm/ts.cpp index b1a0a5544..ca064dd90 100644 --- a/src/core/hle/service/ptm/ts.cpp +++ b/src/core/hle/service/ptm/ts.cpp @@ -4,7 +4,7 @@ #include <memory> #include "core/core.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ptm/ts.h" namespace Service::PTM { @@ -25,7 +25,7 @@ TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} { TS::~TS() = default; -void TS::GetTemperature(Kernel::HLERequestContext& ctx) { +void TS::GetTemperature(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto location{rp.PopEnum<Location>()}; @@ -36,7 +36,7 @@ void TS::GetTemperature(Kernel::HLERequestContext& ctx) { rb.Push(temperature); } -void TS::GetTemperatureMilliC(Kernel::HLERequestContext& ctx) { +void TS::GetTemperatureMilliC(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto location{rp.PopEnum<Location>()}; diff --git a/src/core/hle/service/ptm/ts.h b/src/core/hle/service/ptm/ts.h index 39d51847e..c3f43d5a3 100644 --- a/src/core/hle/service/ptm/ts.h +++ b/src/core/hle/service/ptm/ts.h @@ -19,8 +19,8 @@ private: External, }; - void GetTemperature(Kernel::HLERequestContext& ctx); - void GetTemperatureMilliC(Kernel::HLERequestContext& ctx); + void GetTemperature(HLERequestContext& ctx); + void GetTemperatureMilliC(HLERequestContext& ctx); }; } // namespace Service::PTM diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp new file mode 100644 index 000000000..d1e99b184 --- /dev/null +++ b/src/core/hle/service/server_manager.cpp @@ -0,0 +1,451 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/scope_exit.h" + +#include "core/core.h" +#include "core/hle/kernel/k_client_port.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_object_name.h" +#include "core/hle/kernel/k_port.h" +#include "core/hle/kernel/k_server_port.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/kernel/svc_results.h" +#include "core/hle/service/hle_ipc.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" +#include "core/hle/service/sm/sm.h" + +namespace Service { + +constexpr size_t MaximumWaitObjects = 0x40; + +enum HandleType { + Port, + Session, + DeferEvent, + Event, +}; + +ServerManager::ServerManager(Core::System& system) : m_system{system}, m_serve_mutex{system} { + // Initialize event. + m_event = Kernel::KEvent::Create(system.Kernel()); + m_event->Initialize(nullptr); + + // Register event. + Kernel::KEvent::Register(system.Kernel(), m_event); +} + +ServerManager::~ServerManager() { + // Signal stop. + m_stop_source.request_stop(); + m_event->Signal(); + + // Wait for processing to stop. + m_stopped.Wait(); + m_threads.clear(); + + // Clean up ports. + for (const auto& [port, handler] : m_ports) { + port->Close(); + } + + // Clean up sessions. + for (const auto& [session, manager] : m_sessions) { + session->Close(); + } + + for (const auto& request : m_deferrals) { + request.session->Close(); + } + + // Close event. + m_event->GetReadableEvent().Close(); + m_event->Close(); + + if (m_deferral_event) { + m_deferral_event->GetReadableEvent().Close(); + // Write event is owned by ServiceManager + } +} + +void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) { + server_manager->m_system.RunServer(std::move(server_manager)); +} + +Result ServerManager::RegisterSession(Kernel::KServerSession* session, + std::shared_ptr<SessionRequestManager> manager) { + ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects); + + // We are taking ownership of the server session, so don't open it. + // Begin tracking the server session. + { + std::scoped_lock ll{m_list_mutex}; + m_sessions.emplace(session, std::move(manager)); + } + + // Signal the wakeup event. + m_event->Signal(); + + R_SUCCEED(); +} + +Result ServerManager::RegisterNamedService(const std::string& service_name, + std::shared_ptr<SessionRequestHandler>&& handler, + u32 max_sessions) { + ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects); + + // Add the new server to sm:. + ASSERT(R_SUCCEEDED( + m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); + + // Get the registered port. + auto port = m_system.ServiceManager().GetServicePort(service_name); + ASSERT(port.Succeeded()); + + // Open a new reference to the server port. + (*port)->GetServerPort().Open(); + + // Begin tracking the server port. + { + std::scoped_lock ll{m_list_mutex}; + m_ports.emplace(std::addressof((*port)->GetServerPort()), std::move(handler)); + } + + // Signal the wakeup event. + m_event->Signal(); + + R_SUCCEED(); +} + +Result ServerManager::ManageNamedPort(const std::string& service_name, + std::shared_ptr<SessionRequestHandler>&& handler, + u32 max_sessions) { + ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects); + + // Create a new port. + auto* port = Kernel::KPort::Create(m_system.Kernel()); + port->Initialize(max_sessions, false, 0); + + // Register the port. + Kernel::KPort::Register(m_system.Kernel(), port); + + // Ensure that our reference to the port is closed if we fail to register it. + SCOPE_EXIT({ + port->GetClientPort().Close(); + port->GetServerPort().Close(); + }); + + // Register the object name with the kernel. + R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()), + service_name.c_str())); + + // Open a new reference to the server port. + port->GetServerPort().Open(); + + // Begin tracking the server port. + { + std::scoped_lock ll{m_list_mutex}; + m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler)); + } + + // We succeeded. + R_SUCCEED(); +} + +Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) { + // Create a new event. + m_deferral_event = Kernel::KEvent::Create(m_system.Kernel()); + ASSERT(m_deferral_event != nullptr); + + // Initialize the event. + m_deferral_event->Initialize(nullptr); + + // Register the event. + Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event); + + // Set the output. + *out_event = m_deferral_event; + + // We succeeded. + R_SUCCEED(); +} + +void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) { + for (size_t i = 0; i < num_threads; i++) { + auto thread_name = fmt::format("{}:{}", name, i + 1); + m_threads.emplace_back(m_system.Kernel().RunOnHostCoreThread( + std::move(thread_name), [&] { this->LoopProcessImpl(); })); + } +} + +Result ServerManager::LoopProcess() { + SCOPE_EXIT({ m_stopped.Set(); }); + + R_RETURN(this->LoopProcessImpl()); +} + +Result ServerManager::LoopProcessImpl() { + while (!m_stop_source.stop_requested()) { + R_TRY(this->WaitAndProcessImpl()); + } + + R_SUCCEED(); +} + +Result ServerManager::WaitAndProcessImpl() { + Kernel::KScopedAutoObject<Kernel::KSynchronizationObject> wait_obj; + HandleType wait_type{}; + + // Ensure we are the only thread waiting for this server. + std::unique_lock sl{m_serve_mutex}; + + // If we're done, return before we start waiting. + R_SUCCEED_IF(m_stop_source.stop_requested()); + + // Wait for a tracked object to become signaled. + { + s32 num_objs{}; + std::array<HandleType, MaximumWaitObjects> wait_types{}; + std::array<Kernel::KSynchronizationObject*, MaximumWaitObjects> wait_objs{}; + + const auto AddWaiter{ + [&](Kernel::KSynchronizationObject* synchronization_object, HandleType type) { + // Open a new reference to the object. + synchronization_object->Open(); + + // Insert into the list. + wait_types[num_objs] = type; + wait_objs[num_objs++] = synchronization_object; + }}; + + { + std::scoped_lock ll{m_list_mutex}; + + // Add all of our ports. + for (const auto& [port, handler] : m_ports) { + AddWaiter(port, HandleType::Port); + } + + // Add all of our sessions. + for (const auto& [session, manager] : m_sessions) { + AddWaiter(session, HandleType::Session); + } + } + + // Add the deferral wakeup event. + if (m_deferral_event != nullptr) { + AddWaiter(std::addressof(m_deferral_event->GetReadableEvent()), HandleType::DeferEvent); + } + + // Add the wakeup event. + AddWaiter(std::addressof(m_event->GetReadableEvent()), HandleType::Event); + + // Clean up extra references on exit. + SCOPE_EXIT({ + for (s32 i = 0; i < num_objs; i++) { + wait_objs[i]->Close(); + } + }); + + // Wait for a signal. + s32 out_index{-1}; + R_TRY(Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &out_index, wait_objs.data(), + num_objs, -1)); + ASSERT(out_index >= 0 && out_index < num_objs); + + // Set the output index. + wait_obj = wait_objs[out_index]; + wait_type = wait_types[out_index]; + } + + // Process what we just received, temporarily removing the object so it is + // not processed concurrently by another thread. + { + switch (wait_type) { + case HandleType::Port: { + // Port signaled. + auto* port = wait_obj->DynamicCast<Kernel::KServerPort*>(); + std::shared_ptr<SessionRequestHandler> handler; + + // Remove from tracking. + { + std::scoped_lock ll{m_list_mutex}; + ASSERT(m_ports.contains(port)); + m_ports.at(port).swap(handler); + m_ports.erase(port); + } + + // Allow other threads to serve. + sl.unlock(); + + // Finish. + R_RETURN(this->OnPortEvent(port, std::move(handler))); + } + case HandleType::Session: { + // Session signaled. + auto* session = wait_obj->DynamicCast<Kernel::KServerSession*>(); + std::shared_ptr<SessionRequestManager> manager; + + // Remove from tracking. + { + std::scoped_lock ll{m_list_mutex}; + ASSERT(m_sessions.contains(session)); + m_sessions.at(session).swap(manager); + m_sessions.erase(session); + } + + // Allow other threads to serve. + sl.unlock(); + + // Finish. + R_RETURN(this->OnSessionEvent(session, std::move(manager))); + } + case HandleType::DeferEvent: { + // Clear event. + ASSERT(R_SUCCEEDED(m_deferral_event->Clear())); + + // Drain the list of deferrals while we process. + std::list<RequestState> deferrals; + { + std::scoped_lock ll{m_list_mutex}; + m_deferrals.swap(deferrals); + } + + // Allow other threads to serve. + sl.unlock(); + + // Finish. + R_RETURN(this->OnDeferralEvent(std::move(deferrals))); + } + case HandleType::Event: { + // Clear event and finish. + R_RETURN(m_event->Clear()); + } + default: { + UNREACHABLE(); + } + } + } +} + +Result ServerManager::OnPortEvent(Kernel::KServerPort* port, + std::shared_ptr<SessionRequestHandler>&& handler) { + // Accept a new server session. + Kernel::KServerSession* session = port->AcceptSession(); + ASSERT(session != nullptr); + + // Create the session manager and install the handler. + auto manager = std::make_shared<SessionRequestManager>(m_system.Kernel(), *this); + manager->SetSessionHandler(std::shared_ptr(handler)); + + // Track the server session. + { + std::scoped_lock ll{m_list_mutex}; + m_ports.emplace(port, std::move(handler)); + m_sessions.emplace(session, std::move(manager)); + } + + // Signal the wakeup event. + m_event->Signal(); + + // We succeeded. + R_SUCCEED(); +} + +Result ServerManager::OnSessionEvent(Kernel::KServerSession* session, + std::shared_ptr<SessionRequestManager>&& manager) { + Result rc{ResultSuccess}; + + // Try to receive a message. + std::shared_ptr<HLERequestContext> context; + rc = session->ReceiveRequest(&context, manager); + + // If the session has been closed, we're done. + if (rc == Kernel::ResultSessionClosed) { + // Close the session. + session->Close(); + + // Finish. + R_SUCCEED(); + } + ASSERT(R_SUCCEEDED(rc)); + + RequestState request{ + .session = session, + .context = std::move(context), + .manager = std::move(manager), + }; + + // Complete the sync request with deferral handling. + R_RETURN(this->CompleteSyncRequest(std::move(request))); +} + +Result ServerManager::CompleteSyncRequest(RequestState&& request) { + Result rc{ResultSuccess}; + Result service_rc{ResultSuccess}; + + // Mark the request as not deferred. + request.context->SetIsDeferred(false); + + // Complete the request. We have exclusive access to this session. + service_rc = request.manager->CompleteSyncRequest(request.session, *request.context); + + // If we've been deferred, we're done. + if (request.context->GetIsDeferred()) { + // Insert into deferral list. + std::scoped_lock ll{m_list_mutex}; + m_deferrals.emplace_back(std::move(request)); + + // Finish. + R_SUCCEED(); + } + + // Send the reply. + rc = request.session->SendReplyHLE(); + + // If the session has been closed, we're done. + if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ResultSessionClosed) { + // Close the session. + request.session->Close(); + + // Finish. + R_SUCCEED(); + } + + ASSERT(R_SUCCEEDED(rc)); + ASSERT(R_SUCCEEDED(service_rc)); + + // Reinsert the session. + { + std::scoped_lock ll{m_list_mutex}; + m_sessions.emplace(request.session, std::move(request.manager)); + } + + // Signal the wakeup event. + m_event->Signal(); + + // We succeeded. + R_SUCCEED(); +} + +Result ServerManager::OnDeferralEvent(std::list<RequestState>&& deferrals) { + ON_RESULT_FAILURE { + std::scoped_lock ll{m_list_mutex}; + m_deferrals.splice(m_deferrals.end(), deferrals); + }; + + while (!deferrals.empty()) { + RequestState request = deferrals.front(); + deferrals.pop_front(); + + // Try again to complete the request. + R_TRY(this->CompleteSyncRequest(std::move(request))); + } + + R_SUCCEED(); +} + +} // namespace Service diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h new file mode 100644 index 000000000..58b0a0832 --- /dev/null +++ b/src/core/hle/service/server_manager.h @@ -0,0 +1,90 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <functional> +#include <list> +#include <map> +#include <mutex> +#include <string_view> +#include <vector> + +#include "common/polyfill_thread.h" +#include "common/thread.h" +#include "core/hle/result.h" +#include "core/hle/service/mutex.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KEvent; +class KServerPort; +class KServerSession; +class KSynchronizationObject; +} // namespace Kernel + +namespace Service { + +class HLERequestContext; +class SessionRequestHandler; +class SessionRequestManager; + +class ServerManager { +public: + explicit ServerManager(Core::System& system); + ~ServerManager(); + + Result RegisterSession(Kernel::KServerSession* session, + std::shared_ptr<SessionRequestManager> manager); + Result RegisterNamedService(const std::string& service_name, + std::shared_ptr<SessionRequestHandler>&& handler, + u32 max_sessions = 64); + Result ManageNamedPort(const std::string& service_name, + std::shared_ptr<SessionRequestHandler>&& handler, u32 max_sessions = 64); + Result ManageDeferral(Kernel::KEvent** out_event); + + Result LoopProcess(); + void StartAdditionalHostThreads(const char* name, size_t num_threads); + + static void RunServer(std::unique_ptr<ServerManager>&& server); + +private: + struct RequestState; + + Result LoopProcessImpl(); + Result WaitAndProcessImpl(); + Result OnPortEvent(Kernel::KServerPort* port, std::shared_ptr<SessionRequestHandler>&& handler); + Result OnSessionEvent(Kernel::KServerSession* session, + std::shared_ptr<SessionRequestManager>&& manager); + Result OnDeferralEvent(std::list<RequestState>&& deferrals); + Result CompleteSyncRequest(RequestState&& state); + +private: + Core::System& m_system; + Mutex m_serve_mutex; + std::mutex m_list_mutex; + + // Guest state tracking + std::map<Kernel::KServerPort*, std::shared_ptr<SessionRequestHandler>> m_ports{}; + std::map<Kernel::KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions{}; + Kernel::KEvent* m_event{}; + Kernel::KEvent* m_deferral_event{}; + + // Deferral tracking + struct RequestState { + Kernel::KServerSession* session; + std::shared_ptr<HLERequestContext> context; + std::shared_ptr<SessionRequestManager> manager; + }; + std::list<RequestState> m_deferrals{}; + + // Host state tracking + Common::Event m_stopped{}; + std::vector<std::jthread> m_threads{}; + std::stop_source m_stop_source{}; +}; + +} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 0de67f1e1..69cdb5918 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -7,7 +7,6 @@ #include "common/settings.h" #include "core/core.h" #include "core/hle/ipc.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_server_port.h" #include "core/hle/kernel/kernel.h" @@ -31,6 +30,7 @@ #include "core/hle/service/glue/glue.h" #include "core/hle/service/grc/grc.h" #include "core/hle/service/hid/hid.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/jit/jit.h" #include "core/hle/service/lbl/lbl.h" #include "core/hle/service/ldn/ldn.h" @@ -49,8 +49,8 @@ #include "core/hle/service/npns/npns.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvflinger/nvflinger.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" #include "core/hle/service/olsc/olsc.h" #include "core/hle/service/pcie/pcie.h" #include "core/hle/service/pctl/pctl_module.h" @@ -68,7 +68,6 @@ #include "core/hle/service/time/time.h" #include "core/hle/service/usb/usb.h" #include "core/hle/service/vi/vi.h" -#include "core/hle/service/wlan/wlan.h" #include "core/reporter.h" namespace Service { @@ -91,44 +90,13 @@ namespace Service { } ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, - ServiceThreadType thread_type, u32 max_sessions_, - InvokerFn* handler_invoker_) - : SessionRequestHandler(system_.Kernel(), service_name_, thread_type), system{system_}, + u32 max_sessions_, InvokerFn* handler_invoker_) + : SessionRequestHandler(system_.Kernel(), service_name_), system{system_}, service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {} ServiceFrameworkBase::~ServiceFrameworkBase() { // Wait for other threads to release access before destroying const auto guard = LockService(); - - if (named_port != nullptr) { - named_port->GetClientPort().Close(); - named_port->GetServerPort().Close(); - named_port = nullptr; - } -} - -void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) { - const auto guard = LockService(); - - ASSERT(!service_registered); - - service_manager.RegisterService(service_name, max_sessions, shared_from_this()); - service_registered = true; -} - -Kernel::KClientPort& ServiceFrameworkBase::CreatePort() { - const auto guard = LockService(); - - if (named_port == nullptr) { - ASSERT(!service_registered); - - named_port = Kernel::KPort::Create(kernel); - named_port->Initialize(max_sessions, false, service_name); - - service_registered = true; - } - - return named_port->GetClientPort(); } void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { @@ -149,7 +117,7 @@ void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* func } } -void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, +void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info) { auto cmd_buf = ctx.CommandBuffer(); std::string function_name = info == nullptr ? fmt::format("{}", ctx.GetCommand()) : info->name; @@ -172,7 +140,7 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext } } -void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { +void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) { auto itr = handlers.find(ctx.GetCommand()); const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second; if (info == nullptr || info->handler_callback == nullptr) { @@ -183,7 +151,7 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { handler_invoker(this, info->handler_callback, ctx); } -void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) { +void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) { boost::container::flat_map<u32, FunctionInfoBase>::iterator itr; itr = handlers_tipc.find(ctx.GetCommand()); @@ -198,7 +166,7 @@ void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) { } Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, - Kernel::HLERequestContext& ctx) { + HLERequestContext& ctx) { const auto guard = LockService(); Result result = ResultSuccess; @@ -208,7 +176,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, case IPC::CommandType::TIPC_Close: { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); - result = IPC::ERR_REMOTE_PROCESS_DEAD; + result = IPC::ResultSessionClosed; break; } case IPC::CommandType::ControlWithContext: @@ -242,71 +210,72 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, /// Initialize Services Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) - : hos_binder_driver_server{std::make_unique<NVFlinger::HosBinderDriverServer>(system)}, - nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system, *hos_binder_driver_server)} { + : hos_binder_driver_server{std::make_unique<Nvnflinger::HosBinderDriverServer>(system)}, + nv_flinger{std::make_unique<Nvnflinger::Nvnflinger>(system, *hos_binder_driver_server)} { - // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it - // here and pass it into the respective InstallInterfaces functions. + auto& kernel = system.Kernel(); + // Nvnflinger needs to be accessed by several services like Vi and AppletOE so we instantiate it + // here and pass it into the respective InstallInterfaces functions. system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); - system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory); - system.Kernel().RegisterInterfaceForNamedService("sm:", SM::ServiceManager::SessionHandler); - - Account::InstallInterfaces(system); - AM::InstallInterfaces(*sm, *nv_flinger, system); - AOC::InstallInterfaces(*sm, system); - APM::InstallInterfaces(system); - Audio::InstallInterfaces(*sm, system); - BCAT::InstallInterfaces(system); - BPC::InstallInterfaces(*sm, system); - BtDrv::InstallInterfaces(*sm, system); - BTM::InstallInterfaces(*sm, system); - Capture::InstallInterfaces(*sm, system); - ERPT::InstallInterfaces(*sm, system); - ES::InstallInterfaces(*sm, system); - EUPLD::InstallInterfaces(*sm, system); - Fatal::InstallInterfaces(*sm, system); - FGM::InstallInterfaces(*sm, system); - FileSystem::InstallInterfaces(system); - Friend::InstallInterfaces(*sm, system); - Glue::InstallInterfaces(system); - GRC::InstallInterfaces(*sm, system); - HID::InstallInterfaces(*sm, system); - JIT::InstallInterfaces(*sm, system); - LBL::InstallInterfaces(*sm, system); - LDN::InstallInterfaces(*sm, system); - LDR::InstallInterfaces(*sm, system); - LM::InstallInterfaces(system); - Migration::InstallInterfaces(*sm, system); - Mii::InstallInterfaces(*sm, system); - MM::InstallInterfaces(*sm, system); - MNPP::InstallInterfaces(*sm, system); - NCM::InstallInterfaces(*sm, system); - NFC::InstallInterfaces(*sm, system); - NFP::InstallInterfaces(*sm, system); - NGCT::InstallInterfaces(*sm, system); - NIFM::InstallInterfaces(*sm, system); - NIM::InstallInterfaces(*sm, system); - NPNS::InstallInterfaces(*sm, system); - NS::InstallInterfaces(*sm, system); - Nvidia::InstallInterfaces(*sm, *nv_flinger, system); - OLSC::InstallInterfaces(*sm, system); - PCIe::InstallInterfaces(*sm, system); - PCTL::InstallInterfaces(*sm, system); - PCV::InstallInterfaces(*sm, system); - PlayReport::InstallInterfaces(*sm, system); - PM::InstallInterfaces(system); - PSC::InstallInterfaces(*sm, system); - PTM::InstallInterfaces(*sm, system); - Set::InstallInterfaces(*sm, system); - Sockets::InstallInterfaces(*sm, system); - SPL::InstallInterfaces(*sm, system); - SSL::InstallInterfaces(*sm, system); - Time::InstallInterfaces(system); - USB::InstallInterfaces(*sm, system); - VI::InstallInterfaces(*sm, system, *nv_flinger, *hos_binder_driver_server); - WLAN::InstallInterfaces(*sm, system); + // clang-format off + kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach(); + kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("vi", [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach(); + + kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(*nv_flinger, system); }); + kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ngct", [&] { NGCT::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("time", [&] { Time::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); }); + // clang-format on } Services::~Services() = default; diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 22e2119d7..45b2c43b7 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -8,7 +8,7 @@ #include <string> #include <boost/container/flat_map.hpp> #include "common/common_types.h" -#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/hle_ipc.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Service @@ -18,9 +18,6 @@ class System; } namespace Kernel { -class HLERequestContext; -class KClientPort; -class KPort; class KServerSession; class ServiceThread; } // namespace Kernel @@ -31,10 +28,10 @@ namespace FileSystem { class FileSystemController; } -namespace NVFlinger { +namespace Nvnflinger { class HosBinderDriverServer; -class NVFlinger; -} // namespace NVFlinger +class Nvnflinger; +} // namespace Nvnflinger namespace SM { class ServiceManager; @@ -52,7 +49,7 @@ static_assert(ServerSessionCountMax == 0x40, * * @see ServiceFramework */ -class ServiceFrameworkBase : public Kernel::SessionRequestHandler { +class ServiceFrameworkBase : public SessionRequestHandler { public: /// Returns the string identifier used to connect to the service. std::string GetServiceName() const { @@ -67,26 +64,19 @@ public: return max_sessions; } - /// Creates a port pair and registers this service with the given ServiceManager. - void InstallAsService(SM::ServiceManager& service_manager); - /// Invokes a service request routine using the HIPC protocol. - void InvokeRequest(Kernel::HLERequestContext& ctx); + void InvokeRequest(HLERequestContext& ctx); /// Invokes a service request routine using the HIPC protocol. - void InvokeRequestTipc(Kernel::HLERequestContext& ctx); - - /// Creates a port pair and registers it on the kernel's global port registry. - Kernel::KClientPort& CreatePort(); + void InvokeRequestTipc(HLERequestContext& ctx); /// Handles a synchronization request for the service. - Result HandleSyncRequest(Kernel::KServerSession& session, - Kernel::HLERequestContext& context) override; + Result HandleSyncRequest(Kernel::KServerSession& session, HLERequestContext& context) override; protected: /// Member-function pointer type of SyncRequest handlers. template <typename Self> - using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&); + using HandlerFnP = void (Self::*)(HLERequestContext&); /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. [[nodiscard]] std::scoped_lock<std::mutex> LockService() { @@ -99,9 +89,6 @@ protected: /// Identifier string used to connect to the service. std::string service_name; - /// Port used by ManageNamedPort. - Kernel::KPort* named_port{}; - private: template <typename T> friend class ServiceFramework; @@ -113,16 +100,15 @@ private: }; using InvokerFn = void(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member, - Kernel::HLERequestContext& ctx); + HLERequestContext& ctx); explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_, - ServiceThreadType thread_type, u32 max_sessions_, - InvokerFn* handler_invoker_); + u32 max_sessions_, InvokerFn* handler_invoker_); ~ServiceFrameworkBase() override; void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n); - void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); + void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info); /// Maximum number of concurrent sessions that this service can handle. u32 max_sessions; @@ -156,7 +142,8 @@ template <typename Self> class ServiceFramework : public ServiceFrameworkBase { protected: /// Contains information about a request type which is handled by the service. - struct FunctionInfo : FunctionInfoBase { + template <typename T> + struct FunctionInfoTyped : FunctionInfoBase { // TODO(yuriks): This function could be constexpr, but clang is the only compiler that // doesn't emit an ICE or a wrong diagnostic because of the static_cast. @@ -169,31 +156,29 @@ protected: * the request * @param name_ human-friendly name for the request. Used mostly for logging purposes. */ - FunctionInfo(u32 expected_header_, HandlerFnP<Self> handler_callback_, const char* name_) + FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_) : FunctionInfoBase{ expected_header_, // Type-erase member function pointer by casting it down to the base class. static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {} }; + using FunctionInfo = FunctionInfoTyped<Self>; /** * Initializes the handler with no functions installed. * * @param system_ The system context to construct this service under. * @param service_name_ Name of the service. - * @param thread_type Specifies the thread type for this service. If this is set to CreateNew, - * it creates a new thread for it, otherwise this uses the default thread. * @param max_sessions_ Maximum number of sessions that can be connected to this service at the * same time. */ explicit ServiceFramework(Core::System& system_, const char* service_name_, - ServiceThreadType thread_type = ServiceThreadType::Default, u32 max_sessions_ = ServerSessionCountMax) - : ServiceFrameworkBase(system_, service_name_, thread_type, max_sessions_, Invoker) {} + : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {} /// Registers handlers in the service. - template <std::size_t N> - void RegisterHandlers(const FunctionInfo (&functions)[N]) { + template <typename T = Self, std::size_t N> + void RegisterHandlers(const FunctionInfoTyped<T> (&functions)[N]) { RegisterHandlers(functions, N); } @@ -201,13 +186,14 @@ protected: * Registers handlers in the service. Usually prefer using the other RegisterHandlers * overload in order to avoid needing to specify the array size. */ - void RegisterHandlers(const FunctionInfo* functions, std::size_t n) { + template <typename T = Self> + void RegisterHandlers(const FunctionInfoTyped<T>* functions, std::size_t n) { RegisterHandlersBase(functions, n); } /// Registers handlers in the service. - template <std::size_t N> - void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) { + template <typename T = Self, std::size_t N> + void RegisterHandlersTipc(const FunctionInfoTyped<T> (&functions)[N]) { RegisterHandlersTipc(functions, N); } @@ -215,7 +201,8 @@ protected: * Registers handlers in the service. Usually prefer using the other RegisterHandlers * overload in order to avoid needing to specify the array size. */ - void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) { + template <typename T = Self> + void RegisterHandlersTipc(const FunctionInfoTyped<T>* functions, std::size_t n) { RegisterHandlersBaseTipc(functions, n); } @@ -227,7 +214,7 @@ private: * of the derived class in order to invoke one of it's functions through a pointer. */ static void Invoker(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member, - Kernel::HLERequestContext& ctx) { + HLERequestContext& ctx) { // Cast back up to our original types and call the member function (static_cast<Self*>(object)->*static_cast<HandlerFnP<Self>>(member))(ctx); } @@ -245,8 +232,8 @@ public: void KillNVNFlinger(); private: - std::unique_ptr<NVFlinger::HosBinderDriverServer> hos_binder_driver_server; - std::unique_ptr<NVFlinger::NVFlinger> nv_flinger; + std::unique_ptr<Nvnflinger::HosBinderDriverServer> hos_binder_driver_server; + std::unique_ptr<Nvnflinger::Nvnflinger> nv_flinger; }; } // namespace Service diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 16c5eaf75..f5788b481 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -6,7 +6,7 @@ #include <chrono> #include "common/logging/log.h" #include "common/settings.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/set/set.h" namespace Service::Set { @@ -74,15 +74,15 @@ constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_la constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; -constexpr Result ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625}; +constexpr Result ResultInvalidLanguage{ErrorModule::Settings, 625}; -void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_language_codes) { +void PushResponseLanguageCode(HLERequestContext& ctx, std::size_t num_language_codes) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(static_cast<u32>(num_language_codes)); } -void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t max_entries) { +void GetAvailableLanguageCodesImpl(HLERequestContext& ctx, std::size_t max_entries) { const std::size_t requested_amount = ctx.GetWriteBufferNumElements<LanguageCode>(); const std::size_t max_amount = std::min(requested_amount, max_entries); const std::size_t copy_amount = std::min(available_language_codes.size(), max_amount); @@ -92,7 +92,7 @@ void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t m PushResponseLanguageCode(ctx, copy_amount); } -void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) { +void GetKeyCodeMapImpl(HLERequestContext& ctx) { const auto language_code = available_language_codes[Settings::values.language_index.GetValue()]; const auto key_code = std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), @@ -117,20 +117,20 @@ LanguageCode GetLanguageCodeFromIndex(std::size_t index) { return available_language_codes.at(index); } -void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { +void SET::GetAvailableLanguageCodes(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); GetAvailableLanguageCodesImpl(ctx, PRE_4_0_0_MAX_ENTRIES); } -void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { +void SET::MakeLanguageCode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto index = rp.Pop<u32>(); if (index >= available_language_codes.size()) { LOG_ERROR(Service_SET, "Invalid language code index! index={}", index); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_INVALID_LANGUAGE); + rb.Push(Set::ResultInvalidLanguage); return; } @@ -139,25 +139,25 @@ void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { rb.PushEnum(available_language_codes[index]); } -void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) { +void SET::GetAvailableLanguageCodes2(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); GetAvailableLanguageCodesImpl(ctx, POST_4_0_0_MAX_ENTRIES); } -void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { +void SET::GetAvailableLanguageCodeCount(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); PushResponseLanguageCode(ctx, PRE_4_0_0_MAX_ENTRIES); } -void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) { +void SET::GetAvailableLanguageCodeCount2(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); PushResponseLanguageCode(ctx, POST_4_0_0_MAX_ENTRIES); } -void SET::GetQuestFlag(Kernel::HLERequestContext& ctx) { +void SET::GetQuestFlag(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -165,7 +165,7 @@ void SET::GetQuestFlag(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u32>(Settings::values.quest_flag.GetValue())); } -void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { +void SET::GetLanguageCode(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue()); IPC::ResponseBuilder rb{ctx, 4}; @@ -173,7 +173,7 @@ void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { rb.PushEnum(available_language_codes[Settings::values.language_index.GetValue()]); } -void SET::GetRegionCode(Kernel::HLERequestContext& ctx) { +void SET::GetRegionCode(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -181,17 +181,17 @@ void SET::GetRegionCode(Kernel::HLERequestContext& ctx) { rb.Push(Settings::values.region_index.GetValue()); } -void SET::GetKeyCodeMap(Kernel::HLERequestContext& ctx) { +void SET::GetKeyCodeMap(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "Called {}", ctx.Description()); GetKeyCodeMapImpl(ctx); } -void SET::GetKeyCodeMap2(Kernel::HLERequestContext& ctx) { +void SET::GetKeyCodeMap2(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "Called {}", ctx.Description()); GetKeyCodeMapImpl(ctx); } -void SET::GetDeviceNickName(Kernel::HLERequestContext& ctx) { +void SET::GetDeviceNickName(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h index 375975711..7fd3a7654 100644 --- a/src/core/hle/service/set/set.h +++ b/src/core/hle/service/set/set.h @@ -40,17 +40,17 @@ public: ~SET() override; private: - void GetLanguageCode(Kernel::HLERequestContext& ctx); - void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx); - void MakeLanguageCode(Kernel::HLERequestContext& ctx); - void GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx); - void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx); - void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx); - void GetQuestFlag(Kernel::HLERequestContext& ctx); - void GetRegionCode(Kernel::HLERequestContext& ctx); - void GetKeyCodeMap(Kernel::HLERequestContext& ctx); - void GetKeyCodeMap2(Kernel::HLERequestContext& ctx); - void GetDeviceNickName(Kernel::HLERequestContext& ctx); + void GetLanguageCode(HLERequestContext& ctx); + void GetAvailableLanguageCodes(HLERequestContext& ctx); + void MakeLanguageCode(HLERequestContext& ctx); + void GetAvailableLanguageCodes2(HLERequestContext& ctx); + void GetAvailableLanguageCodeCount(HLERequestContext& ctx); + void GetAvailableLanguageCodeCount2(HLERequestContext& ctx); + void GetQuestFlag(HLERequestContext& ctx); + void GetRegionCode(HLERequestContext& ctx); + void GetKeyCodeMap(HLERequestContext& ctx); + void GetKeyCodeMap2(HLERequestContext& ctx); + void GetDeviceNickName(HLERequestContext& ctx); }; } // namespace Service::Set diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 94c20edda..2e38d1cfc 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -6,8 +6,8 @@ #include "common/settings.h" #include "core/file_sys/errors.h" #include "core/file_sys/system_archive/system_version.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/set/set_sys.h" namespace Service::Set { @@ -20,7 +20,7 @@ enum class GetFirmwareVersionType { Version2, }; -void GetFirmwareVersionImpl(Kernel::HLERequestContext& ctx, GetFirmwareVersionType type) { +void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type) { LOG_WARNING(Service_SET, "called - Using hardcoded firmware version '{}'", FileSys::SystemArchive::GetLongDisplayVersion()); @@ -73,17 +73,17 @@ void GetFirmwareVersionImpl(Kernel::HLERequestContext& ctx, GetFirmwareVersionTy } } // Anonymous namespace -void SET_SYS::GetFirmwareVersion(Kernel::HLERequestContext& ctx) { +void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1); } -void SET_SYS::GetFirmwareVersion2(Kernel::HLERequestContext& ctx) { +void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2); } -void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) { +void SET_SYS::GetColorSetId(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -92,7 +92,7 @@ void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) { rb.PushEnum(color_set); } -void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) { +void SET_SYS::SetColorSetId(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::RequestParser rp{ctx}; @@ -126,7 +126,7 @@ static Settings GetSettings() { return ret; } -void SET_SYS::GetSettingsItemValueSize(Kernel::HLERequestContext& ctx) { +void SET_SYS::GetSettingsItemValueSize(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); // The category of the setting. This corresponds to the top-level keys of @@ -151,7 +151,7 @@ void SET_SYS::GetSettingsItemValueSize(Kernel::HLERequestContext& ctx) { rb.Push(response_size); } -void SET_SYS::GetSettingsItemValue(Kernel::HLERequestContext& ctx) { +void SET_SYS::GetSettingsItemValue(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); // The category of the setting. This corresponds to the top-level keys of @@ -177,7 +177,7 @@ void SET_SYS::GetSettingsItemValue(Kernel::HLERequestContext& ctx) { rb.Push(response); } -void SET_SYS::GetDeviceNickName(Kernel::HLERequestContext& ctx) { +void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index 464ac3da1..1efbcc97a 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -23,13 +23,13 @@ private: BasicBlack = 1, }; - void GetSettingsItemValueSize(Kernel::HLERequestContext& ctx); - void GetSettingsItemValue(Kernel::HLERequestContext& ctx); - void GetFirmwareVersion(Kernel::HLERequestContext& ctx); - void GetFirmwareVersion2(Kernel::HLERequestContext& ctx); - void GetColorSetId(Kernel::HLERequestContext& ctx); - void SetColorSetId(Kernel::HLERequestContext& ctx); - void GetDeviceNickName(Kernel::HLERequestContext& ctx); + void GetSettingsItemValueSize(HLERequestContext& ctx); + void GetSettingsItemValue(HLERequestContext& ctx); + void GetFirmwareVersion(HLERequestContext& ctx); + void GetFirmwareVersion2(HLERequestContext& ctx); + void GetColorSetId(HLERequestContext& ctx); + void SetColorSetId(HLERequestContext& ctx); + void GetDeviceNickName(HLERequestContext& ctx); ColorSet color_set = ColorSet::BasicWhite; }; diff --git a/src/core/hle/service/set/settings.cpp b/src/core/hle/service/set/settings.cpp index 4ebc2a0ec..c48844f77 100644 --- a/src/core/hle/service/set/settings.cpp +++ b/src/core/hle/service/set/settings.cpp @@ -1,20 +1,23 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/server_manager.h" #include "core/hle/service/set/set.h" #include "core/hle/service/set/set_cal.h" #include "core/hle/service/set/set_fd.h" #include "core/hle/service/set/set_sys.h" #include "core/hle/service/set/settings.h" -#include "core/hle/service/sm/sm.h" namespace Service::Set { -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<SET>(system)->InstallAsService(service_manager); - std::make_shared<SET_CAL>(system)->InstallAsService(service_manager); - std::make_shared<SET_FD>(system)->InstallAsService(service_manager); - std::make_shared<SET_SYS>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("set", std::make_shared<SET>(system)); + server_manager->RegisterNamedService("set:cal", std::make_shared<SET_CAL>(system)); + server_manager->RegisterNamedService("set:fd", std::make_shared<SET_FD>(system)); + server_manager->RegisterNamedService("set:sys", std::make_shared<SET_SYS>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Set diff --git a/src/core/hle/service/set/settings.h b/src/core/hle/service/set/settings.h index 6cd7d634c..03cd4bb66 100644 --- a/src/core/hle/service/set/settings.h +++ b/src/core/hle/service/set/settings.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::Set { -/// Registers all Settings services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Set diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 84720094f..1608fa24c 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -5,69 +5,73 @@ #include "common/assert.h" #include "common/scope_exit.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_client_session.h" #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_server_port.h" #include "core/hle/result.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm_controller.h" namespace Service::SM { -constexpr Result ERR_NOT_INITIALIZED(ErrorModule::SM, 2); -constexpr Result ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); -constexpr Result ERR_INVALID_NAME(ErrorModule::SM, 6); -constexpr Result ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); +constexpr Result ResultInvalidClient(ErrorModule::SM, 2); +constexpr Result ResultAlreadyRegistered(ErrorModule::SM, 4); +constexpr Result ResultInvalidServiceName(ErrorModule::SM, 6); +constexpr Result ResultNotRegistered(ErrorModule::SM, 7); -ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {} +ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} { + controller_interface = std::make_unique<Controller>(kernel.System()); +} ServiceManager::~ServiceManager() { for (auto& [name, port] : service_ports) { port->GetClientPort().Close(); port->GetServerPort().Close(); } + + if (deferral_event) { + deferral_event->Close(); + } } -void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) { +void ServiceManager::InvokeControlRequest(HLERequestContext& context) { controller_interface->InvokeRequest(context); } static Result ValidateServiceName(const std::string& name) { if (name.empty() || name.size() > 8) { LOG_ERROR(Service_SM, "Invalid service name! service={}", name); - return ERR_INVALID_NAME; + return Service::SM::ResultInvalidServiceName; } return ResultSuccess; } -Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) { - self.sm_interface = std::make_shared<SM>(self, system); - self.controller_interface = std::make_unique<Controller>(system); - return self.sm_interface->CreatePort(); -} - -void ServiceManager::SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port) { - self.sm_interface->AcceptSession(server_port); -} - Result ServiceManager::RegisterService(std::string name, u32 max_sessions, - Kernel::SessionRequestHandlerPtr handler) { + SessionRequestHandlerPtr handler) { CASCADE_CODE(ValidateServiceName(name)); + std::scoped_lock lk{lock}; if (registered_services.find(name) != registered_services.end()) { LOG_ERROR(Service_SM, "Service is already registered! service={}", name); - return ERR_ALREADY_REGISTERED; + return Service::SM::ResultAlreadyRegistered; } auto* port = Kernel::KPort::Create(kernel); - port->Initialize(ServerSessionCountMax, false, name); + port->Initialize(ServerSessionCountMax, false, 0); + + // Register the port. + Kernel::KPort::Register(kernel, port); service_ports.emplace(name, port); registered_services.emplace(name, handler); + if (deferral_event) { + deferral_event->Signal(); + } return ResultSuccess; } @@ -75,10 +79,11 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions, Result ServiceManager::UnregisterService(const std::string& name) { CASCADE_CODE(ValidateServiceName(name)); + std::scoped_lock lk{lock}; const auto iter = registered_services.find(name); if (iter == registered_services.end()) { LOG_ERROR(Service_SM, "Server is not registered! service={}", name); - return ERR_SERVICE_NOT_REGISTERED; + return Service::SM::ResultNotRegistered; } registered_services.erase(iter); @@ -89,10 +94,12 @@ Result ServiceManager::UnregisterService(const std::string& name) { ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) { CASCADE_CODE(ValidateServiceName(name)); + + std::scoped_lock lk{lock}; auto it = service_ports.find(name); if (it == service_ports.end()) { - LOG_ERROR(Service_SM, "Server is not registered! service={}", name); - return ERR_SERVICE_NOT_REGISTERED; + LOG_WARNING(Service_SM, "Server is not registered! service={}", name); + return Service::SM::ResultNotRegistered; } return it->second; @@ -105,17 +112,22 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name * Outputs: * 0: Result */ -void SM::Initialize(Kernel::HLERequestContext& ctx) { +void SM::Initialize(HLERequestContext& ctx) { LOG_DEBUG(Service_SM, "called"); - is_initialized = true; + ctx.GetManager()->SetIsInitializedForSm(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void SM::GetService(Kernel::HLERequestContext& ctx) { +void SM::GetService(HLERequestContext& ctx) { auto result = GetServiceImpl(ctx); + if (ctx.GetIsDeferred()) { + // Don't overwrite the command buffer. + return; + } + if (result.Succeeded()) { IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; rb.Push(result.Code()); @@ -126,8 +138,13 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { } } -void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) { +void SM::GetServiceTipc(HLERequestContext& ctx) { auto result = GetServiceImpl(ctx); + if (ctx.GetIsDeferred()) { + // Don't overwrite the command buffer. + return; + } + IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; rb.Push(result.Code()); rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); @@ -144,9 +161,9 @@ static std::string PopServiceName(IPC::RequestParser& rp) { return result; } -ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) { - if (!is_initialized) { - return ERR_NOT_INITIALIZED; +ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { + if (!ctx.GetManager()->GetIsInitializedForSm()) { + return Service::SM::ResultInvalidClient; } IPC::RequestParser rp{ctx}; @@ -154,10 +171,15 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& // Find the named port. auto port_result = service_manager.GetServicePort(name); - auto service = service_manager.GetService<Kernel::SessionRequestHandler>(name); - if (port_result.Failed() || !service) { - LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw); - return port_result.Code(); + if (port_result.Code() == Service::SM::ResultInvalidServiceName) { + LOG_ERROR(Service_SM, "Invalid service name '{}'", name); + return Service::SM::ResultInvalidServiceName; + } + + if (port_result.Failed()) { + LOG_INFO(Service_SM, "Waiting for service {} to become available", name); + ctx.SetIsDeferred(); + return Service::SM::ResultNotRegistered; } auto& port = port_result.Unwrap(); @@ -167,14 +189,13 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); return result; } - service->AcceptSession(&port->GetServerPort()); LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); return session; } -void SM::RegisterService(Kernel::HLERequestContext& ctx) { +void SM::RegisterService(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; std::string name(PopServiceName(rp)); @@ -193,7 +214,7 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { } auto* port = Kernel::KPort::Create(kernel); - port->Initialize(ServerSessionCountMax, is_light, name); + port->Initialize(ServerSessionCountMax, is_light, 0); SCOPE_EXIT({ port->GetClientPort().Close(); }); IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; @@ -201,7 +222,7 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { rb.PushMoveObjects(port->GetServerPort()); } -void SM::UnregisterService(Kernel::HLERequestContext& ctx) { +void SM::UnregisterService(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; std::string name(PopServiceName(rp)); @@ -212,7 +233,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) { } SM::SM(ServiceManager& service_manager_, Core::System& system_) - : ServiceFramework{system_, "sm:", ServiceThreadType::Default, 4}, + : ServiceFramework{system_, "sm:", 4}, service_manager{service_manager_}, kernel{system_.Kernel()} { RegisterHandlers({ {0, &SM::Initialize, "Initialize"}, @@ -232,4 +253,16 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_) SM::~SM() = default; +void LoopProcess(Core::System& system) { + auto& service_manager = system.ServiceManager(); + auto server_manager = std::make_unique<ServerManager>(system); + + Kernel::KEvent* deferral_event{}; + server_manager->ManageDeferral(&deferral_event); + service_manager.SetDeferralEvent(deferral_event); + + server_manager->ManageNamedPort("sm:", std::make_shared<SM>(system.ServiceManager(), system)); + ServerManager::RunServer(std::move(server_manager)); +} + } // namespace Service::SM diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 02a5dde9e..6697f4007 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -4,6 +4,7 @@ #pragma once #include <memory> +#include <mutex> #include <string> #include <unordered_map> @@ -35,33 +36,28 @@ public: ~SM() override; private: - void Initialize(Kernel::HLERequestContext& ctx); - void GetService(Kernel::HLERequestContext& ctx); - void GetServiceTipc(Kernel::HLERequestContext& ctx); - void RegisterService(Kernel::HLERequestContext& ctx); - void UnregisterService(Kernel::HLERequestContext& ctx); + void Initialize(HLERequestContext& ctx); + void GetService(HLERequestContext& ctx); + void GetServiceTipc(HLERequestContext& ctx); + void RegisterService(HLERequestContext& ctx); + void UnregisterService(HLERequestContext& ctx); - ResultVal<Kernel::KClientSession*> GetServiceImpl(Kernel::HLERequestContext& ctx); + ResultVal<Kernel::KClientSession*> GetServiceImpl(HLERequestContext& ctx); ServiceManager& service_manager; - bool is_initialized{}; Kernel::KernelCore& kernel; }; class ServiceManager { public: - static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system); - static void SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port); - explicit ServiceManager(Kernel::KernelCore& kernel_); ~ServiceManager(); - Result RegisterService(std::string name, u32 max_sessions, - Kernel::SessionRequestHandlerPtr handler); + Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); Result UnregisterService(const std::string& name); ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); - template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> + template <Common::DerivedFrom<SessionRequestHandler> T> std::shared_ptr<T> GetService(const std::string& service_name) const { auto service = registered_services.find(service_name); if (service == registered_services.end()) { @@ -71,18 +67,27 @@ public: return std::static_pointer_cast<T>(service->second); } - void InvokeControlRequest(Kernel::HLERequestContext& context); + void InvokeControlRequest(HLERequestContext& context); + + void SetDeferralEvent(Kernel::KEvent* deferral_event_) { + deferral_event = deferral_event_; + } private: std::shared_ptr<SM> sm_interface; std::unique_ptr<Controller> controller_interface; /// Map of registered services, retrieved using GetServicePort. - std::unordered_map<std::string, Kernel::SessionRequestHandlerPtr> registered_services; + std::mutex lock; + std::unordered_map<std::string, SessionRequestHandlerPtr> registered_services; std::unordered_map<std::string, Kernel::KPort*> service_ports; /// Kernel context Kernel::KernelCore& kernel; + Kernel::KEvent* deferral_event{}; }; +/// Runs SM services. +void LoopProcess(Core::System& system); + } // namespace Service::SM diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 1cf9dd1c4..7dce28fe0 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -4,17 +4,18 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_session.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/sm/sm_controller.h" namespace Service::SM { -void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { +void Controller::ConvertCurrentObjectToDomain(HLERequestContext& ctx) { ASSERT_MSG(!ctx.GetManager()->IsDomain(), "Session is already a domain"); LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); ctx.GetManager()->ConvertToDomainOnRequestEnd(); @@ -24,7 +25,7 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { rb.Push<u32>(1); // Converted sessions start with 1 request handler } -void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { +void Controller::CloneCurrentObject(HLERequestContext& ctx) { LOG_DEBUG(Service, "called"); auto& process = *ctx.GetThread().GetOwnerProcess(); @@ -43,14 +44,17 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { ASSERT(session != nullptr); // Initialize the session. - session->Initialize(nullptr, ""); + session->Initialize(nullptr, 0); // Commit the session reservation. session_reservation.Commit(); - // Register with manager. - session_manager->SessionHandler().RegisterSession(&session->GetServerSession(), - session_manager); + // Register the session. + Kernel::KSession::Register(system.Kernel(), session); + + // Register with server manager. + session_manager->GetServerManager().RegisterSession(&session->GetServerSession(), + session_manager); // We succeeded. IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; @@ -58,13 +62,13 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { rb.PushMoveObjects(session->GetClientSession()); } -void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { +void Controller::CloneCurrentObjectEx(HLERequestContext& ctx) { LOG_DEBUG(Service, "called"); CloneCurrentObject(ctx); } -void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { +void Controller::QueryPointerBufferSize(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/sm/sm_controller.h b/src/core/hle/service/sm/sm_controller.h index ed386f660..4e748b36d 100644 --- a/src/core/hle/service/sm/sm_controller.h +++ b/src/core/hle/service/sm/sm_controller.h @@ -17,10 +17,10 @@ public: ~Controller() override; private: - void ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx); - void CloneCurrentObject(Kernel::HLERequestContext& ctx); - void CloneCurrentObjectEx(Kernel::HLERequestContext& ctx); - void QueryPointerBufferSize(Kernel::HLERequestContext& ctx); + void ConvertCurrentObjectToDomain(HLERequestContext& ctx); + void CloneCurrentObject(HLERequestContext& ctx); + void CloneCurrentObjectEx(HLERequestContext& ctx); + void QueryPointerBufferSize(HLERequestContext& ctx); }; } // namespace Service::SM diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 9e94a462f..bce45d321 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -11,8 +11,8 @@ #include "common/microprofile.h" #include "common/socket_types.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/sockets/bsd.h" #include "core/hle/service/sockets/sockets_translate.h" #include "core/internal_network/network.h" @@ -42,7 +42,7 @@ void BSD::PollWork::Execute(BSD* bsd) { std::tie(ret, bsd_errno) = bsd->PollImpl(write_buffer, read_buffer, nfds, timeout); } -void BSD::PollWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::PollWork::Response(HLERequestContext& ctx) { if (write_buffer.size() > 0) { ctx.WriteBuffer(write_buffer); } @@ -57,7 +57,7 @@ void BSD::AcceptWork::Execute(BSD* bsd) { std::tie(ret, bsd_errno) = bsd->AcceptImpl(fd, write_buffer); } -void BSD::AcceptWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::AcceptWork::Response(HLERequestContext& ctx) { if (write_buffer.size() > 0) { ctx.WriteBuffer(write_buffer); } @@ -73,7 +73,7 @@ void BSD::ConnectWork::Execute(BSD* bsd) { bsd_errno = bsd->ConnectImpl(fd, addr); } -void BSD::ConnectWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::ConnectWork::Response(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1); @@ -84,7 +84,7 @@ void BSD::RecvWork::Execute(BSD* bsd) { std::tie(ret, bsd_errno) = bsd->RecvImpl(fd, flags, message); } -void BSD::RecvWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::RecvWork::Response(HLERequestContext& ctx) { ctx.WriteBuffer(message); IPC::ResponseBuilder rb{ctx, 4}; @@ -97,7 +97,7 @@ void BSD::RecvFromWork::Execute(BSD* bsd) { std::tie(ret, bsd_errno) = bsd->RecvFromImpl(fd, flags, message, addr); } -void BSD::RecvFromWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::RecvFromWork::Response(HLERequestContext& ctx) { ctx.WriteBuffer(message, 0); if (!addr.empty()) { ctx.WriteBuffer(addr, 1); @@ -114,7 +114,7 @@ void BSD::SendWork::Execute(BSD* bsd) { std::tie(ret, bsd_errno) = bsd->SendImpl(fd, flags, message); } -void BSD::SendWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::SendWork::Response(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push<s32>(ret); @@ -125,14 +125,14 @@ void BSD::SendToWork::Execute(BSD* bsd) { std::tie(ret, bsd_errno) = bsd->SendToImpl(fd, flags, message, addr); } -void BSD::SendToWork::Response(Kernel::HLERequestContext& ctx) { +void BSD::SendToWork::Response(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push<s32>(ret); rb.PushEnum(bsd_errno); } -void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { +void BSD::RegisterClient(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -141,7 +141,7 @@ void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { rb.Push<s32>(0); // bsd errno } -void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) { +void BSD::StartMonitoring(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -149,7 +149,7 @@ void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void BSD::Socket(Kernel::HLERequestContext& ctx) { +void BSD::Socket(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 domain = rp.Pop<u32>(); const u32 type = rp.Pop<u32>(); @@ -166,7 +166,7 @@ void BSD::Socket(Kernel::HLERequestContext& ctx) { rb.PushEnum(bsd_errno); } -void BSD::Select(Kernel::HLERequestContext& ctx) { +void BSD::Select(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -176,7 +176,7 @@ void BSD::Select(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD::Poll(Kernel::HLERequestContext& ctx) { +void BSD::Poll(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 nfds = rp.Pop<s32>(); const s32 timeout = rp.Pop<s32>(); @@ -191,7 +191,7 @@ void BSD::Poll(Kernel::HLERequestContext& ctx) { }); } -void BSD::Accept(Kernel::HLERequestContext& ctx) { +void BSD::Accept(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -203,16 +203,15 @@ void BSD::Accept(Kernel::HLERequestContext& ctx) { }); } -void BSD::Bind(Kernel::HLERequestContext& ctx) { +void BSD::Bind(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize()); - BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer())); } -void BSD::Connect(Kernel::HLERequestContext& ctx) { +void BSD::Connect(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -224,7 +223,7 @@ void BSD::Connect(Kernel::HLERequestContext& ctx) { }); } -void BSD::GetPeerName(Kernel::HLERequestContext& ctx) { +void BSD::GetPeerName(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -242,7 +241,7 @@ void BSD::GetPeerName(Kernel::HLERequestContext& ctx) { rb.Push<u32>(static_cast<u32>(write_buffer.size())); } -void BSD::GetSockName(Kernel::HLERequestContext& ctx) { +void BSD::GetSockName(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -260,7 +259,7 @@ void BSD::GetSockName(Kernel::HLERequestContext& ctx) { rb.Push<u32>(static_cast<u32>(write_buffer.size())); } -void BSD::GetSockOpt(Kernel::HLERequestContext& ctx) { +void BSD::GetSockOpt(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); const u32 level = rp.Pop<u32>(); @@ -279,7 +278,7 @@ void BSD::GetSockOpt(Kernel::HLERequestContext& ctx) { rb.Push<u32>(static_cast<u32>(optval.size())); } -void BSD::Listen(Kernel::HLERequestContext& ctx) { +void BSD::Listen(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); const s32 backlog = rp.Pop<s32>(); @@ -289,7 +288,7 @@ void BSD::Listen(Kernel::HLERequestContext& ctx) { BuildErrnoResponse(ctx, ListenImpl(fd, backlog)); } -void BSD::Fcntl(Kernel::HLERequestContext& ctx) { +void BSD::Fcntl(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); const s32 cmd = rp.Pop<s32>(); @@ -305,14 +304,14 @@ void BSD::Fcntl(Kernel::HLERequestContext& ctx) { rb.PushEnum(bsd_errno); } -void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) { +void BSD::SetSockOpt(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); const u32 level = rp.Pop<u32>(); const OptName optname = static_cast<OptName>(rp.Pop<u32>()); - const std::vector<u8> buffer = ctx.ReadBuffer(); + const auto buffer = ctx.ReadBuffer(); const u8* optval = buffer.empty() ? nullptr : buffer.data(); size_t optlen = buffer.size(); @@ -329,7 +328,7 @@ void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) { BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval)); } -void BSD::Shutdown(Kernel::HLERequestContext& ctx) { +void BSD::Shutdown(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -340,7 +339,7 @@ void BSD::Shutdown(Kernel::HLERequestContext& ctx) { BuildErrnoResponse(ctx, ShutdownImpl(fd, how)); } -void BSD::Recv(Kernel::HLERequestContext& ctx) { +void BSD::Recv(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -355,7 +354,7 @@ void BSD::Recv(Kernel::HLERequestContext& ctx) { }); } -void BSD::RecvFrom(Kernel::HLERequestContext& ctx) { +void BSD::RecvFrom(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -372,7 +371,7 @@ void BSD::RecvFrom(Kernel::HLERequestContext& ctx) { }); } -void BSD::Send(Kernel::HLERequestContext& ctx) { +void BSD::Send(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -387,7 +386,7 @@ void BSD::Send(Kernel::HLERequestContext& ctx) { }); } -void BSD::SendTo(Kernel::HLERequestContext& ctx) { +void BSD::SendTo(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); const u32 flags = rp.Pop<u32>(); @@ -403,7 +402,7 @@ void BSD::SendTo(Kernel::HLERequestContext& ctx) { }); } -void BSD::Write(Kernel::HLERequestContext& ctx) { +void BSD::Write(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -416,7 +415,7 @@ void BSD::Write(Kernel::HLERequestContext& ctx) { }); } -void BSD::Read(Kernel::HLERequestContext& ctx) { +void BSD::Read(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -428,7 +427,7 @@ void BSD::Read(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD::Close(Kernel::HLERequestContext& ctx) { +void BSD::Close(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const s32 fd = rp.Pop<s32>(); @@ -437,7 +436,7 @@ void BSD::Close(Kernel::HLERequestContext& ctx) { BuildErrnoResponse(ctx, CloseImpl(fd)); } -void BSD::EventFd(Kernel::HLERequestContext& ctx) { +void BSD::EventFd(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 initval = rp.Pop<u64>(); const u32 flags = rp.Pop<u32>(); @@ -448,7 +447,7 @@ void BSD::EventFd(Kernel::HLERequestContext& ctx) { } template <typename Work> -void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, Work work) { +void BSD::ExecuteWork(HLERequestContext& ctx, Work work) { work.Execute(this); work.Response(ctx); } @@ -489,7 +488,7 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco return {fd, Errno::SUCCESS}; } -std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, +std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, s32 nfds, s32 timeout) { if (write_buffer.size() < nfds * sizeof(PollFD)) { return {-1, Errno::INVAL}; @@ -584,7 +583,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) { return {new_fd, Errno::SUCCESS}; } -Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) { +Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) { if (!IsFileDescriptorValid(fd)) { return Errno::BADF; } @@ -595,7 +594,7 @@ Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) { return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); } -Errno BSD::ConnectImpl(s32 fd, const std::vector<u8>& addr) { +Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) { if (!IsFileDescriptorValid(fd)) { return Errno::BADF; } @@ -800,15 +799,15 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess return {ret, bsd_errno}; } -std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, const std::vector<u8>& message) { +std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) { if (!IsFileDescriptorValid(fd)) { return {-1, Errno::BADF}; } return Translate(file_descriptors[fd]->socket->Send(message, flags)); } -std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message, - const std::vector<u8>& addr) { +std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message, + std::span<const u8> addr) { if (!IsFileDescriptorValid(fd)) { return {-1, Errno::BADF}; } @@ -863,7 +862,7 @@ bool BSD::IsFileDescriptorValid(s32 fd) const noexcept { return true; } -void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept { +void BSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -882,8 +881,7 @@ void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) { } BSD::BSD(Core::System& system_, const char* name) - : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, room_network{ - system_.GetRoomNetwork()} { + : ServiceFramework{system_, name}, room_network{system_.GetRoomNetwork()} { // clang-format off static const FunctionInfo functions[] = { {0, &BSD::RegisterClient, "RegisterClient"}, @@ -955,6 +953,9 @@ BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { {10, nullptr, "ClearArpEntries"}, {11, nullptr, "ClearArpEntries2"}, {12, nullptr, "PrintArpEntries"}, + {13, nullptr, "Unknown13"}, + {14, nullptr, "Unknown14"}, + {15, nullptr, "Unknown15"}, }; // clang-format on diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 81e855e0f..30ae9c140 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -4,6 +4,7 @@ #pragma once #include <memory> +#include <span> #include <vector> #include "common/common_types.h" @@ -40,11 +41,11 @@ private: struct PollWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 nfds; s32 timeout; - std::vector<u8> read_buffer; + std::span<const u8> read_buffer; std::vector<u8> write_buffer; s32 ret{}; Errno bsd_errno{}; @@ -52,7 +53,7 @@ private: struct AcceptWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 fd; std::vector<u8> write_buffer; @@ -62,16 +63,16 @@ private: struct ConnectWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 fd; - std::vector<u8> addr; + std::span<const u8> addr; Errno bsd_errno{}; }; struct RecvWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 fd; u32 flags; @@ -82,7 +83,7 @@ private: struct RecvFromWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 fd; u32 flags; @@ -94,60 +95,60 @@ private: struct SendWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 fd; u32 flags; - std::vector<u8> message; + std::span<const u8> message; s32 ret{}; Errno bsd_errno{}; }; struct SendToWork { void Execute(BSD* bsd); - void Response(Kernel::HLERequestContext& ctx); + void Response(HLERequestContext& ctx); s32 fd; u32 flags; - std::vector<u8> message; - std::vector<u8> addr; + std::span<const u8> message; + std::span<const u8> addr; s32 ret{}; Errno bsd_errno{}; }; - void RegisterClient(Kernel::HLERequestContext& ctx); - void StartMonitoring(Kernel::HLERequestContext& ctx); - void Socket(Kernel::HLERequestContext& ctx); - void Select(Kernel::HLERequestContext& ctx); - void Poll(Kernel::HLERequestContext& ctx); - void Accept(Kernel::HLERequestContext& ctx); - void Bind(Kernel::HLERequestContext& ctx); - void Connect(Kernel::HLERequestContext& ctx); - void GetPeerName(Kernel::HLERequestContext& ctx); - void GetSockName(Kernel::HLERequestContext& ctx); - void GetSockOpt(Kernel::HLERequestContext& ctx); - void Listen(Kernel::HLERequestContext& ctx); - void Fcntl(Kernel::HLERequestContext& ctx); - void SetSockOpt(Kernel::HLERequestContext& ctx); - void Shutdown(Kernel::HLERequestContext& ctx); - void Recv(Kernel::HLERequestContext& ctx); - void RecvFrom(Kernel::HLERequestContext& ctx); - void Send(Kernel::HLERequestContext& ctx); - void SendTo(Kernel::HLERequestContext& ctx); - void Write(Kernel::HLERequestContext& ctx); - void Read(Kernel::HLERequestContext& ctx); - void Close(Kernel::HLERequestContext& ctx); - void EventFd(Kernel::HLERequestContext& ctx); + void RegisterClient(HLERequestContext& ctx); + void StartMonitoring(HLERequestContext& ctx); + void Socket(HLERequestContext& ctx); + void Select(HLERequestContext& ctx); + void Poll(HLERequestContext& ctx); + void Accept(HLERequestContext& ctx); + void Bind(HLERequestContext& ctx); + void Connect(HLERequestContext& ctx); + void GetPeerName(HLERequestContext& ctx); + void GetSockName(HLERequestContext& ctx); + void GetSockOpt(HLERequestContext& ctx); + void Listen(HLERequestContext& ctx); + void Fcntl(HLERequestContext& ctx); + void SetSockOpt(HLERequestContext& ctx); + void Shutdown(HLERequestContext& ctx); + void Recv(HLERequestContext& ctx); + void RecvFrom(HLERequestContext& ctx); + void Send(HLERequestContext& ctx); + void SendTo(HLERequestContext& ctx); + void Write(HLERequestContext& ctx); + void Read(HLERequestContext& ctx); + void Close(HLERequestContext& ctx); + void EventFd(HLERequestContext& ctx); template <typename Work> - void ExecuteWork(Kernel::HLERequestContext& ctx, Work work); + void ExecuteWork(HLERequestContext& ctx, Work work); std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol); - std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, + std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, s32 nfds, s32 timeout); std::pair<s32, Errno> AcceptImpl(s32 fd, std::vector<u8>& write_buffer); - Errno BindImpl(s32 fd, const std::vector<u8>& addr); - Errno ConnectImpl(s32 fd, const std::vector<u8>& addr); + Errno BindImpl(s32 fd, std::span<const u8> addr); + Errno ConnectImpl(s32 fd, std::span<const u8> addr); Errno GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer); Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer); Errno ListenImpl(s32 fd, s32 backlog); @@ -157,15 +158,15 @@ private: std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, std::vector<u8>& addr); - std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, const std::vector<u8>& message); - std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message, - const std::vector<u8>& addr); + std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, std::span<const u8> message); + std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, std::span<const u8> message, + std::span<const u8> addr); Errno CloseImpl(s32 fd); s32 FindFreeFileDescriptorHandle() noexcept; bool IsFileDescriptorValid(s32 fd) const noexcept; - void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; + void BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept; std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors; diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp deleted file mode 100644 index c12ea999b..000000000 --- a/src/core/hle/service/sockets/ethc.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/sockets/ethc.h" - -namespace Service::Sockets { - -ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {1, nullptr, "Cancel"}, - {2, nullptr, "GetResult"}, - {3, nullptr, "GetMediaList"}, - {4, nullptr, "SetMediaType"}, - {5, nullptr, "GetMediaType"}, - {6, nullptr, "Unknown6"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ETHC_C::~ETHC_C() = default; - -ETHC_I::ETHC_I(Core::System& system_) : ServiceFramework{system_, "ethc:i"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetReadableHandle"}, - {1, nullptr, "Cancel"}, - {2, nullptr, "GetResult"}, - {3, nullptr, "GetInterfaceList"}, - {4, nullptr, "GetInterfaceCount"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ETHC_I::~ETHC_I() = default; - -} // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h deleted file mode 100644 index 7c5759a96..000000000 --- a/src/core/hle/service/sockets/ethc.h +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Sockets { - -class ETHC_C final : public ServiceFramework<ETHC_C> { -public: - explicit ETHC_C(Core::System& system_); - ~ETHC_C() override; -}; - -class ETHC_I final : public ServiceFramework<ETHC_I> { -public: - explicit ETHC_I(Core::System& system_); - ~ETHC_I() override; -}; - -} // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 097c37d7a..132dd5797 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -8,7 +8,7 @@ #include "common/string_util.h" #include "common/swap.h" #include "core/core.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/sockets/sfdnsres.h" #include "core/memory.h" @@ -185,7 +185,7 @@ static std::vector<u8> SerializeAddrInfo(const addrinfo* addrinfo, s32 result_co return data; } -static std::pair<u32, s32> GetAddrInfoRequestImpl(Kernel::HLERequestContext& ctx) { +static std::pair<u32, s32> GetAddrInfoRequestImpl(HLERequestContext& ctx) { struct Parameters { u8 use_nsd_resolve; u32 unknown; @@ -221,7 +221,7 @@ static std::pair<u32, s32> GetAddrInfoRequestImpl(Kernel::HLERequestContext& ctx return std::make_pair(data_size, result_code); } -void SFDNSRES::GetAddrInfoRequest(Kernel::HLERequestContext& ctx) { +void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) { auto [data_size, result_code] = GetAddrInfoRequestImpl(ctx); IPC::ResponseBuilder rb{ctx, 4}; @@ -231,7 +231,7 @@ void SFDNSRES::GetAddrInfoRequest(Kernel::HLERequestContext& ctx) { rb.Push(data_size); // serialized size } -void SFDNSRES::GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx) { +void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) { // Additional options are ignored auto [data_size, result_code] = GetAddrInfoRequestImpl(ctx); @@ -243,4 +243,4 @@ void SFDNSRES::GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx) { rb.Push(0); } -} // namespace Service::Sockets
\ No newline at end of file +} // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h index 96018ea77..18e3cd60c 100644 --- a/src/core/hle/service/sockets/sfdnsres.h +++ b/src/core/hle/service/sockets/sfdnsres.h @@ -17,8 +17,8 @@ public: ~SFDNSRES() override; private: - void GetAddrInfoRequest(Kernel::HLERequestContext& ctx); - void GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx); + void GetAddrInfoRequest(HLERequestContext& ctx); + void GetAddrInfoRequestWithOptions(HLERequestContext& ctx); }; } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp index 8d3ba6f96..676d24e03 100644 --- a/src/core/hle/service/sockets/sockets.cpp +++ b/src/core/hle/service/sockets/sockets.cpp @@ -1,26 +1,25 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/server_manager.h" #include "core/hle/service/sockets/bsd.h" -#include "core/hle/service/sockets/ethc.h" #include "core/hle/service/sockets/nsd.h" #include "core/hle/service/sockets/sfdnsres.h" #include "core/hle/service/sockets/sockets.h" namespace Service::Sockets { -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<BSD>(system, "bsd:s")->InstallAsService(service_manager); - std::make_shared<BSD>(system, "bsd:u")->InstallAsService(service_manager); - std::make_shared<BSDCFG>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); - std::make_shared<ETHC_C>(system)->InstallAsService(service_manager); - std::make_shared<ETHC_I>(system)->InstallAsService(service_manager); - - std::make_shared<NSD>(system, "nsd:a")->InstallAsService(service_manager); - std::make_shared<NSD>(system, "nsd:u")->InstallAsService(service_manager); - - std::make_shared<SFDNSRES>(system)->InstallAsService(service_manager); + server_manager->RegisterNamedService("bsd:s", std::make_shared<BSD>(system, "bsd:s")); + server_manager->RegisterNamedService("bsd:u", std::make_shared<BSD>(system, "bsd:u")); + server_manager->RegisterNamedService("bsdcfg", std::make_shared<BSDCFG>(system)); + server_manager->RegisterNamedService("nsd:a", std::make_shared<NSD>(system, "nsd:a")); + server_manager->RegisterNamedService("nsd:u", std::make_shared<NSD>(system, "nsd:u")); + server_manager->RegisterNamedService("sfdnsres", std::make_shared<SFDNSRES>(system)); + server_manager->StartAdditionalHostThreads("bsdsocket", 2); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h index 31b7dad33..acd2dae7b 100644 --- a/src/core/hle/service/sockets/sockets.h +++ b/src/core/hle/service/sockets/sockets.h @@ -10,10 +10,6 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::Sockets { enum class Errno : u32 { @@ -23,6 +19,7 @@ enum class Errno : u32 { INVAL = 22, MFILE = 24, MSGSIZE = 90, + CONNRESET = 104, NOTCONN = 107, TIMEDOUT = 110, }; @@ -98,7 +95,6 @@ struct Linger { u32 linger; }; -/// Registers all Sockets services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp index 023aa0486..594e58f90 100644 --- a/src/core/hle/service/sockets/sockets_translate.cpp +++ b/src/core/hle/service/sockets/sockets_translate.cpp @@ -27,6 +27,8 @@ Errno Translate(Network::Errno value) { return Errno::NOTCONN; case Network::Errno::TIMEDOUT: return Errno::TIMEDOUT; + case Network::Errno::CONNRESET: + return Errno::CONNRESET; default: UNIMPLEMENTED_MSG("Unimplemented errno={}", value); return Errno::SUCCESS; diff --git a/src/core/hle/service/spl/spl_module.cpp b/src/core/hle/service/spl/spl_module.cpp index 64eae1ebf..0227d4393 100644 --- a/src/core/hle/service/spl/spl_module.cpp +++ b/src/core/hle/service/spl/spl_module.cpp @@ -8,7 +8,8 @@ #include "common/logging/log.h" #include "common/settings.h" #include "core/hle/api_version.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/spl/csrng.h" #include "core/hle/service/spl/spl.h" #include "core/hle/service/spl/spl_module.h" @@ -22,7 +23,7 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu Module::Interface::~Interface() = default; -void Module::Interface::GetConfig(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetConfig(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto config_item = rp.PopEnum<ConfigItem>(); @@ -47,21 +48,21 @@ void Module::Interface::GetConfig(Kernel::HLERequestContext& ctx) { rb.Push(*smc_result); } -void Module::Interface::ModularExponentiate(Kernel::HLERequestContext& ctx) { +void Module::Interface::ModularExponentiate(HLERequestContext& ctx) { UNIMPLEMENTED_MSG("ModularExponentiate is not implemented!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSecureMonitorNotImplemented); } -void Module::Interface::SetConfig(Kernel::HLERequestContext& ctx) { +void Module::Interface::SetConfig(HLERequestContext& ctx) { UNIMPLEMENTED_MSG("SetConfig is not implemented!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSecureMonitorNotImplemented); } -void Module::Interface::GenerateRandomBytes(Kernel::HLERequestContext& ctx) { +void Module::Interface::GenerateRandomBytes(HLERequestContext& ctx) { LOG_DEBUG(Service_SPL, "called"); const std::size_t size = ctx.GetWriteBufferSize(); @@ -76,21 +77,21 @@ void Module::Interface::GenerateRandomBytes(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Module::Interface::IsDevelopment(Kernel::HLERequestContext& ctx) { +void Module::Interface::IsDevelopment(HLERequestContext& ctx) { UNIMPLEMENTED_MSG("IsDevelopment is not implemented!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSecureMonitorNotImplemented); } -void Module::Interface::SetBootReason(Kernel::HLERequestContext& ctx) { +void Module::Interface::SetBootReason(HLERequestContext& ctx) { UNIMPLEMENTED_MSG("SetBootReason is not implemented!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSecureMonitorNotImplemented); } -void Module::Interface::GetBootReason(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetBootReason(HLERequestContext& ctx) { UNIMPLEMENTED_MSG("GetBootReason is not implemented!"); IPC::ResponseBuilder rb{ctx, 2}; @@ -158,15 +159,18 @@ ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const { } } -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); auto module = std::make_shared<Module>(); - std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager); - std::make_shared<SPL>(system, module)->InstallAsService(service_manager); - std::make_shared<SPL_MIG>(system, module)->InstallAsService(service_manager); - std::make_shared<SPL_FS>(system, module)->InstallAsService(service_manager); - std::make_shared<SPL_SSL>(system, module)->InstallAsService(service_manager); - std::make_shared<SPL_ES>(system, module)->InstallAsService(service_manager); - std::make_shared<SPL_MANU>(system, module)->InstallAsService(service_manager); + + server_manager->RegisterNamedService("csrng", std::make_shared<CSRNG>(system, module)); + server_manager->RegisterNamedService("spl", std::make_shared<SPL>(system, module)); + server_manager->RegisterNamedService("spl:mig", std::make_shared<SPL_MIG>(system, module)); + server_manager->RegisterNamedService("spl:fs", std::make_shared<SPL_FS>(system, module)); + server_manager->RegisterNamedService("spl:ssl", std::make_shared<SPL_SSL>(system, module)); + server_manager->RegisterNamedService("spl:es", std::make_shared<SPL_ES>(system, module)); + server_manager->RegisterNamedService("spl:manu", std::make_shared<SPL_MANU>(system, module)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::SPL diff --git a/src/core/hle/service/spl/spl_module.h b/src/core/hle/service/spl/spl_module.h index 4c9a3c618..e074e115d 100644 --- a/src/core/hle/service/spl/spl_module.h +++ b/src/core/hle/service/spl/spl_module.h @@ -23,13 +23,13 @@ public: ~Interface() override; // General - void GetConfig(Kernel::HLERequestContext& ctx); - void ModularExponentiate(Kernel::HLERequestContext& ctx); - void SetConfig(Kernel::HLERequestContext& ctx); - void GenerateRandomBytes(Kernel::HLERequestContext& ctx); - void IsDevelopment(Kernel::HLERequestContext& ctx); - void SetBootReason(Kernel::HLERequestContext& ctx); - void GetBootReason(Kernel::HLERequestContext& ctx); + void GetConfig(HLERequestContext& ctx); + void ModularExponentiate(HLERequestContext& ctx); + void SetConfig(HLERequestContext& ctx); + void GenerateRandomBytes(HLERequestContext& ctx); + void IsDevelopment(HLERequestContext& ctx); + void SetBootReason(HLERequestContext& ctx); + void GetBootReason(HLERequestContext& ctx); protected: std::shared_ptr<Module> module; @@ -41,7 +41,6 @@ public: }; }; -/// Registers all SPL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::SPL diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 3735e0452..2b99dd7ac 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -1,21 +1,43 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" #include "core/hle/service/ssl/ssl.h" namespace Service::SSL { +// This is nn::ssl::sf::CertificateFormat enum class CertificateFormat : u32 { Pem = 1, Der = 2, }; +// This is nn::ssl::sf::ContextOption +enum class ContextOption : u32 { + None = 0, + CrlImportDateCheckEnable = 1, +}; + +// This is nn::ssl::sf::SslVersion +struct SslVersion { + union { + u32 raw{}; + + BitField<0, 1, u32> tls_auto; + BitField<3, 1, u32> tls_v10; + BitField<4, 1, u32> tls_v11; + BitField<5, 1, u32> tls_v12; + BitField<6, 1, u32> tls_v13; + BitField<24, 7, u32> api_version; + }; +}; + class ISslConnection final : public ServiceFramework<ISslConnection> { public: - explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { + explicit ISslConnection(Core::System& system_, SslVersion version) + : ServiceFramework{system_, "ISslConnection"}, ssl_version{version} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetSocketDescriptor"}, @@ -46,16 +68,28 @@ public: {25, nullptr, "GetCipherInfo"}, {26, nullptr, "SetNextAlpnProto"}, {27, nullptr, "GetNextAlpnProto"}, + {28, nullptr, "SetDtlsSocketDescriptor"}, + {29, nullptr, "GetDtlsHandshakeTimeout"}, + {30, nullptr, "SetPrivateOption"}, + {31, nullptr, "SetSrtpCiphers"}, + {32, nullptr, "GetSrtpCipher"}, + {33, nullptr, "ExportKeyingMaterial"}, + {34, nullptr, "SetIoTimeout"}, + {35, nullptr, "GetIoTimeout"}, }; // clang-format on RegisterHandlers(functions); } + +private: + SslVersion ssl_version; }; class ISslContext final : public ServiceFramework<ISslContext> { public: - explicit ISslContext(Core::System& system_) : ServiceFramework{system_, "ISslContext"} { + explicit ISslContext(Core::System& system_, SslVersion version) + : ServiceFramework{system_, "ISslContext"}, ssl_version{version} { static const FunctionInfo functions[] = { {0, &ISslContext::SetOption, "SetOption"}, {1, nullptr, "GetOption"}, @@ -69,39 +103,44 @@ public: {9, nullptr, "AddPolicyOid"}, {10, nullptr, "ImportCrl"}, {11, nullptr, "RemoveCrl"}, + {12, nullptr, "ImportClientCertKeyPki"}, + {13, nullptr, "GeneratePrivateKeyAndCert"}, }; RegisterHandlers(functions); } private: - void SetOption(Kernel::HLERequestContext& ctx) { + SslVersion ssl_version; + + void SetOption(HLERequestContext& ctx) { struct Parameters { - u8 enable; - u32 option; + ContextOption option; + s32 value; }; + static_assert(sizeof(Parameters) == 0x8, "Parameters is an invalid size"); IPC::RequestParser rp{ctx}; const auto parameters = rp.PopRaw<Parameters>(); - LOG_WARNING(Service_SSL, "(STUBBED) called. enable={}, option={}", parameters.enable, - parameters.option); + LOG_WARNING(Service_SSL, "(STUBBED) called. option={}, value={}", parameters.option, + parameters.value); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void CreateConnection(Kernel::HLERequestContext& ctx) { + void CreateConnection(HLERequestContext& ctx) { LOG_WARNING(Service_SSL, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISslConnection>(system); + rb.PushIpcInterface<ISslConnection>(system, ssl_version); } - void ImportServerPki(Kernel::HLERequestContext& ctx) { + void ImportServerPki(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto certificate_format = rp.PopEnum<CertificateFormat>(); - const auto pkcs_12_certificates = ctx.ReadBuffer(0); + [[maybe_unused]] const auto pkcs_12_certificates = ctx.ReadBuffer(0); constexpr u64 server_id = 0; @@ -112,14 +151,14 @@ private: rb.Push(server_id); } - void ImportClientPki(Kernel::HLERequestContext& ctx) { - const auto pkcs_12_certificate = ctx.ReadBuffer(0); - const auto ascii_password = [&ctx] { + void ImportClientPki(HLERequestContext& ctx) { + [[maybe_unused]] const auto pkcs_12_certificate = ctx.ReadBuffer(0); + [[maybe_unused]] const auto ascii_password = [&ctx] { if (ctx.CanReadBuffer(1)) { return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); constexpr u64 client_id = 0; @@ -132,20 +171,21 @@ private: } }; -class SSL final : public ServiceFramework<SSL> { +class ISslService final : public ServiceFramework<ISslService> { public: - explicit SSL(Core::System& system_) : ServiceFramework{system_, "ssl"} { + explicit ISslService(Core::System& system_) : ServiceFramework{system_, "ssl"} { // clang-format off static const FunctionInfo functions[] = { - {0, &SSL::CreateContext, "CreateContext"}, + {0, &ISslService::CreateContext, "CreateContext"}, {1, nullptr, "GetContextCount"}, {2, nullptr, "GetCertificates"}, {3, nullptr, "GetCertificateBufSize"}, {4, nullptr, "DebugIoctl"}, - {5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"}, + {5, &ISslService::SetInterfaceVersion, "SetInterfaceVersion"}, {6, nullptr, "FlushSessionCache"}, {7, nullptr, "SetDebugOption"}, {8, nullptr, "GetDebugOption"}, + {8, nullptr, "ClearTls12FallbackFlag"}, }; // clang-format on @@ -153,28 +193,41 @@ public: } private: - u32 ssl_version{}; - void CreateContext(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_SSL, "(STUBBED) called"); + void CreateContext(HLERequestContext& ctx) { + struct Parameters { + SslVersion ssl_version; + INSERT_PADDING_BYTES(0x4); + u64 pid_placeholder; + }; + static_assert(sizeof(Parameters) == 0x10, "Parameters is an invalid size"); + + IPC::RequestParser rp{ctx}; + const auto parameters = rp.PopRaw<Parameters>(); + + LOG_WARNING(Service_SSL, "(STUBBED) called, api_version={}, pid_placeholder={}", + parameters.ssl_version.api_version, parameters.pid_placeholder); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISslContext>(system); + rb.PushIpcInterface<ISslContext>(system, parameters.ssl_version); } - void SetInterfaceVersion(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_SSL, "called"); - + void SetInterfaceVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - ssl_version = rp.Pop<u32>(); + u32 ssl_version = rp.Pop<u32>(); + + LOG_DEBUG(Service_SSL, "called, ssl_version={}", ssl_version); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } }; -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<SSL>(system)->InstallAsService(service_manager); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("ssl", std::make_shared<ISslService>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::SSL diff --git a/src/core/hle/service/ssl/ssl.h b/src/core/hle/service/ssl/ssl.h index 27b38a003..f6e21bbb3 100644 --- a/src/core/hle/service/ssl/ssl.h +++ b/src/core/hle/service/ssl/ssl.h @@ -7,13 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::SSL { -/// Registers all SSL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::SSL diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h index ed1eb5b2d..9fc01ea90 100644 --- a/src/core/hle/service/time/clock_types.h +++ b/src/core/hle/service/time/clock_types.h @@ -3,6 +3,8 @@ #pragma once +#include <ratio> + #include "common/common_funcs.h" #include "common/common_types.h" #include "common/uuid.h" @@ -59,21 +61,34 @@ static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext is incorre static_assert(std::is_trivially_copyable_v<SystemClockContext>, "SystemClockContext must be trivially copyable"); +struct ContinuousAdjustmentTimePoint { + s64 measurement_offset; + s64 diff_scale; + u32 shift_amount; + s64 lower; + s64 upper; + Common::UUID clock_source_id; +}; +static_assert(sizeof(ContinuousAdjustmentTimePoint) == 0x38); +static_assert(std::is_trivially_copyable_v<ContinuousAdjustmentTimePoint>, + "ContinuousAdjustmentTimePoint must be trivially copyable"); + /// https://switchbrew.org/wiki/Glue_services#TimeSpanType struct TimeSpanType { s64 nanoseconds{}; - static constexpr s64 ns_per_second{1000000000ULL}; s64 ToSeconds() const { - return nanoseconds / ns_per_second; + return nanoseconds / std::nano::den; } static TimeSpanType FromSeconds(s64 seconds) { - return {seconds * ns_per_second}; + return {seconds * std::nano::den}; } - static TimeSpanType FromTicks(u64 ticks, u64 frequency) { - return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency)); + template <u64 Frequency> + static TimeSpanType FromTicks(u64 ticks) { + using TicksToNSRatio = std::ratio<std::nano::den, Frequency>; + return {static_cast<s64>(ticks * TicksToNSRatio::num / TicksToNSRatio::den)}; } }; static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size"); diff --git a/src/core/hle/service/time/standard_steady_clock_core.cpp b/src/core/hle/service/time/standard_steady_clock_core.cpp index 3dbbb9850..5627b7003 100644 --- a/src/core/hle/service/time/standard_steady_clock_core.cpp +++ b/src/core/hle/service/time/standard_steady_clock_core.cpp @@ -10,7 +10,7 @@ namespace Service::Time::Clock { TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) { const TimeSpanType ticks_time_span{ - TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; + TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())}; TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds}; if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) { diff --git a/src/core/hle/service/time/tick_based_steady_clock_core.cpp b/src/core/hle/service/time/tick_based_steady_clock_core.cpp index 27600413e..0d9fb3143 100644 --- a/src/core/hle/service/time/tick_based_steady_clock_core.cpp +++ b/src/core/hle/service/time/tick_based_steady_clock_core.cpp @@ -10,7 +10,7 @@ namespace Service::Time::Clock { SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) { const TimeSpanType ticks_time_span{ - TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; + TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())}; return {ticks_time_span.ToSeconds(), GetClockSourceId()}; } diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index f77cdbb43..7197ca30f 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -5,8 +5,9 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/hardware_properties.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/time/time.h" #include "core/hle/service/time/time_interface.h" #include "core/hle/service/time/time_manager.h" @@ -33,7 +34,7 @@ public: } private: - void GetCurrentTime(Kernel::HLERequestContext& ctx) { + void GetCurrentTime(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); if (!clock_core.IsInitialized()) { @@ -54,7 +55,7 @@ private: rb.Push<s64>(posix_time); } - void GetSystemClockContext(Kernel::HLERequestContext& ctx) { + void GetSystemClockContext(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); if (!clock_core.IsInitialized()) { @@ -97,7 +98,7 @@ public: } private: - void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { + void GetCurrentTimePoint(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); if (!clock_core.IsInitialized()) { @@ -177,7 +178,7 @@ Result Module::Interface::GetClockSnapshotFromSystemClockContextInternal( return ResultSuccess; } -void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetStandardUserSystemClock(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -185,7 +186,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct system); } -void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetStandardNetworkSystemClock(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -193,14 +194,14 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& system); } -void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetStandardSteadyClock(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<ISteadyClock>(system.GetTimeManager().GetStandardSteadyClockCore(), system); } -void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetTimeZoneService(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -208,7 +209,7 @@ void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { system.GetTimeManager().GetTimeZoneContentManager()); } -void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetStandardLocalSystemClock(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -216,8 +217,7 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c system); } -void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( - Kernel::HLERequestContext& ctx) { +void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); auto& clock_core{system.GetTimeManager().GetStandardNetworkSystemClockCore()}; IPC::ResponseBuilder rb{ctx, 3}; @@ -225,7 +225,7 @@ void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system)); } -void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) { +void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); auto& steady_clock_core{system.GetTimeManager().GetStandardSteadyClockCore()}; @@ -240,8 +240,8 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERe const auto current_time_point{steady_clock_core.GetCurrentTimePoint(system)}; if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) { - const auto ticks{Clock::TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), - Core::Hardware::CNTFREQ)}; + const auto ticks{Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>( + system.CoreTiming().GetClockTicks())}; const s64 base_time_point{context.offset + current_time_point.time_point - ticks.ToSeconds()}; IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2}; @@ -254,7 +254,7 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERe rb.Push(ERROR_TIME_MISMATCH); } -void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetClockSnapshot(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto type{rp.PopEnum<Clock::TimeType>()}; @@ -295,7 +295,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto type{rp.PopEnum<Clock::TimeType>()}; @@ -321,8 +321,7 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques rb.Push(ResultSuccess); } -void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( - Kernel::HLERequestContext& ctx) { +void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); Clock::ClockSnapshot snapshot_a; @@ -349,7 +348,7 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( rb.PushRaw(time_span_type.nanoseconds); } -void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) { +void Module::Interface::CalculateSpanBetween(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); Clock::ClockSnapshot snapshot_a; @@ -384,7 +383,7 @@ void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) { rb.PushRaw(time_span_type.nanoseconds); } -void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetSharedMemoryNativeHandle(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); @@ -397,11 +396,17 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst Module::Interface::~Interface() = default; -void InstallInterfaces(Core::System& system) { +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); auto module{std::make_shared<Module>()}; - std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager()); - std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager()); - std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager()); + + server_manager->RegisterNamedService("time:a", + std::make_shared<Time>(module, system, "time:a")); + server_manager->RegisterNamedService("time:s", + std::make_shared<Time>(module, system, "time:s")); + server_manager->RegisterNamedService("time:u", + std::make_shared<Time>(module, system, "time:u")); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Time diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 76a46cfc7..b2d754ef3 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -22,18 +22,18 @@ public: const char* name); ~Interface() override; - void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); - void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx); - void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); - void GetTimeZoneService(Kernel::HLERequestContext& ctx); - void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); - void IsStandardNetworkSystemClockAccuracySufficient(Kernel::HLERequestContext& ctx); - void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx); - void GetClockSnapshot(Kernel::HLERequestContext& ctx); - void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx); - void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); - void CalculateSpanBetween(Kernel::HLERequestContext& ctx); - void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); + void GetStandardUserSystemClock(HLERequestContext& ctx); + void GetStandardNetworkSystemClock(HLERequestContext& ctx); + void GetStandardSteadyClock(HLERequestContext& ctx); + void GetTimeZoneService(HLERequestContext& ctx); + void GetStandardLocalSystemClock(HLERequestContext& ctx); + void IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx); + void CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx); + void GetClockSnapshot(HLERequestContext& ctx); + void GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx); + void CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx); + void CalculateSpanBetween(HLERequestContext& ctx); + void GetSharedMemoryNativeHandle(HLERequestContext& ctx); private: Result GetClockSnapshotFromSystemClockContextInternal( @@ -46,7 +46,6 @@ public: }; }; -/// Registers all Time services with the specified service manager. -void InstallInterfaces(Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Time diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp index 28667710e..fa0fd0531 100644 --- a/src/core/hle/service/time/time_manager.cpp +++ b/src/core/hle/service/time/time_manager.cpp @@ -22,10 +22,6 @@ s64 GetSecondsSinceEpoch() { return std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch).count() + Settings::values.custom_rtc_differential; } - -s64 GetExternalRtcValue() { - return GetSecondsSinceEpoch() + TimeManager::GetExternalTimeZoneOffset(); -} } // Anonymous namespace struct TimeManager::Impl final { @@ -43,7 +39,7 @@ struct TimeManager::Impl final { std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()}, time_zone_content_manager{system} { - const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; + const auto system_time{Clock::TimeSpanType::FromSeconds(GetSecondsSinceEpoch())}; SetupStandardSteadyClock(system, Common::UUID::MakeRandom(), system_time, {}, {}); SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); @@ -107,7 +103,7 @@ struct TimeManager::Impl final { void SetupTimeZoneManager(std::string location_name, Clock::SteadyClockTimePoint time_zone_updated_time_point, - std::size_t total_location_name_count, u128 time_zone_rule_version, + std::vector<std::string> location_names, u128 time_zone_rule_version, FileSys::VirtualFile& vfs_file) { if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( location_name, vfs_file) != ResultSuccess) { @@ -117,20 +113,13 @@ struct TimeManager::Impl final { time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( - total_location_name_count); + location_names.size()); + time_zone_content_manager.GetTimeZoneManager().SetLocationNames(location_names); time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion( time_zone_rule_version); time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); } - static s64 GetExternalTimeZoneOffset() { - // With "auto" timezone setting, we use the external system's timezone offset - if (Settings::GetTimeZoneString() == "auto") { - return Common::TimeZone::GetCurrentOffsetSeconds().count(); - } - return 0; - } - void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id, Clock::TimeSpanType setup_value, Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) { @@ -295,19 +284,10 @@ void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) { void TimeManager::SetupTimeZoneManager(std::string location_name, Clock::SteadyClockTimePoint time_zone_updated_time_point, - std::size_t total_location_name_count, + std::vector<std::string> location_names, u128 time_zone_rule_version, FileSys::VirtualFile& vfs_file) { - impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, - total_location_name_count, time_zone_rule_version, vfs_file); + impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, location_names, + time_zone_rule_version, vfs_file); } - -/*static*/ s64 TimeManager::GetExternalTimeZoneOffset() { - // With "auto" timezone setting, we use the external system's timezone offset - if (Settings::GetTimeZoneString() == "auto") { - return Common::TimeZone::GetCurrentOffsetSeconds().count(); - } - return 0; -} - } // namespace Service::Time diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h index 4f046f266..84572dbfa 100644 --- a/src/core/hle/service/time/time_manager.h +++ b/src/core/hle/service/time/time_manager.h @@ -61,11 +61,9 @@ public: void SetupTimeZoneManager(std::string location_name, Clock::SteadyClockTimePoint time_zone_updated_time_point, - std::size_t total_location_name_count, u128 time_zone_rule_version, + std::vector<std::string> location_names, u128 time_zone_rule_version, FileSys::VirtualFile& vfs_file); - static s64 GetExternalTimeZoneOffset(); - private: Core::System& system; diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp index ff53a7d6f..a00676669 100644 --- a/src/core/hle/service/time/time_sharedmemory.cpp +++ b/src/core/hle/service/time/time_sharedmemory.cpp @@ -21,8 +21,9 @@ SharedMemory::~SharedMemory() = default; void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id, Clock::TimeSpanType current_time_point) { - const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks( - system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; + const Clock::TimeSpanType ticks_time_span{ + Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>( + system.CoreTiming().GetClockTicks())}; const Clock::SteadyClockContext context{ static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds), clock_source_id}; @@ -30,6 +31,25 @@ void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id, } void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) { + // lower and upper are related to the measurement point for the steady time point, + // and compare equal on boot + const s64 time_point_ns = context.steady_time_point.time_point * 1'000'000'000LL; + + // This adjusts for some sort of time skew + // Both 0 on boot + const s64 diff_scale = 0; + const u32 shift_amount = 0; + + const Clock::ContinuousAdjustmentTimePoint adjustment{ + .measurement_offset = system.CoreTiming().GetGlobalTimeNs().count(), + .diff_scale = diff_scale, + .shift_amount = shift_amount, + .lower = time_point_ns, + .upper = time_point_ns, + .clock_source_id = context.steady_time_point.clock_source_id, + }; + + StoreToLockFreeAtomicType(&GetFormat()->continuous_adjustment_timepoint, adjustment); StoreToLockFreeAtomicType(&GetFormat()->standard_local_system_clock_context, context); } diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h index 044a4d24e..c89be9765 100644 --- a/src/core/hle/service/time/time_sharedmemory.h +++ b/src/core/hle/service/time/time_sharedmemory.h @@ -65,14 +65,15 @@ public: LockFreeAtomicType<Clock::SystemClockContext> standard_local_system_clock_context; LockFreeAtomicType<Clock::SystemClockContext> standard_network_system_clock_context; LockFreeAtomicType<bool> is_standard_user_system_clock_automatic_correction_enabled; - u32 format_version; + LockFreeAtomicType<Clock::ContinuousAdjustmentTimePoint> continuous_adjustment_timepoint; }; static_assert(offsetof(Format, standard_steady_clock_timepoint) == 0x0); static_assert(offsetof(Format, standard_local_system_clock_context) == 0x38); static_assert(offsetof(Format, standard_network_system_clock_context) == 0x80); static_assert(offsetof(Format, is_standard_user_system_clock_automatic_correction_enabled) == 0xc8); - static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); + static_assert(offsetof(Format, continuous_adjustment_timepoint) == 0xd0); + static_assert(sizeof(Format) == 0x148, "Format is an invalid size"); void SetupStandardSteadyClock(const Common::UUID& clock_source_id, Clock::TimeSpanType current_time_point); diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index afbfe9715..5d60be67a 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include <chrono> #include <sstream> #include "common/logging/log.h" @@ -12,7 +13,11 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs.h" #include "core/file_sys/system_archive/system_archive.h" +#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_types.h" +#include "core/hle/result.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/time/errors.h" #include "core/hle/service/time/time_manager.h" #include "core/hle/service/time/time_zone_content_manager.h" @@ -71,19 +76,13 @@ TimeZoneContentManager::TimeZoneContentManager(Core::System& system_) : system{system_}, location_name_cache{BuildLocationNameCache(system)} {} void TimeZoneContentManager::Initialize(TimeManager& time_manager) { - std::string location_name; const auto timezone_setting = Settings::GetTimeZoneString(); - if (timezone_setting == "auto" || timezone_setting == "default") { - location_name = Common::TimeZone::GetDefaultTimeZone(); - } else { - location_name = timezone_setting; - } if (FileSys::VirtualFile vfs_file; - GetTimeZoneInfoFile(location_name, vfs_file) == ResultSuccess) { + GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) { const auto time_point{ time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)}; - time_manager.SetupTimeZoneManager(location_name, time_point, location_name_cache.size(), {}, + time_manager.SetupTimeZoneManager(timezone_setting, time_point, location_name_cache, {}, vfs_file); } else { time_zone_manager.MarkAsInitialized(); @@ -126,8 +125,15 @@ Result TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_n vfs_file = zoneinfo_dir->GetFileRelative(location_name); if (!vfs_file) { - LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.", - time_zone_binary_titleid, location_name); + LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using system timezone.", + time_zone_binary_titleid, location_name); + const std::string system_time_zone{Common::TimeZone::FindSystemTimeZone()}; + vfs_file = zoneinfo_dir->GetFile(system_time_zone); + } + + if (!vfs_file) { + LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.", + time_zone_binary_titleid, location_name); vfs_file = zoneinfo_dir->GetFile(Common::TimeZone::GetDefaultTimeZone()); } diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp index f9ada7c93..205371a26 100644 --- a/src/core/hle/service/time/time_zone_manager.cpp +++ b/src/core/hle/service/time/time_zone_manager.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <climits> +#include <limits> #include "common/assert.h" #include "common/logging/log.h" @@ -9,6 +10,7 @@ #include "core/file_sys/nca_metadata.h" #include "core/file_sys/registered_cache.h" #include "core/hle/service/time/time_zone_manager.h" +#include "core/hle/service/time/time_zone_types.h" namespace Service::Time::TimeZone { @@ -128,10 +130,10 @@ static constexpr int GetQZName(const char* name, int offset, char delimiter) { } static constexpr int GetTZName(const char* name, int offset) { - for (char value{name[offset]}; - value != '\0' && !IsDigit(value) && value != ',' && value != '-' && value != '+'; - offset++) { - value = name[offset]; + char c; + + while ((c = name[offset]) != '\0' && !IsDigit(c) && c != ',' && c != '-' && c != '+') { + ++offset; } return offset; } @@ -147,6 +149,7 @@ static constexpr bool GetInteger(const char* name, int& offset, int& value, int if (value > max) { return {}; } + offset++; temp = name[offset]; } while (IsDigit(temp)); @@ -286,7 +289,7 @@ static constexpr int TransitionTime(int year, Rule rule, int offset) { } static bool ParsePosixName(const char* name, TimeZoneRule& rule) { - constexpr char default_rule[]{",M4.1.0,M10.5.0"}; + static constexpr char default_rule[]{",M4.1.0,M10.5.0"}; const char* std_name{name}; int std_len{}; int offset{}; @@ -471,6 +474,13 @@ static bool ParsePosixName(const char* name, TimeZoneRule& rule) { their_std_offset = their_offset; } } + + if (rule.time_count > 0) { + UNIMPLEMENTED(); + // TODO (lat9nq): Implement eggert/tz/localtime.c:tzparse:1329 + // Seems to be unused in yuzu for now: I never hit the UNIMPLEMENTED in testing + } + rule.ttis[0].gmt_offset = -std_offset; rule.ttis[0].is_dst = false; rule.ttis[0].abbreviation_list_index = 0; @@ -514,6 +524,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi constexpr s32 time_zone_max_leaps{50}; constexpr s32 time_zone_max_chars{50}; + constexpr s32 time_zone_max_times{1000}; if (!(0 <= header.leap_count && header.leap_count < time_zone_max_leaps && 0 < header.type_count && header.type_count < s32(time_zone_rule.ttis.size()) && 0 <= header.time_count && header.time_count < s32(time_zone_rule.ats.size()) && @@ -546,7 +557,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi for (int index{}; index < time_zone_rule.time_count; ++index) { const u8 type{*vfs_file->ReadByte(read_offset)}; read_offset += sizeof(u8); - if (time_zone_rule.time_count <= type) { + if (time_zone_rule.type_count <= type) { return {}; } if (time_zone_rule.types[index] != 0) { @@ -624,16 +635,109 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi std::array<char, time_zone_name_max> name{}; std::memcpy(name.data(), temp_name.data() + 1, std::size_t(bytes_read - 1)); + // Fill in computed transition times with temp rule TimeZoneRule temp_rule; if (ParsePosixName(name.data(), temp_rule)) { - UNIMPLEMENTED(); + int have_abbreviation = 0; + int char_count = time_zone_rule.char_count; + + for (int i = 0; i < temp_rule.type_count; i++) { + char* temp_abbreviation = + temp_rule.chars.data() + temp_rule.ttis[i].abbreviation_list_index; + int j; + for (j = 0; j < char_count; j++) { + if (std::strcmp(time_zone_rule.chars.data() + j, temp_abbreviation) == 0) { + temp_rule.ttis[i].abbreviation_list_index = j; + have_abbreviation++; + break; + } + } + if (j >= char_count) { + int temp_abbreviation_length = static_cast<int>(std::strlen(temp_abbreviation)); + if (j + temp_abbreviation_length < time_zone_max_chars) { + std::strcpy(time_zone_rule.chars.data() + j, temp_abbreviation); + char_count = j + temp_abbreviation_length + 1; + temp_rule.ttis[i].abbreviation_list_index = j; + have_abbreviation++; + } + } + } + + if (have_abbreviation == temp_rule.type_count) { + time_zone_rule.char_count = char_count; + + // Original comment: + /* Ignore any trailing, no-op transitions generated + by zic as they don't help here and can run afoul + of bugs in zic 2016j or earlier. */ + // This is possibly unnecessary for yuzu, since Nintendo doesn't run zic + while (1 < time_zone_rule.time_count && + (time_zone_rule.types[time_zone_rule.time_count - 1] == + time_zone_rule.types[time_zone_rule.time_count - 2])) { + time_zone_rule.time_count--; + } + + for (int i = 0; + i < temp_rule.time_count && time_zone_rule.time_count < time_zone_max_times; + i++) { + const s64 transition_time = temp_rule.ats[i]; + if (0 < time_zone_rule.time_count && + transition_time <= time_zone_rule.ats[time_zone_rule.time_count - 1]) { + continue; + } + + time_zone_rule.ats[time_zone_rule.time_count] = transition_time; + time_zone_rule.types[time_zone_rule.time_count] = + static_cast<s8>(time_zone_rule.type_count + temp_rule.types[i]); + time_zone_rule.time_count++; + } + for (int i = 0; i < temp_rule.type_count; i++) { + time_zone_rule.ttis[time_zone_rule.type_count++] = temp_rule.ttis[i]; + } + } } } + + const auto typesequiv = [](TimeZoneRule& rule, int a, int b) -> bool { + if (a < 0 || a >= rule.type_count || b < 0 || b >= rule.type_count) { + return {}; + } + + const struct TimeTypeInfo* ap = &rule.ttis[a]; + const struct TimeTypeInfo* bp = &rule.ttis[b]; + + return (ap->gmt_offset == bp->gmt_offset && ap->is_dst == bp->is_dst && + (std::strcmp(&rule.chars[ap->abbreviation_list_index], + &rule.chars[bp->abbreviation_list_index]) == 0)); + }; + if (time_zone_rule.type_count == 0) { return {}; } if (time_zone_rule.time_count > 1) { - UNIMPLEMENTED(); + if (time_zone_rule.ats[0] <= std::numeric_limits<s64>::max() - seconds_per_repeat) { + s64 repeatat = time_zone_rule.ats[0] + seconds_per_repeat; + int repeatattype = time_zone_rule.types[0]; + for (int i = 1; i < time_zone_rule.time_count; ++i) { + if (time_zone_rule.ats[i] == repeatat && + typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) { + time_zone_rule.go_back = true; + break; + } + } + } + if (std::numeric_limits<s64>::min() + seconds_per_repeat <= + time_zone_rule.ats[time_zone_rule.time_count - 1]) { + s64 repeatat = time_zone_rule.ats[time_zone_rule.time_count - 1] - seconds_per_repeat; + int repeatattype = time_zone_rule.types[time_zone_rule.time_count - 1]; + for (int i = time_zone_rule.time_count; i >= 0; --i) { + if (time_zone_rule.ats[i] == repeatat && + typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) { + time_zone_rule.go_ahead = true; + break; + } + } + } } s32 default_type{}; @@ -745,8 +849,9 @@ static Result CreateCalendarTime(s64 time, int gmt_offset, CalendarTimeInternal& static Result ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time, CalendarTimeInternal& calendar_time, CalendarAdditionalInfo& calendar_additional_info) { - if ((rules.go_ahead && time < rules.ats[0]) || - (rules.go_back && time > rules.ats[rules.time_count - 1])) { + ASSERT(rules.go_ahead ? rules.time_count > 0 : true); + if ((rules.go_back && time < rules.ats[0]) || + (rules.go_ahead && time > rules.ats[rules.time_count - 1])) { s64 seconds{}; if (time < rules.ats[0]) { seconds = rules.ats[0] - time; @@ -806,9 +911,13 @@ static Result ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time, calendar_additional_info.is_dst = rules.ttis[tti_index].is_dst; const char* time_zone{&rules.chars[rules.ttis[tti_index].abbreviation_list_index]}; - for (int index{}; time_zone[index] != '\0'; ++index) { + u32 index; + for (index = 0; time_zone[index] != '\0' && time_zone[index] != ',' && + index < calendar_additional_info.timezone_name.size() - 1; + ++index) { calendar_additional_info.timezone_name[index] = time_zone[index]; } + calendar_additional_info.timezone_name[index] = '\0'; return ResultSuccess; } @@ -1038,4 +1147,36 @@ Result TimeZoneManager::GetDeviceLocationName(LocationName& value) const { return ResultSuccess; } +Result TimeZoneManager::GetTotalLocationNameCount(s32& count) const { + if (!is_initialized) { + return ERROR_UNINITIALIZED_CLOCK; + } + count = static_cast<u32>(total_location_name_count); + + return ResultSuccess; +} + +Result TimeZoneManager::GetTimeZoneRuleVersion(u128& version) const { + if (!is_initialized) { + return ERROR_UNINITIALIZED_CLOCK; + } + version = time_zone_rule_version; + + return ResultSuccess; +} + +Result TimeZoneManager::LoadLocationNameList(std::vector<LocationName>& values) const { + if (!is_initialized) { + return ERROR_UNINITIALIZED_CLOCK; + } + + for (const auto& name : total_location_names) { + LocationName entry{}; + std::memcpy(entry.data(), name.c_str(), name.size()); + values.push_back(entry); + } + + return ResultSuccess; +} + } // namespace Service::Time::TimeZone diff --git a/src/core/hle/service/time/time_zone_manager.h b/src/core/hle/service/time/time_zone_manager.h index 5ebd4035e..8664f28d1 100644 --- a/src/core/hle/service/time/time_zone_manager.h +++ b/src/core/hle/service/time/time_zone_manager.h @@ -21,6 +21,10 @@ public: total_location_name_count = value; } + void SetLocationNames(std::vector<std::string> location_names) { + total_location_names = location_names; + } + void SetTimeZoneRuleVersion(const u128& value) { time_zone_rule_version = value; } @@ -33,6 +37,9 @@ public: FileSys::VirtualFile& vfs_file); Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value); Result GetDeviceLocationName(TimeZone::LocationName& value) const; + Result GetTotalLocationNameCount(s32& count) const; + Result GetTimeZoneRuleVersion(u128& version) const; + Result LoadLocationNameList(std::vector<TimeZone::LocationName>& values) const; Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const; Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const; Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const; @@ -46,6 +53,7 @@ private: std::string device_location_name{"GMT"}; u128 time_zone_rule_version{}; std::size_t total_location_name_count{}; + std::vector<std::string> total_location_names{}; Clock::SteadyClockTimePoint time_zone_update_time_point{ Clock::SteadyClockTimePoint::GetRandom()}; }; diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp index 961040bfc..8171c82a5 100644 --- a/src/core/hle/service/time/time_zone_service.cpp +++ b/src/core/hle/service/time/time_zone_service.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/time/time_zone_content_manager.h" #include "core/hle/service/time/time_zone_service.h" #include "core/hle/service/time/time_zone_types.h" @@ -15,10 +15,10 @@ ITimeZoneService::ITimeZoneService(Core::System& system_, static const FunctionInfo functions[] = { {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"}, {1, nullptr, "SetDeviceLocationName"}, - {2, nullptr, "GetTotalLocationNameCount"}, - {3, nullptr, "LoadLocationNameList"}, + {2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"}, + {3, &ITimeZoneService::LoadLocationNameList, "LoadLocationNameList"}, {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, - {5, nullptr, "GetTimeZoneRuleVersion"}, + {5, &ITimeZoneService::GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"}, {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, @@ -28,7 +28,7 @@ ITimeZoneService::ITimeZoneService(Core::System& system_, RegisterHandlers(functions); } -void ITimeZoneService::GetDeviceLocationName(Kernel::HLERequestContext& ctx) { +void ITimeZoneService::GetDeviceLocationName(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); TimeZone::LocationName location_name{}; @@ -45,7 +45,58 @@ void ITimeZoneService::GetDeviceLocationName(Kernel::HLERequestContext& ctx) { rb.PushRaw(location_name); } -void ITimeZoneService::LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { +void ITimeZoneService::GetTotalLocationNameCount(HLERequestContext& ctx) { + LOG_DEBUG(Service_Time, "called"); + + s32 count{}; + if (const Result result{ + time_zone_content_manager.GetTimeZoneManager().GetTotalLocationNameCount(count)}; + result != ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(count); +} + +void ITimeZoneService::LoadLocationNameList(HLERequestContext& ctx) { + LOG_DEBUG(Service_Time, "called"); + + std::vector<TimeZone::LocationName> location_names{}; + if (const Result result{ + time_zone_content_manager.GetTimeZoneManager().LoadLocationNameList(location_names)}; + result != ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + ctx.WriteBuffer(location_names); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<s32>(location_names.size())); +} +void ITimeZoneService::GetTimeZoneRuleVersion(HLERequestContext& ctx) { + LOG_DEBUG(Service_Time, "called"); + + u128 rule_version{}; + if (const Result result{ + time_zone_content_manager.GetTimeZoneManager().GetTimeZoneRuleVersion(rule_version)}; + result != ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.PushRaw(rule_version); +} + +void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()}; @@ -61,23 +112,17 @@ void ITimeZoneService::LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called, location_name={}", location_name); TimeZone::TimeZoneRule time_zone_rule{}; - if (const Result result{ - time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)}; - result != ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; - } + const Result result{time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)}; std::vector<u8> time_zone_rule_outbuffer(sizeof(TimeZone::TimeZoneRule)); std::memcpy(time_zone_rule_outbuffer.data(), &time_zone_rule, sizeof(TimeZone::TimeZoneRule)); ctx.WriteBuffer(time_zone_rule_outbuffer); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } -void ITimeZoneService::ToCalendarTime(Kernel::HLERequestContext& ctx) { +void ITimeZoneService::ToCalendarTime(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto posix_time{rp.Pop<s64>()}; @@ -101,7 +146,7 @@ void ITimeZoneService::ToCalendarTime(Kernel::HLERequestContext& ctx) { rb.PushRaw(calendar_info); } -void ITimeZoneService::ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) { +void ITimeZoneService::ToCalendarTimeWithMyRule(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto posix_time{rp.Pop<s64>()}; @@ -122,7 +167,7 @@ void ITimeZoneService::ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) rb.PushRaw(calendar_info); } -void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) { +void ITimeZoneService::ToPosixTime(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::RequestParser rp{ctx}; @@ -147,7 +192,7 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) { rb.PushRaw<u32>(1); // Number of times we're returning } -void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { +void ITimeZoneService::ToPosixTimeWithMyRule(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::RequestParser rp{ctx}; diff --git a/src/core/hle/service/time/time_zone_service.h b/src/core/hle/service/time/time_zone_service.h index f151f4b56..952fcb0e2 100644 --- a/src/core/hle/service/time/time_zone_service.h +++ b/src/core/hle/service/time/time_zone_service.h @@ -21,12 +21,15 @@ public: TimeZone::TimeZoneContentManager& time_zone_manager_); private: - void GetDeviceLocationName(Kernel::HLERequestContext& ctx); - void LoadTimeZoneRule(Kernel::HLERequestContext& ctx); - void ToCalendarTime(Kernel::HLERequestContext& ctx); - void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx); - void ToPosixTime(Kernel::HLERequestContext& ctx); - void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx); + void GetDeviceLocationName(HLERequestContext& ctx); + void GetTotalLocationNameCount(HLERequestContext& ctx); + void LoadLocationNameList(HLERequestContext& ctx); + void GetTimeZoneRuleVersion(HLERequestContext& ctx); + void LoadTimeZoneRule(HLERequestContext& ctx); + void ToCalendarTime(HLERequestContext& ctx); + void ToCalendarTimeWithMyRule(HLERequestContext& ctx); + void ToPosixTime(HLERequestContext& ctx); + void ToPosixTimeWithMyRule(HLERequestContext& ctx); private: TimeZone::TimeZoneContentManager& time_zone_content_manager; diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp index ac46a406c..f29fff1dd 100644 --- a/src/core/hle/service/usb/usb.cpp +++ b/src/core/hle/service/usb/usb.cpp @@ -4,9 +4,9 @@ #include <memory> #include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" #include "core/hle/service/usb/usb.h" namespace Service::USB { @@ -16,19 +16,19 @@ public: explicit IDsInterface(Core::System& system_) : ServiceFramework{system_, "IDsInterface"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "BindDevice"}, - {1, nullptr, "BindClientProcess"}, - {2, nullptr, "AddInterface"}, - {3, nullptr, "GetStateChangeEvent"}, - {4, nullptr, "GetState"}, - {5, nullptr, "ClearDeviceData"}, - {6, nullptr, "AddUsbStringDescriptor"}, - {7, nullptr, "DeleteUsbStringDescriptor"}, - {8, nullptr, "SetUsbDeviceDescriptor"}, - {9, nullptr, "SetBinaryObjectStore"}, - {10, nullptr, "Enable"}, - {11, nullptr, "Disable"}, - {12, nullptr, "Unknown12"}, + {0, nullptr, "AddEndpoint"}, + {1, nullptr, "GetSetupEvent"}, + {2, nullptr, "GetSetupPacket"}, + {3, nullptr, "Enable"}, + {4, nullptr, "Disable"}, + {5, nullptr, "CtrlIn"}, + {6, nullptr, "CtrlOut"}, + {7, nullptr, "GetCtrlInCompletionEvent"}, + {8, nullptr, "GetCtrlInUrbReport"}, + {9, nullptr, "GetCtrlOutCompletionEvent"}, + {10, nullptr, "GetCtrlOutUrbReport"}, + {11, nullptr, "CtrlStall"}, + {12, nullptr, "AppendConfigurationData"}, }; // clang-format on @@ -36,9 +36,9 @@ public: } }; -class USB_DS final : public ServiceFramework<USB_DS> { +class IDsRootSession final : public ServiceFramework<IDsRootSession> { public: - explicit USB_DS(Core::System& system_) : ServiceFramework{system_, "usb:ds"} { + explicit IDsRootSession(Core::System& system_) : ServiceFramework{system_, "usb:ds"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenDsService"}, @@ -94,9 +94,9 @@ public: } }; -class USB_HS final : public ServiceFramework<USB_HS> { +class IClientRootSession final : public ServiceFramework<IClientRootSession> { public: - explicit USB_HS(Core::System& system_) : ServiceFramework{system_, "usb:hs"} { + explicit IClientRootSession(Core::System& system_) : ServiceFramework{system_, "usb:hs"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "BindClientProcess"}, @@ -107,7 +107,7 @@ public: {5, nullptr, "DestroyInterfaceAvailableEvent"}, {6, nullptr, "GetInterfaceStateChangeEvent"}, {7, nullptr, "AcquireUsbIf"}, - {8, nullptr, "ResetDevice"}, + {8, nullptr, "SetTestMode"}, }; // clang-format on @@ -134,12 +134,12 @@ public: } }; -class USB_PD final : public ServiceFramework<USB_PD> { +class IPdManager final : public ServiceFramework<IPdManager> { public: - explicit USB_PD(Core::System& system_) : ServiceFramework{system_, "usb:pd"} { + explicit IPdManager(Core::System& system_) : ServiceFramework{system_, "usb:pd"} { // clang-format off static const FunctionInfo functions[] = { - {0, &USB_PD::GetPdSession, "GetPdSession"}, + {0, &IPdManager::OpenSession, "OpenSession"}, }; // clang-format on @@ -147,7 +147,7 @@ public: } private: - void GetPdSession(Kernel::HLERequestContext& ctx) { + void OpenSession(HLERequestContext& ctx) { LOG_DEBUG(Service_USB, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -178,12 +178,12 @@ public: } }; -class USB_PD_C final : public ServiceFramework<USB_PD_C> { +class IPdCradleManager final : public ServiceFramework<IPdCradleManager> { public: - explicit USB_PD_C(Core::System& system_) : ServiceFramework{system_, "usb:pd:c"} { + explicit IPdCradleManager(Core::System& system_) : ServiceFramework{system_, "usb:pd:c"} { // clang-format off static const FunctionInfo functions[] = { - {0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"}, + {0, &IPdCradleManager::OpenCradleSession, "OpenCradleSession"}, }; // clang-format on @@ -191,18 +191,18 @@ public: } private: - void GetPdCradleSession(Kernel::HLERequestContext& ctx) { + void OpenCradleSession(HLERequestContext& ctx) { + LOG_DEBUG(Service_USB, "called"); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IPdCradleSession>(system); - - LOG_DEBUG(Service_USB, "called"); } }; -class USB_PM final : public ServiceFramework<USB_PM> { +class IPmMainService final : public ServiceFramework<IPmMainService> { public: - explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { + explicit IPmMainService(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetPowerEvent"}, @@ -218,12 +218,15 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<USB_DS>(system)->InstallAsService(sm); - std::make_shared<USB_HS>(system)->InstallAsService(sm); - std::make_shared<USB_PD>(system)->InstallAsService(sm); - std::make_shared<USB_PD_C>(system)->InstallAsService(sm); - std::make_shared<USB_PM>(system)->InstallAsService(sm); +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("usb:ds", std::make_shared<IDsRootSession>(system)); + server_manager->RegisterNamedService("usb:hs", std::make_shared<IClientRootSession>(system)); + server_manager->RegisterNamedService("usb:pd", std::make_shared<IPdManager>(system)); + server_manager->RegisterNamedService("usb:pd:c", std::make_shared<IPdCradleManager>(system)); + server_manager->RegisterNamedService("usb:pm", std::make_shared<IPmMainService>(system)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::USB diff --git a/src/core/hle/service/usb/usb.h b/src/core/hle/service/usb/usb.h index b41b9684c..98376ebc0 100644 --- a/src/core/hle/service/usb/usb.h +++ b/src/core/hle/service/usb/usb.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::SM { -class ServiceManager; -} - namespace Service::USB { -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::USB diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 8ef74f1f0..69af2868a 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -12,11 +12,11 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvdrv/core/container.h" -#include "core/hle/service/nvflinger/buffer_item_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/buffer_queue_producer.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/buffer_item_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" #include "core/hle/service/vi/display/vi_display.h" #include "core/hle/service/vi/layer/vi_layer.h" #include "core/hle/service/vi/vi_results.h" @@ -39,7 +39,7 @@ static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_cont } Display::Display(u64 id, std::string name_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, KernelHelpers::ServiceContext& service_context_, Core::System& system_) : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_}, service_context{service_context_} { diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 0b65a65da..3f31d1f32 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h @@ -23,7 +23,7 @@ namespace Service::KernelHelpers { class ServiceContext; } -namespace Service::NVFlinger { +namespace Service::Nvnflinger { class HosBinderDriverServer; } @@ -45,12 +45,12 @@ public: /// Constructs a display with a given unique ID and name. /// /// @param id The unique ID for this display. - /// @param hos_binder_driver_server_ NVFlinger HOSBinderDriver server instance. + /// @param hos_binder_driver_server_ Nvnflinger HOSBinderDriver server instance. /// @param service_context_ The ServiceContext for the owning service. /// @param name_ The name for this display. /// @param system_ The global system instance. /// - Display(u64 id, std::string name_, NVFlinger::HosBinderDriverServer& hos_binder_driver_server_, + Display(u64 id, std::string name_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, KernelHelpers::ServiceContext& service_context_, Core::System& system_); ~Display(); @@ -133,7 +133,7 @@ public: private: u64 display_id; std::string name; - NVFlinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; KernelHelpers::ServiceContext& service_context; std::vector<std::unique_ptr<Layer>> layers; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index bb283e74e..1b193f00c 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -17,15 +17,16 @@ #include "common/settings.h" #include "common/swap.h" #include "core/core_timing.h" -#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvflinger/binder.h" -#include "core/hle/service/nvflinger/buffer_queue_producer.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvflinger/nvflinger.h" -#include "core/hle/service/nvflinger/parcel.h" +#include "core/hle/service/nvnflinger/binder.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/nvnflinger/parcel.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_m.h" @@ -63,8 +64,8 @@ public: private: const u32 magic = 2; const u32 process_id = 1; - const u32 id; - INSERT_PADDING_WORDS(3); + const u64 id; + INSERT_PADDING_WORDS(2); std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; INSERT_PADDING_WORDS(2); }; @@ -72,9 +73,8 @@ static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { public: - explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_) - : ServiceFramework{system_, "IHOSBinderDriver", ServiceThreadType::CreateNew}, - server(server_) { + explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_) + : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { static const FunctionInfo functions[] = { {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, @@ -85,7 +85,7 @@ public: } private: - void TransactParcel(Kernel::HLERequestContext& ctx) { + void TransactParcel(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 id = rp.Pop<u32>(); const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>()); @@ -100,7 +100,7 @@ private: rb.Push(ResultSuccess); } - void AdjustRefcount(Kernel::HLERequestContext& ctx) { + void AdjustRefcount(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 id = rp.Pop<u32>(); const s32 addval = rp.PopRaw<s32>(); @@ -113,7 +113,7 @@ private: rb.Push(ResultSuccess); } - void GetNativeHandle(Kernel::HLERequestContext& ctx) { + void GetNativeHandle(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 id = rp.Pop<u32>(); const u32 unknown = rp.Pop<u32>(); @@ -126,7 +126,7 @@ private: } private: - NVFlinger::HosBinderDriverServer& server; + Nvnflinger::HosBinderDriverServer& server; }; class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { @@ -186,7 +186,7 @@ public: } private: - void SetLayerZ(Kernel::HLERequestContext& ctx) { + void SetLayerZ(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 layer_id = rp.Pop<u64>(); const u64 z_value = rp.Pop<u64>(); @@ -200,7 +200,7 @@ private: // This function currently does nothing but return a success error code in // the vi library itself, so do the same thing, but log out the passed in values. - void SetLayerVisibility(Kernel::HLERequestContext& ctx) { + void SetLayerVisibility(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 layer_id = rp.Pop<u64>(); const bool visibility = rp.Pop<bool>(); @@ -211,7 +211,7 @@ private: rb.Push(ResultSuccess); } - void GetDisplayMode(Kernel::HLERequestContext& ctx) { + void GetDisplayMode(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 6}; @@ -232,7 +232,7 @@ private: class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { public: - explicit IManagerDisplayService(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) + explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_) : ServiceFramework{system_, "IManagerDisplayService"}, nv_flinger{nv_flinger_} { // clang-format off static const FunctionInfo functions[] = { @@ -249,6 +249,9 @@ public: {2053, nullptr, "DestroyIndirectProducerEndPoint"}, {2054, nullptr, "CreateIndirectConsumerEndPoint"}, {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, + {2060, nullptr, "CreateWatermarkCompositor"}, + {2062, nullptr, "SetWatermarkText"}, + {2063, nullptr, "SetWatermarkLayerStacks"}, {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, {2302, nullptr, "GetDisplayHotplugEvent"}, @@ -279,6 +282,8 @@ public: {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, {6013, nullptr, "SetLayerOpacity"}, + {6014, nullptr, "AttachLayerWatermarkCompositor"}, + {6015, nullptr, "DetachLayerWatermarkCompositor"}, {7000, nullptr, "SetContentVisibility"}, {8000, nullptr, "SetConductorLayer"}, {8001, nullptr, "SetTimestampTracking"}, @@ -320,7 +325,7 @@ public: } private: - void CloseDisplay(Kernel::HLERequestContext& ctx) { + void CloseDisplay(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 display = rp.Pop<u64>(); @@ -330,7 +335,7 @@ private: rb.Push(rc); } - void CreateManagedLayer(Kernel::HLERequestContext& ctx) { + void CreateManagedLayer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 unknown = rp.Pop<u32>(); rp.Skip(1, false); @@ -354,7 +359,7 @@ private: rb.Push(*layer_id); } - void AddToLayerStack(Kernel::HLERequestContext& ctx) { + void AddToLayerStack(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 stack = rp.Pop<u32>(); const u64 layer_id = rp.Pop<u64>(); @@ -366,7 +371,7 @@ private: rb.Push(ResultSuccess); } - void SetLayerVisibility(Kernel::HLERequestContext& ctx) { + void SetLayerVisibility(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 layer_id = rp.Pop<u64>(); const bool visibility = rp.Pop<bool>(); @@ -378,13 +383,13 @@ private: rb.Push(ResultSuccess); } - NVFlinger::NVFlinger& nv_flinger; + Nvnflinger::Nvnflinger& nv_flinger; }; class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { public: - IApplicationDisplayService(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_) + IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{hos_binder_driver_server_} { @@ -435,7 +440,7 @@ private: PreserveAspectRatio = 4, }; - void GetRelayService(Kernel::HLERequestContext& ctx) { + void GetRelayService(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -443,7 +448,7 @@ private: rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); } - void GetSystemDisplayService(Kernel::HLERequestContext& ctx) { + void GetSystemDisplayService(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -451,7 +456,7 @@ private: rb.PushIpcInterface<ISystemDisplayService>(system); } - void GetManagerDisplayService(Kernel::HLERequestContext& ctx) { + void GetManagerDisplayService(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -459,7 +464,7 @@ private: rb.PushIpcInterface<IManagerDisplayService>(system, nv_flinger); } - void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) { + void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -467,7 +472,7 @@ private: rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); } - void OpenDisplay(Kernel::HLERequestContext& ctx) { + void OpenDisplay(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); IPC::RequestParser rp{ctx}; @@ -476,13 +481,13 @@ private: OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); } - void OpenDefaultDisplay(Kernel::HLERequestContext& ctx) { + void OpenDefaultDisplay(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); OpenDisplayImpl(ctx, "Default"); } - void OpenDisplayImpl(Kernel::HLERequestContext& ctx, std::string_view name) { + void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { const auto trim_pos = name.find('\0'); if (trim_pos != std::string_view::npos) { @@ -504,7 +509,7 @@ private: rb.Push<u64>(*display_id); } - void CloseDisplay(Kernel::HLERequestContext& ctx) { + void CloseDisplay(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 display_id = rp.Pop<u64>(); @@ -516,14 +521,14 @@ private: // This literally does nothing internally in the actual service itself, // and just returns a successful result code regardless of the input. - void SetDisplayEnabled(Kernel::HLERequestContext& ctx) { + void SetDisplayEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called."); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } - void GetDisplayResolution(Kernel::HLERequestContext& ctx) { + void GetDisplayResolution(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 display_id = rp.Pop<u64>(); @@ -539,7 +544,7 @@ private: rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); } - void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { + void SetLayerScalingMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto scaling_mode = rp.PopEnum<NintendoScaleMode>(); const u64 unknown = rp.Pop<u64>(); @@ -565,7 +570,7 @@ private: rb.Push(ResultSuccess); } - void ListDisplays(Kernel::HLERequestContext& ctx) { + void ListDisplays(HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); const DisplayInfo display_info; @@ -575,7 +580,7 @@ private: rb.Push<u64>(1); } - void OpenLayer(Kernel::HLERequestContext& ctx) { + void OpenLayer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); @@ -603,7 +608,9 @@ private: return; } - const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); IPC::ResponseBuilder rb{ctx, 4}; @@ -611,7 +618,7 @@ private: rb.Push<u64>(buffer_size); } - void CloseLayer(Kernel::HLERequestContext& ctx) { + void CloseLayer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto layer_id{rp.Pop<u64>()}; @@ -623,7 +630,7 @@ private: rb.Push(ResultSuccess); } - void CreateStrayLayer(Kernel::HLERequestContext& ctx) { + void CreateStrayLayer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 flags = rp.Pop<u32>(); rp.Pop<u32>(); // padding @@ -649,7 +656,9 @@ private: return; } - const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); IPC::ResponseBuilder rb{ctx, 6}; @@ -658,7 +667,7 @@ private: rb.Push<u64>(buffer_size); } - void DestroyStrayLayer(Kernel::HLERequestContext& ctx) { + void DestroyStrayLayer(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 layer_id = rp.Pop<u64>(); @@ -668,7 +677,7 @@ private: rb.Push(ResultSuccess); } - void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) { + void GetDisplayVsyncEvent(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 display_id = rp.Pop<u64>(); @@ -691,7 +700,7 @@ private: rb.PushCopyObjects(*vsync_event); } - void ConvertScalingMode(Kernel::HLERequestContext& ctx) { + void ConvertScalingMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto mode = rp.PopEnum<NintendoScaleMode>(); LOG_DEBUG(Service_VI, "called mode={}", mode); @@ -708,7 +717,7 @@ private: } } - void GetIndirectLayerImageMap(Kernel::HLERequestContext& ctx) { + void GetIndirectLayerImageMap(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto width = rp.Pop<s64>(); const auto height = rp.Pop<s64>(); @@ -734,7 +743,7 @@ private: rb.Push(ResultSuccess); } - void GetIndirectLayerImageRequiredMemoryInfo(Kernel::HLERequestContext& ctx) { + void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto width = rp.Pop<u64>(); const auto height = rp.Pop<u64>(); @@ -769,8 +778,8 @@ private: } } - NVFlinger::NVFlinger& nv_flinger; - NVFlinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::Nvnflinger& nv_flinger; + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; }; static bool IsValidServiceAccess(Permission permission, Policy policy) { @@ -785,9 +794,9 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) { return false; } -void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system, - NVFlinger::NVFlinger& nv_flinger, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server, +void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, + Nvnflinger::Nvnflinger& nv_flinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission) { IPC::RequestParser rp{ctx}; const auto policy = rp.PopEnum<Policy>(); @@ -804,15 +813,17 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger, hos_binder_driver_server); } -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system, - NVFlinger::NVFlinger& nv_flinger, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server) { - std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server) - ->InstallAsService(service_manager); - std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server) - ->InstallAsService(service_manager); - std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server) - ->InstallAsService(service_manager); +void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService( + "vi:m", std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server)); + server_manager->RegisterNamedService( + "vi:s", std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server)); + server_manager->RegisterNamedService( + "vi:u", std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index fc2d717e7..a35b62f97 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -9,18 +9,14 @@ namespace Core { class System; } -namespace Kernel { +namespace Service { class HLERequestContext; } -namespace Service::NVFlinger { +namespace Service::Nvnflinger { class HosBinderDriverServer; -class NVFlinger; -} // namespace Service::NVFlinger - -namespace Service::SM { -class ServiceManager; -} +class Nvnflinger; +} // namespace Service::Nvnflinger namespace Service::VI { @@ -46,15 +42,13 @@ enum class Policy { }; namespace detail { -void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system, - NVFlinger::NVFlinger& nv_flinger, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server, +void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, + Nvnflinger::Nvnflinger& nv_flinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission); } // namespace detail -/// Registers all VI services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system, - NVFlinger::NVFlinger& nv_flinger, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server); +void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp index 1ab7fe4ab..0f06dc2f3 100644 --- a/src/core/hle/service/vi/vi_m.cpp +++ b/src/core/hle/service/vi/vi_m.cpp @@ -7,20 +7,24 @@ namespace Service::VI { -VI_M::VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_) +VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ hos_binder_driver_server_} { static const FunctionInfo functions[] = { {2, &VI_M::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, + {100, nullptr, "PrepareFatal"}, + {101, nullptr, "ShowFatal"}, + {102, nullptr, "DrawFatalRectangle"}, + {103, nullptr, "DrawFatalText32"}, }; RegisterHandlers(functions); } VI_M::~VI_M() = default; -void VI_M::GetDisplayService(Kernel::HLERequestContext& ctx) { +void VI_M::GetDisplayService(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h index 3bf76d439..9ca6f3905 100644 --- a/src/core/hle/service/vi/vi_m.h +++ b/src/core/hle/service/vi/vi_m.h @@ -9,28 +9,24 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - -namespace Service::NVFlinger { +namespace Service::Nvnflinger { class HosBinderDriverServer; -class NVFlinger; -} // namespace Service::NVFlinger +class Nvnflinger; +} // namespace Service::Nvnflinger namespace Service::VI { class VI_M final : public ServiceFramework<VI_M> { public: - explicit VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_); + explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); ~VI_M() override; private: - void GetDisplayService(Kernel::HLERequestContext& ctx); + void GetDisplayService(HLERequestContext& ctx); - NVFlinger::NVFlinger& nv_flinger; - NVFlinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::Nvnflinger& nv_flinger; + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp index fd799dac1..77f7a88ff 100644 --- a/src/core/hle/service/vi/vi_s.cpp +++ b/src/core/hle/service/vi/vi_s.cpp @@ -7,8 +7,8 @@ namespace Service::VI { -VI_S::VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_) +VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ hos_binder_driver_server_} { static const FunctionInfo functions[] = { @@ -20,7 +20,7 @@ VI_S::VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, VI_S::~VI_S() = default; -void VI_S::GetDisplayService(Kernel::HLERequestContext& ctx) { +void VI_S::GetDisplayService(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h index 97503ac7f..157839c91 100644 --- a/src/core/hle/service/vi/vi_s.h +++ b/src/core/hle/service/vi/vi_s.h @@ -9,28 +9,24 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - -namespace Service::NVFlinger { +namespace Service::Nvnflinger { class HosBinderDriverServer; -class NVFlinger; -} // namespace Service::NVFlinger +class Nvnflinger; +} // namespace Service::Nvnflinger namespace Service::VI { class VI_S final : public ServiceFramework<VI_S> { public: - explicit VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_); + explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); ~VI_S() override; private: - void GetDisplayService(Kernel::HLERequestContext& ctx); + void GetDisplayService(HLERequestContext& ctx); - NVFlinger::NVFlinger& nv_flinger; - NVFlinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::Nvnflinger& nv_flinger; + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp index 6cc54bd13..59e13c86b 100644 --- a/src/core/hle/service/vi/vi_u.cpp +++ b/src/core/hle/service/vi/vi_u.cpp @@ -7,8 +7,8 @@ namespace Service::VI { -VI_U::VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_) +VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ hos_binder_driver_server_} { static const FunctionInfo functions[] = { @@ -20,7 +20,7 @@ VI_U::VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, VI_U::~VI_U() = default; -void VI_U::GetDisplayService(Kernel::HLERequestContext& ctx) { +void VI_U::GetDisplayService(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h index 797941bd7..5d9ca54c6 100644 --- a/src/core/hle/service/vi/vi_u.h +++ b/src/core/hle/service/vi/vi_u.h @@ -9,28 +9,24 @@ namespace Core { class System; } -namespace Kernel { -class HLERequestContext; -} - -namespace Service::NVFlinger { +namespace Service::Nvnflinger { class HosBinderDriverServer; -class NVFlinger; -} // namespace Service::NVFlinger +class Nvnflinger; +} // namespace Service::Nvnflinger namespace Service::VI { class VI_U final : public ServiceFramework<VI_U> { public: - explicit VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_, - NVFlinger::HosBinderDriverServer& hos_binder_driver_server_); + explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); ~VI_U() override; private: - void GetDisplayService(Kernel::HLERequestContext& ctx); + void GetDisplayService(HLERequestContext& ctx); - NVFlinger::NVFlinger& nv_flinger; - NVFlinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::Nvnflinger& nv_flinger; + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; }; } // namespace Service::VI diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp deleted file mode 100644 index 226e3034c..000000000 --- a/src/core/hle/service/wlan/wlan.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <memory> - -#include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" -#include "core/hle/service/wlan/wlan.h" - -namespace Service::WLAN { - -class WLANInfra final : public ServiceFramework<WLANInfra> { -public: - explicit WLANInfra(Core::System& system_) : ServiceFramework{system_, "wlan:inf"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "OpenMode"}, - {1, nullptr, "CloseMode"}, - {2, nullptr, "GetMacAddress"}, - {3, nullptr, "StartScan"}, - {4, nullptr, "StopScan"}, - {5, nullptr, "Connect"}, - {6, nullptr, "CancelConnect"}, - {7, nullptr, "Disconnect"}, - {8, nullptr, "GetConnectionEvent"}, - {9, nullptr, "GetConnectionStatus"}, - {10, nullptr, "GetState"}, - {11, nullptr, "GetScanResult"}, - {12, nullptr, "GetRssi"}, - {13, nullptr, "ChangeRxAntenna"}, - {14, nullptr, "GetFwVersion"}, - {15, nullptr, "RequestSleep"}, - {16, nullptr, "RequestWakeUp"}, - {17, nullptr, "RequestIfUpDown"}, - {18, nullptr, "Unknown18"}, - {19, nullptr, "Unknown19"}, - {20, nullptr, "Unknown20"}, - {21, nullptr, "Unknown21"}, - {22, nullptr, "Unknown22"}, - {23, nullptr, "Unknown23"}, - {24, nullptr, "Unknown24"}, - {25, nullptr, "Unknown25"}, - {26, nullptr, "Unknown26"}, - {27, nullptr, "Unknown27"}, - {28, nullptr, "Unknown28"}, - {29, nullptr, "Unknown29"}, - {30, nullptr, "Unknown30"}, - {31, nullptr, "Unknown31"}, - {32, nullptr, "Unknown32"}, - {33, nullptr, "Unknown33"}, - {34, nullptr, "Unknown34"}, - {35, nullptr, "Unknown35"}, - {36, nullptr, "Unknown36"}, - {37, nullptr, "Unknown37"}, - {38, nullptr, "Unknown38"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANLocal final : public ServiceFramework<WLANLocal> { -public: - explicit WLANLocal(Core::System& system_) : ServiceFramework{system_, "wlan:lcl"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown0"}, - {1, nullptr, "Unknown1"}, - {2, nullptr, "Unknown2"}, - {3, nullptr, "Unknown3"}, - {4, nullptr, "Unknown4"}, - {5, nullptr, "Unknown5"}, - {6, nullptr, "GetMacAddress"}, - {7, nullptr, "CreateBss"}, - {8, nullptr, "DestroyBss"}, - {9, nullptr, "StartScan"}, - {10, nullptr, "StopScan"}, - {11, nullptr, "Connect"}, - {12, nullptr, "CancelConnect"}, - {13, nullptr, "Join"}, - {14, nullptr, "CancelJoin"}, - {15, nullptr, "Disconnect"}, - {16, nullptr, "SetBeaconLostCount"}, - {17, nullptr, "Unknown17"}, - {18, nullptr, "Unknown18"}, - {19, nullptr, "Unknown19"}, - {20, nullptr, "GetBssIndicationEvent"}, - {21, nullptr, "GetBssIndicationInfo"}, - {22, nullptr, "GetState"}, - {23, nullptr, "GetAllowedChannels"}, - {24, nullptr, "AddIe"}, - {25, nullptr, "DeleteIe"}, - {26, nullptr, "Unknown26"}, - {27, nullptr, "Unknown27"}, - {28, nullptr, "CreateRxEntry"}, - {29, nullptr, "DeleteRxEntry"}, - {30, nullptr, "Unknown30"}, - {31, nullptr, "Unknown31"}, - {32, nullptr, "AddMatchingDataToRxEntry"}, - {33, nullptr, "RemoveMatchingDataFromRxEntry"}, - {34, nullptr, "GetScanResult"}, - {35, nullptr, "Unknown35"}, - {36, nullptr, "SetActionFrameWithBeacon"}, - {37, nullptr, "CancelActionFrameWithBeacon"}, - {38, nullptr, "CreateRxEntryForActionFrame"}, - {39, nullptr, "DeleteRxEntryForActionFrame"}, - {40, nullptr, "Unknown40"}, - {41, nullptr, "Unknown41"}, - {42, nullptr, "CancelGetActionFrame"}, - {43, nullptr, "GetRssi"}, - {44, nullptr, "Unknown44"}, - {45, nullptr, "Unknown45"}, - {46, nullptr, "Unknown46"}, - {47, nullptr, "Unknown47"}, - {48, nullptr, "Unknown48"}, - {49, nullptr, "Unknown49"}, - {50, nullptr, "Unknown50"}, - {51, nullptr, "Unknown51"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANLocalGetFrame final : public ServiceFramework<WLANLocalGetFrame> { -public: - explicit WLANLocalGetFrame(Core::System& system_) : ServiceFramework{system_, "wlan:lg"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANSocketGetFrame final : public ServiceFramework<WLANSocketGetFrame> { -public: - explicit WLANSocketGetFrame(Core::System& system_) : ServiceFramework{system_, "wlan:sg"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANSocketManager final : public ServiceFramework<WLANSocketManager> { -public: - explicit WLANSocketManager(Core::System& system_) : ServiceFramework{system_, "wlan:soc"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown0"}, - {1, nullptr, "Unknown1"}, - {2, nullptr, "Unknown2"}, - {3, nullptr, "Unknown3"}, - {4, nullptr, "Unknown4"}, - {5, nullptr, "Unknown5"}, - {6, nullptr, "GetMacAddress"}, - {7, nullptr, "SwitchTsfTimerFunction"}, - {8, nullptr, "Unknown8"}, - {9, nullptr, "Unknown9"}, - {10, nullptr, "Unknown10"}, - {11, nullptr, "Unknown11"}, - {12, nullptr, "Unknown12"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<WLANInfra>(system)->InstallAsService(sm); - std::make_shared<WLANLocal>(system)->InstallAsService(sm); - std::make_shared<WLANLocalGetFrame>(system)->InstallAsService(sm); - std::make_shared<WLANSocketGetFrame>(system)->InstallAsService(sm); - std::make_shared<WLANSocketManager>(system)->InstallAsService(sm); -} - -} // namespace Service::WLAN diff --git a/src/core/hle/service/wlan/wlan.h b/src/core/hle/service/wlan/wlan.h deleted file mode 100644 index 535c3bf0d..000000000 --- a/src/core/hle/service/wlan/wlan.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace Core { -class System; -} - -namespace Service::SM { -class ServiceManager; -} - -namespace Service::WLAN { - -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); - -} // namespace Service::WLAN |
