mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
More USB changes.
* usb: copy command ID and block size before moving command data within the USB transfer buffer. * nsp_dumper_usb: now spans a background thread for the dump process, progress is now displayed, process can now be cancelled by holding B, updated to properly make use of the new usbCancelFileTransfer() behavior. * usb_gc_dumper: updated to properly make use of the new usbCancelFileTransfer() behavior. * usb_romfs_dumper: updated to properly make use of the new usbCancelFileTransfer() behavior. * Updated ns-usbloader patch. Must be used on commit `8771d551a4e6fa2d645e519d504a377e34cbd730`.
This commit is contained in:
parent
b6759f764b
commit
de076f4908
5 changed files with 515 additions and 151 deletions
|
@ -30,6 +30,15 @@
|
|||
|
||||
#define BLOCK_SIZE 0x800000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *data;
|
||||
size_t data_written;
|
||||
size_t total_size;
|
||||
bool error;
|
||||
bool transfer_cancelled;
|
||||
} ThreadSharedData;
|
||||
|
||||
static const char *dump_type_strings[] = {
|
||||
"dump base application",
|
||||
"dump update",
|
||||
|
@ -55,42 +64,30 @@ static options_t options[] = {
|
|||
|
||||
static const u32 options_count = MAX_ELEMENTS(options);
|
||||
|
||||
static Mutex g_conMutex = 0;
|
||||
|
||||
static void consolePrint(const char *text, ...)
|
||||
{
|
||||
mutexLock(&g_conMutex);
|
||||
va_list v;
|
||||
va_start(v, text);
|
||||
vfprintf(stdout, text, v);
|
||||
va_end(v);
|
||||
consoleUpdate(NULL);
|
||||
mutexUnlock(&g_conMutex);
|
||||
}
|
||||
|
||||
static void nspDump(TitleInfo *title_info)
|
||||
static void consoleRefresh(void)
|
||||
{
|
||||
if (!title_info || !title_info->content_count || !title_info->content_infos) return;
|
||||
mutexLock(&g_conMutex);
|
||||
consoleUpdate(NULL);
|
||||
mutexUnlock(&g_conMutex);
|
||||
}
|
||||
|
||||
static void dump_thread_func(void *arg)
|
||||
{
|
||||
ThreadSharedData *shared_data = (ThreadSharedData*)arg;
|
||||
|
||||
consoleClear();
|
||||
|
||||
TitleApplicationMetadata *app_metadata = title_info->app_metadata;
|
||||
|
||||
printf("%s info:\n\n", title_info->meta_key.type == NcmContentMetaType_Application ? "base application" : \
|
||||
(title_info->meta_key.type == NcmContentMetaType_Patch ? "update" : "dlc"));
|
||||
|
||||
if (app_metadata)
|
||||
{
|
||||
printf("name: %s\n", app_metadata->lang_entry.name);
|
||||
printf("publisher: %s\n", app_metadata->lang_entry.author);
|
||||
}
|
||||
|
||||
printf("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
printf("title id: %016lX\n", title_info->meta_key.id);
|
||||
printf("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
printf("content count: %u\n", title_info->content_count);
|
||||
printf("size: %s\n", title_info->size_str);
|
||||
printf("______________________________\n\n");
|
||||
printf("dump options:\n\n");
|
||||
for(u32 i = 0; i < options_count; i++) printf("%s: %s\n", options[i].str, options[i].val ? "yes" : "no");
|
||||
printf("______________________________\n\n");
|
||||
TitleInfo *title_info = NULL;
|
||||
|
||||
bool set_download_type = options[0].val;
|
||||
bool remove_console_data = options[1].val;
|
||||
|
@ -99,7 +96,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
bool patch_sua = options[4].val;
|
||||
bool patch_screenshot = options[5].val;
|
||||
bool patch_video_capture = options[6].val;
|
||||
bool success = false, usb_conn = false;
|
||||
bool success = false;
|
||||
|
||||
u8 *buf = NULL;
|
||||
char *dump_name = NULL, *path = NULL;
|
||||
|
@ -110,13 +107,13 @@ static void nspDump(TitleInfo *title_info)
|
|||
ContentMetaContext cnmt_ctx = {0};
|
||||
|
||||
ProgramInfoContext *program_info_ctx = NULL;
|
||||
u32 program_idx = 0, program_count = titleGetContentCountByType(title_info, NcmContentType_Program);
|
||||
u32 program_idx = 0, program_count = 0;
|
||||
|
||||
NacpContext *nacp_ctx = NULL;
|
||||
u32 control_idx = 0, control_count = titleGetContentCountByType(title_info, NcmContentType_Control);
|
||||
u32 control_idx = 0, control_count = 0;
|
||||
|
||||
LegalInfoContext *legal_info_ctx = NULL;
|
||||
u32 legal_info_idx = 0, legal_info_count = titleGetContentCountByType(title_info, NcmContentType_LegalInformation);
|
||||
u32 legal_info_idx = 0, legal_info_count = 0;
|
||||
|
||||
Ticket tik = {0};
|
||||
TikCommonBlock *tik_common_block = NULL;
|
||||
|
@ -134,6 +131,12 @@ static void nspDump(TitleInfo *title_info)
|
|||
Sha256Context sha256_ctx = {0};
|
||||
u8 sha256_hash[SHA256_HASH_SIZE] = {0};
|
||||
|
||||
if (!shared_data || !(title_info = (TitleInfo*)shared_data->data) || !title_info->content_count || !title_info->content_infos) goto end;
|
||||
|
||||
program_count = titleGetContentCountByType(title_info, NcmContentType_Program);
|
||||
control_count = titleGetContentCountByType(title_info, NcmContentType_Control);
|
||||
legal_info_count = titleGetContentCountByType(title_info, NcmContentType_LegalInformation);
|
||||
|
||||
/* Allocate memory for the dump process. */
|
||||
if (!(buf = usbAllocatePageAlignedBuffer(BLOCK_SIZE)))
|
||||
{
|
||||
|
@ -461,31 +464,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
nsp_size = (nsp_header_size + pfs_file_ctx.fs_size);
|
||||
consolePrint("nsp header size: 0x%lX | nsp size: 0x%lX\n", nsp_header_size, nsp_size);
|
||||
|
||||
consolePrint("waiting for usb connection... ");
|
||||
|
||||
time_t start = time(NULL);
|
||||
|
||||
while(true)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if ((now - start) >= 10) break;
|
||||
consolePrint("%lu ", now - start);
|
||||
|
||||
if ((usb_conn = usbIsReady())) break;
|
||||
utilsSleep(1);
|
||||
}
|
||||
|
||||
consolePrint("\n");
|
||||
|
||||
if (!usb_conn)
|
||||
{
|
||||
consolePrint("usb connection failed\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
consolePrint("dump process started. please wait...\n");
|
||||
|
||||
start = time(NULL);
|
||||
consolePrint("dump process started, please wait. hold b to cancel.\n");
|
||||
|
||||
if (!usbSendFileProperties(nsp_size, path, (u32)nsp_header_size))
|
||||
{
|
||||
|
@ -495,6 +474,9 @@ static void nspDump(TitleInfo *title_info)
|
|||
|
||||
nsp_offset += nsp_header_size;
|
||||
|
||||
// set nsp size
|
||||
shared_data->total_size = nsp_size;
|
||||
|
||||
// write ncas
|
||||
for(u32 i = 0; i < title_info->content_count; i++)
|
||||
{
|
||||
|
@ -519,8 +501,14 @@ static void nspDump(TitleInfo *title_info)
|
|||
goto end;
|
||||
}
|
||||
|
||||
for(u64 offset = 0; offset < cur_nca_ctx->content_size; offset += blksize, nsp_offset += blksize)
|
||||
for(u64 offset = 0; offset < cur_nca_ctx->content_size; offset += blksize, nsp_offset += blksize, shared_data->data_written += blksize)
|
||||
{
|
||||
if (shared_data->transfer_cancelled)
|
||||
{
|
||||
usbCancelFileTransfer();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((cur_nca_ctx->content_size - offset) < blksize) blksize = (cur_nca_ctx->content_size - offset);
|
||||
|
||||
// read nca chunk
|
||||
|
@ -606,6 +594,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
}
|
||||
|
||||
nsp_offset += cnmt_ctx.authoring_tool_xml_size;
|
||||
shared_data->data_written += cnmt_ctx.authoring_tool_xml_size;
|
||||
|
||||
// update cnmt xml pfs entry name
|
||||
if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, meta_nca_ctx->content_type_ctx_data_idx, meta_nca_ctx->content_id_str))
|
||||
|
@ -653,6 +642,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
}
|
||||
|
||||
nsp_offset += icon_ctx->icon_size;
|
||||
shared_data->data_written += icon_ctx->icon_size;
|
||||
|
||||
// update pfs entry name
|
||||
if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, data_idx++, cur_nca_ctx->content_id_str))
|
||||
|
@ -684,6 +674,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
}
|
||||
|
||||
nsp_offset += authoring_tool_xml_size;
|
||||
shared_data->data_written += authoring_tool_xml_size;
|
||||
|
||||
// update pfs entry name
|
||||
if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, data_idx, cur_nca_ctx->content_id_str))
|
||||
|
@ -704,6 +695,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
}
|
||||
|
||||
nsp_offset += tik.size;
|
||||
shared_data->data_written += tik.size;
|
||||
|
||||
// write cert
|
||||
tmp_name = pfsGetEntryNameByIndexFromFileContext(&pfs_file_ctx, pfs_file_ctx.header.entry_count - 1);
|
||||
|
@ -714,6 +706,7 @@ static void nspDump(TitleInfo *title_info)
|
|||
}
|
||||
|
||||
nsp_offset += raw_cert_chain_size;
|
||||
shared_data->data_written += raw_cert_chain_size;
|
||||
}
|
||||
|
||||
// write new pfs0 header
|
||||
|
@ -729,13 +722,14 @@ static void nspDump(TitleInfo *title_info)
|
|||
goto end;
|
||||
}
|
||||
|
||||
start = (time(NULL) - start);
|
||||
consolePrint("process successfully completed in %lu seconds!\n", start);
|
||||
shared_data->data_written += nsp_header_size;
|
||||
|
||||
success = true;
|
||||
|
||||
end:
|
||||
if (usb_conn && !success) usbCancelFileTransfer();
|
||||
consoleRefresh();
|
||||
|
||||
if (!success && !shared_data->transfer_cancelled) shared_data->error = true;
|
||||
|
||||
pfsFreeFileContext(&pfs_file_ctx);
|
||||
|
||||
|
@ -768,6 +762,146 @@ end:
|
|||
if (dump_name) free(dump_name);
|
||||
|
||||
if (buf) free(buf);
|
||||
|
||||
threadExit();
|
||||
}
|
||||
|
||||
static void nspDump(TitleInfo *title_info)
|
||||
{
|
||||
if (!title_info) return;
|
||||
|
||||
TitleApplicationMetadata *app_metadata = title_info->app_metadata;
|
||||
|
||||
ThreadSharedData shared_data = {0};
|
||||
Thread dump_thread = {0};
|
||||
|
||||
time_t start = 0, btn_cancel_start_tmr = 0, btn_cancel_end_tmr = 0;
|
||||
bool usb_conn = false, btn_cancel_cur_state = false, btn_cancel_prev_state = false;
|
||||
|
||||
u64 prev_size = 0;
|
||||
u8 prev_time = 0, percent = 0;
|
||||
|
||||
consoleClear();
|
||||
|
||||
consolePrint("%s info:\n\n", title_info->meta_key.type == NcmContentMetaType_Application ? "base application" : \
|
||||
(title_info->meta_key.type == NcmContentMetaType_Patch ? "update" : "dlc"));
|
||||
|
||||
if (app_metadata)
|
||||
{
|
||||
consolePrint("name: %s\n", app_metadata->lang_entry.name);
|
||||
consolePrint("publisher: %s\n", app_metadata->lang_entry.author);
|
||||
}
|
||||
|
||||
consolePrint("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
consolePrint("title id: %016lX\n", title_info->meta_key.id);
|
||||
consolePrint("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
consolePrint("content count: %u\n", title_info->content_count);
|
||||
consolePrint("size: %s\n", title_info->size_str);
|
||||
consolePrint("______________________________\n\n");
|
||||
consolePrint("dump options:\n\n");
|
||||
for(u32 i = 0; i < options_count; i++) consolePrint("%s: %s\n", options[i].str, options[i].val ? "yes" : "no");
|
||||
consolePrint("______________________________\n\n");
|
||||
|
||||
// make sure we have a valid usb session
|
||||
consolePrint("waiting for usb connection... ");
|
||||
|
||||
start = time(NULL);
|
||||
|
||||
while(true)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if ((now - start) >= 10) break;
|
||||
|
||||
consolePrint("%lu ", now - start);
|
||||
consoleRefresh();
|
||||
|
||||
if ((usb_conn = usbIsReady())) break;
|
||||
utilsSleep(1);
|
||||
}
|
||||
|
||||
consolePrint("\n");
|
||||
|
||||
if (!usb_conn)
|
||||
{
|
||||
consolePrint("usb connection failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// create dump thread
|
||||
shared_data.data = title_info;
|
||||
utilsCreateThread(&dump_thread, dump_thread_func, &shared_data, 2);
|
||||
|
||||
while(!shared_data.total_size && !shared_data.error) svcSleepThread(10000000); // 10 ms
|
||||
|
||||
if (shared_data.error)
|
||||
{
|
||||
utilsJoinThread(&dump_thread);
|
||||
return;
|
||||
}
|
||||
|
||||
// start dump
|
||||
start = time(NULL);
|
||||
|
||||
while(shared_data.data_written < shared_data.total_size)
|
||||
{
|
||||
if (shared_data.error) break;
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm *ts = localtime(&now);
|
||||
size_t size = shared_data.data_written;
|
||||
|
||||
utilsScanPads();
|
||||
btn_cancel_cur_state = (utilsGetButtonsHeld() & HidNpadButton_B);
|
||||
|
||||
if (btn_cancel_cur_state && btn_cancel_cur_state != btn_cancel_prev_state)
|
||||
{
|
||||
btn_cancel_start_tmr = now;
|
||||
} else
|
||||
if (btn_cancel_cur_state && btn_cancel_cur_state == btn_cancel_prev_state)
|
||||
{
|
||||
btn_cancel_end_tmr = now;
|
||||
if ((btn_cancel_end_tmr - btn_cancel_start_tmr) >= 3)
|
||||
{
|
||||
shared_data.transfer_cancelled = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
btn_cancel_start_tmr = btn_cancel_end_tmr = 0;
|
||||
}
|
||||
|
||||
btn_cancel_prev_state = btn_cancel_cur_state;
|
||||
|
||||
if (prev_time == ts->tm_sec || prev_size == size) continue;
|
||||
|
||||
percent = (u8)((size * 100) / shared_data.total_size);
|
||||
|
||||
prev_time = ts->tm_sec;
|
||||
prev_size = size;
|
||||
|
||||
consolePrint("%lu / %lu (%u%%) | Time elapsed: %lu\n", size, shared_data.total_size, percent, (now - start));
|
||||
consoleRefresh();
|
||||
}
|
||||
|
||||
start = (time(NULL) - start);
|
||||
|
||||
consolePrint("\nwaiting for thread to join\n");
|
||||
utilsJoinThread(&dump_thread);
|
||||
consolePrint("dump_thread done: %lu\n", time(NULL));
|
||||
|
||||
if (shared_data.error)
|
||||
{
|
||||
consolePrint("usb transfer error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (shared_data.transfer_cancelled)
|
||||
{
|
||||
consolePrint("process cancelled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
consolePrint("process completed in %lu seconds\n", start);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -780,6 +914,7 @@ int main(int argc, char *argv[])
|
|||
consoleInit(NULL);
|
||||
|
||||
consolePrint("initializing...\n");
|
||||
consoleRefresh();
|
||||
|
||||
if (!utilsInitializeResources())
|
||||
{
|
||||
|
@ -806,6 +941,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
consolePrint("app metadata succeeded\n");
|
||||
consoleRefresh();
|
||||
|
||||
utilsSleep(1);
|
||||
|
||||
|
@ -813,72 +949,72 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
consoleClear();
|
||||
|
||||
printf("press b to %s.\n", menu == 0 ? "exit" : "go back");
|
||||
printf("______________________________\n\n");
|
||||
consolePrint("press b to %s.\n", menu == 0 ? "exit" : "go back");
|
||||
consolePrint("______________________________\n\n");
|
||||
|
||||
if (menu == 0)
|
||||
{
|
||||
printf("title: %u / %u\n", selected_idx + 1, app_count);
|
||||
printf("selected title: %016lX - %s\n", app_metadata[selected_idx]->title_id, app_metadata[selected_idx]->lang_entry.name);
|
||||
consolePrint("title: %u / %u\n", selected_idx + 1, app_count);
|
||||
consolePrint("selected title: %016lX - %s\n", app_metadata[selected_idx]->title_id, app_metadata[selected_idx]->lang_entry.name);
|
||||
} else {
|
||||
printf("title info:\n\n");
|
||||
printf("name: %s\n", app_metadata[title_idx]->lang_entry.name);
|
||||
printf("publisher: %s\n", app_metadata[title_idx]->lang_entry.author);
|
||||
printf("title id: %016lX\n", app_metadata[title_idx]->title_id);
|
||||
consolePrint("title info:\n\n");
|
||||
consolePrint("name: %s\n", app_metadata[title_idx]->lang_entry.name);
|
||||
consolePrint("publisher: %s\n", app_metadata[title_idx]->lang_entry.author);
|
||||
consolePrint("title id: %016lX\n", app_metadata[title_idx]->title_id);
|
||||
|
||||
if (menu == 2)
|
||||
{
|
||||
printf("______________________________\n\n");
|
||||
consolePrint("______________________________\n\n");
|
||||
|
||||
if (title_info->previous || title_info->next)
|
||||
{
|
||||
printf("press zl/l and/or zr/r to change the selected title\n");
|
||||
printf("title: %u / %u\n", list_idx, list_count);
|
||||
printf("______________________________\n\n");
|
||||
consolePrint("press zl/l and/or zr/r to change the selected title\n");
|
||||
consolePrint("title: %u / %u\n", list_idx, list_count);
|
||||
consolePrint("______________________________\n\n");
|
||||
}
|
||||
|
||||
printf("selected %s info:\n\n", title_info->meta_key.type == NcmContentMetaType_Application ? "base application" : \
|
||||
consolePrint("selected %s info:\n\n", title_info->meta_key.type == NcmContentMetaType_Application ? "base application" : \
|
||||
(title_info->meta_key.type == NcmContentMetaType_Patch ? "update" : "dlc"));
|
||||
printf("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
if (title_info->meta_key.type != NcmContentMetaType_Application) printf("title id: %016lX\n", title_info->meta_key.id);
|
||||
printf("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
consolePrint("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
if (title_info->meta_key.type != NcmContentMetaType_Application) consolePrint("title id: %016lX\n", title_info->meta_key.id);
|
||||
consolePrint("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
printf("content count: %u\n", title_info->content_count);
|
||||
printf("size: %s\n", title_info->size_str);
|
||||
consolePrint("content count: %u\n", title_info->content_count);
|
||||
consolePrint("size: %s\n", title_info->size_str);
|
||||
}
|
||||
}
|
||||
|
||||
printf("______________________________\n\n");
|
||||
consolePrint("______________________________\n\n");
|
||||
|
||||
u32 max_val = (menu == 0 ? app_count : (menu == 1 ? dump_type_strings_count : (1 + options_count)));
|
||||
for(u32 i = scroll; i < max_val; i++)
|
||||
{
|
||||
if (i >= (scroll + page_size)) break;
|
||||
|
||||
printf("%s", i == selected_idx ? " -> " : " ");
|
||||
consolePrint("%s", i == selected_idx ? " -> " : " ");
|
||||
|
||||
if (menu == 0)
|
||||
{
|
||||
printf("%016lX - %s\n", app_metadata[i]->title_id, app_metadata[i]->lang_entry.name);
|
||||
consolePrint("%016lX - %s\n", app_metadata[i]->title_id, app_metadata[i]->lang_entry.name);
|
||||
} else
|
||||
if (menu == 1)
|
||||
{
|
||||
printf("%s\n", dump_type_strings[i]);
|
||||
consolePrint("%s\n", dump_type_strings[i]);
|
||||
} else
|
||||
if (menu == 2)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
printf("start nsp dump\n");
|
||||
consolePrint("start nsp dump\n");
|
||||
} else {
|
||||
printf("%s: < %s >\n", options[i - 1].str, options[i - 1].val ? "yes" : "no");
|
||||
consolePrint("%s: < %s >\n", options[i - 1].str, options[i - 1].val ? "yes" : "no");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
consolePrint("\n");
|
||||
|
||||
consoleUpdate(NULL);
|
||||
consoleRefresh();
|
||||
|
||||
bool gc_update = false;
|
||||
u64 btn_down = 0, btn_held = 0;
|
||||
|
@ -960,7 +1096,6 @@ int main(int argc, char *argv[])
|
|||
} else
|
||||
if (menu == 3)
|
||||
{
|
||||
consoleClear();
|
||||
utilsChangeHomeButtonBlockStatus(true);
|
||||
nspDump(title_info);
|
||||
utilsChangeHomeButtonBlockStatus(false);
|
||||
|
@ -969,6 +1104,7 @@ int main(int argc, char *argv[])
|
|||
if (error || menu >= 3)
|
||||
{
|
||||
consolePrint("press any button to continue\n");
|
||||
consoleRefresh();
|
||||
utilsWaitForButtonPress(0);
|
||||
menu--;
|
||||
} else {
|
||||
|
@ -1043,6 +1179,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
out2:
|
||||
consoleRefresh();
|
||||
|
||||
if (menu != UINT32_MAX)
|
||||
{
|
||||
consolePrint("press any button to exit\n");
|
||||
|
|
|
@ -563,7 +563,6 @@ static bool sendGameCardImageViaUsb(void)
|
|||
if ((btn_cancel_end_tmr - btn_cancel_start_tmr) >= 3)
|
||||
{
|
||||
mutexLock(&g_fileMutex);
|
||||
usbCancelFileTransfer();
|
||||
shared_data.transfer_cancelled = true;
|
||||
mutexUnlock(&g_fileMutex);
|
||||
break;
|
||||
|
@ -738,6 +737,7 @@ static void write_thread_func(void *arg)
|
|||
|
||||
if (shared_data->read_error || shared_data->transfer_cancelled)
|
||||
{
|
||||
if (shared_data->transfer_cancelled) usbCancelFileTransfer();
|
||||
mutexUnlock(&g_fileMutex);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -181,6 +181,7 @@ static void write_thread_func(void *arg)
|
|||
|
||||
if (shared_data->read_error || shared_data->transfer_cancelled)
|
||||
{
|
||||
if (shared_data->transfer_cancelled) usbCancelFileTransfer();
|
||||
mutexUnlock(&g_fileMutex);
|
||||
break;
|
||||
}
|
||||
|
@ -585,7 +586,6 @@ int main(int argc, char *argv[])
|
|||
if ((btn_cancel_end_tmr - btn_cancel_start_tmr) >= 3)
|
||||
{
|
||||
mutexLock(&g_fileMutex);
|
||||
usbCancelFileTransfer();
|
||||
shared_data.transfer_cancelled = true;
|
||||
mutexUnlock(&g_fileMutex);
|
||||
break;
|
||||
|
|
|
@ -1,33 +1,38 @@
|
|||
diff --git a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java
|
||||
index dd2a1bc..58add89 100644
|
||||
index dd2a1bc..6c8f79e 100644
|
||||
--- a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java
|
||||
+++ b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java
|
||||
@@ -42,7 +42,7 @@ class NxdtUsbAbi1 {
|
||||
@@ -42,7 +42,6 @@ class NxdtUsbAbi1 {
|
||||
private final boolean isWindows;
|
||||
private boolean isWindows10;
|
||||
|
||||
- private static final int NXDT_MAX_DIRECTIVE_SIZE = 0x1000;
|
||||
+ private static final int NXDT_MAX_DIRECTIVE_SIZE = 0x800000;
|
||||
private static final int NXDT_FILE_CHUNK_SIZE = 0x800000;
|
||||
private static final int NXDT_FILE_PROPERTIES_MAX_NAME_LENGTH = 0x300;
|
||||
|
||||
@@ -51,6 +51,7 @@ class NxdtUsbAbi1 {
|
||||
@@ -51,7 +50,9 @@ class NxdtUsbAbi1 {
|
||||
|
||||
private static final int CMD_HANDSHAKE = 0;
|
||||
private static final int CMD_SEND_FILE_PROPERTIES = 1;
|
||||
+ private static final int CMD_SEND_NSP_HEADER = 2;
|
||||
private static final int CMD_ENDSESSION = 3;
|
||||
- private static final int CMD_ENDSESSION = 3;
|
||||
+ private static final int CMD_CANCEL_FILE_TRANSFER = 2;
|
||||
+ private static final int CMD_SEND_NSP_HEADER = 3;
|
||||
+ private static final int CMD_ENDSESSION = 4;
|
||||
|
||||
// Standard set of possible replies
|
||||
@@ -79,9 +80,15 @@ class NxdtUsbAbi1 {
|
||||
private static final byte[] USBSTATUS_SUCCESS = { 0x4e, 0x58, 0x44, 0x54,
|
||||
@@ -79,9 +80,17 @@ class NxdtUsbAbi1 {
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
- private short endpointMaxPacketSize;
|
||||
+ private short endpointMaxPacketSize = 0;
|
||||
|
||||
private static final int NXDT_USB_TIMEOUT = 5000;
|
||||
+
|
||||
- private static final int NXDT_USB_TIMEOUT = 5000;
|
||||
+ private static final int NXDT_USB_CMD_TIMEOUT = 1000;
|
||||
+ private static final int NXDT_USB_DATA_TIMEOUT = 5000;
|
||||
+ private static final int USB_BUF_ALIGNMENT = 0x1000;
|
||||
+
|
||||
+ private boolean nspTransferMode = false;
|
||||
+ private long nspSize = 0;
|
||||
+ private int nspHeaderSize = 0;
|
||||
|
@ -36,17 +41,28 @@ index dd2a1bc..58add89 100644
|
|||
|
||||
public NxdtUsbAbi1(DeviceHandle handler,
|
||||
ILogPrinter logPrinter,
|
||||
@@ -111,6 +118,9 @@ class NxdtUsbAbi1 {
|
||||
@@ -111,6 +120,9 @@ class NxdtUsbAbi1 {
|
||||
DeviceInformation deviceInformation = DeviceInformation.build(handlerNS);
|
||||
NsUsbEndpointDescriptor endpointInDescriptor = deviceInformation.getSimplifiedDefaultEndpointDescriptorIn();
|
||||
this.endpointMaxPacketSize = endpointInDescriptor.getwMaxPacketSize();
|
||||
+
|
||||
+ USBSTATUS_SUCCESS[8] = (byte)(endpointMaxPacketSize & 0xFF);
|
||||
+ USBSTATUS_SUCCESS[9] = (byte)((endpointMaxPacketSize >> 8) & 0xFF);
|
||||
+ USBSTATUS_SUCCESS[8] = (byte)(this.endpointMaxPacketSize & 0xFF);
|
||||
+ USBSTATUS_SUCCESS[9] = (byte)((this.endpointMaxPacketSize >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
private void readLoop(){
|
||||
@@ -134,6 +144,9 @@ class NxdtUsbAbi1 {
|
||||
@@ -121,9 +133,7 @@ class NxdtUsbAbi1 {
|
||||
|
||||
while (true){
|
||||
directive = readUsbDirective();
|
||||
-
|
||||
- if (isInvalidDirective(directive))
|
||||
- continue;
|
||||
+ if (directive == null || directive.length == 0) continue;
|
||||
|
||||
command = getLEint(directive, 4);
|
||||
|
||||
@@ -134,7 +144,11 @@ class NxdtUsbAbi1 {
|
||||
case CMD_SEND_FILE_PROPERTIES:
|
||||
handleSendFileProperties(directive);
|
||||
break;
|
||||
|
@ -54,9 +70,40 @@ index dd2a1bc..58add89 100644
|
|||
+ handleSendNspHeader(directive);
|
||||
+ break;
|
||||
case CMD_ENDSESSION:
|
||||
+ writeUsb(USBSTATUS_SUCCESS);
|
||||
logPrinter.print("Session successfully ended.", EMsgType.PASS);
|
||||
return;
|
||||
@@ -187,30 +200,52 @@ class NxdtUsbAbi1 {
|
||||
default:
|
||||
@@ -153,28 +167,6 @@ class NxdtUsbAbi1 {
|
||||
}
|
||||
}
|
||||
|
||||
- private boolean isInvalidDirective(byte[] message) throws Exception{
|
||||
- if (message.length < 0x10){
|
||||
- writeUsb(USBSTATUS_MALFORMED_REQUEST);
|
||||
- logPrinter.print("Directive is too small. Only "+message.length+" bytes received.", EMsgType.FAIL);
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- if (! Arrays.equals(Arrays.copyOfRange(message, 0,4), MAGIC_NXDT)){
|
||||
- writeUsb(USBSTATUS_INVALID_MAGIC);
|
||||
- logPrinter.print("Invalid 'MAGIC'", EMsgType.FAIL);
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- int payloadSize = getLEint(message, 0x8);
|
||||
- if (payloadSize + 0x10 != message.length){
|
||||
- writeUsb(USBSTATUS_MALFORMED_REQUEST);
|
||||
- logPrinter.print("Invalid directive info block size. "+message.length+" bytes received while "+payloadSize+" expected.", EMsgType.FAIL);
|
||||
- return true;
|
||||
- }
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
private void performHandshake(byte[] message) throws Exception{
|
||||
final byte versionMajor = message[0x10];
|
||||
final byte versionMinor = message[0x11];
|
||||
@@ -187,30 +179,52 @@ class NxdtUsbAbi1 {
|
||||
writeUsb(USBSTATUS_UNSUPPORTED_ABI);
|
||||
throw new Exception("ABI v"+versionABI+" is not supported in current version.");
|
||||
}
|
||||
|
@ -120,7 +167,7 @@ index dd2a1bc..58add89 100644
|
|||
// If RomFs related
|
||||
if (isRomFs(filename)) {
|
||||
if (isWindows)
|
||||
@@ -225,24 +260,48 @@ class NxdtUsbAbi1 {
|
||||
@@ -225,30 +239,105 @@ class NxdtUsbAbi1 {
|
||||
filename = saveToPath + filename;
|
||||
}
|
||||
|
||||
|
@ -131,12 +178,6 @@ index dd2a1bc..58add89 100644
|
|||
- logPrinter.print("Not enough space on selected volume. Need: "+fileSize+
|
||||
- " while available: "+fileToDump.getParentFile().getFreeSpace(), EMsgType.FAIL);
|
||||
- return;
|
||||
- }
|
||||
- // Check if FS is NOT read-only
|
||||
- if (! (fileToDump.canWrite() || fileToDump.createNewFile()) ){
|
||||
- writeUsb(USBSTATUS_HOSTIOERROR);
|
||||
- logPrinter.print("Unable to write into selected volume: "+fileToDump.getAbsolutePath(), EMsgType.FAIL);
|
||||
- return;
|
||||
+ File fileToDump;
|
||||
+
|
||||
+ if (!this.nspTransferMode || (this.nspTransferMode && this.nspFile == null)) {
|
||||
|
@ -175,18 +216,31 @@ index dd2a1bc..58add89 100644
|
|||
+ } else {
|
||||
+ fileToDump = this.nspFile;
|
||||
}
|
||||
|
||||
writeUsb(USBSTATUS_SUCCESS);
|
||||
|
||||
- if (fileSize == 0)
|
||||
- // Check if FS is NOT read-only
|
||||
- if (! (fileToDump.canWrite() || fileToDump.createNewFile()) ){
|
||||
- writeUsb(USBSTATUS_HOSTIOERROR);
|
||||
- logPrinter.print("Unable to write into selected volume: "+fileToDump.getAbsolutePath(), EMsgType.FAIL);
|
||||
+
|
||||
+ writeUsb(USBSTATUS_SUCCESS);
|
||||
+
|
||||
+ if (fileSize == 0 || (this.nspTransferMode && fileSize == this.nspSize))
|
||||
return;
|
||||
+
|
||||
+ if (dumpFile(fileToDump, fileSize)){
|
||||
+ writeUsb(USBSTATUS_SUCCESS);
|
||||
+ } else {
|
||||
+ fileToDump.delete();
|
||||
}
|
||||
|
||||
dumpFile(fileToDump, fileSize);
|
||||
@@ -251,6 +310,49 @@ class NxdtUsbAbi1 {
|
||||
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ private void handleCancelFileTransfer() throws Exception{
|
||||
+ resetNspInfo();
|
||||
writeUsb(USBSTATUS_SUCCESS);
|
||||
+ logPrinter.print("User cancelled ongoing file transfer.", EMsgType.FAIL);
|
||||
+ }
|
||||
|
||||
- if (fileSize == 0)
|
||||
+ private void handleSendNspHeader(byte[] message) throws Exception{
|
||||
+ final int headerSize = getLEint(message, 0x8);
|
||||
+
|
||||
|
@ -194,9 +248,10 @@ index dd2a1bc..58add89 100644
|
|||
+ writeUsb(USBSTATUS_MALFORMED_REQUEST);
|
||||
+ logPrinter.print("Received NSP send header request outside of NSP transfer mode!", EMsgType.FAIL);
|
||||
+ resetNspInfo();
|
||||
+ return;
|
||||
return;
|
||||
+ }
|
||||
+
|
||||
|
||||
- dumpFile(fileToDump, fileSize);
|
||||
+ if (this.nspRemainingSize > 0) {
|
||||
+ writeUsb(USBSTATUS_MALFORMED_REQUEST);
|
||||
+ logPrinter.print("Received NSP send header request without receiving all NSP file entry data!", EMsgType.FAIL);
|
||||
|
@ -218,54 +273,225 @@ index dd2a1bc..58add89 100644
|
|||
+ }
|
||||
+
|
||||
+ resetNspInfo();
|
||||
+
|
||||
+ writeUsb(USBSTATUS_SUCCESS);
|
||||
|
||||
writeUsb(USBSTATUS_SUCCESS);
|
||||
+ }
|
||||
+
|
||||
|
||||
+ private void resetNspInfo(){
|
||||
+ this.nspTransferMode = false;
|
||||
+ this.nspSize = 0;
|
||||
+ this.nspHeaderSize = 0;
|
||||
+ this.nspRemainingSize = 0;
|
||||
+ this.nspFile = null;
|
||||
+ }
|
||||
+
|
||||
private int getLEint(byte[] bytes, int fromOffset){
|
||||
return ByteBuffer.wrap(bytes, fromOffset, 0x4).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
}
|
||||
@@ -279,7 +381,7 @@ class NxdtUsbAbi1 {
|
||||
|
||||
// @see https://bugs.openjdk.java.net/browse/JDK-8146538
|
||||
private void dumpFile(File file, long size) throws Exception{
|
||||
- FileOutputStream fos = new FileOutputStream(file, true);
|
||||
+ FileOutputStream fos = new FileOutputStream(file, this.nspTransferMode);
|
||||
private int getLEint(byte[] bytes, int fromOffset){
|
||||
@@ -277,9 +366,9 @@ class NxdtUsbAbi1 {
|
||||
throw new Exception("Unable to create dir(s) for file in "+folderForTheFile);
|
||||
}
|
||||
|
||||
- // @see https://bugs.openjdk.java.net/browse/JDK-8146538
|
||||
- private void dumpFile(File file, long size) throws Exception{
|
||||
+ private boolean dumpFile(File file, long size) throws Exception{
|
||||
FileOutputStream fos = new FileOutputStream(file, true);
|
||||
+ boolean success = true;
|
||||
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(fos)) {
|
||||
FileDescriptor fd = fos.getFD();
|
||||
@@ -296,15 +398,21 @@ class NxdtUsbAbi1 {
|
||||
@@ -287,31 +376,44 @@ class NxdtUsbAbi1 {
|
||||
long received = 0;
|
||||
int bufferSize;
|
||||
|
||||
- while (received+NXDT_FILE_CHUNK_SIZE < size) {
|
||||
- //readBuffer = readUsbFile();
|
||||
- readBuffer = readUsbFileDebug(NXDT_FILE_CHUNK_SIZE);
|
||||
+ while((received + NXDT_FILE_CHUNK_SIZE) < size) {
|
||||
+ readBuffer = readUsb(NXDT_FILE_CHUNK_SIZE, NXDT_USB_DATA_TIMEOUT);
|
||||
bos.write(readBuffer);
|
||||
if (isWindows10)
|
||||
fd.sync();
|
||||
bufferSize = readBuffer.length;
|
||||
received += bufferSize;
|
||||
|
||||
- logPrinter.updateProgress((double)received / (double)size);
|
||||
+ if (bufferSize == 0x10 && Arrays.equals(Arrays.copyOfRange(readBuffer, 0, 4), MAGIC_NXDT)) {
|
||||
+ int cmd = getLEint(readBuffer, 4);
|
||||
+ if (cmd == CMD_CANCEL_FILE_TRANSFER){
|
||||
+ handleCancelFileTransfer();
|
||||
+ success = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!this.nspTransferMode) {
|
||||
+ logPrinter.updateProgress((double)received / (double)size);
|
||||
+ } else {
|
||||
+ this.nspRemainingSize -= bufferSize;
|
||||
+ logPrinter.updateProgress((double)(this.nspSize - this.nspRemainingSize) / (double)this.nspSize);
|
||||
+ }
|
||||
+ }
|
||||
+ if (success){
|
||||
+ int lastChunkSize = (int)((size - received) + 1);
|
||||
+ readBuffer = readUsb(lastChunkSize, NXDT_USB_DATA_TIMEOUT);
|
||||
+ bos.write(readBuffer);
|
||||
+ if (isWindows10)
|
||||
+ fd.sync();
|
||||
+ this.nspRemainingSize -= lastChunkSize;
|
||||
}
|
||||
int lastChunkSize = (int)(size - received) + 1;
|
||||
readBuffer = readUsbFileDebug(lastChunkSize);
|
||||
bos.write(readBuffer);
|
||||
if (isWindows10)
|
||||
fd.sync();
|
||||
+ if (this.nspTransferMode) this.nspRemainingSize -= (lastChunkSize - 1);
|
||||
- int lastChunkSize = (int)(size - received) + 1;
|
||||
- readBuffer = readUsbFileDebug(lastChunkSize);
|
||||
- bos.write(readBuffer);
|
||||
- if (isWindows10)
|
||||
- fd.sync();
|
||||
} finally {
|
||||
- logPrinter.updateProgress(1.0);
|
||||
+ if (!this.nspTransferMode || (this.nspTransferMode && this.nspRemainingSize == 0)) logPrinter.updateProgress(1.0);
|
||||
+ if (success && (!this.nspTransferMode || (this.nspTransferMode && this.nspRemainingSize == 0))) logPrinter.updateProgress(1.0);
|
||||
}
|
||||
+
|
||||
+ return success;
|
||||
}
|
||||
/* Handle Zero-length terminator
|
||||
- /* Handle Zero-length terminator
|
||||
- private boolean isAligned(long size){
|
||||
- return ((size & (endpointMaxPacketSize - 1)) == 0);
|
||||
- }
|
||||
- */
|
||||
|
||||
/** Sending any byte array to USB device **/
|
||||
private void writeUsb(byte[] message) throws Exception{
|
||||
@@ -322,7 +424,7 @@ class NxdtUsbAbi1 {
|
||||
if ( parent.isCancelled() )
|
||||
throw new InterruptedException("Execution interrupted");
|
||||
|
||||
- int result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, NXDT_USB_TIMEOUT);
|
||||
+ int result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, NXDT_USB_CMD_TIMEOUT);
|
||||
|
||||
if (result == LibUsb.SUCCESS) {
|
||||
if (writeBufTransferred.get() == message.length)
|
||||
@@ -335,47 +437,61 @@ class NxdtUsbAbi1 {
|
||||
"\n Returned: " + UsbErrorCodes.getErrCode(result) +
|
||||
"\n (execution stopped)");
|
||||
}
|
||||
+
|
||||
/**
|
||||
- * Reading what USB device responded (command).
|
||||
+ * Reads an USB directive.
|
||||
* @return byte array if data read successful
|
||||
* 'null' if read failed
|
||||
* */
|
||||
private byte[] readUsbDirective() throws Exception{
|
||||
- ByteBuffer readBuffer = ByteBuffer.allocateDirect(NXDT_MAX_DIRECTIVE_SIZE);
|
||||
- // We can limit it to 32 bytes, but there is a non-zero chance to got OVERFLOW from libusb.
|
||||
- IntBuffer readBufTransferred = IntBuffer.allocate(1);
|
||||
- int result;
|
||||
- while (! parent.isCancelled()) {
|
||||
- result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81
|
||||
+ byte[] cmd_header = null, payload = null, directive = null;
|
||||
+ int payloadSize = 0;
|
||||
|
||||
- switch (result) {
|
||||
- case LibUsb.SUCCESS:
|
||||
- int trans = readBufTransferred.get();
|
||||
- byte[] receivedBytes = new byte[trans];
|
||||
- readBuffer.get(receivedBytes);
|
||||
- return receivedBytes;
|
||||
- case LibUsb.ERROR_TIMEOUT:
|
||||
- break;
|
||||
- default:
|
||||
- throw new Exception("Data transfer issue [read command]" +
|
||||
- "\n Returned: " + UsbErrorCodes.getErrCode(result)+
|
||||
- "\n (execution stopped)");
|
||||
+ cmd_header = readUsb(0x10, NXDT_USB_CMD_TIMEOUT);
|
||||
+ if (cmd_header == null || cmd_header.length == 0) return null;
|
||||
+
|
||||
+ if (cmd_header.length != 0x10){
|
||||
+ writeUsb(USBSTATUS_MALFORMED_REQUEST);
|
||||
+ logPrinter.print("Command header is too small. Only "+cmd_header.length+" bytes received.", EMsgType.FAIL);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ if (! Arrays.equals(Arrays.copyOfRange(cmd_header, 0, 4), MAGIC_NXDT)){
|
||||
+ writeUsb(USBSTATUS_INVALID_MAGIC);
|
||||
+ logPrinter.print("Invalid 'MAGIC'", EMsgType.FAIL);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ payloadSize = getLEint(cmd_header, 8);
|
||||
+ if (payloadSize > 0){
|
||||
+ payload = readUsb(payloadSize + 1, NXDT_USB_CMD_TIMEOUT);
|
||||
+ if (payload == null || payload.length != payloadSize){
|
||||
+ writeUsb(USBSTATUS_MALFORMED_REQUEST);
|
||||
+ logPrinter.print("Command payload size mismatch. Received "+payload.length+" bytes.", EMsgType.FAIL);
|
||||
+ return null;
|
||||
}
|
||||
}
|
||||
- throw new InterruptedException();
|
||||
+
|
||||
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
+ outputStream.write(cmd_header);
|
||||
+ if (payloadSize > 0) outputStream.write(payload);
|
||||
+ directive = outputStream.toByteArray();
|
||||
+
|
||||
+ return directive;
|
||||
}
|
||||
+
|
||||
/**
|
||||
- * Reading what USB device responded (file).
|
||||
+ * Reading what USB device responded (command).
|
||||
* @return byte array if data read successful
|
||||
* 'null' if read failed
|
||||
* */
|
||||
- private byte[] readUsbFile() throws Exception{
|
||||
- ByteBuffer readBuffer = ByteBuffer.allocateDirect(NXDT_FILE_CHUNK_SIZE);
|
||||
+ private byte[] readUsb(int length, int timeout) throws Exception{
|
||||
+ ByteBuffer readBuffer = ByteBuffer.allocateDirect(alignUp(length, USB_BUF_ALIGNMENT));
|
||||
IntBuffer readBufTransferred = IntBuffer.allocate(1);
|
||||
int result;
|
||||
- int countDown = 0;
|
||||
- while (! parent.isCancelled() && countDown < 5) {
|
||||
- result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000);
|
||||
+
|
||||
+ while (! parent.isCancelled()) {
|
||||
+ result = LibUsb.bulkTransfer(handlerNS, (byte)0x81, readBuffer, readBufTransferred, timeout); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81
|
||||
|
||||
switch (result) {
|
||||
case LibUsb.SUCCESS:
|
||||
@@ -384,33 +500,17 @@ class NxdtUsbAbi1 {
|
||||
readBuffer.get(receivedBytes);
|
||||
return receivedBytes;
|
||||
case LibUsb.ERROR_TIMEOUT:
|
||||
- countDown++;
|
||||
break;
|
||||
default:
|
||||
- throw new Exception("Data transfer issue [read file]" +
|
||||
+ throw new Exception("Data transfer issue [read]" +
|
||||
"\n Returned: " + UsbErrorCodes.getErrCode(result)+
|
||||
"\n (execution stopped)");
|
||||
}
|
||||
}
|
||||
throw new InterruptedException();
|
||||
}
|
||||
-
|
||||
- private byte[] readUsbFileDebug(int chunkSize) throws Exception {
|
||||
- ByteBuffer readBuffer = ByteBuffer.allocateDirect(chunkSize);
|
||||
- IntBuffer readBufTransferred = IntBuffer.allocate(1);
|
||||
- if (parent.isCancelled())
|
||||
- throw new InterruptedException();
|
||||
-
|
||||
- int result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, NXDT_USB_TIMEOUT);
|
||||
|
||||
- if (result == LibUsb.SUCCESS) {
|
||||
- int trans = readBufTransferred.get();
|
||||
- byte[] receivedBytes = new byte[trans];
|
||||
- readBuffer.get(receivedBytes);
|
||||
- return receivedBytes;
|
||||
- }
|
||||
- throw new Exception("Data transfer issue [read file]" +
|
||||
- "\n Returned: " + UsbErrorCodes.getErrCode(result) +
|
||||
- "\n (execution stopped)");
|
||||
+ private int alignUp(int value, int alignment){
|
||||
+ return ((value + (alignment - 1)) & ~(alignment - 1));
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/resources/NSLMain.fxml b/src/main/resources/NSLMain.fxml
|
||||
index a2d42d6..9114c3d 100644
|
||||
--- a/src/main/resources/NSLMain.fxml
|
||||
|
|
22
source/usb.c
22
source/usb.c
|
@ -657,7 +657,7 @@ NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size)
|
|||
static bool usbSendCommand(void)
|
||||
{
|
||||
UsbCommandHeader *cmd_header = (UsbCommandHeader*)g_usbTransferBuffer;
|
||||
size_t cmd_size = (sizeof(UsbCommandHeader) + cmd_header->cmd_block_size);
|
||||
u32 cmd = cmd_header->cmd, cmd_block_size = cmd_header->cmd_block_size;
|
||||
|
||||
UsbStatus *cmd_status = (UsbStatus*)g_usbTransferBuffer;
|
||||
u32 status = UsbStatusType_Success;
|
||||
|
@ -665,7 +665,7 @@ static bool usbSendCommand(void)
|
|||
/* Log error message only if the USB session has been started, or if thread exit flag hasn't been enabled. */
|
||||
bool ret = false, zlt_required = false, cmd_block_written = false, log_rw_errors = (g_usbSessionStarted || !g_usbDetectionThreadExitFlag);
|
||||
|
||||
if (cmd_size > USB_TRANSFER_BUFFER_SIZE)
|
||||
if ((sizeof(UsbCommandHeader) + cmd_block_size) > USB_TRANSFER_BUFFER_SIZE)
|
||||
{
|
||||
LOGFILE("Invalid command size!");
|
||||
status = UsbStatusType_InvalidCommandSize;
|
||||
|
@ -675,26 +675,26 @@ static bool usbSendCommand(void)
|
|||
/* Write command header first. */
|
||||
if (!usbWrite(cmd_header, sizeof(UsbCommandHeader)))
|
||||
{
|
||||
if (log_rw_errors) LOGFILE("Failed to write header for type 0x%X command!", cmd_header->cmd);
|
||||
if (log_rw_errors) LOGFILE("Failed to write header for type 0x%X command!", cmd);
|
||||
status = UsbStatusType_WriteCommandFailed;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check if we need to transfer a command block. */
|
||||
if (cmd_header->cmd_block_size)
|
||||
if (cmd_block_size)
|
||||
{
|
||||
/* Move command block data within the transfer buffer to guarantee we'll work with proper alignment. */
|
||||
memmove(g_usbTransferBuffer, g_usbTransferBuffer + sizeof(UsbCommandHeader), cmd_block_size);
|
||||
|
||||
/* Determine if we'll need to set a Zero Length Termination (ZLT) packet after sending the command block. */
|
||||
zlt_required = (g_usbSessionStarted && IS_ALIGNED(cmd_header->cmd_block_size, g_usbEndpointMaxPacketSize));
|
||||
zlt_required = IS_ALIGNED(cmd_block_size, g_usbEndpointMaxPacketSize);
|
||||
if (zlt_required) usbSetZltPacket(true);
|
||||
|
||||
/* Move command block data within the transfer buffer to guarantee we'll work with proper alignment. */
|
||||
memmove(g_usbTransferBuffer, g_usbTransferBuffer + sizeof(UsbCommandHeader), cmd_header->cmd_block_size);
|
||||
|
||||
/* Write command block. */
|
||||
cmd_block_written = usbWrite(g_usbTransferBuffer, cmd_header->cmd_block_size);
|
||||
cmd_block_written = usbWrite(g_usbTransferBuffer, cmd_block_size);
|
||||
if (!cmd_block_written)
|
||||
{
|
||||
if (log_rw_errors) LOGFILE("Failed to write command block for type 0x%X command!", cmd_header->cmd);
|
||||
if (log_rw_errors) LOGFILE("Failed to write command block for type 0x%X command!", cmd);
|
||||
status = UsbStatusType_WriteCommandFailed;
|
||||
}
|
||||
|
||||
|
@ -708,7 +708,7 @@ static bool usbSendCommand(void)
|
|||
/* Read status block. */
|
||||
if (!usbRead(cmd_status, sizeof(UsbStatus)))
|
||||
{
|
||||
if (log_rw_errors) LOGFILE("Failed to read 0x%lX bytes long status block for type 0x%X command!", sizeof(UsbStatus), cmd_header->cmd);
|
||||
if (log_rw_errors) LOGFILE("Failed to read 0x%lX bytes long status block for type 0x%X command!", sizeof(UsbStatus), cmd);
|
||||
status = UsbStatusType_ReadStatusFailed;
|
||||
goto end;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue