From 00800d5289f580ffebd38f18d1c3d7e024fc3b16 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 13 Apr 2023 20:55:47 -0600 Subject: service: nfp: Implement system interface --- src/core/hle/service/nfp/nfp.cpp | 32 ++--- src/core/hle/service/nfp/nfp_device.cpp | 52 +++++++- src/core/hle/service/nfp/nfp_device.h | 2 + src/core/hle/service/nfp/nfp_interface.cpp | 202 +++++++++++++++++++++++++++++ src/core/hle/service/nfp/nfp_interface.h | 9 ++ src/core/hle/service/nfp/nfp_types.h | 9 ++ 6 files changed, 289 insertions(+), 17 deletions(-) diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index e57e932c8..8a7365f17 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -51,8 +51,8 @@ public: explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "InitializeSystem"}, - {1, nullptr, "FinalizeSystem"}, + {0, &ISystem::InitializeSystem, "InitializeSystem"}, + {1, &ISystem::FinalizeSystem, "FinalizeSystem"}, {2, &ISystem::ListDevices, "ListDevices"}, {3, &ISystem::StartDetection, "StartDetection"}, {4, &ISystem::StopDetection, "StopDetection"}, @@ -71,13 +71,13 @@ public: {20, &ISystem::GetDeviceState, "GetDeviceState"}, {21, &ISystem::GetNpadId, "GetNpadId"}, {23, &ISystem::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, - {100, nullptr, "Format"}, - {101, nullptr, "GetAdminInfo"}, - {102, nullptr, "GetRegisterInfoPrivate"}, - {103, nullptr, "SetRegisterInfoPrivate"}, - {104, nullptr, "DeleteRegisterInfo"}, - {105, nullptr, "DeleteApplicationArea"}, - {106, nullptr, "ExistsApplicationArea"}, + {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 @@ -115,13 +115,13 @@ public: {22, &IDebug::GetApplicationAreaSize, "GetApplicationAreaSize"}, {23, &IDebug::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, {24, &IDebug::RecreateApplicationArea, "RecreateApplicationArea"}, - {100, nullptr, "Format"}, - {101, nullptr, "GetAdminInfo"}, - {102, nullptr, "GetRegisterInfoPrivate"}, - {103, nullptr, "SetRegisterInfoPrivate"}, - {104, nullptr, "DeleteRegisterInfo"}, - {105, nullptr, "DeleteApplicationArea"}, - {106, nullptr, "ExistsApplicationArea"}, + {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, nullptr, "GetAll"}, {201, nullptr, "SetAll"}, {202, nullptr, "FlushDebug"}, diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index 607e70968..5ed6d4181 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -29,7 +29,6 @@ #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" @@ -417,6 +416,38 @@ Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const { return ResultSuccess; } +Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& 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 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 NfpDevice::GetAdminInfo(AdminInfo& admin_info) const { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); @@ -807,6 +838,25 @@ Result NfpDevice::DeleteApplicationArea() { return Flush(); } +Result NfpDevice::ExistApplicationArea(bool& has_application_area) { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "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_NFC, "Amiibo is read only", device_state); + return WrongDeviceState; + } + + has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0; + + return ResultSuccess; +} + u64 NfpDevice::GetHandle() const { // Generate a handle based of the npad id return static_cast(npad_id); diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 7f963730d..0d778c1d7 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -47,6 +47,7 @@ public: Result GetCommonInfo(CommonInfo& common_info) const; Result GetModelInfo(ModelInfo& model_info) const; Result GetRegisterInfo(RegisterInfo& register_info) const; + Result GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const; Result GetAdminInfo(AdminInfo& admin_info) const; Result DeleteRegisterInfo(); @@ -61,6 +62,7 @@ public: Result CreateApplicationArea(u32 access_id, std::span data); Result RecreateApplicationArea(u32 access_id, std::span data); Result DeleteApplicationArea(); + Result ExistApplicationArea(bool& has_application_area); u64 GetHandle() const; u32 GetApplicationAreaSize() const; diff --git a/src/core/hle/service/nfp/nfp_interface.cpp b/src/core/hle/service/nfp/nfp_interface.cpp index e131703cb..d60f3cb97 100644 --- a/src/core/hle/service/nfp/nfp_interface.cpp +++ b/src/core/hle/service/nfp/nfp_interface.cpp @@ -40,6 +40,19 @@ void Interface::Initialize(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void Interface::InitializeSystem(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 Interface::Finalize(HLERequestContext& ctx) { LOG_INFO(Service_NFP, "called"); @@ -53,6 +66,19 @@ void Interface::Finalize(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void Interface::FinalizeSystem(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 Interface::ListDevices(HLERequestContext& ctx) { LOG_DEBUG(Service_NFP, "called"); @@ -631,6 +657,182 @@ void Interface::RecreateApplicationArea(HLERequestContext& ctx) { rb.Push(result); } +void Interface::Format(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop()}; + 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; + } + + const auto result = device.value()->Format(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::GetAdminInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop()}; + 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; + } + + AdminInfo admin_info{}; + const auto result = device.value()->GetAdminInfo(admin_info); + 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()}; + 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; + } + + RegisterInfoPrivate register_info{}; + const auto result = device.value()->GetRegisterInfoPrivate(register_info); + 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()}; + const auto buffer{ctx.ReadBuffer()}; + LOG_DEBUG(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle, + buffer.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()->SetRegisterInfoPrivate({}); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::DeleteRegisterInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop()}; + 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; + } + + const auto result = device.value()->DeleteRegisterInfo(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::DeleteApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop()}; + 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; + } + + const auto result = device.value()->DeleteApplicationArea(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void Interface::ExistsApplicationArea(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop()}; + 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; + } + + bool has_application_area = false; + const auto result = device.value()->ExistApplicationArea(has_application_area); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(result); + rb.Push(has_application_area); +} + std::optional> Interface::GetNfpDevice(u64 handle) { for (auto& device : devices) { if (device->GetHandle() == handle) { diff --git a/src/core/hle/service/nfp/nfp_interface.h b/src/core/hle/service/nfp/nfp_interface.h index 11f29c2ba..4affdbc0c 100644 --- a/src/core/hle/service/nfp/nfp_interface.h +++ b/src/core/hle/service/nfp/nfp_interface.h @@ -19,7 +19,9 @@ public: ~Interface() override; void Initialize(HLERequestContext& ctx); + void InitializeSystem(HLERequestContext& ctx); void Finalize(HLERequestContext& ctx); + void FinalizeSystem(HLERequestContext& ctx); void ListDevices(HLERequestContext& ctx); void StartDetection(HLERequestContext& ctx); void StopDetection(HLERequestContext& ctx); @@ -43,6 +45,13 @@ public: void GetApplicationAreaSize(HLERequestContext& ctx); void AttachAvailabilityChangeEvent(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); private: enum class State : u32 { diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 70c878552..90429baa2 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -354,6 +354,15 @@ struct RegisterInfo { }; static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); +struct RegisterInfoPrivate { + Service::Mii::MiiStoreData mii_store_data; + WriteDate creation_date; + AmiiboName amiibo_name; + u8 font_region; + INSERT_PADDING_BYTES(0x8E); +}; +static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size"); + struct AdminInfo { u64 application_id; u32 application_area_id; -- cgit v1.2.3