From 79a3f442d658d63d7aec8855d7cd113ba5932c10 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 10 Feb 2021 03:14:26 -0800 Subject: [PATCH] htc: implement psc/pm loop --- .../htc/server/htc_power_state_control.cpp | 104 ++++++++++++++++++ stratosphere/htc/source/htc_main.cpp | 11 +- 2 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 libraries/libstratosphere/source/htc/server/htc_power_state_control.cpp diff --git a/libraries/libstratosphere/source/htc/server/htc_power_state_control.cpp b/libraries/libstratosphere/source/htc/server/htc_power_state_control.cpp new file mode 100644 index 000000000..cb2e2bfee --- /dev/null +++ b/libraries/libstratosphere/source/htc/server/htc_power_state_control.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "../../htclow/htclow_manager.hpp" + +namespace ams::htc::server { + + namespace { + + constinit htclow::HtclowManager *g_htclow_manager = nullptr; + + constexpr const psc::PmModuleId PscModuleDependencies[] = { psc::PmModuleId_Pcie, psc::PmModuleId_Usb }; + psc::PmModule g_pm_module; + + constinit bool g_is_asleep = false; + constinit bool g_is_suspended = false; + + } + + void InitializePowerStateMonitor(htclow::impl::DriverType driver_type, htclow::HtclowManager *htclow_manager) { + /* Set the htclow manager. */ + g_htclow_manager = htclow_manager; + + /* Initialize pm module. */ + R_ABORT_UNLESS(g_pm_module.Initialize(psc::PmModuleId_TmaHostIo, PscModuleDependencies, util::size(PscModuleDependencies), os::EventClearMode_AutoClear)); + + /* We're neither asleep nor suspended. */ + g_is_asleep = false; + g_is_suspended = false; + } + + void LoopMonitorPowerState() { + /* Get the psc module's event pointer. */ + auto *event = g_pm_module.GetEventPointer(); + while (true) { + /* Wait for a new power state event. */ + event->Wait(); + + /* Get the power state. */ + psc::PmState pm_state; + psc::PmFlagSet pm_flags; + R_ABORT_UNLESS(g_pm_module.GetRequest(std::addressof(pm_state), std::addressof(pm_flags))); + + /* Update sleeping state. */ + switch (pm_state) { + case psc::PmState_Awake: + if (g_is_asleep) { + g_htclow_manager->NotifyAwake(); + g_is_asleep = false; + } + break; + case psc::PmState_ReadyAwaken: + case psc::PmState_ReadySleep: + case psc::PmState_ReadySleepCritical: + case psc::PmState_ReadyAwakenCritical: + if (!g_is_asleep) { + g_htclow_manager->NotifyAsleep(); + g_is_asleep = true; + } + break; + default: + break; + } + + /* Update suspend state. */ + switch (pm_state) { + case psc::PmState_Awake: + case psc::PmState_ReadyAwaken: + if (g_is_suspended) { + g_htclow_manager->Resume(); + g_is_suspended = false; + } + break; + case psc::PmState_ReadySleep: + case psc::PmState_ReadySleepCritical: + case psc::PmState_ReadyAwakenCritical: + if (!g_is_suspended) { + g_htclow_manager->Suspend(); + g_is_suspended = true; + } + break; + default: + break; + } + + /* Acknowledge the pm request. */ + R_ABORT_UNLESS(g_pm_module.Acknowledge(pm_state, ResultSuccess())); + } + } + +} diff --git a/stratosphere/htc/source/htc_main.cpp b/stratosphere/htc/source/htc_main.cpp index e83193b81..92b39ac7e 100644 --- a/stratosphere/htc/source/htc_main.cpp +++ b/stratosphere/htc/source/htc_main.cpp @@ -198,6 +198,13 @@ namespace ams::htc { } + namespace server { + + void InitializePowerStateMonitor(htclow::impl::DriverType driver_type, htclow::HtclowManager *htclow_manager); + void LoopMonitorPowerState(); + + } + } int main(int argc, char **argv) @@ -246,7 +253,7 @@ int main(int argc, char **argv) } /* Initialize psc. */ - //htc::server::InitializePowerStateMonitor(driver_type, htclow_manager); + htc::server::InitializePowerStateMonitor(driver_type, htclow_manager); /* Start all threads. */ os::StartThread(std::addressof(htc_ipc_thread)); @@ -256,7 +263,7 @@ int main(int argc, char **argv) } /* Loop psc monitor. */ - //htc::server::LoopMonitorPowerState(); + htc::server::LoopMonitorPowerState(); /* Destroy all threads. */ for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {