From 0add6b7d7a19718d76ce6c400e15895ea538553e Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Mon, 24 Apr 2023 21:58:35 +0300 Subject: [PATCH] [NFC] Tag events --- include/services/nfc.hpp | 11 ++++++- src/core/services/nfc.cpp | 47 +++++++++++++++++++++++++-- src/core/services/service_manager.cpp | 2 +- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/include/services/nfc.hpp b/include/services/nfc.hpp index 13a1a380..9f626037 100644 --- a/include/services/nfc.hpp +++ b/include/services/nfc.hpp @@ -4,16 +4,25 @@ #include "logger.hpp" #include "memory.hpp" +// You know the drill +class Kernel; + class NFCService { Handle handle = KernelHandles::NFC; Memory& mem; + Kernel& kernel; MAKE_LOG_FUNCTION(log, nfcLogger) + // Kernel events signaled when an NFC tag goes in and out of range respectively + std::optional tagInRangeEvent, tagOutOfRangeEvent; + // Service commands void initialize(u32 messagePointer); + void getTagInRangeEvent(u32 messagePointer); + void getTagOutOfRangeEvent(u32 messagePointer); public: - NFCService(Memory& mem) : mem(mem) {} + NFCService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} void reset(); void handleSyncRequest(u32 messagePointer); }; \ No newline at end of file diff --git a/src/core/services/nfc.cpp b/src/core/services/nfc.cpp index 798f465a..833922eb 100644 --- a/src/core/services/nfc.cpp +++ b/src/core/services/nfc.cpp @@ -1,9 +1,12 @@ #include "services/nfc.hpp" #include "ipc.hpp" +#include "kernel.hpp" namespace NFCCommands { enum : u32 { - Initialize = 0x00010040 + Initialize = 0x00010040, + GetTagInRangeEvent = 0x000B0000, + GetTagOutOfRangeEvent = 0x000C0000 }; } @@ -13,12 +16,17 @@ namespace Result { }; } -void NFCService::reset() {} +void NFCService::reset() { + tagInRangeEvent = std::nullopt; + tagOutOfRangeEvent = std::nullopt; +} void NFCService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { case NFCCommands::Initialize: initialize(messagePointer); break; + case NFCCommands::GetTagInRangeEvent: getTagInRangeEvent(messagePointer); break; + case NFCCommands::GetTagOutOfRangeEvent: getTagOutOfRangeEvent(messagePointer); break; default: Helpers::panic("NFC service requested. Command: %08X\n", command); } } @@ -30,4 +38,39 @@ void NFCService::initialize(u32 messagePointer) { // TODO: This should error if already initialized. Also sanitize type. mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 0)); mem.write32(messagePointer + 4, Result::Success); +} + +/* + The NFC service provides userland with 2 events. One that is signaled when an NFC tag gets in range, + And one that is signaled when it gets out of range. Userland can have a thread sleep on this so it will be alerted + Whenever an Amiibo or misc NFC tag is presented or removed. + These events are retrieved via the GetTagInRangeEvent and GetTagOutOfRangeEvent function respectively +*/ + +void NFCService::getTagInRangeEvent(u32 messagePointer) { + log("NFC::GetTagInRangeEvent\n"); + + // Create event if it doesn't exist + if (!tagInRangeEvent.has_value()) { + tagInRangeEvent = kernel.makeEvent(ResetType::OneShot); + } + + mem.write32(messagePointer, IPC::responseHeader(0x0B, 1, 2)); + mem.write32(messagePointer + 4, Result::Success); + // TODO: Translation descriptor here + mem.write32(messagePointer + 12, tagInRangeEvent.value()); +} + +void NFCService::getTagOutOfRangeEvent(u32 messagePointer) { + log("NFC::GetTagOutOfRangeEvent\n"); + + // Create event if it doesn't exist + if (!tagOutOfRangeEvent.has_value()) { + tagOutOfRangeEvent = kernel.makeEvent(ResetType::OneShot); + } + + mem.write32(messagePointer, IPC::responseHeader(0x0C, 1, 2)); + mem.write32(messagePointer + 4, Result::Success); + // TODO: Translation descriptor here + mem.write32(messagePointer + 12, tagOutOfRangeEvent.value()); } \ No newline at end of file diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index 089ee172..082a8e9a 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -6,7 +6,7 @@ ServiceManager::ServiceManager(std::array& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel) : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem), cecd(mem), cfg(mem), dsp(mem, kernel), hid(mem), frd(mem), fs(mem, kernel), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), - ldr(mem), mic(mem), nfc(mem), nim(mem), ndm(mem), ptm(mem), y2r(mem, kernel) {} + ldr(mem), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem), ptm(mem), y2r(mem, kernel) {} static constexpr int MAX_NOTIFICATION_COUNT = 16;