1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-12-23 17:06:02 +00:00

Additional USB changes.

This commit is contained in:
Pablo Curiel 2020-05-07 07:08:54 -04:00
parent 97f7a46a91
commit 61fb465e2a
3 changed files with 124 additions and 79 deletions

View file

@ -22,7 +22,6 @@
#include <dirent.h>
#include <threads.h>
#include <stdarg.h>
#include <malloc.h>
//#include "lvgl_helper.h"
@ -150,7 +149,7 @@ static int read_thread_func(void *arg)
return -1;
}
u8 *buf = memalign(USB_TRANSFER_ALIGNMENT, TEST_BUF_SIZE);
u8 *buf = usbAllocatePageAlignedBuffer(TEST_BUF_SIZE);
if (!buf)
{
shared_data->read_error = true;
@ -268,7 +267,10 @@ int main(int argc, char *argv[])
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
NcmContentInfo base_program_content_info = {
@ -330,7 +332,7 @@ int main(int argc, char *argv[])
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");
goto out2;
@ -390,7 +392,7 @@ int main(int argc, char *argv[])
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");*/
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 = NULL;
@ -425,36 +437,24 @@ int main(int argc, char *argv[])
consolePrint("waiting for usb connection... ");
u8 count = 0;
while(appletMainLoop())
if (!usbPerformHandshake())
{
/* Avoid using usbIsHostAvailable() alone inside a loop, because it can hang up the system */
consolePrint("%u ", count);
if (usbIsHostAvailable()) break;
utilsSleep(1);
count++;
if (count == 10) break;
}
if (count == 10)
{
consolePrint("\nusb connection not detected\n");
consolePrint("failed\n");
goto out2;
}
consolePrint("\nusb connection detected\n");
consolePrint("success\n");
consolePrint("sending file properties... ");
if (!usbSendFileProperties(shared_data.total_size, "gamecard.xci"))
{
consolePrint("usb send file properties failed\n");
consolePrint("failed\n");
goto out2;
}
consolePrint("usb send file properties succeeded\n");
consolePrint("success\n");
thrd_t read_thread, write_thread;
consolePrint("creating threads\n\n");
thrd_create(&read_thread, read_thread_func, &shared_data);
thrd_create(&write_thread, write_thread_func, &shared_data);
@ -475,12 +475,12 @@ int main(int argc, char *argv[])
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_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);
}
@ -514,6 +514,7 @@ int main(int argc, char *argv[])
out2:
consolePrint("press any button to exit\n");
utilsWaitForButtonPress();
if (tmp_file) fclose(tmp_file);

View file

