From ea2c7025568883aecfaec00bbd97cd0c6aeba0b1 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Mon, 30 May 2016 17:16:34 -0700 Subject: [PATCH] Properly pause CDN installation on suspension to home menu. --- source/ui/section/action/deletecontents.c | 11 +++ .../ui/section/action/deletependingtitles.c | 11 +++ source/ui/section/action/installcdn.c | 34 ++++++++ source/ui/section/action/installcias.c | 24 ++++++ source/ui/section/action/installtickets.c | 22 +++++ source/ui/section/action/pastefiles.c | 22 +++++ source/ui/section/dumpnand.c | 22 +++++ source/ui/section/networkinstall.c | 24 ++++++ source/ui/section/qrinstall.c | 24 ++++++ source/ui/section/task/dataop.c | 80 ++++++++++++------- source/ui/section/task/task.c | 21 +++++ source/ui/section/task/task.h | 8 ++ source/ui/section/update.c | 22 +++++ 13 files changed, 297 insertions(+), 28 deletions(-) diff --git a/source/ui/section/action/deletecontents.c b/source/ui/section/action/deletecontents.c index a267421..1593d80 100644 --- a/source/ui/section/action/deletecontents.c +++ b/source/ui/section/action/deletecontents.c @@ -80,6 +80,14 @@ static Result action_delete_contents_delete(void* data, u32 index) { return res; } +static Result action_delete_contents_suspend(void* data, u32 index) { + return 0; +} + +static Result action_delete_contents_restore(void* data, u32 index) { + return 0; +} + static bool action_delete_contents_error(void* data, u32 index, Result res) { delete_contents_data* deleteData = (delete_contents_data*) data; @@ -164,6 +172,9 @@ static void action_delete_contents_internal(linked_list* items, list_item* selec data->deleteInfo.delete = action_delete_contents_delete; + data->deleteInfo.suspend = action_delete_contents_suspend; + data->deleteInfo.restore = action_delete_contents_restore; + data->deleteInfo.error = action_delete_contents_error; data->deleteInfo.finished = false; diff --git a/source/ui/section/action/deletependingtitles.c b/source/ui/section/action/deletependingtitles.c index bf7805c..43db2c5 100644 --- a/source/ui/section/action/deletependingtitles.c +++ b/source/ui/section/action/deletependingtitles.c @@ -57,6 +57,14 @@ static Result action_delete_pending_titles_delete(void* data, u32 index) { return res; } +static Result action_delete_pending_titles_suspend(void* data, u32 index) { + return 0; +} + +static Result action_delete_pending_titles_restore(void* data, u32 index) { + return 0; +} + static bool action_delete_pending_titles_error(void* data, u32 index, Result res) { delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; @@ -139,6 +147,9 @@ void action_delete_pending_titles(linked_list* items, list_item* selected, const data->deleteInfo.delete = action_delete_pending_titles_delete; + data->deleteInfo.suspend = action_delete_pending_titles_suspend; + data->deleteInfo.restore = action_delete_pending_titles_restore; + data->deleteInfo.error = action_delete_pending_titles_error; data->deleteInfo.finished = true; diff --git a/source/ui/section/action/installcdn.c b/source/ui/section/action/installcdn.c index c5ec75e..83e74f6 100644 --- a/source/ui/section/action/installcdn.c +++ b/source/ui/section/action/installcdn.c @@ -151,6 +151,34 @@ static Result action_install_cdn_write_dst(void* data, u32 handle, u32* bytesWri return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result action_install_cdn_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + if(index > 0 && *dstHandle != 0) { + return AM_InstallContentStop(*dstHandle); + } else { + return 0; + } +} + +static Result action_install_cdn_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + install_cdn_data* installData = (install_cdn_data*) data; + + if(index > 0 && *dstHandle != 0) { + return AM_InstallContentResume(dstHandle, &installData->installInfo.currProcessed, installData->contentIndices[index - 1]); + } else { + return 0; + } +} + +static Result action_install_cdn_suspend(void* data, u32 index) { + return AM_InstallTitleStop(); +} + +static Result action_install_cdn_restore(void* data, u32 index) { + install_cdn_data* installData = (install_cdn_data*) data; + + return AM_InstallTitleResume(((installData->ticket->titleId >> 32) & 0x8010) != 0 ? MEDIATYPE_NAND : MEDIATYPE_SD, installData->ticket->titleId); +} + bool action_install_cdn_error(void* data, u32 index, Result res) { install_cdn_data* installData = (install_cdn_data*) data; @@ -256,6 +284,12 @@ void action_install_cdn_noprompt(volatile bool* done, ticket_info* info, bool fi data->installInfo.closeDst = action_install_cdn_close_dst; data->installInfo.writeDst = action_install_cdn_write_dst; + data->installInfo.suspendCopy = action_install_cdn_suspend_copy; + data->installInfo.restoreCopy = action_install_cdn_restore_copy; + + data->installInfo.suspend = action_install_cdn_suspend; + data->installInfo.restore = action_install_cdn_restore; + data->installInfo.error = action_install_cdn_error; data->installInfo.finished = true; diff --git a/source/ui/section/action/installcias.c b/source/ui/section/action/installcias.c index e53b5f6..20f76a3 100644 --- a/source/ui/section/action/installcias.c +++ b/source/ui/section/action/installcias.c @@ -159,6 +159,8 @@ static Result action_install_cias_close_dst(void* data, u32 index, bool succeede } } + installData->currTitleId = 0; + return res; } else { return AM_CancelCIAInstall(handle); @@ -169,6 +171,22 @@ static Result action_install_cias_write_dst(void* data, u32 handle, u32* bytesWr return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result action_install_cias_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result action_install_cias_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result action_install_cias_suspend(void* data, u32 index) { + return 0; +} + +static Result action_install_cias_restore(void* data, u32 index) { + return 0; +} + bool action_install_cias_error(void* data, u32 index, Result res) { install_cias_data* installData = (install_cias_data*) data; @@ -271,6 +289,12 @@ static void action_install_cias_internal(linked_list* items, list_item* selected data->installInfo.closeDst = action_install_cias_close_dst; data->installInfo.writeDst = action_install_cias_write_dst; + data->installInfo.suspendCopy = action_install_cias_suspend_copy; + data->installInfo.restoreCopy = action_install_cias_restore_copy; + + data->installInfo.suspend = action_install_cias_suspend; + data->installInfo.restore = action_install_cias_restore; + data->installInfo.error = action_install_cias_error; data->installInfo.finished = true; diff --git a/source/ui/section/action/installtickets.c b/source/ui/section/action/installtickets.c index 4f60cef..b5ddf14 100644 --- a/source/ui/section/action/installtickets.c +++ b/source/ui/section/action/installtickets.c @@ -144,6 +144,22 @@ static Result action_install_tickets_write_dst(void* data, u32 handle, u32* byte return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result action_install_tickets_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result action_install_tickets_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result action_install_tickets_suspend(void* data, u32 index) { + return 0; +} + +static Result action_install_tickets_restore(void* data, u32 index) { + return 0; +} + static bool action_install_tickets_error(void* data, u32 index, Result res) { install_tickets_data* installData = (install_tickets_data*) data; @@ -250,6 +266,12 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec data->installInfo.closeDst = action_install_tickets_close_dst; data->installInfo.writeDst = action_install_tickets_write_dst; + data->installInfo.suspendCopy = action_install_tickets_suspend_copy; + data->installInfo.restoreCopy = action_install_tickets_restore_copy; + + data->installInfo.suspend = action_install_tickets_suspend; + data->installInfo.restore = action_install_tickets_restore; + data->installInfo.error = action_install_tickets_error; data->installInfo.finished = true; diff --git a/source/ui/section/action/pastefiles.c b/source/ui/section/action/pastefiles.c index 83a1b88..6f6a7e7 100644 --- a/source/ui/section/action/pastefiles.c +++ b/source/ui/section/action/pastefiles.c @@ -175,6 +175,22 @@ static Result action_paste_files_write_dst(void* data, u32 handle, u32* bytesWri return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result action_paste_files_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result action_paste_files_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result action_paste_files_suspend(void* data, u32 index) { + return 0; +} + +static Result action_paste_files_restore(void* data, u32 index) { + return 0; +} + static bool action_paste_files_error(void* data, u32 index, Result res) { paste_files_data* pasteData = (paste_files_data*) data; @@ -293,6 +309,12 @@ void action_paste_contents(linked_list* items, list_item* selected) { data->pasteInfo.closeDst = action_paste_files_close_dst; data->pasteInfo.writeDst = action_paste_files_write_dst; + data->pasteInfo.suspendCopy = action_paste_files_suspend_copy; + data->pasteInfo.restoreCopy = action_paste_files_restore_copy; + + data->pasteInfo.suspend = action_paste_files_suspend; + data->pasteInfo.restore = action_paste_files_restore; + data->pasteInfo.error = action_paste_files_error; data->pasteInfo.finished = true; diff --git a/source/ui/section/dumpnand.c b/source/ui/section/dumpnand.c index c7adea8..d99b6d3 100644 --- a/source/ui/section/dumpnand.c +++ b/source/ui/section/dumpnand.c @@ -48,6 +48,22 @@ static Result dumpnand_write_dst(void* data, u32 handle, u32* bytesWritten, void return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result dumpnand_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result dumpnand_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result dumpnand_suspend(void* data, u32 index) { + return 0; +} + +static Result dumpnand_restore(void* data, u32 index) { + return 0; +} + static bool dumpnand_error(void* data, u32 index, Result res) { if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Dump cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); @@ -125,6 +141,12 @@ void dumpnand_open() { data->closeDst = dumpnand_close_dst; data->writeDst = dumpnand_write_dst; + data->suspendCopy = dumpnand_suspend_copy; + data->restoreCopy = dumpnand_restore_copy; + + data->suspend = dumpnand_suspend; + data->restore = dumpnand_restore; + data->error = dumpnand_error; data->finished = true; diff --git a/source/ui/section/networkinstall.c b/source/ui/section/networkinstall.c index 6874d34..5598760 100644 --- a/source/ui/section/networkinstall.c +++ b/source/ui/section/networkinstall.c @@ -170,6 +170,8 @@ static Result networkinstall_close_dst(void* data, u32 index, bool succeeded, u3 } } + networkInstallData->currTitleId = 0; + return res; } else { if(networkInstallData->ticket) { @@ -184,6 +186,22 @@ static Result networkinstall_write_dst(void* data, u32 handle, u32* bytesWritten return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result networkinstall_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result networkinstall_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result networkinstall_suspend(void* data, u32 index) { + return 0; +} + +static Result networkinstall_restore(void* data, u32 index) { + return 0; +} + static bool networkinstall_error(void* data, u32 index, Result res) { if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); @@ -344,6 +362,12 @@ void networkinstall_open() { data->installInfo.closeDst = networkinstall_close_dst; data->installInfo.writeDst = networkinstall_write_dst; + data->installInfo.suspendCopy = networkinstall_suspend_copy; + data->installInfo.restoreCopy = networkinstall_restore_copy; + + data->installInfo.suspend = networkinstall_suspend; + data->installInfo.restore = networkinstall_restore; + data->installInfo.error = networkinstall_error; data->installInfo.finished = true; diff --git a/source/ui/section/qrinstall.c b/source/ui/section/qrinstall.c index 4fb574e..6eb8b4f 100644 --- a/source/ui/section/qrinstall.c +++ b/source/ui/section/qrinstall.c @@ -170,6 +170,8 @@ static Result qrinstall_close_dst(void* data, u32 index, bool succeeded, u32 han } } + qrInstallData->currTitleId = 0; + return res; } else { if(qrInstallData->ticket) { @@ -184,6 +186,22 @@ static Result qrinstall_write_dst(void* data, u32 handle, u32* bytesWritten, voi return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result qrinstall_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result qrinstall_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result qrinstall_suspend(void* data, u32 index) { + return 0; +} + +static Result qrinstall_restore(void* data, u32 index) { + return 0; +} + static bool qrinstall_error(void* data, u32 index, Result res) { qr_install_data* qrInstallData = (qr_install_data*) data; @@ -429,6 +447,12 @@ void qrinstall_open() { data->installInfo.closeDst = qrinstall_close_dst; data->installInfo.writeDst = qrinstall_write_dst; + data->installInfo.suspendCopy = qrinstall_suspend_copy; + data->installInfo.restoreCopy = qrinstall_restore_copy; + + data->installInfo.suspend = qrinstall_suspend; + data->installInfo.restore = qrinstall_restore; + data->installInfo.error = qrinstall_error; data->installInfo.finished = true; diff --git a/source/ui/section/task/dataop.c b/source/ui/section/task/dataop.c index 9566a51..81c8f92 100644 --- a/source/ui/section/task/dataop.c +++ b/source/ui/section/task/dataop.c @@ -7,7 +7,40 @@ #include "../../list.h" #include "../../error.h" -static bool task_data_op_copy(data_op_data* data, u32 index) { +static Result task_data_op_check_running(data_op_data* data, u32 index, u32* srcHandle, u32* dstHandle) { + Result res = 0; + + if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { + res = R_FBI_CANCELLED; + } else { + bool suspended = svcWaitSynchronization(task_get_suspend_event(), 0) != 0; + if(suspended) { + if(data->op == DATAOP_COPY && srcHandle != NULL && dstHandle != NULL && data->suspendCopy != NULL && R_SUCCEEDED(res)) { + res = data->suspendCopy(data->data, index, srcHandle, dstHandle); + } + + if(data->suspend != NULL && R_SUCCEEDED(res)) { + res = data->suspend(data->data, index); + } + } + + svcWaitSynchronization(task_get_pause_event(), U64_MAX); + + if(suspended) { + if(data->restore != NULL && R_SUCCEEDED(res)) { + res = data->restore(data->data, index); + } + + if(data->op == DATAOP_COPY && srcHandle != NULL && dstHandle != NULL && data->restoreCopy != NULL && R_SUCCEEDED(res)) { + res = data->restoreCopy(data->data, index, srcHandle, dstHandle); + } + } + } + + return res; +} + +static Result task_data_op_copy(data_op_data* data, u32 index) { data->currProcessed = 0; data->currTotal = 0; @@ -35,9 +68,7 @@ static bool task_data_op_copy(data_op_data* data, u32 index) { bool firstRun = true; while(data->currProcessed < data->currTotal) { - svcWaitSynchronization(task_get_pause_event(), U64_MAX); - if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { - res = R_FBI_CANCELLED; + if(R_FAILED(res = task_data_op_check_running(data, data->processed, &srcHandle, &dstHandle))) { break; } @@ -88,41 +119,34 @@ static bool task_data_op_copy(data_op_data* data, u32 index) { } } - if(R_FAILED(res)) { - data->result = res; - return data->error(data->data, index, res); - } - - return true; + return res; } -static bool task_data_op_delete(data_op_data* data, u32 index) { - Result res = 0; - if(R_FAILED(res = data->delete(data->data, index))) { - return data->error(data->data, index, res); - } - - return true; +static Result task_data_op_delete(data_op_data* data, u32 index) { + return data->delete(data->data, index); } static void task_data_op_thread(void* arg) { data_op_data* data = (data_op_data*) arg; for(data->processed = 0; data->processed < data->total; data->processed++) { - bool cont = false; + Result res = 0; - switch(data->op) { - case DATAOP_COPY: - cont = task_data_op_copy(data, data->processed); - break; - case DATAOP_DELETE: - cont = task_data_op_delete(data, data->processed); - break; - default: - break; + if(R_SUCCEEDED(res = task_data_op_check_running(data, data->processed, NULL, NULL))) { + switch(data->op) { + case DATAOP_COPY: + res = task_data_op_copy(data, data->processed); + break; + case DATAOP_DELETE: + res = task_data_op_delete(data, data->processed); + break; + default: + break; + } } - if(!cont) { + if(R_FAILED(res) && !data->error(data->data, data->processed, res)) { + data->result = res; break; } } diff --git a/source/ui/section/task/task.c b/source/ui/section/task/task.c index 1671e34..42d7543 100644 --- a/source/ui/section/task/task.c +++ b/source/ui/section/task/task.c @@ -6,16 +6,19 @@ static bool task_quit; static Handle task_pause_event; +static Handle task_suspend_event; static aptHookCookie cookie; static void task_apt_hook(APT_HookType hook, void* param) { switch(hook) { case APTHOOK_ONRESTORE: + svcSignalEvent(task_suspend_event); case APTHOOK_ONWAKEUP: svcSignalEvent(task_pause_event); break; case APTHOOK_ONSUSPEND: + svcClearEvent(task_suspend_event); case APTHOOK_ONSLEEP: svcClearEvent(task_pause_event); break; @@ -28,12 +31,21 @@ void task_init() { task_quit = false; Result res = 0; + if(R_FAILED(res = svcCreateEvent(&task_pause_event, 1))) { util_panic("Failed to create task awake event: 0x%08lX", res); return; } + if(R_FAILED(res = svcCreateEvent(&task_suspend_event, 1))) { + svcCloseHandle(task_pause_event); + + util_panic("Failed to create task awake event: 0x%08lX", res); + return; + } + svcSignalEvent(task_pause_event); + svcSignalEvent(task_suspend_event); aptHook(&cookie, task_apt_hook, NULL); } @@ -47,6 +59,11 @@ void task_exit() { svcCloseHandle(task_pause_event); task_pause_event = 0; } + + if(task_suspend_event != 0) { + svcCloseHandle(task_suspend_event); + task_suspend_event = 0; + } } bool task_is_quit_all() { @@ -55,4 +72,8 @@ bool task_is_quit_all() { Handle task_get_pause_event() { return task_pause_event; +} + +Handle task_get_suspend_event() { + return task_suspend_event; } \ No newline at end of file diff --git a/source/ui/section/task/task.h b/source/ui/section/task/task.h index d06da45..3c6c624 100644 --- a/source/ui/section/task/task.h +++ b/source/ui/section/task/task.h @@ -115,9 +115,16 @@ typedef struct data_op_info_s { Result (*writeDst)(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size); + Result (*suspendCopy)(void* data, u32 index, u32* srcHandle, u32* dstHandle); + Result (*restoreCopy)(void* data, u32 index, u32* srcHandle, u32* dstHandle); + // Delete Result (*delete)(void* data, u32 index); + // Suspend + Result (*suspend)(void* data, u32 index); + Result (*restore)(void* data, u32 index); + // Errors bool (*error)(void* data, u32 index, Result res); @@ -193,6 +200,7 @@ void task_init(); void task_exit(); bool task_is_quit_all(); Handle task_get_pause_event(); +Handle task_get_suspend_event(); Result task_capture_cam(capture_cam_data* data); diff --git a/source/ui/section/update.c b/source/ui/section/update.c index 7baaf76..040d3a8 100644 --- a/source/ui/section/update.c +++ b/source/ui/section/update.c @@ -121,6 +121,22 @@ static Result update_write_dst(void* data, u32 handle, u32* bytesWritten, void* return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } +static Result update_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result update_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) { + return 0; +} + +static Result update_suspend(void* data, u32 index) { + return 0; +} + +static Result update_restore(void* data, u32 index) { + return 0; +} + static bool update_error(void* data, u32 index, Result res) { update_data* updateData = (update_data*) data; @@ -314,6 +330,12 @@ void update_open() { data->installInfo.closeDst = update_close_dst; data->installInfo.writeDst = update_write_dst; + data->installInfo.suspendCopy = update_suspend_copy; + data->installInfo.restoreCopy = update_restore_copy; + + data->installInfo.suspend = update_suspend; + data->installInfo.restore = update_restore; + data->installInfo.error = update_error; data->installInfo.finished = true;