using Ryujinx.Common; using Ryujinx.HLE.HOS.Services.Pcv.Bpc; using Ryujinx.HLE.HOS.Services.Settings; using Ryujinx.HLE.HOS.Services.Time.Clock; using Ryujinx.HLE.HOS.Services.Time.StaticService; using System; namespace Ryujinx.HLE.HOS.Services.Time { [Service("time:a", TimePermissions.Admin)] [Service("time:r", TimePermissions.Repair)] [Service("time:u", TimePermissions.User)] class IStaticServiceForGlue : IpcService { private IStaticServiceForPsc _inner; private TimePermissions _permissions; public IStaticServiceForGlue(ServiceCtx context, TimePermissions permissions) : base(context.Device.System.TimeServer) { _permissions = permissions; _inner = new IStaticServiceForPsc(context, permissions); _inner.TrySetServer(Server); _inner.SetParent(this); } [CommandHipc(0)] // GetStandardUserSystemClock() -> object public ResultCode GetStandardUserSystemClock(ServiceCtx context) { return _inner.GetStandardUserSystemClock(context); } [CommandHipc(1)] // GetStandardNetworkSystemClock() -> object public ResultCode GetStandardNetworkSystemClock(ServiceCtx context) { return _inner.GetStandardNetworkSystemClock(context); } [CommandHipc(2)] // GetStandardSteadyClock() -> object public ResultCode GetStandardSteadyClock(ServiceCtx context) { return _inner.GetStandardSteadyClock(context); } [CommandHipc(3)] // GetTimeZoneService() -> object public ResultCode GetTimeZoneService(ServiceCtx context) { MakeObject(context, new ITimeZoneServiceForGlue(TimeManager.Instance.TimeZone, (_permissions & TimePermissions.TimeZoneWritableMask) != 0)); return ResultCode.Success; } [CommandHipc(4)] // GetStandardLocalSystemClock() -> object public ResultCode GetStandardLocalSystemClock(ServiceCtx context) { return _inner.GetStandardLocalSystemClock(context); } [CommandHipc(5)] // 4.0.0+ // GetEphemeralNetworkSystemClock() -> object public ResultCode GetEphemeralNetworkSystemClock(ServiceCtx context) { return _inner.GetEphemeralNetworkSystemClock(context); } [CommandHipc(20)] // 6.0.0+ // GetSharedMemoryNativeHandle() -> handle public ResultCode GetSharedMemoryNativeHandle(ServiceCtx context) { return _inner.GetSharedMemoryNativeHandle(context); } [CommandHipc(50)] // 4.0.0+ // SetStandardSteadyClockInternalOffset(nn::TimeSpanType internal_offset) public ResultCode SetStandardSteadyClockInternalOffset(ServiceCtx context) { if ((_permissions & TimePermissions.SteadyClockWritableMask) == 0) { return ResultCode.PermissionDenied; } TimeSpanType internalOffset = context.RequestData.ReadStruct(); // TODO: set:sys SetExternalSteadyClockInternalOffset(internalOffset.ToSeconds()) return ResultCode.Success; } [CommandHipc(51)] // 9.0.0+ // GetStandardSteadyClockRtcValue() -> u64 public ResultCode GetStandardSteadyClockRtcValue(ServiceCtx context) { ResultCode result = (ResultCode)IRtcManager.GetExternalRtcValue(out ulong rtcValue); if (result == ResultCode.Success) { context.ResponseData.Write(rtcValue); } return result; } [CommandHipc(100)] // IsStandardUserSystemClockAutomaticCorrectionEnabled() -> bool public ResultCode IsStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context) { return _inner.IsStandardUserSystemClockAutomaticCorrectionEnabled(context); } [CommandHipc(101)] // SetStandardUserSystemClockAutomaticCorrectionEnabled(b8) public ResultCode SetStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context) { return _inner.SetStandardUserSystemClockAutomaticCorrectionEnabled(context); } [CommandHipc(102)] // 5.0.0+ // GetStandardUserSystemClockInitialYear() -> u32 public ResultCode GetStandardUserSystemClockInitialYear(ServiceCtx context) { if (!NxSettings.Settings.TryGetValue("time!standard_user_clock_initial_year", out object standardUserSystemClockInitialYear)) { throw new InvalidOperationException("standard_user_clock_initial_year isn't defined in system settings!"); } context.ResponseData.Write((int)standardUserSystemClockInitialYear); return ResultCode.Success; } [CommandHipc(200)] // 3.0.0+ // IsStandardNetworkSystemClockAccuracySufficient() -> bool public ResultCode IsStandardNetworkSystemClockAccuracySufficient(ServiceCtx context) { return _inner.IsStandardNetworkSystemClockAccuracySufficient(context); } [CommandHipc(201)] // 6.0.0+ // GetStandardUserSystemClockAutomaticCorrectionUpdatedTime() -> nn::time::SteadyClockTimePoint public ResultCode GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(ServiceCtx context) { return _inner.GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(context); } [CommandHipc(300)] // 4.0.0+ // CalculateMonotonicSystemClockBaseTimePoint(nn::time::SystemClockContext) -> s64 public ResultCode CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx context) { return _inner.CalculateMonotonicSystemClockBaseTimePoint(context); } [CommandHipc(400)] // 4.0.0+ // GetClockSnapshot(u8) -> buffer public ResultCode GetClockSnapshot(ServiceCtx context) { return _inner.GetClockSnapshot(context); } [CommandHipc(401)] // 4.0.0+ // GetClockSnapshotFromSystemClockContext(u8, nn::time::SystemClockContext, nn::time::SystemClockContext) -> buffer public ResultCode GetClockSnapshotFromSystemClockContext(ServiceCtx context) { return _inner.GetClockSnapshotFromSystemClockContext(context); } [CommandHipc(500)] // 4.0.0+ // CalculateStandardUserSystemClockDifferenceByUser(buffer, buffer) -> nn::TimeSpanType public ResultCode CalculateStandardUserSystemClockDifferenceByUser(ServiceCtx context) { return _inner.CalculateStandardUserSystemClockDifferenceByUser(context); } [CommandHipc(501)] // 4.0.0+ // CalculateSpanBetween(buffer, buffer) -> nn::TimeSpanType public ResultCode CalculateSpanBetween(ServiceCtx context) { return _inner.CalculateSpanBetween(context); } } }