ISystemClock.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using Ryujinx.Common;
  2. using Ryujinx.HLE.HOS.Ipc;
  3. using Ryujinx.HLE.HOS.Kernel.Common;
  4. using Ryujinx.HLE.HOS.Kernel.Threading;
  5. using Ryujinx.HLE.HOS.Services.Time.Clock;
  6. using System;
  7. namespace Ryujinx.HLE.HOS.Services.Time.StaticService
  8. {
  9. class ISystemClock : IpcService
  10. {
  11. private SystemClockCore _clockCore;
  12. private bool _writePermission;
  13. private bool _bypassUninitializedClock;
  14. private int _operationEventReadableHandle;
  15. public ISystemClock(SystemClockCore clockCore, bool writePermission, bool bypassUninitializedClock)
  16. {
  17. _clockCore = clockCore;
  18. _writePermission = writePermission;
  19. _bypassUninitializedClock = bypassUninitializedClock;
  20. _operationEventReadableHandle = 0;
  21. }
  22. [Command(0)]
  23. // GetCurrentTime() -> nn::time::PosixTime
  24. public ResultCode GetCurrentTime(ServiceCtx context)
  25. {
  26. if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
  27. {
  28. return ResultCode.UninitializedClock;
  29. }
  30. ResultCode result = _clockCore.GetCurrentTime(context.Thread, out long posixTime);
  31. if (result == ResultCode.Success)
  32. {
  33. context.ResponseData.Write(posixTime);
  34. }
  35. return result;
  36. }
  37. [Command(1)]
  38. // SetCurrentTime(nn::time::PosixTime)
  39. public ResultCode SetCurrentTime(ServiceCtx context)
  40. {
  41. if (!_writePermission)
  42. {
  43. return ResultCode.PermissionDenied;
  44. }
  45. if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
  46. {
  47. return ResultCode.UninitializedClock;
  48. }
  49. long posixTime = context.RequestData.ReadInt64();
  50. return _clockCore.SetCurrentTime(context.Thread, posixTime);
  51. }
  52. [Command(2)]
  53. // GetClockContext() -> nn::time::SystemClockContext
  54. public ResultCode GetSystemClockContext(ServiceCtx context)
  55. {
  56. if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
  57. {
  58. return ResultCode.UninitializedClock;
  59. }
  60. ResultCode result = _clockCore.GetClockContext(context.Thread, out SystemClockContext clockContext);
  61. if (result == ResultCode.Success)
  62. {
  63. context.ResponseData.WriteStruct(clockContext);
  64. }
  65. return result;
  66. }
  67. [Command(3)]
  68. // SetClockContext(nn::time::SystemClockContext)
  69. public ResultCode SetSystemClockContext(ServiceCtx context)
  70. {
  71. if (!_writePermission)
  72. {
  73. return ResultCode.PermissionDenied;
  74. }
  75. if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
  76. {
  77. return ResultCode.UninitializedClock;
  78. }
  79. SystemClockContext clockContext = context.RequestData.ReadStruct<SystemClockContext>();
  80. ResultCode result = _clockCore.SetSystemClockContext(clockContext);
  81. return result;
  82. }
  83. [Command(4)] // 9.0.0+
  84. // GetOperationEventReadableHandle() -> handle<copy>
  85. public ResultCode GetOperationEventReadableHandle(ServiceCtx context)
  86. {
  87. if (_operationEventReadableHandle == 0)
  88. {
  89. KEvent kEvent = new KEvent(context.Device.System);
  90. _clockCore.RegisterOperationEvent(kEvent.WritableEvent);
  91. if (context.Process.HandleTable.GenerateHandle(kEvent.ReadableEvent, out _operationEventReadableHandle) != KernelResult.Success)
  92. {
  93. throw new InvalidOperationException("Out of handles!");
  94. }
  95. }
  96. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_operationEventReadableHandle);
  97. return ResultCode.Success;
  98. }
  99. }
  100. }