@ -19,6 +19,7 @@
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include "usb.h"
#include "utils.h"
@ -27,7 +28,8 @@
#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. */
@ -68,17 +70,17 @@ typedef struct {
} UsbCommandSendFileProperties;
typedef enum {
UsbStatusType_Success = 0,
UsbStatusType_Success = 0,
UsbStatusType_InvalidCommandSize = 1,
UsbStatusType_WriteCommandFailed = 2,
UsbStatusType_ReadStatusFailed = 3,
UsbStatusType_InvalidMagicWord = 4,
UsbStatusType_InvalidCommandSize = 1,
UsbStatusType_WriteCommandFailed = 2,
UsbStatusType_ReadStatusFailed = 3,
UsbStatusType_InvalidMagicWord = 4,
UsbStatusType_MalformedCommand = 5,
UsbStatusType_UnsupportedAbiVersion = 6,
UsbStatusType_UnsupportedCommand = 7,
UsbStatusType_HostIoError = 8
UsbStatusType_MalformedCommand = 5,
UsbStatusType_UnsupportedAbiVersion = 6,
UsbStatusType_UnsupportedCommand = 7,
UsbStatusType_HostIoError = 8
} UsbStatusType;
typedef struct {
@ -98,6 +100,8 @@ static u64 g_usbTransferRemainingSize = 0;
/* Function prototypes. */
static bool _usbPerformHandshake(void);
NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size);
static u32 usbSendCommand(size_t cmd_size);
NX_INLINE void usbLogStatusDetail(u32 status);
@ -114,8 +118,10 @@ NX_INLINE bool usbInitializeDeviceInterface(void);
static bool usbInitializeDeviceInterface5x(void);
static bool usbInitializeDeviceInterface1x(void);
static bool usbRead(void *buf, size_t size);
static bool usbWrite(void *buf, size_t size);
NX_INLINE bool usbIsHostAvailable(void);
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);
bool usbInitialize(void)
@ -159,11 +165,10 @@ void usbExit(void)
rwlockWriteUnlock(&g_usbDeviceLock);
}
bool usbIsHostAvailable(void)
void *usbAllocatePageAlignedBuffer(size_t size)
{
u32 state = 0;
usbDsGetState(&state);
return (state == 5);
if (!size) return NULL;
return memalign(USB_TRANSFER_ALIGNMENT, size);
}
bool usbPerformHandshake(void)
@ -172,34 +177,23 @@ bool usbPerformHandshake(void)
rwlockWriteLock(&(g_usbDeviceInterface.lock));
bool ret = false;
UsbCommandPerformHandshake *cmd_block = NULL;
size_t cmd_size = 0;
u32 status = UsbStatusType_Success;
time_t start = time(NULL);
time_t now = start;
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized)
while((now - start) < USB_TRANSFER_TIMEOUT)
{
LOGFILE("Invalid parameters!");
goto exit;
if (usbIsHostAvailable())
{
/* 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;
}
utilsSleep(1);
now = time(NULL);
}
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);
ret = (status == UsbStatusType_Success);
exit:
rwlockWriteUnlock(&(g_usbDeviceInterface.lock));
rwlockWriteUnlock(&g_usbDeviceLock);
@ -251,7 +245,7 @@ exit:
return ret;
}
bool usbSendFileData(void *data, u32 data_size)
bool usbSendFileData(void *data, u64 data_size)
{
rwlockWriteLock(&g_usbDeviceLock);
rwlockWriteLock(&(g_usbDeviceInterface.lock));
@ -317,6 +311,36 @@ exit:
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)
{
if (cmd > UsbCommandType_SendNspHeader) return;
@ -518,6 +542,19 @@ static bool usbInitializeComms(void)
rc = usbDsSetBinaryObjectStore(bos, sizeof(bos));
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;
@ -822,7 +859,14 @@ static bool usbInitializeDeviceInterface1x(void)
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));
bool ret = usbTransferData(buf, size, g_usbDeviceInterface.endpoint_out);
@ -830,7 +874,7 @@ static bool usbRead(void *buf, size_t size)
return ret;
}
static bool usbWrite(void *buf, size_t size)
NX_INLINE bool usbWrite(void *buf, u64 size)
{
rwlockWriteLock(&(g_usbDeviceInterface.lock_in));
bool ret = usbTransferData(buf, size, g_usbDeviceInterface.endpoint_in);
@ -838,7 +882,7 @@ static bool usbWrite(void *buf, size_t size)
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)
{
@ -866,7 +910,7 @@ static bool usbTransferData(void *buf, size_t size, UsbDsEndpoint *endpoint)
}
/* 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));
if (R_FAILED(rc))

View file

@ -21,7 +21,6 @@
#include <switch.h>
#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 an internal transfer buffer.
@ -30,17 +29,18 @@ bool usbInitialize(void);
/// Closes the USB interface, input and output endpoints and frees the transfer buffer.
void usbExit(void);
/// Checks if the console is currently connected to a host device.
bool usbIsHostAvailable(void);
/// Returns a pointer to a heap-allocated, page-aligned memory buffer that's suitable for USB transfers.
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);
/// 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);
/// 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.
bool usbSendFileData(void *data, u32 data_size);
bool usbSendFileData(void *data, u64 data_size);
#endif /* __USB_H__ */