diff options
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs')
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs new file mode 100644 index 00000000..3cd0a4a6 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs @@ -0,0 +1,131 @@ +using Ryujinx.Common; +using Ryujinx.Cpu; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Services.Time.Clock; +using Ryujinx.Horizon.Common; +using System; + +namespace Ryujinx.HLE.HOS.Services.Time.StaticService +{ + class ISystemClock : IpcService + { + private SystemClockCore _clockCore; + private bool _writePermission; + private bool _bypassUninitializedClock; + private int _operationEventReadableHandle; + + public ISystemClock(SystemClockCore clockCore, bool writePermission, bool bypassUninitializedClock) + { + _clockCore = clockCore; + _writePermission = writePermission; + _bypassUninitializedClock = bypassUninitializedClock; + _operationEventReadableHandle = 0; + } + + [CommandCmif(0)] + // GetCurrentTime() -> nn::time::PosixTime + public ResultCode GetCurrentTime(ServiceCtx context) + { + if (!_bypassUninitializedClock && !_clockCore.IsInitialized()) + { + return ResultCode.UninitializedClock; + } + + ITickSource tickSource = context.Device.System.TickSource; + + ResultCode result = _clockCore.GetCurrentTime(tickSource, out long posixTime); + + if (result == ResultCode.Success) + { + context.ResponseData.Write(posixTime); + } + + return result; + } + + [CommandCmif(1)] + // SetCurrentTime(nn::time::PosixTime) + public ResultCode SetCurrentTime(ServiceCtx context) + { + if (!_writePermission) + { + return ResultCode.PermissionDenied; + } + + if (!_bypassUninitializedClock && !_clockCore.IsInitialized()) + { + return ResultCode.UninitializedClock; + } + + long posixTime = context.RequestData.ReadInt64(); + + ITickSource tickSource = context.Device.System.TickSource; + + return _clockCore.SetCurrentTime(tickSource, posixTime); + } + + [CommandCmif(2)] + // GetClockContext() -> nn::time::SystemClockContext + public ResultCode GetSystemClockContext(ServiceCtx context) + { + if (!_bypassUninitializedClock && !_clockCore.IsInitialized()) + { + return ResultCode.UninitializedClock; + } + + ITickSource tickSource = context.Device.System.TickSource; + + ResultCode result = _clockCore.GetClockContext(tickSource, out SystemClockContext clockContext); + + if (result == ResultCode.Success) + { + context.ResponseData.WriteStruct(clockContext); + } + + return result; + } + + [CommandCmif(3)] + // SetClockContext(nn::time::SystemClockContext) + public ResultCode SetSystemClockContext(ServiceCtx context) + { + if (!_writePermission) + { + return ResultCode.PermissionDenied; + } + + if (!_bypassUninitializedClock && !_clockCore.IsInitialized()) + { + return ResultCode.UninitializedClock; + } + + SystemClockContext clockContext = context.RequestData.ReadStruct<SystemClockContext>(); + + ResultCode result = _clockCore.SetSystemClockContext(clockContext); + + return result; + } + + [CommandCmif(4)] // 9.0.0+ + // GetOperationEventReadableHandle() -> handle<copy> + public ResultCode GetOperationEventReadableHandle(ServiceCtx context) + { + if (_operationEventReadableHandle == 0) + { + KEvent kEvent = new KEvent(context.Device.System.KernelContext); + + _clockCore.RegisterOperationEvent(kEvent.WritableEvent); + + if (context.Process.HandleTable.GenerateHandle(kEvent.ReadableEvent, out _operationEventReadableHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_operationEventReadableHandle); + + return ResultCode.Success; + } + } +}
\ No newline at end of file |
