IpcHandler.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. using ChocolArm64.Memory;
  2. using Ryujinx.OsHle.Handles;
  3. using Ryujinx.OsHle.Objects;
  4. using Ryujinx.OsHle.Services;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. namespace Ryujinx.OsHle.Ipc
  9. {
  10. static class IpcHandler
  11. {
  12. private delegate long ServiceProcessRequest(ServiceCtx Context);
  13. private static Dictionary<(string, int), ServiceProcessRequest> ServiceCmds =
  14. new Dictionary<(string, int), ServiceProcessRequest>()
  15. {
  16. { ( "acc:u0", 3), Service.AccU0ListOpenUsers },
  17. { ( "acc:u0", 5), Service.AccU0GetProfile },
  18. { ( "acc:u0", 100), Service.AccU0InitializeApplicationInfo },
  19. { ( "acc:u0", 101), Service.AccU0GetBaasAccountManagerForApplication },
  20. { ( "apm", 0), Service.ApmOpenSession },
  21. { ( "apm:p", 0), Service.ApmOpenSession },
  22. { ( "appletOE", 0), Service.AppletOpenApplicationProxy },
  23. { ( "audout:u", 0), Service.AudOutListAudioOuts },
  24. { ( "audout:u", 1), Service.AudOutOpenAudioOut },
  25. { ( "audren:u", 0), Service.AudRenOpenAudioRenderer },
  26. { ( "audren:u", 1), Service.AudRenGetAudioRendererWorkBufferSize },
  27. { ( "friend:a", 0), Service.FriendCreateFriendService },
  28. { ( "fsp-srv", 1), Service.FspSrvInitialize },
  29. { ( "fsp-srv", 18), Service.FspSrvMountSdCard },
  30. { ( "fsp-srv", 51), Service.FspSrvMountSaveData },
  31. { ( "fsp-srv", 200), Service.FspSrvOpenDataStorageByCurrentProcess },
  32. { ( "fsp-srv", 203), Service.FspSrvOpenRomStorage },
  33. { ( "fsp-srv", 1005), Service.FspSrvGetGlobalAccessLogMode },
  34. { ( "hid", 0), Service.HidCreateAppletResource },
  35. { ( "hid", 11), Service.HidActivateTouchScreen },
  36. { ( "hid", 100), Service.HidSetSupportedNpadStyleSet },
  37. { ( "hid", 102), Service.HidSetSupportedNpadIdType },
  38. { ( "hid", 103), Service.HidActivateNpad },
  39. { ( "hid", 120), Service.HidSetNpadJoyHoldType },
  40. { ( "lm", 0), Service.LmInitialize },
  41. { ( "nvdrv", 0), Service.NvDrvOpen },
  42. { ( "nvdrv", 1), Service.NvDrvIoctl },
  43. { ( "nvdrv", 2), Service.NvDrvClose },
  44. { ( "nvdrv", 3), Service.NvDrvInitialize },
  45. { ( "nvdrv", 4), Service.NvDrvQueryEvent },
  46. { ( "nvdrv", 8), Service.NvDrvSetClientPid },
  47. { ( "nvdrv:a", 0), Service.NvDrvOpen },
  48. { ( "nvdrv:a", 1), Service.NvDrvIoctl },
  49. { ( "nvdrv:a", 2), Service.NvDrvClose },
  50. { ( "nvdrv:a", 3), Service.NvDrvInitialize },
  51. { ( "nvdrv:a", 4), Service.NvDrvQueryEvent },
  52. { ( "nvdrv:a", 8), Service.NvDrvSetClientPid },
  53. { ( "pctl:a", 0), Service.PctlCreateService },
  54. { ( "pl:u", 1), Service.PlGetLoadState },
  55. { ( "pl:u", 2), Service.PlGetFontSize },
  56. { ( "pl:u", 3), Service.PlGetSharedMemoryAddressOffset },
  57. { ( "pl:u", 4), Service.PlGetSharedMemoryNativeHandle },
  58. { ( "set", 1), Service.SetGetAvailableLanguageCodes },
  59. { ( "sm:", 0), Service.SmInitialize },
  60. { ( "sm:", 1), Service.SmGetService },
  61. { ( "time:u", 0), Service.TimeGetStandardUserSystemClock },
  62. { ( "time:u", 1), Service.TimeGetStandardNetworkSystemClock },
  63. { ( "time:u", 2), Service.TimeGetStandardSteadyClock },
  64. { ( "time:u", 3), Service.TimeGetTimeZoneService },
  65. { ( "time:s", 0), Service.TimeGetStandardUserSystemClock },
  66. { ( "time:s", 1), Service.TimeGetStandardNetworkSystemClock },
  67. { ( "time:s", 2), Service.TimeGetStandardSteadyClock },
  68. { ( "time:s", 3), Service.TimeGetTimeZoneService },
  69. { ( "vi:m", 2), Service.ViGetDisplayService },
  70. };
  71. private static Dictionary<(Type, int), ServiceProcessRequest> ObjectCmds =
  72. new Dictionary<(Type, int), ServiceProcessRequest>()
  73. {
  74. //IManagerForApplication
  75. { (typeof(AccIManagerForApplication), 0), AccIManagerForApplication.CheckAvailability },
  76. { (typeof(AccIManagerForApplication), 1), AccIManagerForApplication.GetAccountId },
  77. //IProfile
  78. { (typeof(AccIProfile), 1), AccIProfile.GetBase },
  79. //IApplicationFunctions
  80. { (typeof(AmIApplicationFunctions), 1), AmIApplicationFunctions.PopLaunchParameter },
  81. { (typeof(AmIApplicationFunctions), 20), AmIApplicationFunctions.EnsureSaveData },
  82. { (typeof(AmIApplicationFunctions), 21), AmIApplicationFunctions.GetDesiredLanguage },
  83. { (typeof(AmIApplicationFunctions), 40), AmIApplicationFunctions.NotifyRunning },
  84. //IApplicationProxy
  85. { (typeof(AmIApplicationProxy), 0), AmIApplicationProxy.GetCommonStateGetter },
  86. { (typeof(AmIApplicationProxy), 1), AmIApplicationProxy.GetSelfController },
  87. { (typeof(AmIApplicationProxy), 2), AmIApplicationProxy.GetWindowController },
  88. { (typeof(AmIApplicationProxy), 3), AmIApplicationProxy.GetAudioController },
  89. { (typeof(AmIApplicationProxy), 4), AmIApplicationProxy.GetDisplayController },
  90. { (typeof(AmIApplicationProxy), 11), AmIApplicationProxy.GetLibraryAppletCreator },
  91. { (typeof(AmIApplicationProxy), 20), AmIApplicationProxy.GetApplicationFunctions },
  92. { (typeof(AmIApplicationProxy), 1000), AmIApplicationProxy.GetDebugFunctions },
  93. //ICommonStateGetter
  94. { (typeof(AmICommonStateGetter), 0), AmICommonStateGetter.GetEventHandle },
  95. { (typeof(AmICommonStateGetter), 1), AmICommonStateGetter.ReceiveMessage },
  96. { (typeof(AmICommonStateGetter), 5), AmICommonStateGetter.GetOperationMode },
  97. { (typeof(AmICommonStateGetter), 6), AmICommonStateGetter.GetPerformanceMode },
  98. { (typeof(AmICommonStateGetter), 9), AmICommonStateGetter.GetCurrentFocusState },
  99. //ISelfController
  100. { (typeof(AmISelfController), 11), AmISelfController.SetOperationModeChangedNotification },
  101. { (typeof(AmISelfController), 12), AmISelfController.SetPerformanceModeChangedNotification },
  102. { (typeof(AmISelfController), 13), AmISelfController.SetFocusHandlingMode },
  103. { (typeof(AmISelfController), 16), AmISelfController.SetOutOfFocusSuspendingEnabled },
  104. //IStorage
  105. { (typeof(AmIStorage), 0), AmIStorage.Open },
  106. //IStorageAccessor
  107. { (typeof(AmIStorageAccessor), 0), AmIStorageAccessor.GetSize },
  108. { (typeof(AmIStorageAccessor), 11), AmIStorageAccessor.Read },
  109. //IWindowController
  110. { (typeof(AmIWindowController), 1), AmIWindowController.GetAppletResourceUserId },
  111. { (typeof(AmIWindowController), 10), AmIWindowController.AcquireForegroundRights },
  112. //ISession
  113. { (typeof(ApmISession), 0), ApmISession.SetPerformanceConfiguration },
  114. //IAudioRenderer
  115. { (typeof(AudIAudioRenderer), 4), AudIAudioRenderer.RequestUpdateAudioRenderer },
  116. { (typeof(AudIAudioRenderer), 5), AudIAudioRenderer.StartAudioRenderer },
  117. { (typeof(AudIAudioRenderer), 6), AudIAudioRenderer.StopAudioRenderer },
  118. { (typeof(AudIAudioRenderer), 7), AudIAudioRenderer.QuerySystemEvent },
  119. //IAudioOut
  120. { (typeof(AudIAudioOut), 0), AudIAudioOut.GetAudioOutState },
  121. { (typeof(AudIAudioOut), 1), AudIAudioOut.StartAudioOut },
  122. { (typeof(AudIAudioOut), 2), AudIAudioOut.StopAudioOut },
  123. { (typeof(AudIAudioOut), 3), AudIAudioOut.AppendAudioOutBuffer },
  124. { (typeof(AudIAudioOut), 4), AudIAudioOut.RegisterBufferEvent },
  125. { (typeof(AudIAudioOut), 5), AudIAudioOut.GetReleasedAudioOutBuffer },
  126. { (typeof(AudIAudioOut), 6), AudIAudioOut.ContainsAudioOutBuffer },
  127. { (typeof(AudIAudioOut), 7), AudIAudioOut.AppendAudioOutBuffer_ex },
  128. { (typeof(AudIAudioOut), 8), AudIAudioOut.GetReleasedAudioOutBuffer_ex },
  129. //IFile
  130. { (typeof(FspSrvIFile), 0), FspSrvIFile.Read },
  131. { (typeof(FspSrvIFile), 1), FspSrvIFile.Write },
  132. //IFileSystem
  133. { (typeof(FspSrvIFileSystem), 7), FspSrvIFileSystem.GetEntryType },
  134. { (typeof(FspSrvIFileSystem), 8), FspSrvIFileSystem.OpenFile },
  135. { (typeof(FspSrvIFileSystem), 10), FspSrvIFileSystem.Commit },
  136. //IStorage
  137. { (typeof(FspSrvIStorage), 0), FspSrvIStorage.Read },
  138. //IAppletResource
  139. { (typeof(HidIAppletResource), 0), HidIAppletResource.GetSharedMemoryHandle },
  140. //ISystemClock
  141. { (typeof(TimeISystemClock), 0), TimeISystemClock.GetCurrentTime },
  142. //IApplicationDisplayService
  143. { (typeof(ViIApplicationDisplayService), 100), ViIApplicationDisplayService.GetRelayService },
  144. { (typeof(ViIApplicationDisplayService), 101), ViIApplicationDisplayService.GetSystemDisplayService },
  145. { (typeof(ViIApplicationDisplayService), 102), ViIApplicationDisplayService.GetManagerDisplayService },
  146. { (typeof(ViIApplicationDisplayService), 103), ViIApplicationDisplayService.GetIndirectDisplayTransactionService },
  147. { (typeof(ViIApplicationDisplayService), 1010), ViIApplicationDisplayService.OpenDisplay },
  148. { (typeof(ViIApplicationDisplayService), 2020), ViIApplicationDisplayService.OpenLayer },
  149. { (typeof(ViIApplicationDisplayService), 2030), ViIApplicationDisplayService.CreateStrayLayer },
  150. { (typeof(ViIApplicationDisplayService), 2101), ViIApplicationDisplayService.SetLayerScalingMode },
  151. { (typeof(ViIApplicationDisplayService), 5202), ViIApplicationDisplayService.GetDisplayVSyncEvent },
  152. //IHOSBinderDriver
  153. { (typeof(ViIHOSBinderDriver), 0), ViIHOSBinderDriver.TransactParcel },
  154. { (typeof(ViIHOSBinderDriver), 1), ViIHOSBinderDriver.AdjustRefcount },
  155. { (typeof(ViIHOSBinderDriver), 2), ViIHOSBinderDriver.GetNativeHandle },
  156. //IManagerDisplayService
  157. { (typeof(ViIManagerDisplayService), 2010), ViIManagerDisplayService.CreateManagedLayer },
  158. { (typeof(ViIManagerDisplayService), 6000), ViIManagerDisplayService.AddToLayerStack },
  159. //ISystemDisplayService
  160. { (typeof(ViISystemDisplayService), 2205), ViISystemDisplayService.SetLayerZ },
  161. };
  162. private const long SfciMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24;
  163. private const long SfcoMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24;
  164. public static void ProcessRequest(
  165. Switch Ns,
  166. AMemory Memory,
  167. HSession Session,
  168. IpcMessage Request,
  169. long CmdPtr,
  170. int HndId)
  171. {
  172. IpcMessage Response = new IpcMessage(Request.IsDomain);
  173. using (MemoryStream Raw = new MemoryStream(Request.RawData))
  174. {
  175. BinaryReader ReqReader = new BinaryReader(Raw);
  176. if (Request.Type == IpcMessageType.Request)
  177. {
  178. string ServiceName = Session.ServiceName;
  179. ServiceProcessRequest ProcReq = null;
  180. bool IgnoreNullPR = false;
  181. string DbgServiceName = string.Empty;
  182. if (Session is HDomain Dom)
  183. {
  184. if (Request.DomCmd == IpcDomCmd.SendMsg)
  185. {
  186. long Magic = ReqReader.ReadInt64();
  187. int CmdId = (int)ReqReader.ReadInt64();
  188. object Obj = Dom.GetObject(Request.DomObjId);
  189. if (Obj is HDomain)
  190. {
  191. DbgServiceName = $"{ServiceName} {CmdId}";
  192. ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
  193. }
  194. else if (Obj != null)
  195. {
  196. DbgServiceName = $"{ServiceName} {Obj.GetType().Name} {CmdId}";
  197. ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
  198. }
  199. }
  200. else if (Request.DomCmd == IpcDomCmd.DeleteObj)
  201. {
  202. Dom.DeleteObject(Request.DomObjId);
  203. Response = FillResponse(Response, 0);
  204. IgnoreNullPR = true;
  205. }
  206. }
  207. else
  208. {
  209. long Magic = ReqReader.ReadInt64();
  210. int CmdId = (int)ReqReader.ReadInt64();
  211. if (Session is HSessionObj)
  212. {
  213. object Obj = ((HSessionObj)Session).Obj;
  214. DbgServiceName = $"{ServiceName} {Obj.GetType().Name} {CmdId}";
  215. ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
  216. }
  217. else
  218. {
  219. DbgServiceName = $"{ServiceName} {CmdId}";
  220. ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
  221. }
  222. }
  223. Logging.Debug($"IpcMessage: {DbgServiceName}");
  224. if (ProcReq != null)
  225. {
  226. using (MemoryStream ResMS = new MemoryStream())
  227. {
  228. BinaryWriter ResWriter = new BinaryWriter(ResMS);
  229. ServiceCtx Context = new ServiceCtx(
  230. Ns,
  231. Memory,
  232. Session,
  233. Request,
  234. Response,
  235. ReqReader,
  236. ResWriter);
  237. long Result = ProcReq(Context);
  238. Response = FillResponse(Response, Result, ResMS.ToArray());
  239. }
  240. }
  241. else if (!IgnoreNullPR)
  242. {
  243. throw new NotImplementedException(DbgServiceName);
  244. }
  245. }
  246. else if (Request.Type == IpcMessageType.Control)
  247. {
  248. long Magic = ReqReader.ReadInt64();
  249. long CmdId = ReqReader.ReadInt64();
  250. switch (CmdId)
  251. {
  252. case 0: Request = IpcConvertSessionToDomain(Ns, Session, Response, HndId); break;
  253. case 3: Request = IpcQueryBufferPointerSize(Response); break;
  254. case 4: Request = IpcDuplicateSessionEx(Ns, Session, Response, ReqReader); break;
  255. default: throw new NotImplementedException(CmdId.ToString());
  256. }
  257. }
  258. else if (Request.Type == IpcMessageType.Unknown2)
  259. {
  260. //TODO
  261. }
  262. else
  263. {
  264. throw new NotImplementedException(Request.Type.ToString());
  265. }
  266. AMemoryHelper.WriteBytes(Memory, CmdPtr, Response.GetBytes(CmdPtr));
  267. }
  268. }
  269. private static IpcMessage IpcConvertSessionToDomain(
  270. Switch Ns,
  271. HSession Session,
  272. IpcMessage Response,
  273. int HndId)
  274. {
  275. HDomain Dom = new HDomain(Session);
  276. Ns.Os.Handles.ReplaceData(HndId, Dom);
  277. return FillResponse(Response, 0, Dom.GenertateObjectId(Dom));
  278. }
  279. private static IpcMessage IpcDuplicateSessionEx(
  280. Switch Ns,
  281. HSession Session,
  282. IpcMessage Response,
  283. BinaryReader ReqReader)
  284. {
  285. int Unknown = ReqReader.ReadInt32();
  286. int Handle = Ns.Os.Handles.GenerateId(Session);
  287. Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
  288. return FillResponse(Response, 0);
  289. }
  290. private static IpcMessage IpcQueryBufferPointerSize(IpcMessage Response)
  291. {
  292. return FillResponse(Response, 0, 0x500);
  293. }
  294. private static IpcMessage FillResponse(IpcMessage Response, long Result, params int[] Values)
  295. {
  296. using (MemoryStream MS = new MemoryStream())
  297. {
  298. BinaryWriter Writer = new BinaryWriter(MS);
  299. foreach (int Value in Values)
  300. {
  301. Writer.Write(Value);
  302. }
  303. return FillResponse(Response, Result, MS.ToArray());
  304. }
  305. }
  306. private static IpcMessage FillResponse(IpcMessage Response, long Result, byte[] Data = null)
  307. {
  308. Response.Type = IpcMessageType.Response;
  309. using (MemoryStream MS = new MemoryStream())
  310. {
  311. BinaryWriter Writer = new BinaryWriter(MS);
  312. Writer.Write(SfcoMagic);
  313. Writer.Write(Result);
  314. if (Data != null)
  315. {
  316. Writer.Write(Data);
  317. }
  318. Response.RawData = MS.ToArray();
  319. }
  320. return Response;
  321. }
  322. }
  323. }