mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-29 02:41:51 +00:00
1059202c75
This PR primarily focuses on upbringing constexpr maps for handlers. Each time an HLE object of a service is construed, it registers it's own handlers, over and over. Regardless of whetever it needs them at the moment or not. Additionally we don't require to keep track of different function pointers amongst each object. This can be done by overriding the given function instead, as opposed to having a separate hash map for every given object. In other words: Remove handlers (and handlers_tipc) map for every instance then read from a static defined per-class. - [x] Migrate all HLE functions to new `frozen::map` constexpr time finder - [ ] Measure if this approach actually makes better codegen Optional: - [x] Properly gate all functions (that have versions commented next to them) - [x] Maybe store `HandlerFnP<>` and `const char*` separately, version gating can go in a different map as well Information such as name can be used on debug builds, but doesn't particularly help on release as one can consult an external reference (or have an annotated IPC map) Signed-off-by: lizzie <lizzie@eden-emu.dev> - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- Co-authored-by: Maufeat <sahyno1996@gmail.com> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4480 Reviewed-by: Maufeat <sahyno1996@gmail.com> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
228 lines
7.0 KiB
C++
228 lines
7.0 KiB
C++
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <memory>
|
|
|
|
#include "common/common_funcs.h"
|
|
#include "common/device_power_state.h"
|
|
#include "common/logging.h"
|
|
#include "core/core.h"
|
|
#include "core/hle/kernel/k_event.h"
|
|
#include "core/hle/result.h"
|
|
#include "core/hle/service/ipc_helpers.h"
|
|
#include "core/hle/service/kernel_helpers.h"
|
|
#include "core/hle/service/ptm/psm.h"
|
|
|
|
namespace Service::PTM {
|
|
|
|
class IPsmSession final : public ServiceFramework<IPsmSession> {
|
|
public:
|
|
explicit IPsmSession(Core::System& system_)
|
|
: ServiceFramework{system_, "IPsmSession"}
|
|
, service_context{system_, "IPsmSession"} {
|
|
state_change_event = service_context.CreateEvent("IPsmSession::state_change_event");
|
|
}
|
|
|
|
std::optional<FunctionInfoBase> FindRequest(u32 key) override {
|
|
return HandlerTableGenerateWithFind(key, functions);
|
|
}
|
|
|
|
~IPsmSession() override {
|
|
service_context.CloseEvent(state_change_event);
|
|
}
|
|
|
|
void SignalChargerTypeChanged() {
|
|
if (should_signal && should_signal_charger_type) {
|
|
state_change_event->Signal(system.Kernel());
|
|
}
|
|
}
|
|
|
|
void SignalPowerSupplyChanged() {
|
|
if (should_signal && should_signal_power_supply) {
|
|
state_change_event->Signal(system.Kernel());
|
|
}
|
|
}
|
|
|
|
void SignalBatteryVoltageStateChanged() {
|
|
if (should_signal && should_signal_battery_voltage) {
|
|
state_change_event->Signal(system.Kernel());
|
|
}
|
|
}
|
|
|
|
private:
|
|
void BindStateChangeEvent(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "called");
|
|
|
|
should_signal = true;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushCopyObjects(ctx, state_change_event->GetReadableEvent());
|
|
}
|
|
|
|
void UnbindStateChangeEvent(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "called");
|
|
|
|
should_signal = false;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void SetChargerTypeChangeEventEnabled(HLERequestContext& ctx) {
|
|
IPC::RequestParser rp{ctx};
|
|
const auto state = rp.Pop<bool>();
|
|
LOG_DEBUG(Service_PTM, "called, state={}", state);
|
|
|
|
should_signal_charger_type = state;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void SetPowerSupplyChangeEventEnabled(HLERequestContext& ctx) {
|
|
IPC::RequestParser rp{ctx};
|
|
const auto state = rp.Pop<bool>();
|
|
LOG_DEBUG(Service_PTM, "called, state={}", state);
|
|
|
|
should_signal_power_supply = state;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void SetBatteryVoltageStateChangeEventEnabled(HLERequestContext& ctx) {
|
|
IPC::RequestParser rp{ctx};
|
|
const auto state = rp.Pop<bool>();
|
|
LOG_DEBUG(Service_PTM, "called, state={}", state);
|
|
|
|
should_signal_battery_voltage = state;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
static constexpr auto functions = CreateStaticMap(
|
|
FunctionInfo{0, &IPsmSession::BindStateChangeEvent, "BindStateChangeEvent"},
|
|
FunctionInfo{1, &IPsmSession::UnbindStateChangeEvent, "UnbindStateChangeEvent"},
|
|
FunctionInfo{2, &IPsmSession::SetChargerTypeChangeEventEnabled, "SetChargerTypeChangeEventEnabled"},
|
|
FunctionInfo{3, &IPsmSession::SetPowerSupplyChangeEventEnabled, "SetPowerSupplyChangeEventEnabled"},
|
|
FunctionInfo{4, &IPsmSession::SetBatteryVoltageStateChangeEventEnabled, "SetBatteryVoltageStateChangeEventEnabled"}
|
|
);
|
|
|
|
KernelHelpers::ServiceContext service_context;
|
|
bool should_signal_charger_type{};
|
|
bool should_signal_power_supply{};
|
|
bool should_signal_battery_voltage{};
|
|
bool should_signal{};
|
|
Kernel::KEvent* state_change_event;
|
|
};
|
|
|
|
PSM::PSM(Core::System& system_) : ServiceFramework{system_, "psm"} {
|
|
}
|
|
|
|
PSM::~PSM() = default;
|
|
|
|
void PSM::GetBatteryChargePercentage(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "called");
|
|
|
|
u32 percentage = 100;
|
|
|
|
Common::PowerStatus power_status = Common::GetPowerStatus();
|
|
|
|
if (power_status.has_battery && power_status.percentage >= 0) {
|
|
percentage = static_cast<u32>(power_status.percentage);
|
|
}
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
rb.Push(ResultSuccess);
|
|
rb.Push<u32>(percentage);
|
|
}
|
|
|
|
void PSM::GetChargerType(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "called");
|
|
|
|
ChargerType charger = ChargerType::Unplugged;
|
|
Common::PowerStatus power_status = Common::GetPowerStatus();
|
|
if (power_status.has_battery && power_status.charging) {
|
|
charger = ChargerType::RegularCharger;
|
|
}
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushEnum(charger);
|
|
}
|
|
|
|
void PSM::OpenSession(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "called");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushIpcInterface<IPsmSession>(ctx, system);
|
|
}
|
|
|
|
void PSM::GetBatteryVoltageState(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "(stubbed)");
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushRaw<u32>(0); //
|
|
}
|
|
|
|
void PSM::GetBatteryAgePercentage(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "(stubbed)");
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushRaw<f64>(1.f);
|
|
}
|
|
|
|
struct BatteryChargeInfoFields {
|
|
u32 input_current_limit; //mA
|
|
u32 boost_mode_current_limit;
|
|
u32 fast_charge_current_limit;
|
|
u32 charge_voltage_limit;
|
|
u32 charger_type;
|
|
u8 hi2_mode;
|
|
u8 battery_charging;
|
|
INSERT_PADDING_BYTES_NOINIT(2);
|
|
u32 vdd50_state;
|
|
u32 temperature_celcius;
|
|
f32 battery_charge_percentage;
|
|
u32 battery_charge_milli_voltage;
|
|
f32 battery_age_percentage;
|
|
u32 usb_power_role;
|
|
u32 usb_charger_type;
|
|
u32 charger_input_voltage_limit;
|
|
u32 charger_input_current_limit;
|
|
u8 fast_battery_charging;
|
|
u8 controller_power_supply;
|
|
u8 otg_request;
|
|
INSERT_PADDING_BYTES_NOINIT(1);
|
|
INSERT_PADDING_BYTES_NOINIT(0x14); //[+17.0.0]
|
|
};
|
|
static_assert(sizeof(struct BatteryChargeInfoFields) == 0x54);
|
|
void PSM::GetBatteryChargeInfoFields(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_PTM, "called");
|
|
Common::PowerStatus power_status = Common::GetPowerStatus();
|
|
|
|
BatteryChargeInfoFields r{};
|
|
r.battery_charge_percentage = f32(power_status.percentage); //100%
|
|
r.battery_age_percentage = f32(power_status.percentage); //100%
|
|
r.battery_charging = power_status.charging ? 1 : 0;
|
|
r.charger_type = u32(power_status.has_battery && power_status.charging
|
|
? ChargerType::RegularCharger : ChargerType::Unplugged);
|
|
r.charger_input_voltage_limit = 100;
|
|
r.charger_input_voltage_limit = 100;
|
|
r.input_current_limit = 100;
|
|
r.boost_mode_current_limit = 100;
|
|
r.fast_charge_current_limit = 100;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushRaw<BatteryChargeInfoFields>(r);
|
|
}
|
|
|
|
} // namespace Service::PTM
|