diff --git a/Ryujinx.Common/Logging/LogClass.cs b/Ryujinx.Common/Logging/LogClass.cs index 97ffb314..8739fbc6 100644 --- a/Ryujinx.Common/Logging/LogClass.cs +++ b/Ryujinx.Common/Logging/LogClass.cs @@ -33,6 +33,7 @@ namespace Ryujinx.Common.Logging ServicePctl, ServicePl, ServicePrepo, + ServicePsm, ServiceSet, ServiceSfdnsres, ServiceSm, diff --git a/Ryujinx.HLE/HOS/Services/Psm/IPsmServer.cs b/Ryujinx.HLE/HOS/Services/Psm/IPsmServer.cs new file mode 100644 index 00000000..0b45e3c9 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Psm/IPsmServer.cs @@ -0,0 +1,60 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Psm +{ + class IPsmServer : IpcService + { + enum ChargerType : int + { + None, + ChargerOrDock, + UsbC + } + + private Dictionary m_Commands; + + public override IReadOnlyDictionary Commands => m_Commands; + + public IPsmServer() + { + m_Commands = new Dictionary() + { + { 0, GetBatteryChargePercentage }, + { 1, GetChargerType }, + { 7, OpenSession } + }; + } + + // GetBatteryChargePercentage() -> u32 + public static long GetBatteryChargePercentage(ServiceCtx Context) + { + int ChargePercentage = 100; + + Context.ResponseData.Write(ChargePercentage); + + Logger.PrintStub(LogClass.ServicePsm, $"Stubbed. ChargePercentage: {ChargePercentage}"); + + return 0; + } + + // GetChargerType() -> u32 + public static long GetChargerType(ServiceCtx Context) + { + Context.ResponseData.Write((int)ChargerType.ChargerOrDock); + + Logger.PrintStub(LogClass.ServicePsm, $"Stubbed. ChargerType: {ChargerType.ChargerOrDock}"); + + return 0; + } + + // OpenSession() -> IPsmSession + public long OpenSession(ServiceCtx Context) + { + MakeObject(Context, new IPsmSession(Context.Device.System)); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs b/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs new file mode 100644 index 00000000..30e5d532 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs @@ -0,0 +1,96 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Psm +{ + class IPsmSession : IpcService + { + private Dictionary m_Commands; + + public override IReadOnlyDictionary Commands => m_Commands; + + private KEvent StateChangeEvent; + private int StateChangeEventHandle; + + public IPsmSession(Horizon System) + { + m_Commands = new Dictionary() + { + { 0, BindStateChangeEvent }, + { 1, UnbindStateChangeEvent }, + { 2, SetChargerTypeChangeEventEnabled }, + { 3, SetPowerSupplyChangeEventEnabled }, + { 4, SetBatteryVoltageStateChangeEventEnabled } + }; + + StateChangeEvent = new KEvent(System); + StateChangeEventHandle = -1; + } + + // BindStateChangeEvent() -> KObject + public long BindStateChangeEvent(ServiceCtx Context) + { + if (StateChangeEventHandle == -1) + { + KernelResult ResultCode = Context.Process.HandleTable.GenerateHandle(StateChangeEvent, out int StateChangeEventHandle); + + if (ResultCode != KernelResult.Success) + { + return (long)ResultCode; + } + } + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(StateChangeEventHandle); + + Logger.PrintStub(LogClass.ServicePsm, "Stubbed."); + + return 0; + } + + // UnbindStateChangeEvent() + public long UnbindStateChangeEvent(ServiceCtx Context) + { + if (StateChangeEventHandle != -1) + { + Context.Process.HandleTable.CloseHandle(StateChangeEventHandle); + StateChangeEventHandle = -1; + } + + Logger.PrintStub(LogClass.ServicePsm, "Stubbed."); + + return 0; + } + + // SetChargerTypeChangeEventEnabled(u8) + public long SetChargerTypeChangeEventEnabled(ServiceCtx Context) + { + bool ChargerTypeChangeEventEnabled = Context.RequestData.ReadBoolean(); + + Logger.PrintStub(LogClass.ServicePsm, $"Stubbed. ChargerTypeChangeEventEnabled: {ChargerTypeChangeEventEnabled}"); + + return 0; + } + + // SetPowerSupplyChangeEventEnabled(u8) + public long SetPowerSupplyChangeEventEnabled(ServiceCtx Context) + { + bool PowerSupplyChangeEventEnabled = Context.RequestData.ReadBoolean(); + + Logger.PrintStub(LogClass.ServicePsm, $"Stubbed. PowerSupplyChangeEventEnabled: {PowerSupplyChangeEventEnabled}"); + + return 0; + } + + // SetBatteryVoltageStateChangeEventEnabled(u8) + public long SetBatteryVoltageStateChangeEventEnabled(ServiceCtx Context) + { + bool BatteryVoltageStateChangeEventEnabled = Context.RequestData.ReadBoolean(); + + Logger.PrintStub(LogClass.ServicePsm, $"Stubbed. BatteryVoltageStateChangeEventEnabled: {BatteryVoltageStateChangeEventEnabled}"); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/ServiceFactory.cs b/Ryujinx.HLE/HOS/Services/ServiceFactory.cs index 29f1c0e7..5908e810 100644 --- a/Ryujinx.HLE/HOS/Services/ServiceFactory.cs +++ b/Ryujinx.HLE/HOS/Services/ServiceFactory.cs @@ -16,6 +16,7 @@ using Ryujinx.HLE.HOS.Services.Nv; using Ryujinx.HLE.HOS.Services.Pctl; using Ryujinx.HLE.HOS.Services.Pl; using Ryujinx.HLE.HOS.Services.Prepo; +using Ryujinx.HLE.HOS.Services.Psm; using Ryujinx.HLE.HOS.Services.Set; using Ryujinx.HLE.HOS.Services.Sfdnsres; using Ryujinx.HLE.HOS.Services.Sm; @@ -152,6 +153,9 @@ namespace Ryujinx.HLE.HOS.Services case "prepo:u": return new IPrepoService(); + case "psm": + return new IPsmServer(); + case "set": return new ISettingsServer();