diff --git a/source/main.c b/source/main.c index 2920961..da30e1c 100644 --- a/source/main.c +++ b/source/main.c @@ -22,6 +22,7 @@ #include #include #include +#include //#include "lvgl_helper.h" @@ -127,6 +128,8 @@ typedef struct size_t data_size; size_t data_written; size_t total_size; + bool read_error; + bool write_error; } ThreadSharedData; static void consolePrint(const char *text, ...) @@ -143,19 +146,30 @@ static int read_thread_func(void *arg) ThreadSharedData *shared_data = (ThreadSharedData*)arg; if (!shared_data || !shared_data->data || !shared_data->total_size) return -1; - u8 *buf = malloc(TEST_BUF_SIZE); + u8 *buf = memalign(USB_TRANSFER_ALIGNMENT, TEST_BUF_SIZE); if (!buf) return -2; for(u64 offset = 0, blksize = TEST_BUF_SIZE; offset < shared_data->total_size; offset += blksize) { if (blksize > (shared_data->total_size - offset)) blksize = (shared_data->total_size - offset); - if (!gamecardReadStorage(buf, blksize, offset)) break; + shared_data->read_error = !gamecardReadStorage(buf, blksize, offset); + if (shared_data->read_error) + { + condvarWakeAll(&g_writeCondvar); + break; + } mutexLock(&g_fileMutex); if (shared_data->data_size) condvarWait(&g_readCondvar, &g_fileMutex); + if (shared_data->write_error) + { + mutexUnlock(&g_fileMutex); + break; + } + memcpy(shared_data->data, buf, blksize); shared_data->data_size = blksize; @@ -179,13 +193,25 @@ static int write_thread_func(void *arg) if (!shared_data->data_size) condvarWait(&g_writeCondvar, &g_fileMutex); - fwrite(shared_data->data, 1, shared_data->data_size, shared_data->fileobj); + if (shared_data->read_error) + { + mutexUnlock(&g_fileMutex); + break; + } - shared_data->data_written += shared_data->data_size; - shared_data->data_size = 0; + //shared_data->write_error = (fwrite(shared_data->data, 1, shared_data->data_size, shared_data->fileobj) != shared_data->data_size); + + shared_data->write_error = !usbSendFileData(shared_data->data, shared_data->data_size); + if (!shared_data->write_error) + { + shared_data->data_written += shared_data->data_size; + shared_data->data_size = 0; + } mutexUnlock(&g_fileMutex); condvarWakeAll(&g_readCondvar); + + if (shared_data->write_error) break; } return 0; @@ -359,7 +385,7 @@ int main(int argc, char *argv[]) - if (!utilsCreateConcatenationFile("sdmc:/nxdt_test/gamecard.xci")) + /*if (!utilsCreateConcatenationFile("sdmc:/nxdt_test/gamecard.xci")) { consolePrint("create concatenationfile failed\n"); goto out2; @@ -374,18 +400,17 @@ int main(int argc, char *argv[]) goto out2; } - consolePrint("open concatenationfile success\n"); + consolePrint("open concatenationfile success\n");*/ ThreadSharedData shared_data = {0}; - shared_data.fileobj = tmp_file; + //shared_data.fileobj = tmp_file; + shared_data.fileobj = NULL; shared_data.data = buf; shared_data.data_size = 0; shared_data.data_written = 0; gamecardGetTotalSize(&(shared_data.total_size)); - - consolePrint("waiting for usb connection... "); u8 count = 0; @@ -408,14 +433,15 @@ int main(int argc, char *argv[]) consolePrint("\nusb connection detected\n"); - if (usbSendFileProperties(shared_data.total_size, "gamecard.xci")) + if (!usbSendFileProperties(shared_data.total_size, "gamecard.xci")) { - consolePrint("usb send file properties succeeded\n"); - } else { consolePrint("usb send file properties failed\n"); + goto out2; } - /*thrd_t read_thread, write_thread; + consolePrint("usb send file properties succeeded\n"); + + thrd_t read_thread, write_thread; consolePrint("creating threads\n\n"); thrd_create(&read_thread, read_thread_func, &shared_data); @@ -429,6 +455,8 @@ int main(int argc, char *argv[]) while(shared_data.data_written < shared_data.total_size) { + if (shared_data.read_error || shared_data.write_error) break; + time_t now = time(NULL); struct tm *ts = localtime(&now); size_t size = shared_data.data_written; @@ -444,14 +472,22 @@ int main(int argc, char *argv[]) consoleUpdate(NULL); } - fclose(tmp_file); - tmp_file = NULL; + //fclose(tmp_file); + //tmp_file = NULL; - consolePrint("\n\nprocess completed in %lu seconds\n", (time(NULL) - start)); + start = (time(NULL) - start); - consolePrint("waiting for threads to join\n"); + consolePrint("\n\nwaiting for threads to join\n"); thrd_join(read_thread, NULL); - thrd_join(write_thread, NULL);*/ + thrd_join(write_thread, NULL); + + if (shared_data.read_error || shared_data.write_error) + { + consolePrint("\n\nusb transfer error\n"); + goto out2; + } + + consolePrint("\n\nprocess completed in %lu seconds\n", start); diff --git a/source/usb.c b/source/usb.c index 0d223a6..ca82da0 100644 --- a/source/usb.c +++ b/source/usb.c @@ -27,8 +27,7 @@ #define USB_CMD_HEADER_MAGIC 0x4E584454 /* "NXDT" */ -#define USB_TRANSFER_ALIGNMENT 0x1000 -#define USB_TRANSFER_TIMEOUT (u64)10000000000 /* 10 seconds (in nanoseconds) */ +#define USB_TRANSFER_TIMEOUT (u64)30000000000 /* 10 seconds (in nanoseconds) */ /* Type definitions. */ @@ -187,14 +186,13 @@ bool usbPerformHandshake(void) cmd_block = (UsbCommandPerformHandshake*)(g_usbTransferBuffer + sizeof(UsbCommandHeader)); memset(cmd_block, 0, sizeof(UsbCommandPerformHandshake)); + cmd_block->app_ver_major = VERSION_MAJOR; cmd_block->app_ver_minor = VERSION_MINOR; cmd_block->app_ver_micro = VERSION_MICRO; cmd_block->abi_version = USB_ABI_VERSION; cmd_size = (sizeof(UsbCommandHeader) + sizeof(UsbCommandPerformHandshake)); - memset(g_usbTransferBuffer + cmd_size, 0, USB_TRANSFER_ALIGNMENT - cmd_size); - cmd_size = USB_TRANSFER_ALIGNMENT; status = usbSendCommand(cmd_size); if (status != UsbStatusType_Success) usbLogStatusDetail(status); @@ -230,13 +228,12 @@ bool usbSendFileProperties(u64 file_size, const char *filename) cmd_block = (UsbCommandSendFileProperties*)(g_usbTransferBuffer + sizeof(UsbCommandHeader)); memset(cmd_block, 0, sizeof(UsbCommandSendFileProperties)); + cmd_block->file_size = file_size; cmd_block->filename_length = filename_length; sprintf(cmd_block->filename, filename); cmd_size = (sizeof(UsbCommandHeader) + sizeof(UsbCommandSendFileProperties)); - memset(g_usbTransferBuffer + cmd_size, 0, USB_TRANSFER_ALIGNMENT - cmd_size); - cmd_size = USB_TRANSFER_ALIGNMENT; status = usbSendCommand(cmd_size); if (status == UsbStatusType_Success) @@ -260,7 +257,8 @@ bool usbSendFileData(void *data, u32 data_size) rwlockWriteLock(&(g_usbDeviceInterface.lock)); bool ret = false; - u32 block_size = 0; + void *buf = NULL; + UsbStatus *cmd_status = NULL; if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbTransferRemainingSize || !data || !data_size || data_size > USB_TRANSFER_BUFFER_SIZE || \ data_size > g_usbTransferRemainingSize) @@ -269,13 +267,18 @@ bool usbSendFileData(void *data, u32 data_size) goto exit; } - block_size = ALIGN_UP(data_size, USB_TRANSFER_ALIGNMENT); - memcpy(g_usbTransferBuffer, data, data_size); - if (block_size > data_size) memset(g_usbTransferBuffer + data_size, 0, block_size - data_size); - - if (!usbWrite(g_usbTransferBuffer, block_size)) + /* Optimization for buffers that already are page aligned */ + if (!((u64)data & (USB_TRANSFER_ALIGNMENT - 1))) { - LOGFILE("Failed to write 0x%lX bytes long file data chunk!", block_size); + buf = data; + } else { + buf = g_usbTransferBuffer; + memcpy(buf, data, data_size); + } + + if (!usbWrite(buf, data_size)) + { + LOGFILE("Failed to write 0x%lX bytes long file data chunk!", data_size); goto exit; } @@ -285,11 +288,9 @@ bool usbSendFileData(void *data, u32 data_size) /* Check if this is the last chunk */ if (!g_usbTransferRemainingSize) { - UsbStatus *cmd_status = NULL; - - if (!usbRead(g_usbTransferBuffer, USB_TRANSFER_ALIGNMENT)) + if (!usbRead(g_usbTransferBuffer, sizeof(UsbStatus))) { - LOGFILE("Failed to read 0x%lX bytes long status block!", USB_TRANSFER_ALIGNMENT); + LOGFILE("Failed to read 0x%lX bytes long status block!", sizeof(UsbStatus)); ret = false; goto exit; } @@ -331,7 +332,7 @@ static u32 usbSendCommand(size_t cmd_size) u32 cmd = ((UsbCommandHeader*)g_usbTransferBuffer)->cmd; UsbStatus *cmd_status = NULL; - if (!cmd_size || (cmd_size % USB_TRANSFER_ALIGNMENT) > 0 || cmd_size > USB_TRANSFER_BUFFER_SIZE) + if (cmd_size < sizeof(UsbCommandHeader) || cmd_size > USB_TRANSFER_BUFFER_SIZE) { LOGFILE("Invalid command size!"); return UsbStatusType_InvalidCommandSize; @@ -343,9 +344,9 @@ static u32 usbSendCommand(size_t cmd_size) return UsbStatusType_WriteCommandFailed; } - if (!usbRead(g_usbTransferBuffer, USB_TRANSFER_ALIGNMENT)) + if (!usbRead(g_usbTransferBuffer, sizeof(UsbStatus))) { - LOGFILE("Failed to read 0x%lX bytes long status block for type 0x%X command!", USB_TRANSFER_ALIGNMENT, cmd); + LOGFILE("Failed to read 0x%lX bytes long status block for type 0x%X command!", sizeof(UsbStatus), cmd); return UsbStatusType_ReadStatusFailed; } @@ -839,7 +840,7 @@ static bool usbWrite(void *buf, size_t size) static bool usbTransferData(void *buf, size_t size, UsbDsEndpoint *endpoint) { - if (!buf || ((u64)buf & (USB_TRANSFER_ALIGNMENT - 1)) > 0 || !size || (size % USB_TRANSFER_ALIGNMENT) > 0 || !endpoint) + if (!buf || ((u64)buf & (USB_TRANSFER_ALIGNMENT - 1)) > 0 || !size || !endpoint) { LOGFILE("Invalid parameters!"); return false; diff --git a/source/usb.h b/source/usb.h index e0c8364..a229354 100644 --- a/source/usb.h +++ b/source/usb.h @@ -21,9 +21,10 @@ #include -#define USB_TRANSFER_BUFFER_SIZE 0x800000 +#define USB_TRANSFER_ALIGNMENT 0x1000 /* 4 KiB */ +#define USB_TRANSFER_BUFFER_SIZE 0x800000 /* 8 MiB */ -/// Initializes the USB interface, input and output endpoints and allocates a USB_TRANSFER_BUFFER_SIZE sized, 0x1000 page aligned transfer buffer. +/// Initializes the USB interface, input and output endpoints and allocates an internal transfer buffer. bool usbInitialize(void); /// Closes the USB interface, input and output endpoints and frees the transfer buffer.