blob: 3cd0a4a691365024ff9e143cbe61de1ab8980bf1 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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;
}
}
}
|