diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 5cd13794..dd5ab686 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -221,6 +221,11 @@ typedef struct { u8 unk_x1a[0x6]; ///< Unknown. } NsApplicationRightsOnClient; +/// DownloadTaskStatus +typedef struct { + u8 unk_x0[0x20]; ///< Unknown. +} NsDownloadTaskStatus; + /// Default size for \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater. This is the size used by qlaunch for SetupCardUpdate. #define NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT 0x100000 @@ -243,6 +248,10 @@ Service* nsGetServiceSession_ApplicationManagerInterface(void); /// Only available on [3.0.0+]. Result nsGetFactoryResetInterface(Service* srv_out); +/// Gets the Service object for IDownloadTaskInterface via the cmd for that. +/// Only available on [3.0.0+]. +Result nsGetDownloadTaskInterface(Service* srv_out); + /// Gets the Service object for IContentManagementInterface via the cmd for that. /// Only available on [3.0.0+]. Result nsGetContentManagementInterface(Service* srv_out); @@ -967,6 +976,75 @@ Result nsGetPromotionInfo(NsPromotionInfo *promotion, u64 application_id, Accoun ///@} +///@name IDownloadTaskInterface +///@{ + +/** + * @brief ClearTaskStatusList + * @note Uses \ref nsGetDownloadTaskInterface on [3.0.0+], otherwise IApplicationManagerInterface is used. + * @note Only available on [2.0.0+]. + */ +Result nsClearTaskStatusList(void); + +/** + * @brief RequestDownloadTaskList + * @note Uses \ref nsGetDownloadTaskInterface on [3.0.0+], otherwise IApplicationManagerInterface is used. + * @note Only available on [2.0.0+]. + */ +Result nsRequestDownloadTaskList(void); + +/** + * @brief RequestEnsureDownloadTask + * @note Uses \ref nsGetDownloadTaskInterface on [3.0.0+], otherwise IApplicationManagerInterface is used. + * @note Only available on [2.0.0+]. + * @param[out] a \ref AsyncResult + */ +Result nsRequestEnsureDownloadTask(AsyncResult *a); + +/** + * @brief ListDownloadTaskStatus + * @note Uses \ref nsGetDownloadTaskInterface on [3.0.0+], otherwise IApplicationManagerInterface is used. + * @note Only available on [2.0.0+]. + * @param[out] tasks Output array of \ref NsDownloadTaskStatus. + * @param[in] count Size of the tasks array in entries. A maximum of 0x100 tasks can be stored in state. + * @param[out] total_out Total output entries. + */ +Result nsListDownloadTaskStatus(NsDownloadTaskStatus* tasks, s32 count, s32 *total_out); + +/** + * @brief RequestDownloadTaskListData + * @note Uses \ref nsGetDownloadTaskInterface on [3.0.0+], otherwise IApplicationManagerInterface is used. + * @note Only available on [2.0.0+]. + * @param[out] a \ref AsyncValue + */ +Result nsRequestDownloadTaskListData(AsyncValue *a); + +/** + * @brief TryCommitCurrentApplicationDownloadTask + * @note Only available on [4.0.0+]. + */ +Result nsTryCommitCurrentApplicationDownloadTask(void); + +/** + * @brief EnableAutoCommit + * @note Only available on [4.0.0+]. + */ +Result nsEnableAutoCommit(void); + +/** + * @brief DisableAutoCommit + * @note Only available on [4.0.0+]. + */ +Result nsDisableAutoCommit(void); + +/** + * @brief TriggerDynamicCommitEvent + * @note Only available on [4.0.0+]. + */ +Result nsTriggerDynamicCommitEvent(void); + +///@} + ///@name IContentManagementInterface ///@{ diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 4f8ec96b..f0bba149 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -53,6 +53,13 @@ Result nsGetFactoryResetInterface(Service* srv_out) { return _nsGetSession(&g_nsGetterSrv, srv_out, 7994); } +Result nsGetDownloadTaskInterface(Service* srv_out) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsGetSession(&g_nsGetterSrv, srv_out, 7997); +} + Result nsGetContentManagementInterface(Service* srv_out) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -1257,6 +1264,149 @@ Result nsGetPromotionInfo(NsPromotionInfo *promotion, u64 application_id, Accoun ); } +// IDownloadTaskInterface + +Result nsClearTaskStatusList(void) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}, *srv_ptr = &srv; + Result rc=0; + if (hosversionAtLeast(3,0,0)) + rc = nsGetDownloadTaskInterface(&srv); + else + srv_ptr = &g_nsAppManSrv; + + if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(srv_ptr, 701); + + serviceClose(&srv); + return rc; +} + +Result nsRequestDownloadTaskList(void) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}, *srv_ptr = &srv; + Result rc=0; + if (hosversionAtLeast(3,0,0)) + rc = nsGetDownloadTaskInterface(&srv); + else + srv_ptr = &g_nsAppManSrv; + + if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(srv_ptr, 702); + + serviceClose(&srv); + return rc; +} + +Result nsRequestEnsureDownloadTask(AsyncResult *a) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}, *srv_ptr = &srv; + Result rc=0; + if (hosversionAtLeast(3,0,0)) + rc = nsGetDownloadTaskInterface(&srv); + else + srv_ptr = &g_nsAppManSrv; + + if (R_SUCCEEDED(rc)) rc =_nsCmdNoInOutAsyncResult(srv_ptr, a, 703); + + serviceClose(&srv); + return rc; +} + +Result nsListDownloadTaskStatus(NsDownloadTaskStatus* tasks, s32 count, s32 *total_out) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}, *srv_ptr = &srv; + Result rc=0; + if (hosversionAtLeast(3,0,0)) + rc = nsGetDownloadTaskInterface(&srv); + else + srv_ptr = &g_nsAppManSrv; + + if (R_SUCCEEDED(rc)) rc = serviceDispatchOut(srv_ptr, 704, *total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { tasks, count*sizeof(NsDownloadTaskStatus) } }, + ); + + + serviceClose(&srv); + return rc; +} + +Result nsRequestDownloadTaskListData(AsyncValue *a) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}, *srv_ptr = &srv; + Result rc=0; + if (hosversionAtLeast(3,0,0)) + rc = nsGetDownloadTaskInterface(&srv); + else + srv_ptr = &g_nsAppManSrv; + + if (R_SUCCEEDED(rc)) rc =_nsCmdNoInOutAsyncValue(srv_ptr, a, 705); + + serviceClose(&srv); + return rc; +} + +Result nsTryCommitCurrentApplicationDownloadTask(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}; + Result rc = nsGetDownloadTaskInterface(&srv); + + if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&srv, 706); + + serviceClose(&srv); + return rc; +} + +Result nsEnableAutoCommit(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}; + Result rc = nsGetDownloadTaskInterface(&srv); + + if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&srv, 707); + + serviceClose(&srv); + return rc; +} + +Result nsDisableAutoCommit(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}; + Result rc = nsGetDownloadTaskInterface(&srv); + + if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&srv, 708); + + serviceClose(&srv); + return rc; +} + +Result nsTriggerDynamicCommitEvent(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Service srv={0}; + Result rc = nsGetDownloadTaskInterface(&srv); + + if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&srv, 709); + + serviceClose(&srv); + return rc; +} + // IContentManagementInterface Result nsCalculateApplicationOccupiedSize(u64 application_id, NsApplicationOccupiedSize *out) {