summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nfp
diff options
context:
space:
mode:
authorNarr the Reg <juangerman-13@hotmail.com>2023-04-20 03:01:23 +0200
committergerman77 <juangerman-13@hotmail.com>2023-05-06 06:02:59 +0200
commit94151097b9abadf35c55ea06a31925c9848f4c62 (patch)
tree28a00c878f90492ffd2bb95521c2cc3990cc4323 /src/core/hle/service/nfp
parentcore: service: Add FunctionInfoTyped to allow expanding existing interfaces (diff)
downloadyuzu-94151097b9abadf35c55ea06a31925c9848f4c62.tar
yuzu-94151097b9abadf35c55ea06a31925c9848f4c62.tar.gz
yuzu-94151097b9abadf35c55ea06a31925c9848f4c62.tar.bz2
yuzu-94151097b9abadf35c55ea06a31925c9848f4c62.tar.lz
yuzu-94151097b9abadf35c55ea06a31925c9848f4c62.tar.xz
yuzu-94151097b9abadf35c55ea06a31925c9848f4c62.tar.zst
yuzu-94151097b9abadf35c55ea06a31925c9848f4c62.zip
Diffstat (limited to 'src/core/hle/service/nfp')
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.cpp405
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.h106
-rw-r--r--src/core/hle/service/nfp/nfp.cpp12
-rw-r--r--src/core/hle/service/nfp/nfp_device.cpp1137
-rw-r--r--src/core/hle/service/nfp/nfp_device.h120
-rw-r--r--src/core/hle/service/nfp/nfp_interface.cpp839
-rw-r--r--src/core/hle/service/nfp/nfp_interface.h37
-rw-r--r--src/core/hle/service/nfp/nfp_result.h29
-rw-r--r--src/core/hle/service/nfp/nfp_types.h129
9 files changed, 159 insertions, 2655 deletions
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp
deleted file mode 100644
index a3622e792..000000000
--- a/src/core/hle/service/nfp/amiibo_crypto.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-// SPDX-FileCopyrightText: Copyright 2017 socram8888/amiitool
-// SPDX-License-Identifier: MIT
-
-#include <array>
-#include <mbedtls/aes.h>
-#include <mbedtls/hmac_drbg.h>
-
-#include "common/fs/file.h"
-#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
-#include "common/logging/log.h"
-#include "core/hle/service/nfp/amiibo_crypto.h"
-
-namespace Service::NFP::AmiiboCrypto {
-
-bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
- const auto& amiibo_data = ntag_file.user_memory;
- LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", ntag_file.static_lock);
- LOG_DEBUG(Service_NFP, "compability_container=0x{0:x}", ntag_file.compability_container);
- LOG_DEBUG(Service_NFP, "write_count={}", static_cast<u16>(amiibo_data.write_counter));
-
- LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id);
- LOG_DEBUG(Service_NFP, "character_variant={}", amiibo_data.model_info.character_variant);
- LOG_DEBUG(Service_NFP, "amiibo_type={}", amiibo_data.model_info.amiibo_type);
- LOG_DEBUG(Service_NFP, "model_number=0x{0:x}",
- static_cast<u16>(amiibo_data.model_info.model_number));
- LOG_DEBUG(Service_NFP, "series={}", amiibo_data.model_info.series);
- LOG_DEBUG(Service_NFP, "tag_type=0x{0:x}", amiibo_data.model_info.tag_type);
-
- LOG_DEBUG(Service_NFP, "tag_dynamic_lock=0x{0:x}", ntag_file.dynamic_lock);
- LOG_DEBUG(Service_NFP, "tag_CFG0=0x{0:x}", ntag_file.CFG0);
- LOG_DEBUG(Service_NFP, "tag_CFG1=0x{0:x}", ntag_file.CFG1);
-
- // Validate UUID
- constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3`
- if ((CT ^ ntag_file.uuid.uid[0] ^ ntag_file.uuid.uid[1] ^ ntag_file.uuid.uid[2]) !=
- ntag_file.uuid.uid[3]) {
- return false;
- }
- if ((ntag_file.uuid.uid[4] ^ ntag_file.uuid.uid[5] ^ ntag_file.uuid.uid[6] ^
- ntag_file.uuid.nintendo_id) != ntag_file.uuid.lock_bytes[0]) {
- return false;
- }
-
- // Check against all know constants on an amiibo binary
- if (ntag_file.static_lock != 0xE00F) {
- return false;
- }
- if (ntag_file.compability_container != 0xEEFF10F1U) {
- return false;
- }
- if (amiibo_data.constant_value != 0xA5) {
- return false;
- }
- if (amiibo_data.model_info.tag_type != PackedTagType::Type2) {
- return false;
- }
- if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) {
- return false;
- }
- if (ntag_file.CFG0 != 0x04000000U) {
- return false;
- }
- if (ntag_file.CFG1 != 0x5F) {
- return false;
- }
- return true;
-}
-
-bool IsAmiiboValid(const NTAG215File& ntag_file) {
- return IsAmiiboValid(EncodedDataToNfcData(ntag_file));
-}
-
-NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
- NTAG215File encoded_data{};
-
- encoded_data.uid = nfc_data.uuid.uid;
- encoded_data.nintendo_id = nfc_data.uuid.nintendo_id;
- encoded_data.static_lock = nfc_data.static_lock;
- encoded_data.compability_container = nfc_data.compability_container;
- encoded_data.hmac_data = nfc_data.user_memory.hmac_data;
- encoded_data.constant_value = nfc_data.user_memory.constant_value;
- encoded_data.write_counter = nfc_data.user_memory.write_counter;
- encoded_data.amiibo_version = nfc_data.user_memory.amiibo_version;
- encoded_data.settings = nfc_data.user_memory.settings;
- encoded_data.owner_mii = nfc_data.user_memory.owner_mii;
- encoded_data.application_id = nfc_data.user_memory.application_id;
- encoded_data.application_write_counter = nfc_data.user_memory.application_write_counter;
- encoded_data.application_area_id = nfc_data.user_memory.application_area_id;
- encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte;
- encoded_data.unknown = nfc_data.user_memory.unknown;
- encoded_data.mii_extension = nfc_data.user_memory.mii_extension;
- encoded_data.unknown2 = nfc_data.user_memory.unknown2;
- encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc;
- encoded_data.application_area = nfc_data.user_memory.application_area;
- encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag;
- encoded_data.lock_bytes = nfc_data.uuid.lock_bytes;
- encoded_data.model_info = nfc_data.user_memory.model_info;
- encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt;
- encoded_data.dynamic_lock = nfc_data.dynamic_lock;
- encoded_data.CFG0 = nfc_data.CFG0;
- encoded_data.CFG1 = nfc_data.CFG1;
- encoded_data.password = nfc_data.password;
-
- return encoded_data;
-}
-
-EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
- EncryptedNTAG215File nfc_data{};
-
- nfc_data.uuid.uid = encoded_data.uid;
- nfc_data.uuid.nintendo_id = encoded_data.nintendo_id;
- nfc_data.uuid.lock_bytes = encoded_data.lock_bytes;
- nfc_data.static_lock = encoded_data.static_lock;
- nfc_data.compability_container = encoded_data.compability_container;
- nfc_data.user_memory.hmac_data = encoded_data.hmac_data;
- nfc_data.user_memory.constant_value = encoded_data.constant_value;
- nfc_data.user_memory.write_counter = encoded_data.write_counter;
- nfc_data.user_memory.amiibo_version = encoded_data.amiibo_version;
- nfc_data.user_memory.settings = encoded_data.settings;
- nfc_data.user_memory.owner_mii = encoded_data.owner_mii;
- nfc_data.user_memory.application_id = encoded_data.application_id;
- nfc_data.user_memory.application_write_counter = encoded_data.application_write_counter;
- nfc_data.user_memory.application_area_id = encoded_data.application_area_id;
- nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte;
- nfc_data.user_memory.unknown = encoded_data.unknown;
- nfc_data.user_memory.mii_extension = encoded_data.mii_extension;
- nfc_data.user_memory.unknown2 = encoded_data.unknown2;
- nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc;
- nfc_data.user_memory.application_area = encoded_data.application_area;
- nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag;
- nfc_data.user_memory.model_info = encoded_data.model_info;
- nfc_data.user_memory.keygen_salt = encoded_data.keygen_salt;
- nfc_data.dynamic_lock = encoded_data.dynamic_lock;
- nfc_data.CFG0 = encoded_data.CFG0;
- nfc_data.CFG1 = encoded_data.CFG1;
- nfc_data.password = encoded_data.password;
-
- return nfc_data;
-}
-
-u32 GetTagPassword(const TagUuid& uuid) {
- // Verify that the generated password is correct
- u32 password = 0xAA ^ (uuid.uid[1] ^ uuid.uid[3]);
- password &= (0x55 ^ (uuid.uid[2] ^ uuid.uid[4])) << 8;
- password &= (0xAA ^ (uuid.uid[3] ^ uuid.uid[5])) << 16;
- password &= (0x55 ^ (uuid.uid[4] ^ uuid.uid[6])) << 24;
- return password;
-}
-
-HashSeed GetSeed(const NTAG215File& data) {
- HashSeed seed{
- .magic = data.write_counter,
- .padding = {},
- .uid_1 = data.uid,
- .nintendo_id_1 = data.nintendo_id,
- .uid_2 = data.uid,
- .nintendo_id_2 = data.nintendo_id,
- .keygen_salt = data.keygen_salt,
- };
-
- return seed;
-}
-
-std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed) {
- const std::size_t seedPart1Len = sizeof(key.magic_bytes) - key.magic_length;
- const std::size_t string_size = key.type_string.size();
- std::vector<u8> output(string_size + seedPart1Len);
-
- // Copy whole type string
- memccpy(output.data(), key.type_string.data(), '\0', string_size);
-
- // Append (16 - magic_length) from the input seed
- memcpy(output.data() + string_size, &seed, seedPart1Len);
-
- // Append all bytes from magicBytes
- output.insert(output.end(), key.magic_bytes.begin(),
- key.magic_bytes.begin() + key.magic_length);
-
- output.insert(output.end(), seed.uid_1.begin(), seed.uid_1.end());
- output.emplace_back(seed.nintendo_id_1);
- output.insert(output.end(), seed.uid_2.begin(), seed.uid_2.end());
- output.emplace_back(seed.nintendo_id_2);
-
- for (std::size_t i = 0; i < sizeof(seed.keygen_salt); i++) {
- output.emplace_back(static_cast<u8>(seed.keygen_salt[i] ^ key.xor_pad[i]));
- }
-
- return output;
-}
-
-void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
- const std::vector<u8>& seed) {
- // Initialize context
- ctx.used = false;
- ctx.counter = 0;
- ctx.buffer_size = sizeof(ctx.counter) + seed.size();
- memcpy(ctx.buffer.data() + sizeof(u16), seed.data(), seed.size());
-
- // Initialize HMAC context
- mbedtls_md_init(&hmac_ctx);
- mbedtls_md_setup(&hmac_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
- mbedtls_md_hmac_starts(&hmac_ctx, hmac_key.data(), hmac_key.size());
-}
-
-void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output) {
- // If used at least once, reinitialize the HMAC
- if (ctx.used) {
- mbedtls_md_hmac_reset(&hmac_ctx);
- }
-
- ctx.used = true;
-
- // Store counter in big endian, and increment it
- ctx.buffer[0] = static_cast<u8>(ctx.counter >> 8);
- ctx.buffer[1] = static_cast<u8>(ctx.counter >> 0);
- ctx.counter++;
-
- // Do HMAC magic
- mbedtls_md_hmac_update(&hmac_ctx, reinterpret_cast<const unsigned char*>(ctx.buffer.data()),
- ctx.buffer_size);
- mbedtls_md_hmac_finish(&hmac_ctx, output.data());
-}
-
-DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
- const auto seed = GetSeed(data);
-
- // Generate internal seed
- const std::vector<u8> internal_key = GenerateInternalKey(key, seed);
-
- // Initialize context
- CryptoCtx ctx{};
- mbedtls_md_context_t hmac_ctx;
- CryptoInit(ctx, hmac_ctx, key.hmac_key, internal_key);
-
- // Generate derived keys
- DerivedKeys derived_keys{};
- std::array<DrgbOutput, 2> temp{};
- CryptoStep(ctx, hmac_ctx, temp[0]);
- CryptoStep(ctx, hmac_ctx, temp[1]);
- memcpy(&derived_keys, temp.data(), sizeof(DerivedKeys));
-
- // Cleanup context
- mbedtls_md_free(&hmac_ctx);
-
- return derived_keys;
-}
-
-void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data) {
- mbedtls_aes_context aes;
- std::size_t nc_off = 0;
- std::array<u8, sizeof(keys.aes_iv)> nonce_counter{};
- std::array<u8, sizeof(keys.aes_iv)> stream_block{};
-
- const auto aes_key_size = static_cast<u32>(keys.aes_key.size() * 8);
- mbedtls_aes_setkey_enc(&aes, keys.aes_key.data(), aes_key_size);
- memcpy(nonce_counter.data(), keys.aes_iv.data(), sizeof(keys.aes_iv));
-
- constexpr std::size_t encrypted_data_size = HMAC_TAG_START - SETTINGS_START;
- mbedtls_aes_crypt_ctr(&aes, encrypted_data_size, &nc_off, nonce_counter.data(),
- stream_block.data(),
- reinterpret_cast<const unsigned char*>(&in_data.settings),
- reinterpret_cast<unsigned char*>(&out_data.settings));
-
- // Copy the rest of the data directly
- out_data.uid = in_data.uid;
- out_data.nintendo_id = in_data.nintendo_id;
- out_data.lock_bytes = in_data.lock_bytes;
- out_data.static_lock = in_data.static_lock;
- out_data.compability_container = in_data.compability_container;
-
- out_data.constant_value = in_data.constant_value;
- out_data.write_counter = in_data.write_counter;
-
- out_data.model_info = in_data.model_info;
- out_data.keygen_salt = in_data.keygen_salt;
- out_data.dynamic_lock = in_data.dynamic_lock;
- out_data.CFG0 = in_data.CFG0;
- out_data.CFG1 = in_data.CFG1;
- out_data.password = in_data.password;
-}
-
-bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info) {
- const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
-
- const Common::FS::IOFile keys_file{yuzu_keys_dir / "key_retail.bin",
- Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
-
- if (!keys_file.IsOpen()) {
- LOG_ERROR(Service_NFP, "Failed to open key file");
- return false;
- }
-
- if (keys_file.Read(unfixed_info) != 1) {
- LOG_ERROR(Service_NFP, "Failed to read unfixed_info");
- return false;
- }
- if (keys_file.Read(locked_secret) != 1) {
- LOG_ERROR(Service_NFP, "Failed to read locked-secret");
- return false;
- }
-
- return true;
-}
-
-bool IsKeyAvailable() {
- const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
- return Common::FS::Exists(yuzu_keys_dir / "key_retail.bin");
-}
-
-bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data) {
- InternalKey locked_secret{};
- InternalKey unfixed_info{};
-
- if (!LoadKeys(locked_secret, unfixed_info)) {
- return false;
- }
-
- // Generate keys
- NTAG215File encoded_data = NfcDataToEncodedData(encrypted_tag_data);
- const auto data_keys = GenerateKey(unfixed_info, encoded_data);
- const auto tag_keys = GenerateKey(locked_secret, encoded_data);
-
- // Decrypt
- Cipher(data_keys, encoded_data, tag_data);
-
- // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
- constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(),
- sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
- input_length, reinterpret_cast<unsigned char*>(&tag_data.hmac_tag));
-
- // Regenerate data HMAC
- constexpr std::size_t input_length2 = DYNAMIC_LOCK_START - WRITE_COUNTER_START;
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), data_keys.hmac_key.data(),
- sizeof(HmacKey),
- reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2,
- reinterpret_cast<unsigned char*>(&tag_data.hmac_data));
-
- if (tag_data.hmac_data != encrypted_tag_data.user_memory.hmac_data) {
- LOG_ERROR(Service_NFP, "hmac_data doesn't match");
- return false;
- }
-
- if (tag_data.hmac_tag != encrypted_tag_data.user_memory.hmac_tag) {
- LOG_ERROR(Service_NFP, "hmac_tag doesn't match");
- return false;
- }
-
- return true;
-}
-
-bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_tag_data) {
- InternalKey locked_secret{};
- InternalKey unfixed_info{};
-
- if (!LoadKeys(locked_secret, unfixed_info)) {
- return false;
- }
-
- // Generate keys
- const auto data_keys = GenerateKey(unfixed_info, tag_data);
- const auto tag_keys = GenerateKey(locked_secret, tag_data);
-
- NTAG215File encoded_tag_data{};
-
- // Generate tag HMAC
- constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
- constexpr std::size_t input_length2 = HMAC_TAG_START - WRITE_COUNTER_START;
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(),
- sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
- input_length, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag));
-
- // Init mbedtls HMAC context
- mbedtls_md_context_t ctx;
- mbedtls_md_init(&ctx);
- mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
-
- // Generate data HMAC
- mbedtls_md_hmac_starts(&ctx, data_keys.hmac_key.data(), sizeof(HmacKey));
- mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.write_counter),
- input_length2); // Data
- mbedtls_md_hmac_update(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag),
- sizeof(HashData)); // Tag HMAC
- mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.uid),
- input_length);
- mbedtls_md_hmac_finish(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_data));
-
- // HMAC cleanup
- mbedtls_md_free(&ctx);
-
- // Encrypt
- Cipher(data_keys, tag_data, encoded_tag_data);
-
- // Convert back to hardware
- encrypted_tag_data = EncodedDataToNfcData(encoded_tag_data);
-
- return true;
-}
-
-} // namespace Service::NFP::AmiiboCrypto
diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfp/amiibo_crypto.h
deleted file mode 100644
index f6208ee6b..000000000
--- a/src/core/hle/service/nfp/amiibo_crypto.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <array>
-
-#include "core/hle/service/nfp/nfp_types.h"
-
-struct mbedtls_md_context_t;
-
-namespace Service::NFP::AmiiboCrypto {
-// Byte locations in Service::NFP::NTAG215File
-constexpr std::size_t HMAC_DATA_START = 0x8;
-constexpr std::size_t SETTINGS_START = 0x2c;
-constexpr std::size_t WRITE_COUNTER_START = 0x29;
-constexpr std::size_t HMAC_TAG_START = 0x1B4;
-constexpr std::size_t UUID_START = 0x1D4;
-constexpr std::size_t DYNAMIC_LOCK_START = 0x208;
-
-using HmacKey = std::array<u8, 0x10>;
-using DrgbOutput = std::array<u8, 0x20>;
-
-struct HashSeed {
- u16_be magic;
- std::array<u8, 0xE> padding;
- UniqueSerialNumber uid_1;
- u8 nintendo_id_1;
- UniqueSerialNumber uid_2;
- u8 nintendo_id_2;
- std::array<u8, 0x20> keygen_salt;
-};
-static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size");
-
-struct InternalKey {
- HmacKey hmac_key;
- std::array<char, 0xE> type_string;
- u8 reserved;
- u8 magic_length;
- std::array<u8, 0x10> magic_bytes;
- std::array<u8, 0x20> xor_pad;
-};
-static_assert(sizeof(InternalKey) == 0x50, "InternalKey is an invalid size");
-static_assert(std::is_trivially_copyable_v<InternalKey>, "InternalKey must be trivially copyable.");
-
-struct CryptoCtx {
- std::array<char, 480> buffer;
- bool used;
- std::size_t buffer_size;
- s16 counter;
-};
-
-struct DerivedKeys {
- std::array<u8, 0x10> aes_key;
- std::array<u8, 0x10> aes_iv;
- std::array<u8, 0x10> hmac_key;
-};
-static_assert(sizeof(DerivedKeys) == 0x30, "DerivedKeys is an invalid size");
-
-/// Validates that the amiibo file is not corrupted
-bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file);
-
-/// Validates that the amiibo file is not corrupted
-bool IsAmiiboValid(const NTAG215File& ntag_file);
-
-/// Converts from encrypted file format to encoded file format
-NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data);
-
-/// Converts from encoded file format to encrypted file format
-EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data);
-
-/// Returns password needed to allow write access to protected memory
-u32 GetTagPassword(const TagUuid& uuid);
-
-// Generates Seed needed for key derivation
-HashSeed GetSeed(const NTAG215File& data);
-
-// Middle step on the generation of derived keys
-std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed);
-
-// Initializes mbedtls context
-void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
- const std::vector<u8>& seed);
-
-// Feeds data to mbedtls context to generate the derived key
-void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output);
-
-// Generates the derived key from amiibo data
-DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data);
-
-// Encodes or decodes amiibo data
-void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data);
-
-/// Loads both amiibo keys from key_retail.bin
-bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info);
-
-/// Returns true if key_retail.bin exist
-bool IsKeyAvailable();
-
-/// Decodes encrypted amiibo data returns true if output is valid
-bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data);
-
-/// Encodes plain amiibo data returns true if output is valid
-bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_tag_data);
-
-} // namespace Service::NFP::AmiiboCrypto
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 2559fe598..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
diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp
deleted file mode 100644
index 3f9af53c8..000000000
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ /dev/null
@@ -1,1137 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 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
-#endif
-
-#include <boost/crc.hpp>
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#include "common/input.h"
-#include "common/logging/log.h"
-#include "common/string_util.h"
-#include "common/tiny_mt.h"
-#include "core/core.h"
-#include "core/hid/emulated_controller.h"
-#include "core/hid/hid_core.h"
-#include "core/hid/hid_types.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/mii/mii_manager.h"
-#include "core/hle/service/mii/types.h"
-#include "core/hle/service/nfp/amiibo_crypto.h"
-#include "core/hle/service/nfp/nfp_device.h"
-#include "core/hle/service/nfp/nfp_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_,
- KernelHelpers::ServiceContext& service_context_,
- Kernel::KEvent* availability_change_event_)
- : npad_id{npad_id_}, system{system_}, service_context{service_context_},
- availability_change_event{availability_change_event_} {
- activate_event = service_context.CreateEvent("IUser:NFPActivateEvent");
- deactivate_event = service_context.CreateEvent("IUser:NFPDeactivateEvent");
- npad_device = system.HIDCore().GetEmulatedController(npad_id);
-
- Core::HID::ControllerUpdateCallback engine_callback{
- .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); },
- .is_npad_service = false,
- };
- is_controller_set = true;
- callback_key = npad_device->SetCallback(engine_callback);
-
- auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
- current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point;
-}
-
-NfpDevice::~NfpDevice() {
- activate_event->Close();
- deactivate_event->Close();
- if (!is_controller_set) {
- return;
- }
- npad_device->DeleteCallback(callback_key);
- is_controller_set = false;
-};
-
-void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
- if (!is_initalized) {
- return;
- }
-
- if (type == Core::HID::ControllerTriggerType::Connected) {
- Initialize();
- availability_change_event->Signal();
- return;
- }
-
- if (type == Core::HID::ControllerTriggerType::Disconnected) {
- device_state = DeviceState::Unavailable;
- availability_change_event->Signal();
- return;
- }
-
- if (type != Core::HID::ControllerTriggerType::Nfc) {
- return;
- }
-
- if (!npad_device->IsConnected()) {
- return;
- }
-
- const auto nfc_status = npad_device->GetNfc();
- switch (nfc_status.state) {
- case Common::Input::NfcState::NewAmiibo:
- LoadAmiibo(nfc_status.data);
- break;
- case Common::Input::NfcState::AmiiboRemoved:
- if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
- break;
- }
- if (device_state != DeviceState::SearchingForTag) {
- CloseAmiibo();
- }
- break;
- default:
- break;
- }
-}
-
-bool NfpDevice::LoadAmiibo(std::span<const u8> data) {
- if (device_state != DeviceState::SearchingForTag) {
- LOG_ERROR(Service_NFP, "Game is not looking for amiibos, current state {}", device_state);
- return false;
- }
-
- if (data.size() != sizeof(EncryptedNTAG215File)) {
- LOG_ERROR(Service_NFP, "Not an amiibo, size={}", data.size());
- return false;
- }
-
- // TODO: Filter by allowed_protocols here
-
- memcpy(&tag_data, data.data(), sizeof(EncryptedNTAG215File));
- is_plain_amiibo = AmiiboCrypto::IsAmiiboValid(tag_data);
-
- if (is_plain_amiibo) {
- encrypted_tag_data = AmiiboCrypto::EncodedDataToNfcData(tag_data);
- LOG_INFO(Service_NFP, "Using plain amiibo");
- } else {
- tag_data = {};
- memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File));
- }
-
- device_state = DeviceState::TagFound;
- deactivate_event->GetReadableEvent().Clear();
- activate_event->Signal();
- return true;
-}
-
-void NfpDevice::CloseAmiibo() {
- LOG_INFO(Service_NFP, "Remove amiibo");
-
- if (device_state == DeviceState::TagMounted) {
- Unmount();
- }
-
- device_state = DeviceState::TagRemoved;
- encrypted_tag_data = {};
- tag_data = {};
- activate_event->GetReadableEvent().Clear();
- deactivate_event->Signal();
-}
-
-Kernel::KReadableEvent& NfpDevice::GetActivateEvent() const {
- return activate_event->GetReadableEvent();
-}
-
-Kernel::KReadableEvent& NfpDevice::GetDeactivateEvent() const {
- return deactivate_event->GetReadableEvent();
-}
-
-void NfpDevice::Initialize() {
- device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable;
- encrypted_tag_data = {};
- tag_data = {};
- is_initalized = true;
-}
-
-void NfpDevice::Finalize() {
- if (device_state == DeviceState::TagMounted) {
- Unmount();
- }
- if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
- StopDetection();
- }
- device_state = DeviceState::Unavailable;
- is_initalized = false;
-}
-
-Result NfpDevice::StartDetection(TagProtocol allowed_protocol) {
- if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- return WrongDeviceState;
- }
-
- if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
- Common::Input::PollingMode::NFC) !=
- Common::Input::DriverResult::Success) {
- LOG_ERROR(Service_NFP, "Nfc not supported");
- return NfcDisabled;
- }
-
- device_state = DeviceState::SearchingForTag;
- allowed_protocols = allowed_protocol;
- return ResultSuccess;
-}
-
-Result NfpDevice::StopDetection() {
- npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
- Common::Input::PollingMode::Active);
-
- if (device_state == DeviceState::Initialized) {
- return ResultSuccess;
- }
-
- if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
- CloseAmiibo();
- }
-
- if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
- device_state = DeviceState::Initialized;
- return ResultSuccess;
- }
-
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- return WrongDeviceState;
-}
-
-Result NfpDevice::Flush() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- auto& settings = tag_data.settings;
-
- const auto& current_date = GetAmiiboDate(current_posix_time);
- if (settings.write_date.raw_date != current_date.raw_date) {
- settings.write_date = current_date;
- UpdateSettingsCrc();
- }
-
- tag_data.write_counter++;
-
- FlushWithBreak(BreakType::Normal);
-
- is_data_moddified = false;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::FlushDebug() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- tag_data.write_counter++;
-
- FlushWithBreak(BreakType::Normal);
-
- is_data_moddified = false;
-
- 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;
- }
-
- 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;
- }
-
- memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
- }
-
- if (!npad_device->WriteNfc(data)) {
- LOG_ERROR(Service_NFP, "Error writing to file");
- return WriteAmiiboFailed;
- }
-
- return ResultSuccess;
-}
-
-Result NfpDevice::Mount(MountTarget mount_target_) {
- if (device_state != DeviceState::TagFound) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- return WrongDeviceState;
- }
-
- // The loaded amiibo is not encrypted
- if (is_plain_amiibo) {
- device_state = DeviceState::TagMounted;
- mount_target = mount_target_;
- return ResultSuccess;
- }
-
- if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
- LOG_ERROR(Service_NFP, "Not an amiibo");
- return NotAnAmiibo;
- }
-
- // Mark amiibos as read only when keys are missing
- if (!AmiiboCrypto::IsKeyAvailable()) {
- LOG_ERROR(Service_NFP, "No keys detected");
- device_state = DeviceState::TagMounted;
- mount_target = MountTarget::Rom;
- return ResultSuccess;
- }
-
- if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
- LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state);
- return CorruptedData;
- }
-
- device_state = DeviceState::TagMounted;
- mount_target = mount_target_;
- return ResultSuccess;
-}
-
-Result NfpDevice::Unmount() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- // Save data before unloading the amiibo
- if (is_data_moddified) {
- Flush();
- }
-
- device_state = DeviceState::TagFound;
- mount_target = MountTarget::None;
- is_app_area_open = false;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetTagInfo(TagInfo& tag_info) const {
- if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- tag_info = {
- .uuid = encrypted_tag_data.uuid.uid,
- .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
- .protocol = TagProtocol::TypeA,
- .tag_type = TagType::Type2,
- };
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- const auto& settings = tag_data.settings;
-
- // TODO: Validate this data
- common_info = {
- .last_write_date = settings.write_date.GetWriteDate(),
- .write_counter = tag_data.write_counter,
- .version = tag_data.amiibo_version,
- .application_area_size = sizeof(ApplicationArea),
- };
- return ResultSuccess;
-}
-
-Result NfpDevice::GetModelInfo(ModelInfo& model_info) const {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- const auto& model_info_data = encrypted_tag_data.user_memory.model_info;
- model_info = {
- .character_id = model_info_data.character_id,
- .character_variant = model_info_data.character_variant,
- .amiibo_type = model_info_data.amiibo_type,
- .model_number = model_info_data.model_number,
- .series = model_info_data.series,
- };
- return ResultSuccess;
-}
-
-Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.amiibo_initialized == 0) {
- return RegistrationIsNotInitialized;
- }
-
- Service::Mii::MiiManager manager;
- const auto& settings = tag_data.settings;
-
- // TODO: Validate this data
- register_info = {
- .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii),
- .creation_date = settings.init_date.GetWriteDate(),
- .amiibo_name = GetAmiiboName(settings),
- .font_region = settings.settings.font_region,
- };
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.amiibo_initialized == 0) {
- return RegistrationIsNotInitialized;
- }
-
- Service::Mii::MiiManager manager;
- const auto& settings = tag_data.settings;
-
- // TODO: Validate and complete this data
- register_info = {
- .mii_store_data = {},
- .creation_date = settings.init_date.GetWriteDate(),
- .amiibo_name = GetAmiiboName(settings),
- .font_region = settings.settings.font_region,
- };
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- u8 flags = static_cast<u8>(tag_data.settings.settings.raw >> 0x4);
- if (tag_data.settings.settings.amiibo_initialized == 0) {
- flags = flags & 0xfe;
- }
-
- u64 application_id = 0;
- u32 application_area_id = 0;
- AppAreaVersion app_area_version = 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);
-
- // 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_area_id = tag_data.application_area_id;
- }
-
- // TODO: Validate this data
- admin_info = {
- .application_id = application_id,
- .application_area_id = application_area_id,
- .crc_change_counter = tag_data.settings.crc_counter,
- .flags = flags,
- .tag_type = PackedTagType::Type2,
- .app_area_version = app_area_version,
- };
-
- return ResultSuccess;
-}
-
-Result NfpDevice::DeleteRegisterInfo() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.amiibo_initialized == 0) {
- return RegistrationIsNotInitialized;
- }
-
- Common::TinyMT rng{};
- rng.GenerateRandomBytes(&tag_data.owner_mii, sizeof(tag_data.owner_mii));
- rng.GenerateRandomBytes(&tag_data.settings.amiibo_name, sizeof(tag_data.settings.amiibo_name));
- rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8));
- rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32));
- rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32));
- rng.GenerateRandomBytes(&tag_data.register_info_crc, sizeof(u32));
- rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32));
- tag_data.settings.settings.font_region.Assign(0);
- tag_data.settings.settings.amiibo_initialized.Assign(0);
-
- return Flush();
-}
-
-Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- Service::Mii::MiiManager manager;
- const auto mii = manager.BuildDefault(0);
- auto& settings = tag_data.settings;
-
- if (tag_data.settings.settings.amiibo_initialized == 0) {
- settings.init_date = GetAmiiboDate(current_posix_time);
- settings.write_date.raw_date = 0;
- }
-
- SetAmiiboName(settings, amiibo_name);
- tag_data.owner_mii = manager.BuildFromStoreData(mii);
- tag_data.mii_extension = manager.SetFromStoreData(mii);
- tag_data.unknown = 0;
- tag_data.unknown2 = {};
- settings.country_code_id = 0;
- settings.settings.font_region.Assign(0);
- settings.settings.amiibo_initialized.Assign(1);
-
- UpdateRegisterInfoCrc();
-
- return Flush();
-}
-
-Result NfpDevice::RestoreAmiibo() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- // TODO: Load amiibo from backup on system
- LOG_ERROR(Service_NFP, "Not Implemented");
- return ResultSuccess;
-}
-
-Result NfpDevice::Format() {
- auto result1 = DeleteApplicationArea();
- auto result2 = DeleteRegisterInfo();
-
- if (result1.IsError()) {
- return result1;
- }
-
- if (result2.IsError()) {
- return result2;
- }
-
- return Flush();
-}
-
-Result NfpDevice::OpenApplicationArea(u32 access_id) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
- LOG_WARNING(Service_NFP, "Application area is not initialized");
- return ApplicationAreaIsNotInitialized;
- }
-
- if (tag_data.application_area_id != access_id) {
- LOG_WARNING(Service_NFP, "Wrong application area id");
- return WrongApplicationAreaId;
- }
-
- is_app_area_open = true;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const {
- application_area_id = {};
-
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
- LOG_WARNING(Service_NFP, "Application area is not initialized");
- return ApplicationAreaIsNotInitialized;
- }
-
- application_area_id = tag_data.application_area_id;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetApplicationArea(std::vector<u8>& data) const {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (!is_app_area_open) {
- LOG_ERROR(Service_NFP, "Application area is not open");
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
- LOG_ERROR(Service_NFP, "Application area is not initialized");
- return ApplicationAreaIsNotInitialized;
- }
-
- if (data.size() > sizeof(ApplicationArea)) {
- data.resize(sizeof(ApplicationArea));
- }
-
- memcpy(data.data(), tag_data.application_area.data(), data.size());
-
- return ResultSuccess;
-}
-
-Result NfpDevice::SetApplicationArea(std::span<const u8> data) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (!is_app_area_open) {
- LOG_ERROR(Service_NFP, "Application area is not open");
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
- LOG_ERROR(Service_NFP, "Application area is not initialized");
- return ApplicationAreaIsNotInitialized;
- }
-
- if (data.size() > sizeof(ApplicationArea)) {
- LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
- return ResultUnknown;
- }
-
- Common::TinyMT rng{};
- std::memcpy(tag_data.application_area.data(), data.data(), data.size());
- // Fill remaining data with random numbers
- rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
- sizeof(ApplicationArea) - data.size());
-
- if (tag_data.application_write_counter != counter_limit) {
- tag_data.application_write_counter++;
- }
-
- is_data_moddified = true;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::CreateApplicationArea(u32 access_id, std::span<const u8> data) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.appdata_initialized.Value() != 0) {
- LOG_ERROR(Service_NFP, "Application area already exist");
- return ApplicationAreaExist;
- }
-
- return RecreateApplicationArea(access_id, data);
-}
-
-Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> data) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (is_app_area_open) {
- LOG_ERROR(Service_NFP, "Application area is open");
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (data.size() > sizeof(ApplicationArea)) {
- LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
- return WrongApplicationAreaSize;
- }
-
- Common::TinyMT rng{};
- std::memcpy(tag_data.application_area.data(), data.data(), data.size());
- // Fill remaining data with random numbers
- rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
- sizeof(ApplicationArea) - data.size());
-
- if (tag_data.application_write_counter != 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);
- tag_data.application_id =
- RemoveVersionByte(application_id) |
- (static_cast<u64>(AppAreaVersion::NintendoSwitch) << application_id_version_offset);
- tag_data.settings.settings.appdata_initialized.Assign(1);
- tag_data.application_area_id = access_id;
- tag_data.unknown = {};
- tag_data.unknown2 = {};
-
- UpdateRegisterInfoCrc();
-
- return Flush();
-}
-
-Result NfpDevice::DeleteApplicationArea() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- if (tag_data.settings.settings.appdata_initialized == 0) {
- return ApplicationAreaIsNotInitialized;
- }
-
- if (tag_data.application_write_counter != counter_limit) {
- tag_data.application_write_counter++;
- }
-
- Common::TinyMT rng{};
- rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(ApplicationArea));
- rng.GenerateRandomBytes(&tag_data.application_id, sizeof(u64));
- rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32));
- rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8));
- tag_data.settings.settings.appdata_initialized.Assign(0);
- tag_data.unknown = {};
- tag_data.unknown2 = {};
- is_app_area_open = false;
-
- UpdateRegisterInfoCrc();
-
- return Flush();
-}
-
-Result NfpDevice::ExistApplicationArea(bool& has_application_area) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::GetAll(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 WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- CommonInfo common_info{};
- Service::Mii::MiiManager manager;
- const u64 application_id = tag_data.application_id;
-
- GetCommonInfo(common_info);
-
- data = {
- .magic = tag_data.constant_value,
- .write_counter = tag_data.write_counter,
- .settings_crc = tag_data.settings.crc,
- .common_info = common_info,
- .mii_char_info = tag_data.owner_mii,
- .mii_store_data_extension = tag_data.mii_extension,
- .creation_date = tag_data.settings.init_date.GetWriteDate(),
- .amiibo_name = tag_data.settings.amiibo_name,
- .amiibo_name_null_terminated = 0,
- .settings = tag_data.settings.settings,
- .unknown1 = tag_data.unknown,
- .register_info_crc = tag_data.register_info_crc,
- .unknown2 = tag_data.unknown2,
- .application_id = application_id,
- .access_id = tag_data.application_area_id,
- .settings_crc_counter = tag_data.settings.crc_counter,
- .font_region = tag_data.settings.settings.font_region,
- .tag_type = PackedTagType::Type2,
- .console_type =
- static_cast<AppAreaVersion>(application_id >> application_id_version_offset & 0xf),
- .application_id_byte = tag_data.application_id_byte,
- .application_area = tag_data.application_area,
- };
-
- return ResultSuccess;
-}
-
-Result NfpDevice::SetAll(const NfpData& data) {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- tag_data.constant_value = data.magic;
- tag_data.write_counter = data.write_counter;
- tag_data.settings.crc = data.settings_crc;
- tag_data.settings.write_date.SetWriteDate(data.common_info.last_write_date);
- tag_data.write_counter = data.common_info.write_counter;
- tag_data.amiibo_version = data.common_info.version;
- tag_data.owner_mii = data.mii_char_info;
- tag_data.mii_extension = data.mii_store_data_extension;
- tag_data.settings.init_date.SetWriteDate(data.creation_date);
- tag_data.settings.amiibo_name = data.amiibo_name;
- tag_data.settings.settings = data.settings;
- tag_data.unknown = data.unknown1;
- tag_data.register_info_crc = data.register_info_crc;
- tag_data.unknown2 = data.unknown2;
- tag_data.application_id = data.application_id;
- tag_data.application_area_id = data.access_id;
- tag_data.settings.crc_counter = data.settings_crc_counter;
- tag_data.settings.settings.font_region.Assign(data.font_region);
- tag_data.application_id_byte = data.application_id_byte;
- tag_data.application_area = data.application_area;
-
- return ResultSuccess;
-}
-
-Result NfpDevice::BreakTag(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 WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- // TODO: Complete this implementation
-
- return FlushWithBreak(break_type);
-}
-
-Result NfpDevice::ReadBackupData() {
- // Not implemented
- return ResultSuccess;
-}
-
-Result NfpDevice::WriteBackupData() {
- // Not implemented
- return ResultSuccess;
-}
-
-Result NfpDevice::WriteNtf() {
- if (device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return TagRemoved;
- }
- return WrongDeviceState;
- }
-
- if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
- LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
- return WrongDeviceState;
- }
-
- // Not implemented
-
- 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{};
-
- // Convert from big endian to little endian
- for (std::size_t i = 0; i < amiibo_name_length; i++) {
- settings_amiibo_name[i] = static_cast<u16>(settings.amiibo_name[i]);
- }
-
- // Convert from utf16 to utf8
- const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data());
- memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size());
-
- return amiibo_name;
-}
-
-void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name) {
- std::array<char16_t, amiibo_name_length> settings_amiibo_name{};
-
- // Convert from utf8 to utf16
- const auto amiibo_name_utf16 = Common::UTF8ToUTF16(amiibo_name.data());
- memcpy(settings_amiibo_name.data(), amiibo_name_utf16.data(),
- amiibo_name_utf16.size() * sizeof(char16_t));
-
- // Convert from little endian to big endian
- for (std::size_t i = 0; i < amiibo_name_length; i++) {
- settings.amiibo_name[i] = static_cast<u16_be>(settings_amiibo_name[i]);
- }
-}
-
-AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const {
- const auto& time_zone_manager =
- system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager();
- Time::TimeZone::CalendarInfo calendar_info{};
- AmiiboDate amiibo_date{};
-
- amiibo_date.SetYear(2000);
- amiibo_date.SetMonth(1);
- amiibo_date.SetDay(1);
-
- if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) {
- amiibo_date.SetYear(calendar_info.time.year);
- amiibo_date.SetMonth(calendar_info.time.month);
- amiibo_date.SetDay(calendar_info.time.day);
- }
-
- return amiibo_date;
-}
-
-u64 NfpDevice::RemoveVersionByte(u64 application_id) const {
- return application_id & ~(0xfULL << application_id_version_offset);
-}
-
-void NfpDevice::UpdateSettingsCrc() {
- auto& settings = tag_data.settings;
-
- if (settings.crc_counter != counter_limit) {
- settings.crc_counter++;
- }
-
- // TODO: this reads data from a global, find what it is
- std::array<u8, 8> unknown_input{};
- boost::crc_32_type crc;
- crc.process_bytes(&unknown_input, sizeof(unknown_input));
- settings.crc = crc.checksum();
-}
-
-void NfpDevice::UpdateRegisterInfoCrc() {
-#pragma pack(push, 1)
- struct CrcData {
- Mii::Ver3StoreData mii;
- u8 application_id_byte;
- u8 unknown;
- Mii::NfpStoreDataExtension mii_extension;
- std::array<u32, 0x5> unknown2;
- };
- static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size");
-#pragma pack(pop)
-
- const CrcData crc_data{
- .mii = tag_data.owner_mii,
- .application_id_byte = tag_data.application_id_byte,
- .unknown = tag_data.unknown,
- .mii_extension = tag_data.mii_extension,
- .unknown2 = tag_data.unknown2,
- };
-
- boost::crc_32_type crc;
- crc.process_bytes(&crc_data, sizeof(CrcData));
- tag_data.register_info_crc = crc.checksum();
-}
-
-} // namespace Service::NFP
diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h
deleted file mode 100644
index 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(&register_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