summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt21
-rw-r--r--src/core/frontend/applets/cabinet.cpp2
-rw-r--r--src/core/frontend/applets/cabinet.h10
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp24
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.h6
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.cpp (renamed from src/core/hle/service/nfp/amiibo_crypto.cpp)4
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.h (renamed from src/core/hle/service/nfp/amiibo_crypto.h)4
-rw-r--r--src/core/hle/service/nfc/common/device.cpp (renamed from src/core/hle/service/nfp/nfp_device.cpp)672
-rw-r--r--src/core/hle/service/nfc/common/device.h138
-rw-r--r--src/core/hle/service/nfc/common/device_manager.cpp695
-rw-r--r--src/core/hle/service/nfc/common/device_manager.h100
-rw-r--r--src/core/hle/service/nfc/mifare_interface.cpp382
-rw-r--r--src/core/hle/service/nfc/mifare_interface.h52
-rw-r--r--src/core/hle/service/nfc/mifare_result.h17
-rw-r--r--src/core/hle/service/nfc/mifare_types.h63
-rw-r--r--src/core/hle/service/nfc/nfc.cpp125
-rw-r--r--src/core/hle/service/nfc/nfc_device.cpp287
-rw-r--r--src/core/hle/service/nfc/nfc_device.h78
-rw-r--r--src/core/hle/service/nfc/nfc_interface.cpp399
-rw-r--r--src/core/hle/service/nfc/nfc_interface.h33
-rw-r--r--src/core/hle/service/nfc/nfc_result.h33
-rw-r--r--src/core/hle/service/nfc/nfc_types.h90
-rw-r--r--src/core/hle/service/nfp/nfp.cpp12
-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
-rw-r--r--src/yuzu/applets/qt_amiibo_settings.cpp12
-rw-r--r--src/yuzu/applets/qt_amiibo_settings.h14
-rw-r--r--src/yuzu/main.cpp6
-rw-r--r--src/yuzu/main.h8
32 files changed, 2031 insertions, 2410 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8817a99c9..45328158f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -555,21 +555,22 @@ add_library(core STATIC
555 hle/service/mnpp/mnpp_app.h 555 hle/service/mnpp/mnpp_app.h
556 hle/service/ncm/ncm.cpp 556 hle/service/ncm/ncm.cpp
557 hle/service/ncm/ncm.h 557 hle/service/ncm/ncm.h
558 hle/service/nfc/mifare_user.cpp 558 hle/service/nfc/common/amiibo_crypto.cpp
559 hle/service/nfc/mifare_user.h 559 hle/service/nfc/common/amiibo_crypto.h
560 hle/service/nfc/common/device.cpp
561 hle/service/nfc/common/device.h
562 hle/service/nfc/common/device_manager.cpp
563 hle/service/nfc/common/device_manager.h
564 hle/service/nfc/mifare_result.h
565 hle/service/nfc/mifare_types.h
560 hle/service/nfc/nfc.cpp 566 hle/service/nfc/nfc.cpp
561 hle/service/nfc/nfc.h 567 hle/service/nfc/nfc.h
562 hle/service/nfc/nfc_device.cpp 568 hle/service/nfc/nfc_interface.cpp
563 hle/service/nfc/nfc_device.h 569 hle/service/nfc/nfc_interface.h
564 hle/service/nfc/nfc_result.h 570 hle/service/nfc/nfc_result.h
565 hle/service/nfc/nfc_user.cpp 571 hle/service/nfc/nfc_types.h
566 hle/service/nfc/nfc_user.h
567 hle/service/nfp/amiibo_crypto.cpp
568 hle/service/nfp/amiibo_crypto.h
569 hle/service/nfp/nfp.cpp 572 hle/service/nfp/nfp.cpp
570 hle/service/nfp/nfp.h 573 hle/service/nfp/nfp.h
571 hle/service/nfp/nfp_device.cpp
572 hle/service/nfp/nfp_device.h
573 hle/service/nfp/nfp_interface.cpp 574 hle/service/nfp/nfp_interface.cpp
574 hle/service/nfp/nfp_interface.h 575 hle/service/nfp/nfp_interface.h
575 hle/service/nfp/nfp_result.h 576 hle/service/nfp/nfp_result.h
diff --git a/src/core/frontend/applets/cabinet.cpp b/src/core/frontend/applets/cabinet.cpp
index 2d501eeae..c33ce248b 100644
--- a/src/core/frontend/applets/cabinet.cpp
+++ b/src/core/frontend/applets/cabinet.cpp
@@ -14,7 +14,7 @@ void DefaultCabinetApplet::Close() const {}
14 14
15void DefaultCabinetApplet::ShowCabinetApplet( 15void DefaultCabinetApplet::ShowCabinetApplet(
16 const CabinetCallback& callback, const CabinetParameters& parameters, 16 const CabinetCallback& callback, const CabinetParameters& parameters,
17 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const { 17 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const {
18 LOG_WARNING(Service_AM, "(STUBBED) called"); 18 LOG_WARNING(Service_AM, "(STUBBED) called");
19 callback(false, {}); 19 callback(false, {});
20} 20}
diff --git a/src/core/frontend/applets/cabinet.h b/src/core/frontend/applets/cabinet.h
index 74dc5a4f6..af3fc6c3d 100644
--- a/src/core/frontend/applets/cabinet.h
+++ b/src/core/frontend/applets/cabinet.h
@@ -7,9 +7,9 @@
7#include "core/frontend/applets/applet.h" 7#include "core/frontend/applets/applet.h"
8#include "core/hle/service/nfp/nfp_types.h" 8#include "core/hle/service/nfp/nfp_types.h"
9 9
10namespace Service::NFP { 10namespace Service::NFC {
11class NfpDevice; 11class NfcDevice;
12} // namespace Service::NFP 12} // namespace Service::NFC
13 13
14namespace Core::Frontend { 14namespace Core::Frontend {
15 15
@@ -26,14 +26,14 @@ public:
26 virtual ~CabinetApplet(); 26 virtual ~CabinetApplet();
27 virtual void ShowCabinetApplet(const CabinetCallback& callback, 27 virtual void ShowCabinetApplet(const CabinetCallback& callback,
28 const CabinetParameters& parameters, 28 const CabinetParameters& parameters,
29 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const = 0; 29 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const = 0;
30}; 30};
31 31
32class DefaultCabinetApplet final : public CabinetApplet { 32class DefaultCabinetApplet final : public CabinetApplet {
33public: 33public:
34 void Close() const override; 34 void Close() const override;
35 void ShowCabinetApplet(const CabinetCallback& callback, const CabinetParameters& parameters, 35 void ShowCabinetApplet(const CabinetCallback& callback, const CabinetParameters& parameters,
36 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; 36 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const override;
37}; 37};
38 38
39} // namespace Core::Frontend 39} // namespace Core::Frontend
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index 93c9f2a55..8b754e9d4 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -11,7 +11,7 @@
11#include "core/hle/service/am/am.h" 11#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/applet_cabinet.h" 12#include "core/hle/service/am/applets/applet_cabinet.h"
13#include "core/hle/service/mii/mii_manager.h" 13#include "core/hle/service/mii/mii_manager.h"
14#include "core/hle/service/nfp/nfp_device.h" 14#include "core/hle/service/nfc/common/device.h"
15 15
16namespace Service::AM::Applets { 16namespace Service::AM::Applets {
17 17
@@ -72,10 +72,10 @@ void Cabinet::Execute() {
72 72
73 // TODO: listen on all controllers 73 // TODO: listen on all controllers
74 if (nfp_device == nullptr) { 74 if (nfp_device == nullptr) {
75 nfp_device = std::make_shared<Service::NFP::NfpDevice>( 75 nfp_device = std::make_shared<Service::NFC::NfcDevice>(
76 system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event); 76 system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event);
77 nfp_device->Initialize(); 77 nfp_device->Initialize();
78 nfp_device->StartDetection(Service::NFP::TagProtocol::All); 78 nfp_device->StartDetection(Service::NFC::NfcProtocol::All);
79 } 79 }
80 80
81 const Core::Frontend::CabinetParameters parameters{ 81 const Core::Frontend::CabinetParameters parameters{
@@ -106,20 +106,22 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
106 Cancel(); 106 Cancel();
107 } 107 }
108 108
109 if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && 109 if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound &&
110 nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { 110 nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) {
111 Cancel(); 111 Cancel();
112 } 112 }
113 113
114 if (nfp_device->GetCurrentState() == Service::NFP::DeviceState::TagFound) { 114 if (nfp_device->GetCurrentState() == Service::NFC::DeviceState::TagFound) {
115 nfp_device->Mount(Service::NFP::MountTarget::All); 115 nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All);
116 } 116 }
117 117
118 switch (applet_input_common.applet_mode) { 118 switch (applet_input_common.applet_mode) {
119 case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { 119 case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: {
120 Service::NFP::AmiiboName name{}; 120 Service::NFP::RegisterInfoPrivate register_info{};
121 std::memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1)); 121 std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(),
122 nfp_device->SetRegisterInfoPrivate(name); 122 std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1));
123
124 nfp_device->SetRegisterInfoPrivate(register_info);
123 break; 125 break;
124 } 126 }
125 case Service::NFP::CabinetMode::StartGameDataEraser: 127 case Service::NFP::CabinetMode::StartGameDataEraser:
@@ -139,7 +141,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
139 applet_output.device_handle = applet_input_common.device_handle; 141 applet_output.device_handle = applet_input_common.device_handle;
140 applet_output.result = CabinetResult::Cancel; 142 applet_output.result = CabinetResult::Cancel;
141 const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info); 143 const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info);
142 const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info); 144 const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info, false);
143 nfp_device->Finalize(); 145 nfp_device->Finalize();
144 146
145 if (reg_result.IsSuccess()) { 147 if (reg_result.IsSuccess()) {
diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h
index edd295a27..b56427021 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.h
+++ b/src/core/hle/service/am/applets/applet_cabinet.h
@@ -19,8 +19,8 @@ namespace Core {
19class System; 19class System;
20} // namespace Core 20} // namespace Core
21 21
22namespace Service::NFP { 22namespace Service::NFC {
23class NfpDevice; 23class NfcDevice;
24} 24}
25 25
26namespace Service::AM::Applets { 26namespace Service::AM::Applets {
@@ -96,7 +96,7 @@ private:
96 Core::System& system; 96 Core::System& system;
97 97
98 bool is_complete{false}; 98 bool is_complete{false};
99 std::shared_ptr<Service::NFP::NfpDevice> nfp_device; 99 std::shared_ptr<Service::NFC::NfcDevice> nfp_device;
100 Kernel::KEvent* availability_change_event; 100 Kernel::KEvent* availability_change_event;
101 KernelHelpers::ServiceContext service_context; 101 KernelHelpers::ServiceContext service_context;
102 StartParamForAmiiboSettings applet_input_common{}; 102 StartParamForAmiiboSettings applet_input_common{};
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
index a3622e792..f3901ee8d 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
@@ -12,7 +12,7 @@
12#include "common/fs/fs.h" 12#include "common/fs/fs.h"
13#include "common/fs/path_util.h" 13#include "common/fs/path_util.h"
14#include "common/logging/log.h" 14#include "common/logging/log.h"
15#include "core/hle/service/nfp/amiibo_crypto.h" 15#include "core/hle/service/nfc/common/amiibo_crypto.h"
16 16
17namespace Service::NFP::AmiiboCrypto { 17namespace Service::NFP::AmiiboCrypto {
18 18
@@ -55,7 +55,7 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
55 if (amiibo_data.constant_value != 0xA5) { 55 if (amiibo_data.constant_value != 0xA5) {
56 return false; 56 return false;
57 } 57 }
58 if (amiibo_data.model_info.tag_type != PackedTagType::Type2) { 58 if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) {
59 return false; 59 return false;
60 } 60 }
61 if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) { 61 if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) {
diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h
index f6208ee6b..bf3044ed9 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.h
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.h
@@ -24,9 +24,9 @@ using DrgbOutput = std::array<u8, 0x20>;
24struct HashSeed { 24struct HashSeed {
25 u16_be magic; 25 u16_be magic;
26 std::array<u8, 0xE> padding; 26 std::array<u8, 0xE> padding;
27 UniqueSerialNumber uid_1; 27 NFC::UniqueSerialNumber uid_1;
28 u8 nintendo_id_1; 28 u8 nintendo_id_1;
29 UniqueSerialNumber uid_2; 29 NFC::UniqueSerialNumber uid_2;
30 u8 nintendo_id_2; 30 u8 nintendo_id_2;
31 std::array<u8, 0x20> keygen_salt; 31 std::array<u8, 0x20> keygen_salt;
32}; 32};
diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 3f9af53c8..e5de65ce0 100644
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -1,8 +1,6 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <array>
5
6#ifdef _MSC_VER 4#ifdef _MSC_VER
7#pragma warning(push) 5#pragma warning(push)
8#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used 6#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used
@@ -26,21 +24,22 @@
26#include "core/hle/service/ipc_helpers.h" 24#include "core/hle/service/ipc_helpers.h"
27#include "core/hle/service/mii/mii_manager.h" 25#include "core/hle/service/mii/mii_manager.h"
28#include "core/hle/service/mii/types.h" 26#include "core/hle/service/mii/types.h"
29#include "core/hle/service/nfp/amiibo_crypto.h" 27#include "core/hle/service/nfc/common/amiibo_crypto.h"
30#include "core/hle/service/nfp/nfp_device.h" 28#include "core/hle/service/nfc/common/device.h"
31#include "core/hle/service/nfp/nfp_result.h" 29#include "core/hle/service/nfc/mifare_result.h"
30#include "core/hle/service/nfc/nfc_result.h"
32#include "core/hle/service/time/time_manager.h" 31#include "core/hle/service/time/time_manager.h"
33#include "core/hle/service/time/time_zone_content_manager.h" 32#include "core/hle/service/time/time_zone_content_manager.h"
34#include "core/hle/service/time/time_zone_types.h" 33#include "core/hle/service/time/time_zone_types.h"
35 34
36namespace Service::NFP { 35namespace Service::NFC {
37NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, 36NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
38 KernelHelpers::ServiceContext& service_context_, 37 KernelHelpers::ServiceContext& service_context_,
39 Kernel::KEvent* availability_change_event_) 38 Kernel::KEvent* availability_change_event_)
40 : npad_id{npad_id_}, system{system_}, service_context{service_context_}, 39 : npad_id{npad_id_}, system{system_}, service_context{service_context_},
41 availability_change_event{availability_change_event_} { 40 availability_change_event{availability_change_event_} {
42 activate_event = service_context.CreateEvent("IUser:NFPActivateEvent"); 41 activate_event = service_context.CreateEvent("NFC:ActivateEvent");
43 deactivate_event = service_context.CreateEvent("IUser:NFPDeactivateEvent"); 42 deactivate_event = service_context.CreateEvent("NFC:DeactivateEvent");
44 npad_device = system.HIDCore().GetEmulatedController(npad_id); 43 npad_device = system.HIDCore().GetEmulatedController(npad_id);
45 44
46 Core::HID::ControllerUpdateCallback engine_callback{ 45 Core::HID::ControllerUpdateCallback engine_callback{
@@ -54,9 +53,9 @@ NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
54 current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point; 53 current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point;
55} 54}
56 55
57NfpDevice::~NfpDevice() { 56NfcDevice::~NfcDevice() {
58 activate_event->Close(); 57 service_context.CloseEvent(activate_event);
59 deactivate_event->Close(); 58 service_context.CloseEvent(deactivate_event);
60 if (!is_controller_set) { 59 if (!is_controller_set) {
61 return; 60 return;
62 } 61 }
@@ -64,7 +63,7 @@ NfpDevice::~NfpDevice() {
64 is_controller_set = false; 63 is_controller_set = false;
65}; 64};
66 65
67void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { 66void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
68 if (!is_initalized) { 67 if (!is_initalized) {
69 return; 68 return;
70 } 69 }
@@ -92,14 +91,14 @@ void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
92 const auto nfc_status = npad_device->GetNfc(); 91 const auto nfc_status = npad_device->GetNfc();
93 switch (nfc_status.state) { 92 switch (nfc_status.state) {
94 case Common::Input::NfcState::NewAmiibo: 93 case Common::Input::NfcState::NewAmiibo:
95 LoadAmiibo(nfc_status.data); 94 LoadNfcTag(nfc_status.data);
96 break; 95 break;
97 case Common::Input::NfcState::AmiiboRemoved: 96 case Common::Input::NfcState::AmiiboRemoved:
98 if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { 97 if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
99 break; 98 break;
100 } 99 }
101 if (device_state != DeviceState::SearchingForTag) { 100 if (device_state != DeviceState::SearchingForTag) {
102 CloseAmiibo(); 101 CloseNfcTag();
103 } 102 }
104 break; 103 break;
105 default: 104 default:
@@ -107,28 +106,29 @@ void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
107 } 106 }
108} 107}
109 108
110bool NfpDevice::LoadAmiibo(std::span<const u8> data) { 109bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
111 if (device_state != DeviceState::SearchingForTag) { 110 if (device_state != DeviceState::SearchingForTag) {
112 LOG_ERROR(Service_NFP, "Game is not looking for amiibos, current state {}", device_state); 111 LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state);
113 return false; 112 return false;
114 } 113 }
115 114
116 if (data.size() != sizeof(EncryptedNTAG215File)) { 115 if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {
117 LOG_ERROR(Service_NFP, "Not an amiibo, size={}", data.size()); 116 LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());
118 return false; 117 return false;
119 } 118 }
120 119
121 // TODO: Filter by allowed_protocols here 120 mifare_data.resize(data.size());
121 memcpy(mifare_data.data(), data.data(), data.size());
122 122
123 memcpy(&tag_data, data.data(), sizeof(EncryptedNTAG215File)); 123 memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
124 is_plain_amiibo = AmiiboCrypto::IsAmiiboValid(tag_data); 124 is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data);
125 125
126 if (is_plain_amiibo) { 126 if (is_plain_amiibo) {
127 encrypted_tag_data = AmiiboCrypto::EncodedDataToNfcData(tag_data); 127 encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(tag_data);
128 LOG_INFO(Service_NFP, "Using plain amiibo"); 128 LOG_INFO(Service_NFP, "Using plain amiibo");
129 } else { 129 } else {
130 tag_data = {}; 130 tag_data = {};
131 memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); 131 memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
132 } 132 }
133 133
134 device_state = DeviceState::TagFound; 134 device_state = DeviceState::TagFound;
@@ -137,8 +137,8 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) {
137 return true; 137 return true;
138} 138}
139 139
140void NfpDevice::CloseAmiibo() { 140void NfcDevice::CloseNfcTag() {
141 LOG_INFO(Service_NFP, "Remove amiibo"); 141 LOG_INFO(Service_NFC, "Remove nfc tag");
142 142
143 if (device_state == DeviceState::TagMounted) { 143 if (device_state == DeviceState::TagMounted) {
144 Unmount(); 144 Unmount();
@@ -147,26 +147,28 @@ void NfpDevice::CloseAmiibo() {
147 device_state = DeviceState::TagRemoved; 147 device_state = DeviceState::TagRemoved;
148 encrypted_tag_data = {}; 148 encrypted_tag_data = {};
149 tag_data = {}; 149 tag_data = {};
150 mifare_data = {};
150 activate_event->GetReadableEvent().Clear(); 151 activate_event->GetReadableEvent().Clear();
151 deactivate_event->Signal(); 152 deactivate_event->Signal();
152} 153}
153 154
154Kernel::KReadableEvent& NfpDevice::GetActivateEvent() const { 155Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const {
155 return activate_event->GetReadableEvent(); 156 return activate_event->GetReadableEvent();
156} 157}
157 158
158Kernel::KReadableEvent& NfpDevice::GetDeactivateEvent() const { 159Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const {
159 return deactivate_event->GetReadableEvent(); 160 return deactivate_event->GetReadableEvent();
160} 161}
161 162
162void NfpDevice::Initialize() { 163void NfcDevice::Initialize() {
163 device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable; 164 device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable;
164 encrypted_tag_data = {}; 165 encrypted_tag_data = {};
165 tag_data = {}; 166 tag_data = {};
167 mifare_data = {};
166 is_initalized = true; 168 is_initalized = true;
167} 169}
168 170
169void NfpDevice::Finalize() { 171void NfcDevice::Finalize() {
170 if (device_state == DeviceState::TagMounted) { 172 if (device_state == DeviceState::TagMounted) {
171 Unmount(); 173 Unmount();
172 } 174 }
@@ -177,17 +179,17 @@ void NfpDevice::Finalize() {
177 is_initalized = false; 179 is_initalized = false;
178} 180}
179 181
180Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { 182Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {
181 if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { 183 if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) {
182 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 184 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
183 return WrongDeviceState; 185 return ResultWrongDeviceState;
184 } 186 }
185 187
186 if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, 188 if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
187 Common::Input::PollingMode::NFC) != 189 Common::Input::PollingMode::NFC) !=
188 Common::Input::DriverResult::Success) { 190 Common::Input::DriverResult::Success) {
189 LOG_ERROR(Service_NFP, "Nfc not supported"); 191 LOG_ERROR(Service_NFC, "Nfc not supported");
190 return NfcDisabled; 192 return ResultNfcDisabled;
191 } 193 }
192 194
193 device_state = DeviceState::SearchingForTag; 195 device_state = DeviceState::SearchingForTag;
@@ -195,7 +197,7 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) {
195 return ResultSuccess; 197 return ResultSuccess;
196} 198}
197 199
198Result NfpDevice::StopDetection() { 200Result NfcDevice::StopDetection() {
199 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, 201 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
200 Common::Input::PollingMode::Active); 202 Common::Input::PollingMode::Active);
201 203
@@ -204,7 +206,7 @@ Result NfpDevice::StopDetection() {
204 } 206 }
205 207
206 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { 208 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
207 CloseAmiibo(); 209 CloseNfcTag();
208 } 210 }
209 211
210 if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { 212 if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
@@ -212,94 +214,129 @@ Result NfpDevice::StopDetection() {
212 return ResultSuccess; 214 return ResultSuccess;
213 } 215 }
214 216
215 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 217 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
216 return WrongDeviceState; 218 return ResultWrongDeviceState;
217} 219}
218 220
219Result NfpDevice::Flush() { 221Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
220 if (device_state != DeviceState::TagMounted) { 222 if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
221 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 223 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
222 if (device_state == DeviceState::TagRemoved) { 224 if (device_state == DeviceState::TagRemoved) {
223 return TagRemoved; 225 return ResultTagRemoved;
224 } 226 }
225 return WrongDeviceState; 227 return ResultWrongDeviceState;
226 } 228 }
227 229
228 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 230 if (is_mifare) {
229 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 231 tag_info = {
230 return WrongDeviceState; 232 .uuid = encrypted_tag_data.uuid.uid,
233 .uuid_extension = {},
234 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
235 .protocol = NfcProtocol::TypeA,
236 .tag_type = TagType::Type4,
237 };
238 return ResultSuccess;
231 } 239 }
232 240
233 auto& settings = tag_data.settings; 241 // Protocol and tag type may change here
234 242 tag_info = {
235 const auto& current_date = GetAmiiboDate(current_posix_time); 243 .uuid = encrypted_tag_data.uuid.uid,
236 if (settings.write_date.raw_date != current_date.raw_date) { 244 .uuid_extension = {},
237 settings.write_date = current_date; 245 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
238 UpdateSettingsCrc(); 246 .protocol = NfcProtocol::TypeA,
239 } 247 .tag_type = TagType::Type2,
248 };
240 249
241 tag_data.write_counter++; 250 return ResultSuccess;
251}
242 252
243 FlushWithBreak(BreakType::Normal); 253Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameters,
254 std::span<MifareReadBlockData> read_block_data) const {
255 Result result = ResultSuccess;
244 256
245 is_data_moddified = false; 257 for (std::size_t i = 0; i < parameters.size(); i++) {
258 result = ReadMifare(parameters[i], read_block_data[i]);
259 if (result.IsError()) {
260 break;
261 }
262 }
246 263
247 return ResultSuccess; 264 return result;
248} 265}
249 266
250Result NfpDevice::FlushDebug() { 267Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter,
251 if (device_state != DeviceState::TagMounted) { 268 MifareReadBlockData& read_block_data) const {
269 const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock);
270 read_block_data.sector_number = parameter.sector_number;
271
272 if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
252 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 273 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
253 if (device_state == DeviceState::TagRemoved) { 274 if (device_state == DeviceState::TagRemoved) {
254 return TagRemoved; 275 return ResultTagRemoved;
255 } 276 }
256 return WrongDeviceState; 277 return ResultWrongDeviceState;
257 } 278 }
258 279
259 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 280 if (mifare_data.size() < sector_index + sizeof(DataBlock)) {
260 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 281 return Mifare::ResultReadError;
261 return WrongDeviceState;
262 } 282 }
263 283
264 tag_data.write_counter++; 284 // TODO: Use parameter.sector_key to read encrypted data
265 285 memcpy(read_block_data.data.data(), mifare_data.data() + sector_index, sizeof(DataBlock));
266 FlushWithBreak(BreakType::Normal);
267
268 is_data_moddified = false;
269 286
270 return ResultSuccess; 287 return ResultSuccess;
271} 288}
272 289
273Result NfpDevice::FlushWithBreak(BreakType break_type) { 290Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> parameters) {
274 if (break_type != BreakType::Normal) { 291 Result result = ResultSuccess;
275 LOG_ERROR(Service_NFC, "Break type not implemented {}", break_type);
276 return WrongDeviceState;
277 }
278 292
279 std::vector<u8> data(sizeof(EncryptedNTAG215File)); 293 for (std::size_t i = 0; i < parameters.size(); i++) {
280 if (is_plain_amiibo) { 294 result = WriteMifare(parameters[i]);
281 memcpy(data.data(), &tag_data, sizeof(tag_data)); 295 if (result.IsError()) {
282 } else { 296 break;
283 if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) {
284 LOG_ERROR(Service_NFP, "Failed to encode data");
285 return WriteAmiiboFailed;
286 } 297 }
287
288 memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
289 } 298 }
290 299
291 if (!npad_device->WriteNfc(data)) { 300 if (!npad_device->WriteNfc(mifare_data)) {
292 LOG_ERROR(Service_NFP, "Error writing to file"); 301 LOG_ERROR(Service_NFP, "Error writing to file");
293 return WriteAmiiboFailed; 302 return Mifare::ResultReadError;
303 }
304
305 return result;
306}
307
308Result NfcDevice::WriteMifare(const MifareWriteBlockParameter& parameter) {
309 const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock);
310
311 if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
312 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
313 if (device_state == DeviceState::TagRemoved) {
314 return ResultTagRemoved;
315 }
316 return ResultWrongDeviceState;
317 }
318
319 if (mifare_data.size() < sector_index + sizeof(DataBlock)) {
320 return Mifare::ResultReadError;
294 } 321 }
295 322
323 // TODO: Use parameter.sector_key to encrypt the data
324 memcpy(mifare_data.data() + sector_index, parameter.data.data(), sizeof(DataBlock));
325
296 return ResultSuccess; 326 return ResultSuccess;
297} 327}
298 328
299Result NfpDevice::Mount(MountTarget mount_target_) { 329Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
330 std::span<const u8> command_data,
331 std::span<u8> out_data) {
332 // Not implemented
333 return ResultSuccess;
334}
335
336Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) {
300 if (device_state != DeviceState::TagFound) { 337 if (device_state != DeviceState::TagFound) {
301 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 338 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
302 return WrongDeviceState; 339 return ResultWrongDeviceState;
303 } 340 }
304 341
305 // The loaded amiibo is not encrypted 342 // The loaded amiibo is not encrypted
@@ -309,22 +346,22 @@ Result NfpDevice::Mount(MountTarget mount_target_) {
309 return ResultSuccess; 346 return ResultSuccess;
310 } 347 }
311 348
312 if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { 349 if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
313 LOG_ERROR(Service_NFP, "Not an amiibo"); 350 LOG_ERROR(Service_NFP, "Not an amiibo");
314 return NotAnAmiibo; 351 return ResultNotAnAmiibo;
315 } 352 }
316 353
317 // Mark amiibos as read only when keys are missing 354 // Mark amiibos as read only when keys are missing
318 if (!AmiiboCrypto::IsKeyAvailable()) { 355 if (!NFP::AmiiboCrypto::IsKeyAvailable()) {
319 LOG_ERROR(Service_NFP, "No keys detected"); 356 LOG_ERROR(Service_NFP, "No keys detected");
320 device_state = DeviceState::TagMounted; 357 device_state = DeviceState::TagMounted;
321 mount_target = MountTarget::Rom; 358 mount_target = NFP::MountTarget::Rom;
322 return ResultSuccess; 359 return ResultSuccess;
323 } 360 }
324 361
325 if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { 362 if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
326 LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state); 363 LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state);
327 return CorruptedData; 364 return ResultCorruptedData;
328 } 365 }
329 366
330 device_state = DeviceState::TagMounted; 367 device_state = DeviceState::TagMounted;
@@ -332,13 +369,13 @@ Result NfpDevice::Mount(MountTarget mount_target_) {
332 return ResultSuccess; 369 return ResultSuccess;
333} 370}
334 371
335Result NfpDevice::Unmount() { 372Result NfcDevice::Unmount() {
336 if (device_state != DeviceState::TagMounted) { 373 if (device_state != DeviceState::TagMounted) {
337 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 374 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
338 if (device_state == DeviceState::TagRemoved) { 375 if (device_state == DeviceState::TagRemoved) {
339 return TagRemoved; 376 return ResultTagRemoved;
340 } 377 }
341 return WrongDeviceState; 378 return ResultWrongDeviceState;
342 } 379 }
343 380
344 // Save data before unloading the amiibo 381 // Save data before unloading the amiibo
@@ -347,43 +384,123 @@ Result NfpDevice::Unmount() {
347 } 384 }
348 385
349 device_state = DeviceState::TagFound; 386 device_state = DeviceState::TagFound;
350 mount_target = MountTarget::None; 387 mount_target = NFP::MountTarget::None;
351 is_app_area_open = false; 388 is_app_area_open = false;
352 389
353 return ResultSuccess; 390 return ResultSuccess;
354} 391}
355 392
356Result NfpDevice::GetTagInfo(TagInfo& tag_info) const { 393Result NfcDevice::Flush() {
357 if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { 394 if (device_state != DeviceState::TagMounted) {
358 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 395 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
359 if (device_state == DeviceState::TagRemoved) { 396 if (device_state == DeviceState::TagRemoved) {
360 return TagRemoved; 397 return ResultTagRemoved;
361 } 398 }
362 return WrongDeviceState; 399 return ResultWrongDeviceState;
363 } 400 }
364 401
365 tag_info = { 402 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
366 .uuid = encrypted_tag_data.uuid.uid, 403 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
367 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()), 404 return ResultWrongDeviceState;
368 .protocol = TagProtocol::TypeA, 405 }
369 .tag_type = TagType::Type2, 406
370 }; 407 auto& settings = tag_data.settings;
408
409 const auto& current_date = GetAmiiboDate(current_posix_time);
410 if (settings.write_date.raw_date != current_date.raw_date) {
411 settings.write_date = current_date;
412 UpdateSettingsCrc();
413 }
414
415 tag_data.write_counter++;
416
417 FlushWithBreak(NFP::BreakType::Normal);
418
419 is_data_moddified = false;
371 420
372 return ResultSuccess; 421 return ResultSuccess;
373} 422}
374 423
375Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const { 424Result NfcDevice::FlushDebug() {
425 if (device_state != DeviceState::TagMounted) {
426 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
427 if (device_state == DeviceState::TagRemoved) {
428 return ResultTagRemoved;
429 }
430 return ResultWrongDeviceState;
431 }
432
433 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
434 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
435 return ResultWrongDeviceState;
436 }
437
438 tag_data.write_counter++;
439
440 FlushWithBreak(NFP::BreakType::Normal);
441
442 is_data_moddified = false;
443
444 return ResultSuccess;
445}
446
447Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) {
448 if (break_type != NFP::BreakType::Normal) {
449 LOG_ERROR(Service_NFC, "Break type not implemented {}", break_type);
450 return ResultWrongDeviceState;
451 }
452
453 std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File));
454 if (is_plain_amiibo) {
455 memcpy(data.data(), &tag_data, sizeof(tag_data));
456 } else {
457 if (!NFP::AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) {
458 LOG_ERROR(Service_NFP, "Failed to encode data");
459 return ResultWriteAmiiboFailed;
460 }
461
462 memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
463 }
464
465 if (!npad_device->WriteNfc(data)) {
466 LOG_ERROR(Service_NFP, "Error writing to file");
467 return ResultWriteAmiiboFailed;
468 }
469
470 return ResultSuccess;
471}
472
473Result NfcDevice::Restore() {
474 if (device_state != DeviceState::TagMounted) {
475 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
476 if (device_state == DeviceState::TagRemoved) {
477 return ResultTagRemoved;
478 }
479 return ResultWrongDeviceState;
480 }
481
482 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
483 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
484 return ResultWrongDeviceState;
485 }
486
487 // TODO: Load amiibo from backup on system
488 LOG_ERROR(Service_NFP, "Not Implemented");
489 return ResultSuccess;
490}
491
492Result NfcDevice::GetCommonInfo(NFP::CommonInfo& common_info) const {
376 if (device_state != DeviceState::TagMounted) { 493 if (device_state != DeviceState::TagMounted) {
377 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 494 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
378 if (device_state == DeviceState::TagRemoved) { 495 if (device_state == DeviceState::TagRemoved) {
379 return TagRemoved; 496 return ResultTagRemoved;
380 } 497 }
381 return WrongDeviceState; 498 return ResultWrongDeviceState;
382 } 499 }
383 500
384 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 501 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
385 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 502 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
386 return WrongDeviceState; 503 return ResultWrongDeviceState;
387 } 504 }
388 505
389 const auto& settings = tag_data.settings; 506 const auto& settings = tag_data.settings;
@@ -393,18 +510,18 @@ Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const {
393 .last_write_date = settings.write_date.GetWriteDate(), 510 .last_write_date = settings.write_date.GetWriteDate(),
394 .write_counter = tag_data.write_counter, 511 .write_counter = tag_data.write_counter,
395 .version = tag_data.amiibo_version, 512 .version = tag_data.amiibo_version,
396 .application_area_size = sizeof(ApplicationArea), 513 .application_area_size = sizeof(NFP::ApplicationArea),
397 }; 514 };
398 return ResultSuccess; 515 return ResultSuccess;
399} 516}
400 517
401Result NfpDevice::GetModelInfo(ModelInfo& model_info) const { 518Result NfcDevice::GetModelInfo(NFP::ModelInfo& model_info) const {
402 if (device_state != DeviceState::TagMounted) { 519 if (device_state != DeviceState::TagMounted) {
403 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 520 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
404 if (device_state == DeviceState::TagRemoved) { 521 if (device_state == DeviceState::TagRemoved) {
405 return TagRemoved; 522 return ResultTagRemoved;
406 } 523 }
407 return WrongDeviceState; 524 return ResultWrongDeviceState;
408 } 525 }
409 526
410 const auto& model_info_data = encrypted_tag_data.user_memory.model_info; 527 const auto& model_info_data = encrypted_tag_data.user_memory.model_info;
@@ -418,22 +535,22 @@ Result NfpDevice::GetModelInfo(ModelInfo& model_info) const {
418 return ResultSuccess; 535 return ResultSuccess;
419} 536}
420 537
421Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const { 538Result NfcDevice::GetRegisterInfo(NFP::RegisterInfo& register_info) const {
422 if (device_state != DeviceState::TagMounted) { 539 if (device_state != DeviceState::TagMounted) {
423 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 540 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
424 if (device_state == DeviceState::TagRemoved) { 541 if (device_state == DeviceState::TagRemoved) {
425 return TagRemoved; 542 return ResultTagRemoved;
426 } 543 }
427 return WrongDeviceState; 544 return ResultWrongDeviceState;
428 } 545 }
429 546
430 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 547 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
431 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 548 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
432 return WrongDeviceState; 549 return ResultWrongDeviceState;
433 } 550 }
434 551
435 if (tag_data.settings.settings.amiibo_initialized == 0) { 552 if (tag_data.settings.settings.amiibo_initialized == 0) {
436 return RegistrationIsNotInitialized; 553 return ResultRegistrationIsNotInitialized;
437 } 554 }
438 555
439 Service::Mii::MiiManager manager; 556 Service::Mii::MiiManager manager;
@@ -450,22 +567,22 @@ Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const {
450 return ResultSuccess; 567 return ResultSuccess;
451} 568}
452 569
453Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const { 570Result NfcDevice::GetRegisterInfoPrivate(NFP::RegisterInfoPrivate& register_info) const {
454 if (device_state != DeviceState::TagMounted) { 571 if (device_state != DeviceState::TagMounted) {
455 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 572 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
456 if (device_state == DeviceState::TagRemoved) { 573 if (device_state == DeviceState::TagRemoved) {
457 return TagRemoved; 574 return ResultTagRemoved;
458 } 575 }
459 return WrongDeviceState; 576 return ResultWrongDeviceState;
460 } 577 }
461 578
462 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 579 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
463 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 580 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
464 return WrongDeviceState; 581 return ResultWrongDeviceState;
465 } 582 }
466 583
467 if (tag_data.settings.settings.amiibo_initialized == 0) { 584 if (tag_data.settings.settings.amiibo_initialized == 0) {
468 return RegistrationIsNotInitialized; 585 return ResultRegistrationIsNotInitialized;
469 } 586 }
470 587
471 Service::Mii::MiiManager manager; 588 Service::Mii::MiiManager manager;
@@ -482,18 +599,18 @@ Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) con
482 return ResultSuccess; 599 return ResultSuccess;
483} 600}
484 601
485Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const { 602Result NfcDevice::GetAdminInfo(NFP::AdminInfo& admin_info) const {
486 if (device_state != DeviceState::TagMounted) { 603 if (device_state != DeviceState::TagMounted) {
487 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 604 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
488 if (device_state == DeviceState::TagRemoved) { 605 if (device_state == DeviceState::TagRemoved) {
489 return TagRemoved; 606 return ResultTagRemoved;
490 } 607 }
491 return WrongDeviceState; 608 return ResultWrongDeviceState;
492 } 609 }
493 610
494 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 611 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
495 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 612 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
496 return WrongDeviceState; 613 return ResultWrongDeviceState;
497 } 614 }
498 615
499 u8 flags = static_cast<u8>(tag_data.settings.settings.raw >> 0x4); 616 u8 flags = static_cast<u8>(tag_data.settings.settings.raw >> 0x4);
@@ -503,17 +620,18 @@ Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const {
503 620
504 u64 application_id = 0; 621 u64 application_id = 0;
505 u32 application_area_id = 0; 622 u32 application_area_id = 0;
506 AppAreaVersion app_area_version = AppAreaVersion::NotSet; 623 NFP::AppAreaVersion app_area_version = NFP::AppAreaVersion::NotSet;
507 if (tag_data.settings.settings.appdata_initialized != 0) { 624 if (tag_data.settings.settings.appdata_initialized != 0) {
508 application_id = tag_data.application_id; 625 application_id = tag_data.application_id;
509 app_area_version = 626 app_area_version = static_cast<NFP::AppAreaVersion>(
510 static_cast<AppAreaVersion>(application_id >> application_id_version_offset & 0xf); 627 application_id >> NFP::application_id_version_offset & 0xf);
511 628
512 // Restore application id to original value 629 // Restore application id to original value
513 if (application_id >> 0x38 != 0) { 630 if (application_id >> 0x38 != 0) {
514 const u8 application_byte = tag_data.application_id_byte & 0xf; 631 const u8 application_byte = tag_data.application_id_byte & 0xf;
515 application_id = RemoveVersionByte(application_id) | 632 application_id =
516 (static_cast<u64>(application_byte) << application_id_version_offset); 633 RemoveVersionByte(application_id) |
634 (static_cast<u64>(application_byte) << NFP::application_id_version_offset);
517 } 635 }
518 636
519 application_area_id = tag_data.application_area_id; 637 application_area_id = tag_data.application_area_id;
@@ -532,22 +650,22 @@ Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const {
532 return ResultSuccess; 650 return ResultSuccess;
533} 651}
534 652
535Result NfpDevice::DeleteRegisterInfo() { 653Result NfcDevice::DeleteRegisterInfo() {
536 if (device_state != DeviceState::TagMounted) { 654 if (device_state != DeviceState::TagMounted) {
537 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 655 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
538 if (device_state == DeviceState::TagRemoved) { 656 if (device_state == DeviceState::TagRemoved) {
539 return TagRemoved; 657 return ResultTagRemoved;
540 } 658 }
541 return WrongDeviceState; 659 return ResultWrongDeviceState;
542 } 660 }
543 661
544 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 662 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
545 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 663 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
546 return WrongDeviceState; 664 return ResultWrongDeviceState;
547 } 665 }
548 666
549 if (tag_data.settings.settings.amiibo_initialized == 0) { 667 if (tag_data.settings.settings.amiibo_initialized == 0) {
550 return RegistrationIsNotInitialized; 668 return ResultRegistrationIsNotInitialized;
551 } 669 }
552 670
553 Common::TinyMT rng{}; 671 Common::TinyMT rng{};
@@ -564,18 +682,18 @@ Result NfpDevice::DeleteRegisterInfo() {
564 return Flush(); 682 return Flush();
565} 683}
566 684
567Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { 685Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info) {
568 if (device_state != DeviceState::TagMounted) { 686 if (device_state != DeviceState::TagMounted) {
569 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 687 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
570 if (device_state == DeviceState::TagRemoved) { 688 if (device_state == DeviceState::TagRemoved) {
571 return TagRemoved; 689 return ResultTagRemoved;
572 } 690 }
573 return WrongDeviceState; 691 return ResultWrongDeviceState;
574 } 692 }
575 693
576 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 694 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
577 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 695 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
578 return WrongDeviceState; 696 return ResultWrongDeviceState;
579 } 697 }
580 698
581 Service::Mii::MiiManager manager; 699 Service::Mii::MiiManager manager;
@@ -587,7 +705,7 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) {
587 settings.write_date.raw_date = 0; 705 settings.write_date.raw_date = 0;
588 } 706 }
589 707
590 SetAmiiboName(settings, amiibo_name); 708 SetAmiiboName(settings, register_info.amiibo_name);
591 tag_data.owner_mii = manager.BuildFromStoreData(mii); 709 tag_data.owner_mii = manager.BuildFromStoreData(mii);
592 tag_data.mii_extension = manager.SetFromStoreData(mii); 710 tag_data.mii_extension = manager.SetFromStoreData(mii);
593 tag_data.unknown = 0; 711 tag_data.unknown = 0;
@@ -601,18 +719,18 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) {
601 return Flush(); 719 return Flush();
602} 720}
603 721
604Result NfpDevice::RestoreAmiibo() { 722Result NfcDevice::RestoreAmiibo() {
605 if (device_state != DeviceState::TagMounted) { 723 if (device_state != DeviceState::TagMounted) {
606 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 724 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
607 if (device_state == DeviceState::TagRemoved) { 725 if (device_state == DeviceState::TagRemoved) {
608 return TagRemoved; 726 return ResultTagRemoved;
609 } 727 }
610 return WrongDeviceState; 728 return ResultWrongDeviceState;
611 } 729 }
612 730
613 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 731 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
614 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 732 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
615 return WrongDeviceState; 733 return ResultWrongDeviceState;
616 } 734 }
617 735
618 // TODO: Load amiibo from backup on system 736 // TODO: Load amiibo from backup on system
@@ -620,7 +738,7 @@ Result NfpDevice::RestoreAmiibo() {
620 return ResultSuccess; 738 return ResultSuccess;
621} 739}
622 740
623Result NfpDevice::Format() { 741Result NfcDevice::Format() {
624 auto result1 = DeleteApplicationArea(); 742 auto result1 = DeleteApplicationArea();
625 auto result2 = DeleteRegisterInfo(); 743 auto result2 = DeleteRegisterInfo();
626 744
@@ -635,28 +753,28 @@ Result NfpDevice::Format() {
635 return Flush(); 753 return Flush();
636} 754}
637 755
638Result NfpDevice::OpenApplicationArea(u32 access_id) { 756Result NfcDevice::OpenApplicationArea(u32 access_id) {
639 if (device_state != DeviceState::TagMounted) { 757 if (device_state != DeviceState::TagMounted) {
640 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 758 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
641 if (device_state == DeviceState::TagRemoved) { 759 if (device_state == DeviceState::TagRemoved) {
642 return TagRemoved; 760 return ResultTagRemoved;
643 } 761 }
644 return WrongDeviceState; 762 return ResultWrongDeviceState;
645 } 763 }
646 764
647 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 765 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
648 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 766 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
649 return WrongDeviceState; 767 return ResultWrongDeviceState;
650 } 768 }
651 769
652 if (tag_data.settings.settings.appdata_initialized.Value() == 0) { 770 if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
653 LOG_WARNING(Service_NFP, "Application area is not initialized"); 771 LOG_WARNING(Service_NFP, "Application area is not initialized");
654 return ApplicationAreaIsNotInitialized; 772 return ResultApplicationAreaIsNotInitialized;
655 } 773 }
656 774
657 if (tag_data.application_area_id != access_id) { 775 if (tag_data.application_area_id != access_id) {
658 LOG_WARNING(Service_NFP, "Wrong application area id"); 776 LOG_WARNING(Service_NFP, "Wrong application area id");
659 return WrongApplicationAreaId; 777 return ResultWrongApplicationAreaId;
660 } 778 }
661 779
662 is_app_area_open = true; 780 is_app_area_open = true;
@@ -664,25 +782,25 @@ Result NfpDevice::OpenApplicationArea(u32 access_id) {
664 return ResultSuccess; 782 return ResultSuccess;
665} 783}
666 784
667Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { 785Result NfcDevice::GetApplicationAreaId(u32& application_area_id) const {
668 application_area_id = {}; 786 application_area_id = {};
669 787
670 if (device_state != DeviceState::TagMounted) { 788 if (device_state != DeviceState::TagMounted) {
671 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 789 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
672 if (device_state == DeviceState::TagRemoved) { 790 if (device_state == DeviceState::TagRemoved) {
673 return TagRemoved; 791 return ResultTagRemoved;
674 } 792 }
675 return WrongDeviceState; 793 return ResultWrongDeviceState;
676 } 794 }
677 795
678 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 796 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
679 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 797 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
680 return WrongDeviceState; 798 return ResultWrongDeviceState;
681 } 799 }
682 800
683 if (tag_data.settings.settings.appdata_initialized.Value() == 0) { 801 if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
684 LOG_WARNING(Service_NFP, "Application area is not initialized"); 802 LOG_WARNING(Service_NFP, "Application area is not initialized");
685 return ApplicationAreaIsNotInitialized; 803 return ResultApplicationAreaIsNotInitialized;
686 } 804 }
687 805
688 application_area_id = tag_data.application_area_id; 806 application_area_id = tag_data.application_area_id;
@@ -690,64 +808,61 @@ Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const {
690 return ResultSuccess; 808 return ResultSuccess;
691} 809}
692 810
693Result NfpDevice::GetApplicationArea(std::vector<u8>& data) const { 811Result NfcDevice::GetApplicationArea(std::span<u8> data) const {
694 if (device_state != DeviceState::TagMounted) { 812 if (device_state != DeviceState::TagMounted) {
695 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 813 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
696 if (device_state == DeviceState::TagRemoved) { 814 if (device_state == DeviceState::TagRemoved) {
697 return TagRemoved; 815 return ResultTagRemoved;
698 } 816 }
699 return WrongDeviceState; 817 return ResultWrongDeviceState;
700 } 818 }
701 819
702 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 820 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
703 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 821 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
704 return WrongDeviceState; 822 return ResultWrongDeviceState;
705 } 823 }
706 824
707 if (!is_app_area_open) { 825 if (!is_app_area_open) {
708 LOG_ERROR(Service_NFP, "Application area is not open"); 826 LOG_ERROR(Service_NFP, "Application area is not open");
709 return WrongDeviceState; 827 return ResultWrongDeviceState;
710 } 828 }
711 829
712 if (tag_data.settings.settings.appdata_initialized.Value() == 0) { 830 if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
713 LOG_ERROR(Service_NFP, "Application area is not initialized"); 831 LOG_ERROR(Service_NFP, "Application area is not initialized");
714 return ApplicationAreaIsNotInitialized; 832 return ResultApplicationAreaIsNotInitialized;
715 }
716
717 if (data.size() > sizeof(ApplicationArea)) {
718 data.resize(sizeof(ApplicationArea));
719 } 833 }
720 834
721 memcpy(data.data(), tag_data.application_area.data(), data.size()); 835 memcpy(data.data(), tag_data.application_area.data(),
836 std::min(data.size(), sizeof(NFP::ApplicationArea)));
722 837
723 return ResultSuccess; 838 return ResultSuccess;
724} 839}
725 840
726Result NfpDevice::SetApplicationArea(std::span<const u8> data) { 841Result NfcDevice::SetApplicationArea(std::span<const u8> data) {
727 if (device_state != DeviceState::TagMounted) { 842 if (device_state != DeviceState::TagMounted) {
728 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 843 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
729 if (device_state == DeviceState::TagRemoved) { 844 if (device_state == DeviceState::TagRemoved) {
730 return TagRemoved; 845 return ResultTagRemoved;
731 } 846 }
732 return WrongDeviceState; 847 return ResultWrongDeviceState;
733 } 848 }
734 849
735 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 850 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
736 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 851 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
737 return WrongDeviceState; 852 return ResultWrongDeviceState;
738 } 853 }
739 854
740 if (!is_app_area_open) { 855 if (!is_app_area_open) {
741 LOG_ERROR(Service_NFP, "Application area is not open"); 856 LOG_ERROR(Service_NFP, "Application area is not open");
742 return WrongDeviceState; 857 return ResultWrongDeviceState;
743 } 858 }
744 859
745 if (tag_data.settings.settings.appdata_initialized.Value() == 0) { 860 if (tag_data.settings.settings.appdata_initialized.Value() == 0) {
746 LOG_ERROR(Service_NFP, "Application area is not initialized"); 861 LOG_ERROR(Service_NFP, "Application area is not initialized");
747 return ApplicationAreaIsNotInitialized; 862 return ResultApplicationAreaIsNotInitialized;
748 } 863 }
749 864
750 if (data.size() > sizeof(ApplicationArea)) { 865 if (data.size() > sizeof(NFP::ApplicationArea)) {
751 LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); 866 LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
752 return ResultUnknown; 867 return ResultUnknown;
753 } 868 }
@@ -756,9 +871,9 @@ Result NfpDevice::SetApplicationArea(std::span<const u8> data) {
756 std::memcpy(tag_data.application_area.data(), data.data(), data.size()); 871 std::memcpy(tag_data.application_area.data(), data.data(), data.size());
757 // Fill remaining data with random numbers 872 // Fill remaining data with random numbers
758 rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), 873 rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
759 sizeof(ApplicationArea) - data.size()); 874 sizeof(NFP::ApplicationArea) - data.size());
760 875
761 if (tag_data.application_write_counter != counter_limit) { 876 if (tag_data.application_write_counter != NFP::counter_limit) {
762 tag_data.application_write_counter++; 877 tag_data.application_write_counter++;
763 } 878 }
764 879
@@ -767,64 +882,64 @@ Result NfpDevice::SetApplicationArea(std::span<const u8> data) {
767 return ResultSuccess; 882 return ResultSuccess;
768} 883}
769 884
770Result NfpDevice::CreateApplicationArea(u32 access_id, std::span<const u8> data) { 885Result NfcDevice::CreateApplicationArea(u32 access_id, std::span<const u8> data) {
771 if (device_state != DeviceState::TagMounted) { 886 if (device_state != DeviceState::TagMounted) {
772 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 887 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
773 if (device_state == DeviceState::TagRemoved) { 888 if (device_state == DeviceState::TagRemoved) {
774 return TagRemoved; 889 return ResultTagRemoved;
775 } 890 }
776 return WrongDeviceState; 891 return ResultWrongDeviceState;
777 } 892 }
778 893
779 if (tag_data.settings.settings.appdata_initialized.Value() != 0) { 894 if (tag_data.settings.settings.appdata_initialized.Value() != 0) {
780 LOG_ERROR(Service_NFP, "Application area already exist"); 895 LOG_ERROR(Service_NFP, "Application area already exist");
781 return ApplicationAreaExist; 896 return ResultApplicationAreaExist;
782 } 897 }
783 898
784 return RecreateApplicationArea(access_id, data); 899 return RecreateApplicationArea(access_id, data);
785} 900}
786 901
787Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> data) { 902Result NfcDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> data) {
788 if (device_state != DeviceState::TagMounted) { 903 if (device_state != DeviceState::TagMounted) {
789 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 904 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
790 if (device_state == DeviceState::TagRemoved) { 905 if (device_state == DeviceState::TagRemoved) {
791 return TagRemoved; 906 return ResultTagRemoved;
792 } 907 }
793 return WrongDeviceState; 908 return ResultWrongDeviceState;
794 } 909 }
795 910
796 if (is_app_area_open) { 911 if (is_app_area_open) {
797 LOG_ERROR(Service_NFP, "Application area is open"); 912 LOG_ERROR(Service_NFP, "Application area is open");
798 return WrongDeviceState; 913 return ResultWrongDeviceState;
799 } 914 }
800 915
801 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 916 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
802 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 917 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
803 return WrongDeviceState; 918 return ResultWrongDeviceState;
804 } 919 }
805 920
806 if (data.size() > sizeof(ApplicationArea)) { 921 if (data.size() > sizeof(NFP::ApplicationArea)) {
807 LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); 922 LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
808 return WrongApplicationAreaSize; 923 return ResultWrongApplicationAreaSize;
809 } 924 }
810 925
811 Common::TinyMT rng{}; 926 Common::TinyMT rng{};
812 std::memcpy(tag_data.application_area.data(), data.data(), data.size()); 927 std::memcpy(tag_data.application_area.data(), data.data(), data.size());
813 // Fill remaining data with random numbers 928 // Fill remaining data with random numbers
814 rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), 929 rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
815 sizeof(ApplicationArea) - data.size()); 930 sizeof(NFP::ApplicationArea) - data.size());
816 931
817 if (tag_data.application_write_counter != counter_limit) { 932 if (tag_data.application_write_counter != NFP::counter_limit) {
818 tag_data.application_write_counter++; 933 tag_data.application_write_counter++;
819 } 934 }
820 935
821 const u64 application_id = system.GetApplicationProcessProgramID(); 936 const u64 application_id = system.GetApplicationProcessProgramID();
822 937
823 tag_data.application_id_byte = 938 tag_data.application_id_byte =
824 static_cast<u8>(application_id >> application_id_version_offset & 0xf); 939 static_cast<u8>(application_id >> NFP::application_id_version_offset & 0xf);
825 tag_data.application_id = 940 tag_data.application_id =
826 RemoveVersionByte(application_id) | 941 RemoveVersionByte(application_id) | (static_cast<u64>(NFP::AppAreaVersion::NintendoSwitch)
827 (static_cast<u64>(AppAreaVersion::NintendoSwitch) << application_id_version_offset); 942 << NFP::application_id_version_offset);
828 tag_data.settings.settings.appdata_initialized.Assign(1); 943 tag_data.settings.settings.appdata_initialized.Assign(1);
829 tag_data.application_area_id = access_id; 944 tag_data.application_area_id = access_id;
830 tag_data.unknown = {}; 945 tag_data.unknown = {};
@@ -835,30 +950,30 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat
835 return Flush(); 950 return Flush();
836} 951}
837 952
838Result NfpDevice::DeleteApplicationArea() { 953Result NfcDevice::DeleteApplicationArea() {
839 if (device_state != DeviceState::TagMounted) { 954 if (device_state != DeviceState::TagMounted) {
840 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 955 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
841 if (device_state == DeviceState::TagRemoved) { 956 if (device_state == DeviceState::TagRemoved) {
842 return TagRemoved; 957 return ResultTagRemoved;
843 } 958 }
844 return WrongDeviceState; 959 return ResultWrongDeviceState;
845 } 960 }
846 961
847 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 962 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
848 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 963 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
849 return WrongDeviceState; 964 return ResultWrongDeviceState;
850 } 965 }
851 966
852 if (tag_data.settings.settings.appdata_initialized == 0) { 967 if (tag_data.settings.settings.appdata_initialized == 0) {
853 return ApplicationAreaIsNotInitialized; 968 return ResultApplicationAreaIsNotInitialized;
854 } 969 }
855 970
856 if (tag_data.application_write_counter != counter_limit) { 971 if (tag_data.application_write_counter != NFP::counter_limit) {
857 tag_data.application_write_counter++; 972 tag_data.application_write_counter++;
858 } 973 }
859 974
860 Common::TinyMT rng{}; 975 Common::TinyMT rng{};
861 rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(ApplicationArea)); 976 rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(NFP::ApplicationArea));
862 rng.GenerateRandomBytes(&tag_data.application_id, sizeof(u64)); 977 rng.GenerateRandomBytes(&tag_data.application_id, sizeof(u64));
863 rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32)); 978 rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32));
864 rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8)); 979 rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8));
@@ -872,18 +987,18 @@ Result NfpDevice::DeleteApplicationArea() {
872 return Flush(); 987 return Flush();
873} 988}
874 989
875Result NfpDevice::ExistApplicationArea(bool& has_application_area) { 990Result NfcDevice::ExistsApplicationArea(bool& has_application_area) const {
876 if (device_state != DeviceState::TagMounted) { 991 if (device_state != DeviceState::TagMounted) {
877 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 992 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
878 if (device_state == DeviceState::TagRemoved) { 993 if (device_state == DeviceState::TagRemoved) {
879 return TagRemoved; 994 return ResultTagRemoved;
880 } 995 }
881 return WrongDeviceState; 996 return ResultWrongDeviceState;
882 } 997 }
883 998
884 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 999 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
885 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 1000 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
886 return WrongDeviceState; 1001 return ResultWrongDeviceState;
887 } 1002 }
888 1003
889 has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0; 1004 has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0;
@@ -891,21 +1006,21 @@ Result NfpDevice::ExistApplicationArea(bool& has_application_area) {
891 return ResultSuccess; 1006 return ResultSuccess;
892} 1007}
893 1008
894Result NfpDevice::GetAll(NfpData& data) const { 1009Result NfcDevice::GetAll(NFP::NfpData& data) const {
895 if (device_state != DeviceState::TagMounted) { 1010 if (device_state != DeviceState::TagMounted) {
896 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 1011 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
897 if (device_state == DeviceState::TagRemoved) { 1012 if (device_state == DeviceState::TagRemoved) {
898 return TagRemoved; 1013 return ResultTagRemoved;
899 } 1014 }
900 return WrongDeviceState; 1015 return ResultWrongDeviceState;
901 } 1016 }
902 1017
903 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 1018 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
904 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 1019 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
905 return WrongDeviceState; 1020 return ResultWrongDeviceState;
906 } 1021 }
907 1022
908 CommonInfo common_info{}; 1023 NFP::CommonInfo common_info{};
909 Service::Mii::MiiManager manager; 1024 Service::Mii::MiiManager manager;
910 const u64 application_id = tag_data.application_id; 1025 const u64 application_id = tag_data.application_id;
911 1026
@@ -930,8 +1045,8 @@ Result NfpDevice::GetAll(NfpData& data) const {
930 .settings_crc_counter = tag_data.settings.crc_counter, 1045 .settings_crc_counter = tag_data.settings.crc_counter,
931 .font_region = tag_data.settings.settings.font_region, 1046 .font_region = tag_data.settings.settings.font_region,
932 .tag_type = PackedTagType::Type2, 1047 .tag_type = PackedTagType::Type2,
933 .console_type = 1048 .console_type = static_cast<NFP::AppAreaVersion>(
934 static_cast<AppAreaVersion>(application_id >> application_id_version_offset & 0xf), 1049 application_id >> NFP::application_id_version_offset & 0xf),
935 .application_id_byte = tag_data.application_id_byte, 1050 .application_id_byte = tag_data.application_id_byte,
936 .application_area = tag_data.application_area, 1051 .application_area = tag_data.application_area,
937 }; 1052 };
@@ -939,18 +1054,18 @@ Result NfpDevice::GetAll(NfpData& data) const {
939 return ResultSuccess; 1054 return ResultSuccess;
940} 1055}
941 1056
942Result NfpDevice::SetAll(const NfpData& data) { 1057Result NfcDevice::SetAll(const NFP::NfpData& data) {
943 if (device_state != DeviceState::TagMounted) { 1058 if (device_state != DeviceState::TagMounted) {
944 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 1059 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
945 if (device_state == DeviceState::TagRemoved) { 1060 if (device_state == DeviceState::TagRemoved) {
946 return TagRemoved; 1061 return ResultTagRemoved;
947 } 1062 }
948 return WrongDeviceState; 1063 return ResultWrongDeviceState;
949 } 1064 }
950 1065
951 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 1066 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
952 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 1067 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
953 return WrongDeviceState; 1068 return ResultWrongDeviceState;
954 } 1069 }
955 1070
956 tag_data.constant_value = data.magic; 1071 tag_data.constant_value = data.magic;
@@ -977,18 +1092,18 @@ Result NfpDevice::SetAll(const NfpData& data) {
977 return ResultSuccess; 1092 return ResultSuccess;
978} 1093}
979 1094
980Result NfpDevice::BreakTag(BreakType break_type) { 1095Result NfcDevice::BreakTag(NFP::BreakType break_type) {
981 if (device_state != DeviceState::TagMounted) { 1096 if (device_state != DeviceState::TagMounted) {
982 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 1097 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
983 if (device_state == DeviceState::TagRemoved) { 1098 if (device_state == DeviceState::TagRemoved) {
984 return TagRemoved; 1099 return ResultTagRemoved;
985 } 1100 }
986 return WrongDeviceState; 1101 return ResultWrongDeviceState;
987 } 1102 }
988 1103
989 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 1104 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
990 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 1105 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
991 return WrongDeviceState; 1106 return ResultWrongDeviceState;
992 } 1107 }
993 1108
994 // TODO: Complete this implementation 1109 // TODO: Complete this implementation
@@ -996,28 +1111,28 @@ Result NfpDevice::BreakTag(BreakType break_type) {
996 return FlushWithBreak(break_type); 1111 return FlushWithBreak(break_type);
997} 1112}
998 1113
999Result NfpDevice::ReadBackupData() { 1114Result NfcDevice::ReadBackupData(std::span<u8> data) const {
1000 // Not implemented 1115 // Not implemented
1001 return ResultSuccess; 1116 return ResultSuccess;
1002} 1117}
1003 1118
1004Result NfpDevice::WriteBackupData() { 1119Result NfcDevice::WriteBackupData(std::span<const u8> data) {
1005 // Not implemented 1120 // Not implemented
1006 return ResultSuccess; 1121 return ResultSuccess;
1007} 1122}
1008 1123
1009Result NfpDevice::WriteNtf() { 1124Result NfcDevice::WriteNtf(std::span<const u8> data) {
1010 if (device_state != DeviceState::TagMounted) { 1125 if (device_state != DeviceState::TagMounted) {
1011 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 1126 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
1012 if (device_state == DeviceState::TagRemoved) { 1127 if (device_state == DeviceState::TagRemoved) {
1013 return TagRemoved; 1128 return ResultTagRemoved;
1014 } 1129 }
1015 return WrongDeviceState; 1130 return ResultWrongDeviceState;
1016 } 1131 }
1017 1132
1018 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 1133 if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
1019 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); 1134 LOG_ERROR(Service_NFC, "Amiibo is read only", device_state);
1020 return WrongDeviceState; 1135 return ResultWrongDeviceState;
1021 } 1136 }
1022 1137
1023 // Not implemented 1138 // Not implemented
@@ -1025,29 +1140,12 @@ Result NfpDevice::WriteNtf() {
1025 return ResultSuccess; 1140 return ResultSuccess;
1026} 1141}
1027 1142
1028u64 NfpDevice::GetHandle() const { 1143NFP::AmiiboName NfcDevice::GetAmiiboName(const NFP::AmiiboSettings& settings) const {
1029 // Generate a handle based of the npad id 1144 std::array<char16_t, NFP::amiibo_name_length> settings_amiibo_name{};
1030 return static_cast<u64>(npad_id); 1145 NFP::AmiiboName amiibo_name{};
1031}
1032
1033u32 NfpDevice::GetApplicationAreaSize() const {
1034 return sizeof(ApplicationArea);
1035}
1036
1037DeviceState NfpDevice::GetCurrentState() const {
1038 return device_state;
1039}
1040
1041Core::HID::NpadIdType NfpDevice::GetNpadId() const {
1042 return npad_id;
1043}
1044
1045AmiiboName NfpDevice::GetAmiiboName(const AmiiboSettings& settings) const {
1046 std::array<char16_t, amiibo_name_length> settings_amiibo_name{};
1047 AmiiboName amiibo_name{};
1048 1146
1049 // Convert from big endian to little endian 1147 // Convert from big endian to little endian
1050 for (std::size_t i = 0; i < amiibo_name_length; i++) { 1148 for (std::size_t i = 0; i < NFP::amiibo_name_length; i++) {
1051 settings_amiibo_name[i] = static_cast<u16>(settings.amiibo_name[i]); 1149 settings_amiibo_name[i] = static_cast<u16>(settings.amiibo_name[i]);
1052 } 1150 }
1053 1151
@@ -1058,8 +1156,8 @@ AmiiboName NfpDevice::GetAmiiboName(const AmiiboSettings& settings) const {
1058 return amiibo_name; 1156 return amiibo_name;
1059} 1157}
1060 1158
1061void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name) { 1159void NfcDevice::SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name) {
1062 std::array<char16_t, amiibo_name_length> settings_amiibo_name{}; 1160 std::array<char16_t, NFP::amiibo_name_length> settings_amiibo_name{};
1063 1161
1064 // Convert from utf8 to utf16 1162 // Convert from utf8 to utf16
1065 const auto amiibo_name_utf16 = Common::UTF8ToUTF16(amiibo_name.data()); 1163 const auto amiibo_name_utf16 = Common::UTF8ToUTF16(amiibo_name.data());
@@ -1067,16 +1165,16 @@ void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo
1067 amiibo_name_utf16.size() * sizeof(char16_t)); 1165 amiibo_name_utf16.size() * sizeof(char16_t));
1068 1166
1069 // Convert from little endian to big endian 1167 // Convert from little endian to big endian
1070 for (std::size_t i = 0; i < amiibo_name_length; i++) { 1168 for (std::size_t i = 0; i < NFP::amiibo_name_length; i++) {
1071 settings.amiibo_name[i] = static_cast<u16_be>(settings_amiibo_name[i]); 1169 settings.amiibo_name[i] = static_cast<u16_be>(settings_amiibo_name[i]);
1072 } 1170 }
1073} 1171}
1074 1172
1075AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const { 1173NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
1076 const auto& time_zone_manager = 1174 const auto& time_zone_manager =
1077 system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager(); 1175 system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager();
1078 Time::TimeZone::CalendarInfo calendar_info{}; 1176 Time::TimeZone::CalendarInfo calendar_info{};
1079 AmiiboDate amiibo_date{}; 1177 NFP::AmiiboDate amiibo_date{};
1080 1178
1081 amiibo_date.SetYear(2000); 1179 amiibo_date.SetYear(2000);
1082 amiibo_date.SetMonth(1); 1180 amiibo_date.SetMonth(1);
@@ -1091,14 +1189,14 @@ AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const {
1091 return amiibo_date; 1189 return amiibo_date;
1092} 1190}
1093 1191
1094u64 NfpDevice::RemoveVersionByte(u64 application_id) const { 1192u64 NfcDevice::RemoveVersionByte(u64 application_id) const {
1095 return application_id & ~(0xfULL << application_id_version_offset); 1193 return application_id & ~(0xfULL << NFP::application_id_version_offset);
1096} 1194}
1097 1195
1098void NfpDevice::UpdateSettingsCrc() { 1196void NfcDevice::UpdateSettingsCrc() {
1099 auto& settings = tag_data.settings; 1197 auto& settings = tag_data.settings;
1100 1198
1101 if (settings.crc_counter != counter_limit) { 1199 if (settings.crc_counter != NFP::counter_limit) {
1102 settings.crc_counter++; 1200 settings.crc_counter++;
1103 } 1201 }
1104 1202
@@ -1109,7 +1207,7 @@ void NfpDevice::UpdateSettingsCrc() {
1109 settings.crc = crc.checksum(); 1207 settings.crc = crc.checksum();
1110} 1208}
1111 1209
1112void NfpDevice::UpdateRegisterInfoCrc() { 1210void NfcDevice::UpdateRegisterInfoCrc() {
1113#pragma pack(push, 1) 1211#pragma pack(push, 1)
1114 struct CrcData { 1212 struct CrcData {
1115 Mii::Ver3StoreData mii; 1213 Mii::Ver3StoreData mii;
@@ -1134,4 +1232,18 @@ void NfpDevice::UpdateRegisterInfoCrc() {
1134 tag_data.register_info_crc = crc.checksum(); 1232 tag_data.register_info_crc = crc.checksum();
1135} 1233}
1136 1234
1137} // namespace Service::NFP 1235u64 NfcDevice::GetHandle() const {
1236 // Generate a handle based of the npad id
1237 return static_cast<u64>(npad_id);
1238}
1239
1240DeviceState NfcDevice::GetCurrentState() const {
1241 return device_state;
1242}
1243
1244Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const {
1245 out_npad_id = npad_id;
1246 return ResultSuccess;
1247}
1248
1249} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h
new file mode 100644
index 000000000..654eda98e
--- /dev/null
+++ b/src/core/hle/service/nfc/common/device.h
@@ -0,0 +1,138 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <span>
7
8#include "common/common_types.h"
9#include "core/hle/service/kernel_helpers.h"
10#include "core/hle/service/nfc/mifare_types.h"
11#include "core/hle/service/nfc/nfc_types.h"
12#include "core/hle/service/nfp/nfp_types.h"
13#include "core/hle/service/service.h"
14#include "core/hle/service/time/clock_types.h"
15
16namespace Kernel {
17class KEvent;
18class KReadableEvent;
19} // namespace Kernel
20
21namespace Core {
22class System;
23} // namespace Core
24
25namespace Core::HID {
26class EmulatedController;
27enum class ControllerTriggerType;
28enum class NpadIdType : u32;
29} // namespace Core::HID
30
31namespace Service::NFC {
32class NfcDevice {
33public:
34 NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
35 KernelHelpers::ServiceContext& service_context_,
36 Kernel::KEvent* availability_change_event_);
37 ~NfcDevice();
38
39 void Initialize();
40 void Finalize();
41
42 Result StartDetection(NfcProtocol allowed_protocol);
43 Result StopDetection();
44
45 Result GetTagInfo(TagInfo& tag_info, bool is_mifare) const;
46
47 Result ReadMifare(std::span<const MifareReadBlockParameter> parameters,
48 std::span<MifareReadBlockData> read_block_data) const;
49 Result ReadMifare(const MifareReadBlockParameter& parameter,
50 MifareReadBlockData& read_block_data) const;
51
52 Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters);
53 Result WriteMifare(const MifareWriteBlockParameter& parameter);
54
55 Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
56 std::span<const u8> command_data, std::span<u8> out_data);
57
58 Result Mount(NFP::ModelType model_type, NFP::MountTarget mount_target);
59 Result Unmount();
60
61 Result Flush();
62 Result FlushDebug();
63 Result FlushWithBreak(NFP::BreakType break_type);
64 Result Restore();
65
66 Result GetCommonInfo(NFP::CommonInfo& common_info) const;
67 Result GetModelInfo(NFP::ModelInfo& model_info) const;
68 Result GetRegisterInfo(NFP::RegisterInfo& register_info) const;
69 Result GetRegisterInfoPrivate(NFP::RegisterInfoPrivate& register_info) const;
70 Result GetAdminInfo(NFP::AdminInfo& admin_info) const;
71
72 Result DeleteRegisterInfo();
73 Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info);
74 Result RestoreAmiibo();
75 Result Format();
76
77 Result OpenApplicationArea(u32 access_id);
78 Result GetApplicationAreaId(u32& application_area_id) const;
79 Result GetApplicationArea(std::span<u8> data) const;
80 Result SetApplicationArea(std::span<const u8> data);
81 Result CreateApplicationArea(u32 access_id, std::span<const u8> data);
82 Result RecreateApplicationArea(u32 access_id, std::span<const u8> data);
83 Result DeleteApplicationArea();
84 Result ExistsApplicationArea(bool& has_application_area) const;
85
86 Result GetAll(NFP::NfpData& data) const;
87 Result SetAll(const NFP::NfpData& data);
88 Result BreakTag(NFP::BreakType break_type);
89 Result ReadBackupData(std::span<u8> data) const;
90 Result WriteBackupData(std::span<const u8> data);
91 Result WriteNtf(std::span<const u8> data);
92
93 u64 GetHandle() const;
94 DeviceState GetCurrentState() const;
95 Result GetNpadId(Core::HID::NpadIdType& out_npad_id) const;
96
97 Kernel::KReadableEvent& GetActivateEvent() const;
98 Kernel::KReadableEvent& GetDeactivateEvent() const;
99
100private:
101 void NpadUpdate(Core::HID::ControllerTriggerType type);
102 bool LoadNfcTag(std::span<const u8> data);
103 void CloseNfcTag();
104
105 NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const;
106 void SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name);
107 NFP::AmiiboDate GetAmiiboDate(s64 posix_time) const;
108 u64 RemoveVersionByte(u64 application_id) const;
109 void UpdateSettingsCrc();
110 void UpdateRegisterInfoCrc();
111
112 bool is_controller_set{};
113 int callback_key;
114 const Core::HID::NpadIdType npad_id;
115 Core::System& system;
116 Core::HID::EmulatedController* npad_device = nullptr;
117 KernelHelpers::ServiceContext& service_context;
118 Kernel::KEvent* activate_event = nullptr;
119 Kernel::KEvent* deactivate_event = nullptr;
120 Kernel::KEvent* availability_change_event = nullptr;
121
122 bool is_initalized{};
123 NfcProtocol allowed_protocols{};
124 DeviceState device_state{DeviceState::Unavailable};
125
126 // NFP data
127 bool is_data_moddified{};
128 bool is_app_area_open{};
129 bool is_plain_amiibo{};
130 s64 current_posix_time{};
131 NFP::MountTarget mount_target{NFP::MountTarget::None};
132
133 NFP::NTAG215File tag_data{};
134 std::vector<u8> mifare_data{};
135 NFP::EncryptedNTAG215File encrypted_tag_data{};
136};
137
138} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp
new file mode 100644
index 000000000..d5deaaf27
--- /dev/null
+++ b/src/core/hle/service/nfc/common/device_manager.cpp
@@ -0,0 +1,695 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "common/logging/log.h"
5#include "core/core.h"
6#include "core/hid/hid_types.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nfc/common/device.h"
10#include "core/hle/service/nfc/common/device_manager.h"
11#include "core/hle/service/nfc/nfc_result.h"
12#include "core/hle/service/time/clock_types.h"
13
14namespace Service::NFC {
15
16DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContext& service_context_)
17 : system{system_}, service_context{service_context_} {
18
19 availability_change_event =
20 service_context.CreateEvent("Nfc:DeviceManager:AvailabilityChangeEvent");
21
22 for (u32 device_index = 0; device_index < devices.size(); device_index++) {
23 devices[device_index] =
24 std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
25 service_context, availability_change_event);
26 }
27
28 is_initialized = false;
29}
30
31DeviceManager ::~DeviceManager() {
32 service_context.CloseEvent(availability_change_event);
33}
34
35Result DeviceManager::Initialize() {
36 for (auto& device : devices) {
37 device->Initialize();
38 }
39 is_initialized = true;
40 return ResultSuccess;
41}
42
43Result DeviceManager::Finalize() {
44 for (auto& device : devices) {
45 device->Finalize();
46 }
47 is_initialized = false;
48 return ResultSuccess;
49}
50
51Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices,
52 std::size_t max_allowed_devices) const {
53 for (auto& device : devices) {
54 if (nfp_devices.size() >= max_allowed_devices) {
55 continue;
56 }
57 if (device->GetCurrentState() != DeviceState::Unavailable) {
58 nfp_devices.push_back(device->GetHandle());
59 }
60 }
61
62 if (nfp_devices.empty()) {
63 return ResultDeviceNotFound;
64 }
65
66 return ResultSuccess;
67}
68
69DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
70 std::scoped_lock lock{mutex};
71
72 std::shared_ptr<NfcDevice> device = nullptr;
73 const auto result = GetDeviceFromHandle(device_handle, device, false);
74
75 if (result.IsSuccess()) {
76 return device->GetCurrentState();
77 }
78
79 return DeviceState::Unavailable;
80}
81
82Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const {
83 std::scoped_lock lock{mutex};
84
85 std::shared_ptr<NfcDevice> device = nullptr;
86 auto result = GetDeviceHandle(device_handle, device);
87
88 if (result.IsSuccess()) {
89 result = device->GetNpadId(npad_id);
90 result = VerifyDeviceResult(device, result);
91 }
92
93 return result;
94}
95
96Kernel::KReadableEvent& DeviceManager::AttachAvailabilityChangeEvent() const {
97 return availability_change_event->GetReadableEvent();
98}
99
100Result DeviceManager::StartDetection(u64 device_handle, NfcProtocol tag_protocol) {
101 std::scoped_lock lock{mutex};
102
103 std::shared_ptr<NfcDevice> device = nullptr;
104 auto result = GetDeviceHandle(device_handle, device);
105
106 if (result.IsSuccess()) {
107 result = device->StartDetection(tag_protocol);
108 result = VerifyDeviceResult(device, result);
109 }
110
111 return result;
112}
113
114Result DeviceManager::StopDetection(u64 device_handle) {
115 std::scoped_lock lock{mutex};
116
117 std::shared_ptr<NfcDevice> device = nullptr;
118 auto result = GetDeviceHandle(device_handle, device);
119
120 if (result.IsSuccess()) {
121 result = device->StopDetection();
122 result = VerifyDeviceResult(device, result);
123 }
124
125 return result;
126}
127
128Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info, bool is_mifare) const {
129 std::scoped_lock lock{mutex};
130
131 std::shared_ptr<NfcDevice> device = nullptr;
132 auto result = GetDeviceHandle(device_handle, device);
133
134 if (result.IsSuccess()) {
135 result = device->GetTagInfo(tag_info, is_mifare);
136 result = VerifyDeviceResult(device, result);
137 }
138
139 return result;
140}
141
142Kernel::KReadableEvent& DeviceManager::AttachActivateEvent(u64 device_handle) const {
143 std::scoped_lock lock{mutex};
144
145 std::shared_ptr<NfcDevice> device = nullptr;
146 GetDeviceFromHandle(device_handle, device, false);
147
148 // TODO: Return proper error code on failure
149 return device->GetActivateEvent();
150}
151
152Kernel::KReadableEvent& DeviceManager::AttachDeactivateEvent(u64 device_handle) const {
153 std::scoped_lock lock{mutex};
154
155 std::shared_ptr<NfcDevice> device = nullptr;
156 GetDeviceFromHandle(device_handle, device, false);
157
158 // TODO: Return proper error code on failure
159 return device->GetDeactivateEvent();
160}
161
162Result DeviceManager::ReadMifare(u64 device_handle,
163 std::span<const MifareReadBlockParameter> read_parameters,
164 std::span<MifareReadBlockData> read_data) {
165 std::scoped_lock lock{mutex};
166
167 std::shared_ptr<NfcDevice> device = nullptr;
168 auto result = GetDeviceHandle(device_handle, device);
169
170 if (result.IsSuccess()) {
171 result = device->ReadMifare(read_parameters, read_data);
172 result = VerifyDeviceResult(device, result);
173 }
174
175 return result;
176}
177
178Result DeviceManager::WriteMifare(u64 device_handle,
179 std::span<const MifareWriteBlockParameter> write_parameters) {
180 std::scoped_lock lock{mutex};
181
182 std::shared_ptr<NfcDevice> device = nullptr;
183 auto result = GetDeviceHandle(device_handle, device);
184
185 if (result.IsSuccess()) {
186 result = device->WriteMifare(write_parameters);
187 result = VerifyDeviceResult(device, result);
188 }
189
190 return result;
191}
192
193Result DeviceManager::SendCommandByPassThrough(u64 device_handle,
194 const Time::Clock::TimeSpanType& timeout,
195 std::span<const u8> command_data,
196 std::span<u8> out_data) {
197 std::scoped_lock lock{mutex};
198
199 std::shared_ptr<NfcDevice> device = nullptr;
200 auto result = GetDeviceHandle(device_handle, device);
201
202 if (result.IsSuccess()) {
203 result = device->SendCommandByPassThrough(timeout, command_data, out_data);
204 result = VerifyDeviceResult(device, result);
205 }
206
207 return result;
208}
209
210Result DeviceManager::Mount(u64 device_handle, NFP::ModelType model_type,
211 NFP::MountTarget mount_target) {
212 std::scoped_lock lock{mutex};
213
214 std::shared_ptr<NfcDevice> device = nullptr;
215 auto result = GetDeviceHandle(device_handle, device);
216
217 if (result.IsSuccess()) {
218 result = device->Mount(model_type, mount_target);
219 result = VerifyDeviceResult(device, result);
220 }
221
222 return result;
223}
224
225Result DeviceManager::Unmount(u64 device_handle) {
226 std::scoped_lock lock{mutex};
227
228 std::shared_ptr<NfcDevice> device = nullptr;
229 auto result = GetDeviceHandle(device_handle, device);
230
231 if (result.IsSuccess()) {
232 result = device->Unmount();
233 result = VerifyDeviceResult(device, result);
234 }
235
236 return result;
237}
238
239Result DeviceManager::OpenApplicationArea(u64 device_handle, u32 access_id) {
240 std::scoped_lock lock{mutex};
241
242 std::shared_ptr<NfcDevice> device = nullptr;
243 auto result = GetDeviceHandle(device_handle, device);
244
245 if (result.IsSuccess()) {
246 result = device->OpenApplicationArea(access_id);
247 result = VerifyDeviceResult(device, result);
248 }
249
250 return result;
251}
252
253Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) const {
254 std::scoped_lock lock{mutex};
255
256 std::shared_ptr<NfcDevice> device = nullptr;
257 auto result = GetDeviceHandle(device_handle, device);
258
259 if (result.IsSuccess()) {
260 result = device->GetApplicationArea(data);
261 result = VerifyDeviceResult(device, result);
262 }
263
264 return result;
265}
266
267Result DeviceManager::SetApplicationArea(u64 device_handle, std::span<const u8> data) {
268 std::scoped_lock lock{mutex};
269
270 std::shared_ptr<NfcDevice> device = nullptr;
271 auto result = GetDeviceHandle(device_handle, device);
272
273 if (result.IsSuccess()) {
274 result = device->SetApplicationArea(data);
275 result = VerifyDeviceResult(device, result);
276 }
277
278 return result;
279}
280
281Result DeviceManager::Flush(u64 device_handle) {
282 std::scoped_lock lock{mutex};
283
284 std::shared_ptr<NfcDevice> device = nullptr;
285 auto result = GetDeviceHandle(device_handle, device);
286
287 if (result.IsSuccess()) {
288 result = device->Flush();
289 result = VerifyDeviceResult(device, result);
290 }
291
292 return result;
293}
294
295Result DeviceManager::Restore(u64 device_handle) {
296 std::scoped_lock lock{mutex};
297
298 std::shared_ptr<NfcDevice> device = nullptr;
299 auto result = GetDeviceHandle(device_handle, device);
300
301 if (result.IsSuccess()) {
302 result = device->Restore();
303 result = VerifyDeviceResult(device, result);
304 }
305
306 return result;
307}
308
309Result DeviceManager::CreateApplicationArea(u64 device_handle, u32 access_id,
310 std::span<const u8> data) {
311 std::scoped_lock lock{mutex};
312
313 std::shared_ptr<NfcDevice> device = nullptr;
314 auto result = GetDeviceHandle(device_handle, device);
315
316 if (result.IsSuccess()) {
317 result = device->CreateApplicationArea(access_id, data);
318 result = VerifyDeviceResult(device, result);
319 }
320
321 return result;
322}
323
324Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const {
325 std::scoped_lock lock{mutex};
326
327 std::shared_ptr<NfcDevice> device = nullptr;
328 auto result = GetDeviceHandle(device_handle, device);
329
330 if (result.IsSuccess()) {
331 result = device->GetRegisterInfo(register_info);
332 result = VerifyDeviceResult(device, result);
333 }
334
335 return result;
336}
337
338Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const {
339 std::scoped_lock lock{mutex};
340
341 std::shared_ptr<NfcDevice> device = nullptr;
342 auto result = GetDeviceHandle(device_handle, device);
343
344 if (result.IsSuccess()) {
345 result = device->GetCommonInfo(common_info);
346 result = VerifyDeviceResult(device, result);
347 }
348
349 return result;
350}
351
352Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const {
353 std::scoped_lock lock{mutex};
354
355 std::shared_ptr<NfcDevice> device = nullptr;
356 auto result = GetDeviceHandle(device_handle, device);
357
358 if (result.IsSuccess()) {
359 result = device->GetModelInfo(model_info);
360 result = VerifyDeviceResult(device, result);
361 }
362
363 return result;
364}
365
366u32 DeviceManager::GetApplicationAreaSize() const {
367 return sizeof(NFP::ApplicationArea);
368}
369
370Result DeviceManager::RecreateApplicationArea(u64 device_handle, u32 access_id,
371 std::span<const u8> data) {
372 std::scoped_lock lock{mutex};
373
374 std::shared_ptr<NfcDevice> device = nullptr;
375 auto result = GetDeviceHandle(device_handle, device);
376
377 if (result.IsSuccess()) {
378 result = device->RecreateApplicationArea(access_id, data);
379 result = VerifyDeviceResult(device, result);
380 }
381
382 return result;
383}
384
385Result DeviceManager::Format(u64 device_handle) {
386 std::scoped_lock lock{mutex};
387
388 std::shared_ptr<NfcDevice> device = nullptr;
389 auto result = GetDeviceHandle(device_handle, device);
390
391 if (result.IsSuccess()) {
392 result = device->Format();
393 result = VerifyDeviceResult(device, result);
394 }
395
396 return result;
397}
398
399Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const {
400 std::scoped_lock lock{mutex};
401
402 std::shared_ptr<NfcDevice> device = nullptr;
403 auto result = GetDeviceHandle(device_handle, device);
404
405 if (result.IsSuccess()) {
406 result = device->GetAdminInfo(admin_info);
407 result = VerifyDeviceResult(device, result);
408 }
409
410 return result;
411}
412
413Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle,
414 NFP::RegisterInfoPrivate& register_info) const {
415 std::scoped_lock lock{mutex};
416
417 std::shared_ptr<NfcDevice> device = nullptr;
418 auto result = GetDeviceHandle(device_handle, device);
419
420 if (result.IsSuccess()) {
421 result = device->GetRegisterInfoPrivate(register_info);
422 result = VerifyDeviceResult(device, result);
423 }
424
425 return result;
426}
427
428Result DeviceManager::SetRegisterInfoPrivate(u64 device_handle,
429 const NFP::RegisterInfoPrivate& register_info) {
430 std::scoped_lock lock{mutex};
431
432 std::shared_ptr<NfcDevice> device = nullptr;
433 auto result = GetDeviceHandle(device_handle, device);
434
435 if (result.IsSuccess()) {
436 result = device->SetRegisterInfoPrivate(register_info);
437 result = VerifyDeviceResult(device, result);
438 }
439
440 return result;
441}
442
443Result DeviceManager::DeleteRegisterInfo(u64 device_handle) {
444 std::scoped_lock lock{mutex};
445
446 std::shared_ptr<NfcDevice> device = nullptr;
447 auto result = GetDeviceHandle(device_handle, device);
448
449 if (result.IsSuccess()) {
450 result = device->DeleteRegisterInfo();
451 result = VerifyDeviceResult(device, result);
452 }
453
454 return result;
455}
456
457Result DeviceManager::DeleteApplicationArea(u64 device_handle) {
458 std::scoped_lock lock{mutex};
459
460 std::shared_ptr<NfcDevice> device = nullptr;
461 auto result = GetDeviceHandle(device_handle, device);
462
463 if (result.IsSuccess()) {
464 result = device->DeleteApplicationArea();
465 result = VerifyDeviceResult(device, result);
466 }
467
468 return result;
469}
470
471Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) const {
472 std::scoped_lock lock{mutex};
473
474 std::shared_ptr<NfcDevice> device = nullptr;
475 auto result = GetDeviceHandle(device_handle, device);
476
477 if (result.IsSuccess()) {
478 result = device->ExistsApplicationArea(has_application_area);
479 result = VerifyDeviceResult(device, result);
480 }
481
482 return result;
483}
484
485Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) const {
486 std::scoped_lock lock{mutex};
487
488 std::shared_ptr<NfcDevice> device = nullptr;
489 auto result = GetDeviceHandle(device_handle, device);
490
491 if (result.IsSuccess()) {
492 result = device->GetAll(nfp_data);
493 result = VerifyDeviceResult(device, result);
494 }
495
496 return result;
497}
498
499Result DeviceManager::SetAll(u64 device_handle, const NFP::NfpData& nfp_data) {
500 std::scoped_lock lock{mutex};
501
502 std::shared_ptr<NfcDevice> device = nullptr;
503 auto result = GetDeviceHandle(device_handle, device);
504
505 if (result.IsSuccess()) {
506 result = device->SetAll(nfp_data);
507 result = VerifyDeviceResult(device, result);
508 }
509
510 return result;
511}
512
513Result DeviceManager::FlushDebug(u64 device_handle) {
514 std::scoped_lock lock{mutex};
515
516 std::shared_ptr<NfcDevice> device = nullptr;
517 auto result = GetDeviceHandle(device_handle, device);
518
519 if (result.IsSuccess()) {
520 result = device->FlushDebug();
521 result = VerifyDeviceResult(device, result);
522 }
523
524 return result;
525}
526
527Result DeviceManager::BreakTag(u64 device_handle, NFP::BreakType break_type) {
528 std::scoped_lock lock{mutex};
529
530 std::shared_ptr<NfcDevice> device = nullptr;
531 auto result = GetDeviceHandle(device_handle, device);
532
533 if (result.IsSuccess()) {
534 result = device->BreakTag(break_type);
535 result = VerifyDeviceResult(device, result);
536 }
537
538 return result;
539}
540
541Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) const {
542 std::scoped_lock lock{mutex};
543
544 std::shared_ptr<NfcDevice> device = nullptr;
545 auto result = GetDeviceHandle(device_handle, device);
546
547 if (result.IsSuccess()) {
548 result = device->ReadBackupData(data);
549 result = VerifyDeviceResult(device, result);
550 }
551
552 return result;
553}
554
555Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> data) {
556 std::scoped_lock lock{mutex};
557
558 std::shared_ptr<NfcDevice> device = nullptr;
559 auto result = GetDeviceHandle(device_handle, device);
560
561 if (result.IsSuccess()) {
562 result = device->WriteBackupData(data);
563 result = VerifyDeviceResult(device, result);
564 }
565
566 return result;
567}
568
569Result DeviceManager::WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data) {
570 std::scoped_lock lock{mutex};
571
572 std::shared_ptr<NfcDevice> device = nullptr;
573 auto result = GetDeviceHandle(device_handle, device);
574
575 if (result.IsSuccess()) {
576 result = device->WriteNtf(data);
577 result = VerifyDeviceResult(device, result);
578 }
579
580 return result;
581}
582
583Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device,
584 bool check_state) const {
585 if (check_state) {
586 const Result is_parameter_set = IsNfcParameterSet();
587 if (is_parameter_set.IsError()) {
588 return is_parameter_set;
589 }
590 const Result is_enabled = IsNfcEnabled();
591 if (is_enabled.IsError()) {
592 return is_enabled;
593 }
594 const Result is_nfc_initialized = IsNfcInitialized();
595 if (is_nfc_initialized.IsError()) {
596 return is_nfc_initialized;
597 }
598 }
599
600 for (auto& device : devices) {
601 if (device->GetHandle() == handle) {
602 nfc_device = device;
603 return ResultSuccess;
604 }
605 }
606
607 return ResultDeviceNotFound;
608}
609
610std::optional<std::shared_ptr<NfcDevice>> DeviceManager::GetNfcDevice(u64 handle) {
611 for (auto& device : devices) {
612 if (device->GetHandle() == handle) {
613 return device;
614 }
615 }
616 return std::nullopt;
617}
618
619const std::optional<std::shared_ptr<NfcDevice>> DeviceManager::GetNfcDevice(u64 handle) const {
620 for (auto& device : devices) {
621 if (device->GetHandle() == handle) {
622 return device;
623 }
624 }
625 return std::nullopt;
626}
627
628Result DeviceManager::GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const {
629 const auto result = GetDeviceFromHandle(handle, device, true);
630 if (result.IsError()) {
631 return result;
632 }
633 return CheckDeviceState(device);
634}
635
636Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
637 Result operation_result) const {
638 if (operation_result.IsSuccess()) {
639 return operation_result;
640 }
641
642 const Result is_parameter_set = IsNfcParameterSet();
643 if (is_parameter_set.IsError()) {
644 return is_parameter_set;
645 }
646 const Result is_enabled = IsNfcEnabled();
647 if (is_enabled.IsError()) {
648 return is_enabled;
649 }
650 const Result is_nfc_initialized = IsNfcInitialized();
651 if (is_nfc_initialized.IsError()) {
652 return is_nfc_initialized;
653 }
654 const Result device_state = CheckDeviceState(device);
655 if (device_state.IsError()) {
656 return device_state;
657 }
658
659 return operation_result;
660}
661
662Result DeviceManager::CheckDeviceState(std::shared_ptr<NfcDevice> device) const {
663 if (device == nullptr) {
664 return ResultInvalidArgument;
665 }
666
667 return ResultSuccess;
668}
669
670Result DeviceManager::IsNfcEnabled() const {
671 // TODO: This calls nn::settings::detail::GetNfcEnableFlag
672 const bool is_enabled = true;
673 if (!is_enabled) {
674 return ResultNfcDisabled;
675 }
676 return ResultSuccess;
677}
678
679Result DeviceManager::IsNfcParameterSet() const {
680 // TODO: This calls checks against a bool on offset 0x450
681 const bool is_set = true;
682 if (!is_set) {
683 return ResultUnknown76;
684 }
685 return ResultSuccess;
686}
687
688Result DeviceManager::IsNfcInitialized() const {
689 if (!is_initialized) {
690 return ResultNfcNotInitialized;
691 }
692 return ResultSuccess;
693}
694
695} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h
new file mode 100644
index 000000000..2971e280f
--- /dev/null
+++ b/src/core/hle/service/nfc/common/device_manager.h
@@ -0,0 +1,100 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <memory>
8#include <optional>
9#include <span>
10
11#include "core/hid/hid_types.h"
12#include "core/hle/service/kernel_helpers.h"
13#include "core/hle/service/nfc/mifare_types.h"
14#include "core/hle/service/nfc/nfc_types.h"
15#include "core/hle/service/nfp/nfp_types.h"
16#include "core/hle/service/service.h"
17#include "core/hle/service/time/clock_types.h"
18
19namespace Service::NFC {
20class NfcDevice;
21
22class DeviceManager {
23public:
24 explicit DeviceManager(Core::System& system_, KernelHelpers::ServiceContext& service_context_);
25 ~DeviceManager();
26
27 // Nfc device manager
28 Result Initialize();
29 Result Finalize();
30 Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices) const;
31 DeviceState GetDeviceState(u64 device_handle) const;
32 Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const;
33 Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;
34 Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);
35 Result StopDetection(u64 device_handle);
36 Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info, bool is_mifare) const;
37 Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const;
38 Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const;
39 Result ReadMifare(u64 device_handle,
40 const std::span<const MifareReadBlockParameter> read_parameters,
41 std::span<MifareReadBlockData> read_data);
42 Result WriteMifare(u64 device_handle,
43 std::span<const MifareWriteBlockParameter> write_parameters);
44 Result SendCommandByPassThrough(u64 device_handle, const Time::Clock::TimeSpanType& timeout,
45 std::span<const u8> command_data, std::span<u8> out_data);
46
47 // Nfp device manager
48 Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
49 Result Unmount(u64 device_handle);
50 Result OpenApplicationArea(u64 device_handle, u32 access_id);
51 Result GetApplicationArea(u64 device_handle, std::span<u8> data) const;
52 Result SetApplicationArea(u64 device_handle, std::span<const u8> data);
53 Result Flush(u64 device_handle);
54 Result Restore(u64 device_handle);
55 Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
56 Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const;
57 Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const;
58 Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const;
59 u32 GetApplicationAreaSize() const;
60 Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
61 Result Format(u64 device_handle);
62 Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const;
63 Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info) const;
64 Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info);
65 Result DeleteRegisterInfo(u64 device_handle);
66 Result DeleteApplicationArea(u64 device_handle);
67 Result ExistsApplicationArea(u64 device_handle, bool& has_application_area) const;
68 Result GetAll(u64 device_handle, NFP::NfpData& nfp_data) const;
69 Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data);
70 Result FlushDebug(u64 device_handle);
71 Result BreakTag(u64 device_handle, NFP::BreakType break_type);
72 Result ReadBackupData(u64 device_handle, std::span<u8> data) const;
73 Result WriteBackupData(u64 device_handle, std::span<const u8> data);
74 Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data);
75
76private:
77 Result IsNfcEnabled() const;
78 Result IsNfcParameterSet() const;
79 Result IsNfcInitialized() const;
80
81 Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device,
82 bool check_state) const;
83
84 Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const;
85 Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result) const;
86 Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const;
87
88 std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
89 const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const;
90
91 bool is_initialized = false;
92 mutable std::mutex mutex;
93 std::array<std::shared_ptr<NfcDevice>, 10> devices{};
94
95 Core::System& system;
96 KernelHelpers::ServiceContext service_context;
97 Kernel::KEvent* availability_change_event;
98};
99
100} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/mifare_interface.cpp b/src/core/hle/service/nfc/mifare_interface.cpp
deleted file mode 100644
index 7e6635ba2..000000000
--- a/src/core/hle/service/nfc/mifare_interface.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/logging/log.h"
5#include "core/core.h"
6#include "core/hid/hid_types.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nfc/mifare_interface.h"
10#include "core/hle/service/nfc/nfc_device.h"
11#include "core/hle/service/nfc/nfc_result.h"
12
13namespace Service::NFC {
14
15MFInterface::MFInterface(Core::System& system_, const char* name)
16 : ServiceFramework{system_, name}, service_context{system_, service_name} {
17 availability_change_event = service_context.CreateEvent("MFInterface:AvailabilityChangeEvent");
18
19 for (u32 device_index = 0; device_index < 10; device_index++) {
20 devices[device_index] =
21 std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
22 service_context, availability_change_event);
23 }
24}
25
26MFInterface ::~MFInterface() {
27 availability_change_event->Close();
28}
29
30void MFInterface::Initialize(HLERequestContext& ctx) {
31 LOG_INFO(Service_NFC, "called");
32
33 state = State::Initialized;
34
35 for (auto& device : devices) {
36 device->Initialize();
37 }
38
39 IPC::ResponseBuilder rb{ctx, 2, 0};
40 rb.Push(ResultSuccess);
41}
42
43void MFInterface::Finalize(HLERequestContext& ctx) {
44 LOG_INFO(Service_NFC, "called");
45
46 state = State::NonInitialized;
47
48 for (auto& device : devices) {
49 device->Finalize();
50 }
51
52 IPC::ResponseBuilder rb{ctx, 2};
53 rb.Push(ResultSuccess);
54}
55
56void MFInterface::ListDevices(HLERequestContext& ctx) {
57 LOG_DEBUG(Service_NFC, "called");
58
59 if (state == State::NonInitialized) {
60 IPC::ResponseBuilder rb{ctx, 2};
61 rb.Push(MifareNfcDisabled);
62 return;
63 }
64
65 if (!ctx.CanWriteBuffer()) {
66 IPC::ResponseBuilder rb{ctx, 2};
67 rb.Push(MifareInvalidArgument);
68 return;
69 }
70
71 if (ctx.GetWriteBufferSize() == 0) {
72 IPC::ResponseBuilder rb{ctx, 2};
73 rb.Push(MifareInvalidArgument);
74 return;
75 }
76
77 std::vector<u64> nfp_devices;
78 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
79
80 for (const auto& device : devices) {
81 if (nfp_devices.size() >= max_allowed_devices) {
82 continue;
83 }
84 if (device->GetCurrentState() != NFP::DeviceState::Unavailable) {
85 nfp_devices.push_back(device->GetHandle());
86 }
87 }
88
89 if (nfp_devices.empty()) {
90 IPC::ResponseBuilder rb{ctx, 2};
91 rb.Push(MifareDeviceNotFound);
92 return;
93 }
94
95 ctx.WriteBuffer(nfp_devices);
96
97 IPC::ResponseBuilder rb{ctx, 3};
98 rb.Push(ResultSuccess);
99 rb.Push(static_cast<s32>(nfp_devices.size()));
100}
101
102void MFInterface::StartDetection(HLERequestContext& ctx) {
103 IPC::RequestParser rp{ctx};
104 const auto device_handle{rp.Pop<u64>()};
105 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
106
107 if (state == State::NonInitialized) {
108 IPC::ResponseBuilder rb{ctx, 2};
109 rb.Push(MifareNfcDisabled);
110 return;
111 }
112
113 auto device = GetNfcDevice(device_handle);
114
115 if (!device.has_value()) {
116 IPC::ResponseBuilder rb{ctx, 2};
117 rb.Push(MifareDeviceNotFound);
118 return;
119 }
120
121 const auto result = device.value()->StartDetection(NFP::TagProtocol::All);
122 IPC::ResponseBuilder rb{ctx, 2};
123 rb.Push(result);
124}
125
126void MFInterface::StopDetection(HLERequestContext& ctx) {
127 IPC::RequestParser rp{ctx};
128 const auto device_handle{rp.Pop<u64>()};
129 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
130
131 if (state == State::NonInitialized) {
132 IPC::ResponseBuilder rb{ctx, 2};
133 rb.Push(MifareNfcDisabled);
134 return;
135 }
136
137 auto device = GetNfcDevice(device_handle);
138
139 if (!device.has_value()) {
140 IPC::ResponseBuilder rb{ctx, 2};
141 rb.Push(MifareDeviceNotFound);
142 return;
143 }
144
145 const auto result = device.value()->StopDetection();
146 IPC::ResponseBuilder rb{ctx, 2};
147 rb.Push(result);
148}
149
150void MFInterface::Read(HLERequestContext& ctx) {
151 IPC::RequestParser rp{ctx};
152 const auto device_handle{rp.Pop<u64>()};
153 const auto buffer{ctx.ReadBuffer()};
154 const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareReadBlockParameter>()};
155 std::vector<NFP::MifareReadBlockParameter> read_commands(number_of_commands);
156
157 memcpy(read_commands.data(), buffer.data(),
158 number_of_commands * sizeof(NFP::MifareReadBlockParameter));
159
160 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
161 device_handle, number_of_commands);
162
163 if (state == State::NonInitialized) {
164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(MifareNfcDisabled);
166 return;
167 }
168
169 auto device = GetNfcDevice(device_handle);
170
171 if (!device.has_value()) {
172 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(MifareDeviceNotFound);
174 return;
175 }
176
177 Result result = ResultSuccess;
178 std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
179 for (std::size_t i = 0; i < number_of_commands; i++) {
180 result = device.value()->MifareRead(read_commands[i], out_data[i]);
181 if (result.IsError()) {
182 break;
183 }
184 }
185
186 ctx.WriteBuffer(out_data);
187 IPC::ResponseBuilder rb{ctx, 2};
188 rb.Push(result);
189}
190
191void MFInterface::Write(HLERequestContext& ctx) {
192 IPC::RequestParser rp{ctx};
193 const auto device_handle{rp.Pop<u64>()};
194 const auto buffer{ctx.ReadBuffer()};
195 const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareWriteBlockParameter>()};
196 std::vector<NFP::MifareWriteBlockParameter> write_commands(number_of_commands);
197
198 memcpy(write_commands.data(), buffer.data(),
199 number_of_commands * sizeof(NFP::MifareWriteBlockParameter));
200
201 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
202 device_handle, number_of_commands);
203
204 if (state == State::NonInitialized) {
205 IPC::ResponseBuilder rb{ctx, 2};
206 rb.Push(MifareNfcDisabled);
207 return;
208 }
209
210 auto device = GetNfcDevice(device_handle);
211
212 if (!device.has_value()) {
213 IPC::ResponseBuilder rb{ctx, 2};
214 rb.Push(MifareDeviceNotFound);
215 return;
216 }
217
218 Result result = ResultSuccess;
219 std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
220 for (std::size_t i = 0; i < number_of_commands; i++) {
221 result = device.value()->MifareWrite(write_commands[i]);
222 if (result.IsError()) {
223 break;
224 }
225 }
226
227 if (result.IsSuccess()) {
228 result = device.value()->Flush();
229 }
230
231 IPC::ResponseBuilder rb{ctx, 2};
232 rb.Push(result);
233}
234
235void MFInterface::GetTagInfo(HLERequestContext& ctx) {
236 IPC::RequestParser rp{ctx};
237 const auto device_handle{rp.Pop<u64>()};
238 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
239
240 if (state == State::NonInitialized) {
241 IPC::ResponseBuilder rb{ctx, 2};
242 rb.Push(MifareNfcDisabled);
243 return;
244 }
245
246 auto device = GetNfcDevice(device_handle);
247
248 if (!device.has_value()) {
249 IPC::ResponseBuilder rb{ctx, 2};
250 rb.Push(MifareDeviceNotFound);
251 return;
252 }
253
254 NFP::TagInfo tag_info{};
255 const auto result = device.value()->GetTagInfo(tag_info, true);
256 ctx.WriteBuffer(tag_info);
257 IPC::ResponseBuilder rb{ctx, 2};
258 rb.Push(result);
259}
260
261void MFInterface::GetActivateEventHandle(HLERequestContext& ctx) {
262 IPC::RequestParser rp{ctx};
263 const auto device_handle{rp.Pop<u64>()};
264 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
265
266 if (state == State::NonInitialized) {
267 IPC::ResponseBuilder rb{ctx, 2};
268 rb.Push(MifareNfcDisabled);
269 return;
270 }
271
272 auto device = GetNfcDevice(device_handle);
273
274 if (!device.has_value()) {
275 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(MifareDeviceNotFound);
277 return;
278 }
279
280 IPC::ResponseBuilder rb{ctx, 2, 1};
281 rb.Push(ResultSuccess);
282 rb.PushCopyObjects(device.value()->GetActivateEvent());
283}
284
285void MFInterface::GetDeactivateEventHandle(HLERequestContext& ctx) {
286 IPC::RequestParser rp{ctx};
287 const auto device_handle{rp.Pop<u64>()};
288 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
289
290 if (state == State::NonInitialized) {
291 IPC::ResponseBuilder rb{ctx, 2};
292 rb.Push(MifareNfcDisabled);
293 return;
294 }
295
296 auto device = GetNfcDevice(device_handle);
297
298 if (!device.has_value()) {
299 IPC::ResponseBuilder rb{ctx, 2};
300 rb.Push(MifareDeviceNotFound);
301 return;
302 }
303
304 IPC::ResponseBuilder rb{ctx, 2, 1};
305 rb.Push(ResultSuccess);
306 rb.PushCopyObjects(device.value()->GetDeactivateEvent());
307}
308
309void MFInterface::GetState(HLERequestContext& ctx) {
310 LOG_DEBUG(Service_NFC, "called");
311
312 IPC::ResponseBuilder rb{ctx, 3};
313 rb.Push(ResultSuccess);
314 rb.PushEnum(state);
315}
316
317void MFInterface::GetDeviceState(HLERequestContext& ctx) {
318 IPC::RequestParser rp{ctx};
319 const auto device_handle{rp.Pop<u64>()};
320 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
321
322 auto device = GetNfcDevice(device_handle);
323
324 if (!device.has_value()) {
325 IPC::ResponseBuilder rb{ctx, 2};
326 rb.Push(MifareDeviceNotFound);
327 return;
328 }
329
330 IPC::ResponseBuilder rb{ctx, 3};
331 rb.Push(ResultSuccess);
332 rb.PushEnum(device.value()->GetCurrentState());
333}
334
335void MFInterface::GetNpadId(HLERequestContext& ctx) {
336 IPC::RequestParser rp{ctx};
337 const auto device_handle{rp.Pop<u64>()};
338 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
339
340 if (state == State::NonInitialized) {
341 IPC::ResponseBuilder rb{ctx, 2};
342 rb.Push(MifareNfcDisabled);
343 return;
344 }
345
346 auto device = GetNfcDevice(device_handle);
347
348 if (!device.has_value()) {
349 IPC::ResponseBuilder rb{ctx, 2};
350 rb.Push(MifareDeviceNotFound);
351 return;
352 }
353
354 IPC::ResponseBuilder rb{ctx, 3};
355 rb.Push(ResultSuccess);
356 rb.PushEnum(device.value()->GetNpadId());
357}
358
359void MFInterface::GetAvailabilityChangeEventHandle(HLERequestContext& ctx) {
360 LOG_INFO(Service_NFC, "called");
361
362 if (state == State::NonInitialized) {
363 IPC::ResponseBuilder rb{ctx, 2};
364 rb.Push(MifareNfcDisabled);
365 return;
366 }
367
368 IPC::ResponseBuilder rb{ctx, 2, 1};
369 rb.Push(ResultSuccess);
370 rb.PushCopyObjects(availability_change_event->GetReadableEvent());
371}
372
373std::optional<std::shared_ptr<NfcDevice>> MFInterface::GetNfcDevice(u64 handle) {
374 for (auto& device : devices) {
375 if (device->GetHandle() == handle) {
376 return device;
377 }
378 }
379 return std::nullopt;
380}
381
382} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/mifare_interface.h b/src/core/hle/service/nfc/mifare_interface.h
deleted file mode 100644
index 698c8a6b6..000000000
--- a/src/core/hle/service/nfc/mifare_interface.h
+++ /dev/null
@@ -1,52 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <memory>
8#include <optional>
9
10#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/service.h"
12
13namespace Service::NFC {
14class NfcDevice;
15
16class MFInterface : public ServiceFramework<MFInterface> {
17public:
18 explicit MFInterface(Core::System& system_, const char* name);
19 ~MFInterface();
20
21 void Initialize(HLERequestContext& ctx);
22 void Finalize(HLERequestContext& ctx);
23 void ListDevices(HLERequestContext& ctx);
24 void StartDetection(HLERequestContext& ctx);
25 void StopDetection(HLERequestContext& ctx);
26 void Read(HLERequestContext& ctx);
27 void Write(HLERequestContext& ctx);
28 void GetTagInfo(HLERequestContext& ctx);
29 void GetActivateEventHandle(HLERequestContext& ctx);
30 void GetDeactivateEventHandle(HLERequestContext& ctx);
31 void GetState(HLERequestContext& ctx);
32 void GetDeviceState(HLERequestContext& ctx);
33 void GetNpadId(HLERequestContext& ctx);
34 void GetAvailabilityChangeEventHandle(HLERequestContext& ctx);
35
36private:
37 enum class State : u32 {
38 NonInitialized,
39 Initialized,
40 };
41
42 std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
43
44 KernelHelpers::ServiceContext service_context;
45
46 std::array<std::shared_ptr<NfcDevice>, 10> devices{};
47
48 State state{State::NonInitialized};
49 Kernel::KEvent* availability_change_event;
50};
51
52} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/mifare_result.h b/src/core/hle/service/nfc/mifare_result.h
new file mode 100644
index 000000000..4b60048a5
--- /dev/null
+++ b/src/core/hle/service/nfc/mifare_result.h
@@ -0,0 +1,17 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::NFC::Mifare {
9
10constexpr Result ResultDeviceNotFound(ErrorModule::NFCMifare, 64);
11constexpr Result ResultInvalidArgument(ErrorModule::NFCMifare, 65);
12constexpr Result ResultWrongDeviceState(ErrorModule::NFCMifare, 73);
13constexpr Result ResultNfcDisabled(ErrorModule::NFCMifare, 80);
14constexpr Result ResultTagRemoved(ErrorModule::NFCMifare, 97);
15constexpr Result ResultReadError(ErrorModule::NFCMifare, 288);
16
17} // namespace Service::NFC::Mifare
diff --git a/src/core/hle/service/nfc/mifare_types.h b/src/core/hle/service/nfc/mifare_types.h
new file mode 100644
index 000000000..75b59f021
--- /dev/null
+++ b/src/core/hle/service/nfc/mifare_types.h
@@ -0,0 +1,63 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10
11namespace Service::NFC {
12
13enum class MifareCmd : u8 {
14 AuthA = 0x60,
15 AuthB = 0x61,
16 Read = 0x30,
17 Write = 0xA0,
18 Transfer = 0xB0,
19 Decrement = 0xC0,
20 Increment = 0xC1,
21 Store = 0xC2
22};
23
24using DataBlock = std::array<u8, 0x10>;
25using KeyData = std::array<u8, 0x6>;
26
27struct SectorKey {
28 MifareCmd command;
29 u8 unknown; // Usually 1
30 INSERT_PADDING_BYTES(0x6);
31 KeyData sector_key;
32 INSERT_PADDING_BYTES(0x2);
33};
34static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");
35
36// This is nn::nfc::MifareReadBlockParameter
37struct MifareReadBlockParameter {
38 u8 sector_number;
39 INSERT_PADDING_BYTES(0x7);
40 SectorKey sector_key;
41};
42static_assert(sizeof(MifareReadBlockParameter) == 0x18,
43 "MifareReadBlockParameter is an invalid size");
44
45// This is nn::nfc::MifareReadBlockData
46struct MifareReadBlockData {
47 DataBlock data;
48 u8 sector_number;
49 INSERT_PADDING_BYTES(0x7);
50};
51static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size");
52
53// This is nn::nfc::MifareWriteBlockParameter
54struct MifareWriteBlockParameter {
55 DataBlock data;
56 u8 sector_number;
57 INSERT_PADDING_BYTES(0x7);
58 SectorKey sector_key;
59};
60static_assert(sizeof(MifareWriteBlockParameter) == 0x28,
61 "MifareWriteBlockParameter is an invalid size");
62
63} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 444d65f07..30ae989b9 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -6,7 +6,6 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nfc/mifare_interface.h"
10#include "core/hle/service/nfc/nfc.h" 9#include "core/hle/service/nfc/nfc.h"
11#include "core/hle/service/nfc/nfc_interface.h" 10#include "core/hle/service/nfc/nfc_interface.h"
12#include "core/hle/service/server_manager.h" 11#include "core/hle/service/server_manager.h"
@@ -14,31 +13,31 @@
14 13
15namespace Service::NFC { 14namespace Service::NFC {
16 15
17class IUser final : public Interface { 16class IUser final : public NfcInterface {
18public: 17public:
19 explicit IUser(Core::System& system_) : Interface(system_, "NFC::IUser") { 18 explicit IUser(Core::System& system_) : NfcInterface(system_, "NFC::IUser", BackendType::Nfc) {
20 // clang-format off 19 // clang-format off
21 static const FunctionInfo functions[] = { 20 static const FunctionInfo functions[] = {
22 {0, &Interface::Initialize, "InitializeOld"}, 21 {0, &NfcInterface::Initialize, "InitializeOld"},
23 {1, &Interface::Finalize, "FinalizeOld"}, 22 {1, &NfcInterface::Finalize, "FinalizeOld"},
24 {2, &Interface::GetState, "GetStateOld"}, 23 {2, &NfcInterface::GetState, "GetStateOld"},
25 {3, &Interface::IsNfcEnabled, "IsNfcEnabledOld"}, 24 {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"},
26 {400, &Interface::Initialize, "Initialize"}, 25 {400, &NfcInterface::Initialize, "Initialize"},
27 {401, &Interface::Finalize, "Finalize"}, 26 {401, &NfcInterface::Finalize, "Finalize"},
28 {402, &Interface::GetState, "GetState"}, 27 {402, &NfcInterface::GetState, "GetState"},
29 {403, &Interface::IsNfcEnabled, "IsNfcEnabled"}, 28 {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"},
30 {404, &Interface::ListDevices, "ListDevices"}, 29 {404, &NfcInterface::ListDevices, "ListDevices"},
31 {405, &Interface::GetDeviceState, "GetDeviceState"}, 30 {405, &NfcInterface::GetDeviceState, "GetDeviceState"},
32 {406, &Interface::GetNpadId, "GetNpadId"}, 31 {406, &NfcInterface::GetNpadId, "GetNpadId"},
33 {407, &Interface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, 32 {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
34 {408, &Interface::StartDetection, "StartDetection"}, 33 {408, &NfcInterface::StartDetection, "StartDetection"},
35 {409, &Interface::StopDetection, "StopDetection"}, 34 {409, &NfcInterface::StopDetection, "StopDetection"},
36 {410, &Interface::GetTagInfo, "GetTagInfo"}, 35 {410, &NfcInterface::GetTagInfo, "GetTagInfo"},
37 {411, &Interface::AttachActivateEvent, "AttachActivateEvent"}, 36 {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"},
38 {412, &Interface::AttachDeactivateEvent, "AttachDeactivateEvent"}, 37 {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"},
39 {1000, nullptr, "ReadMifare"}, 38 {1000, &NfcInterface::ReadMifare, "ReadMifare"},
40 {1001, nullptr, "WriteMifare"}, 39 {1001, &NfcInterface::WriteMifare ,"WriteMifare"},
41 {1300, &Interface::SendCommandByPassThrough, "SendCommandByPassThrough"}, 40 {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"},
42 {1301, nullptr, "KeepPassThroughSession"}, 41 {1301, nullptr, "KeepPassThroughSession"},
43 {1302, nullptr, "ReleasePassThroughSession"}, 42 {1302, nullptr, "ReleasePassThroughSession"},
44 }; 43 };
@@ -48,34 +47,35 @@ public:
48 } 47 }
49}; 48};
50 49
51class ISystem final : public Interface { 50class ISystem final : public NfcInterface {
52public: 51public:
53 explicit ISystem(Core::System& system_) : Interface{system_, "NFC::ISystem"} { 52 explicit ISystem(Core::System& system_)
53 : NfcInterface{system_, "NFC::ISystem", BackendType::Nfc} {
54 // clang-format off 54 // clang-format off
55 static const FunctionInfo functions[] = { 55 static const FunctionInfo functions[] = {
56 {0, &Interface::Initialize, "InitializeOld"}, 56 {0, &NfcInterface::Initialize, "InitializeOld"},
57 {1, &Interface::Finalize, "FinalizeOld"}, 57 {1, &NfcInterface::Finalize, "FinalizeOld"},
58 {2, &Interface::GetState, "GetStateOld"}, 58 {2, &NfcInterface::GetState, "GetStateOld"},
59 {3, &Interface::IsNfcEnabled, "IsNfcEnabledOld"}, 59 {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"},
60 {100, nullptr, "SetNfcEnabledOld"}, 60 {100, nullptr, "SetNfcEnabledOld"},
61 {400, &Interface::Initialize, "Initialize"}, 61 {400, &NfcInterface::Initialize, "Initialize"},
62 {401, &Interface::Finalize, "Finalize"}, 62 {401, &NfcInterface::Finalize, "Finalize"},
63 {402, &Interface::GetState, "GetState"}, 63 {402, &NfcInterface::GetState, "GetState"},
64 {403, &Interface::IsNfcEnabled, "IsNfcEnabled"}, 64 {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"},
65 {404, &Interface::ListDevices, "ListDevices"}, 65 {404, &NfcInterface::ListDevices, "ListDevices"},
66 {405, &Interface::GetDeviceState, "GetDeviceState"}, 66 {405, &NfcInterface::GetDeviceState, "GetDeviceState"},
67 {406, &Interface::GetNpadId, "GetNpadId"}, 67 {406, &NfcInterface::GetNpadId, "GetNpadId"},
68 {407, &Interface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, 68 {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
69 {408, &Interface::StartDetection, "StartDetection"}, 69 {408, &NfcInterface::StartDetection, "StartDetection"},
70 {409, &Interface::StopDetection, "StopDetection"}, 70 {409, &NfcInterface::StopDetection, "StopDetection"},
71 {410, &Interface::GetTagInfo, "GetTagInfo"}, 71 {410, &NfcInterface::GetTagInfo, "GetTagInfo"},
72 {411, &Interface::AttachActivateEvent, "AttachActivateEvent"}, 72 {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"},
73 {412, &Interface::AttachDeactivateEvent, "AttachDeactivateEvent"}, 73 {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"},
74 {500, nullptr, "SetNfcEnabled"}, 74 {500, nullptr, "SetNfcEnabled"},
75 {510, nullptr, "OutputTestWave"}, 75 {510, nullptr, "OutputTestWave"},
76 {1000, nullptr, "ReadMifare"}, 76 {1000, &NfcInterface::ReadMifare, "ReadMifare"},
77 {1001, nullptr, "WriteMifare"}, 77 {1001, &NfcInterface::WriteMifare, "WriteMifare"},
78 {1300, &Interface::SendCommandByPassThrough, "SendCommandByPassThrough"}, 78 {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"},
79 {1301, nullptr, "KeepPassThroughSession"}, 79 {1301, nullptr, "KeepPassThroughSession"},
80 {1302, nullptr, "ReleasePassThroughSession"}, 80 {1302, nullptr, "ReleasePassThroughSession"},
81 }; 81 };
@@ -85,25 +85,29 @@ public:
85 } 85 }
86}; 86};
87 87
88// MFInterface has an unique interface but it's identical to NfcInterface so we can keep the code
89// simpler
90using MFInterface = NfcInterface;
88class MFIUser final : public MFInterface { 91class MFIUser final : public MFInterface {
89public: 92public:
90 explicit MFIUser(Core::System& system_) : MFInterface{system_, "NFC::MFInterface"} { 93 explicit MFIUser(Core::System& system_)
94 : MFInterface{system_, "NFC::MFInterface", BackendType::Mifare} {
91 // clang-format off 95 // clang-format off
92 static const FunctionInfo functions[] = { 96 static const FunctionInfoTyped<MFIUser> functions[] = {
93 {0, &MFIUser::Initialize, "Initialize"}, 97 {0, &MFIUser::Initialize, "Initialize"},
94 {1, &MFIUser::Finalize, "Finalize"}, 98 {1, &MFIUser::Finalize, "Finalize"},
95 {2, &MFIUser::ListDevices, "ListDevices"}, 99 {2, &MFIUser::ListDevices, "ListDevices"},
96 {3, &MFIUser::StartDetection, "StartDetection"}, 100 {3, &MFIUser::StartDetection, "StartDetection"},
97 {4, &MFIUser::StopDetection, "StopDetection"}, 101 {4, &MFIUser::StopDetection, "StopDetection"},
98 {5, &MFIUser::Read, "Read"}, 102 {5, &MFIUser::ReadMifare, "Read"},
99 {6, &MFIUser::Write, "Write"}, 103 {6, &MFIUser::WriteMifare, "Write"},
100 {7, &MFIUser::GetTagInfo, "GetTagInfo"}, 104 {7, &MFIUser::GetTagInfo, "GetTagInfo"},
101 {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"}, 105 {8, &MFIUser::AttachActivateEvent, "GetActivateEventHandle"},
102 {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"}, 106 {9, &MFIUser::AttachDeactivateEvent, "GetDeactivateEventHandle"},
103 {10, &MFIUser::GetState, "GetState"}, 107 {10, &MFIUser::GetState, "GetState"},
104 {11, &MFIUser::GetDeviceState, "GetDeviceState"}, 108 {11, &MFIUser::GetDeviceState, "GetDeviceState"},
105 {12, &MFIUser::GetNpadId, "GetNpadId"}, 109 {12, &MFIUser::GetNpadId, "GetNpadId"},
106 {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"}, 110 {13, &MFIUser::AttachAvailabilityChangeEvent, "GetAvailabilityChangeEventHandle"},
107 }; 111 };
108 // clang-format on 112 // clang-format on
109 113
@@ -131,7 +135,7 @@ public:
131 explicit NFC_AM(Core::System& system_) : ServiceFramework{system_, "nfc:am"} { 135 explicit NFC_AM(Core::System& system_) : ServiceFramework{system_, "nfc:am"} {
132 // clang-format off 136 // clang-format off
133 static const FunctionInfo functions[] = { 137 static const FunctionInfo functions[] = {
134 {0, &NFC_AM::CreateAmInterface, "CreateAmInterface"}, 138 {0, &NFC_AM::CreateAmNfcInterface, "CreateAmNfcInterface"},
135 }; 139 };
136 // clang-format on 140 // clang-format on
137 141
@@ -139,7 +143,7 @@ public:
139 } 143 }
140 144
141private: 145private:
142 void CreateAmInterface(HLERequestContext& ctx) { 146 void CreateAmNfcInterface(HLERequestContext& ctx) {
143 LOG_DEBUG(Service_NFC, "called"); 147 LOG_DEBUG(Service_NFC, "called");
144 148
145 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 149 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -153,7 +157,7 @@ public:
153 explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} { 157 explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} {
154 // clang-format off 158 // clang-format off
155 static const FunctionInfo functions[] = { 159 static const FunctionInfo functions[] = {
156 {0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"}, 160 {0, &NFC_MF_U::CreateUserNfcInterface, "CreateUserNfcInterface"},
157 }; 161 };
158 // clang-format on 162 // clang-format on
159 163
@@ -161,7 +165,7 @@ public:
161 } 165 }
162 166
163private: 167private:
164 void CreateUserInterface(HLERequestContext& ctx) { 168 void CreateUserNfcInterface(HLERequestContext& ctx) {
165 LOG_DEBUG(Service_NFC, "called"); 169 LOG_DEBUG(Service_NFC, "called");
166 170
167 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 171 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -175,7 +179,7 @@ public:
175 explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} { 179 explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} {
176 // clang-format off 180 // clang-format off
177 static const FunctionInfo functions[] = { 181 static const FunctionInfo functions[] = {
178 {0, &NFC_U::CreateUserInterface, "CreateUserInterface"}, 182 {0, &NFC_U::CreateUserNfcInterface, "CreateUserNfcInterface"},
179 }; 183 };
180 // clang-format on 184 // clang-format on
181 185
@@ -183,7 +187,7 @@ public:
183 } 187 }
184 188
185private: 189private:
186 void CreateUserInterface(HLERequestContext& ctx) { 190 void CreateUserNfcInterface(HLERequestContext& ctx) {
187 LOG_DEBUG(Service_NFC, "called"); 191 LOG_DEBUG(Service_NFC, "called");
188 192
189 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 193 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -197,7 +201,7 @@ public:
197 explicit NFC_SYS(Core::System& system_) : ServiceFramework{system_, "nfc:sys"} { 201 explicit NFC_SYS(Core::System& system_) : ServiceFramework{system_, "nfc:sys"} {
198 // clang-format off 202 // clang-format off
199 static const FunctionInfo functions[] = { 203 static const FunctionInfo functions[] = {
200 {0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"}, 204 {0, &NFC_SYS::CreateSystemNfcInterface, "CreateSystemNfcInterface"},
201 }; 205 };
202 // clang-format on 206 // clang-format on
203 207
@@ -205,7 +209,7 @@ public:
205 } 209 }
206 210
207private: 211private:
208 void CreateSystemInterface(HLERequestContext& ctx) { 212 void CreateSystemNfcInterface(HLERequestContext& ctx) {
209 LOG_DEBUG(Service_NFC, "called"); 213 LOG_DEBUG(Service_NFC, "called");
210 214
211 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 215 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -221,6 +225,7 @@ void LoopProcess(Core::System& system) {
221 server_manager->RegisterNamedService("nfc:mf:u", std::make_shared<NFC_MF_U>(system)); 225 server_manager->RegisterNamedService("nfc:mf:u", std::make_shared<NFC_MF_U>(system));
222 server_manager->RegisterNamedService("nfc:user", std::make_shared<NFC_U>(system)); 226 server_manager->RegisterNamedService("nfc:user", std::make_shared<NFC_U>(system));
223 server_manager->RegisterNamedService("nfc:sys", std::make_shared<NFC_SYS>(system)); 227 server_manager->RegisterNamedService("nfc:sys", std::make_shared<NFC_SYS>(system));
228
224 ServerManager::RunServer(std::move(server_manager)); 229 ServerManager::RunServer(std::move(server_manager));
225} 230}
226 231
diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp
deleted file mode 100644
index 47bc1a05d..000000000
--- a/src/core/hle/service/nfc/nfc_device.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/input.h"
5#include "common/logging/log.h"
6#include "core/core.h"
7#include "core/hid/emulated_controller.h"
8#include "core/hid/hid_core.h"
9#include "core/hid/hid_types.h"
10#include "core/hle/kernel/k_event.h"
11#include "core/hle/service/ipc_helpers.h"
12#include "core/hle/service/nfc/nfc_device.h"
13#include "core/hle/service/nfc/nfc_result.h"
14
15namespace Service::NFC {
16NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
17 KernelHelpers::ServiceContext& service_context_,
18 Kernel::KEvent* availability_change_event_)
19 : npad_id{npad_id_}, system{system_}, service_context{service_context_},
20 availability_change_event{availability_change_event_} {
21 activate_event = service_context.CreateEvent("IUser:NFCActivateEvent");
22 deactivate_event = service_context.CreateEvent("IUser:NFCDeactivateEvent");
23 npad_device = system.HIDCore().GetEmulatedController(npad_id);
24
25 Core::HID::ControllerUpdateCallback engine_callback{
26 .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); },
27 .is_npad_service = false,
28 };
29 is_controller_set = true;
30 callback_key = npad_device->SetCallback(engine_callback);
31}
32
33NfcDevice::~NfcDevice() {
34 activate_event->Close();
35 deactivate_event->Close();
36 if (!is_controller_set) {
37 return;
38 }
39 npad_device->DeleteCallback(callback_key);
40 is_controller_set = false;
41};
42
43void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
44 if (!is_initalized) {
45 return;
46 }
47
48 if (type == Core::HID::ControllerTriggerType::Connected) {
49 Initialize();
50 availability_change_event->Signal();
51 return;
52 }
53
54 if (type == Core::HID::ControllerTriggerType::Disconnected) {
55 device_state = NFP::DeviceState::Unavailable;
56 availability_change_event->Signal();
57 return;
58 }
59
60 if (type != Core::HID::ControllerTriggerType::Nfc) {
61 return;
62 }
63
64 if (!npad_device->IsConnected()) {
65 return;
66 }
67
68 const auto nfc_status = npad_device->GetNfc();
69 switch (nfc_status.state) {
70 case Common::Input::NfcState::NewAmiibo:
71 LoadNfcTag(nfc_status.data);
72 break;
73 case Common::Input::NfcState::AmiiboRemoved:
74 if (device_state != NFP::DeviceState::SearchingForTag) {
75 CloseNfcTag();
76 }
77 break;
78 default:
79 break;
80 }
81}
82
83bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
84 if (device_state != NFP::DeviceState::SearchingForTag) {
85 LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state);
86 return false;
87 }
88
89 if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {
90 LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());
91 return false;
92 }
93
94 tag_data.resize(data.size());
95 memcpy(tag_data.data(), data.data(), data.size());
96 memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
97
98 device_state = NFP::DeviceState::TagFound;
99 deactivate_event->GetReadableEvent().Clear();
100 activate_event->Signal();
101 return true;
102}
103
104void NfcDevice::CloseNfcTag() {
105 LOG_INFO(Service_NFC, "Remove nfc tag");
106
107 device_state = NFP::DeviceState::TagRemoved;
108 encrypted_tag_data = {};
109 activate_event->GetReadableEvent().Clear();
110 deactivate_event->Signal();
111}
112
113Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const {
114 return activate_event->GetReadableEvent();
115}
116
117Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const {
118 return deactivate_event->GetReadableEvent();
119}
120
121void NfcDevice::Initialize() {
122 device_state =
123 npad_device->HasNfc() ? NFP::DeviceState::Initialized : NFP::DeviceState::Unavailable;
124 encrypted_tag_data = {};
125 is_initalized = true;
126}
127
128void NfcDevice::Finalize() {
129 if (device_state == NFP::DeviceState::SearchingForTag ||
130 device_state == NFP::DeviceState::TagRemoved) {
131 StopDetection();
132 }
133 device_state = NFP::DeviceState::Unavailable;
134 is_initalized = false;
135}
136
137Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) {
138 if (device_state != NFP::DeviceState::Initialized &&
139 device_state != NFP::DeviceState::TagRemoved) {
140 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
141 return WrongDeviceState;
142 }
143
144 if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
145 Common::Input::PollingMode::NFC) !=
146 Common::Input::DriverResult::Success) {
147 LOG_ERROR(Service_NFC, "Nfc not supported");
148 return NfcDisabled;
149 }
150
151 device_state = NFP::DeviceState::SearchingForTag;
152 allowed_protocols = allowed_protocol;
153 return ResultSuccess;
154}
155
156Result NfcDevice::StopDetection() {
157 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
158 Common::Input::PollingMode::Active);
159
160 if (device_state == NFP::DeviceState::Initialized) {
161 return ResultSuccess;
162 }
163
164 if (device_state == NFP::DeviceState::TagFound ||
165 device_state == NFP::DeviceState::TagMounted) {
166 CloseNfcTag();
167 return ResultSuccess;
168 }
169 if (device_state == NFP::DeviceState::SearchingForTag ||
170 device_state == NFP::DeviceState::TagRemoved) {
171 device_state = NFP::DeviceState::Initialized;
172 return ResultSuccess;
173 }
174
175 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
176 return WrongDeviceState;
177}
178
179Result NfcDevice::Flush() {
180 if (device_state != NFP::DeviceState::TagFound &&
181 device_state != NFP::DeviceState::TagMounted) {
182 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
183 if (device_state == NFP::DeviceState::TagRemoved) {
184 return TagRemoved;
185 }
186 return WrongDeviceState;
187 }
188
189 if (!npad_device->WriteNfc(tag_data)) {
190 LOG_ERROR(Service_NFP, "Error writing to file");
191 return MifareReadError;
192 }
193
194 return ResultSuccess;
195}
196
197Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
198 if (device_state != NFP::DeviceState::TagFound &&
199 device_state != NFP::DeviceState::TagMounted) {
200 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
201 if (device_state == NFP::DeviceState::TagRemoved) {
202 return TagRemoved;
203 }
204 return WrongDeviceState;
205 }
206
207 if (is_mifare) {
208 tag_info = {
209 .uuid = encrypted_tag_data.uuid.uid,
210 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
211 .protocol = NFP::TagProtocol::TypeA,
212 .tag_type = NFP::TagType::Type4,
213 };
214 return ResultSuccess;
215 }
216
217 // Protocol and tag type may change here
218 tag_info = {
219 .uuid = encrypted_tag_data.uuid.uid,
220 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
221 .protocol = NFP::TagProtocol::TypeA,
222 .tag_type = NFP::TagType::Type2,
223 };
224
225 return ResultSuccess;
226}
227
228Result NfcDevice::MifareRead(const NFP::MifareReadBlockParameter& parameter,
229 NFP::MifareReadBlockData& read_block_data) {
230 const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock);
231 read_block_data.sector_number = parameter.sector_number;
232
233 if (device_state != NFP::DeviceState::TagFound &&
234 device_state != NFP::DeviceState::TagMounted) {
235 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
236 if (device_state == NFP::DeviceState::TagRemoved) {
237 return TagRemoved;
238 }
239 return WrongDeviceState;
240 }
241
242 if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) {
243 return MifareReadError;
244 }
245
246 // TODO: Use parameter.sector_key to read encrypted data
247 memcpy(read_block_data.data.data(), tag_data.data() + sector_index, sizeof(NFP::DataBlock));
248
249 return ResultSuccess;
250}
251
252Result NfcDevice::MifareWrite(const NFP::MifareWriteBlockParameter& parameter) {
253 const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock);
254
255 if (device_state != NFP::DeviceState::TagFound &&
256 device_state != NFP::DeviceState::TagMounted) {
257 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
258 if (device_state == NFP::DeviceState::TagRemoved) {
259 return TagRemoved;
260 }
261 return WrongDeviceState;
262 }
263
264 if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) {
265 return MifareReadError;
266 }
267
268 // TODO: Use parameter.sector_key to encrypt the data
269 memcpy(tag_data.data() + sector_index, parameter.data.data(), sizeof(NFP::DataBlock));
270
271 return ResultSuccess;
272}
273
274u64 NfcDevice::GetHandle() const {
275 // Generate a handle based of the npad id
276 return static_cast<u64>(npad_id);
277}
278
279NFP::DeviceState NfcDevice::GetCurrentState() const {
280 return device_state;
281}
282
283Core::HID::NpadIdType NfcDevice::GetNpadId() const {
284 return npad_id;
285}
286
287} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h
deleted file mode 100644
index ea63f0537..000000000
--- a/src/core/hle/service/nfc/nfc_device.h
+++ /dev/null
@@ -1,78 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/nfp/nfp_types.h"
9#include "core/hle/service/service.h"
10
11namespace Kernel {
12class KEvent;
13class KReadableEvent;
14} // namespace Kernel
15
16namespace Core {
17class System;
18} // namespace Core
19
20namespace Core::HID {
21class EmulatedController;
22enum class ControllerTriggerType;
23enum class NpadIdType : u32;
24} // namespace Core::HID
25
26namespace Service::NFC {
27class NfcDevice {
28public:
29 NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
30 KernelHelpers::ServiceContext& service_context_,
31 Kernel::KEvent* availability_change_event_);
32 ~NfcDevice();
33
34 void Initialize();
35 void Finalize();
36
37 Result StartDetection(NFP::TagProtocol allowed_protocol);
38 Result StopDetection();
39 Result Flush();
40
41 Result GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const;
42
43 Result MifareRead(const NFP::MifareReadBlockParameter& parameter,
44 NFP::MifareReadBlockData& read_block_data);
45
46 Result MifareWrite(const NFP::MifareWriteBlockParameter& parameter);
47
48 u64 GetHandle() const;
49 NFP::DeviceState GetCurrentState() const;
50 Core::HID::NpadIdType GetNpadId() const;
51
52 Kernel::KReadableEvent& GetActivateEvent() const;
53 Kernel::KReadableEvent& GetDeactivateEvent() const;
54
55private:
56 void NpadUpdate(Core::HID::ControllerTriggerType type);
57 bool LoadNfcTag(std::span<const u8> data);
58 void CloseNfcTag();
59
60 bool is_controller_set{};
61 int callback_key;
62 const Core::HID::NpadIdType npad_id;
63 Core::System& system;
64 Core::HID::EmulatedController* npad_device = nullptr;
65 KernelHelpers::ServiceContext& service_context;
66 Kernel::KEvent* activate_event = nullptr;
67 Kernel::KEvent* deactivate_event = nullptr;
68 Kernel::KEvent* availability_change_event = nullptr;
69
70 bool is_initalized{};
71 NFP::TagProtocol allowed_protocols{};
72 NFP::DeviceState device_state{NFP::DeviceState::Unavailable};
73
74 NFP::EncryptedNTAG215File encrypted_tag_data{};
75 std::vector<u8> tag_data{};
76};
77
78} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp
index be96d0cbc..0fa29d398 100644
--- a/src/core/hle/service/nfc/nfc_interface.cpp
+++ b/src/core/hle/service/nfc/nfc_interface.cpp
@@ -6,55 +6,56 @@
6#include "core/hid/hid_types.h" 6#include "core/hid/hid_types.h"
7#include "core/hle/kernel/k_event.h" 7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nfc/nfc_device.h" 9#include "core/hle/service/nfc/common/device.h"
10#include "core/hle/service/nfc/common/device_manager.h"
11#include "core/hle/service/nfc/mifare_result.h"
12#include "core/hle/service/nfc/mifare_types.h"
10#include "core/hle/service/nfc/nfc_interface.h" 13#include "core/hle/service/nfc/nfc_interface.h"
11#include "core/hle/service/nfc/nfc_result.h" 14#include "core/hle/service/nfc/nfc_result.h"
15#include "core/hle/service/nfc/nfc_types.h"
16#include "core/hle/service/nfp/nfp_result.h"
12#include "core/hle/service/time/clock_types.h" 17#include "core/hle/service/time/clock_types.h"
13 18
14namespace Service::NFC { 19namespace Service::NFC {
15 20
16Interface::Interface(Core::System& system_, const char* name) 21NfcInterface::NfcInterface(Core::System& system_, const char* name, BackendType service_backend)
17 : ServiceFramework{system_, name}, service_context{system_, service_name} { 22 : ServiceFramework{system_, name}, service_context{system_, service_name},
18 availability_change_event = service_context.CreateEvent("Interface:AvailabilityChangeEvent"); 23 backend_type{service_backend} {}
19 24
20 for (u32 device_index = 0; device_index < 10; device_index++) { 25NfcInterface ::~NfcInterface() = default;
21 devices[device_index] =
22 std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
23 service_context, availability_change_event);
24 }
25}
26 26
27Interface ::~Interface() { 27void NfcInterface::Initialize(HLERequestContext& ctx) {
28 availability_change_event->Close();
29}
30
31void Interface::Initialize(HLERequestContext& ctx) {
32 LOG_INFO(Service_NFC, "called"); 28 LOG_INFO(Service_NFC, "called");
33 29
34 state = State::Initialized; 30 auto manager = GetManager();
31 auto result = manager->Initialize();
35 32
36 for (auto& device : devices) { 33 if (result.IsSuccess()) {
37 device->Initialize(); 34 state = State::Initialized;
35 } else {
36 manager->Finalize();
38 } 37 }
39 38
40 IPC::ResponseBuilder rb{ctx, 2, 0}; 39 IPC::ResponseBuilder rb{ctx, 2, 0};
41 rb.Push(ResultSuccess); 40 rb.Push(result);
42} 41}
43 42
44void Interface::Finalize(HLERequestContext& ctx) { 43void NfcInterface::Finalize(HLERequestContext& ctx) {
45 LOG_INFO(Service_NFC, "called"); 44 LOG_INFO(Service_NFC, "called");
46 45
47 state = State::NonInitialized; 46 if (state != State::NonInitialized) {
48 47 if (GetBackendType() != BackendType::None) {
49 for (auto& device : devices) { 48 GetManager()->Finalize();
50 device->Finalize(); 49 }
50 device_manager = nullptr;
51 state = State::NonInitialized;
51 } 52 }
52 53
53 IPC::ResponseBuilder rb{ctx, 2}; 54 IPC::ResponseBuilder rb{ctx, 2};
54 rb.Push(ResultSuccess); 55 rb.Push(ResultSuccess);
55} 56}
56 57
57void Interface::GetState(HLERequestContext& ctx) { 58void NfcInterface::GetState(HLERequestContext& ctx) {
58 LOG_DEBUG(Service_NFC, "called"); 59 LOG_DEBUG(Service_NFC, "called");
59 60
60 IPC::ResponseBuilder rb{ctx, 3}; 61 IPC::ResponseBuilder rb{ctx, 3};
@@ -62,50 +63,28 @@ void Interface::GetState(HLERequestContext& ctx) {
62 rb.PushEnum(state); 63 rb.PushEnum(state);
63} 64}
64 65
65void Interface::IsNfcEnabled(HLERequestContext& ctx) { 66void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) {
66 LOG_DEBUG(Service_NFC, "called"); 67 LOG_DEBUG(Service_NFC, "called");
67 68
69 // TODO: This calls nn::settings::detail::GetNfcEnableFlag
70 const bool is_enabled = true;
71
68 IPC::ResponseBuilder rb{ctx, 3}; 72 IPC::ResponseBuilder rb{ctx, 3};
69 rb.Push(ResultSuccess); 73 rb.Push(ResultSuccess);
70 rb.Push(state != State::NonInitialized); 74 rb.Push(is_enabled);
71} 75}
72 76
73void Interface::ListDevices(HLERequestContext& ctx) { 77void NfcInterface::ListDevices(HLERequestContext& ctx) {
74 LOG_DEBUG(Service_NFC, "called");
75
76 if (state == State::NonInitialized) {
77 IPC::ResponseBuilder rb{ctx, 2};
78 rb.Push(NfcDisabled);
79 return;
80 }
81
82 if (!ctx.CanWriteBuffer()) {
83 IPC::ResponseBuilder rb{ctx, 2};
84 rb.Push(InvalidArgument);
85 return;
86 }
87
88 if (ctx.GetWriteBufferSize() == 0) {
89 IPC::ResponseBuilder rb{ctx, 2};
90 rb.Push(InvalidArgument);
91 return;
92 }
93
94 std::vector<u64> nfp_devices; 78 std::vector<u64> nfp_devices;
95 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); 79 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
80 LOG_DEBUG(Service_NFC, "called");
96 81
97 for (auto& device : devices) { 82 auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices);
98 if (nfp_devices.size() >= max_allowed_devices) { 83 result = TranslateResultToServiceError(result);
99 continue;
100 }
101 if (device->GetCurrentState() != NFP::DeviceState::Unavailable) {
102 nfp_devices.push_back(device->GetHandle());
103 }
104 }
105 84
106 if (nfp_devices.empty()) { 85 if (result.IsError()) {
107 IPC::ResponseBuilder rb{ctx, 2}; 86 IPC::ResponseBuilder rb{ctx, 2};
108 rb.Push(DeviceNotFound); 87 rb.Push(result);
109 return; 88 return;
110 } 89 }
111 90
@@ -116,210 +95,177 @@ void Interface::ListDevices(HLERequestContext& ctx) {
116 rb.Push(static_cast<s32>(nfp_devices.size())); 95 rb.Push(static_cast<s32>(nfp_devices.size()));
117} 96}
118 97
119void Interface::GetDeviceState(HLERequestContext& ctx) { 98void NfcInterface::GetDeviceState(HLERequestContext& ctx) {
120 IPC::RequestParser rp{ctx}; 99 IPC::RequestParser rp{ctx};
121 const auto device_handle{rp.Pop<u64>()}; 100 const auto device_handle{rp.Pop<u64>()};
122 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); 101 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
123 102
124 auto device = GetNfcDevice(device_handle); 103 const auto device_state = GetManager()->GetDeviceState(device_handle);
125 104
126 if (!device.has_value()) { 105 if (device_state > DeviceState::Finalized) {
127 IPC::ResponseBuilder rb{ctx, 2}; 106 ASSERT_MSG(false, "Invalid device state");
128 rb.Push(DeviceNotFound);
129 return;
130 } 107 }
131 108
132 IPC::ResponseBuilder rb{ctx, 3}; 109 IPC::ResponseBuilder rb{ctx, 3};
133 rb.Push(ResultSuccess); 110 rb.Push(ResultSuccess);
134 rb.PushEnum(device.value()->GetCurrentState()); 111 rb.PushEnum(device_state);
135} 112}
136 113
137void Interface::GetNpadId(HLERequestContext& ctx) { 114void NfcInterface::GetNpadId(HLERequestContext& ctx) {
138 IPC::RequestParser rp{ctx}; 115 IPC::RequestParser rp{ctx};
139 const auto device_handle{rp.Pop<u64>()}; 116 const auto device_handle{rp.Pop<u64>()};
140 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); 117 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
141 118
142 if (state == State::NonInitialized) { 119 Core::HID::NpadIdType npad_id{};
143 IPC::ResponseBuilder rb{ctx, 2}; 120 auto result = GetManager()->GetNpadId(device_handle, npad_id);
144 rb.Push(NfcDisabled); 121 result = TranslateResultToServiceError(result);
145 return;
146 }
147
148 auto device = GetNfcDevice(device_handle);
149 122
150 if (!device.has_value()) { 123 if (result.IsError()) {
151 IPC::ResponseBuilder rb{ctx, 2}; 124 IPC::ResponseBuilder rb{ctx, 2};
152 rb.Push(DeviceNotFound); 125 rb.Push(result);
153 return; 126 return;
154 } 127 }
155 128
156 IPC::ResponseBuilder rb{ctx, 3}; 129 IPC::ResponseBuilder rb{ctx, 3};
157 rb.Push(ResultSuccess); 130 rb.Push(ResultSuccess);
158 rb.PushEnum(device.value()->GetNpadId()); 131 rb.PushEnum(npad_id);
159} 132}
160 133
161void Interface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { 134void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
162 LOG_INFO(Service_NFC, "called"); 135 LOG_INFO(Service_NFC, "called");
163 136
164 if (state == State::NonInitialized) {
165 IPC::ResponseBuilder rb{ctx, 2};
166 rb.Push(NfcDisabled);
167 return;
168 }
169
170 IPC::ResponseBuilder rb{ctx, 2, 1}; 137 IPC::ResponseBuilder rb{ctx, 2, 1};
171 rb.Push(ResultSuccess); 138 rb.Push(ResultSuccess);
172 rb.PushCopyObjects(availability_change_event->GetReadableEvent()); 139 rb.PushCopyObjects(GetManager()->AttachAvailabilityChangeEvent());
173} 140}
174 141
175void Interface::StartDetection(HLERequestContext& ctx) { 142void NfcInterface::StartDetection(HLERequestContext& ctx) {
176 IPC::RequestParser rp{ctx}; 143 IPC::RequestParser rp{ctx};
177 const auto device_handle{rp.Pop<u64>()}; 144 const auto device_handle{rp.Pop<u64>()};
178 const auto nfp_protocol{rp.PopEnum<NFP::TagProtocol>()}; 145 const auto tag_protocol{rp.PopEnum<NfcProtocol>()};
179 LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); 146 LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol);
180 147
181 if (state == State::NonInitialized) { 148 auto result = GetManager()->StartDetection(device_handle, tag_protocol);
182 IPC::ResponseBuilder rb{ctx, 2}; 149 result = TranslateResultToServiceError(result);
183 rb.Push(NfcDisabled);
184 return;
185 }
186
187 auto device = GetNfcDevice(device_handle);
188 150
189 if (!device.has_value()) {
190 IPC::ResponseBuilder rb{ctx, 2};
191 rb.Push(DeviceNotFound);
192 return;
193 }
194
195 const auto result = device.value()->StartDetection(nfp_protocol);
196 IPC::ResponseBuilder rb{ctx, 2}; 151 IPC::ResponseBuilder rb{ctx, 2};
197 rb.Push(result); 152 rb.Push(result);
198} 153}
199 154
200void Interface::StopDetection(HLERequestContext& ctx) { 155void NfcInterface::StopDetection(HLERequestContext& ctx) {
201 IPC::RequestParser rp{ctx}; 156 IPC::RequestParser rp{ctx};
202 const auto device_handle{rp.Pop<u64>()}; 157 const auto device_handle{rp.Pop<u64>()};
203 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); 158 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
204 159
205 if (state == State::NonInitialized) { 160 auto result = GetManager()->StopDetection(device_handle);
206 IPC::ResponseBuilder rb{ctx, 2}; 161 result = TranslateResultToServiceError(result);
207 rb.Push(NfcDisabled);
208 return;
209 }
210
211 auto device = GetNfcDevice(device_handle);
212
213 if (!device.has_value()) {
214 IPC::ResponseBuilder rb{ctx, 2};
215 rb.Push(DeviceNotFound);
216 return;
217 }
218 162
219 const auto result = device.value()->StopDetection();
220 IPC::ResponseBuilder rb{ctx, 2}; 163 IPC::ResponseBuilder rb{ctx, 2};
221 rb.Push(result); 164 rb.Push(result);
222} 165}
223 166
224void Interface::GetTagInfo(HLERequestContext& ctx) { 167void NfcInterface::GetTagInfo(HLERequestContext& ctx) {
225 IPC::RequestParser rp{ctx}; 168 IPC::RequestParser rp{ctx};
226 const auto device_handle{rp.Pop<u64>()}; 169 const auto device_handle{rp.Pop<u64>()};
227 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); 170 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
228 171
229 if (state == State::NonInitialized) { 172 TagInfo tag_info{};
230 IPC::ResponseBuilder rb{ctx, 2}; 173 auto result =
231 rb.Push(NfcDisabled); 174 GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare);
232 return; 175 result = TranslateResultToServiceError(result);
233 }
234 176
235 auto device = GetNfcDevice(device_handle); 177 if (result.IsSuccess()) {
236 178 ctx.WriteBuffer(tag_info);
237 if (!device.has_value()) {
238 IPC::ResponseBuilder rb{ctx, 2};
239 rb.Push(DeviceNotFound);
240 return;
241 } 179 }
242 180
243 NFP::TagInfo tag_info{};
244 const auto result = device.value()->GetTagInfo(tag_info, false);
245 ctx.WriteBuffer(tag_info);
246 IPC::ResponseBuilder rb{ctx, 2}; 181 IPC::ResponseBuilder rb{ctx, 2};
247 rb.Push(result); 182 rb.Push(result);
248} 183}
249 184
250void Interface::AttachActivateEvent(HLERequestContext& ctx) { 185void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
251 IPC::RequestParser rp{ctx}; 186 IPC::RequestParser rp{ctx};
252 const auto device_handle{rp.Pop<u64>()}; 187 const auto device_handle{rp.Pop<u64>()};
253 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); 188 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
254 189
255 if (state == State::NonInitialized) { 190 IPC::ResponseBuilder rb{ctx, 2, 1};
256 IPC::ResponseBuilder rb{ctx, 2}; 191 rb.Push(ResultSuccess);
257 rb.Push(NfcDisabled); 192 rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle));
258 return; 193}
259 }
260
261 auto device = GetNfcDevice(device_handle);
262 194
263 if (!device.has_value()) { 195void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
264 IPC::ResponseBuilder rb{ctx, 2}; 196 IPC::RequestParser rp{ctx};
265 rb.Push(DeviceNotFound); 197 const auto device_handle{rp.Pop<u64>()};
266 return; 198 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
267 }
268 199
269 IPC::ResponseBuilder rb{ctx, 2, 1}; 200 IPC::ResponseBuilder rb{ctx, 2, 1};
270 rb.Push(ResultSuccess); 201 rb.Push(ResultSuccess);
271 rb.PushCopyObjects(device.value()->GetActivateEvent()); 202 rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle));
272} 203}
273 204
274void Interface::AttachDeactivateEvent(HLERequestContext& ctx) { 205void NfcInterface::ReadMifare(HLERequestContext& ctx) {
275 IPC::RequestParser rp{ctx}; 206 IPC::RequestParser rp{ctx};
276 const auto device_handle{rp.Pop<u64>()}; 207 const auto device_handle{rp.Pop<u64>()};
277 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); 208 const auto buffer{ctx.ReadBuffer()};
209 const auto number_of_commands{ctx.GetReadBufferNumElements<MifareReadBlockParameter>()};
210 std::vector<MifareReadBlockParameter> read_commands(number_of_commands);
278 211
279 if (state == State::NonInitialized) { 212 memcpy(read_commands.data(), buffer.data(),
280 IPC::ResponseBuilder rb{ctx, 2}; 213 number_of_commands * sizeof(MifareReadBlockParameter));
281 rb.Push(NfcDisabled);
282 return;
283 }
284 214
285 auto device = GetNfcDevice(device_handle); 215 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
216 device_handle, number_of_commands);
286 217
287 if (!device.has_value()) { 218 std::vector<MifareReadBlockData> out_data(number_of_commands);
288 IPC::ResponseBuilder rb{ctx, 2}; 219 auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data);
289 rb.Push(DeviceNotFound); 220 result = TranslateResultToServiceError(result);
290 return; 221
222 if (result.IsSuccess()) {
223 ctx.WriteBuffer(out_data);
291 } 224 }
292 225
293 IPC::ResponseBuilder rb{ctx, 2, 1}; 226 IPC::ResponseBuilder rb{ctx, 2};
294 rb.Push(ResultSuccess); 227 rb.Push(result);
295 rb.PushCopyObjects(device.value()->GetDeactivateEvent()); 228}
229
230void NfcInterface::WriteMifare(HLERequestContext& ctx) {
231 IPC::RequestParser rp{ctx};
232 const auto device_handle{rp.Pop<u64>()};
233 const auto buffer{ctx.ReadBuffer()};
234 const auto number_of_commands{ctx.GetReadBufferNumElements<MifareWriteBlockParameter>()};
235 std::vector<MifareWriteBlockParameter> write_commands(number_of_commands);
236
237 memcpy(write_commands.data(), buffer.data(),
238 number_of_commands * sizeof(MifareWriteBlockParameter));
239
240 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
241 device_handle, number_of_commands);
242
243 auto result = GetManager()->WriteMifare(device_handle, write_commands);
244 result = TranslateResultToServiceError(result);
245
246 IPC::ResponseBuilder rb{ctx, 2};
247 rb.Push(result);
296} 248}
297 249
298void Interface::SendCommandByPassThrough(HLERequestContext& ctx) { 250void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) {
299 IPC::RequestParser rp{ctx}; 251 IPC::RequestParser rp{ctx};
300 const auto device_handle{rp.Pop<u64>()}; 252 const auto device_handle{rp.Pop<u64>()};
301 const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()}; 253 const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
302 const auto command_data{ctx.ReadBuffer()}; 254 const auto command_data{ctx.ReadBuffer()};
303
304 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", 255 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
305 device_handle, timeout.ToSeconds(), command_data.size()); 256 device_handle, timeout.ToSeconds(), command_data.size());
306 257
307 if (state == State::NonInitialized) { 258 std::vector<u8> out_data(1);
308 IPC::ResponseBuilder rb{ctx, 2}; 259 auto result =
309 rb.Push(NfcDisabled); 260 GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data);
310 return; 261 result = TranslateResultToServiceError(result);
311 }
312
313 auto device = GetNfcDevice(device_handle);
314 262
315 if (!device.has_value()) { 263 if (result.IsError()) {
316 IPC::ResponseBuilder rb{ctx, 2}; 264 IPC::ResponseBuilder rb{ctx, 2};
317 rb.Push(DeviceNotFound); 265 rb.Push(result);
318 return; 266 return;
319 } 267 }
320 268
321 std::vector<u8> out_data(1);
322 // TODO: Request data from nfc device
323 ctx.WriteBuffer(out_data); 269 ctx.WriteBuffer(out_data);
324 270
325 IPC::ResponseBuilder rb{ctx, 3}; 271 IPC::ResponseBuilder rb{ctx, 3};
@@ -327,13 +273,110 @@ void Interface::SendCommandByPassThrough(HLERequestContext& ctx) {
327 rb.Push(static_cast<u32>(out_data.size())); 273 rb.Push(static_cast<u32>(out_data.size()));
328} 274}
329 275
330std::optional<std::shared_ptr<NfcDevice>> Interface::GetNfcDevice(u64 handle) { 276std::shared_ptr<DeviceManager> NfcInterface::GetManager() {
331 for (auto& device : devices) { 277 if (device_manager == nullptr) {
332 if (device->GetHandle() == handle) { 278 device_manager = std::make_shared<DeviceManager>(system, service_context);
333 return device; 279 }
280 return device_manager;
281}
282
283BackendType NfcInterface::GetBackendType() const {
284 return backend_type;
285}
286
287Result NfcInterface::TranslateResultToServiceError(Result result) const {
288 const auto backend = GetBackendType();
289
290 if (result.IsSuccess()) {
291 return result;
292 }
293
294 if (result.module != ErrorModule::NFC) {
295 return result;
296 }
297
298 switch (backend) {
299 case BackendType::Mifare:
300 return TranslateResultToNfp(result);
301 case BackendType::Nfp: {
302 return TranslateResultToNfp(result);
303 }
304 default:
305 if (result != ResultUnknown216) {
306 return result;
334 } 307 }
308 return ResultUnknown74;
309 }
310}
311
312Result NfcInterface::TranslateResultToNfp(Result result) const {
313 if (result == ResultDeviceNotFound) {
314 return NFP::ResultDeviceNotFound;
315 }
316 if (result == ResultInvalidArgument) {
317 return NFP::ResultInvalidArgument;
318 }
319 if (result == ResultWrongApplicationAreaSize) {
320 return NFP::ResultWrongApplicationAreaSize;
321 }
322 if (result == ResultWrongDeviceState) {
323 return NFP::ResultWrongDeviceState;
324 }
325 if (result == ResultUnknown74) {
326 return NFP::ResultUnknown74;
327 }
328 if (result == ResultNfcDisabled) {
329 return NFP::ResultNfcDisabled;
330 }
331 if (result == ResultNfcNotInitialized) {
332 return NFP::ResultNfcDisabled;
333 }
334 if (result == ResultWriteAmiiboFailed) {
335 return NFP::ResultWriteAmiiboFailed;
336 }
337 if (result == ResultTagRemoved) {
338 return NFP::ResultTagRemoved;
339 }
340 if (result == ResultRegistrationIsNotInitialized) {
341 return NFP::ResultRegistrationIsNotInitialized;
342 }
343 if (result == ResultApplicationAreaIsNotInitialized) {
344 return NFP::ResultApplicationAreaIsNotInitialized;
345 }
346 if (result == ResultCorruptedData) {
347 return NFP::ResultCorruptedData;
348 }
349 if (result == ResultWrongApplicationAreaId) {
350 return NFP::ResultWrongApplicationAreaId;
351 }
352 if (result == ResultApplicationAreaExist) {
353 return NFP::ResultApplicationAreaExist;
354 }
355 if (result == ResultNotAnAmiibo) {
356 return NFP::ResultNotAnAmiibo;
357 }
358 LOG_WARNING(Service_NFC, "Result conversion not handled");
359 return result;
360}
361
362Result NfcInterface::TranslateResultToMifare(Result result) const {
363 if (result == ResultDeviceNotFound) {
364 return Mifare::ResultDeviceNotFound;
365 }
366 if (result == ResultInvalidArgument) {
367 return Mifare::ResultInvalidArgument;
368 }
369 if (result == ResultWrongDeviceState) {
370 return Mifare::ResultWrongDeviceState;
371 }
372 if (result == ResultNfcDisabled) {
373 return Mifare::ResultNfcDisabled;
374 }
375 if (result == ResultTagRemoved) {
376 return Mifare::ResultTagRemoved;
335 } 377 }
336 return std::nullopt; 378 LOG_WARNING(Service_NFC, "Result conversion not handled");
379 return result;
337} 380}
338 381
339} // namespace Service::NFC 382} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_interface.h b/src/core/hle/service/nfc/nfc_interface.h
index 8c1bf5a59..08be174d8 100644
--- a/src/core/hle/service/nfc/nfc_interface.h
+++ b/src/core/hle/service/nfc/nfc_interface.h
@@ -3,20 +3,17 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <array>
7#include <memory>
8#include <optional>
9
10#include "core/hle/service/kernel_helpers.h" 6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/nfc/nfc_types.h"
11#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
12 9
13namespace Service::NFC { 10namespace Service::NFC {
14class NfcDevice; 11class DeviceManager;
15 12
16class Interface : public ServiceFramework<Interface> { 13class NfcInterface : public ServiceFramework<NfcInterface> {
17public: 14public:
18 explicit Interface(Core::System& system_, const char* name); 15 explicit NfcInterface(Core::System& system_, const char* name, BackendType service_backend);
19 ~Interface(); 16 ~NfcInterface();
20 17
21 void Initialize(HLERequestContext& ctx); 18 void Initialize(HLERequestContext& ctx);
22 void Finalize(HLERequestContext& ctx); 19 void Finalize(HLERequestContext& ctx);
@@ -31,22 +28,22 @@ public:
31 void GetTagInfo(HLERequestContext& ctx); 28 void GetTagInfo(HLERequestContext& ctx);
32 void AttachActivateEvent(HLERequestContext& ctx); 29 void AttachActivateEvent(HLERequestContext& ctx);
33 void AttachDeactivateEvent(HLERequestContext& ctx); 30 void AttachDeactivateEvent(HLERequestContext& ctx);
31 void ReadMifare(HLERequestContext& ctx);
32 void WriteMifare(HLERequestContext& ctx);
34 void SendCommandByPassThrough(HLERequestContext& ctx); 33 void SendCommandByPassThrough(HLERequestContext& ctx);
35 34
36private: 35protected:
37 enum class State : u32 { 36 std::shared_ptr<DeviceManager> GetManager();
38 NonInitialized, 37 BackendType GetBackendType() const;
39 Initialized, 38 Result TranslateResultToServiceError(Result result) const;
40 }; 39 Result TranslateResultToNfp(Result result) const;
41 40 Result TranslateResultToMifare(Result result) const;
42 std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
43 41
44 KernelHelpers::ServiceContext service_context; 42 KernelHelpers::ServiceContext service_context;
45 43
46 std::array<std::shared_ptr<NfcDevice>, 10> devices{}; 44 BackendType backend_type;
47
48 State state{State::NonInitialized}; 45 State state{State::NonInitialized};
49 Kernel::KEvent* availability_change_event; 46 std::shared_ptr<DeviceManager> device_manager = nullptr;
50}; 47};
51 48
52} // namespace Service::NFC 49} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h
index 146b8ba61..917d79ef8 100644
--- a/src/core/hle/service/nfc/nfc_result.h
+++ b/src/core/hle/service/nfc/nfc_result.h
@@ -1,5 +1,5 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
5 5
@@ -7,17 +7,22 @@
7 7
8namespace Service::NFC { 8namespace Service::NFC {
9 9
10constexpr Result DeviceNotFound(ErrorModule::NFC, 64); 10constexpr Result ResultDeviceNotFound(ErrorModule::NFC, 64);
11constexpr Result InvalidArgument(ErrorModule::NFC, 65); 11constexpr Result ResultInvalidArgument(ErrorModule::NFC, 65);
12constexpr Result WrongDeviceState(ErrorModule::NFC, 73); 12constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFP, 68);
13constexpr Result NfcDisabled(ErrorModule::NFC, 80); 13constexpr Result ResultWrongDeviceState(ErrorModule::NFC, 73);
14constexpr Result TagRemoved(ErrorModule::NFC, 97); 14constexpr Result ResultUnknown74(ErrorModule::NFC, 74);
15 15constexpr Result ResultUnknown76(ErrorModule::NFC, 76);
16constexpr Result MifareDeviceNotFound(ErrorModule::NFCMifare, 64); 16constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77);
17constexpr Result MifareInvalidArgument(ErrorModule::NFCMifare, 65); 17constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80);
18constexpr Result MifareWrongDeviceState(ErrorModule::NFCMifare, 73); 18constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88);
19constexpr Result MifareNfcDisabled(ErrorModule::NFCMifare, 80); 19constexpr Result ResultTagRemoved(ErrorModule::NFC, 97);
20constexpr Result MifareTagRemoved(ErrorModule::NFCMifare, 97); 20constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120);
21constexpr Result MifareReadError(ErrorModule::NFCMifare, 288); 21constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
22constexpr Result ResultCorruptedData(ErrorModule::NFP, 144);
23constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152);
24constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168);
25constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178);
26constexpr Result ResultUnknown216(ErrorModule::NFC, 216);
22 27
23} // namespace Service::NFC 28} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_types.h b/src/core/hle/service/nfc/nfc_types.h
new file mode 100644
index 000000000..c7ebd1fdb
--- /dev/null
+++ b/src/core/hle/service/nfc/nfc_types.h
@@ -0,0 +1,90 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10
11namespace Service::NFC {
12enum class BackendType : u32 {
13 None,
14 Nfc,
15 Nfp,
16 Mifare,
17};
18
19// This is nn::nfc::DeviceState
20enum class DeviceState : u32 {
21 Initialized,
22 SearchingForTag,
23 TagFound,
24 TagRemoved,
25 TagMounted,
26 Unavailable,
27 Finalized,
28};
29
30// This is nn::nfc::State
31enum class State : u32 {
32 NonInitialized,
33 Initialized,
34};
35
36// This is nn::nfc::TagType
37enum class TagType : u32 {
38 None,
39 Type1, // ISO14443A RW 96-2k bytes 106kbit/s
40 Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
41 Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s
42 Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
43 Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
44};
45
46enum class PackedTagType : u8 {
47 None,
48 Type1, // ISO14443A RW 96-2k bytes 106kbit/s
49 Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
50 Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s
51 Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
52 Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
53};
54
55// This is nn::nfc::NfcProtocol
56// Verify this enum. It might be completely wrong default protocol is 0x48
57enum class NfcProtocol : u32 {
58 None,
59 TypeA = 1U << 0, // ISO14443A
60 TypeB = 1U << 1, // ISO14443B
61 TypeF = 1U << 2, // Sony FeliCa
62 Unknown1 = 1U << 3,
63 Unknown2 = 1U << 5,
64 All = 0xFFFFFFFFU,
65};
66
67// this is nn::nfc::TestWaveType
68enum class TestWaveType : u32 {
69 Unknown,
70};
71
72using UniqueSerialNumber = std::array<u8, 7>;
73using UniqueSerialNumberExtension = std::array<u8, 3>;
74
75// This is nn::nfc::DeviceHandle
76using DeviceHandle = u64;
77
78// This is nn::nfc::TagInfo
79struct TagInfo {
80 UniqueSerialNumber uuid;
81 UniqueSerialNumberExtension uuid_extension;
82 u8 uuid_length;
83 INSERT_PADDING_BYTES(0x15);
84 NfcProtocol protocol;
85 TagType tag_type;
86 INSERT_PADDING_BYTES(0x30);
87};
88static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size");
89
90} // namespace Service::NFC
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 {
13public: 13public:
14 explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") { 14 explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") {
15 // clang-format off 15 // clang-format off
16 static const FunctionInfo functions[] = { 16 static const FunctionInfoTyped<IUser> functions[] = {
17 {0, &IUser::Initialize, "Initialize"}, 17 {0, &IUser::Initialize, "Initialize"},
18 {1, &IUser::Finalize, "Finalize"}, 18 {1, &IUser::Finalize, "Finalize"},
19 {2, &IUser::ListDevices, "ListDevices"}, 19 {2, &IUser::ListDevices, "ListDevices"},
@@ -50,7 +50,7 @@ class ISystem final : public Interface {
50public: 50public:
51 explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") { 51 explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") {
52 // clang-format off 52 // clang-format off
53 static const FunctionInfo functions[] = { 53 static const FunctionInfoTyped<ISystem> functions[] = {
54 {0, &ISystem::InitializeSystem, "InitializeSystem"}, 54 {0, &ISystem::InitializeSystem, "InitializeSystem"},
55 {1, &ISystem::FinalizeSystem, "FinalizeSystem"}, 55 {1, &ISystem::FinalizeSystem, "FinalizeSystem"},
56 {2, &ISystem::ListDevices, "ListDevices"}, 56 {2, &ISystem::ListDevices, "ListDevices"},
@@ -89,7 +89,7 @@ class IDebug final : public Interface {
89public: 89public:
90 explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") { 90 explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") {
91 // clang-format off 91 // clang-format off
92 static const FunctionInfo functions[] = { 92 static const FunctionInfoTyped<IDebug> functions[] = {
93 {0, &IDebug::InitializeDebug, "InitializeDebug"}, 93 {0, &IDebug::InitializeDebug, "InitializeDebug"},
94 {1, &IDebug::FinalizeDebug, "FinalizeDebug"}, 94 {1, &IDebug::FinalizeDebug, "FinalizeDebug"},
95 {2, &IDebug::ListDevices, "ListDevices"}, 95 {2, &IDebug::ListDevices, "ListDevices"},
@@ -126,9 +126,9 @@ public:
126 {201, &IDebug::SetAll, "SetAll"}, 126 {201, &IDebug::SetAll, "SetAll"},
127 {202, &IDebug::FlushDebug, "FlushDebug"}, 127 {202, &IDebug::FlushDebug, "FlushDebug"},
128 {203, &IDebug::BreakTag, "BreakTag"}, 128 {203, &IDebug::BreakTag, "BreakTag"},
129 {204, nullptr, "ReadBackupData"}, 129 {204, &IDebug::ReadBackupData, "ReadBackupData"},
130 {205, nullptr, "WriteBackupData"}, 130 {205, &IDebug::WriteBackupData, "WriteBackupData"},
131 {206, nullptr, "WriteNtf"}, 131 {206, &IDebug::WriteNtf, "WriteNtf"},
132 }; 132 };
133 // clang-format on 133 // clang-format on
134 134
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 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <span>
7#include <vector>
8
9#include "common/common_types.h"
10#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/nfp/nfp_types.h"
12#include "core/hle/service/service.h"
13
14namespace Kernel {
15class KEvent;
16class KReadableEvent;
17} // namespace Kernel
18
19namespace Core {
20class System;
21} // namespace Core
22
23namespace Core::HID {
24class EmulatedController;
25enum class ControllerTriggerType;
26enum class NpadIdType : u32;
27} // namespace Core::HID
28
29namespace Service::NFP {
30class NfpDevice {
31public:
32 NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
33 KernelHelpers::ServiceContext& service_context_,
34 Kernel::KEvent* availability_change_event_);
35 ~NfpDevice();
36
37 void Initialize();
38 void Finalize();
39
40 Result StartDetection(TagProtocol allowed_protocol);
41 Result StopDetection();
42 Result Mount(MountTarget mount_target);
43 Result Unmount();
44
45 Result Flush();
46 Result FlushDebug();
47 Result FlushWithBreak(BreakType break_type);
48
49 Result GetTagInfo(TagInfo& tag_info) const;
50 Result GetCommonInfo(CommonInfo& common_info) const;
51 Result GetModelInfo(ModelInfo& model_info) const;
52 Result GetRegisterInfo(RegisterInfo& register_info) const;
53 Result GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const;
54 Result GetAdminInfo(AdminInfo& admin_info) const;
55
56 Result DeleteRegisterInfo();
57 Result SetRegisterInfoPrivate(const AmiiboName& amiibo_name);
58 Result RestoreAmiibo();
59 Result Format();
60
61 Result OpenApplicationArea(u32 access_id);
62 Result GetApplicationAreaId(u32& application_area_id) const;
63 Result GetApplicationArea(std::vector<u8>& data) const;
64 Result SetApplicationArea(std::span<const u8> data);
65 Result CreateApplicationArea(u32 access_id, std::span<const u8> data);
66 Result RecreateApplicationArea(u32 access_id, std::span<const u8> data);
67 Result DeleteApplicationArea();
68 Result ExistApplicationArea(bool& has_application_area);
69
70 Result GetAll(NfpData& data) const;
71 Result SetAll(const NfpData& data);
72 Result BreakTag(BreakType break_type);
73 Result ReadBackupData();
74 Result WriteBackupData();
75 Result WriteNtf();
76
77 u64 GetHandle() const;
78 u32 GetApplicationAreaSize() const;
79 DeviceState GetCurrentState() const;
80 Core::HID::NpadIdType GetNpadId() const;
81
82 Kernel::KReadableEvent& GetActivateEvent() const;
83 Kernel::KReadableEvent& GetDeactivateEvent() const;
84
85private:
86 void NpadUpdate(Core::HID::ControllerTriggerType type);
87 bool LoadAmiibo(std::span<const u8> data);
88 void CloseAmiibo();
89
90 AmiiboName GetAmiiboName(const AmiiboSettings& settings) const;
91 void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name);
92 AmiiboDate GetAmiiboDate(s64 posix_time) const;
93 u64 RemoveVersionByte(u64 application_id) const;
94 void UpdateSettingsCrc();
95 void UpdateRegisterInfoCrc();
96
97 bool is_controller_set{};
98 int callback_key;
99 const Core::HID::NpadIdType npad_id;
100 Core::System& system;
101 Core::HID::EmulatedController* npad_device = nullptr;
102 KernelHelpers::ServiceContext& service_context;
103 Kernel::KEvent* activate_event = nullptr;
104 Kernel::KEvent* deactivate_event = nullptr;
105 Kernel::KEvent* availability_change_event = nullptr;
106
107 bool is_initalized{};
108 bool is_data_moddified{};
109 bool is_app_area_open{};
110 bool is_plain_amiibo{};
111 TagProtocol allowed_protocols{};
112 s64 current_posix_time{};
113 MountTarget mount_target{MountTarget::None};
114 DeviceState device_state{DeviceState::Unavailable};
115
116 NTAG215File tag_data{};
117 EncryptedNTAG215File encrypted_tag_data{};
118};
119
120} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/logging/log.h" 4#include "common/logging/log.h"
@@ -6,198 +6,34 @@
6#include "core/hid/hid_types.h" 6#include "core/hid/hid_types.h"
7#include "core/hle/kernel/k_event.h" 7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nfp/nfp_device.h" 9#include "core/hle/service/nfc/common/device.h"
10#include "core/hle/service/nfc/common/device_manager.h"
11#include "core/hle/service/nfc/nfc_types.h"
10#include "core/hle/service/nfp/nfp_interface.h" 12#include "core/hle/service/nfp/nfp_interface.h"
11#include "core/hle/service/nfp/nfp_result.h" 13#include "core/hle/service/nfp/nfp_result.h"
14#include "core/hle/service/nfp/nfp_types.h"
12 15
13namespace Service::NFP { 16namespace Service::NFP {
14 17
15Interface::Interface(Core::System& system_, const char* name) 18Interface::Interface(Core::System& system_, const char* name)
16 : ServiceFramework{system_, name}, service_context{system_, service_name} { 19 : NfcInterface{system_, name, NFC::BackendType::Nfp} {}
17 availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent");
18 20
19 for (u32 device_index = 0; device_index < 10; device_index++) { 21Interface::~Interface() = default;
20 devices[device_index] =
21 std::make_shared<NfpDevice>(Core::HID::IndexToNpadIdType(device_index), system,
22 service_context, availability_change_event);
23 }
24}
25
26Interface::~Interface() {
27 availability_change_event->Close();
28}
29
30void Interface::Initialize(HLERequestContext& ctx) {
31 LOG_INFO(Service_NFP, "called");
32
33 state = State::Initialized;
34
35 for (auto& device : devices) {
36 device->Initialize();
37 }
38
39 IPC::ResponseBuilder rb{ctx, 2};
40 rb.Push(ResultSuccess);
41}
42 22
43void Interface::InitializeSystem(HLERequestContext& ctx) { 23void Interface::InitializeSystem(HLERequestContext& ctx) {
44 LOG_INFO(Service_NFP, "called"); 24 Initialize(ctx);
45
46 state = State::Initialized;
47
48 for (auto& device : devices) {
49 device->Initialize();
50 }
51
52 IPC::ResponseBuilder rb{ctx, 2};
53 rb.Push(ResultSuccess);
54} 25}
55 26
56void Interface::InitializeDebug(HLERequestContext& ctx) { 27void Interface::InitializeDebug(HLERequestContext& ctx) {
57 LOG_INFO(Service_NFP, "called"); 28 Initialize(ctx);
58
59 state = State::Initialized;
60
61 for (auto& device : devices) {
62 device->Initialize();
63 }
64
65 IPC::ResponseBuilder rb{ctx, 2};
66 rb.Push(ResultSuccess);
67}
68
69void Interface::Finalize(HLERequestContext& ctx) {
70 LOG_INFO(Service_NFP, "called");
71
72 state = State::NonInitialized;
73
74 for (auto& device : devices) {
75 device->Finalize();
76 }
77
78 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(ResultSuccess);
80} 29}
81 30
82void Interface::FinalizeSystem(HLERequestContext& ctx) { 31void Interface::FinalizeSystem(HLERequestContext& ctx) {
83 LOG_INFO(Service_NFP, "called"); 32 Finalize(ctx);
84
85 state = State::NonInitialized;
86
87 for (auto& device : devices) {
88 device->Finalize();
89 }
90
91 IPC::ResponseBuilder rb{ctx, 2};
92 rb.Push(ResultSuccess);
93} 33}
94 34
95void Interface::FinalizeDebug(HLERequestContext& ctx) { 35void Interface::FinalizeDebug(HLERequestContext& ctx) {
96 LOG_INFO(Service_NFP, "called"); 36 Finalize(ctx);
97
98 state = State::NonInitialized;
99
100 for (auto& device : devices) {
101 device->Finalize();
102 }
103
104 IPC::ResponseBuilder rb{ctx, 2};
105 rb.Push(ResultSuccess);
106}
107
108void Interface::ListDevices(HLERequestContext& ctx) {
109 LOG_DEBUG(Service_NFP, "called");
110
111 if (state == State::NonInitialized) {
112 IPC::ResponseBuilder rb{ctx, 2};
113 rb.Push(NfcDisabled);
114 return;
115 }
116
117 if (!ctx.CanWriteBuffer()) {
118 IPC::ResponseBuilder rb{ctx, 2};
119 rb.Push(InvalidArgument);
120 return;
121 }
122
123 if (ctx.GetWriteBufferSize() == 0) {
124 IPC::ResponseBuilder rb{ctx, 2};
125 rb.Push(InvalidArgument);
126 return;
127 }
128
129 std::vector<u64> nfp_devices;
130 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
131
132 for (const auto& device : devices) {
133 if (nfp_devices.size() >= max_allowed_devices) {
134 continue;
135 }
136 if (device->GetCurrentState() != DeviceState::Unavailable) {
137 nfp_devices.push_back(device->GetHandle());
138 }
139 }
140
141 if (nfp_devices.empty()) {
142 IPC::ResponseBuilder rb{ctx, 2};
143 rb.Push(DeviceNotFound);
144 return;
145 }
146
147 ctx.WriteBuffer(nfp_devices);
148
149 IPC::ResponseBuilder rb{ctx, 3};
150 rb.Push(ResultSuccess);
151 rb.Push(static_cast<s32>(nfp_devices.size()));
152}
153
154void Interface::StartDetection(HLERequestContext& ctx) {
155 IPC::RequestParser rp{ctx};
156 const auto device_handle{rp.Pop<u64>()};
157 const auto nfp_protocol{rp.PopEnum<TagProtocol>()};
158 LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
159
160 if (state == State::NonInitialized) {
161 IPC::ResponseBuilder rb{ctx, 2};
162 rb.Push(NfcDisabled);
163 return;
164 }
165
166 auto device = GetNfpDevice(device_handle);
167
168 if (!device.has_value()) {
169 IPC::ResponseBuilder rb{ctx, 2};
170 rb.Push(DeviceNotFound);
171 return;
172 }
173
174 const auto result = device.value()->StartDetection(nfp_protocol);
175 IPC::ResponseBuilder rb{ctx, 2};
176 rb.Push(result);
177}
178
179void Interface::StopDetection(HLERequestContext& ctx) {
180 IPC::RequestParser rp{ctx};
181 const auto device_handle{rp.Pop<u64>()};
182 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
183
184 if (state == State::NonInitialized) {
185 IPC::ResponseBuilder rb{ctx, 2};
186 rb.Push(NfcDisabled);
187 return;
188 }
189
190 auto device = GetNfpDevice(device_handle);
191
192 if (!device.has_value()) {
193 IPC::ResponseBuilder rb{ctx, 2};
194 rb.Push(DeviceNotFound);
195 return;
196 }
197
198 const auto result = device.value()->StopDetection();
199 IPC::ResponseBuilder rb{ctx, 2};
200 rb.Push(result);
201} 37}
202 38
203void Interface::Mount(HLERequestContext& ctx) { 39void Interface::Mount(HLERequestContext& ctx) {
@@ -208,21 +44,9 @@ void Interface::Mount(HLERequestContext& ctx) {
208 LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle, 44 LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle,
209 model_type, mount_target); 45 model_type, mount_target);
210 46
211 if (state == State::NonInitialized) { 47 auto result = GetManager()->Mount(device_handle, model_type, mount_target);
212 IPC::ResponseBuilder rb{ctx, 2}; 48 result = TranslateResultToServiceError(result);
213 rb.Push(NfcDisabled);
214 return;
215 }
216
217 auto device = GetNfpDevice(device_handle);
218
219 if (!device.has_value()) {
220 IPC::ResponseBuilder rb{ctx, 2};
221 rb.Push(DeviceNotFound);
222 return;
223 }
224 49
225 const auto result = device.value()->Mount(mount_target);
226 IPC::ResponseBuilder rb{ctx, 2}; 50 IPC::ResponseBuilder rb{ctx, 2};
227 rb.Push(result); 51 rb.Push(result);
228} 52}
@@ -232,21 +56,9 @@ void Interface::Unmount(HLERequestContext& ctx) {
232 const auto device_handle{rp.Pop<u64>()}; 56 const auto device_handle{rp.Pop<u64>()};
233 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 57 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
234 58
235 if (state == State::NonInitialized) { 59 auto result = GetManager()->Unmount(device_handle);
236 IPC::ResponseBuilder rb{ctx, 2}; 60 result = TranslateResultToServiceError(result);
237 rb.Push(NfcDisabled);
238 return;
239 }
240
241 auto device = GetNfpDevice(device_handle);
242
243 if (!device.has_value()) {
244 IPC::ResponseBuilder rb{ctx, 2};
245 rb.Push(DeviceNotFound);
246 return;
247 }
248 61
249 const auto result = device.value()->Unmount();
250 IPC::ResponseBuilder rb{ctx, 2}; 62 IPC::ResponseBuilder rb{ctx, 2};
251 rb.Push(result); 63 rb.Push(result);
252} 64}
@@ -257,21 +69,9 @@ void Interface::OpenApplicationArea(HLERequestContext& ctx) {
257 const auto access_id{rp.Pop<u32>()}; 69 const auto access_id{rp.Pop<u32>()};
258 LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id); 70 LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id);
259 71
260 if (state == State::NonInitialized) { 72 auto result = GetManager()->OpenApplicationArea(device_handle, access_id);
261 IPC::ResponseBuilder rb{ctx, 2}; 73 result = TranslateResultToServiceError(result);
262 rb.Push(NfcDisabled);
263 return;
264 }
265
266 auto device = GetNfpDevice(device_handle);
267
268 if (!device.has_value()) {
269 IPC::ResponseBuilder rb{ctx, 2};
270 rb.Push(DeviceNotFound);
271 return;
272 }
273 74
274 const auto result = device.value()->OpenApplicationArea(access_id);
275 IPC::ResponseBuilder rb{ctx, 2}; 75 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(result); 76 rb.Push(result);
277} 77}
@@ -282,28 +82,16 @@ void Interface::GetApplicationArea(HLERequestContext& ctx) {
282 const auto data_size = ctx.GetWriteBufferSize(); 82 const auto data_size = ctx.GetWriteBufferSize();
283 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 83 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
284 84
285 if (state == State::NonInitialized) { 85 std::vector<u8> data(data_size);
286 IPC::ResponseBuilder rb{ctx, 2}; 86 auto result = GetManager()->GetApplicationArea(device_handle, data);
287 rb.Push(NfcDisabled); 87 result = TranslateResultToServiceError(result);
288 return;
289 }
290
291 if (!ctx.CanWriteBuffer()) {
292 IPC::ResponseBuilder rb{ctx, 2};
293 rb.Push(InvalidArgument);
294 return;
295 }
296
297 auto device = GetNfpDevice(device_handle);
298 88
299 if (!device.has_value()) { 89 if (result.IsError()) {
300 IPC::ResponseBuilder rb{ctx, 2}; 90 IPC::ResponseBuilder rb{ctx, 2};
301 rb.Push(DeviceNotFound); 91 rb.Push(result);
302 return; 92 return;
303 } 93 }
304 94
305 std::vector<u8> data(data_size);
306 const auto result = device.value()->GetApplicationArea(data);
307 ctx.WriteBuffer(data); 95 ctx.WriteBuffer(data);
308 IPC::ResponseBuilder rb{ctx, 3}; 96 IPC::ResponseBuilder rb{ctx, 3};
309 rb.Push(result); 97 rb.Push(result);
@@ -316,27 +104,9 @@ void Interface::SetApplicationArea(HLERequestContext& ctx) {
316 const auto data{ctx.ReadBuffer()}; 104 const auto data{ctx.ReadBuffer()};
317 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size()); 105 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size());
318 106
319 if (state == State::NonInitialized) { 107 auto result = GetManager()->SetApplicationArea(device_handle, data);
320 IPC::ResponseBuilder rb{ctx, 2}; 108 result = TranslateResultToServiceError(result);
321 rb.Push(NfcDisabled);
322 return;
323 }
324
325 if (!ctx.CanReadBuffer()) {
326 IPC::ResponseBuilder rb{ctx, 2};
327 rb.Push(InvalidArgument);
328 return;
329 }
330
331 auto device = GetNfpDevice(device_handle);
332
333 if (!device.has_value()) {
334 IPC::ResponseBuilder rb{ctx, 2};
335 rb.Push(DeviceNotFound);
336 return;
337 }
338 109
339 const auto result = device.value()->SetApplicationArea(data);
340 IPC::ResponseBuilder rb{ctx, 2}; 110 IPC::ResponseBuilder rb{ctx, 2};
341 rb.Push(result); 111 rb.Push(result);
342} 112}
@@ -346,21 +116,9 @@ void Interface::Flush(HLERequestContext& ctx) {
346 const auto device_handle{rp.Pop<u64>()}; 116 const auto device_handle{rp.Pop<u64>()};
347 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 117 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
348 118
349 if (state == State::NonInitialized) { 119 auto result = GetManager()->Flush(device_handle);
350 IPC::ResponseBuilder rb{ctx, 2}; 120 result = TranslateResultToServiceError(result);
351 rb.Push(NfcDisabled);
352 return;
353 }
354
355 auto device = GetNfpDevice(device_handle);
356 121
357 if (!device.has_value()) {
358 IPC::ResponseBuilder rb{ctx, 2};
359 rb.Push(DeviceNotFound);
360 return;
361 }
362
363 const auto result = device.value()->Flush();
364 IPC::ResponseBuilder rb{ctx, 2}; 122 IPC::ResponseBuilder rb{ctx, 2};
365 rb.Push(result); 123 rb.Push(result);
366} 124}
@@ -370,21 +128,9 @@ void Interface::Restore(HLERequestContext& ctx) {
370 const auto device_handle{rp.Pop<u64>()}; 128 const auto device_handle{rp.Pop<u64>()};
371 LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); 129 LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle);
372 130
373 if (state == State::NonInitialized) { 131 auto result = GetManager()->Restore(device_handle);
374 IPC::ResponseBuilder rb{ctx, 2}; 132 result = TranslateResultToServiceError(result);
375 rb.Push(NfcDisabled);
376 return;
377 }
378 133
379 auto device = GetNfpDevice(device_handle);
380
381 if (!device.has_value()) {
382 IPC::ResponseBuilder rb{ctx, 2};
383 rb.Push(DeviceNotFound);
384 return;
385 }
386
387 const auto result = device.value()->RestoreAmiibo();
388 IPC::ResponseBuilder rb{ctx, 2}; 134 IPC::ResponseBuilder rb{ctx, 2};
389 rb.Push(result); 135 rb.Push(result);
390} 136}
@@ -397,53 +143,9 @@ void Interface::CreateApplicationArea(HLERequestContext& ctx) {
397 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, 143 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle,
398 access_id, data.size()); 144 access_id, data.size());
399 145
400 if (state == State::NonInitialized) { 146 auto result = GetManager()->CreateApplicationArea(device_handle, access_id, data);
401 IPC::ResponseBuilder rb{ctx, 2}; 147 result = TranslateResultToServiceError(result);
402 rb.Push(NfcDisabled);
403 return;
404 }
405
406 if (!ctx.CanReadBuffer()) {
407 IPC::ResponseBuilder rb{ctx, 2};
408 rb.Push(InvalidArgument);
409 return;
410 }
411
412 auto device = GetNfpDevice(device_handle);
413
414 if (!device.has_value()) {
415 IPC::ResponseBuilder rb{ctx, 2};
416 rb.Push(DeviceNotFound);
417 return;
418 }
419
420 const auto result = device.value()->CreateApplicationArea(access_id, data);
421 IPC::ResponseBuilder rb{ctx, 2};
422 rb.Push(result);
423}
424
425void Interface::GetTagInfo(HLERequestContext& ctx) {
426 IPC::RequestParser rp{ctx};
427 const auto device_handle{rp.Pop<u64>()};
428 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
429
430 if (state == State::NonInitialized) {
431 IPC::ResponseBuilder rb{ctx, 2};
432 rb.Push(NfcDisabled);
433 return;
434 }
435
436 auto device = GetNfpDevice(device_handle);
437
438 if (!device.has_value()) {
439 IPC::ResponseBuilder rb{ctx, 2};
440 rb.Push(DeviceNotFound);
441 return;
442 }
443 148
444 TagInfo tag_info{};
445 const auto result = device.value()->GetTagInfo(tag_info);
446 ctx.WriteBuffer(tag_info);
447 IPC::ResponseBuilder rb{ctx, 2}; 149 IPC::ResponseBuilder rb{ctx, 2};
448 rb.Push(result); 150 rb.Push(result);
449} 151}
@@ -453,23 +155,14 @@ void Interface::GetRegisterInfo(HLERequestContext& ctx) {
453 const auto device_handle{rp.Pop<u64>()}; 155 const auto device_handle{rp.Pop<u64>()};
454 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 156 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
455 157
456 if (state == State::NonInitialized) { 158 RegisterInfo register_info{};
457 IPC::ResponseBuilder rb{ctx, 2}; 159 auto result = GetManager()->GetRegisterInfo(device_handle, register_info);
458 rb.Push(NfcDisabled); 160 result = TranslateResultToServiceError(result);
459 return;
460 }
461
462 auto device = GetNfpDevice(device_handle);
463 161
464 if (!device.has_value()) { 162 if (result.IsSuccess()) {
465 IPC::ResponseBuilder rb{ctx, 2}; 163 ctx.WriteBuffer(register_info);
466 rb.Push(DeviceNotFound);
467 return;
468 } 164 }
469 165
470 RegisterInfo register_info{};
471 const auto result = device.value()->GetRegisterInfo(register_info);
472 ctx.WriteBuffer(register_info);
473 IPC::ResponseBuilder rb{ctx, 2}; 166 IPC::ResponseBuilder rb{ctx, 2};
474 rb.Push(result); 167 rb.Push(result);
475} 168}
@@ -479,23 +172,14 @@ void Interface::GetCommonInfo(HLERequestContext& ctx) {
479 const auto device_handle{rp.Pop<u64>()}; 172 const auto device_handle{rp.Pop<u64>()};
480 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 173 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
481 174
482 if (state == State::NonInitialized) { 175 CommonInfo common_info{};
483 IPC::ResponseBuilder rb{ctx, 2}; 176 auto result = GetManager()->GetCommonInfo(device_handle, common_info);
484 rb.Push(NfcDisabled); 177 result = TranslateResultToServiceError(result);
485 return;
486 }
487
488 auto device = GetNfpDevice(device_handle);
489 178
490 if (!device.has_value()) { 179 if (result.IsSuccess()) {
491 IPC::ResponseBuilder rb{ctx, 2}; 180 ctx.WriteBuffer(common_info);
492 rb.Push(DeviceNotFound);
493 return;
494 } 181 }
495 182
496 CommonInfo common_info{};
497 const auto result = device.value()->GetCommonInfo(common_info);
498 ctx.WriteBuffer(common_info);
499 IPC::ResponseBuilder rb{ctx, 2}; 183 IPC::ResponseBuilder rb{ctx, 2};
500 rb.Push(result); 184 rb.Push(result);
501} 185}
@@ -505,155 +189,26 @@ void Interface::GetModelInfo(HLERequestContext& ctx) {
505 const auto device_handle{rp.Pop<u64>()}; 189 const auto device_handle{rp.Pop<u64>()};
506 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 190 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
507 191
508 if (state == State::NonInitialized) { 192 ModelInfo model_info{};
509 IPC::ResponseBuilder rb{ctx, 2}; 193 auto result = GetManager()->GetModelInfo(device_handle, model_info);
510 rb.Push(NfcDisabled); 194 result = TranslateResultToServiceError(result);
511 return;
512 }
513
514 auto device = GetNfpDevice(device_handle);
515 195
516 if (!device.has_value()) { 196 if (result.IsSuccess()) {
517 IPC::ResponseBuilder rb{ctx, 2}; 197 ctx.WriteBuffer(model_info);
518 rb.Push(DeviceNotFound);
519 return;
520 } 198 }
521 199
522 ModelInfo model_info{};
523 const auto result = device.value()->GetModelInfo(model_info);
524 ctx.WriteBuffer(model_info);
525 IPC::ResponseBuilder rb{ctx, 2}; 200 IPC::ResponseBuilder rb{ctx, 2};
526 rb.Push(result); 201 rb.Push(result);
527} 202}
528 203
529void Interface::AttachActivateEvent(HLERequestContext& ctx) {
530 IPC::RequestParser rp{ctx};
531 const auto device_handle{rp.Pop<u64>()};
532 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
533
534 if (state == State::NonInitialized) {
535 IPC::ResponseBuilder rb{ctx, 2};
536 rb.Push(NfcDisabled);
537 return;
538 }
539
540 auto device = GetNfpDevice(device_handle);
541
542 if (!device.has_value()) {
543 IPC::ResponseBuilder rb{ctx, 2};
544 rb.Push(DeviceNotFound);
545 return;
546 }
547
548 IPC::ResponseBuilder rb{ctx, 2, 1};
549 rb.Push(ResultSuccess);
550 rb.PushCopyObjects(device.value()->GetActivateEvent());
551}
552
553void Interface::AttachDeactivateEvent(HLERequestContext& ctx) {
554 IPC::RequestParser rp{ctx};
555 const auto device_handle{rp.Pop<u64>()};
556 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
557
558 if (state == State::NonInitialized) {
559 IPC::ResponseBuilder rb{ctx, 2};
560 rb.Push(NfcDisabled);
561 return;
562 }
563
564 auto device = GetNfpDevice(device_handle);
565
566 if (!device.has_value()) {
567 IPC::ResponseBuilder rb{ctx, 2};
568 rb.Push(DeviceNotFound);
569 return;
570 }
571
572 IPC::ResponseBuilder rb{ctx, 2, 1};
573 rb.Push(ResultSuccess);
574 rb.PushCopyObjects(device.value()->GetDeactivateEvent());
575}
576
577void Interface::GetState(HLERequestContext& ctx) {
578 LOG_DEBUG(Service_NFP, "called");
579
580 IPC::ResponseBuilder rb{ctx, 3};
581 rb.Push(ResultSuccess);
582 rb.PushEnum(state);
583}
584
585void Interface::GetDeviceState(HLERequestContext& ctx) {
586 IPC::RequestParser rp{ctx};
587 const auto device_handle{rp.Pop<u64>()};
588 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
589
590 auto device = GetNfpDevice(device_handle);
591
592 if (!device.has_value()) {
593 IPC::ResponseBuilder rb{ctx, 2};
594 rb.Push(DeviceNotFound);
595 return;
596 }
597
598 IPC::ResponseBuilder rb{ctx, 3};
599 rb.Push(ResultSuccess);
600 rb.PushEnum(device.value()->GetCurrentState());
601}
602
603void Interface::GetNpadId(HLERequestContext& ctx) {
604 IPC::RequestParser rp{ctx};
605 const auto device_handle{rp.Pop<u64>()};
606 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
607
608 if (state == State::NonInitialized) {
609 IPC::ResponseBuilder rb{ctx, 2};
610 rb.Push(NfcDisabled);
611 return;
612 }
613
614 auto device = GetNfpDevice(device_handle);
615
616 if (!device.has_value()) {
617 IPC::ResponseBuilder rb{ctx, 2};
618 rb.Push(DeviceNotFound);
619 return;
620 }
621
622 IPC::ResponseBuilder rb{ctx, 3};
623 rb.Push(ResultSuccess);
624 rb.PushEnum(device.value()->GetNpadId());
625}
626
627void Interface::GetApplicationAreaSize(HLERequestContext& ctx) { 204void Interface::GetApplicationAreaSize(HLERequestContext& ctx) {
628 IPC::RequestParser rp{ctx}; 205 IPC::RequestParser rp{ctx};
629 const auto device_handle{rp.Pop<u64>()}; 206 const auto device_handle{rp.Pop<u64>()};
630 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 207 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
631 208
632 auto device = GetNfpDevice(device_handle);
633
634 if (!device.has_value()) {
635 IPC::ResponseBuilder rb{ctx, 2};
636 rb.Push(DeviceNotFound);
637 return;
638 }
639
640 IPC::ResponseBuilder rb{ctx, 3}; 209 IPC::ResponseBuilder rb{ctx, 3};
641 rb.Push(ResultSuccess); 210 rb.Push(ResultSuccess);
642 rb.Push(device.value()->GetApplicationAreaSize()); 211 rb.Push(GetManager()->GetApplicationAreaSize());
643}
644
645void Interface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
646 LOG_INFO(Service_NFP, "called");
647
648 if (state == State::NonInitialized) {
649 IPC::ResponseBuilder rb{ctx, 2};
650 rb.Push(NfcDisabled);
651 return;
652 }
653
654 IPC::ResponseBuilder rb{ctx, 2, 1};
655 rb.Push(ResultSuccess);
656 rb.PushCopyObjects(availability_change_event->GetReadableEvent());
657} 212}
658 213
659void Interface::RecreateApplicationArea(HLERequestContext& ctx) { 214void Interface::RecreateApplicationArea(HLERequestContext& ctx) {
@@ -664,21 +219,9 @@ void Interface::RecreateApplicationArea(HLERequestContext& ctx) {
664 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, 219 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle,
665 access_id, data.size()); 220 access_id, data.size());
666 221
667 if (state == State::NonInitialized) { 222 auto result = GetManager()->RecreateApplicationArea(device_handle, access_id, data);
668 IPC::ResponseBuilder rb{ctx, 2}; 223 result = TranslateResultToServiceError(result);
669 rb.Push(NfcDisabled);
670 return;
671 }
672 224
673 auto device = GetNfpDevice(device_handle);
674
675 if (!device.has_value()) {
676 IPC::ResponseBuilder rb{ctx, 2};
677 rb.Push(DeviceNotFound);
678 return;
679 }
680
681 const auto result = device.value()->RecreateApplicationArea(access_id, data);
682 IPC::ResponseBuilder rb{ctx, 2}; 225 IPC::ResponseBuilder rb{ctx, 2};
683 rb.Push(result); 226 rb.Push(result);
684} 227}
@@ -686,23 +229,11 @@ void Interface::RecreateApplicationArea(HLERequestContext& ctx) {
686void Interface::Format(HLERequestContext& ctx) { 229void Interface::Format(HLERequestContext& ctx) {
687 IPC::RequestParser rp{ctx}; 230 IPC::RequestParser rp{ctx};
688 const auto device_handle{rp.Pop<u64>()}; 231 const auto device_handle{rp.Pop<u64>()};
689 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 232 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
690
691 if (state == State::NonInitialized) {
692 IPC::ResponseBuilder rb{ctx, 2};
693 rb.Push(NfcDisabled);
694 return;
695 }
696 233
697 auto device = GetNfpDevice(device_handle); 234 auto result = GetManager()->Format(device_handle);
235 result = TranslateResultToServiceError(result);
698 236
699 if (!device.has_value()) {
700 IPC::ResponseBuilder rb{ctx, 2};
701 rb.Push(DeviceNotFound);
702 return;
703 }
704
705 const auto result = device.value()->Format();
706 IPC::ResponseBuilder rb{ctx, 2}; 237 IPC::ResponseBuilder rb{ctx, 2};
707 rb.Push(result); 238 rb.Push(result);
708} 239}
@@ -712,23 +243,14 @@ void Interface::GetAdminInfo(HLERequestContext& ctx) {
712 const auto device_handle{rp.Pop<u64>()}; 243 const auto device_handle{rp.Pop<u64>()};
713 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 244 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
714 245
715 if (state == State::NonInitialized) { 246 AdminInfo admin_info{};
716 IPC::ResponseBuilder rb{ctx, 2}; 247 auto result = GetManager()->GetAdminInfo(device_handle, admin_info);
717 rb.Push(NfcDisabled); 248 result = TranslateResultToServiceError(result);
718 return;
719 }
720
721 auto device = GetNfpDevice(device_handle);
722 249
723 if (!device.has_value()) { 250 if (result.IsSuccess()) {
724 IPC::ResponseBuilder rb{ctx, 2}; 251 ctx.WriteBuffer(admin_info);
725 rb.Push(DeviceNotFound);
726 return;
727 } 252 }
728 253
729 AdminInfo admin_info{};
730 const auto result = device.value()->GetAdminInfo(admin_info);
731 ctx.WriteBuffer(admin_info);
732 IPC::ResponseBuilder rb{ctx, 2}; 254 IPC::ResponseBuilder rb{ctx, 2};
733 rb.Push(result); 255 rb.Push(result);
734} 256}
@@ -738,23 +260,14 @@ void Interface::GetRegisterInfoPrivate(HLERequestContext& ctx) {
738 const auto device_handle{rp.Pop<u64>()}; 260 const auto device_handle{rp.Pop<u64>()};
739 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); 261 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
740 262
741 if (state == State::NonInitialized) { 263 RegisterInfoPrivate register_info{};
742 IPC::ResponseBuilder rb{ctx, 2}; 264 auto result = GetManager()->GetRegisterInfoPrivate(device_handle, register_info);
743 rb.Push(NfcDisabled); 265 result = TranslateResultToServiceError(result);
744 return;
745 }
746
747 auto device = GetNfpDevice(device_handle);
748 266
749 if (!device.has_value()) { 267 if (result.IsSuccess()) {
750 IPC::ResponseBuilder rb{ctx, 2}; 268 ctx.WriteBuffer(register_info);
751 rb.Push(DeviceNotFound);
752 return;
753 } 269 }
754 270
755 RegisterInfoPrivate register_info{};
756 const auto result = device.value()->GetRegisterInfoPrivate(register_info);
757 ctx.WriteBuffer(register_info);
758 IPC::ResponseBuilder rb{ctx, 2}; 271 IPC::ResponseBuilder rb{ctx, 2};
759 rb.Push(result); 272 rb.Push(result);
760} 273}
@@ -762,25 +275,15 @@ void Interface::GetRegisterInfoPrivate(HLERequestContext& ctx) {
762void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) { 275void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) {
763 IPC::RequestParser rp{ctx}; 276 IPC::RequestParser rp{ctx};
764 const auto device_handle{rp.Pop<u64>()}; 277 const auto device_handle{rp.Pop<u64>()};
765 const auto buffer{ctx.ReadBuffer()}; 278 const auto register_info_buffer{ctx.ReadBuffer()};
766 LOG_DEBUG(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle, 279 LOG_INFO(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle,
767 buffer.size()); 280 register_info_buffer.size());
768 281
769 if (state == State::NonInitialized) { 282 RegisterInfoPrivate register_info{};
770 IPC::ResponseBuilder rb{ctx, 2}; 283 memcpy(&register_info, register_info_buffer.data(), sizeof(RegisterInfoPrivate));
771 rb.Push(NfcDisabled); 284 auto result = GetManager()->SetRegisterInfoPrivate(device_handle, register_info);
772 return; 285 result = TranslateResultToServiceError(result);
773 }
774
775 auto device = GetNfpDevice(device_handle);
776
777 if (!device.has_value()) {
778 IPC::ResponseBuilder rb{ctx, 2};
779 rb.Push(DeviceNotFound);
780 return;
781 }
782 286
783 const auto result = device.value()->SetRegisterInfoPrivate({});
784 IPC::ResponseBuilder rb{ctx, 2}; 287 IPC::ResponseBuilder rb{ctx, 2};
785 rb.Push(result); 288 rb.Push(result);
786} 289}
@@ -788,23 +291,11 @@ void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) {
788void Interface::DeleteRegisterInfo(HLERequestContext& ctx) { 291void Interface::DeleteRegisterInfo(HLERequestContext& ctx) {
789 IPC::RequestParser rp{ctx}; 292 IPC::RequestParser rp{ctx};
790 const auto device_handle{rp.Pop<u64>()}; 293 const auto device_handle{rp.Pop<u64>()};
791 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 294 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
792
793 if (state == State::NonInitialized) {
794 IPC::ResponseBuilder rb{ctx, 2};
795 rb.Push(NfcDisabled);
796 return;
797 }
798 295
799 auto device = GetNfpDevice(device_handle); 296 auto result = GetManager()->DeleteRegisterInfo(device_handle);
297 result = TranslateResultToServiceError(result);
800 298
801 if (!device.has_value()) {
802 IPC::ResponseBuilder rb{ctx, 2};
803 rb.Push(DeviceNotFound);
804 return;
805 }
806
807 const auto result = device.value()->DeleteRegisterInfo();
808 IPC::ResponseBuilder rb{ctx, 2}; 299 IPC::ResponseBuilder rb{ctx, 2};
809 rb.Push(result); 300 rb.Push(result);
810} 301}
@@ -812,23 +303,11 @@ void Interface::DeleteRegisterInfo(HLERequestContext& ctx) {
812void Interface::DeleteApplicationArea(HLERequestContext& ctx) { 303void Interface::DeleteApplicationArea(HLERequestContext& ctx) {
813 IPC::RequestParser rp{ctx}; 304 IPC::RequestParser rp{ctx};
814 const auto device_handle{rp.Pop<u64>()}; 305 const auto device_handle{rp.Pop<u64>()};
815 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 306 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
816
817 if (state == State::NonInitialized) {
818 IPC::ResponseBuilder rb{ctx, 2};
819 rb.Push(NfcDisabled);
820 return;
821 }
822 307
823 auto device = GetNfpDevice(device_handle); 308 auto result = GetManager()->DeleteApplicationArea(device_handle);
309 result = TranslateResultToServiceError(result);
824 310
825 if (!device.has_value()) {
826 IPC::ResponseBuilder rb{ctx, 2};
827 rb.Push(DeviceNotFound);
828 return;
829 }
830
831 const auto result = device.value()->DeleteApplicationArea();
832 IPC::ResponseBuilder rb{ctx, 2}; 311 IPC::ResponseBuilder rb{ctx, 2};
833 rb.Push(result); 312 rb.Push(result);
834} 313}
@@ -836,24 +315,18 @@ void Interface::DeleteApplicationArea(HLERequestContext& ctx) {
836void Interface::ExistsApplicationArea(HLERequestContext& ctx) { 315void Interface::ExistsApplicationArea(HLERequestContext& ctx) {
837 IPC::RequestParser rp{ctx}; 316 IPC::RequestParser rp{ctx};
838 const auto device_handle{rp.Pop<u64>()}; 317 const auto device_handle{rp.Pop<u64>()};
839 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 318 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
840
841 if (state == State::NonInitialized) {
842 IPC::ResponseBuilder rb{ctx, 2};
843 rb.Push(NfcDisabled);
844 return;
845 }
846 319
847 auto device = GetNfpDevice(device_handle); 320 bool has_application_area = false;
321 auto result = GetManager()->ExistsApplicationArea(device_handle, has_application_area);
322 result = TranslateResultToServiceError(result);
848 323
849 if (!device.has_value()) { 324 if (result.IsError()) {
850 IPC::ResponseBuilder rb{ctx, 2}; 325 IPC::ResponseBuilder rb{ctx, 2};
851 rb.Push(DeviceNotFound); 326 rb.Push(result);
852 return; 327 return;
853 } 328 }
854 329
855 bool has_application_area = false;
856 const auto result = device.value()->ExistApplicationArea(has_application_area);
857 IPC::ResponseBuilder rb{ctx, 3}; 330 IPC::ResponseBuilder rb{ctx, 3};
858 rb.Push(result); 331 rb.Push(result);
859 rb.Push(has_application_area); 332 rb.Push(has_application_area);
@@ -862,27 +335,16 @@ void Interface::ExistsApplicationArea(HLERequestContext& ctx) {
862void Interface::GetAll(HLERequestContext& ctx) { 335void Interface::GetAll(HLERequestContext& ctx) {
863 IPC::RequestParser rp{ctx}; 336 IPC::RequestParser rp{ctx};
864 const auto device_handle{rp.Pop<u64>()}; 337 const auto device_handle{rp.Pop<u64>()};
865 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 338 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
866
867 if (state == State::NonInitialized) {
868 IPC::ResponseBuilder rb{ctx, 2};
869 rb.Push(NfcDisabled);
870 return;
871 }
872 339
873 auto device = GetNfpDevice(device_handle); 340 NfpData nfp_data{};
341 auto result = GetManager()->GetAll(device_handle, nfp_data);
342 result = TranslateResultToServiceError(result);
874 343
875 if (!device.has_value()) { 344 if (result.IsSuccess()) {
876 IPC::ResponseBuilder rb{ctx, 2}; 345 ctx.WriteBuffer(nfp_data);
877 rb.Push(DeviceNotFound);
878 return;
879 } 346 }
880 347
881 NfpData data{};
882 const auto result = device.value()->GetAll(data);
883
884 ctx.WriteBuffer(data);
885
886 IPC::ResponseBuilder rb{ctx, 2}; 348 IPC::ResponseBuilder rb{ctx, 2};
887 rb.Push(result); 349 rb.Push(result);
888} 350}
@@ -890,28 +352,15 @@ void Interface::GetAll(HLERequestContext& ctx) {
890void Interface::SetAll(HLERequestContext& ctx) { 352void Interface::SetAll(HLERequestContext& ctx) {
891 IPC::RequestParser rp{ctx}; 353 IPC::RequestParser rp{ctx};
892 const auto device_handle{rp.Pop<u64>()}; 354 const auto device_handle{rp.Pop<u64>()};
893 const auto nfp_data{ctx.ReadBuffer()}; 355 const auto nfp_data_buffer{ctx.ReadBuffer()};
894
895 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
896
897 if (state == State::NonInitialized) {
898 IPC::ResponseBuilder rb{ctx, 2};
899 rb.Push(NfcDisabled);
900 return;
901 }
902 356
903 auto device = GetNfpDevice(device_handle); 357 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
904
905 if (!device.has_value()) {
906 IPC::ResponseBuilder rb{ctx, 2};
907 rb.Push(DeviceNotFound);
908 return;
909 }
910 358
911 NfpData data{}; 359 NfpData nfp_data{};
912 memcpy(&data, nfp_data.data(), sizeof(NfpData)); 360 memcpy(&nfp_data, nfp_data_buffer.data(), sizeof(NfpData));
361 auto result = GetManager()->SetAll(device_handle, nfp_data);
362 result = TranslateResultToServiceError(result);
913 363
914 const auto result = device.value()->SetAll(data);
915 IPC::ResponseBuilder rb{ctx, 2}; 364 IPC::ResponseBuilder rb{ctx, 2};
916 rb.Push(result); 365 rb.Push(result);
917} 366}
@@ -919,23 +368,11 @@ void Interface::SetAll(HLERequestContext& ctx) {
919void Interface::FlushDebug(HLERequestContext& ctx) { 368void Interface::FlushDebug(HLERequestContext& ctx) {
920 IPC::RequestParser rp{ctx}; 369 IPC::RequestParser rp{ctx};
921 const auto device_handle{rp.Pop<u64>()}; 370 const auto device_handle{rp.Pop<u64>()};
922 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 371 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
923
924 if (state == State::NonInitialized) {
925 IPC::ResponseBuilder rb{ctx, 2};
926 rb.Push(NfcDisabled);
927 return;
928 }
929 372
930 auto device = GetNfpDevice(device_handle); 373 auto result = GetManager()->FlushDebug(device_handle);
374 result = TranslateResultToServiceError(result);
931 375
932 if (!device.has_value()) {
933 IPC::ResponseBuilder rb{ctx, 2};
934 rb.Push(DeviceNotFound);
935 return;
936 }
937
938 const auto result = device.value()->FlushDebug();
939 IPC::ResponseBuilder rb{ctx, 2}; 376 IPC::ResponseBuilder rb{ctx, 2};
940 rb.Push(result); 377 rb.Push(result);
941} 378}
@@ -944,23 +381,12 @@ void Interface::BreakTag(HLERequestContext& ctx) {
944 IPC::RequestParser rp{ctx}; 381 IPC::RequestParser rp{ctx};
945 const auto device_handle{rp.Pop<u64>()}; 382 const auto device_handle{rp.Pop<u64>()};
946 const auto break_type{rp.PopEnum<BreakType>()}; 383 const auto break_type{rp.PopEnum<BreakType>()};
947 LOG_DEBUG(Service_NFP, "called, device_handle={}, break_type={}", device_handle, break_type); 384 LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}, break_type={}", device_handle,
385 break_type);
948 386
949 if (state == State::NonInitialized) { 387 auto result = GetManager()->BreakTag(device_handle, break_type);
950 IPC::ResponseBuilder rb{ctx, 2}; 388 result = TranslateResultToServiceError(result);
951 rb.Push(NfcDisabled);
952 return;
953 }
954 389
955 auto device = GetNfpDevice(device_handle);
956
957 if (!device.has_value()) {
958 IPC::ResponseBuilder rb{ctx, 2};
959 rb.Push(DeviceNotFound);
960 return;
961 }
962
963 const auto result = device.value()->BreakTag(break_type);
964 IPC::ResponseBuilder rb{ctx, 2}; 390 IPC::ResponseBuilder rb{ctx, 2};
965 rb.Push(result); 391 rb.Push(result);
966} 392}
@@ -968,23 +394,16 @@ void Interface::BreakTag(HLERequestContext& ctx) {
968void Interface::ReadBackupData(HLERequestContext& ctx) { 394void Interface::ReadBackupData(HLERequestContext& ctx) {
969 IPC::RequestParser rp{ctx}; 395 IPC::RequestParser rp{ctx};
970 const auto device_handle{rp.Pop<u64>()}; 396 const auto device_handle{rp.Pop<u64>()};
971 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 397 LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle);
972
973 if (state == State::NonInitialized) {
974 IPC::ResponseBuilder rb{ctx, 2};
975 rb.Push(NfcDisabled);
976 return;
977 }
978 398
979 auto device = GetNfpDevice(device_handle); 399 std::vector<u8> backup_data{};
400 auto result = GetManager()->ReadBackupData(device_handle, backup_data);
401 result = TranslateResultToServiceError(result);
980 402
981 if (!device.has_value()) { 403 if (result.IsSuccess()) {
982 IPC::ResponseBuilder rb{ctx, 2}; 404 ctx.WriteBuffer(backup_data);
983 rb.Push(DeviceNotFound);
984 return;
985 } 405 }
986 406
987 const auto result = device.value()->ReadBackupData();
988 IPC::ResponseBuilder rb{ctx, 2}; 407 IPC::ResponseBuilder rb{ctx, 2};
989 rb.Push(result); 408 rb.Push(result);
990} 409}
@@ -992,23 +411,12 @@ void Interface::ReadBackupData(HLERequestContext& ctx) {
992void Interface::WriteBackupData(HLERequestContext& ctx) { 411void Interface::WriteBackupData(HLERequestContext& ctx) {
993 IPC::RequestParser rp{ctx}; 412 IPC::RequestParser rp{ctx};
994 const auto device_handle{rp.Pop<u64>()}; 413 const auto device_handle{rp.Pop<u64>()};
995 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 414 const auto backup_data_buffer{ctx.ReadBuffer()};
996 415 LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle);
997 if (state == State::NonInitialized) {
998 IPC::ResponseBuilder rb{ctx, 2};
999 rb.Push(NfcDisabled);
1000 return;
1001 }
1002
1003 auto device = GetNfpDevice(device_handle);
1004 416
1005 if (!device.has_value()) { 417 auto result = GetManager()->WriteBackupData(device_handle, backup_data_buffer);
1006 IPC::ResponseBuilder rb{ctx, 2}; 418 result = TranslateResultToServiceError(result);
1007 rb.Push(DeviceNotFound);
1008 return;
1009 }
1010 419
1011 const auto result = device.value()->WriteBackupData();
1012 IPC::ResponseBuilder rb{ctx, 2}; 420 IPC::ResponseBuilder rb{ctx, 2};
1013 rb.Push(result); 421 rb.Push(result);
1014} 422}
@@ -1016,34 +424,15 @@ void Interface::WriteBackupData(HLERequestContext& ctx) {
1016void Interface::WriteNtf(HLERequestContext& ctx) { 424void Interface::WriteNtf(HLERequestContext& ctx) {
1017 IPC::RequestParser rp{ctx}; 425 IPC::RequestParser rp{ctx};
1018 const auto device_handle{rp.Pop<u64>()}; 426 const auto device_handle{rp.Pop<u64>()};
1019 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); 427 const auto write_type{rp.PopEnum<WriteType>()};
1020 428 const auto ntf_data_buffer{ctx.ReadBuffer()};
1021 if (state == State::NonInitialized) { 429 LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle);
1022 IPC::ResponseBuilder rb{ctx, 2};
1023 rb.Push(NfcDisabled);
1024 return;
1025 }
1026 430
1027 auto device = GetNfpDevice(device_handle); 431 auto result = GetManager()->WriteNtf(device_handle, write_type, ntf_data_buffer);
432 result = TranslateResultToServiceError(result);
1028 433
1029 if (!device.has_value()) {
1030 IPC::ResponseBuilder rb{ctx, 2};
1031 rb.Push(DeviceNotFound);
1032 return;
1033 }
1034
1035 const auto result = device.value()->WriteNtf();
1036 IPC::ResponseBuilder rb{ctx, 2}; 434 IPC::ResponseBuilder rb{ctx, 2};
1037 rb.Push(result); 435 rb.Push(result);
1038} 436}
1039 437
1040std::optional<std::shared_ptr<NfpDevice>> Interface::GetNfpDevice(u64 handle) {
1041 for (auto& device : devices) {
1042 if (device->GetHandle() == handle) {
1043 return device;
1044 }
1045 }
1046 return std::nullopt;
1047}
1048
1049} // namespace Service::NFP 438} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include <array>
7#include <memory>
8#include <optional>
9
10#include "core/hle/service/kernel_helpers.h" 6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/nfc/nfc_interface.h"
11#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
12 9
13namespace Service::NFP { 10namespace Service::NFP {
14class NfpDevice;
15 11
16class Interface : public ServiceFramework<Interface> { 12class Interface : public NFC::NfcInterface {
17public: 13public:
18 explicit Interface(Core::System& system_, const char* name); 14 explicit Interface(Core::System& system_, const char* name);
19 ~Interface() override; 15 ~Interface() override;
20 16
21 void Initialize(HLERequestContext& ctx);
22 void InitializeSystem(HLERequestContext& ctx); 17 void InitializeSystem(HLERequestContext& ctx);
23 void InitializeDebug(HLERequestContext& ctx); 18 void InitializeDebug(HLERequestContext& ctx);
24 void Finalize(HLERequestContext& ctx);
25 void FinalizeSystem(HLERequestContext& ctx); 19 void FinalizeSystem(HLERequestContext& ctx);
26 void FinalizeDebug(HLERequestContext& ctx); 20 void FinalizeDebug(HLERequestContext& ctx);
27 void ListDevices(HLERequestContext& ctx);
28 void StartDetection(HLERequestContext& ctx);
29 void StopDetection(HLERequestContext& ctx);
30 void Mount(HLERequestContext& ctx); 21 void Mount(HLERequestContext& ctx);
31 void Unmount(HLERequestContext& ctx); 22 void Unmount(HLERequestContext& ctx);
32 void OpenApplicationArea(HLERequestContext& ctx); 23 void OpenApplicationArea(HLERequestContext& ctx);
@@ -35,17 +26,10 @@ public:
35 void Flush(HLERequestContext& ctx); 26 void Flush(HLERequestContext& ctx);
36 void Restore(HLERequestContext& ctx); 27 void Restore(HLERequestContext& ctx);
37 void CreateApplicationArea(HLERequestContext& ctx); 28 void CreateApplicationArea(HLERequestContext& ctx);
38 void GetTagInfo(HLERequestContext& ctx);
39 void GetRegisterInfo(HLERequestContext& ctx); 29 void GetRegisterInfo(HLERequestContext& ctx);
40 void GetCommonInfo(HLERequestContext& ctx); 30 void GetCommonInfo(HLERequestContext& ctx);
41 void GetModelInfo(HLERequestContext& ctx); 31 void GetModelInfo(HLERequestContext& ctx);
42 void AttachActivateEvent(HLERequestContext& ctx);
43 void AttachDeactivateEvent(HLERequestContext& ctx);
44 void GetState(HLERequestContext& ctx);
45 void GetDeviceState(HLERequestContext& ctx);
46 void GetNpadId(HLERequestContext& ctx);
47 void GetApplicationAreaSize(HLERequestContext& ctx); 32 void GetApplicationAreaSize(HLERequestContext& ctx);
48 void AttachAvailabilityChangeEvent(HLERequestContext& ctx);
49 void RecreateApplicationArea(HLERequestContext& ctx); 33 void RecreateApplicationArea(HLERequestContext& ctx);
50 void Format(HLERequestContext& ctx); 34 void Format(HLERequestContext& ctx);
51 void GetAdminInfo(HLERequestContext& ctx); 35 void GetAdminInfo(HLERequestContext& ctx);
@@ -61,21 +45,6 @@ public:
61 void ReadBackupData(HLERequestContext& ctx); 45 void ReadBackupData(HLERequestContext& ctx);
62 void WriteBackupData(HLERequestContext& ctx); 46 void WriteBackupData(HLERequestContext& ctx);
63 void WriteNtf(HLERequestContext& ctx); 47 void WriteNtf(HLERequestContext& ctx);
64
65private:
66 enum class State : u32 {
67 NonInitialized,
68 Initialized,
69 };
70
71 std::optional<std::shared_ptr<NfpDevice>> GetNfpDevice(u64 handle);
72
73 KernelHelpers::ServiceContext service_context;
74
75 std::array<std::shared_ptr<NfpDevice>, 10> devices{};
76
77 State state{State::NonInitialized};
78 Kernel::KEvent* availability_change_event;
79}; 48};
80 49
81} // namespace Service::NFP 50} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
@@ -7,18 +7,19 @@
7 7
8namespace Service::NFP { 8namespace Service::NFP {
9 9
10constexpr Result DeviceNotFound(ErrorModule::NFP, 64); 10constexpr Result ResultDeviceNotFound(ErrorModule::NFP, 64);
11constexpr Result InvalidArgument(ErrorModule::NFP, 65); 11constexpr Result ResultInvalidArgument(ErrorModule::NFP, 65);
12constexpr Result WrongApplicationAreaSize(ErrorModule::NFP, 68); 12constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFP, 68);
13constexpr Result WrongDeviceState(ErrorModule::NFP, 73); 13constexpr Result ResultWrongDeviceState(ErrorModule::NFP, 73);
14constexpr Result NfcDisabled(ErrorModule::NFP, 80); 14constexpr Result ResultUnknown74(ErrorModule::NFC, 74);
15constexpr Result WriteAmiiboFailed(ErrorModule::NFP, 88); 15constexpr Result ResultNfcDisabled(ErrorModule::NFP, 80);
16constexpr Result TagRemoved(ErrorModule::NFP, 97); 16constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88);
17constexpr Result RegistrationIsNotInitialized(ErrorModule::NFP, 120); 17constexpr Result ResultTagRemoved(ErrorModule::NFP, 97);
18constexpr Result ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); 18constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120);
19constexpr Result CorruptedData(ErrorModule::NFP, 144); 19constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
20constexpr Result WrongApplicationAreaId(ErrorModule::NFP, 152); 20constexpr Result ResultCorruptedData(ErrorModule::NFP, 144);
21constexpr Result ApplicationAreaExist(ErrorModule::NFP, 168); 21constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152);
22constexpr Result NotAnAmiibo(ErrorModule::NFP, 178); 22constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168);
23constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178);
23 24
24} // namespace Service::NFP 25} // 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 @@
7 7
8#include "common/swap.h" 8#include "common/swap.h"
9#include "core/hle/service/mii/types.h" 9#include "core/hle/service/mii/types.h"
10#include "core/hle/service/nfc/nfc_types.h"
10 11
11namespace Service::NFP { 12namespace Service::NFP {
12static constexpr std::size_t amiibo_name_length = 0xA; 13static constexpr std::size_t amiibo_name_length = 0xA;
13static constexpr std::size_t application_id_version_offset = 0x1c; 14static constexpr std::size_t application_id_version_offset = 0x1c;
14static constexpr std::size_t counter_limit = 0xffff; 15static constexpr std::size_t counter_limit = 0xffff;
15 16
16enum class ServiceType : u32 { 17// This is nn::nfp::ModelType
17 User,
18 Debug,
19 System,
20};
21
22enum class DeviceState : u32 {
23 Initialized,
24 SearchingForTag,
25 TagFound,
26 TagRemoved,
27 TagMounted,
28 Unavailable,
29 Finalized,
30};
31
32enum class ModelType : u32 { 18enum class ModelType : u32 {
33 Amiibo, 19 Amiibo,
34}; 20};
35 21
22// This is nn::nfp::MountTarget
36enum class MountTarget : u32 { 23enum class MountTarget : u32 {
37 None, 24 None,
38 Rom, 25 Rom,
@@ -72,35 +59,6 @@ enum class AmiiboSeries : u8 {
72 Diablo, 59 Diablo,
73}; 60};
74 61
75enum class TagType : u32 {
76 None,
77 Type1, // ISO14443A RW 96-2k bytes 106kbit/s
78 Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
79 Type3, // Sony Felica RW/RO 2k bytes 212kbit/s
80 Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
81 Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
82};
83
84enum class PackedTagType : u8 {
85 None,
86 Type1, // ISO14443A RW 96-2k bytes 106kbit/s
87 Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
88 Type3, // Sony Felica RW/RO 2k bytes 212kbit/s
89 Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
90 Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
91};
92
93// Verify this enum. It might be completely wrong default protocol is 0x48
94enum class TagProtocol : u32 {
95 None,
96 TypeA = 1U << 0, // ISO14443A
97 TypeB = 1U << 1, // ISO14443B
98 TypeF = 1U << 2, // Sony Felica
99 Unknown1 = 1U << 3,
100 Unknown2 = 1U << 5,
101 All = 0xFFFFFFFFU,
102};
103
104enum class AppAreaVersion : u8 { 62enum class AppAreaVersion : u8 {
105 Nintendo3DS = 0, 63 Nintendo3DS = 0,
106 NintendoWiiU = 1, 64 NintendoWiiU = 1,
@@ -115,6 +73,11 @@ enum class BreakType : u32 {
115 Unknown2, 73 Unknown2,
116}; 74};
117 75
76enum class WriteType : u32 {
77 Unknown0,
78 Unknown1,
79};
80
118enum class CabinetMode : u8 { 81enum class CabinetMode : u8 {
119 StartNicknameAndOwnerSettings, 82 StartNicknameAndOwnerSettings,
120 StartGameDataEraser, 83 StartGameDataEraser,
@@ -122,27 +85,16 @@ enum class CabinetMode : u8 {
122 StartFormatter, 85 StartFormatter,
123}; 86};
124 87
125enum class MifareCmd : u8 {
126 AuthA = 0x60,
127 AuthB = 0x61,
128 Read = 0x30,
129 Write = 0xA0,
130 Transfer = 0xB0,
131 Decrement = 0xC0,
132 Increment = 0xC1,
133 Store = 0xC2
134};
135
136using UniqueSerialNumber = std::array<u8, 7>;
137using LockBytes = std::array<u8, 2>; 88using LockBytes = std::array<u8, 2>;
138using HashData = std::array<u8, 0x20>; 89using HashData = std::array<u8, 0x20>;
139using ApplicationArea = std::array<u8, 0xD8>; 90using ApplicationArea = std::array<u8, 0xD8>;
140using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; 91using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
141using DataBlock = std::array<u8, 0x10>; 92
142using KeyData = std::array<u8, 0x6>; 93// This is nn::nfp::TagInfo
94using TagInfo = NFC::TagInfo;
143 95
144struct TagUuid { 96struct TagUuid {
145 UniqueSerialNumber uid; 97 NFC::UniqueSerialNumber uid;
146 u8 nintendo_id; 98 u8 nintendo_id;
147 LockBytes lock_bytes; 99 LockBytes lock_bytes;
148}; 100};
@@ -243,7 +195,7 @@ struct AmiiboModelInfo {
243 AmiiboType amiibo_type; 195 AmiiboType amiibo_type;
244 u16_be model_number; 196 u16_be model_number;
245 AmiiboSeries series; 197 AmiiboSeries series;
246 PackedTagType tag_type; 198 NFC::PackedTagType tag_type;
247 INSERT_PADDING_BYTES(0x4); // Unknown 199 INSERT_PADDING_BYTES(0x4); // Unknown
248}; 200};
249static_assert(sizeof(AmiiboModelInfo) == 0xC, "AmiiboModelInfo is an invalid size"); 201static_assert(sizeof(AmiiboModelInfo) == 0xC, "AmiiboModelInfo is an invalid size");
@@ -298,7 +250,7 @@ struct NTAG215File {
298 u32_be register_info_crc; 250 u32_be register_info_crc;
299 ApplicationArea application_area; // Encrypted Game data 251 ApplicationArea application_area; // Encrypted Game data
300 HashData hmac_tag; // Hash 252 HashData hmac_tag; // Hash
301 UniqueSerialNumber uid; // Unique serial number 253 NFC::UniqueSerialNumber uid; // Unique serial number
302 u8 nintendo_id; // Tag UUID 254 u8 nintendo_id; // Tag UUID
303 AmiiboModelInfo model_info; 255 AmiiboModelInfo model_info;
304 HashData keygen_salt; // Salt 256 HashData keygen_salt; // Salt
@@ -326,17 +278,7 @@ static_assert(sizeof(EncryptedNTAG215File) == sizeof(NTAG215File),
326static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>, 278static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>,
327 "EncryptedNTAG215File must be trivially copyable."); 279 "EncryptedNTAG215File must be trivially copyable.");
328 280
329struct TagInfo { 281// This is nn::nfp::CommonInfo
330 UniqueSerialNumber uuid;
331 INSERT_PADDING_BYTES(0x3);
332 u8 uuid_length;
333 INSERT_PADDING_BYTES(0x15);
334 TagProtocol protocol;
335 TagType tag_type;
336 INSERT_PADDING_BYTES(0x30);
337};
338static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size");
339
340struct CommonInfo { 282struct CommonInfo {
341 WriteDate last_write_date; 283 WriteDate last_write_date;
342 u16 write_counter; 284 u16 write_counter;
@@ -347,6 +289,7 @@ struct CommonInfo {
347}; 289};
348static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size"); 290static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
349 291
292// This is nn::nfp::ModelInfo
350struct ModelInfo { 293struct ModelInfo {
351 u16 character_id; 294 u16 character_id;
352 u8 character_variant; 295 u8 character_variant;
@@ -357,6 +300,7 @@ struct ModelInfo {
357}; 300};
358static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); 301static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
359 302
303// This is nn::nfp::RegisterInfo
360struct RegisterInfo { 304struct RegisterInfo {
361 Service::Mii::CharInfo mii_char_info; 305 Service::Mii::CharInfo mii_char_info;
362 WriteDate creation_date; 306 WriteDate creation_date;
@@ -366,6 +310,7 @@ struct RegisterInfo {
366}; 310};
367static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); 311static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
368 312
313// This is nn::nfp::RegisterInfoPrivate
369struct RegisterInfoPrivate { 314struct RegisterInfoPrivate {
370 Service::Mii::MiiStoreData mii_store_data; 315 Service::Mii::MiiStoreData mii_store_data;
371 WriteDate creation_date; 316 WriteDate creation_date;
@@ -375,12 +320,13 @@ struct RegisterInfoPrivate {
375}; 320};
376static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size"); 321static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size");
377 322
323// This is nn::nfp::AdminInfo
378struct AdminInfo { 324struct AdminInfo {
379 u64 application_id; 325 u64 application_id;
380 u32 application_area_id; 326 u32 application_area_id;
381 u16 crc_change_counter; 327 u16 crc_change_counter;
382 u8 flags; 328 u8 flags;
383 PackedTagType tag_type; 329 NFC::PackedTagType tag_type;
384 AppAreaVersion app_area_version; 330 AppAreaVersion app_area_version;
385 INSERT_PADDING_BYTES(0x7); 331 INSERT_PADDING_BYTES(0x7);
386 INSERT_PADDING_BYTES(0x28); 332 INSERT_PADDING_BYTES(0x28);
@@ -411,7 +357,7 @@ struct NfpData {
411 u32 access_id; 357 u32 access_id;
412 u16 settings_crc_counter; 358 u16 settings_crc_counter;
413 u8 font_region; 359 u8 font_region;
414 PackedTagType tag_type; 360 NFC::PackedTagType tag_type;
415 AppAreaVersion console_type; 361 AppAreaVersion console_type;
416 u8 application_id_byte; 362 u8 application_id_byte;
417 INSERT_PADDING_BYTES(0x2E); 363 INSERT_PADDING_BYTES(0x2E);
@@ -420,37 +366,4 @@ struct NfpData {
420static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size"); 366static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size");
421#pragma pack() 367#pragma pack()
422 368
423struct SectorKey {
424 MifareCmd command;
425 u8 unknown; // Usually 1
426 INSERT_PADDING_BYTES(0x6);
427 KeyData sector_key;
428 INSERT_PADDING_BYTES(0x2);
429};
430static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");
431
432struct MifareReadBlockParameter {
433 u8 sector_number;
434 INSERT_PADDING_BYTES(0x7);
435 SectorKey sector_key;
436};
437static_assert(sizeof(MifareReadBlockParameter) == 0x18,
438 "MifareReadBlockParameter is an invalid size");
439
440struct MifareReadBlockData {
441 DataBlock data;
442 u8 sector_number;
443 INSERT_PADDING_BYTES(0x7);
444};
445static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size");
446
447struct MifareWriteBlockParameter {
448 DataBlock data;
449 u8 sector_number;
450 INSERT_PADDING_BYTES(0x7);
451 SectorKey sector_key;
452};
453static_assert(sizeof(MifareWriteBlockParameter) == 0x28,
454 "MifareWriteBlockParameter is an invalid size");
455
456} // namespace Service::NFP 369} // namespace Service::NFP
diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp
index 4559df5b1..4988fcc83 100644
--- a/src/yuzu/applets/qt_amiibo_settings.cpp
+++ b/src/yuzu/applets/qt_amiibo_settings.cpp
@@ -8,7 +8,7 @@
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "core/hle/service/nfp/nfp_device.h" 11#include "core/hle/service/nfc/common/device.h"
12#include "core/hle/service/nfp/nfp_result.h" 12#include "core/hle/service/nfp/nfp_result.h"
13#include "input_common/drivers/virtual_amiibo.h" 13#include "input_common/drivers/virtual_amiibo.h"
14#include "input_common/main.h" 14#include "input_common/main.h"
@@ -22,7 +22,7 @@
22QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent, 22QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent,
23 Core::Frontend::CabinetParameters parameters_, 23 Core::Frontend::CabinetParameters parameters_,
24 InputCommon::InputSubsystem* input_subsystem_, 24 InputCommon::InputSubsystem* input_subsystem_,
25 std::shared_ptr<Service::NFP::NfpDevice> nfp_device_) 25 std::shared_ptr<Service::NFC::NfcDevice> nfp_device_)
26 : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboSettingsDialog>()), 26 : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboSettingsDialog>()),
27 input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)}, 27 input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)},
28 parameters(std::move(parameters_)) { 28 parameters(std::move(parameters_)) {
@@ -52,11 +52,11 @@ void QtAmiiboSettingsDialog::LoadInfo() {
52 return; 52 return;
53 } 53 }
54 54
55 if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && 55 if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound &&
56 nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { 56 nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) {
57 return; 57 return;
58 } 58 }
59 nfp_device->Mount(Service::NFP::MountTarget::All); 59 nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All);
60 60
61 LoadAmiiboInfo(); 61 LoadAmiiboInfo();
62 LoadAmiiboData(); 62 LoadAmiiboData();
@@ -261,7 +261,7 @@ void QtAmiiboSettings::Close() const {
261void QtAmiiboSettings::ShowCabinetApplet( 261void QtAmiiboSettings::ShowCabinetApplet(
262 const Core::Frontend::CabinetCallback& callback_, 262 const Core::Frontend::CabinetCallback& callback_,
263 const Core::Frontend::CabinetParameters& parameters, 263 const Core::Frontend::CabinetParameters& parameters,
264 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const { 264 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const {
265 callback = std::move(callback_); 265 callback = std::move(callback_);
266 emit MainWindowShowAmiiboSettings(parameters, nfp_device); 266 emit MainWindowShowAmiiboSettings(parameters, nfp_device);
267} 267}
diff --git a/src/yuzu/applets/qt_amiibo_settings.h b/src/yuzu/applets/qt_amiibo_settings.h
index bc389a33f..ee66a0255 100644
--- a/src/yuzu/applets/qt_amiibo_settings.h
+++ b/src/yuzu/applets/qt_amiibo_settings.h
@@ -23,9 +23,9 @@ namespace Ui {
23class QtAmiiboSettingsDialog; 23class QtAmiiboSettingsDialog;
24} 24}
25 25
26namespace Service::NFP { 26namespace Service::NFC {
27class NfpDevice; 27class NfcDevice;
28} // namespace Service::NFP 28} // namespace Service::NFC
29 29
30class QtAmiiboSettingsDialog final : public QDialog { 30class QtAmiiboSettingsDialog final : public QDialog {
31 Q_OBJECT 31 Q_OBJECT
@@ -33,7 +33,7 @@ class QtAmiiboSettingsDialog final : public QDialog {
33public: 33public:
34 explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_, 34 explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_,
35 InputCommon::InputSubsystem* input_subsystem_, 35 InputCommon::InputSubsystem* input_subsystem_,
36 std::shared_ptr<Service::NFP::NfpDevice> nfp_device_); 36 std::shared_ptr<Service::NFC::NfcDevice> nfp_device_);
37 ~QtAmiiboSettingsDialog() override; 37 ~QtAmiiboSettingsDialog() override;
38 38
39 int exec() override; 39 int exec() override;
@@ -52,7 +52,7 @@ private:
52 std::unique_ptr<Ui::QtAmiiboSettingsDialog> ui; 52 std::unique_ptr<Ui::QtAmiiboSettingsDialog> ui;
53 53
54 InputCommon::InputSubsystem* input_subsystem; 54 InputCommon::InputSubsystem* input_subsystem;
55 std::shared_ptr<Service::NFP::NfpDevice> nfp_device; 55 std::shared_ptr<Service::NFC::NfcDevice> nfp_device;
56 56
57 // Parameters sent in from the backend HLE applet. 57 // Parameters sent in from the backend HLE applet.
58 Core::Frontend::CabinetParameters parameters; 58 Core::Frontend::CabinetParameters parameters;
@@ -71,11 +71,11 @@ public:
71 void Close() const override; 71 void Close() const override;
72 void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_, 72 void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_,
73 const Core::Frontend::CabinetParameters& parameters, 73 const Core::Frontend::CabinetParameters& parameters,
74 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; 74 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const override;
75 75
76signals: 76signals:
77 void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters, 77 void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters,
78 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const; 78 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const;
79 void MainWindowRequestExit() const; 79 void MainWindowRequestExit() const;
80 80
81private: 81private:
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b79409a68..e051e35df 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -570,8 +570,8 @@ void GMainWindow::RegisterMetaTypes() {
570 570
571 // Cabinet Applet 571 // Cabinet Applet
572 qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters"); 572 qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters");
573 qRegisterMetaType<std::shared_ptr<Service::NFP::NfpDevice>>( 573 qRegisterMetaType<std::shared_ptr<Service::NFC::NfcDevice>>(
574 "std::shared_ptr<Service::NFP::NfpDevice>"); 574 "std::shared_ptr<Service::NFC::NfcDevice>");
575 575
576 // Controller Applet 576 // Controller Applet
577 qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); 577 qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
@@ -599,7 +599,7 @@ void GMainWindow::RegisterMetaTypes() {
599} 599}
600 600
601void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, 601void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
602 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) { 602 std::shared_ptr<Service::NFC::NfcDevice> nfp_device) {
603 cabinet_applet = 603 cabinet_applet =
604 new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device); 604 new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device);
605 SCOPE_EXIT({ 605 SCOPE_EXIT({
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 8b5c1d747..ac90bd5ae 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -93,9 +93,9 @@ enum class SwkbdReplyType : u32;
93enum class WebExitReason : u32; 93enum class WebExitReason : u32;
94} // namespace Service::AM::Applets 94} // namespace Service::AM::Applets
95 95
96namespace Service::NFP { 96namespace Service::NFC {
97class NfpDevice; 97class NfcDevice;
98} // namespace Service::NFP 98} // namespace Service::NFC
99 99
100namespace Ui { 100namespace Ui {
101class MainWindow; 101class MainWindow;
@@ -188,7 +188,7 @@ public slots:
188 void OnExit(); 188 void OnExit();
189 void OnSaveConfig(); 189 void OnSaveConfig();
190 void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, 190 void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
191 std::shared_ptr<Service::NFP::NfpDevice> nfp_device); 191 std::shared_ptr<Service::NFC::NfcDevice> nfp_device);
192 void AmiiboSettingsRequestExit(); 192 void AmiiboSettingsRequestExit();
193 void ControllerSelectorReconfigureControllers( 193 void ControllerSelectorReconfigureControllers(
194 const Core::Frontend::ControllerParameters& parameters); 194 const Core::Frontend::ControllerParameters& parameters);