From 6c045c9beb9c202fdea49274edd845fb2af491c3 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 13 Nov 2022 10:52:48 -0600
Subject: [PATCH] service: nfc: fix tagprotocol and implement
 GetApplicationAreaId

---
 src/core/hle/service/nfp/nfp_device.cpp | 33 +++++++++++++++++++++++--
 src/core/hle/service/nfp/nfp_device.h   |  6 +++--
 src/core/hle/service/nfp/nfp_types.h    | 10 +++++---
 src/core/hle/service/nfp/nfp_user.cpp   |  2 +-
 4 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp
index b196725601..2f9dfa9c20 100644
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ b/src/core/hle/service/nfp/nfp_device.cpp
@@ -77,6 +77,9 @@ void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
         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();
         }
@@ -97,6 +100,8 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) {
         return false;
     }
 
+    // TODO: Filter by allowed_protocols here
+
     memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File));
 
     device_state = DeviceState::TagFound;
@@ -143,7 +148,7 @@ void NfpDevice::Finalize() {
     device_state = DeviceState::Unavailable;
 }
 
-Result NfpDevice::StartDetection(s32 protocol_) {
+Result NfpDevice::StartDetection([[maybe_unused]] TagProtocol allowed_protocol) {
     if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) {
         LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
         return WrongDeviceState;
@@ -155,7 +160,7 @@ Result NfpDevice::StartDetection(s32 protocol_) {
     }
 
     device_state = DeviceState::SearchingForTag;
-    protocol = protocol_;
+    allowed_protocols = allowed_protocol;
     return ResultSuccess;
 }
 
@@ -469,6 +474,30 @@ Result NfpDevice::OpenApplicationArea(u32 access_id) {
     return ResultSuccess;
 }
 
+Result NfpDevice::GetApplicationAreaId(u32& application_area_id) 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.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);
diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h
index 76d0e9ae46..3d1cb46095 100644
--- a/src/core/hle/service/nfp/nfp_device.h
+++ b/src/core/hle/service/nfp/nfp_device.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <array>
+#include <span>
 #include <vector>
 
 #include "common/common_funcs.h"
@@ -37,7 +38,7 @@ public:
     void Initialize();
     void Finalize();
 
-    Result StartDetection(s32 protocol_);
+    Result StartDetection(TagProtocol allowed_protocol);
     Result StopDetection();
     Result Mount(MountTarget mount_target);
     Result Unmount();
@@ -53,6 +54,7 @@ public:
     Result DeleteAllData();
 
     Result OpenApplicationArea(u32 access_id);
+    Result GetApplicationAreaId(u32& application_area_id) const;
     Result GetApplicationArea(std::vector<u8>& data) const;
     Result SetApplicationArea(std::span<const u8> data);
     Result CreateApplicationArea(u32 access_id, std::span<const u8> data);
@@ -88,7 +90,7 @@ private:
 
     bool is_data_moddified{};
     bool is_app_area_open{};
-    s32 protocol{};
+    TagProtocol allowed_protocols{};
     s64 current_posix_time{};
     MountTarget mount_target{MountTarget::None};
     DeviceState device_state{DeviceState::Unavailable};
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index 63d5917cb0..866aefe209 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -88,11 +88,15 @@ enum class PackedTagType : u8 {
     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, // ISO14443A
-    TypeB, // ISO14443B
-    TypeF, // Sony Felica
+    TypeA = 1U << 0, // ISO14443A
+    TypeB = 1U << 1, // ISO14443B
+    TypeF = 1U << 2, // Sony Felica
+    Unknown1 = 1U << 3,
+    Unknown2 = 1U << 5,
+    All = 0xFFFFFFFFU,
 };
 
 using UniqueSerialNumber = std::array<u8, 7>;
diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp
index 33e2ef5183..ac492cc27e 100644
--- a/src/core/hle/service/nfp/nfp_user.cpp
+++ b/src/core/hle/service/nfp/nfp_user.cpp
@@ -130,7 +130,7 @@ void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
 void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto device_handle{rp.Pop<u64>()};
-    const auto nfp_protocol{rp.Pop<s32>()};
+    const auto nfp_protocol{rp.PopEnum<TagProtocol>()};
     LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
 
     if (state == State::NonInitialized) {