IRequest.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.Services.Mm.Types;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.HLE.HOS.Services.Mm
  5. {
  6. [Service("mm:u")]
  7. class IRequest : IpcService
  8. {
  9. private static object _sessionListLock = new object();
  10. private static List<MultiMediaSession> _sessionList = new List<MultiMediaSession>();
  11. private static uint _uniqueId = 1;
  12. public IRequest(ServiceCtx context) { }
  13. [CommandHipc(0)]
  14. // InitializeOld(u32, u32, u32)
  15. public ResultCode InitializeOld(ServiceCtx context)
  16. {
  17. MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32();
  18. int fgmId = context.RequestData.ReadInt32();
  19. bool isAutoClearEvent = context.RequestData.ReadInt32() != 0;
  20. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType, fgmId, isAutoClearEvent });
  21. Register(operationType, fgmId, isAutoClearEvent);
  22. return ResultCode.Success;
  23. }
  24. [CommandHipc(1)]
  25. // FinalizeOld(u32)
  26. public ResultCode FinalizeOld(ServiceCtx context)
  27. {
  28. MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32();
  29. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType });
  30. lock (_sessionListLock)
  31. {
  32. _sessionList.Remove(GetSessionByType(operationType));
  33. }
  34. return ResultCode.Success;
  35. }
  36. [CommandHipc(2)]
  37. // SetAndWaitOld(u32, u32, u32)
  38. public ResultCode SetAndWaitOld(ServiceCtx context)
  39. {
  40. MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32();
  41. uint frequenceHz = context.RequestData.ReadUInt32();
  42. int timeout = context.RequestData.ReadInt32();
  43. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType, frequenceHz, timeout });
  44. lock (_sessionListLock)
  45. {
  46. GetSessionByType(operationType)?.SetAndWait(frequenceHz, timeout);
  47. }
  48. return ResultCode.Success;
  49. }
  50. [CommandHipc(3)]
  51. // GetOld(u32) -> u32
  52. public ResultCode GetOld(ServiceCtx context)
  53. {
  54. MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32();
  55. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType });
  56. lock (_sessionListLock)
  57. {
  58. MultiMediaSession session = GetSessionByType(operationType);
  59. uint currentValue = session == null ? 0 : session.CurrentValue;
  60. context.ResponseData.Write(currentValue);
  61. }
  62. return ResultCode.Success;
  63. }
  64. [CommandHipc(4)]
  65. // Initialize(u32, u32, u32) -> u32
  66. public ResultCode Initialize(ServiceCtx context)
  67. {
  68. MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32();
  69. int fgmId = context.RequestData.ReadInt32();
  70. bool isAutoClearEvent = context.RequestData.ReadInt32() != 0;
  71. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType, fgmId, isAutoClearEvent });
  72. uint id = Register(operationType, fgmId, isAutoClearEvent);
  73. context.ResponseData.Write(id);
  74. return ResultCode.Success;
  75. }
  76. [CommandHipc(5)]
  77. // Finalize(u32)
  78. public ResultCode Finalize(ServiceCtx context)
  79. {
  80. uint id = context.RequestData.ReadUInt32();
  81. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { id });
  82. lock (_sessionListLock)
  83. {
  84. _sessionList.Remove(GetSessionById(id));
  85. }
  86. return ResultCode.Success;
  87. }
  88. [CommandHipc(6)]
  89. // SetAndWait(u32, u32, u32)
  90. public ResultCode SetAndWait(ServiceCtx context)
  91. {
  92. uint id = context.RequestData.ReadUInt32();
  93. uint frequenceHz = context.RequestData.ReadUInt32();
  94. int timeout = context.RequestData.ReadInt32();
  95. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { id, frequenceHz, timeout });
  96. lock (_sessionListLock)
  97. {
  98. GetSessionById(id)?.SetAndWait(frequenceHz, timeout);
  99. }
  100. return ResultCode.Success;
  101. }
  102. [CommandHipc(7)]
  103. // Get(u32) -> u32
  104. public ResultCode Get(ServiceCtx context)
  105. {
  106. uint id = context.RequestData.ReadUInt32();
  107. Logger.Stub?.PrintStub(LogClass.ServiceMm, new { id });
  108. lock (_sessionListLock)
  109. {
  110. MultiMediaSession session = GetSessionById(id);
  111. uint currentValue = session == null ? 0 : session.CurrentValue;
  112. context.ResponseData.Write(currentValue);
  113. }
  114. return ResultCode.Success;
  115. }
  116. private MultiMediaSession GetSessionById(uint id)
  117. {
  118. foreach (MultiMediaSession session in _sessionList)
  119. {
  120. if (session.Id == id)
  121. {
  122. return session;
  123. }
  124. }
  125. return null;
  126. }
  127. private MultiMediaSession GetSessionByType(MultiMediaOperationType type)
  128. {
  129. foreach (MultiMediaSession session in _sessionList)
  130. {
  131. if (session.Type == type)
  132. {
  133. return session;
  134. }
  135. }
  136. return null;
  137. }
  138. private uint Register(MultiMediaOperationType type, int fgmId, bool isAutoClearEvent)
  139. {
  140. lock (_sessionListLock)
  141. {
  142. // Nintendo ignore the fgm id as the other interfaces were deprecated.
  143. MultiMediaSession session = new MultiMediaSession(_uniqueId++, type, isAutoClearEvent);
  144. _sessionList.Add(session);
  145. return session.Id;
  146. }
  147. }
  148. }
  149. }