From e40d69305785a380dd935174f9dc0bfcae28ae43 Mon Sep 17 00:00:00 2001
From: wwylele <wwylele@gmail.com>
Date: Mon, 5 Mar 2018 10:48:09 +0200
Subject: [PATCH] Service/NFC: convert to ServiceFramework

---
 src/core/hle/service/nfc/nfc.cpp   | 137 ++++++++--------
 src/core/hle/service/nfc/nfc.h     | 246 ++++++++++++++++-------------
 src/core/hle/service/nfc/nfc_m.cpp |  66 ++++----
 src/core/hle/service/nfc/nfc_m.h   |  10 +-
 src/core/hle/service/nfc/nfc_u.cpp |  60 ++++---
 src/core/hle/service/nfc/nfc_u.h   |  10 +-
 src/core/hle/service/service.cpp   |   3 +-
 7 files changed, 272 insertions(+), 260 deletions(-)

diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 56c56fe83..0d19fdc65 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -2,10 +2,8 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "core/hle/ipc.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/event.h"
-#include "core/hle/kernel/handle_table.h"
 #include "core/hle/service/nfc/nfc.h"
 #include "core/hle/service/nfc/nfc_m.h"
 #include "core/hle/service/nfc/nfc_u.h"
@@ -13,48 +11,46 @@
 namespace Service {
 namespace NFC {
 
-static Kernel::SharedPtr<Kernel::Event> tag_in_range_event;
-static Kernel::SharedPtr<Kernel::Event> tag_out_of_range_event;
-static TagState nfc_tag_state = TagState::NotInitialized;
-static CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
+void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x01, 1, 0);
+    u8 param = rp.Pop<u8>();
 
-void Initialize(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+    nfc->nfc_tag_state = TagState::NotScanning;
 
-    u8 param = static_cast<u8>(cmd_buff[1] & 0xFF);
-
-    nfc_tag_state = TagState::NotScanning;
-
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called, param=%u", param);
 }
 
-void Shutdown(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::Shutdown(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x02, 1, 0);
+    u8 param = rp.Pop<u8>();
 
-    u8 param = static_cast<u8>(cmd_buff[1] & 0xFF);
-    nfc_tag_state = TagState::NotInitialized;
+    nfc->nfc_tag_state = TagState::NotInitialized;
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called, param=%u", param);
 }
 
-void StartCommunication(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::StartCommunication(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x03, 0, 0);
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void StopCommunication(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::StopCommunication(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x04, 0, 0);
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void StartTagScanning(Interface* self) {
-    IPC::RequestParser rp(Kernel::GetCommandBuffer(), 5, 1, 0); // 0x00050040
+void Module::Interface::StartTagScanning(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x05, 1, 0); // 0x00050040
     u16 in_val = rp.Pop<u16>();
 
     ResultCode result = RESULT_SUCCESS;
@@ -64,8 +60,8 @@ void StartTagScanning(Interface* self) {
                         ErrorSummary::InvalidState, ErrorLevel::Status);
 
     if (result == RESULT_SUCCESS) {
-        nfc_tag_state = TagState::TagInRange;
-        tag_in_range_event->Signal();
+        nfc->nfc_tag_state = TagState::TagInRange;
+        nfc->tag_in_range_event->Signal();
     }
 
     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@@ -73,83 +69,90 @@ void StartTagScanning(Interface* self) {
     LOG_WARNING(Service_NFC, "(STUBBED) called, in_val=%04x", in_val);
 }
 
-void StopTagScanning(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::StopTagScanning(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x06, 0, 0);
 
-    nfc_tag_state = TagState::NotScanning;
+    nfc->nfc_tag_state = TagState::NotScanning;
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void LoadAmiiboData(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::LoadAmiiboData(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x07, 0, 0);
 
-    nfc_tag_state = TagState::TagDataLoaded;
+    nfc->nfc_tag_state = TagState::TagDataLoaded;
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void ResetTagScanState(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::ResetTagScanState(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x08, 0, 0);
 
-    nfc_tag_state = TagState::NotScanning;
+    nfc->nfc_tag_state = TagState::NotScanning;
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
+    rb.Push(RESULT_SUCCESS);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void GetTagInRangeEvent(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::GetTagInRangeEvent(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x0B, 0, 0);
 
-    cmd_buff[0] = IPC::MakeHeader(0xB, 1, 2);
-    cmd_buff[1] = RESULT_SUCCESS.raw;
-    cmd_buff[2] = IPC::CopyHandleDesc();
-    cmd_buff[3] = Kernel::g_handle_table.Create(tag_in_range_event).Unwrap();
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
+    rb.Push(RESULT_SUCCESS);
+    rb.PushCopyObjects(nfc->tag_in_range_event);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void GetTagOutOfRangeEvent(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::GetTagOutOfRangeEvent(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x0C, 0, 0);
 
-    cmd_buff[0] = IPC::MakeHeader(0xC, 1, 2);
-    cmd_buff[1] = RESULT_SUCCESS.raw;
-    cmd_buff[2] = IPC::CopyHandleDesc();
-    cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).Unwrap();
+    IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
+    rb.Push(RESULT_SUCCESS);
+    rb.PushCopyObjects(nfc->tag_out_of_range_event);
     LOG_WARNING(Service_NFC, "(STUBBED) called");
 }
 
-void GetTagState(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::GetTagState(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x0D, 0, 0);
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
-    cmd_buff[2] = static_cast<u8>(nfc_tag_state);
+    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
+    rb.Push(RESULT_SUCCESS);
+    rb.PushEnum(nfc->nfc_tag_state);
     LOG_DEBUG(Service_NFC, "(STUBBED) called");
 }
 
-void CommunicationGetStatus(Interface* self) {
-    u32* cmd_buff = Kernel::GetCommandBuffer();
+void Module::Interface::CommunicationGetStatus(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp(ctx, 0x0F, 0, 0);
 
-    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
-    cmd_buff[2] = static_cast<u8>(nfc_status);
+    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
+    rb.Push(RESULT_SUCCESS);
+    rb.PushEnum(nfc->nfc_status);
     LOG_DEBUG(Service_NFC, "(STUBBED) called");
 }
 
-void Init() {
-    AddService(new NFC_M());
-    AddService(new NFC_U());
+Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session)
+    : ServiceFramework(name, max_session), nfc(std::move(nfc)) {}
 
+Module::Interface::~Interface() = default;
+
+Module::Module() {
     tag_in_range_event =
         Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
     tag_out_of_range_event =
         Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_out_range_event");
-    nfc_tag_state = TagState::NotInitialized;
 }
 
-void Shutdown() {
-    tag_in_range_event = nullptr;
-    tag_out_of_range_event = nullptr;
+Module::~Module() = default;
+
+void InstallInterfaces(SM::ServiceManager& service_manager) {
+    auto nfc = std::make_shared<Module>();
+    std::make_shared<NFC_M>(nfc)->InstallAsService(service_manager);
+    std::make_shared<NFC_U>(nfc)->InstallAsService(service_manager);
 }
 
 } // namespace NFC
diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h
index 57f8d86b2..89530706d 100644
--- a/src/core/hle/service/nfc/nfc.h
+++ b/src/core/hle/service/nfc/nfc.h
@@ -4,12 +4,16 @@
 
 #pragma once
 
+#include <memory>
 #include "common/common_types.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class Event;
+} // namespace Kernel
 
 namespace Service {
-
-class Interface;
-
 namespace NFC {
 
 namespace ErrCodes {
@@ -32,128 +36,146 @@ enum class CommunicationStatus : u8 {
     NfcInitialized = 2,
 };
 
-/**
- * NFC::Initialize service function
- *  Inputs:
- *      0 : Header code [0x00010040]
- *      1 : (u8) unknown parameter. Can be either value 0x1 or 0x2
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void Initialize(Interface* self);
+class Module final {
+public:
+    Module();
+    ~Module();
 
-/**
- * NFC::Shutdown service function
- *  Inputs:
- *      0 : Header code [0x00020040]
- *      1 : (u8) unknown parameter
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void Shutdown(Interface* self);
+    class Interface : public ServiceFramework<Interface> {
+    public:
+        Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session);
+        ~Interface();
 
-/**
- * NFC::StartCommunication service function
- *  Inputs:
- *      0 : Header code [0x00030000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void StartCommunication(Interface* self);
+    protected:
+        /**
+         * NFC::Initialize service function
+         *  Inputs:
+         *      0 : Header code [0x00010040]
+         *      1 : (u8) unknown parameter. Can be either value 0x1 or 0x2
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void Initialize(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::StopCommunication service function
- *  Inputs:
- *      0 : Header code [0x00040000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void StopCommunication(Interface* self);
+        /**
+         * NFC::Shutdown service function
+         *  Inputs:
+         *      0 : Header code [0x00020040]
+         *      1 : (u8) unknown parameter
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void Shutdown(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::StartTagScanning service function
- *  Inputs:
- *      0 : Header code [0x00050040]
- *      1 : (u16) unknown. This is normally 0x0
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void StartTagScanning(Interface* self);
+        /**
+         * NFC::StartCommunication service function
+         *  Inputs:
+         *      0 : Header code [0x00030000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void StartCommunication(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::StopTagScanning service function
- *  Inputs:
- *      0 : Header code [0x00060000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void StopTagScanning(Interface* self);
+        /**
+         * NFC::StopCommunication service function
+         *  Inputs:
+         *      0 : Header code [0x00040000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void StopCommunication(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::LoadAmiiboData service function
- *  Inputs:
- *      0 : Header code [0x00070000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void LoadAmiiboData(Interface* self);
+        /**
+         * NFC::StartTagScanning service function
+         *  Inputs:
+         *      0 : Header code [0x00050040]
+         *      1 : (u16) unknown. This is normally 0x0
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void StartTagScanning(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::ResetTagScanState service function
- *  Inputs:
- *      0 : Header code [0x00080000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- */
-void ResetTagScanState(Interface* self);
+        /**
+         * NFC::StopTagScanning service function
+         *  Inputs:
+         *      0 : Header code [0x00060000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void StopTagScanning(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::GetTagInRangeEvent service function
- *  Inputs:
- *      0 : Header code [0x000B0000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- *      2 : Copy handle descriptor
- *      3 : Event Handle
- */
-void GetTagInRangeEvent(Interface* self);
+        /**
+         * NFC::LoadAmiiboData service function
+         *  Inputs:
+         *      0 : Header code [0x00070000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void LoadAmiiboData(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::GetTagOutOfRangeEvent service function
- *  Inputs:
- *      0 : Header code [0x000C0000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- *      2 : Copy handle descriptor
- *      3 : Event Handle
- */
-void GetTagOutOfRangeEvent(Interface* self);
+        /**
+         * NFC::ResetTagScanState service function
+         *  Inputs:
+         *      0 : Header code [0x00080000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         */
+        void ResetTagScanState(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::GetTagState service function
- *  Inputs:
- *      0 : Header code [0x000D0000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- *      2 : (u8) Tag state
- */
-void GetTagState(Interface* self);
+        /**
+         * NFC::GetTagInRangeEvent service function
+         *  Inputs:
+         *      0 : Header code [0x000B0000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         *      2 : Copy handle descriptor
+         *      3 : Event Handle
+         */
+        void GetTagInRangeEvent(Kernel::HLERequestContext& ctx);
 
-/**
- * NFC::CommunicationGetStatus service function
- *  Inputs:
- *      0 : Header code [0x000F0000]
- *  Outputs:
- *      1 : Result of function, 0 on success, otherwise error code
- *      2 : (u8) Communication state
- */
-void CommunicationGetStatus(Interface* self);
+        /**
+         * NFC::GetTagOutOfRangeEvent service function
+         *  Inputs:
+         *      0 : Header code [0x000C0000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         *      2 : Copy handle descriptor
+         *      3 : Event Handle
+         */
+        void GetTagOutOfRangeEvent(Kernel::HLERequestContext& ctx);
 
-/// Initialize all NFC services.
-void Init();
+        /**
+         * NFC::GetTagState service function
+         *  Inputs:
+         *      0 : Header code [0x000D0000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         *      2 : (u8) Tag state
+         */
+        void GetTagState(Kernel::HLERequestContext& ctx);
 
-/// Shutdown all NFC services.
-void Shutdown();
+        /**
+         * NFC::CommunicationGetStatus service function
+         *  Inputs:
+         *      0 : Header code [0x000F0000]
+         *  Outputs:
+         *      1 : Result of function, 0 on success, otherwise error code
+         *      2 : (u8) Communication state
+         */
+        void CommunicationGetStatus(Kernel::HLERequestContext& ctx);
+
+    private:
+        std::shared_ptr<Module> nfc;
+    };
+
+private:
+    Kernel::SharedPtr<Kernel::Event> tag_in_range_event;
+    Kernel::SharedPtr<Kernel::Event> tag_out_of_range_event;
+    TagState nfc_tag_state = TagState::NotInitialized;
+    CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
+};
+
+void InstallInterfaces(SM::ServiceManager& service_manager);
 
 } // namespace NFC
 } // namespace Service
diff --git a/src/core/hle/service/nfc/nfc_m.cpp b/src/core/hle/service/nfc/nfc_m.cpp
index ebe637650..032bda0d6 100644
--- a/src/core/hle/service/nfc/nfc_m.cpp
+++ b/src/core/hle/service/nfc/nfc_m.cpp
@@ -2,45 +2,43 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "core/hle/service/nfc/nfc.h"
 #include "core/hle/service/nfc/nfc_m.h"
 
 namespace Service {
 namespace NFC {
 
-const Interface::FunctionInfo FunctionTable[] = {
-    // clang-format off
-    // nfc:u shared commands
-    {0x00010040, Initialize, "Initialize"},
-    {0x00020040, Shutdown, "Shutdown"},
-    {0x00030000, StartCommunication, "StartCommunication"},
-    {0x00040000, StopCommunication, "StopCommunication"},
-    {0x00050040, StartTagScanning, "StartTagScanning"},
-    {0x00060000, StopTagScanning, "StopTagScanning"},
-    {0x00070000, LoadAmiiboData, "LoadAmiiboData"},
-    {0x00080000, ResetTagScanState, "ResetTagScanState"},
-    {0x00090002, nullptr, "UpdateStoredAmiiboData"},
-    {0x000B0000, GetTagInRangeEvent, "GetTagInRangeEvent"},
-    {0x000C0000, GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"},
-    {0x000D0000, GetTagState, "GetTagState"},
-    {0x000F0000, CommunicationGetStatus, "CommunicationGetStatus"},
-    {0x00100000, nullptr, "GetTagInfo2"},
-    {0x00110000, nullptr, "GetTagInfo"},
-    {0x00120000, nullptr, "CommunicationGetResult"},
-    {0x00130040, nullptr, "OpenAppData"},
-    {0x00140384, nullptr, "InitializeWriteAppData"},
-    {0x00150040, nullptr, "ReadAppData"},
-    {0x00160242, nullptr, "WriteAppData"},
-    {0x00170000, nullptr, "GetAmiiboSettings"},
-    {0x00180000, nullptr, "GetAmiiboConfig"},
-    {0x00190000, nullptr, "GetAppDataInitStruct"},
-    // nfc:m
-    {0x04040A40, nullptr, "SetAmiiboSettings"}
-    // clang-format on
-};
-
-NFC_M::NFC_M() {
-    Register(FunctionTable);
+NFC_M::NFC_M(std::shared_ptr<Module> nfc) : Module::Interface(std::move(nfc), "nfc:m", 1) {
+    static const FunctionInfo functions[] = {
+        // clang-format off
+        // nfc:u shared commands
+        {0x00010040, &NFC_M::Initialize, "Initialize"},
+        {0x00020040, &NFC_M::Shutdown, "Shutdown"},
+        {0x00030000, &NFC_M::StartCommunication, "StartCommunication"},
+        {0x00040000, &NFC_M::StopCommunication, "StopCommunication"},
+        {0x00050040, &NFC_M::StartTagScanning, "StartTagScanning"},
+        {0x00060000, &NFC_M::StopTagScanning, "StopTagScanning"},
+        {0x00070000, &NFC_M::LoadAmiiboData, "LoadAmiiboData"},
+        {0x00080000, &NFC_M::ResetTagScanState, "ResetTagScanState"},
+        {0x00090002, nullptr, "UpdateStoredAmiiboData"},
+        {0x000B0000, &NFC_M::GetTagInRangeEvent, "GetTagInRangeEvent"},
+        {0x000C0000, &NFC_M::GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"},
+        {0x000D0000, &NFC_M::GetTagState, "GetTagState"},
+        {0x000F0000, &NFC_M::CommunicationGetStatus, "CommunicationGetStatus"},
+        {0x00100000, nullptr, "GetTagInfo2"},
+        {0x00110000, nullptr, "GetTagInfo"},
+        {0x00120000, nullptr, "CommunicationGetResult"},
+        {0x00130040, nullptr, "OpenAppData"},
+        {0x00140384, nullptr, "InitializeWriteAppData"},
+        {0x00150040, nullptr, "ReadAppData"},
+        {0x00160242, nullptr, "WriteAppData"},
+        {0x00170000, nullptr, "GetAmiiboSettings"},
+        {0x00180000, nullptr, "GetAmiiboConfig"},
+        {0x00190000, nullptr, "GetAppDataInitStruct"},
+        // nfc:m
+        {0x04040A40, nullptr, "SetAmiiboSettings"}
+        // clang-format on
+    };
+    RegisterHandlers(functions);
 }
 
 } // namespace NFC
diff --git a/src/core/hle/service/nfc/nfc_m.h b/src/core/hle/service/nfc/nfc_m.h
index fae75535b..207b7b263 100644
--- a/src/core/hle/service/nfc/nfc_m.h
+++ b/src/core/hle/service/nfc/nfc_m.h
@@ -4,18 +4,14 @@
 
 #pragma once
 
-#include "core/hle/service/service.h"
+#include "core/hle/service/nfc/nfc.h"
 
 namespace Service {
 namespace NFC {
 
-class NFC_M final : public Interface {
+class NFC_M final : public Module::Interface {
 public:
-    NFC_M();
-
-    std::string GetPortName() const override {
-        return "nfc:m";
-    }
+    explicit NFC_M(std::shared_ptr<Module> nfc);
 };
 
 } // namespace NFC
diff --git a/src/core/hle/service/nfc/nfc_u.cpp b/src/core/hle/service/nfc/nfc_u.cpp
index 5a40c7874..ff1310749 100644
--- a/src/core/hle/service/nfc/nfc_u.cpp
+++ b/src/core/hle/service/nfc/nfc_u.cpp
@@ -2,42 +2,40 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "core/hle/service/nfc/nfc.h"
 #include "core/hle/service/nfc/nfc_u.h"
 
 namespace Service {
 namespace NFC {
 
-const Interface::FunctionInfo FunctionTable[] = {
-    // clang-format off
-    {0x00010040, Initialize, "Initialize"},
-    {0x00020040, Shutdown, "Shutdown"},
-    {0x00030000, StartCommunication, "StartCommunication"},
-    {0x00040000, StopCommunication, "StopCommunication"},
-    {0x00050040, StartTagScanning, "StartTagScanning"},
-    {0x00060000, StopTagScanning, "StopTagScanning"},
-    {0x00070000, LoadAmiiboData, "LoadAmiiboData"},
-    {0x00080000, ResetTagScanState, "ResetTagScanState"},
-    {0x00090002, nullptr, "UpdateStoredAmiiboData"},
-    {0x000B0000, GetTagInRangeEvent, "GetTagInRangeEvent"},
-    {0x000C0000, GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"},
-    {0x000D0000, GetTagState, "GetTagState"},
-    {0x000F0000, CommunicationGetStatus, "CommunicationGetStatus"},
-    {0x00100000, nullptr, "GetTagInfo2"},
-    {0x00110000, nullptr, "GetTagInfo"},
-    {0x00120000, nullptr, "CommunicationGetResult"},
-    {0x00130040, nullptr, "OpenAppData"},
-    {0x00140384, nullptr, "InitializeWriteAppData"},
-    {0x00150040, nullptr, "ReadAppData"},
-    {0x00160242, nullptr, "WriteAppData"},
-    {0x00170000, nullptr, "GetAmiiboSettings"},
-    {0x00180000, nullptr, "GetAmiiboConfig"},
-    {0x00190000, nullptr, "GetAppDataInitStruct"},
-    // clang-format on
-};
-
-NFC_U::NFC_U() {
-    Register(FunctionTable);
+NFC_U::NFC_U(std::shared_ptr<Module> nfc) : Module::Interface(std::move(nfc), "nfc:u", 1) {
+    static const FunctionInfo functions[] = {
+        // clang-format off
+        {0x00010040, &NFC_U::Initialize, "Initialize"},
+        {0x00020040, &NFC_U::Shutdown, "Shutdown"},
+        {0x00030000, &NFC_U::StartCommunication, "StartCommunication"},
+        {0x00040000, &NFC_U::StopCommunication, "StopCommunication"},
+        {0x00050040, &NFC_U::StartTagScanning, "StartTagScanning"},
+        {0x00060000, &NFC_U::StopTagScanning, "StopTagScanning"},
+        {0x00070000, &NFC_U::LoadAmiiboData, "LoadAmiiboData"},
+        {0x00080000, &NFC_U::ResetTagScanState, "ResetTagScanState"},
+        {0x00090002, nullptr, "UpdateStoredAmiiboData"},
+        {0x000B0000, &NFC_U::GetTagInRangeEvent, "GetTagInRangeEvent"},
+        {0x000C0000, &NFC_U::GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"},
+        {0x000D0000, &NFC_U::GetTagState, "GetTagState"},
+        {0x000F0000, &NFC_U::CommunicationGetStatus, "CommunicationGetStatus"},
+        {0x00100000, nullptr, "GetTagInfo2"},
+        {0x00110000, nullptr, "GetTagInfo"},
+        {0x00120000, nullptr, "CommunicationGetResult"},
+        {0x00130040, nullptr, "OpenAppData"},
+        {0x00140384, nullptr, "InitializeWriteAppData"},
+        {0x00150040, nullptr, "ReadAppData"},
+        {0x00160242, nullptr, "WriteAppData"},
+        {0x00170000, nullptr, "GetAmiiboSettings"},
+        {0x00180000, nullptr, "GetAmiiboConfig"},
+        {0x00190000, nullptr, "GetAppDataInitStruct"},
+        // clang-format on
+    };
+    RegisterHandlers(functions);
 }
 
 } // namespace NFC
diff --git a/src/core/hle/service/nfc/nfc_u.h b/src/core/hle/service/nfc/nfc_u.h
index eb7507314..ef23c6763 100644
--- a/src/core/hle/service/nfc/nfc_u.h
+++ b/src/core/hle/service/nfc/nfc_u.h
@@ -4,18 +4,14 @@
 
 #pragma once
 
-#include "core/hle/service/service.h"
+#include "core/hle/service/nfc/nfc.h"
 
 namespace Service {
 namespace NFC {
 
-class NFC_U final : public Interface {
+class NFC_U final : public Module::Interface {
 public:
-    NFC_U();
-
-    std::string GetPortName() const override {
-        return "nfc:u";
-    }
+    explicit NFC_U(std::shared_ptr<Module> nfc);
 };
 
 } // namespace NFC
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index fe6ed7a96..534a65706 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -251,7 +251,7 @@ void Init() {
     MVD::Init();
     NDM::Init();
     NEWS::InstallInterfaces(*SM::g_service_manager);
-    NFC::Init();
+    NFC::InstallInterfaces(*SM::g_service_manager);
     NIM::InstallInterfaces(*SM::g_service_manager);
     NWM::Init();
     PTM::InstallInterfaces(*SM::g_service_manager);
@@ -271,7 +271,6 @@ void Init() {
 
 /// Shutdown ServiceManager
 void Shutdown() {
-    NFC::Shutdown();
     NDM::Shutdown();
     DLP::Shutdown();
     CFG::Shutdown();