diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/nfc/common/amiibo_crypto.cpp (renamed from src/core/hle/service/nfp/amiibo_crypto.cpp) | 4 | ||||
-rw-r--r-- | src/core/hle/service/nfc/common/amiibo_crypto.h (renamed from src/core/hle/service/nfp/amiibo_crypto.h) | 4 | ||||
-rw-r--r-- | src/core/hle/service/nfc/common/device.cpp (renamed from src/core/hle/service/nfp/nfp_device.cpp) | 695 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp.cpp | 36 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_device.h | 120 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_interface.cpp | 839 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_interface.h | 37 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_result.h | 29 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_types.h | 129 |
9 files changed, 578 insertions, 1315 deletions
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp index a3622e792..f3901ee8d 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 { @@ -55,7 +55,7 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { 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) { diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h index f6208ee6b..bf3044ed9 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.h +++ b/src/core/hle/service/nfc/common/amiibo_crypto.h @@ -24,9 +24,9 @@ using DrgbOutput = std::array<u8, 0x20>; struct HashSeed { u16_be magic; std::array<u8, 0xE> padding; - UniqueSerialNumber uid_1; + NFC::UniqueSerialNumber uid_1; u8 nintendo_id_1; - UniqueSerialNumber uid_2; + NFC::UniqueSerialNumber uid_2; u8 nintendo_id_2; std::array<u8, 0x20> keygen_salt; }; diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfc/common/device.cpp index 3f9af53c8..322bde2ed 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -1,8 +1,6 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <array> - #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used @@ -26,21 +24,22 @@ #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/nfp/amiibo_crypto.h" -#include "core/hle/service/nfp/nfp_device.h" -#include "core/hle/service/nfp/nfp_result.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::NFP { -NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, +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:NFPActivateEvent"); - deactivate_event = service_context.CreateEvent("IUser:NFPDeactivateEvent"); + 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{ @@ -49,14 +48,11 @@ NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, }; 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(); +NfcDevice::~NfcDevice() { + service_context.CloseEvent(activate_event); + service_context.CloseEvent(deactivate_event); if (!is_controller_set) { return; } @@ -64,7 +60,7 @@ NfpDevice::~NfpDevice() { is_controller_set = false; }; -void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { +void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { if (!is_initalized) { return; } @@ -92,14 +88,14 @@ void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { const auto nfc_status = npad_device->GetNfc(); switch (nfc_status.state) { case Common::Input::NfcState::NewAmiibo: - LoadAmiibo(nfc_status.data); + LoadNfcTag(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(); + CloseNfcTag(); } break; default: @@ -107,28 +103,29 @@ void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { } } -bool NfpDevice::LoadAmiibo(std::span<const u8> data) { +bool NfcDevice::LoadNfcTag(std::span<const u8> data) { if (device_state != DeviceState::SearchingForTag) { - LOG_ERROR(Service_NFP, "Game is not looking for amiibos, current state {}", device_state); + LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state); return false; } - if (data.size() != sizeof(EncryptedNTAG215File)) { - LOG_ERROR(Service_NFP, "Not an amiibo, size={}", data.size()); + if (data.size() < sizeof(NFP::EncryptedNTAG215File)) { + LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); return false; } - // TODO: Filter by allowed_protocols here + mifare_data.resize(data.size()); + memcpy(mifare_data.data(), data.data(), data.size()); - memcpy(&tag_data, data.data(), sizeof(EncryptedNTAG215File)); - is_plain_amiibo = AmiiboCrypto::IsAmiiboValid(tag_data); + memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data); if (is_plain_amiibo) { - encrypted_tag_data = AmiiboCrypto::EncodedDataToNfcData(tag_data); + encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(tag_data); LOG_INFO(Service_NFP, "Using plain amiibo"); } else { tag_data = {}; - memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); + memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); } device_state = DeviceState::TagFound; @@ -137,8 +134,8 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) { return true; } -void NfpDevice::CloseAmiibo() { - LOG_INFO(Service_NFP, "Remove amiibo"); +void NfcDevice::CloseNfcTag() { + LOG_INFO(Service_NFC, "Remove nfc tag"); if (device_state == DeviceState::TagMounted) { Unmount(); @@ -147,26 +144,28 @@ void NfpDevice::CloseAmiibo() { device_state = DeviceState::TagRemoved; encrypted_tag_data = {}; tag_data = {}; + mifare_data = {}; activate_event->GetReadableEvent().Clear(); deactivate_event->Signal(); } -Kernel::KReadableEvent& NfpDevice::GetActivateEvent() const { +Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { return activate_event->GetReadableEvent(); } -Kernel::KReadableEvent& NfpDevice::GetDeactivateEvent() const { +Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const { return deactivate_event->GetReadableEvent(); } -void NfpDevice::Initialize() { +void NfcDevice::Initialize() { device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable; encrypted_tag_data = {}; tag_data = {}; + mifare_data = {}; is_initalized = true; } -void NfpDevice::Finalize() { +void NfcDevice::Finalize() { if (device_state == DeviceState::TagMounted) { Unmount(); } @@ -177,17 +176,17 @@ void NfpDevice::Finalize() { is_initalized = false; } -Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { +Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) { if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + return ResultWrongDeviceState; } if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::NFC) != Common::Input::DriverResult::Success) { - LOG_ERROR(Service_NFP, "Nfc not supported"); - return NfcDisabled; + LOG_ERROR(Service_NFC, "Nfc not supported"); + return ResultNfcDisabled; } device_state = DeviceState::SearchingForTag; @@ -195,7 +194,7 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { return ResultSuccess; } -Result NfpDevice::StopDetection() { +Result NfcDevice::StopDetection() { npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Active); @@ -204,7 +203,7 @@ Result NfpDevice::StopDetection() { } if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { - CloseAmiibo(); + CloseNfcTag(); } if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { @@ -212,94 +211,139 @@ Result NfpDevice::StopDetection() { return ResultSuccess; } - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + return ResultWrongDeviceState; } -Result NfpDevice::Flush() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); +Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) 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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } + UniqueSerialNumber uuid = encrypted_tag_data.uuid.uid; - auto& settings = tag_data.settings; + // Generate random UUID to bypass amiibo load limits + if (Settings::values.random_amiibo_id) { + Common::TinyMT rng{}; + rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); + rng.GenerateRandomBytes(uuid.data(), sizeof(UniqueSerialNumber)); + uuid[3] = 0x88 ^ uuid[0] ^ uuid[1] ^ uuid[2]; + } - const auto& current_date = GetAmiiboDate(current_posix_time); - if (settings.write_date.raw_date != current_date.raw_date) { - settings.write_date = current_date; - UpdateSettingsCrc(); + if (is_mifare) { + tag_info = { + .uuid = uuid, + .uuid_extension = {}, + .uuid_length = static_cast<u8>(uuid.size()), + .protocol = NfcProtocol::TypeA, + .tag_type = TagType::Type4, + }; + return ResultSuccess; } - tag_data.write_counter++; + // Protocol and tag type may change here + tag_info = { + .uuid = uuid, + .uuid_extension = {}, + .uuid_length = static_cast<u8>(uuid.size()), + .protocol = NfcProtocol::TypeA, + .tag_type = TagType::Type2, + }; - FlushWithBreak(BreakType::Normal); + return ResultSuccess; +} - is_data_moddified = false; +Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameters, + std::span<MifareReadBlockData> read_block_data) const { + Result result = ResultSuccess; - return ResultSuccess; + for (std::size_t i = 0; i < parameters.size(); i++) { + result = ReadMifare(parameters[i], read_block_data[i]); + if (result.IsError()) { + break; + } + } + + return result; } -Result NfpDevice::FlushDebug() { - if (device_state != DeviceState::TagMounted) { +Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter, + MifareReadBlockData& read_block_data) const { + const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); + read_block_data.sector_number = parameter.sector_number; + + if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + if (mifare_data.size() < sector_index + sizeof(DataBlock)) { + return Mifare::ResultReadError; } - tag_data.write_counter++; - - FlushWithBreak(BreakType::Normal); - - is_data_moddified = false; + // TODO: Use parameter.sector_key to read encrypted data + memcpy(read_block_data.data.data(), mifare_data.data() + sector_index, sizeof(DataBlock)); return ResultSuccess; } -Result NfpDevice::FlushWithBreak(BreakType break_type) { - if (break_type != BreakType::Normal) { - LOG_ERROR(Service_NFC, "Break type not implemented {}", break_type); - return WrongDeviceState; - } +Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> parameters) { + Result result = ResultSuccess; - std::vector<u8> data(sizeof(EncryptedNTAG215File)); - if (is_plain_amiibo) { - memcpy(data.data(), &tag_data, sizeof(tag_data)); - } else { - if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { - LOG_ERROR(Service_NFP, "Failed to encode data"); - return WriteAmiiboFailed; + for (std::size_t i = 0; i < parameters.size(); i++) { + result = WriteMifare(parameters[i]); + if (result.IsError()) { + break; } - - memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); } - if (!npad_device->WriteNfc(data)) { + if (!npad_device->WriteNfc(mifare_data)) { LOG_ERROR(Service_NFP, "Error writing to file"); - return WriteAmiiboFailed; + return Mifare::ResultReadError; + } + + return result; +} + +Result NfcDevice::WriteMifare(const MifareWriteBlockParameter& parameter) { + const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); + + 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; + } + + if (mifare_data.size() < sector_index + sizeof(DataBlock)) { + return Mifare::ResultReadError; } + // TODO: Use parameter.sector_key to encrypt the data + memcpy(mifare_data.data() + sector_index, parameter.data.data(), sizeof(DataBlock)); + + return ResultSuccess; +} + +Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout, + std::span<const u8> command_data, + std::span<u8> out_data) { + // Not implemented return ResultSuccess; } -Result NfpDevice::Mount(MountTarget mount_target_) { +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 WrongDeviceState; + return ResultWrongDeviceState; } // The loaded amiibo is not encrypted @@ -309,22 +353,22 @@ Result NfpDevice::Mount(MountTarget mount_target_) { return ResultSuccess; } - if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { + if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { LOG_ERROR(Service_NFP, "Not an amiibo"); - return NotAnAmiibo; + return ResultNotAnAmiibo; } // Mark amiibos as read only when keys are missing - if (!AmiiboCrypto::IsKeyAvailable()) { + if (!NFP::AmiiboCrypto::IsKeyAvailable()) { LOG_ERROR(Service_NFP, "No keys detected"); device_state = DeviceState::TagMounted; - mount_target = MountTarget::Rom; + mount_target = NFP::MountTarget::Rom; return ResultSuccess; } - if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { + if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state); - return CorruptedData; + return ResultCorruptedData; } device_state = DeviceState::TagMounted; @@ -332,13 +376,13 @@ Result NfpDevice::Mount(MountTarget mount_target_) { return ResultSuccess; } -Result NfpDevice::Unmount() { +Result NfcDevice::Unmount() { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } // Save data before unloading the amiibo @@ -347,43 +391,123 @@ Result NfpDevice::Unmount() { } device_state = DeviceState::TagFound; - mount_target = MountTarget::None; + mount_target = NFP::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) { +Result NfcDevice::Flush() { + if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - 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, - }; + 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++; + + FlushWithBreak(NFP::BreakType::Normal); + + is_data_moddified = false; + + return ResultSuccess; +} + +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++; + + FlushWithBreak(NFP::BreakType::Normal); + + is_data_moddified = false; + + return ResultSuccess; +} + +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; + } + + std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); + if (is_plain_amiibo) { + memcpy(data.data(), &tag_data, sizeof(tag_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)); + } + + if (!npad_device->WriteNfc(data)) { + LOG_ERROR(Service_NFP, "Error writing to file"); + return ResultWriteAmiiboFailed; + } return ResultSuccess; } -Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const { +Result NfcDevice::Restore() { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { + LOG_ERROR(Service_NFC, "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::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 WrongDeviceState; + return ResultWrongDeviceState; } const auto& settings = tag_data.settings; @@ -393,21 +517,22 @@ Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const { .last_write_date = settings.write_date.GetWriteDate(), .write_counter = tag_data.write_counter, .version = tag_data.amiibo_version, - .application_area_size = sizeof(ApplicationArea), + .application_area_size = sizeof(NFP::ApplicationArea), }; return ResultSuccess; } -Result NfpDevice::GetModelInfo(ModelInfo& model_info) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + 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, @@ -418,22 +543,22 @@ Result NfpDevice::GetModelInfo(ModelInfo& model_info) const { return ResultSuccess; } -Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; + return ResultRegistrationIsNotInitialized; } Service::Mii::MiiManager manager; @@ -450,22 +575,22 @@ Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const { return ResultSuccess; } -Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; + return ResultRegistrationIsNotInitialized; } Service::Mii::MiiManager manager; @@ -482,18 +607,18 @@ Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) con return ResultSuccess; } -Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } u8 flags = static_cast<u8>(tag_data.settings.settings.raw >> 0x4); @@ -503,17 +628,18 @@ Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const { u64 application_id = 0; u32 application_area_id = 0; - AppAreaVersion app_area_version = AppAreaVersion::NotSet; + 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<AppAreaVersion>(application_id >> application_id_version_offset & 0xf); + 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) << application_id_version_offset); + application_id = + RemoveVersionByte(application_id) | + (static_cast<u64>(application_byte) << NFP::application_id_version_offset); } application_area_id = tag_data.application_area_id; @@ -532,25 +658,26 @@ Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const { return ResultSuccess; } -Result NfpDevice::DeleteRegisterInfo() { +Result NfcDevice::DeleteRegisterInfo() { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; + 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)); @@ -564,18 +691,18 @@ Result NfpDevice::DeleteRegisterInfo() { return Flush(); } -Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } Service::Mii::MiiManager manager; @@ -583,11 +710,11 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { auto& settings = tag_data.settings; if (tag_data.settings.settings.amiibo_initialized == 0) { - settings.init_date = GetAmiiboDate(current_posix_time); + settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); settings.write_date.raw_date = 0; } - SetAmiiboName(settings, amiibo_name); + SetAmiiboName(settings, register_info.amiibo_name); tag_data.owner_mii = manager.BuildFromStoreData(mii); tag_data.mii_extension = manager.SetFromStoreData(mii); tag_data.unknown = 0; @@ -601,18 +728,18 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { return Flush(); } -Result NfpDevice::RestoreAmiibo() { +Result NfcDevice::RestoreAmiibo() { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } // TODO: Load amiibo from backup on system @@ -620,7 +747,7 @@ Result NfpDevice::RestoreAmiibo() { return ResultSuccess; } -Result NfpDevice::Format() { +Result NfcDevice::Format() { auto result1 = DeleteApplicationArea(); auto result2 = DeleteRegisterInfo(); @@ -635,28 +762,28 @@ Result NfpDevice::Format() { return Flush(); } -Result NfpDevice::OpenApplicationArea(u32 access_id) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.appdata_initialized.Value() == 0) { LOG_WARNING(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; + return ResultApplicationAreaIsNotInitialized; } if (tag_data.application_area_id != access_id) { LOG_WARNING(Service_NFP, "Wrong application area id"); - return WrongApplicationAreaId; + return ResultWrongApplicationAreaId; } is_app_area_open = true; @@ -664,25 +791,25 @@ Result NfpDevice::OpenApplicationArea(u32 access_id) { return ResultSuccess; } -Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.appdata_initialized.Value() == 0) { LOG_WARNING(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; + return ResultApplicationAreaIsNotInitialized; } application_area_id = tag_data.application_area_id; @@ -690,75 +817,73 @@ Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { return ResultSuccess; } -Result NfpDevice::GetApplicationArea(std::vector<u8>& data) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (!is_app_area_open) { LOG_ERROR(Service_NFP, "Application area is not open"); - return WrongDeviceState; + return ResultWrongDeviceState; } 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)); + return ResultApplicationAreaIsNotInitialized; } - memcpy(data.data(), tag_data.application_area.data(), data.size()); + memcpy(data.data(), tag_data.application_area.data(), + std::min(data.size(), sizeof(NFP::ApplicationArea))); return ResultSuccess; } -Result NfpDevice::SetApplicationArea(std::span<const u8> data) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (!is_app_area_open) { LOG_ERROR(Service_NFP, "Application area is not open"); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.appdata_initialized.Value() == 0) { LOG_ERROR(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; + return ResultApplicationAreaIsNotInitialized; } - if (data.size() > sizeof(ApplicationArea)) { + 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(ApplicationArea) - data.size()); + sizeof(NFP::ApplicationArea) - data.size()); - if (tag_data.application_write_counter != counter_limit) { + if (tag_data.application_write_counter != NFP::counter_limit) { tag_data.application_write_counter++; } @@ -767,64 +892,65 @@ Result NfpDevice::SetApplicationArea(std::span<const u8> data) { return ResultSuccess; } -Result NfpDevice::CreateApplicationArea(u32 access_id, std::span<const u8> data) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.appdata_initialized.Value() != 0) { LOG_ERROR(Service_NFP, "Application area already exist"); - return ApplicationAreaExist; + return ResultApplicationAreaExist; } return RecreateApplicationArea(access_id, data); } -Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> 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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } if (is_app_area_open) { LOG_ERROR(Service_NFP, "Application area is open"); - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } - if (data.size() > sizeof(ApplicationArea)) { + if (data.size() > sizeof(NFP::ApplicationArea)) { LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); - return WrongApplicationAreaSize; + 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(ApplicationArea) - data.size()); + sizeof(NFP::ApplicationArea) - data.size()); - if (tag_data.application_write_counter != counter_limit) { + 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 >> application_id_version_offset & 0xf); + static_cast<u8>(application_id >> NFP::application_id_version_offset & 0xf); tag_data.application_id = - RemoveVersionByte(application_id) | - (static_cast<u64>(AppAreaVersion::NintendoSwitch) << application_id_version_offset); + 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 = {}; @@ -835,30 +961,31 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat return Flush(); } -Result NfpDevice::DeleteApplicationArea() { +Result NfcDevice::DeleteApplicationArea() { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { - return TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } if (tag_data.settings.settings.appdata_initialized == 0) { - return ApplicationAreaIsNotInitialized; + return ResultApplicationAreaIsNotInitialized; } - if (tag_data.application_write_counter != counter_limit) { + if (tag_data.application_write_counter != NFP::counter_limit) { tag_data.application_write_counter++; } Common::TinyMT rng{}; - rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(ApplicationArea)); + 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)); @@ -872,18 +999,18 @@ Result NfpDevice::DeleteApplicationArea() { return Flush(); } -Result NfpDevice::ExistApplicationArea(bool& has_application_area) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0; @@ -891,21 +1018,21 @@ Result NfpDevice::ExistApplicationArea(bool& has_application_area) { return ResultSuccess; } -Result NfpDevice::GetAll(NfpData& data) const { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } - CommonInfo common_info{}; + NFP::CommonInfo common_info{}; Service::Mii::MiiManager manager; const u64 application_id = tag_data.application_id; @@ -930,8 +1057,8 @@ Result NfpDevice::GetAll(NfpData& data) const { .settings_crc_counter = tag_data.settings.crc_counter, .font_region = tag_data.settings.settings.font_region, .tag_type = PackedTagType::Type2, - .console_type = - static_cast<AppAreaVersion>(application_id >> application_id_version_offset & 0xf), + .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, }; @@ -939,18 +1066,18 @@ Result NfpDevice::GetAll(NfpData& data) const { return ResultSuccess; } -Result NfpDevice::SetAll(const NfpData& data) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } tag_data.constant_value = data.magic; @@ -977,18 +1104,18 @@ Result NfpDevice::SetAll(const NfpData& data) { return ResultSuccess; } -Result NfpDevice::BreakTag(BreakType break_type) { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } // TODO: Complete this implementation @@ -996,28 +1123,28 @@ Result NfpDevice::BreakTag(BreakType break_type) { return FlushWithBreak(break_type); } -Result NfpDevice::ReadBackupData() { +Result NfcDevice::ReadBackupData(std::span<u8> data) const { // Not implemented return ResultSuccess; } -Result NfpDevice::WriteBackupData() { +Result NfcDevice::WriteBackupData(std::span<const u8> data) { // Not implemented return ResultSuccess; } -Result NfpDevice::WriteNtf() { +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 TagRemoved; + return ResultTagRemoved; } - return WrongDeviceState; + return ResultWrongDeviceState; } - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; + return ResultWrongDeviceState; } // Not implemented @@ -1025,29 +1152,12 @@ Result NfpDevice::WriteNtf() { return ResultSuccess; } -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{}; +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 < amiibo_name_length; i++) { + for (std::size_t i = 0; i < NFP::amiibo_name_length; i++) { settings_amiibo_name[i] = static_cast<u16>(settings.amiibo_name[i]); } @@ -1058,8 +1168,8 @@ AmiiboName NfpDevice::GetAmiiboName(const AmiiboSettings& settings) const { return amiibo_name; } -void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name) { - std::array<char16_t, amiibo_name_length> settings_amiibo_name{}; +void NfcDevice::SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name) { + 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()); @@ -1067,16 +1177,16 @@ void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo 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++) { + for (std::size_t i = 0; i < NFP::amiibo_name_length; i++) { settings.amiibo_name[i] = static_cast<u16_be>(settings_amiibo_name[i]); } } -AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const { +NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const { const auto& time_zone_manager = system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager(); Time::TimeZone::CalendarInfo calendar_info{}; - AmiiboDate amiibo_date{}; + NFP::AmiiboDate amiibo_date{}; amiibo_date.SetYear(2000); amiibo_date.SetMonth(1); @@ -1091,14 +1201,19 @@ AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const { return amiibo_date; } -u64 NfpDevice::RemoveVersionByte(u64 application_id) const { - return application_id & ~(0xfULL << application_id_version_offset); +u64 NfcDevice::GetCurrentPosixTime() const { + auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()}; + return standard_steady_clock.GetCurrentTimePoint(system).time_point; } -void NfpDevice::UpdateSettingsCrc() { +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 != counter_limit) { + if (settings.crc_counter != NFP::counter_limit) { settings.crc_counter++; } @@ -1109,7 +1224,7 @@ void NfpDevice::UpdateSettingsCrc() { settings.crc = crc.checksum(); } -void NfpDevice::UpdateRegisterInfoCrc() { +void NfcDevice::UpdateRegisterInfoCrc() { #pragma pack(push, 1) struct CrcData { Mii::Ver3StoreData mii; @@ -1134,4 +1249,18 @@ void NfpDevice::UpdateRegisterInfoCrc() { tag_data.register_info_crc = crc.checksum(); } -} // namespace Service::NFP +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/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 2714f4bea..2eeabc138 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -13,7 +13,7 @@ class IUser final : public Interface { public: explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") { // clang-format off - static const FunctionInfo functions[] = { + static const FunctionInfoTyped<IUser> functions[] = { {0, &IUser::Initialize, "Initialize"}, {1, &IUser::Finalize, "Finalize"}, {2, &IUser::ListDevices, "ListDevices"}, @@ -50,7 +50,7 @@ class ISystem final : public Interface { public: explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") { // clang-format off - static const FunctionInfo functions[] = { + static const FunctionInfoTyped<ISystem> functions[] = { {0, &ISystem::InitializeSystem, "InitializeSystem"}, {1, &ISystem::FinalizeSystem, "FinalizeSystem"}, {2, &ISystem::ListDevices, "ListDevices"}, @@ -89,7 +89,7 @@ class IDebug final : public Interface { public: explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") { // clang-format off - static const FunctionInfo functions[] = { + static const FunctionInfoTyped<IDebug> functions[] = { {0, &IDebug::InitializeDebug, "InitializeDebug"}, {1, &IDebug::FinalizeDebug, "FinalizeDebug"}, {2, &IDebug::ListDevices, "ListDevices"}, @@ -126,9 +126,9 @@ public: {201, &IDebug::SetAll, "SetAll"}, {202, &IDebug::FlushDebug, "FlushDebug"}, {203, &IDebug::BreakTag, "BreakTag"}, - {204, nullptr, "ReadBackupData"}, - {205, nullptr, "WriteBackupData"}, - {206, nullptr, "WriteNtf"}, + {204, &IDebug::ReadBackupData, "ReadBackupData"}, + {205, &IDebug::WriteBackupData, "WriteBackupData"}, + {206, &IDebug::WriteNtf, "WriteNtf"}, }; // clang-format on @@ -152,16 +152,10 @@ private: 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>(user_interface); + rb.PushIpcInterface<IUser>(system); } - - std::shared_ptr<IUser> user_interface; }; class ISystemManager final : public ServiceFramework<ISystemManager> { @@ -180,16 +174,10 @@ private: void CreateSystemInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFP, "called"); - if (system_interface == nullptr) { - system_interface = std::make_shared<ISystem>(system); - } - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISystem>(system_interface); + rb.PushIpcInterface<ISystem>(system); } - - std::shared_ptr<ISystem> system_interface; }; class IDebugManager final : public ServiceFramework<IDebugManager> { @@ -208,16 +196,10 @@ private: void CreateDebugInterface(HLERequestContext& ctx) { LOG_DEBUG(Service_NFP, "called"); - if (system_interface == nullptr) { - system_interface = std::make_shared<IDebug>(system); - } - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<IDebug>(system_interface); + rb.PushIpcInterface<IDebug>(system); } - - std::shared_ptr<IDebug> system_interface; }; void LoopProcess(Core::System& system) { 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 bab05538a..000000000 --- a/src/core/hle/service/nfp/nfp_device.h +++ /dev/null @@ -1,120 +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 FlushDebug(); - Result FlushWithBreak(BreakType break_type); - - 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 GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const; - Result GetAdminInfo(AdminInfo& admin_info) const; - - Result DeleteRegisterInfo(); - Result SetRegisterInfoPrivate(const AmiiboName& amiibo_name); - Result RestoreAmiibo(); - Result Format(); - - 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(); - Result ExistApplicationArea(bool& has_application_area); - - Result GetAll(NfpData& data) const; - Result SetAll(const NfpData& data); - Result BreakTag(BreakType break_type); - Result ReadBackupData(); - Result WriteBackupData(); - Result WriteNtf(); - - 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; - u64 RemoveVersionByte(u64 application_id) const; - void UpdateSettingsCrc(); - void UpdateRegisterInfoCrc(); - - 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{}; - bool is_data_moddified{}; - bool is_app_area_open{}; - bool is_plain_amiibo{}; - 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 index 2ed8bb1ba..21d159154 100644 --- a/src/core/hle/service/nfp/nfp_interface.cpp +++ b/src/core/hle/service/nfp/nfp_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" @@ -6,198 +6,34 @@ #include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nfp/nfp_device.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) - : ServiceFramework{system_, name}, service_context{system_, service_name} { - availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent"); + : NfcInterface{system_, name, NFC::BackendType::Nfp} {} - 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); - } -} - -Interface::~Interface() { - availability_change_event->Close(); -} - -void Interface::Initialize(HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} +Interface::~Interface() = default; 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); + Initialize(ctx); } void Interface::InitializeDebug(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"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + Initialize(ctx); } 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); + Finalize(ctx); } void Interface::FinalizeDebug(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"); - - 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 Interface::StartDetection(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 Interface::StopDetection(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); + Finalize(ctx); } void Interface::Mount(HLERequestContext& ctx) { @@ -208,21 +44,9 @@ void Interface::Mount(HLERequestContext& ctx) { 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; - } + auto result = GetManager()->Mount(device_handle, model_type, mount_target); + result = TranslateResultToServiceError(result); - const auto result = device.value()->Mount(mount_target); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -232,21 +56,9 @@ void Interface::Unmount(HLERequestContext& 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; - } + auto result = GetManager()->Unmount(device_handle); + result = TranslateResultToServiceError(result); - const auto result = device.value()->Unmount(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -257,21 +69,9 @@ void Interface::OpenApplicationArea(HLERequestContext& ctx) { 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; - } + auto result = GetManager()->OpenApplicationArea(device_handle, access_id); + result = TranslateResultToServiceError(result); - const auto result = device.value()->OpenApplicationArea(access_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -282,28 +82,16 @@ void Interface::GetApplicationArea(HLERequestContext& ctx) { 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); + std::vector<u8> data(data_size); + auto result = GetManager()->GetApplicationArea(device_handle, data); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { + if (result.IsError()) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); + rb.Push(result); 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); @@ -316,27 +104,9 @@ void Interface::SetApplicationArea(HLERequestContext& ctx) { 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; - } + auto result = GetManager()->SetApplicationArea(device_handle, data); + result = TranslateResultToServiceError(result); - const auto result = device.value()->SetApplicationArea(data); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -346,21 +116,9 @@ void Interface::Flush(HLERequestContext& 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); + auto result = GetManager()->Flush(device_handle); + result = TranslateResultToServiceError(result); - 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); } @@ -370,21 +128,9 @@ void Interface::Restore(HLERequestContext& 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 result = GetManager()->Restore(device_handle); + result = TranslateResultToServiceError(result); - 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); } @@ -397,53 +143,9 @@ void Interface::CreateApplicationArea(HLERequestContext& ctx) { 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 Interface::GetTagInfo(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; - } + auto result = GetManager()->CreateApplicationArea(device_handle, access_id, data); + result = TranslateResultToServiceError(result); - TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info); - ctx.WriteBuffer(tag_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -453,23 +155,14 @@ void Interface::GetRegisterInfo(HLERequestContext& 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); + RegisterInfo register_info{}; + auto result = GetManager()->GetRegisterInfo(device_handle, register_info); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(register_info); } - RegisterInfo register_info{}; - const auto result = device.value()->GetRegisterInfo(register_info); - ctx.WriteBuffer(register_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -479,23 +172,14 @@ void Interface::GetCommonInfo(HLERequestContext& 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); + CommonInfo common_info{}; + auto result = GetManager()->GetCommonInfo(device_handle, common_info); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(common_info); } - CommonInfo common_info{}; - const auto result = device.value()->GetCommonInfo(common_info); - ctx.WriteBuffer(common_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -505,155 +189,26 @@ void Interface::GetModelInfo(HLERequestContext& 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); + ModelInfo model_info{}; + auto result = GetManager()->GetModelInfo(device_handle, model_info); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(model_info); } - ModelInfo model_info{}; - const auto result = device.value()->GetModelInfo(model_info); - ctx.WriteBuffer(model_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -void Interface::AttachActivateEvent(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 Interface::AttachDeactivateEvent(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 Interface::GetState(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFP, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void Interface::GetDeviceState(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 Interface::GetNpadId(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 Interface::GetApplicationAreaSize(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 Interface::AttachAvailabilityChangeEvent(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()); + rb.Push(GetManager()->GetApplicationAreaSize()); } void Interface::RecreateApplicationArea(HLERequestContext& ctx) { @@ -664,21 +219,9 @@ void Interface::RecreateApplicationArea(HLERequestContext& ctx) { 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 result = GetManager()->RecreateApplicationArea(device_handle, access_id, data); + result = TranslateResultToServiceError(result); - 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); } @@ -686,23 +229,11 @@ void Interface::RecreateApplicationArea(HLERequestContext& ctx) { void Interface::Format(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; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + auto result = GetManager()->Format(device_handle); + result = TranslateResultToServiceError(result); - 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); } @@ -712,23 +243,14 @@ void Interface::GetAdminInfo(HLERequestContext& 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); + AdminInfo admin_info{}; + auto result = GetManager()->GetAdminInfo(device_handle, admin_info); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(admin_info); } - AdminInfo admin_info{}; - const auto result = device.value()->GetAdminInfo(admin_info); - ctx.WriteBuffer(admin_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -738,23 +260,14 @@ void Interface::GetRegisterInfoPrivate(HLERequestContext& 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); + RegisterInfoPrivate register_info{}; + auto result = GetManager()->GetRegisterInfoPrivate(device_handle, register_info); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(register_info); } - RegisterInfoPrivate register_info{}; - const auto result = device.value()->GetRegisterInfoPrivate(register_info); - ctx.WriteBuffer(register_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -762,25 +275,15 @@ void Interface::GetRegisterInfoPrivate(HLERequestContext& ctx) { void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto device_handle{rp.Pop<u64>()}; - const auto buffer{ctx.ReadBuffer()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle, - buffer.size()); + const auto register_info_buffer{ctx.ReadBuffer()}; + LOG_INFO(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle, + register_info_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; - } + RegisterInfoPrivate register_info{}; + memcpy(®ister_info, register_info_buffer.data(), sizeof(RegisterInfoPrivate)); + auto result = GetManager()->SetRegisterInfoPrivate(device_handle, register_info); + result = TranslateResultToServiceError(result); - const auto result = device.value()->SetRegisterInfoPrivate({}); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -788,23 +291,11 @@ void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) { void Interface::DeleteRegisterInfo(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; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + auto result = GetManager()->DeleteRegisterInfo(device_handle); + result = TranslateResultToServiceError(result); - 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); } @@ -812,23 +303,11 @@ void Interface::DeleteRegisterInfo(HLERequestContext& ctx) { void Interface::DeleteApplicationArea(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; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + auto result = GetManager()->DeleteApplicationArea(device_handle); + result = TranslateResultToServiceError(result); - 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); } @@ -836,24 +315,18 @@ void Interface::DeleteApplicationArea(HLERequestContext& ctx) { void Interface::ExistsApplicationArea(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; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + bool has_application_area = false; + auto result = GetManager()->ExistsApplicationArea(device_handle, has_application_area); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { + if (result.IsError()) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); + rb.Push(result); 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); @@ -862,27 +335,16 @@ void Interface::ExistsApplicationArea(HLERequestContext& ctx) { void Interface::GetAll(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; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + NfpData nfp_data{}; + auto result = GetManager()->GetAll(device_handle, nfp_data); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(nfp_data); } - NfpData data{}; - const auto result = device.value()->GetAll(data); - - ctx.WriteBuffer(data); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -890,28 +352,15 @@ void Interface::GetAll(HLERequestContext& ctx) { void Interface::SetAll(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto device_handle{rp.Pop<u64>()}; - const auto nfp_data{ctx.ReadBuffer()}; - - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } + const auto nfp_data_buffer{ctx.ReadBuffer()}; - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - NfpData data{}; - memcpy(&data, nfp_data.data(), sizeof(NfpData)); + NfpData nfp_data{}; + memcpy(&nfp_data, nfp_data_buffer.data(), sizeof(NfpData)); + auto result = GetManager()->SetAll(device_handle, nfp_data); + result = TranslateResultToServiceError(result); - const auto result = device.value()->SetAll(data); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -919,23 +368,11 @@ void Interface::SetAll(HLERequestContext& ctx) { void Interface::FlushDebug(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; - } + LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + auto result = GetManager()->FlushDebug(device_handle); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->FlushDebug(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -944,23 +381,12 @@ void Interface::BreakTag(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto device_handle{rp.Pop<u64>()}; const auto break_type{rp.PopEnum<BreakType>()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}, break_type={}", device_handle, break_type); + LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}, break_type={}", device_handle, + break_type); - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } + auto result = GetManager()->BreakTag(device_handle, break_type); + result = TranslateResultToServiceError(result); - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->BreakTag(break_type); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -968,23 +394,16 @@ void Interface::BreakTag(HLERequestContext& ctx) { void Interface::ReadBackupData(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; - } + LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); - auto device = GetNfpDevice(device_handle); + std::vector<u8> backup_data{}; + auto result = GetManager()->ReadBackupData(device_handle, backup_data); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; + if (result.IsSuccess()) { + ctx.WriteBuffer(backup_data); } - const auto result = device.value()->ReadBackupData(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -992,23 +411,12 @@ void Interface::ReadBackupData(HLERequestContext& ctx) { void Interface::WriteBackupData(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); + const auto backup_data_buffer{ctx.ReadBuffer()}; + LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } + auto result = GetManager()->WriteBackupData(device_handle, backup_data_buffer); + result = TranslateResultToServiceError(result); - const auto result = device.value()->WriteBackupData(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -1016,34 +424,15 @@ void Interface::WriteBackupData(HLERequestContext& ctx) { void Interface::WriteNtf(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; - } + 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 device = GetNfpDevice(device_handle); + auto result = GetManager()->WriteNtf(device_handle, write_type, ntf_data_buffer); + result = TranslateResultToServiceError(result); - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->WriteNtf(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } -std::optional<std::shared_ptr<NfpDevice>> Interface::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_interface.h b/src/core/hle/service/nfp/nfp_interface.h index 616c94b06..fa985b068 100644 --- a/src/core/hle/service/nfp/nfp_interface.h +++ b/src/core/hle/service/nfp/nfp_interface.h @@ -1,32 +1,23 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 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/nfc/nfc_interface.h" #include "core/hle/service/service.h" namespace Service::NFP { -class NfpDevice; -class Interface : public ServiceFramework<Interface> { +class Interface : public NFC::NfcInterface { public: explicit Interface(Core::System& system_, const char* name); ~Interface() override; - void Initialize(HLERequestContext& ctx); void InitializeSystem(HLERequestContext& ctx); void InitializeDebug(HLERequestContext& ctx); - void Finalize(HLERequestContext& ctx); void FinalizeSystem(HLERequestContext& ctx); void FinalizeDebug(HLERequestContext& ctx); - void ListDevices(HLERequestContext& ctx); - void StartDetection(HLERequestContext& ctx); - void StopDetection(HLERequestContext& ctx); void Mount(HLERequestContext& ctx); void Unmount(HLERequestContext& ctx); void OpenApplicationArea(HLERequestContext& ctx); @@ -35,17 +26,10 @@ public: void Flush(HLERequestContext& ctx); void Restore(HLERequestContext& ctx); void CreateApplicationArea(HLERequestContext& ctx); - void GetTagInfo(HLERequestContext& ctx); void GetRegisterInfo(HLERequestContext& ctx); void GetCommonInfo(HLERequestContext& ctx); void GetModelInfo(HLERequestContext& ctx); - void AttachActivateEvent(HLERequestContext& ctx); - void AttachDeactivateEvent(HLERequestContext& ctx); - void GetState(HLERequestContext& ctx); - void GetDeviceState(HLERequestContext& ctx); - void GetNpadId(HLERequestContext& ctx); void GetApplicationAreaSize(HLERequestContext& ctx); - void AttachAvailabilityChangeEvent(HLERequestContext& ctx); void RecreateApplicationArea(HLERequestContext& ctx); void Format(HLERequestContext& ctx); void GetAdminInfo(HLERequestContext& ctx); @@ -61,21 +45,6 @@ public: void ReadBackupData(HLERequestContext& ctx); void WriteBackupData(HLERequestContext& ctx); void WriteNtf(HLERequestContext& ctx); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - 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/nfp/nfp_result.h b/src/core/hle/service/nfp/nfp_result.h index d8e4cf094..4c126cd81 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,19 @@ 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 ResultCorruptedData(ErrorModule::NFP, 144); +constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152); +constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168); +constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178); } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 1ef047cee..7d36d5ee6 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -7,32 +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, @@ -72,35 +59,6 @@ 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 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 -}; - -// 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 AppAreaVersion : u8 { Nintendo3DS = 0, NintendoWiiU = 1, @@ -115,6 +73,11 @@ enum class BreakType : u32 { Unknown2, }; +enum class WriteType : u32 { + Unknown0, + Unknown1, +}; + enum class CabinetMode : u8 { StartNicknameAndOwnerSettings, StartGameDataEraser, @@ -122,27 +85,16 @@ 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 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 TagUuid { - UniqueSerialNumber uid; + NFC::UniqueSerialNumber uid; u8 nintendo_id; LockBytes lock_bytes; }; @@ -243,7 +195,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"); @@ -298,7 +250,7 @@ struct NTAG215File { u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data HashData hmac_tag; // Hash - UniqueSerialNumber uid; // Unique serial number + NFC::UniqueSerialNumber uid; // Unique serial number u8 nintendo_id; // Tag UUID AmiiboModelInfo model_info; HashData keygen_salt; // Salt @@ -326,17 +278,7 @@ static_assert(sizeof(EncryptedNTAG215File) == sizeof(NTAG215File), 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; @@ -347,6 +289,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; @@ -357,6 +300,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; @@ -366,6 +310,7 @@ struct RegisterInfo { }; static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); +// This is nn::nfp::RegisterInfoPrivate struct RegisterInfoPrivate { Service::Mii::MiiStoreData mii_store_data; WriteDate creation_date; @@ -375,12 +320,13 @@ struct RegisterInfoPrivate { }; 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; - PackedTagType tag_type; + NFC::PackedTagType tag_type; AppAreaVersion app_area_version; INSERT_PADDING_BYTES(0x7); INSERT_PADDING_BYTES(0x28); @@ -411,7 +357,7 @@ struct NfpData { u32 access_id; u16 settings_crc_counter; u8 font_region; - PackedTagType tag_type; + NFC::PackedTagType tag_type; AppAreaVersion console_type; u8 application_id_byte; INSERT_PADDING_BYTES(0x2E); @@ -420,37 +366,4 @@ struct NfpData { static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size"); #pragma pack() -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; -}; -static_assert(sizeof(MifareReadBlockParameter) == 0x18, - "MifareReadBlockParameter is an invalid size"); - -struct MifareReadBlockData { - DataBlock data; - u8 sector_number; - INSERT_PADDING_BYTES(0x7); -}; -static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size"); - -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::NFP |