From f477da1d249efe782651b377af5c77a610d759f8 Mon Sep 17 00:00:00 2001 From: XorTroll Date: Tue, 13 Oct 2020 15:13:39 +0200 Subject: [PATCH] Fix home button detection and crashes when switching menus --- uDaemon/include/ipc/ipc_GlobalManager.hpp | 2 ++ uDaemon/source/Main.cpp | 36 ++++++++++++---------- uDaemon/source/ipc/ipc_IPrivateService.cpp | 31 +++++++++++-------- uMenu/source/am/am_DaemonMessages.cpp | 13 ++++---- uMenu/source/ui/ui_MenuLayout.cpp | 2 ++ uMenu/uMenu.json | 8 ++--- 6 files changed, 49 insertions(+), 43 deletions(-) diff --git a/uDaemon/include/ipc/ipc_GlobalManager.hpp b/uDaemon/include/ipc/ipc_GlobalManager.hpp index 59da67e..2350285 100644 --- a/uDaemon/include/ipc/ipc_GlobalManager.hpp +++ b/uDaemon/include/ipc/ipc_GlobalManager.hpp @@ -4,6 +4,8 @@ namespace ipc { + // Note: domains and pointer buffer are required since ECS sessions will make use of them (like normal fs interfaces) + struct ServerOptions { static const size_t PointerBufferSize = 0x400; static const size_t MaxDomains = 0x40; diff --git a/uDaemon/source/Main.cpp b/uDaemon/source/Main.cpp index 643d3c8..91628e3 100644 --- a/uDaemon/source/Main.cpp +++ b/uDaemon/source/Main.cpp @@ -13,6 +13,8 @@ #include #include +// Outside of anonymous namespace since these are accessed by IPC + ams::os::Mutex g_LastMenuMessageLock(false); dmi::MenuMessage g_LastMenuMessage = dmi::MenuMessage::Invalid; @@ -42,12 +44,12 @@ namespace { u8 *g_UsbViewerReadBuffer = nullptr; cfg::Config g_Config = {}; ams::os::ThreadType g_UsbViewerThread; - alignas(ams::os::ThreadStackAlignment) u8 g_UsbViewerThreadStack[0x8000]; + alignas(ams::os::ThreadStackAlignment) u8 g_UsbViewerThreadStack[0x4000]; UsbMode g_UsbViewerMode = UsbMode::Invalid; - // In the USB packet, the first u32 / the first 4 bytes are the USB mode (raw RGBA or JPEG, depending on what the console supports) + // In the USB packet, the first u32 stores the USB mode (raw RGBA or JPEG, depending on what the console supports) - constexpr size_t UsbPacketSize = RawRGBAScreenBufferSize + sizeof(u32); + constexpr size_t UsbPacketSize = RawRGBAScreenBufferSize + sizeof(UsbMode); } @@ -69,10 +71,13 @@ extern "C" { u32 __nx_applet_type = AppletType_SystemApplet; u32 __nx_fs_num_sessions = 1; + bool __nx_fsdev_support_cwd = false; + u32 __nx_fsdev_direntry_cache_size = 0; void __libnx_initheap(); void __appInit(); void __appExit(); + } extern char *fake_heap_start; @@ -99,10 +104,9 @@ void __appInit() { } void __appExit() { - ((void(*)())0xBEEFBABE)(); // qlaunch should not terminate, so this is considered an invalid system state // am would fatal otherwise - fatalThrow(0xDEBF); + fatalThrow(0xDEADBABE); } namespace { @@ -129,27 +133,25 @@ namespace { appletStartSleepSequence(true); } - Result LaunchMenu(dmi::MenuStartMode stmode, dmi::DaemonStatus status) { - R_TRY(ecs::RegisterLaunchAsApplet(g_Config.menu_program_id, static_cast(stmode), "/ulaunch/bin/uMenu", &status, sizeof(status))); - return ResultSuccess; + inline Result LaunchMenu(dmi::MenuStartMode stmode, dmi::DaemonStatus status) { + return ecs::RegisterLaunchAsApplet(g_Config.menu_program_id, static_cast(stmode), "/ulaunch/bin/uMenu", &status, sizeof(status)); } void HandleHomeButton() { if(am::LibraryAppletIsActive() && !am::LibraryAppletIsMenu()) { + // An applet is opened (which is not our menu), thus close it and reopen the menu am::LibraryAppletTerminate(); auto status = CreateStatus(); UL_ASSERT(LaunchMenu(dmi::MenuStartMode::Menu, status)); - return; } - if(am::ApplicationIsActive()) { - if(am::ApplicationHasForeground()) { - am::HomeMenuSetForeground(); - auto status = CreateStatus(); - UL_ASSERT(LaunchMenu(dmi::MenuStartMode::MenuApplicationSuspended, status)); - return; - } + else if(am::ApplicationIsActive() && am::ApplicationHasForeground()) { + // Hide the application currently on focus and open our menu + am::HomeMenuSetForeground(); + auto status = CreateStatus(); + UL_ASSERT(LaunchMenu(dmi::MenuStartMode::MenuApplicationSuspended, status)); } - if(am::LibraryAppletIsMenu()) { + else if(am::LibraryAppletIsMenu()) { + // Send a message to our menu to handle itself the home press std::scoped_lock lk(g_LastMenuMessageLock); g_LastMenuMessage = dmi::MenuMessage::HomeRequest; } diff --git a/uDaemon/source/ipc/ipc_IPrivateService.cpp b/uDaemon/source/ipc/ipc_IPrivateService.cpp index d9419b3..786d838 100644 --- a/uDaemon/source/ipc/ipc_IPrivateService.cpp +++ b/uDaemon/source/ipc/ipc_IPrivateService.cpp @@ -8,21 +8,20 @@ extern dmi::MenuMessage g_LastMenuMessage; namespace ipc { ams::Result PrivateService::Initialize(const ams::sf::ClientProcessId &client_pid) { - if(this->initialized) { - return ams::ResultSuccess(); - } - - u64 program_id = 0; - R_TRY(pminfoGetProgramId(&program_id, client_pid.process_id.value)); - - auto last_menu_program_id = am::LibraryAppletGetProgramIdForAppletId(am::LibraryAppletGetMenuAppletId()); - // If Menu hasn't been launched it's program ID will be 0/invalid, thus a != check wouldn't be enough - // If any of the IDs is invalid, something unexpected is happening... - if((last_menu_program_id == 0) || (program_id == 0) || (program_id != last_menu_program_id)) { - return RES_VALUE(Daemon, PrivateServiceInvalidProcess); + if(!this->initialized) { + u64 program_id = 0; + R_TRY(pminfoGetProgramId(&program_id, client_pid.process_id.value)); + + auto last_menu_program_id = am::LibraryAppletGetProgramIdForAppletId(am::LibraryAppletGetMenuAppletId()); + // If Menu hasn't been launched it's program ID will be 0/invalid, thus a != check wouldn't be enough + // If any of the IDs is invalid, something unexpected is happening... + if((last_menu_program_id == 0) || (program_id == 0) || (program_id != last_menu_program_id)) { + return RES_VALUE(Daemon, PrivateServiceInvalidProcess); + } + + this->initialized = true; } - this->initialized = true; return ams::ResultSuccess(); } @@ -33,6 +32,12 @@ namespace ipc { std::scoped_lock lk(g_LastMenuMessageLock); out_msg.SetValue(g_LastMenuMessage); + auto f = fopen("sdmc:/udaemon-priv.log", "ab+"); + if(f) { + auto msg = "Sending message: " + std::to_string(static_cast(g_LastMenuMessage)); + fwrite(msg.c_str(), msg.length(), 1, f); + fclose(f); + } g_LastMenuMessage = dmi::MenuMessage::Invalid; return ams::ResultSuccess(); } diff --git a/uMenu/source/am/am_DaemonMessages.cpp b/uMenu/source/am/am_DaemonMessages.cpp index 743b955..c0fcf7c 100644 --- a/uMenu/source/am/am_DaemonMessages.cpp +++ b/uMenu/source/am/am_DaemonMessages.cpp @@ -2,8 +2,6 @@ namespace { - Service g_DaemonPrivateService; - Result daemonPrivateInitialize(Service *srv) { u64 pid_placeholder = 0; return serviceDispatchIn(srv, 0, pid_placeholder, @@ -12,9 +10,11 @@ namespace { } Result daemonPrivateGetMessage(Service *srv, dmi::MenuMessage *out_msg) { - return serviceDispatchOut(&g_DaemonPrivateService, 1, out_msg); + return serviceDispatchOut(srv, 1, *out_msg); } + Service g_DaemonPrivateService; + Result daemonInitializePrivateService() { if(serviceIsActive(&g_DaemonPrivateService)) { return ResultSuccess; @@ -58,11 +58,10 @@ namespace am { break; } - auto tmp_msg = daemonGetMessage(); - + auto last_msg = daemonGetMessage(); mutexLock(&g_ReceiverLock); for(auto &[cb, msg] : g_ReceiverCallbackTable) { - if(msg == tmp_msg) { + if(msg == last_msg) { cb(); } } @@ -81,7 +80,7 @@ namespace am { R_TRY(daemonInitializePrivateService()); g_ReceiveThreadShouldStop = false; - R_TRY(threadCreate(&g_ReceiverThread, &DaemonMessageReceiverThread, nullptr, nullptr, 0x1000, 0x2b, -2)); + R_TRY(threadCreate(&g_ReceiverThread, &DaemonMessageReceiverThread, nullptr, nullptr, 0x2000, 0x2B, -2)); R_TRY(threadStart(&g_ReceiverThread)); g_Initialized = true; diff --git a/uMenu/source/ui/ui_MenuLayout.cpp b/uMenu/source/ui/ui_MenuLayout.cpp index aeaf19c..faf832f 100644 --- a/uMenu/source/ui/ui_MenuLayout.cpp +++ b/uMenu/source/ui/ui_MenuLayout.cpp @@ -679,6 +679,8 @@ namespace ui { } void MenuLayout::MoveFolder(const std::string &name, bool fade) { + this->itemsMenu->SetSelectedItem(0); + if(fade) { g_MenuApplication->FadeOut(); } diff --git a/uMenu/uMenu.json b/uMenu/uMenu.json index eca56d5..c075d5b 100644 --- a/uMenu/uMenu.json +++ b/uMenu/uMenu.json @@ -14,12 +14,8 @@ "filesystem_access": { "permissions": "0xFFFFFFFFFFFFFFFF" }, - "service_host": [ - "*" - ], - "service_access": [ - "*" - ], + "service_host": [ "*" ], + "service_access": [ "*" ], "kernel_capabilities": [ { "type": "kernel_flags",