From 75c79e8d5e6d58b26081779378306aef34096be7 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 5 Aug 2019 22:39:27 -0400 Subject: [PATCH] Replaced appletHomeButtonReaderLockAccessorGetEvent with appletGetHomeButtonReaderLockAccessor. Added appletGetReaderLockAccessorEx, appletGetWriterLockAccessorEx, and appletGetHomeButtonWriterLockAccessor. Added support for AppletLockAccessor. --- nx/include/switch/services/applet.h | 67 ++++++++++- nx/source/services/applet.c | 168 +++++++++++++++++++++++++++- 2 files changed, 227 insertions(+), 8 deletions(-) diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index 3c6ce3df..b5272d85 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -186,6 +186,12 @@ struct AppletHookCookie void* param; ///< Callback parameter. }; +/// LockAccessor +typedef struct { + Service s; ///< ILockAccessor + Event event; ///< Event from the GetEvent cmd, with autoclear=false. +} AppletLockAccessor; + /// applet IStorage typedef struct { Service s; @@ -289,10 +295,27 @@ Result appletReleaseSleepLockTransiently(void); Result appletPushToGeneralChannel(AppletStorage *s); /** - * @brief Get an event that fires when the home button is pressed, doesn't interfere with home menu. This event does not auto clear. - * @note Doesn't fire for long press. + * @brief Gets a \ref AppletLockAccessor for HomeButtonReader. + * @note Similar to using \ref appletGetReaderLockAccessorEx with inval=0. + * @param a LockAccessor object. */ -Result appletHomeButtonReaderLockAccessorGetEvent(Event *out_event); +Result appletGetHomeButtonReaderLockAccessor(AppletLockAccessor *a); + +/** + * @brief Gets a Reader \ref AppletLockAccessor. + * @note Only available with [2.0.0+]. + * @param a LockAccessor object. + * @param[in] inval Input value, must be 0-3. 0 = HomeButton. + */ +Result appletGetReaderLockAccessorEx(AppletLockAccessor *a, u32 inval); + +/** + * @brief Gets a Writer \ref AppletLockAccessor. + * @note Only available with [7.0.0+]. On older sysvers, this is only available with AppletType_SystemApplet on [2.0.0+]. + * @param a LockAccessor object. + * @param[in] inval Input value, must be 0-3. 0 = HomeButton. + */ +Result appletGetWriterLockAccessorEx(AppletLockAccessor *a, u32 inval); /** * @brief Gets the Dock firmware version. @@ -792,6 +815,34 @@ Result appletReleaseCallerAppletCaptureSharedBuffer(void); */ Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCaptureSharedBuffer captureBuf); +// LockAccessor + +/** + * @brief Closes a LockAccessor. + * @param a LockAccessor object. + */ +void appletLockAccessorClose(AppletLockAccessor *a); + +/** + * @brief TryLock a LockAccessor. + * @param a LockAccessor object. + * @param[out] flag Whether locking was successful, when false this indicates that this func should be called again. + */ +Result appletLockAccessorTryLock(AppletLockAccessor *a, bool *flag); + +/** + * @brief Lock a LockAccessor. + * @note Similar to \ref appletLockAccessorTryLock, except this uses timeout U64_MAX with the eventWait call, and this uses TryLock repeatedly until the output flag value is true. + * @param a LockAccessor object. + */ +Result appletLockAccessorLock(AppletLockAccessor *a); + +/** + * @brief Unlock a LockAccessor. + * @param a LockAccessor object. + */ +Result appletLockAccessorUnlock(AppletLockAccessor *a); + // ILibraryAppletCreator /** @@ -1168,6 +1219,16 @@ Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlay */ Result appletGetGpuErrorDetectedSystemEvent(Event *out_event); +// IHomeMenuFunctions + +/** + * @brief Gets a \ref AppletLockAccessor for HomeButtonWriter. + * @note Only available with AppletType_SystemApplet. + * @note Similar to using \ref appletGetWriterLockAccessorEx with inval=0. + * @param a LockAccessor object. + */ +Result appletGetHomeButtonWriterLockAccessor(AppletLockAccessor *a); + // ILibraryAppletSelfAccessor /** diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index abb24115..770c1e91 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -652,6 +652,44 @@ static Result _appletGetSessionIn64(Service* srv, Service* srv_out, u64 cmd_id, return rc; } +static Result _appletGetSessionIn32(Service* srv, Service* srv_out, u64 cmd_id, u32 inval) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 inval; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->inval = inval; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(srv_out, srv, &r, 0); + } + } + + return rc; +} + static Result _appletCmdNoIO(Service* session, u64 cmd_id) { IpcCommand c; ipcInitialize(&c); @@ -1306,17 +1344,48 @@ Result appletPushToGeneralChannel(AppletStorage *s) { return _appletCmdInStorage(&g_appletICommonStateGetter, s, 20); } -Result appletHomeButtonReaderLockAccessorGetEvent(Event *out_event) { - Service ILockAccessor = {0}; - Result rc = _appletGetSession(&g_appletICommonStateGetter, &ILockAccessor, 30); +static Result _appletGetHomeButtonRwLockAccessor(Service* srv, AppletLockAccessor *a, u64 cmd_id) { + Result rc = _appletGetSession(srv, &a->s, cmd_id); if (R_FAILED(rc)) return rc; - rc = _appletGetEvent(&ILockAccessor, out_event, 3, false); - serviceClose(&ILockAccessor); + rc = _appletGetEvent(&a->s, &a->event, 3, false); + if (R_FAILED(rc)) serviceClose(&a->s); return rc; } +Result appletGetHomeButtonReaderLockAccessor(AppletLockAccessor *a) { + return _appletGetHomeButtonRwLockAccessor(&g_appletICommonStateGetter, a, 30); +} + +static Result _appletGetRwLockAccessor(Service* srv, AppletLockAccessor *a, u64 cmd_id, s32 inval) { + Result rc = _appletGetSessionIn32(srv, &a->s, cmd_id, inval); + if (R_FAILED(rc)) + return rc; + + rc = _appletGetEvent(&a->s, &a->event, 3, false); + if (R_FAILED(rc)) serviceClose(&a->s); + return rc; +} + +Result appletGetReaderLockAccessorEx(AppletLockAccessor *a, u32 inval) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletGetRwLockAccessor(&g_appletICommonStateGetter, a, 31, inval); +} + +Result appletGetWriterLockAccessorEx(AppletLockAccessor *a, u32 inval) { + if (hosversionBefore(7,0,0)) { + if (__nx_applet_type == AppletType_SystemApplet && hosversionAtLeast(2,0,0)) + return _appletGetRwLockAccessor(&g_appletIFunctions, a, 31, inval); + + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + + return _appletGetRwLockAccessor(&g_appletICommonStateGetter, a, 32, inval); +} + Result appletGetCradleFwVersion(u32 *out0, u32 *out1, u32 *out2, u32 *out3) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -2434,6 +2503,86 @@ Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCapt return rc; } +// LockAccessor +void appletLockAccessorClose(AppletLockAccessor *a) { + eventClose(&a->event); + serviceClose(&a->s); +} + +static Result _appletLockAccessorTryLock(AppletLockAccessor *a, bool get_handle, Handle* handle_out, bool *outflag) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 inflag; + } *raw; + + raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1; + raw->inflag = get_handle!=0; + + Result rc = serviceIpcDispatch(&a->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u8 outflag; + } *resp; + + serviceIpcParse(&a->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (handle_out) *handle_out = r.Handles[0]; + if (outflag) *outflag = resp->outflag!=0; + } + } + + return rc; +} + +Result appletLockAccessorTryLock(AppletLockAccessor *a, bool *flag) { + Result rc=0; + + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + rc = eventWait(&a->event, 0); + if (R_SUCCEEDED(rc)) rc = _appletLockAccessorTryLock(a, false, NULL, flag); + return rc; +} + +Result appletLockAccessorLock(AppletLockAccessor *a) { + Result rc=0; + bool flag=0; + + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + do { + rc = eventWait(&a->event, U64_MAX); + if (R_SUCCEEDED(rc)) rc = _appletLockAccessorTryLock(a, false, NULL, &flag); + if (R_FAILED(rc)) break; + } while(!flag); + + return rc; +} + +Result appletLockAccessorUnlock(AppletLockAccessor *a) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _appletCmdNoIO(&a->s, 2); +} + // ILibraryAppletCreator static Result _appletCreateLibraryApplet(Service* srv_out, AppletId id, LibAppletMode mode) { @@ -3781,6 +3930,15 @@ Result appletGetGpuErrorDetectedSystemEvent(Event *out_event) { return _appletGetEvent(&g_appletIFunctions, out_event, 130, false); } +// IHomeMenuFunctions + +Result appletGetHomeButtonWriterLockAccessor(AppletLockAccessor *a) { + if (__nx_applet_type != AppletType_SystemApplet) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _appletGetHomeButtonRwLockAccessor(&g_appletIFunctions, a, 30); +} + // ILibraryAppletSelfAccessor static Result _appletExitProcessAndReturn(void) {