diff --git a/nx/include/switch/applets/libapplet.h b/nx/include/switch/applets/libapplet.h index c17f3f4d..77792c62 100644 --- a/nx/include/switch/applets/libapplet.h +++ b/nx/include/switch/applets/libapplet.h @@ -47,7 +47,7 @@ Result libappletCreateWriteStorage(AppletStorage* s, const void* buffer, size_t * @param s Storage object. * @param buffer Output buffer. * @param size Size to read. - * @param transfer_size Optional output size field for the actual size used for the read. + * @param transfer_size Optional output size field for the actual size used for the read, can be NULL. */ Result libappletReadStorage(AppletStorage* s, void* buffer, size_t size, size_t *transfer_size); @@ -71,10 +71,29 @@ Result libappletPushInData(AppletHolder *h, const void* buffer, size_t size); * @param h AppletHolder object. * @param buffer Output buffer. * @param size Size to read. - * @param transfer_size Optional output size field for the actual size used for the read. + * @param transfer_size Optional output size field for the actual size used for the read, can be NULL. */ Result libappletPopOutData(AppletHolder *h, void* buffer, size_t size, size_t *transfer_size); +/** + * @brief Starts the applet and waits for it to finish, then checks the \ref LibAppletExitReason. + * @note Uses \ref appletHolderStart and \ref appletHolderJoin. + * @param h AppletHolder object. + */ +Result libappletStart(AppletHolder *h); + +/** + * @brief Creates a LibraryApplet with the specified input storage data, uses \ref libappletStart, and reads the output storage reply data via \ref libappletPopOutData. + * @param id \ref AppletId + * @param commonargs \ref LibAppletArgs struct. + * @param arg Input storage data buffer. Optional, can be NULL. + * @param arg_size Size of the arg buffer. + * @param reply Output storage data buffer. Optional, can be NULL. + * @param reply_size Size to read for the reply buffer. + * @param out_reply_size Actual read reply data size, see \ref libappletPopOutData. + */ +Result libappletLaunch(AppletId id, LibAppletArgs *commonargs, const void* arg, size_t arg_size, void* reply, size_t reply_size, size_t *out_reply_size); + /// Wrapper for \ref appletPushToGeneralChannel, see appletPushToGeneralChannel regarding the requirements for using this. /// Returns to the main Home Menu, equivalent to pressing the HOME button. Result libappletRequestHomeMenu(void); diff --git a/nx/source/applets/libapplet.c b/nx/source/applets/libapplet.c index 374bdce3..c431ce5d 100644 --- a/nx/source/applets/libapplet.c +++ b/nx/source/applets/libapplet.c @@ -95,6 +95,44 @@ Result libappletPopOutData(AppletHolder *h, void* buffer, size_t size, size_t *t return rc; } +Result libappletStart(AppletHolder *h) { + Result rc=0; + + rc = appletHolderStart(h); + + if (R_SUCCEEDED(rc)) { + appletHolderJoin(h); + + LibAppletExitReason reason = appletHolderGetExitReason(h); + + if (reason == LibAppletExitReason_Canceled || reason == LibAppletExitReason_Abnormal || reason == LibAppletExitReason_Unexpected) { + rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit); + } + } + + return rc; +} + +Result libappletLaunch(AppletId id, LibAppletArgs *commonargs, const void* arg, size_t arg_size, void* reply, size_t reply_size, size_t *out_reply_size) { + Result rc=0; + AppletHolder holder; + + rc = appletCreateLibraryApplet(&holder, id, LibAppletMode_AllForeground); + if (R_FAILED(rc)) return rc; + + rc = libappletArgsPush(commonargs, &holder); + + if (R_SUCCEEDED(rc) && arg && arg_size) rc = libappletPushInData(&holder, arg, arg_size); + + if (R_SUCCEEDED(rc)) rc = libappletStart(&holder); + + if (R_SUCCEEDED(rc) && reply && reply_size) rc = libappletPopOutData(&holder, reply, reply_size, out_reply_size); + + appletHolderClose(&holder); + + return rc; +} + Result libappletRequestHomeMenu(void) { u8 storagedata[0x10] = {0x53, 0x41, 0x4d, 0x53, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};//RequestHomeMenu return _libappletQlaunchRequest(storagedata, sizeof(storagedata));