applet_oe.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/logging/log.h"
  5. #include "core/hle/ipc_helpers.h"
  6. #include "core/hle/kernel/event.h"
  7. #include "core/hle/service/am/applet_oe.h"
  8. #include "core/hle/service/apm/apm.h"
  9. #include "core/hle/service/nvflinger/nvflinger.h"
  10. namespace Service {
  11. namespace AM {
  12. class IWindowController final : public ServiceFramework<IWindowController> {
  13. public:
  14. IWindowController() : ServiceFramework("IWindowController") {
  15. static const FunctionInfo functions[] = {
  16. {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
  17. {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
  18. };
  19. RegisterHandlers(functions);
  20. }
  21. private:
  22. void GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
  23. LOG_WARNING(Service, "(STUBBED) called");
  24. IPC::ResponseBuilder rb{ctx, 4};
  25. rb.Push(RESULT_SUCCESS);
  26. rb.Push<u64>(0);
  27. }
  28. void AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
  29. LOG_WARNING(Service, "(STUBBED) called");
  30. IPC::ResponseBuilder rb{ctx, 2};
  31. rb.Push(RESULT_SUCCESS);
  32. }
  33. };
  34. class IAudioController final : public ServiceFramework<IAudioController> {
  35. public:
  36. IAudioController() : ServiceFramework("IAudioController") {}
  37. };
  38. class IDisplayController final : public ServiceFramework<IDisplayController> {
  39. public:
  40. IDisplayController() : ServiceFramework("IDisplayController") {}
  41. };
  42. class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
  43. public:
  44. IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
  45. };
  46. class ISelfController final : public ServiceFramework<ISelfController> {
  47. public:
  48. ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
  49. : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
  50. static const FunctionInfo functions[] = {
  51. {1, &ISelfController::LockExit, "LockExit"},
  52. {2, &ISelfController::UnlockExit, "UnlockExit"},
  53. {11, &ISelfController::SetOperationModeChangedNotification,
  54. "SetOperationModeChangedNotification"},
  55. {12, &ISelfController::SetPerformanceModeChangedNotification,
  56. "SetPerformanceModeChangedNotification"},
  57. {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
  58. {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
  59. {16, &ISelfController::SetOutOfFocusSuspendingEnabled,
  60. "SetOutOfFocusSuspendingEnabled"},
  61. {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
  62. };
  63. RegisterHandlers(functions);
  64. }
  65. private:
  66. void SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
  67. // Takes 3 input u8s with each field located immediately after the previous u8, these are
  68. // bool flags. No output.
  69. IPC::RequestParser rp{ctx};
  70. struct FocusHandlingModeParams {
  71. u8 unknown0;
  72. u8 unknown1;
  73. u8 unknown2;
  74. };
  75. auto flags = rp.PopRaw<FocusHandlingModeParams>();
  76. IPC::ResponseBuilder rb{ctx, 2};
  77. rb.Push(RESULT_SUCCESS);
  78. LOG_WARNING(Service, "(STUBBED) called");
  79. }
  80. void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
  81. IPC::ResponseBuilder rb{ctx, 2};
  82. rb.Push(RESULT_SUCCESS);
  83. LOG_WARNING(Service, "(STUBBED) called");
  84. }
  85. void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
  86. IPC::RequestParser rp{ctx};
  87. bool flag = rp.Pop<bool>();
  88. IPC::ResponseBuilder rb{ctx, 2};
  89. rb.Push(RESULT_SUCCESS);
  90. LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
  91. }
  92. void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
  93. IPC::RequestParser rp{ctx};
  94. bool flag = rp.Pop<bool>();
  95. IPC::ResponseBuilder rb{ctx, 2};
  96. rb.Push(RESULT_SUCCESS);
  97. LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
  98. }
  99. void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
  100. // Takes 3 input u8s with each field located immediately after the previous u8, these are
  101. // bool flags. No output.
  102. IPC::RequestParser rp{ctx};
  103. bool enabled = rp.Pop<bool>();
  104. IPC::ResponseBuilder rb{ctx, 2};
  105. rb.Push(RESULT_SUCCESS);
  106. LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled));
  107. }
  108. void LockExit(Kernel::HLERequestContext& ctx) {
  109. IPC::ResponseBuilder rb{ctx, 2};
  110. rb.Push(RESULT_SUCCESS);
  111. LOG_WARNING(Service, "(STUBBED) called");
  112. }
  113. void UnlockExit(Kernel::HLERequestContext& ctx) {
  114. IPC::ResponseBuilder rb{ctx, 2};
  115. rb.Push(RESULT_SUCCESS);
  116. LOG_WARNING(Service, "(STUBBED) called");
  117. }
  118. void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
  119. // TODO(Subv): Find out how AM determines the display to use, for now just create the layer
  120. // in the Default display.
  121. u64 display_id = nvflinger->OpenDisplay("Default");
  122. u64 layer_id = nvflinger->CreateLayer(display_id);
  123. IPC::ResponseBuilder rb{ctx, 4};
  124. rb.Push(RESULT_SUCCESS);
  125. rb.Push(layer_id);
  126. LOG_WARNING(Service, "(STUBBED) called");
  127. }
  128. std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
  129. };
  130. class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
  131. public:
  132. ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
  133. static const FunctionInfo functions[] = {
  134. {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
  135. {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
  136. {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
  137. {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
  138. {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
  139. };
  140. RegisterHandlers(functions);
  141. event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
  142. }
  143. private:
  144. enum class FocusState : u8 {
  145. InFocus = 1,
  146. NotInFocus = 2,
  147. };
  148. enum class OperationMode : u8 {
  149. Handheld = 0,
  150. Docked = 1,
  151. };
  152. void GetEventHandle(Kernel::HLERequestContext& ctx) {
  153. event->Signal();
  154. IPC::ResponseBuilder rb{ctx, 2, 1};
  155. rb.Push(RESULT_SUCCESS);
  156. rb.PushCopyObjects(event);
  157. LOG_WARNING(Service, "(STUBBED) called");
  158. }
  159. void ReceiveMessage(Kernel::HLERequestContext& ctx) {
  160. IPC::ResponseBuilder rb{ctx, 3};
  161. rb.Push(RESULT_SUCCESS);
  162. rb.Push<u32>(15);
  163. LOG_WARNING(Service, "(STUBBED) called");
  164. }
  165. void GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
  166. IPC::ResponseBuilder rb{ctx, 3};
  167. rb.Push(RESULT_SUCCESS);
  168. rb.Push(static_cast<u8>(FocusState::InFocus));
  169. LOG_WARNING(Service, "(STUBBED) called");
  170. }
  171. void GetOperationMode(Kernel::HLERequestContext& ctx) {
  172. IPC::ResponseBuilder rb{ctx, 3};
  173. rb.Push(RESULT_SUCCESS);
  174. rb.Push(static_cast<u8>(OperationMode::Handheld));
  175. LOG_WARNING(Service, "(STUBBED) called");
  176. }
  177. void GetPerformanceMode(Kernel::HLERequestContext& ctx) {
  178. IPC::ResponseBuilder rb{ctx, 3};
  179. rb.Push(RESULT_SUCCESS);
  180. rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld));
  181. LOG_WARNING(Service, "(STUBBED) called");
  182. }
  183. Kernel::SharedPtr<Kernel::Event> event;
  184. };
  185. class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
  186. public:
  187. explicit IStorageAccessor(std::vector<u8> buffer)
  188. : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
  189. static const FunctionInfo functions[] = {
  190. {0, &IStorageAccessor::GetSize, "GetSize"},
  191. {11, &IStorageAccessor::Read, "Read"},
  192. };
  193. RegisterHandlers(functions);
  194. }
  195. private:
  196. std::vector<u8> buffer;
  197. void GetSize(Kernel::HLERequestContext& ctx) {
  198. IPC::ResponseBuilder rb{ctx, 4};
  199. rb.Push(RESULT_SUCCESS);
  200. rb.Push(static_cast<u64>(buffer.size()));
  201. LOG_DEBUG(Service, "called");
  202. }
  203. void Read(Kernel::HLERequestContext& ctx) {
  204. IPC::RequestParser rp{ctx};
  205. u64 offset = rp.Pop<u64>();
  206. const auto& output_buffer = ctx.BufferDescriptorC()[0];
  207. ASSERT(offset + output_buffer.Size() <= buffer.size());
  208. Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size());
  209. IPC::ResponseBuilder rb{ctx, 2};
  210. rb.Push(RESULT_SUCCESS);
  211. LOG_DEBUG(Service, "called");
  212. }
  213. };
  214. class IStorage final : public ServiceFramework<IStorage> {
  215. public:
  216. explicit IStorage(std::vector<u8> buffer)
  217. : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
  218. static const FunctionInfo functions[] = {
  219. {0, &IStorage::Open, "Open"},
  220. };
  221. RegisterHandlers(functions);
  222. }
  223. private:
  224. std::vector<u8> buffer;
  225. void Open(Kernel::HLERequestContext& ctx) {
  226. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  227. rb.Push(RESULT_SUCCESS);
  228. rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
  229. LOG_DEBUG(Service, "called");
  230. }
  231. };
  232. class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
  233. public:
  234. IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
  235. static const FunctionInfo functions[] = {
  236. {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
  237. {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
  238. {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
  239. {66, &IApplicationFunctions::InitializeGamePlayRecording,
  240. "InitializeGamePlayRecording"},
  241. {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
  242. {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
  243. };
  244. RegisterHandlers(functions);
  245. }
  246. private:
  247. void PopLaunchParameter(Kernel::HLERequestContext& ctx) {
  248. constexpr u8 data[0x88] = {
  249. 0xca, 0x97, 0x94, 0xc7, // Magic
  250. 1, 0, 0, 0, // IsAccountSelected (bool)
  251. 1, 0, 0, 0, // User Id (word 0)
  252. 0, 0, 0, 0, // User Id (word 1)
  253. 0, 0, 0, 0, // User Id (word 2)
  254. 0, 0, 0, 0 // User Id (word 3)
  255. };
  256. std::vector<u8> buffer(data, data + sizeof(data));
  257. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  258. rb.Push(RESULT_SUCCESS);
  259. rb.PushIpcInterface<AM::IStorage>(buffer);
  260. LOG_DEBUG(Service, "called");
  261. }
  262. void SetTerminateResult(Kernel::HLERequestContext& ctx) {
  263. // Takes an input u32 Result, no output.
  264. // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak.
  265. IPC::RequestParser rp{ctx};
  266. u32 result = rp.Pop<u32>();
  267. IPC::ResponseBuilder rb{ctx, 2};
  268. rb.Push(RESULT_SUCCESS);
  269. LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result);
  270. }
  271. void GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
  272. IPC::ResponseBuilder rb{ctx, 4};
  273. rb.Push(RESULT_SUCCESS);
  274. rb.Push<u64>(SystemLanguage::English);
  275. LOG_WARNING(Service, "(STUBBED) called");
  276. }
  277. void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
  278. IPC::ResponseBuilder rb{ctx, 2};
  279. rb.Push(RESULT_SUCCESS);
  280. LOG_WARNING(Service, "(STUBBED) called");
  281. }
  282. void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
  283. IPC::ResponseBuilder rb{ctx, 2};
  284. rb.Push(RESULT_SUCCESS);
  285. LOG_WARNING(Service, "(STUBBED) called");
  286. }
  287. void NotifyRunning(Kernel::HLERequestContext& ctx) {
  288. IPC::ResponseBuilder rb{ctx, 3};
  289. rb.Push(RESULT_SUCCESS);
  290. rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
  291. LOG_WARNING(Service, "(STUBBED) called");
  292. }
  293. };
  294. class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
  295. public:
  296. ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {}
  297. };
  298. class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
  299. public:
  300. IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
  301. : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)) {
  302. static const FunctionInfo functions[] = {
  303. {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
  304. {1, &IApplicationProxy::GetSelfController, "GetSelfController"},
  305. {2, &IApplicationProxy::GetWindowController, "GetWindowController"},
  306. {3, &IApplicationProxy::GetAudioController, "GetAudioController"},
  307. {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
  308. {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
  309. {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
  310. {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
  311. };
  312. RegisterHandlers(functions);
  313. }
  314. private:
  315. void GetAudioController(Kernel::HLERequestContext& ctx) {
  316. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  317. rb.Push(RESULT_SUCCESS);
  318. rb.PushIpcInterface<IAudioController>();
  319. LOG_DEBUG(Service, "called");
  320. }
  321. void GetDisplayController(Kernel::HLERequestContext& ctx) {
  322. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  323. rb.Push(RESULT_SUCCESS);
  324. rb.PushIpcInterface<IDisplayController>();
  325. LOG_DEBUG(Service, "called");
  326. }
  327. void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
  328. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  329. rb.Push(RESULT_SUCCESS);
  330. rb.PushIpcInterface<IDebugFunctions>();
  331. LOG_DEBUG(Service, "called");
  332. }
  333. void GetWindowController(Kernel::HLERequestContext& ctx) {
  334. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  335. rb.Push(RESULT_SUCCESS);
  336. rb.PushIpcInterface<IWindowController>();
  337. LOG_DEBUG(Service, "called");
  338. }
  339. void GetSelfController(Kernel::HLERequestContext& ctx) {
  340. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  341. rb.Push(RESULT_SUCCESS);
  342. rb.PushIpcInterface<ISelfController>(nvflinger);
  343. LOG_DEBUG(Service, "called");
  344. }
  345. void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
  346. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  347. rb.Push(RESULT_SUCCESS);
  348. rb.PushIpcInterface<ICommonStateGetter>();
  349. LOG_DEBUG(Service, "called");
  350. }
  351. void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
  352. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  353. rb.Push(RESULT_SUCCESS);
  354. rb.PushIpcInterface<ILibraryAppletCreator>();
  355. LOG_DEBUG(Service, "called");
  356. }
  357. void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
  358. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  359. rb.Push(RESULT_SUCCESS);
  360. rb.PushIpcInterface<IApplicationFunctions>();
  361. LOG_DEBUG(Service, "called");
  362. }
  363. std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
  364. };
  365. void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
  366. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  367. rb.Push(RESULT_SUCCESS);
  368. rb.PushIpcInterface<IApplicationProxy>(nvflinger);
  369. LOG_DEBUG(Service, "called");
  370. }
  371. AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
  372. : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)) {
  373. static const FunctionInfo functions[] = {
  374. {0x00000000, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
  375. };
  376. RegisterHandlers(functions);
  377. }
  378. } // namespace AM
  379. } // namespace Service