diff --git a/include/services/cam.hpp b/include/services/cam.hpp index 3ff80a327..977292099 100644 --- a/include/services/cam.hpp +++ b/include/services/cam.hpp @@ -1,21 +1,33 @@ #pragma once +#include +#include + #include "helpers.hpp" #include "kernel_types.hpp" #include "logger.hpp" #include "memory.hpp" #include "result/result.hpp" +// Yay, circular dependencies! +class Kernel; + class CAMService { Handle handle = KernelHandles::CAM; Memory& mem; + Kernel& kernel; MAKE_LOG_FUNCTION(log, camLogger) + using Event = std::optional; + static constexpr size_t portCount = 4; // PORT_NONE, PORT_CAM1, PORT_CAM2, PORT_BOTH + std::array bufferErrorInterruptEvents; + // Service commands void driverInitialize(u32 messagePointer); void getMaxLines(u32 messagePointer); + void getBufferErrorInterruptEvent(u32 messagePointer); -public: - CAMService(Memory& mem) : mem(mem) {} + public: + CAMService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} void reset(); void handleSyncRequest(u32 messagePointer); }; \ No newline at end of file diff --git a/include/services/mic.hpp b/include/services/mic.hpp index 568d498c1..e193db1c3 100644 --- a/include/services/mic.hpp +++ b/include/services/mic.hpp @@ -18,11 +18,13 @@ class MICService { void setIirFilter(u32 messagePointer); void setPower(u32 messagePointer); void startSampling(u32 messagePointer); + void stopSampling(u32 messagePointer); void theCaptainToadFunction(u32 messagePointer); u8 gain = 0; // How loud our microphone input signal is bool micEnabled = false; bool shouldClamp = false; + bool isSampling = false; public: MICService(Memory& mem) : mem(mem) {} diff --git a/src/core/services/cam.cpp b/src/core/services/cam.cpp index ea21cf9dd..e0acab37e 100644 --- a/src/core/services/cam.cpp +++ b/src/core/services/cam.cpp @@ -1,19 +1,22 @@ #include "services/cam.hpp" #include "ipc.hpp" +#include "kernel.hpp" namespace CAMCommands { enum : u32 { + GetBufferErrorInterruptEvent = 0x00060040, DriverInitialize = 0x00390000, - GetMaxLines = 0x000A0080 + GetMaxLines = 0x000A0080, }; } -void CAMService::reset() {} +void CAMService::reset() { bufferErrorInterruptEvents.fill(std::nullopt); } void CAMService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { case CAMCommands::DriverInitialize: driverInitialize(messagePointer); break; + case CAMCommands::GetBufferErrorInterruptEvent: getBufferErrorInterruptEvent(messagePointer); break; case CAMCommands::GetMaxLines: getMaxLines(messagePointer); break; default: Helpers::panic("CAM service requested. Command: %08X\n", command); } @@ -55,4 +58,24 @@ void CAMService::getMaxLines(u32 messagePointer) { mem.write32(messagePointer + 4, result); mem.write16(messagePointer + 8, lines); } +} + +void CAMService::getBufferErrorInterruptEvent(u32 messagePointer) { + const u32 port = mem.read32(messagePointer + 4); + log("CAM::GetBufferErrorInterruptEvent (port = %d)\n", port); + + mem.write32(messagePointer, IPC::responseHeader(0x6, 1, 2)); + + if (port >= portCount) { + Helpers::panic("CAM::GetBufferErrorInterruptEvent: Invalid port"); + } else { + auto& event = bufferErrorInterruptEvents[port]; + if (!event.has_value()) { + event = kernel.makeEvent(ResetType::OneShot); + } + + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, 0); + mem.write32(messagePointer + 12, event.value()); + } } \ No newline at end of file diff --git a/src/core/services/mic.cpp b/src/core/services/mic.cpp index 0648ad53b..055f5c1d9 100644 --- a/src/core/services/mic.cpp +++ b/src/core/services/mic.cpp @@ -5,6 +5,7 @@ namespace MICCommands { enum : u32 { MapSharedMem = 0x00010042, StartSampling = 0x00030140, + StopSampling = 0x00050000, SetGain = 0x00080040, GetGain = 0x00090000, SetPower = 0x000A0040, @@ -17,6 +18,7 @@ namespace MICCommands { void MICService::reset() { micEnabled = false; shouldClamp = false; + isSampling = false; gain = 0; } @@ -30,6 +32,7 @@ void MICService::handleSyncRequest(u32 messagePointer) { case MICCommands::SetIirFilter: setIirFilter(messagePointer); break; case MICCommands::SetPower: setPower(messagePointer); break; case MICCommands::StartSampling: startSampling(messagePointer); break; + case MICCommands::StopSampling: stopSampling(messagePointer); break; case MICCommands::CaptainToadFunction: theCaptainToadFunction(messagePointer); break; default: Helpers::panic("MIC service requested. Command: %08X\n", command); } @@ -88,10 +91,19 @@ void MICService::startSampling(u32 messagePointer) { encoding, sampleRate, offset, dataSize, loop ? "yes" : "no" ); + isSampling = true; mem.write32(messagePointer, IPC::responseHeader(0x3, 1, 0)); mem.write32(messagePointer + 4, Result::Success); } +void MICService::stopSampling(u32 messagePointer) { + log("MIC::StopSampling\n"); + isSampling = false; + + mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); +} + void MICService::setIirFilter(u32 messagePointer) { const u32 size = mem.read32(messagePointer + 4); const u32 pointer = mem.read32(messagePointer + 12); diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index ea2c031f5..02f9d5691 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -6,7 +6,7 @@ #include "kernel.hpp" ServiceManager::ServiceManager(std::span 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, kernel), cfg(mem), + : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem), ptm(mem), soc(mem), ssl(mem), y2r(mem, kernel) {}