diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index 33637c28..e5a6fa05 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -8,6 +8,7 @@ #include "../types.h" #include "../services/sm.h" #include "../kernel/tmem.h" +#include "../kernel/event.h" typedef enum { AppletType_None = -2, @@ -55,6 +56,37 @@ typedef enum { AppletLaunchParameterKind_Unknown = 3, ///< Unknown if used by anything? } AppletLaunchParameterKind; +typedef enum { + AppletId_overlayDisp = 0x02, ///< 010000000000100C "overlayDisp" + AppletId_qlaunch = 0x03, ///< 0100000000001000 "qlaunch" (SystemAppletMenu) + AppletId_starter = 0x04, ///< 0100000000001012 "starter" + AppletId_auth = 0x0A, ///< 0100000000001001 "auth" + AppletId_cabinet = 0x0B, ///< 0100000000001002 "cabinet" + AppletId_controller = 0x0C, ///< 0100000000001003 "controller" + AppletId_dataErase = 0x0D, ///< 0100000000001004 "dataErase" + AppletId_error = 0x0E, ///< 0100000000001005 "error" + AppletId_netConnect = 0x0F, ///< 0100000000001006 "netConnect" + AppletId_playerSelect = 0x10, ///< 0100000000001007 "playerSelect" + AppletId_swkbd = 0x11, ///< 0100000000001008 "swkbd" + AppletId_miiEdit = 0x12, ///< 0100000000001009 "miiEdit" + AppletId_web = 0x13, ///< 010000000000100A "LibAppletWeb" WebApplet applet + AppletId_shop = 0x14, ///< 010000000000100B "LibAppletShop" ShopN applet + AppletId_photoViewer = 0x15, ///< 010000000000100D "photoViewer" + AppletId_set = 0x16, ///< 010000000000100E "set" (This title is currently not present on retail devices.) + AppletId_offlineWeb = 0x17, ///< 010000000000100F "LibAppletOff" Offline web-applet + AppletId_loginShare = 0x18, ///< 0100000000001010 "LibAppletLns" Whitelisted web-applet + AppletId_wifiWebAuth = 0x19, ///< 0100000000001011 "LibAppletAuth" WifiWebAuth applet + AppletId_myPage = 0x1A, ///< 0100000000001013 "myPage" +} AppletId; + +/// LibraryAppletMode +typedef enum { + LibAppletMode_AllForeground = 0, + LibAppletMode_Background = 1, + LibAppletMode_Unknown2 = 2, + LibAppletMode_Unknown3 = 3, +} LibAppletMode; + /// applet hook function. typedef void (*AppletHookFn)(AppletHookType hook, void* param); @@ -74,6 +106,14 @@ typedef struct { TransferMemory tmem; } AppletStorage; +/// LibraryApplet state. +typedef struct { + Service s; ///< ILibraryAppletAccessor + Event StateChangedEvent; ///< Output from GetAppletStateChangedEvent, autoclear=false. + LibAppletMode mode; ///< See ref \ref LibAppletMode. + u64 layer_handle; ///< Output from GetIndirectLayerConsumerHandle on 2.0.0+. +} AppletHolder; + Result appletInitialize(void); void appletExit(void); Result appletGetAppletResourceUserId(u64 *out); @@ -141,6 +181,25 @@ Result appletSetScreenShotImageOrientation(s32 val); */ Result appletPushToGeneralChannel(AppletStorage *s); +/** + * @brief Creates a LibraryApplet. + * @param h AppletHolder object. + * @param id See \ref AppletId. + * @param mode See \ref LibAppletMode. + */ +Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mode); + +/// Closes an AppletHolder object. +void appletHolderClose(AppletHolder *h); + +/** + * @brief Gets the IndirectLayerConsumerHandle loaded during \ref appletCreateLibraryApplet, on 2.0.0+. + * @note Only available when \ref LibAppletMode is \ref LibAppletMode_Unknown3. + * @param h AppletHolder object. + * @param out Output IndirectLayerConsumerHandle. + */ +Result appletHolderGetIndirectLayerConsumerHandle(AppletHolder *h, u64 *out); + /** * @brief Creates a storage. * @param s Storage object. diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index 1ee1a028..4b23d500 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -1437,6 +1437,125 @@ static Result _appletExitProcessAndReturn(void) { // ILibraryAppletCreator +static Result _appletCreateLibraryApplet(Service* srv_out, AppletId id, LibAppletMode mode) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 id; + u32 mode; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletILibraryAppletCreator, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->id = id; + raw->mode = mode; + + Result rc = serviceIpcDispatch(&g_appletILibraryAppletCreator); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_appletILibraryAppletCreator, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && srv_out) { + serviceCreateSubservice(srv_out, &g_appletILibraryAppletCreator, &r, 0); + } + } + + return rc; +} + +static Result _appletGetIndirectLayerConsumerHandle(Service* srv, u64 *out) { + Result rc; + u64 AppletResourceUserId; + + rc = appletGetAppletResourceUserId(&AppletResourceUserId); + if (R_FAILED(rc)) return rc; + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 AppletResourceUserId; + } *raw; + + ipcSendPid(&c); + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 160; + raw->AppletResourceUserId = AppletResourceUserId; + + rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 out; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) *out = resp->out; + } + + return rc; +} + +Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mode) { + Result rc=0; + + memset(h, 0, sizeof(AppletHolder)); + h->mode = mode; + + rc = _appletCreateLibraryApplet(&h->s, id, mode); + + if (R_SUCCEEDED(rc)) rc = _appletGetEvent(&h->s, &h->StateChangedEvent, 0, false);//GetAppletStateChangedEvent + + if (R_SUCCEEDED(rc) && kernelAbove200() && h->mode == LibAppletMode_Unknown3) rc = _appletGetIndirectLayerConsumerHandle(&h->s, &h->layer_handle); + + return rc; +} + +void appletHolderClose(AppletHolder *h) { + eventClose(&h->StateChangedEvent); + serviceClose(&h->s); + memset(h, 0, sizeof(AppletHolder)); +} + +Result appletHolderGetIndirectLayerConsumerHandle(AppletHolder *h, u64 *out) { + if (!serviceIsActive(&h->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (h->mode!=LibAppletMode_Unknown3) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + if (!kernelAbove200()) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (out) *out = h->layer_handle; + + return 0; +} + Result appletCreateStorage(AppletStorage *s, s64 size) { memset(s, 0, sizeof(AppletStorage));