diff --git a/include/services/cecd.hpp b/include/services/cecd.hpp index 4612c17b..b9374844 100644 --- a/include/services/cecd.hpp +++ b/include/services/cecd.hpp @@ -18,10 +18,13 @@ class CECDService { MAKE_LOG_FUNCTION(log, cecdLogger) std::optional infoEvent; + std::optional changeStateEvent; // Service commands + void getChangeStateEventHandle(u32 messagePointer); void getInfoEventHandle(u32 messagePointer); void openAndRead(u32 messagePointer); + void stop(u32 messagePointer); public: CECDService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} diff --git a/src/core/services/cecd.cpp b/src/core/services/cecd.cpp index 75a9f4f0..18ccbf53 100644 --- a/src/core/services/cecd.cpp +++ b/src/core/services/cecd.cpp @@ -5,18 +5,27 @@ namespace CECDCommands { enum : u32 { + Stop = 0x000C0040, GetInfoEventHandle = 0x000F0000, + GetChangeStateEventHandle = 0x00100000, OpenAndRead = 0x00120104, }; } -void CECDService::reset() { infoEvent = std::nullopt; } +void CECDService::reset() { + changeStateEvent = std::nullopt; + infoEvent = std::nullopt; +} void CECDService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); + switch (command) { case CECDCommands::GetInfoEventHandle: getInfoEventHandle(messagePointer); break; + case CECDCommands::GetChangeStateEventHandle: getChangeStateEventHandle(messagePointer); break; case CECDCommands::OpenAndRead: openAndRead(messagePointer); break; + case CECDCommands::Stop: stop(messagePointer); break; + default: Helpers::panicDev("CECD service requested. Command: %08X\n", command); mem.write32(messagePointer + 4, Result::Success); @@ -34,7 +43,20 @@ void CECDService::getInfoEventHandle(u32 messagePointer) { mem.write32(messagePointer, IPC::responseHeader(0xF, 1, 2)); mem.write32(messagePointer + 4, Result::Success); // TODO: Translation descriptor here? - mem.write32(messagePointer + 12, infoEvent.value()); + mem.write32(messagePointer + 12, *infoEvent); +} + +void CECDService::getChangeStateEventHandle(u32 messagePointer) { + log("CECD::GetChangeStateEventHandle (stubbed)\n"); + + if (!changeStateEvent.has_value()) { + changeStateEvent = kernel.makeEvent(ResetType::OneShot); + } + + mem.write32(messagePointer, IPC::responseHeader(0x10, 1, 2)); + mem.write32(messagePointer + 4, Result::Success); + // TODO: Translation descriptor here? + mem.write32(messagePointer + 12, *changeStateEvent); } void CECDService::openAndRead(u32 messagePointer) { @@ -48,4 +70,15 @@ void CECDService::openAndRead(u32 messagePointer) { mem.write32(messagePointer, IPC::responseHeader(0x12, 2, 2)); mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 8, 0); // Bytes read -} \ No newline at end of file +} + +void CECDService::stop(u32 messagePointer) { + log("CECD::Stop (stubbed)\n"); + + if (changeStateEvent.has_value()) { + kernel.signalEvent(*changeStateEvent); + } + + mem.write32(messagePointer, IPC::responseHeader(0x0C, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); +}