am.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include <cinttypes>
  7. #include <cstring>
  8. #include "audio_core/audio_renderer.h"
  9. #include "core/core.h"
  10. #include "core/file_sys/savedata_factory.h"
  11. #include "core/hle/ipc_helpers.h"
  12. #include "core/hle/kernel/kernel.h"
  13. #include "core/hle/kernel/process.h"
  14. #include "core/hle/kernel/readable_event.h"
  15. #include "core/hle/kernel/shared_memory.h"
  16. #include "core/hle/kernel/writable_event.h"
  17. #include "core/hle/service/acc/profile_manager.h"
  18. #include "core/hle/service/am/am.h"
  19. #include "core/hle/service/am/applet_ae.h"
  20. #include "core/hle/service/am/applet_oe.h"
  21. #include "core/hle/service/am/applets/applets.h"
  22. #include "core/hle/service/am/applets/profile_select.h"
  23. #include "core/hle/service/am/applets/software_keyboard.h"
  24. #include "core/hle/service/am/applets/stub_applet.h"
  25. #include "core/hle/service/am/applets/web_browser.h"
  26. #include "core/hle/service/am/idle.h"
  27. #include "core/hle/service/am/omm.h"
  28. #include "core/hle/service/am/spsm.h"
  29. #include "core/hle/service/am/tcap.h"
  30. #include "core/hle/service/apm/apm.h"
  31. #include "core/hle/service/filesystem/filesystem.h"
  32. #include "core/hle/service/nvflinger/nvflinger.h"
  33. #include "core/hle/service/pm/pm.h"
  34. #include "core/hle/service/set/set.h"
  35. #include "core/hle/service/vi/vi.h"
  36. #include "core/settings.h"
  37. namespace Service::AM {
  38. constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
  39. constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
  40. constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
  41. enum class AppletId : u32 {
  42. ProfileSelect = 0x10,
  43. SoftwareKeyboard = 0x11,
  44. LibAppletOff = 0x17,
  45. };
  46. constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
  47. struct LaunchParameters {
  48. u32_le magic;
  49. u32_le is_account_selected;
  50. u128 current_user;
  51. INSERT_PADDING_BYTES(0x70);
  52. };
  53. static_assert(sizeof(LaunchParameters) == 0x88);
  54. IWindowController::IWindowController() : ServiceFramework("IWindowController") {
  55. // clang-format off
  56. static const FunctionInfo functions[] = {
  57. {0, nullptr, "CreateWindow"},
  58. {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
  59. {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
  60. {11, nullptr, "ReleaseForegroundRights"},
  61. {12, nullptr, "RejectToChangeIntoBackground"},
  62. {20, nullptr, "SetAppletWindowVisibility"},
  63. {21, nullptr, "SetAppletGpuTimeSlice"},
  64. };
  65. // clang-format on
  66. RegisterHandlers(functions);
  67. }
  68. IWindowController::~IWindowController() = default;
  69. void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
  70. const u64 process_id = Core::System::GetInstance().Kernel().CurrentProcess()->GetProcessID();
  71. LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
  72. IPC::ResponseBuilder rb{ctx, 4};
  73. rb.Push(RESULT_SUCCESS);
  74. rb.Push<u64>(process_id);
  75. }
  76. void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
  77. LOG_WARNING(Service_AM, "(STUBBED) called");
  78. IPC::ResponseBuilder rb{ctx, 2};
  79. rb.Push(RESULT_SUCCESS);
  80. }
  81. IAudioController::IAudioController() : ServiceFramework("IAudioController") {
  82. // clang-format off
  83. static const FunctionInfo functions[] = {
  84. {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
  85. {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
  86. {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
  87. {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
  88. {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
  89. };
  90. // clang-format on
  91. RegisterHandlers(functions);
  92. }
  93. IAudioController::~IAudioController() = default;
  94. void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
  95. IPC::RequestParser rp{ctx};
  96. const float main_applet_volume_tmp = rp.Pop<float>();
  97. const float library_applet_volume_tmp = rp.Pop<float>();
  98. LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
  99. main_applet_volume_tmp, library_applet_volume_tmp);
  100. // Ensure the volume values remain within the 0-100% range
  101. main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
  102. library_applet_volume =
  103. std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
  104. IPC::ResponseBuilder rb{ctx, 2};
  105. rb.Push(RESULT_SUCCESS);
  106. }
  107. void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
  108. LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
  109. IPC::ResponseBuilder rb{ctx, 3};
  110. rb.Push(RESULT_SUCCESS);
  111. rb.Push(main_applet_volume);
  112. }
  113. void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
  114. LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
  115. IPC::ResponseBuilder rb{ctx, 3};
  116. rb.Push(RESULT_SUCCESS);
  117. rb.Push(library_applet_volume);
  118. }
  119. void IAudioController::ChangeMainAppletMasterVolume(Kernel::HLERequestContext& ctx) {
  120. struct Parameters {
  121. float volume;
  122. s64 fade_time_ns;
  123. };
  124. static_assert(sizeof(Parameters) == 16);
  125. IPC::RequestParser rp{ctx};
  126. const auto parameters = rp.PopRaw<Parameters>();
  127. LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
  128. parameters.fade_time_ns);
  129. main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
  130. fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
  131. IPC::ResponseBuilder rb{ctx, 2};
  132. rb.Push(RESULT_SUCCESS);
  133. }
  134. void IAudioController::SetTransparentAudioRate(Kernel::HLERequestContext& ctx) {
  135. IPC::RequestParser rp{ctx};
  136. const float transparent_volume_rate_tmp = rp.Pop<float>();
  137. LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
  138. // Clamp volume range to 0-100%.
  139. transparent_volume_rate =
  140. std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
  141. IPC::ResponseBuilder rb{ctx, 2};
  142. rb.Push(RESULT_SUCCESS);
  143. }
  144. IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {
  145. // clang-format off
  146. static const FunctionInfo functions[] = {
  147. {0, nullptr, "GetLastForegroundCaptureImage"},
  148. {1, nullptr, "UpdateLastForegroundCaptureImage"},
  149. {2, nullptr, "GetLastApplicationCaptureImage"},
  150. {3, nullptr, "GetCallerAppletCaptureImage"},
  151. {4, nullptr, "UpdateCallerAppletCaptureImage"},
  152. {5, nullptr, "GetLastForegroundCaptureImageEx"},
  153. {6, nullptr, "GetLastApplicationCaptureImageEx"},
  154. {7, nullptr, "GetCallerAppletCaptureImageEx"},
  155. {8, nullptr, "TakeScreenShotOfOwnLayer"}, // 2.0.0+
  156. {9, nullptr, "CopyBetweenCaptureBuffers"}, // 5.0.0+
  157. {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
  158. {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
  159. {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
  160. {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
  161. {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
  162. {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
  163. {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
  164. {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
  165. {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
  166. // 2.0.0+
  167. {20, nullptr, "ClearCaptureBuffer"},
  168. {21, nullptr, "ClearAppletTransitionBuffer"},
  169. // 4.0.0+
  170. {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
  171. {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
  172. {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
  173. {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
  174. {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"},
  175. {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"},
  176. // 6.0.0+
  177. {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
  178. };
  179. // clang-format on
  180. RegisterHandlers(functions);
  181. }
  182. IDisplayController::~IDisplayController() = default;
  183. IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
  184. // clang-format off
  185. static const FunctionInfo functions[] = {
  186. {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
  187. {1, nullptr, "OpenMainApplication"},
  188. {10, nullptr, "EmulateButtonEvent"},
  189. {20, nullptr, "InvalidateTransitionLayer"},
  190. {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
  191. {40, nullptr, "GetAppletResourceUsageInfo"},
  192. };
  193. // clang-format on
  194. RegisterHandlers(functions);
  195. }
  196. IDebugFunctions::~IDebugFunctions() = default;
  197. ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
  198. : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
  199. // clang-format off
  200. static const FunctionInfo functions[] = {
  201. {0, nullptr, "Exit"},
  202. {1, &ISelfController::LockExit, "LockExit"},
  203. {2, &ISelfController::UnlockExit, "UnlockExit"},
  204. {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
  205. {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
  206. {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
  207. {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
  208. {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
  209. {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
  210. {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
  211. {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
  212. {15, nullptr, "SetScreenShotAppletIdentityInfo"},
  213. {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
  214. {17, nullptr, "SetControllerFirmwareUpdateSection"},
  215. {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
  216. {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"},
  217. {20, nullptr, "SetDesirableKeyboardLayout"},
  218. {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
  219. {41, nullptr, "IsSystemBufferSharingEnabled"},
  220. {42, nullptr, "GetSystemSharedLayerHandle"},
  221. {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
  222. {51, nullptr, "ApproveToDisplay"},
  223. {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
  224. {61, nullptr, "SetMediaPlaybackState"},
  225. {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
  226. {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
  227. {64, nullptr, "SetInputDetectionSourceSet"},
  228. {65, nullptr, "ReportUserIsActive"},
  229. {66, nullptr, "GetCurrentIlluminance"},
  230. {67, nullptr, "IsIlluminanceAvailable"},
  231. {68, nullptr, "SetAutoSleepDisabled"},
  232. {69, nullptr, "IsAutoSleepDisabled"},
  233. {70, nullptr, "ReportMultimediaError"},
  234. {80, nullptr, "SetWirelessPriorityMode"},
  235. {90, nullptr, "GetAccumulatedSuspendedTickValue"},
  236. {91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"},
  237. {1000, nullptr, "GetDebugStorageChannel"},
  238. };
  239. // clang-format on
  240. RegisterHandlers(functions);
  241. auto& kernel = Core::System::GetInstance().Kernel();
  242. launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
  243. "ISelfController:LaunchableEvent");
  244. }
  245. ISelfController::~ISelfController() = default;
  246. void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
  247. LOG_WARNING(Service_AM, "(STUBBED) called");
  248. IPC::ResponseBuilder rb{ctx, 2};
  249. rb.Push(RESULT_SUCCESS);
  250. }
  251. void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
  252. LOG_WARNING(Service_AM, "(STUBBED) called");
  253. IPC::ResponseBuilder rb{ctx, 2};
  254. rb.Push(RESULT_SUCCESS);
  255. }
  256. void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) {
  257. ++num_fatal_sections_entered;
  258. LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
  259. IPC::ResponseBuilder rb{ctx, 2};
  260. rb.Push(RESULT_SUCCESS);
  261. }
  262. void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
  263. LOG_DEBUG(Service_AM, "called.");
  264. // Entry and exit of fatal sections must be balanced.
  265. if (num_fatal_sections_entered == 0) {
  266. IPC::ResponseBuilder rb{ctx, 2};
  267. rb.Push(ResultCode{ErrorModule::AM, 512});
  268. return;
  269. }
  270. --num_fatal_sections_entered;
  271. IPC::ResponseBuilder rb{ctx, 2};
  272. rb.Push(RESULT_SUCCESS);
  273. }
  274. void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
  275. LOG_WARNING(Service_AM, "(STUBBED) called");
  276. launchable_event.writable->Signal();
  277. IPC::ResponseBuilder rb{ctx, 2, 1};
  278. rb.Push(RESULT_SUCCESS);
  279. rb.PushCopyObjects(launchable_event.readable);
  280. }
  281. void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
  282. LOG_WARNING(Service_AM, "(STUBBED) called");
  283. IPC::ResponseBuilder rb{ctx, 2};
  284. rb.Push(RESULT_SUCCESS);
  285. }
  286. void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
  287. IPC::RequestParser rp{ctx};
  288. bool flag = rp.Pop<bool>();
  289. LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
  290. IPC::ResponseBuilder rb{ctx, 2};
  291. rb.Push(RESULT_SUCCESS);
  292. }
  293. void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
  294. IPC::RequestParser rp{ctx};
  295. bool flag = rp.Pop<bool>();
  296. LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
  297. IPC::ResponseBuilder rb{ctx, 2};
  298. rb.Push(RESULT_SUCCESS);
  299. }
  300. void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
  301. // Takes 3 input u8s with each field located immediately after the previous
  302. // u8, these are bool flags. No output.
  303. LOG_WARNING(Service_AM, "(STUBBED) called");
  304. IPC::RequestParser rp{ctx};
  305. struct FocusHandlingModeParams {
  306. u8 unknown0;
  307. u8 unknown1;
  308. u8 unknown2;
  309. };
  310. auto flags = rp.PopRaw<FocusHandlingModeParams>();
  311. IPC::ResponseBuilder rb{ctx, 2};
  312. rb.Push(RESULT_SUCCESS);
  313. }
  314. void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
  315. LOG_WARNING(Service_AM, "(STUBBED) called");
  316. IPC::ResponseBuilder rb{ctx, 2};
  317. rb.Push(RESULT_SUCCESS);
  318. }
  319. void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
  320. // Takes 3 input u8s with each field located immediately after the previous
  321. // u8, these are bool flags. No output.
  322. IPC::RequestParser rp{ctx};
  323. bool enabled = rp.Pop<bool>();
  324. LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
  325. IPC::ResponseBuilder rb{ctx, 2};
  326. rb.Push(RESULT_SUCCESS);
  327. }
  328. void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
  329. LOG_WARNING(Service_AM, "(STUBBED) called");
  330. IPC::ResponseBuilder rb{ctx, 2};
  331. rb.Push(RESULT_SUCCESS);
  332. }
  333. void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
  334. LOG_WARNING(Service_AM, "(STUBBED) called");
  335. // TODO(Subv): Find out how AM determines the display to use, for now just
  336. // create the layer in the Default display.
  337. const auto display_id = nvflinger->OpenDisplay("Default");
  338. const auto layer_id = nvflinger->CreateLayer(*display_id);
  339. IPC::ResponseBuilder rb{ctx, 4};
  340. rb.Push(RESULT_SUCCESS);
  341. rb.Push(*layer_id);
  342. }
  343. void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
  344. LOG_WARNING(Service_AM, "(STUBBED) called");
  345. IPC::ResponseBuilder rb{ctx, 2};
  346. rb.Push(RESULT_SUCCESS);
  347. }
  348. void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
  349. IPC::RequestParser rp{ctx};
  350. idle_time_detection_extension = rp.Pop<u32>();
  351. LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
  352. idle_time_detection_extension);
  353. IPC::ResponseBuilder rb{ctx, 2};
  354. rb.Push(RESULT_SUCCESS);
  355. }
  356. void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
  357. LOG_WARNING(Service_AM, "(STUBBED) called");
  358. IPC::ResponseBuilder rb{ctx, 3};
  359. rb.Push(RESULT_SUCCESS);
  360. rb.Push<u32>(idle_time_detection_extension);
  361. }
  362. AppletMessageQueue::AppletMessageQueue() {
  363. auto& kernel = Core::System::GetInstance().Kernel();
  364. on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
  365. "AMMessageQueue:OnMessageRecieved");
  366. on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
  367. kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged");
  368. }
  369. AppletMessageQueue::~AppletMessageQueue() = default;
  370. const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetMesssageRecieveEvent()
  371. const {
  372. return on_new_message.readable;
  373. }
  374. const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
  375. const {
  376. return on_operation_mode_changed.readable;
  377. }
  378. void AppletMessageQueue::PushMessage(AppletMessage msg) {
  379. messages.push(msg);
  380. on_new_message.writable->Signal();
  381. }
  382. AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
  383. if (messages.empty()) {
  384. on_new_message.writable->Clear();
  385. return AppletMessage::NoMessage;
  386. }
  387. auto msg = messages.front();
  388. messages.pop();
  389. if (messages.empty()) {
  390. on_new_message.writable->Clear();
  391. }
  392. return msg;
  393. }
  394. std::size_t AppletMessageQueue::GetMessageCount() const {
  395. return messages.size();
  396. }
  397. void AppletMessageQueue::OperationModeChanged() {
  398. PushMessage(AppletMessage::OperationModeChanged);
  399. PushMessage(AppletMessage::PerformanceModeChanged);
  400. on_operation_mode_changed.writable->Signal();
  401. }
  402. ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue)
  403. : ServiceFramework("ICommonStateGetter"), msg_queue(std::move(msg_queue)) {
  404. // clang-format off
  405. static const FunctionInfo functions[] = {
  406. {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
  407. {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
  408. {2, nullptr, "GetThisAppletKind"},
  409. {3, nullptr, "AllowToEnterSleep"},
  410. {4, nullptr, "DisallowToEnterSleep"},
  411. {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
  412. {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
  413. {7, nullptr, "GetCradleStatus"},
  414. {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
  415. {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
  416. {10, nullptr, "RequestToAcquireSleepLock"},
  417. {11, nullptr, "ReleaseSleepLock"},
  418. {12, nullptr, "ReleaseSleepLockTransiently"},
  419. {13, nullptr, "GetAcquiredSleepLockEvent"},
  420. {20, nullptr, "PushToGeneralChannel"},
  421. {30, nullptr, "GetHomeButtonReaderLockAccessor"},
  422. {31, nullptr, "GetReaderLockAccessorEx"},
  423. {40, nullptr, "GetCradleFwVersion"},
  424. {50, nullptr, "IsVrModeEnabled"},
  425. {51, nullptr, "SetVrModeEnabled"},
  426. {52, nullptr, "SwitchLcdBacklight"},
  427. {55, nullptr, "IsInControllerFirmwareUpdateSection"},
  428. {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
  429. {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
  430. {62, nullptr, "GetHdcpAuthenticationState"},
  431. {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
  432. };
  433. // clang-format on
  434. RegisterHandlers(functions);
  435. }
  436. ICommonStateGetter::~ICommonStateGetter() = default;
  437. void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
  438. LOG_DEBUG(Service_AM, "called");
  439. IPC::ResponseBuilder rb{ctx, 3};
  440. rb.Push(RESULT_SUCCESS);
  441. rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
  442. }
  443. void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
  444. LOG_DEBUG(Service_AM, "called");
  445. IPC::ResponseBuilder rb{ctx, 2, 1};
  446. rb.Push(RESULT_SUCCESS);
  447. rb.PushCopyObjects(msg_queue->GetMesssageRecieveEvent());
  448. }
  449. void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
  450. LOG_DEBUG(Service_AM, "called");
  451. const auto message = msg_queue->PopMessage();
  452. IPC::ResponseBuilder rb{ctx, 3};
  453. if (message == AppletMessageQueue::AppletMessage::NoMessage) {
  454. LOG_ERROR(Service_AM, "Message queue is empty");
  455. rb.Push(ERR_NO_MESSAGES);
  456. rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
  457. return;
  458. }
  459. rb.Push(RESULT_SUCCESS);
  460. rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
  461. }
  462. void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
  463. LOG_WARNING(Service_AM, "(STUBBED) called");
  464. IPC::ResponseBuilder rb{ctx, 3};
  465. rb.Push(RESULT_SUCCESS);
  466. rb.Push(static_cast<u8>(FocusState::InFocus));
  467. }
  468. void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
  469. LOG_DEBUG(Service_AM, "called");
  470. IPC::ResponseBuilder rb{ctx, 2, 1};
  471. rb.Push(RESULT_SUCCESS);
  472. rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
  473. }
  474. void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) {
  475. LOG_DEBUG(Service_AM, "called");
  476. IPC::ResponseBuilder rb{ctx, 4};
  477. rb.Push(RESULT_SUCCESS);
  478. if (Settings::values.use_docked_mode) {
  479. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
  480. static_cast<u32>(Settings::values.resolution_factor));
  481. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
  482. static_cast<u32>(Settings::values.resolution_factor));
  483. } else {
  484. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
  485. static_cast<u32>(Settings::values.resolution_factor));
  486. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
  487. static_cast<u32>(Settings::values.resolution_factor));
  488. }
  489. }
  490. IStorage::IStorage(std::vector<u8> buffer)
  491. : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
  492. // clang-format off
  493. static const FunctionInfo functions[] = {
  494. {0, &IStorage::Open, "Open"},
  495. {1, nullptr, "OpenTransferStorage"},
  496. };
  497. // clang-format on
  498. RegisterHandlers(functions);
  499. }
  500. IStorage::~IStorage() = default;
  501. const std::vector<u8>& IStorage::GetData() const {
  502. return buffer;
  503. }
  504. void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
  505. const bool use_docked_mode{Settings::values.use_docked_mode};
  506. LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
  507. IPC::ResponseBuilder rb{ctx, 3};
  508. rb.Push(RESULT_SUCCESS);
  509. rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
  510. }
  511. void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
  512. const bool use_docked_mode{Settings::values.use_docked_mode};
  513. LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
  514. IPC::ResponseBuilder rb{ctx, 3};
  515. rb.Push(RESULT_SUCCESS);
  516. rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
  517. : APM::PerformanceMode::Handheld));
  518. }
  519. class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
  520. public:
  521. explicit ILibraryAppletAccessor(std::shared_ptr<Applets::Applet> applet)
  522. : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) {
  523. // clang-format off
  524. static const FunctionInfo functions[] = {
  525. {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
  526. {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
  527. {10, &ILibraryAppletAccessor::Start, "Start"},
  528. {20, nullptr, "RequestExit"},
  529. {25, nullptr, "Terminate"},
  530. {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
  531. {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
  532. {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
  533. {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
  534. {102, nullptr, "PushExtraStorage"},
  535. {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
  536. {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
  537. {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
  538. {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
  539. {110, nullptr, "NeedsToExitProcess"},
  540. {120, nullptr, "GetLibraryAppletInfo"},
  541. {150, nullptr, "RequestForAppletToGetForeground"},
  542. {160, nullptr, "GetIndirectLayerConsumerHandle"},
  543. };
  544. // clang-format on
  545. RegisterHandlers(functions);
  546. }
  547. private:
  548. void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) {
  549. LOG_DEBUG(Service_AM, "called");
  550. const auto event = applet->GetBroker().GetStateChangedEvent();
  551. IPC::ResponseBuilder rb{ctx, 2, 1};
  552. rb.Push(RESULT_SUCCESS);
  553. rb.PushCopyObjects(event);
  554. }
  555. void IsCompleted(Kernel::HLERequestContext& ctx) {
  556. LOG_DEBUG(Service_AM, "called");
  557. IPC::ResponseBuilder rb{ctx, 3};
  558. rb.Push(RESULT_SUCCESS);
  559. rb.Push<u32>(applet->TransactionComplete());
  560. }
  561. void GetResult(Kernel::HLERequestContext& ctx) {
  562. LOG_DEBUG(Service_AM, "called");
  563. IPC::ResponseBuilder rb{ctx, 2};
  564. rb.Push(applet->GetStatus());
  565. }
  566. void Start(Kernel::HLERequestContext& ctx) {
  567. LOG_DEBUG(Service_AM, "called");
  568. ASSERT(applet != nullptr);
  569. applet->Initialize();
  570. applet->Execute();
  571. IPC::ResponseBuilder rb{ctx, 2};
  572. rb.Push(RESULT_SUCCESS);
  573. }
  574. void PushInData(Kernel::HLERequestContext& ctx) {
  575. LOG_DEBUG(Service_AM, "called");
  576. IPC::RequestParser rp{ctx};
  577. applet->GetBroker().PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>());
  578. IPC::ResponseBuilder rb{ctx, 2};
  579. rb.Push(RESULT_SUCCESS);
  580. }
  581. void PopOutData(Kernel::HLERequestContext& ctx) {
  582. LOG_DEBUG(Service_AM, "called");
  583. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  584. const auto storage = applet->GetBroker().PopNormalDataToGame();
  585. if (storage == nullptr) {
  586. LOG_ERROR(Service_AM,
  587. "storage is a nullptr. There is no data in the current normal channel");
  588. rb.Push(ERR_NO_DATA_IN_CHANNEL);
  589. return;
  590. }
  591. rb.Push(RESULT_SUCCESS);
  592. rb.PushIpcInterface<IStorage>(std::move(*storage));
  593. }
  594. void PushInteractiveInData(Kernel::HLERequestContext& ctx) {
  595. LOG_DEBUG(Service_AM, "called");
  596. IPC::RequestParser rp{ctx};
  597. applet->GetBroker().PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>());
  598. ASSERT(applet->IsInitialized());
  599. applet->ExecuteInteractive();
  600. applet->Execute();
  601. IPC::ResponseBuilder rb{ctx, 2};
  602. rb.Push(RESULT_SUCCESS);
  603. }
  604. void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
  605. LOG_DEBUG(Service_AM, "called");
  606. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  607. const auto storage = applet->GetBroker().PopInteractiveDataToGame();
  608. if (storage == nullptr) {
  609. LOG_ERROR(Service_AM,
  610. "storage is a nullptr. There is no data in the current interactive channel");
  611. rb.Push(ERR_NO_DATA_IN_CHANNEL);
  612. return;
  613. }
  614. rb.Push(RESULT_SUCCESS);
  615. rb.PushIpcInterface<IStorage>(std::move(*storage));
  616. }
  617. void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
  618. LOG_DEBUG(Service_AM, "called");
  619. IPC::ResponseBuilder rb{ctx, 2, 1};
  620. rb.Push(RESULT_SUCCESS);
  621. rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
  622. }
  623. void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
  624. LOG_DEBUG(Service_AM, "called");
  625. IPC::ResponseBuilder rb{ctx, 2, 1};
  626. rb.Push(RESULT_SUCCESS);
  627. rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
  628. }
  629. std::shared_ptr<Applets::Applet> applet;
  630. };
  631. void IStorage::Open(Kernel::HLERequestContext& ctx) {
  632. LOG_DEBUG(Service_AM, "called");
  633. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  634. rb.Push(RESULT_SUCCESS);
  635. rb.PushIpcInterface<IStorageAccessor>(*this);
  636. }
  637. IStorageAccessor::IStorageAccessor(IStorage& storage)
  638. : ServiceFramework("IStorageAccessor"), backing(storage) {
  639. // clang-format off
  640. static const FunctionInfo functions[] = {
  641. {0, &IStorageAccessor::GetSize, "GetSize"},
  642. {10, &IStorageAccessor::Write, "Write"},
  643. {11, &IStorageAccessor::Read, "Read"},
  644. };
  645. // clang-format on
  646. RegisterHandlers(functions);
  647. }
  648. IStorageAccessor::~IStorageAccessor() = default;
  649. void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) {
  650. LOG_DEBUG(Service_AM, "called");
  651. IPC::ResponseBuilder rb{ctx, 4};
  652. rb.Push(RESULT_SUCCESS);
  653. rb.Push(static_cast<u64>(backing.buffer.size()));
  654. }
  655. void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
  656. IPC::RequestParser rp{ctx};
  657. const u64 offset{rp.Pop<u64>()};
  658. const std::vector<u8> data{ctx.ReadBuffer()};
  659. LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size());
  660. if (data.size() > backing.buffer.size() - offset) {
  661. LOG_ERROR(Service_AM,
  662. "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
  663. backing.buffer.size(), data.size(), offset);
  664. IPC::ResponseBuilder rb{ctx, 2};
  665. rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
  666. }
  667. std::memcpy(backing.buffer.data() + offset, data.data(), data.size());
  668. IPC::ResponseBuilder rb{ctx, 2};
  669. rb.Push(RESULT_SUCCESS);
  670. }
  671. void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
  672. IPC::RequestParser rp{ctx};
  673. const u64 offset{rp.Pop<u64>()};
  674. const std::size_t size{ctx.GetWriteBufferSize()};
  675. LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
  676. if (size > backing.buffer.size() - offset) {
  677. LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
  678. backing.buffer.size(), size, offset);
  679. IPC::ResponseBuilder rb{ctx, 2};
  680. rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
  681. }
  682. ctx.WriteBuffer(backing.buffer.data() + offset, size);
  683. IPC::ResponseBuilder rb{ctx, 2};
  684. rb.Push(RESULT_SUCCESS);
  685. }
  686. ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {
  687. static const FunctionInfo functions[] = {
  688. {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
  689. {1, nullptr, "TerminateAllLibraryApplets"},
  690. {2, nullptr, "AreAnyLibraryAppletsLeft"},
  691. {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
  692. {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
  693. {12, nullptr, "CreateHandleStorage"},
  694. };
  695. RegisterHandlers(functions);
  696. }
  697. ILibraryAppletCreator::~ILibraryAppletCreator() = default;
  698. static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
  699. switch (id) {
  700. case AppletId::ProfileSelect:
  701. return std::make_shared<Applets::ProfileSelect>();
  702. case AppletId::SoftwareKeyboard:
  703. return std::make_shared<Applets::SoftwareKeyboard>();
  704. case AppletId::LibAppletOff:
  705. return std::make_shared<Applets::WebBrowser>();
  706. default:
  707. LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!",
  708. static_cast<u32>(id));
  709. return std::make_shared<Applets::StubApplet>();
  710. }
  711. }
  712. void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
  713. IPC::RequestParser rp{ctx};
  714. const auto applet_id = rp.PopRaw<AppletId>();
  715. const auto applet_mode = rp.PopRaw<u32>();
  716. LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
  717. static_cast<u32>(applet_id), applet_mode);
  718. const auto applet = GetAppletFromId(applet_id);
  719. if (applet == nullptr) {
  720. LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
  721. IPC::ResponseBuilder rb{ctx, 2};
  722. rb.Push(ResultCode(-1));
  723. return;
  724. }
  725. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  726. rb.Push(RESULT_SUCCESS);
  727. rb.PushIpcInterface<AM::ILibraryAppletAccessor>(applet);
  728. }
  729. void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
  730. IPC::RequestParser rp{ctx};
  731. const u64 size{rp.Pop<u64>()};
  732. LOG_DEBUG(Service_AM, "called, size={}", size);
  733. std::vector<u8> buffer(size);
  734. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  735. rb.Push(RESULT_SUCCESS);
  736. rb.PushIpcInterface<AM::IStorage>(std::move(buffer));
  737. }
  738. void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
  739. LOG_DEBUG(Service_AM, "called");
  740. IPC::RequestParser rp{ctx};
  741. rp.SetCurrentOffset(3);
  742. const auto handle{rp.Pop<Kernel::Handle>()};
  743. const auto shared_mem =
  744. Core::System::GetInstance().CurrentProcess()->GetHandleTable().Get<Kernel::SharedMemory>(
  745. handle);
  746. if (shared_mem == nullptr) {
  747. LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
  748. IPC::ResponseBuilder rb{ctx, 2};
  749. rb.Push(ResultCode(-1));
  750. return;
  751. }
  752. const u8* mem_begin = shared_mem->GetPointer();
  753. const u8* mem_end = mem_begin + shared_mem->GetSize();
  754. std::vector<u8> memory{mem_begin, mem_end};
  755. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  756. rb.Push(RESULT_SUCCESS);
  757. rb.PushIpcInterface(std::make_shared<IStorage>(std::move(memory)));
  758. }
  759. IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
  760. // clang-format off
  761. static const FunctionInfo functions[] = {
  762. {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
  763. {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
  764. {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
  765. {12, nullptr, "CreateApplicationAndRequestToStart"},
  766. {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
  767. {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
  768. {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
  769. {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
  770. {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
  771. {24, nullptr, "GetLaunchStorageInfoForDebug"},
  772. {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
  773. {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
  774. {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
  775. {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
  776. {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
  777. {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
  778. {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
  779. {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
  780. {60, nullptr, "SetMediaPlaybackStateForApplication"},
  781. {65, nullptr, "IsGamePlayRecordingSupported"},
  782. {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
  783. {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
  784. {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
  785. {70, nullptr, "RequestToShutdown"},
  786. {71, nullptr, "RequestToReboot"},
  787. {80, nullptr, "ExitAndRequestToShowThanksMessage"},
  788. {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
  789. {100, nullptr, "InitializeApplicationCopyrightFrameBuffer"},
  790. {101, nullptr, "SetApplicationCopyrightImage"},
  791. {102, nullptr, "SetApplicationCopyrightVisibility"},
  792. {110, nullptr, "QueryApplicationPlayStatistics"},
  793. {120, nullptr, "ExecuteProgram"},
  794. {121, nullptr, "ClearUserChannel"},
  795. {122, nullptr, "UnpopToUserChannel"},
  796. {500, nullptr, "StartContinuousRecordingFlushForDebug"},
  797. {1000, nullptr, "CreateMovieMaker"},
  798. {1001, nullptr, "PrepareForJit"},
  799. };
  800. // clang-format on
  801. RegisterHandlers(functions);
  802. }
  803. IApplicationFunctions::~IApplicationFunctions() = default;
  804. void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestContext& ctx) {
  805. LOG_WARNING(Service_AM, "(STUBBED) called");
  806. IPC::ResponseBuilder rb{ctx, 2};
  807. rb.Push(RESULT_SUCCESS);
  808. }
  809. void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
  810. Kernel::HLERequestContext& ctx) {
  811. LOG_WARNING(Service_AM, "(STUBBED) called");
  812. IPC::ResponseBuilder rb{ctx, 2};
  813. rb.Push(RESULT_SUCCESS);
  814. }
  815. void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(
  816. Kernel::HLERequestContext& ctx) {
  817. LOG_WARNING(Service_AM, "(STUBBED) called");
  818. IPC::ResponseBuilder rb{ctx, 2};
  819. rb.Push(RESULT_SUCCESS);
  820. }
  821. void IApplicationFunctions::BeginBlockingHomeButton(Kernel::HLERequestContext& ctx) {
  822. LOG_WARNING(Service_AM, "(STUBBED) called");
  823. IPC::ResponseBuilder rb{ctx, 2};
  824. rb.Push(RESULT_SUCCESS);
  825. }
  826. void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx) {
  827. LOG_WARNING(Service_AM, "(STUBBED) called");
  828. IPC::ResponseBuilder rb{ctx, 2};
  829. rb.Push(RESULT_SUCCESS);
  830. }
  831. void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
  832. LOG_DEBUG(Service_AM, "called");
  833. LaunchParameters params{};
  834. params.magic = POP_LAUNCH_PARAMETER_MAGIC;
  835. params.is_account_selected = 1;
  836. Account::ProfileManager profile_manager{};
  837. const auto uuid = profile_manager.GetUser(Settings::values.current_user);
  838. ASSERT(uuid);
  839. params.current_user = uuid->uuid;
  840. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  841. rb.Push(RESULT_SUCCESS);
  842. std::vector<u8> buffer(sizeof(LaunchParameters));
  843. std::memcpy(buffer.data(), &params, buffer.size());
  844. rb.PushIpcInterface<AM::IStorage>(buffer);
  845. }
  846. void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
  847. Kernel::HLERequestContext& ctx) {
  848. LOG_WARNING(Service_AM, "(STUBBED) called");
  849. IPC::ResponseBuilder rb{ctx, 2};
  850. rb.Push(RESULT_SUCCESS);
  851. }
  852. void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
  853. IPC::RequestParser rp{ctx};
  854. u128 uid = rp.PopRaw<u128>(); // What does this do?
  855. LOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
  856. IPC::ResponseBuilder rb{ctx, 4};
  857. rb.Push(RESULT_SUCCESS);
  858. rb.Push<u64>(0);
  859. } // namespace Service::AM
  860. void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
  861. // Takes an input u32 Result, no output.
  862. // For example, in some cases official apps use this with error 0x2A2 then
  863. // uses svcBreak.
  864. IPC::RequestParser rp{ctx};
  865. u32 result = rp.Pop<u32>();
  866. LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
  867. IPC::ResponseBuilder rb{ctx, 2};
  868. rb.Push(RESULT_SUCCESS);
  869. }
  870. void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
  871. LOG_WARNING(Service_AM, "(STUBBED) called");
  872. IPC::ResponseBuilder rb{ctx, 6};
  873. rb.Push(RESULT_SUCCESS);
  874. rb.Push<u64>(1);
  875. rb.Push<u64>(0);
  876. }
  877. void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
  878. // TODO(bunnei): This should be configurable
  879. LOG_DEBUG(Service_AM, "called");
  880. IPC::ResponseBuilder rb{ctx, 4};
  881. rb.Push(RESULT_SUCCESS);
  882. rb.Push(
  883. static_cast<u64>(Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index)));
  884. }
  885. void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
  886. LOG_WARNING(Service_AM, "(STUBBED) called");
  887. IPC::ResponseBuilder rb{ctx, 2};
  888. rb.Push(RESULT_SUCCESS);
  889. }
  890. void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
  891. LOG_WARNING(Service_AM, "(STUBBED) called");
  892. IPC::ResponseBuilder rb{ctx, 2};
  893. rb.Push(RESULT_SUCCESS);
  894. }
  895. void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
  896. LOG_WARNING(Service_AM, "(STUBBED) called");
  897. IPC::ResponseBuilder rb{ctx, 3};
  898. rb.Push(RESULT_SUCCESS);
  899. rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
  900. }
  901. void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
  902. LOG_WARNING(Service_AM, "(STUBBED) called");
  903. IPC::ResponseBuilder rb{ctx, 6};
  904. rb.Push(RESULT_SUCCESS);
  905. // Returns a 128-bit UUID
  906. rb.Push<u64>(0);
  907. rb.Push<u64>(0);
  908. }
  909. void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
  910. IPC::RequestParser rp{ctx};
  911. const auto type{rp.PopRaw<FileSys::SaveDataType>()};
  912. rp.Skip(1, false);
  913. const auto user_id{rp.PopRaw<u128>()};
  914. const auto new_normal_size{rp.PopRaw<u64>()};
  915. const auto new_journal_size{rp.PopRaw<u64>()};
  916. LOG_DEBUG(Service_AM,
  917. "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
  918. "new_journal={:016X}",
  919. static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
  920. FileSystem::WriteSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id,
  921. {new_normal_size, new_journal_size});
  922. IPC::ResponseBuilder rb{ctx, 4};
  923. rb.Push(RESULT_SUCCESS);
  924. // The following value is used upon failure to help the system recover.
  925. // Since we always succeed, this should be 0.
  926. rb.Push<u64>(0);
  927. }
  928. void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
  929. IPC::RequestParser rp{ctx};
  930. const auto type{rp.PopRaw<FileSys::SaveDataType>()};
  931. rp.Skip(1, false);
  932. const auto user_id{rp.PopRaw<u128>()};
  933. LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", static_cast<u8>(type),
  934. user_id[1], user_id[0]);
  935. const auto size =
  936. FileSystem::ReadSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id);
  937. IPC::ResponseBuilder rb{ctx, 6};
  938. rb.Push(RESULT_SUCCESS);
  939. rb.Push(size.normal);
  940. rb.Push(size.journal);
  941. }
  942. void InstallInterfaces(SM::ServiceManager& service_manager,
  943. std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
  944. auto message_queue = std::make_shared<AppletMessageQueue>();
  945. message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); // Needed on
  946. // game boot
  947. std::make_shared<AppletAE>(nvflinger, message_queue)->InstallAsService(service_manager);
  948. std::make_shared<AppletOE>(nvflinger, message_queue)->InstallAsService(service_manager);
  949. std::make_shared<IdleSys>()->InstallAsService(service_manager);
  950. std::make_shared<OMM>()->InstallAsService(service_manager);
  951. std::make_shared<SPSM>()->InstallAsService(service_manager);
  952. std::make_shared<TCAP>()->InstallAsService(service_manager);
  953. }
  954. IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") {
  955. // clang-format off
  956. static const FunctionInfo functions[] = {
  957. {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
  958. {11, nullptr, "LockForeground"},
  959. {12, nullptr, "UnlockForeground"},
  960. {20, nullptr, "PopFromGeneralChannel"},
  961. {21, nullptr, "GetPopFromGeneralChannelEvent"},
  962. {30, nullptr, "GetHomeButtonWriterLockAccessor"},
  963. {31, nullptr, "GetWriterLockAccessorEx"},
  964. {100, nullptr, "PopRequestLaunchApplicationForDebug"},
  965. };
  966. // clang-format on
  967. RegisterHandlers(functions);
  968. }
  969. IHomeMenuFunctions::~IHomeMenuFunctions() = default;
  970. void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
  971. LOG_WARNING(Service_AM, "(STUBBED) called");
  972. IPC::ResponseBuilder rb{ctx, 2};
  973. rb.Push(RESULT_SUCCESS);
  974. }
  975. IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStateController") {
  976. // clang-format off
  977. static const FunctionInfo functions[] = {
  978. {0, nullptr, "RequestToEnterSleep"},
  979. {1, nullptr, "EnterSleep"},
  980. {2, nullptr, "StartSleepSequence"},
  981. {3, nullptr, "StartShutdownSequence"},
  982. {4, nullptr, "StartRebootSequence"},
  983. {10, nullptr, "LoadAndApplyIdlePolicySettings"},
  984. {11, nullptr, "NotifyCecSettingsChanged"},
  985. {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
  986. {13, nullptr, "UpdateDefaultDisplayResolution"},
  987. {14, nullptr, "ShouldSleepOnBoot"},
  988. {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
  989. };
  990. // clang-format on
  991. RegisterHandlers(functions);
  992. }
  993. IGlobalStateController::~IGlobalStateController() = default;
  994. IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreator") {
  995. // clang-format off
  996. static const FunctionInfo functions[] = {
  997. {0, nullptr, "CreateApplication"},
  998. {1, nullptr, "PopLaunchRequestedApplication"},
  999. {10, nullptr, "CreateSystemApplication"},
  1000. {100, nullptr, "PopFloatingApplicationForDevelopment"},
  1001. };
  1002. // clang-format on
  1003. RegisterHandlers(functions);
  1004. }
  1005. IApplicationCreator::~IApplicationCreator() = default;
  1006. IProcessWindingController::IProcessWindingController()
  1007. : ServiceFramework("IProcessWindingController") {
  1008. // clang-format off
  1009. static const FunctionInfo functions[] = {
  1010. {0, nullptr, "GetLaunchReason"},
  1011. {11, nullptr, "OpenCallingLibraryApplet"},
  1012. {21, nullptr, "PushContext"},
  1013. {22, nullptr, "PopContext"},
  1014. {23, nullptr, "CancelWindingReservation"},
  1015. {30, nullptr, "WindAndDoReserved"},
  1016. {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
  1017. {41, nullptr, "ReserveToStartAndWait"},
  1018. };
  1019. // clang-format on
  1020. RegisterHandlers(functions);
  1021. }
  1022. IProcessWindingController::~IProcessWindingController() = default;
  1023. } // namespace Service::AM