diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/ptm/psm.cpp | 116 |
1 files changed, 114 insertions, 2 deletions
diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index b4b0dd241..4f98e15ef 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -5,16 +5,119 @@ #include <memory> #include "common/logging/log.h" +#include "core/core.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/readable_event.h" +#include "core/hle/kernel/writable_event.h" #include "core/hle/service/ptm/psm.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" namespace Service::PSM { +class IPsmSession final : public ServiceFramework<IPsmSession> { +public: + explicit IPsmSession(Core::System& system_) : ServiceFramework{system_, "IPsmSession"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IPsmSession::BindStateChangeEvent, "BindStateChangeEvent"}, + {1, &IPsmSession::UnbindStateChangeEvent, "UnbindStateChangeEvent"}, + {2, &IPsmSession::SetChargerTypeChangeEventEnabled, "SetChargerTypeChangeEventEnabled"}, + {3, &IPsmSession::SetPowerSupplyChangeEventEnabled, "SetPowerSupplyChangeEventEnabled"}, + {4, &IPsmSession::SetBatteryVoltageStateChangeEventEnabled, "SetBatteryVoltageStateChangeEventEnabled"}, + }; + // clang-format on + + RegisterHandlers(functions); + + state_change_event = Kernel::WritableEvent::CreateEventPair( + system_.Kernel(), "IPsmSession::state_change_event"); + } + + ~IPsmSession() override = default; + + void SignalChargerTypeChanged() { + if (should_signal && should_signal_charger_type) { + state_change_event.writable->Signal(); + } + } + + void SignalPowerSupplyChanged() { + if (should_signal && should_signal_power_supply) { + state_change_event.writable->Signal(); + } + } + + void SignalBatteryVoltageStateChanged() { + if (should_signal && should_signal_battery_voltage) { + state_change_event.writable->Signal(); + } + } + +private: + void BindStateChangeEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PSM, "called"); + + should_signal = true; + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(state_change_event.readable); + } + + void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PSM, "called"); + + should_signal = false; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetChargerTypeChangeEventEnabled(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto state = rp.Pop<bool>(); + LOG_DEBUG(Service_PSM, "called, state={}", state); + + should_signal_charger_type = state; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetPowerSupplyChangeEventEnabled(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto state = rp.Pop<bool>(); + LOG_DEBUG(Service_PSM, "called, state={}", state); + + should_signal_power_supply = state; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetBatteryVoltageStateChangeEventEnabled(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto state = rp.Pop<bool>(); + LOG_DEBUG(Service_PSM, "called, state={}", state); + + should_signal_battery_voltage = state; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + bool should_signal_charger_type{}; + bool should_signal_power_supply{}; + bool should_signal_battery_voltage{}; + bool should_signal{}; + Kernel::EventPair state_change_event; +}; + class PSM final : public ServiceFramework<PSM> { public: - explicit PSM(Core::System& system_) : ServiceFramework{system_, "psm"} { + explicit PSM(Core::System& system_) : ServiceFramework{system_, "psm"}, system(system_) { // clang-format off static const FunctionInfo functions[] = { {0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"}, @@ -24,7 +127,7 @@ public: {4, nullptr, "IsBatteryChargingEnabled"}, {5, nullptr, "AcquireControllerPowerSupply"}, {6, nullptr, "ReleaseControllerPowerSupply"}, - {7, nullptr, "OpenSession"}, + {7, &PSM::OpenSession, "OpenSession"}, {8, nullptr, "EnableEnoughPowerChargeEmulation"}, {9, nullptr, "DisableEnoughPowerChargeEmulation"}, {10, nullptr, "EnableFastBatteryCharging"}, @@ -61,6 +164,14 @@ private: rb.PushEnum(charger_type); } + void OpenSession(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PSM, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IPsmSession>(system); + } + enum class ChargerType : u32 { Unplugged = 0, RegularCharger = 1, @@ -70,6 +181,7 @@ private: u32 battery_charge_percentage{100}; // 100% ChargerType charger_type{ChargerType::RegularCharger}; + Core::System& system; }; void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { |