mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-23 02:36:41 +00:00
Additional USB changes.
This commit is contained in:
parent
97f7a46a91
commit
61fb465e2a
3 changed files with 124 additions and 79 deletions
|
@ -22,7 +22,6 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
//#include "lvgl_helper.h"
|
//#include "lvgl_helper.h"
|
||||||
|
|
||||||
|
@ -150,7 +149,7 @@ static int read_thread_func(void *arg)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *buf = memalign(USB_TRANSFER_ALIGNMENT, TEST_BUF_SIZE);
|
u8 *buf = usbAllocatePageAlignedBuffer(TEST_BUF_SIZE);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
shared_data->read_error = true;
|
shared_data->read_error = true;
|
||||||
|
@ -268,7 +267,10 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
|
|
||||||
mkdir("sdmc:/nxdt_test", 0744);
|
ThreadSharedData shared_data = {0};
|
||||||
|
thrd_t read_thread, write_thread;
|
||||||
|
|
||||||
|
//mkdir("sdmc:/nxdt_test", 0744);
|
||||||
|
|
||||||
// SSBU's Base Program NCA
|
// SSBU's Base Program NCA
|
||||||
NcmContentInfo base_program_content_info = {
|
NcmContentInfo base_program_content_info = {
|
||||||
|
@ -330,7 +332,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consolePrint("ncm open storage succeeded\n");
|
consolePrint("ncm open storage succeeded\n");
|
||||||
|
|
||||||
if (!ncaInitializeContext(base_nca_ctx, NcmStorageId_SdCard, &ncm_storage, 0, &base_program_content_info, &base_tik))
|
/*if (!ncaInitializeContext(base_nca_ctx, NcmStorageId_SdCard, &ncm_storage, 0, &base_program_content_info, &base_tik))
|
||||||
{
|
{
|
||||||
consolePrint("base nca initialize ctx failed\n");
|
consolePrint("base nca initialize ctx failed\n");
|
||||||
goto out2;
|
goto out2;
|
||||||
|
@ -390,7 +392,7 @@ int main(int argc, char *argv[])
|
||||||
goto out2;
|
goto out2;
|
||||||
}
|
}
|
||||||
|
|
||||||
consolePrint("bktr get file entry by path success: %.*s | 0x%lX\n", bktr_file_entry->name_length, bktr_file_entry->name, bktr_file_entry->size);
|
consolePrint("bktr get file entry by path success: %.*s | 0x%lX\n", bktr_file_entry->name_length, bktr_file_entry->name, bktr_file_entry->size);*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -414,7 +416,17 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consolePrint("open concatenationfile success\n");*/
|
consolePrint("open concatenationfile success\n");*/
|
||||||
|
|
||||||
ThreadSharedData shared_data = {0};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
consolePrint("waiting for gamecard to be ready...\n");
|
||||||
|
|
||||||
|
while(appletMainLoop())
|
||||||
|
{
|
||||||
|
if (gamecardIsReady()) break;
|
||||||
|
}
|
||||||
|
|
||||||
//shared_data.fileobj = tmp_file;
|
//shared_data.fileobj = tmp_file;
|
||||||
shared_data.fileobj = NULL;
|
shared_data.fileobj = NULL;
|
||||||
|
@ -425,35 +437,23 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consolePrint("waiting for usb connection... ");
|
consolePrint("waiting for usb connection... ");
|
||||||
|
|
||||||
u8 count = 0;
|
if (!usbPerformHandshake())
|
||||||
|
|
||||||
while(appletMainLoop())
|
|
||||||
{
|
{
|
||||||
/* Avoid using usbIsHostAvailable() alone inside a loop, because it can hang up the system */
|
consolePrint("failed\n");
|
||||||
consolePrint("%u ", count);
|
|
||||||
if (usbIsHostAvailable()) break;
|
|
||||||
utilsSleep(1);
|
|
||||||
count++;
|
|
||||||
if (count == 10) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 10)
|
|
||||||
{
|
|
||||||
consolePrint("\nusb connection not detected\n");
|
|
||||||
goto out2;
|
goto out2;
|
||||||
}
|
}
|
||||||
|
|
||||||
consolePrint("\nusb connection detected\n");
|
consolePrint("success\n");
|
||||||
|
|
||||||
|
consolePrint("sending file properties... ");
|
||||||
|
|
||||||
if (!usbSendFileProperties(shared_data.total_size, "gamecard.xci"))
|
if (!usbSendFileProperties(shared_data.total_size, "gamecard.xci"))
|
||||||
{
|
{
|
||||||
consolePrint("usb send file properties failed\n");
|
consolePrint("failed\n");
|
||||||
goto out2;
|
goto out2;
|
||||||
}
|
}
|
||||||
|
|
||||||
consolePrint("usb send file properties succeeded\n");
|
consolePrint("success\n");
|
||||||
|
|
||||||
thrd_t read_thread, write_thread;
|
|
||||||
|
|
||||||
consolePrint("creating threads\n\n");
|
consolePrint("creating threads\n\n");
|
||||||
thrd_create(&read_thread, read_thread_func, &shared_data);
|
thrd_create(&read_thread, read_thread_func, &shared_data);
|
||||||
|
@ -475,12 +475,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if (prev_time == ts->tm_sec || prev_size == size) continue;
|
if (prev_time == ts->tm_sec || prev_size == size) continue;
|
||||||
|
|
||||||
percent = (u8)((size * 100) / shared_data.total_size) + 1;
|
percent = (u8)((size * 100) / shared_data.total_size);
|
||||||
|
|
||||||
prev_time = ts->tm_sec;
|
prev_time = ts->tm_sec;
|
||||||
prev_size = size;
|
prev_size = size;
|
||||||
|
|
||||||
printf("%lu / %lu (%u%%) | Time elapsed: %lu\n", size, shared_data.total_size, percent, (time(NULL) - start));
|
printf("%lu / %lu (%u%%) | Time elapsed: %lu\n", size, shared_data.total_size, percent, (now - start));
|
||||||
consoleUpdate(NULL);
|
consoleUpdate(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +514,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
|
|
||||||
out2:
|
out2:
|
||||||
|
consolePrint("press any button to exit\n");
|
||||||
utilsWaitForButtonPress();
|
utilsWaitForButtonPress();
|
||||||
|
|
||||||
if (tmp_file) fclose(tmp_file);
|
if (tmp_file) fclose(tmp_file);
|
||||||
|
|
114
source/usb.c
114
source/usb.c
|
@ -19,6 +19,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -27,7 +28,8 @@
|
||||||
|
|
||||||
#define USB_CMD_HEADER_MAGIC 0x4E584454 /* "NXDT" */
|
#define USB_CMD_HEADER_MAGIC 0x4E584454 /* "NXDT" */
|
||||||
|
|
||||||
#define USB_TRANSFER_TIMEOUT (u64)30000000000 /* 10 seconds (in nanoseconds) */
|
#define USB_TRANSFER_ALIGNMENT 0x1000 /* 4 KiB */
|
||||||
|
#define USB_TRANSFER_TIMEOUT 30 /* 30 seconds */
|
||||||
|
|
||||||
/* Type definitions. */
|
/* Type definitions. */
|
||||||
|
|
||||||
|
@ -98,6 +100,8 @@ static u64 g_usbTransferRemainingSize = 0;
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
|
|
||||||
|
static bool _usbPerformHandshake(void);
|
||||||
|
|
||||||
NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size);
|
NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size);
|
||||||
static u32 usbSendCommand(size_t cmd_size);
|
static u32 usbSendCommand(size_t cmd_size);
|
||||||
NX_INLINE void usbLogStatusDetail(u32 status);
|
NX_INLINE void usbLogStatusDetail(u32 status);
|
||||||
|
@ -114,8 +118,10 @@ NX_INLINE bool usbInitializeDeviceInterface(void);
|
||||||
static bool usbInitializeDeviceInterface5x(void);
|
static bool usbInitializeDeviceInterface5x(void);
|
||||||
static bool usbInitializeDeviceInterface1x(void);
|
static bool usbInitializeDeviceInterface1x(void);
|
||||||
|
|
||||||
static bool usbRead(void *buf, size_t size);
|
NX_INLINE bool usbIsHostAvailable(void);
|
||||||
static bool usbWrite(void *buf, size_t size);
|
|
||||||
|
NX_INLINE bool usbRead(void *buf, size_t size);
|
||||||
|
NX_INLINE bool usbWrite(void *buf, size_t size);
|
||||||
static bool usbTransferData(void *buf, size_t size, UsbDsEndpoint *endpoint);
|
static bool usbTransferData(void *buf, size_t size, UsbDsEndpoint *endpoint);
|
||||||
|
|
||||||
bool usbInitialize(void)
|
bool usbInitialize(void)
|
||||||
|
@ -159,11 +165,10 @@ void usbExit(void)
|
||||||
rwlockWriteUnlock(&g_usbDeviceLock);
|
rwlockWriteUnlock(&g_usbDeviceLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usbIsHostAvailable(void)
|
void *usbAllocatePageAlignedBuffer(size_t size)
|
||||||
{
|
{
|
||||||
u32 state = 0;
|
if (!size) return NULL;
|
||||||
usbDsGetState(&state);
|
return memalign(USB_TRANSFER_ALIGNMENT, size);
|
||||||
return (state == 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usbPerformHandshake(void)
|
bool usbPerformHandshake(void)
|
||||||
|
@ -172,34 +177,23 @@ bool usbPerformHandshake(void)
|
||||||
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
UsbCommandPerformHandshake *cmd_block = NULL;
|
time_t start = time(NULL);
|
||||||
size_t cmd_size = 0;
|
time_t now = start;
|
||||||
u32 status = UsbStatusType_Success;
|
|
||||||
|
|
||||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized)
|
while((now - start) < USB_TRANSFER_TIMEOUT)
|
||||||
{
|
{
|
||||||
LOGFILE("Invalid parameters!");
|
if (usbIsHostAvailable())
|
||||||
goto exit;
|
{
|
||||||
|
/* Once the console has been connected to a host device, there's no need to keep running this loop */
|
||||||
|
/* usbTransferData() implements its own timeout */
|
||||||
|
ret = _usbPerformHandshake();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbPrepareCommandHeader(UsbCommandType_PerformHandshake, (u32)sizeof(UsbCommandPerformHandshake));
|
utilsSleep(1);
|
||||||
|
now = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
status = usbSendCommand(cmd_size);
|
|
||||||
if (status != UsbStatusType_Success) usbLogStatusDetail(status);
|
|
||||||
|
|
||||||
ret = (status == UsbStatusType_Success);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
rwlockWriteUnlock(&(g_usbDeviceInterface.lock));
|
rwlockWriteUnlock(&(g_usbDeviceInterface.lock));
|
||||||
rwlockWriteUnlock(&g_usbDeviceLock);
|
rwlockWriteUnlock(&g_usbDeviceLock);
|
||||||
|
|
||||||
|
@ -251,7 +245,7 @@ exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usbSendFileData(void *data, u32 data_size)
|
bool usbSendFileData(void *data, u64 data_size)
|
||||||
{
|
{
|
||||||
rwlockWriteLock(&g_usbDeviceLock);
|
rwlockWriteLock(&g_usbDeviceLock);
|
||||||
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
||||||
|
@ -317,6 +311,36 @@ exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _usbPerformHandshake(void)
|
||||||
|
{
|
||||||
|
UsbCommandPerformHandshake *cmd_block = NULL;
|
||||||
|
size_t cmd_size = 0;
|
||||||
|
u32 status = UsbStatusType_Success;
|
||||||
|
|
||||||
|
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized)
|
||||||
|
{
|
||||||
|
LOGFILE("Invalid parameters!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
usbPrepareCommandHeader(UsbCommandType_PerformHandshake, (u32)sizeof(UsbCommandPerformHandshake));
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
status = usbSendCommand(cmd_size);
|
||||||
|
if (status != UsbStatusType_Success) usbLogStatusDetail(status);
|
||||||
|
|
||||||
|
return (status == UsbStatusType_Success);
|
||||||
|
}
|
||||||
|
|
||||||
NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size)
|
NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size)
|
||||||
{
|
{
|
||||||
if (cmd > UsbCommandType_SendNspHeader) return;
|
if (cmd > UsbCommandType_SendNspHeader) return;
|
||||||
|
@ -518,6 +542,19 @@ static bool usbInitializeComms(void)
|
||||||
rc = usbDsSetBinaryObjectStore(bos, sizeof(bos));
|
rc = usbDsSetBinaryObjectStore(bos, sizeof(bos));
|
||||||
if (R_FAILED(rc)) LOGFILE("usbDsSetBinaryObjectStore failed! (0x%08X)", rc);
|
if (R_FAILED(rc)) LOGFILE("usbDsSetBinaryObjectStore failed! (0x%08X)", rc);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
static const UsbDsDeviceInfo device_info = {
|
||||||
|
.idVendor = 0x057e,
|
||||||
|
.idProduct = 0x3000,
|
||||||
|
.bcdDevice = 0x0100,
|
||||||
|
.Manufacturer = APP_AUTHOR,
|
||||||
|
.Product = APP_TITLE,
|
||||||
|
.SerialNumber = APP_VERSION
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set VID, PID and BCD */
|
||||||
|
rc = usbDsSetVidPidBcd(&device_info);
|
||||||
|
if (R_FAILED(rc)) LOGFILE("usbDsSetVidPidBcd failed! (0x%08X)", rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc)) goto exit;
|
if (R_FAILED(rc)) goto exit;
|
||||||
|
@ -822,7 +859,14 @@ static bool usbInitializeDeviceInterface1x(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool usbRead(void *buf, size_t size)
|
NX_INLINE bool usbIsHostAvailable(void)
|
||||||
|
{
|
||||||
|
u32 state = 0;
|
||||||
|
Result rc = usbDsGetState(&state);
|
||||||
|
return (R_SUCCEEDED(rc) && state == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
NX_INLINE bool usbRead(void *buf, u64 size)
|
||||||
{
|
{
|
||||||
rwlockWriteLock(&(g_usbDeviceInterface.lock_out));
|
rwlockWriteLock(&(g_usbDeviceInterface.lock_out));
|
||||||
bool ret = usbTransferData(buf, size, g_usbDeviceInterface.endpoint_out);
|
bool ret = usbTransferData(buf, size, g_usbDeviceInterface.endpoint_out);
|
||||||
|
@ -830,7 +874,7 @@ static bool usbRead(void *buf, size_t size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool usbWrite(void *buf, size_t size)
|
NX_INLINE bool usbWrite(void *buf, u64 size)
|
||||||
{
|
{
|
||||||
rwlockWriteLock(&(g_usbDeviceInterface.lock_in));
|
rwlockWriteLock(&(g_usbDeviceInterface.lock_in));
|
||||||
bool ret = usbTransferData(buf, size, g_usbDeviceInterface.endpoint_in);
|
bool ret = usbTransferData(buf, size, g_usbDeviceInterface.endpoint_in);
|
||||||
|
@ -838,7 +882,7 @@ static bool usbWrite(void *buf, size_t size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool usbTransferData(void *buf, size_t size, UsbDsEndpoint *endpoint)
|
static bool usbTransferData(void *buf, u64 size, UsbDsEndpoint *endpoint)
|
||||||
{
|
{
|
||||||
if (!buf || ((u64)buf & (USB_TRANSFER_ALIGNMENT - 1)) > 0 || !size || !endpoint)
|
if (!buf || ((u64)buf & (USB_TRANSFER_ALIGNMENT - 1)) > 0 || !size || !endpoint)
|
||||||
{
|
{
|
||||||
|
@ -866,7 +910,7 @@ static bool usbTransferData(void *buf, size_t size, UsbDsEndpoint *endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the transfer to finish */
|
/* Wait for the transfer to finish */
|
||||||
rc = eventWait(&(endpoint->CompletionEvent), USB_TRANSFER_TIMEOUT);
|
rc = eventWait(&(endpoint->CompletionEvent), USB_TRANSFER_TIMEOUT * (u64)1000000000);
|
||||||
eventClear(&(endpoint->CompletionEvent));
|
eventClear(&(endpoint->CompletionEvent));
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
|
|
14
source/usb.h
14
source/usb.h
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
|
||||||
#define USB_TRANSFER_ALIGNMENT 0x1000 /* 4 KiB */
|
|
||||||
#define USB_TRANSFER_BUFFER_SIZE 0x800000 /* 8 MiB */
|
#define USB_TRANSFER_BUFFER_SIZE 0x800000 /* 8 MiB */
|
||||||
|
|
||||||
/// Initializes the USB interface, input and output endpoints and allocates an internal transfer buffer.
|
/// Initializes the USB interface, input and output endpoints and allocates an internal transfer buffer.
|
||||||
|
@ -30,17 +29,18 @@ bool usbInitialize(void);
|
||||||
/// Closes the USB interface, input and output endpoints and frees the transfer buffer.
|
/// Closes the USB interface, input and output endpoints and frees the transfer buffer.
|
||||||
void usbExit(void);
|
void usbExit(void);
|
||||||
|
|
||||||
/// Checks if the console is currently connected to a host device.
|
/// Returns a pointer to a heap-allocated, page-aligned memory buffer that's suitable for USB transfers.
|
||||||
bool usbIsHostAvailable(void);
|
void *usbAllocatePageAlignedBuffer(size_t size);
|
||||||
|
|
||||||
/// Performs a handshake with the host device. Returns true if the host device replies with valid data.
|
/// Performs a handshake with the host device. Returns true if the host device replies with valid data within a certain time span.
|
||||||
|
/// This should be called before usbSendFileProperties().
|
||||||
bool usbPerformHandshake(void);
|
bool usbPerformHandshake(void);
|
||||||
|
|
||||||
/// Sends file properties to the host device before starting a file data transfer. Must be called before usbSendFileData().
|
/// Sends file properties to the host device before starting a file data transfer. Must be called before usbSendFileData(), and after usbPerformHandshake().
|
||||||
bool usbSendFileProperties(u64 file_size, const char *filename);
|
bool usbSendFileProperties(u64 file_size, const char *filename);
|
||||||
|
|
||||||
/// Performs a file data transfer. Must be called after usbSendFileProperties().
|
/// Performs a file data transfer. Must be continuously called after usbSendFileProperties() until all file data has been transferred.
|
||||||
/// Data chunk size must not exceed USB_TRANSFER_BUFFER_SIZE.
|
/// Data chunk size must not exceed USB_TRANSFER_BUFFER_SIZE.
|
||||||
bool usbSendFileData(void *data, u32 data_size);
|
bool usbSendFileData(void *data, u64 data_size);
|
||||||
|
|
||||||
#endif /* __USB_H__ */
|
#endif /* __USB_H__ */
|
||||||
|
|
Loading…
Reference in a new issue