am.cpp 15 KB

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