mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-23 02:36:41 +00:00
USB protocol updated.
This commit is contained in:
parent
61fb465e2a
commit
a7698e435e
3 changed files with 57 additions and 23 deletions
|
@ -437,7 +437,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consolePrint("waiting for usb connection... ");
|
consolePrint("waiting for usb connection... ");
|
||||||
|
|
||||||
if (!usbPerformHandshake())
|
if (!usbStartSession())
|
||||||
{
|
{
|
||||||
consolePrint("failed\n");
|
consolePrint("failed\n");
|
||||||
goto out2;
|
goto out2;
|
||||||
|
@ -493,6 +493,8 @@ int main(int argc, char *argv[])
|
||||||
thrd_join(read_thread, NULL);
|
thrd_join(read_thread, NULL);
|
||||||
thrd_join(write_thread, NULL);
|
thrd_join(write_thread, NULL);
|
||||||
|
|
||||||
|
usbEndSession();
|
||||||
|
|
||||||
if (shared_data.read_error || shared_data.write_error)
|
if (shared_data.read_error || shared_data.write_error)
|
||||||
{
|
{
|
||||||
consolePrint("usb transfer error\n");
|
consolePrint("usb transfer error\n");
|
||||||
|
|
67
source/usb.c
67
source/usb.c
|
@ -29,7 +29,7 @@
|
||||||
#define USB_CMD_HEADER_MAGIC 0x4E584454 /* "NXDT" */
|
#define USB_CMD_HEADER_MAGIC 0x4E584454 /* "NXDT" */
|
||||||
|
|
||||||
#define USB_TRANSFER_ALIGNMENT 0x1000 /* 4 KiB */
|
#define USB_TRANSFER_ALIGNMENT 0x1000 /* 4 KiB */
|
||||||
#define USB_TRANSFER_TIMEOUT 30 /* 30 seconds */
|
#define USB_TRANSFER_TIMEOUT 5 /* 5 seconds */
|
||||||
|
|
||||||
/* Type definitions. */
|
/* Type definitions. */
|
||||||
|
|
||||||
|
@ -41,9 +41,10 @@ typedef struct {
|
||||||
} usbDeviceInterface;
|
} usbDeviceInterface;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UsbCommandType_PerformHandshake = 0,
|
UsbCommandType_StartSession = 0,
|
||||||
UsbCommandType_SendFileProperties = 1,
|
UsbCommandType_SendFileProperties = 1,
|
||||||
UsbCommandType_SendNspHeader = 2 /* Needs to be implemented */
|
UsbCommandType_SendNspHeader = 2, /* Needs to be implemented */
|
||||||
|
UsbCommandType_EndSession = 3
|
||||||
} UsbCommandType;
|
} UsbCommandType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -59,7 +60,7 @@ typedef struct {
|
||||||
u8 app_ver_micro;
|
u8 app_ver_micro;
|
||||||
u8 abi_version;
|
u8 abi_version;
|
||||||
u8 reserved[0xC];
|
u8 reserved[0xC];
|
||||||
} UsbCommandPerformHandshake;
|
} UsbCommandStartSession;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 file_size;
|
u64 file_size;
|
||||||
|
@ -95,12 +96,14 @@ static bool g_usbDeviceInterfaceInitialized = false;
|
||||||
static usbDeviceInterface g_usbDeviceInterface = {0};
|
static usbDeviceInterface g_usbDeviceInterface = {0};
|
||||||
static RwLock g_usbDeviceLock = {0};
|
static RwLock g_usbDeviceLock = {0};
|
||||||
|
|
||||||
|
static bool g_usbSessionStarted = false;
|
||||||
|
|
||||||
static u8 *g_usbTransferBuffer = NULL;
|
static u8 *g_usbTransferBuffer = NULL;
|
||||||
static u64 g_usbTransferRemainingSize = 0;
|
static u64 g_usbTransferRemainingSize = 0;
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
|
|
||||||
static bool _usbPerformHandshake(void);
|
static bool _usbStartSession(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);
|
||||||
|
@ -171,12 +174,14 @@ void *usbAllocatePageAlignedBuffer(size_t size)
|
||||||
return memalign(USB_TRANSFER_ALIGNMENT, size);
|
return memalign(USB_TRANSFER_ALIGNMENT, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usbPerformHandshake(void)
|
bool usbStartSession(void)
|
||||||
{
|
{
|
||||||
rwlockWriteLock(&g_usbDeviceLock);
|
rwlockWriteLock(&g_usbDeviceLock);
|
||||||
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = g_usbSessionStarted;
|
||||||
|
if (ret) goto exit;
|
||||||
|
|
||||||
time_t start = time(NULL);
|
time_t start = time(NULL);
|
||||||
time_t now = start;
|
time_t now = start;
|
||||||
|
|
||||||
|
@ -186,7 +191,7 @@ bool usbPerformHandshake(void)
|
||||||
{
|
{
|
||||||
/* Once the console has been connected to a host device, there's no need to keep running this loop */
|
/* Once the console has been connected to a host device, there's no need to keep running this loop */
|
||||||
/* usbTransferData() implements its own timeout */
|
/* usbTransferData() implements its own timeout */
|
||||||
ret = _usbPerformHandshake();
|
ret = g_usbSessionStarted = _usbStartSession();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +199,7 @@ bool usbPerformHandshake(void)
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
rwlockWriteUnlock(&(g_usbDeviceInterface.lock));
|
rwlockWriteUnlock(&(g_usbDeviceInterface.lock));
|
||||||
rwlockWriteUnlock(&g_usbDeviceLock);
|
rwlockWriteUnlock(&g_usbDeviceLock);
|
||||||
|
|
||||||
|
@ -211,7 +217,7 @@ bool usbSendFileProperties(u64 file_size, const char *filename)
|
||||||
u32 status = UsbStatusType_Success;
|
u32 status = UsbStatusType_Success;
|
||||||
u32 filename_length = 0;
|
u32 filename_length = 0;
|
||||||
|
|
||||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || g_usbTransferRemainingSize > 0 || !filename || \
|
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbSessionStarted || g_usbTransferRemainingSize > 0 || !filename || \
|
||||||
!(filename_length = (u32)strlen(filename)) || filename_length >= FS_MAX_PATH)
|
!(filename_length = (u32)strlen(filename)) || filename_length >= FS_MAX_PATH)
|
||||||
{
|
{
|
||||||
LOGFILE("Invalid parameters!");
|
LOGFILE("Invalid parameters!");
|
||||||
|
@ -254,8 +260,8 @@ bool usbSendFileData(void *data, u64 data_size)
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
UsbStatus *cmd_status = NULL;
|
UsbStatus *cmd_status = NULL;
|
||||||
|
|
||||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbTransferRemainingSize || !data || !data_size || data_size > USB_TRANSFER_BUFFER_SIZE || \
|
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbSessionStarted || !g_usbTransferRemainingSize || !data || !data_size || \
|
||||||
data_size > g_usbTransferRemainingSize)
|
data_size > USB_TRANSFER_BUFFER_SIZE || data_size > g_usbTransferRemainingSize)
|
||||||
{
|
{
|
||||||
LOGFILE("Invalid parameters!");
|
LOGFILE("Invalid parameters!");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -311,9 +317,31 @@ exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _usbPerformHandshake(void)
|
void usbEndSession(void)
|
||||||
{
|
{
|
||||||
UsbCommandPerformHandshake *cmd_block = NULL;
|
rwlockWriteLock(&g_usbDeviceLock);
|
||||||
|
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
||||||
|
|
||||||
|
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbSessionStarted)
|
||||||
|
{
|
||||||
|
LOGFILE("Invalid parameters!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
usbPrepareCommandHeader(UsbCommandType_EndSession, 0);
|
||||||
|
|
||||||
|
if (!usbWrite(g_usbTransferBuffer, sizeof(UsbCommandHeader))) LOGFILE("Failed to send EndSession command!");
|
||||||
|
|
||||||
|
g_usbSessionStarted = false;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
rwlockWriteUnlock(&(g_usbDeviceInterface.lock));
|
||||||
|
rwlockWriteUnlock(&g_usbDeviceLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _usbStartSession(void)
|
||||||
|
{
|
||||||
|
UsbCommandStartSession *cmd_block = NULL;
|
||||||
size_t cmd_size = 0;
|
size_t cmd_size = 0;
|
||||||
u32 status = UsbStatusType_Success;
|
u32 status = UsbStatusType_Success;
|
||||||
|
|
||||||
|
@ -323,17 +351,17 @@ static bool _usbPerformHandshake(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbPrepareCommandHeader(UsbCommandType_PerformHandshake, (u32)sizeof(UsbCommandPerformHandshake));
|
usbPrepareCommandHeader(UsbCommandType_StartSession, (u32)sizeof(UsbCommandStartSession));
|
||||||
|
|
||||||
cmd_block = (UsbCommandPerformHandshake*)(g_usbTransferBuffer + sizeof(UsbCommandHeader));
|
cmd_block = (UsbCommandStartSession*)(g_usbTransferBuffer + sizeof(UsbCommandHeader));
|
||||||
memset(cmd_block, 0, sizeof(UsbCommandPerformHandshake));
|
memset(cmd_block, 0, sizeof(UsbCommandStartSession));
|
||||||
|
|
||||||
cmd_block->app_ver_major = VERSION_MAJOR;
|
cmd_block->app_ver_major = VERSION_MAJOR;
|
||||||
cmd_block->app_ver_minor = VERSION_MINOR;
|
cmd_block->app_ver_minor = VERSION_MINOR;
|
||||||
cmd_block->app_ver_micro = VERSION_MICRO;
|
cmd_block->app_ver_micro = VERSION_MICRO;
|
||||||
cmd_block->abi_version = USB_ABI_VERSION;
|
cmd_block->abi_version = USB_ABI_VERSION;
|
||||||
|
|
||||||
cmd_size = (sizeof(UsbCommandHeader) + sizeof(UsbCommandPerformHandshake));
|
cmd_size = (sizeof(UsbCommandHeader) + sizeof(UsbCommandStartSession));
|
||||||
|
|
||||||
status = usbSendCommand(cmd_size);
|
status = usbSendCommand(cmd_size);
|
||||||
if (status != UsbStatusType_Success) usbLogStatusDetail(status);
|
if (status != UsbStatusType_Success) usbLogStatusDetail(status);
|
||||||
|
@ -343,7 +371,7 @@ static bool _usbPerformHandshake(void)
|
||||||
|
|
||||||
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_EndSession) return;
|
||||||
UsbCommandHeader *cmd_header = (UsbCommandHeader*)g_usbTransferBuffer;
|
UsbCommandHeader *cmd_header = (UsbCommandHeader*)g_usbTransferBuffer;
|
||||||
memset(cmd_header, 0, sizeof(UsbCommandHeader));
|
memset(cmd_header, 0, sizeof(UsbCommandHeader));
|
||||||
cmd_header->magic = __builtin_bswap32(USB_CMD_HEADER_MAGIC);
|
cmd_header->magic = __builtin_bswap32(USB_CMD_HEADER_MAGIC);
|
||||||
|
@ -426,6 +454,7 @@ NX_INLINE void usbFreeTransferBuffer(void)
|
||||||
free(g_usbTransferBuffer);
|
free(g_usbTransferBuffer);
|
||||||
g_usbTransferBuffer = NULL;
|
g_usbTransferBuffer = NULL;
|
||||||
g_usbTransferRemainingSize = 0;
|
g_usbTransferRemainingSize = 0;
|
||||||
|
g_usbSessionStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool usbInitializeComms(void)
|
static bool usbInitializeComms(void)
|
||||||
|
|
|
@ -32,15 +32,18 @@ void usbExit(void);
|
||||||
/// Returns a pointer to a heap-allocated, page-aligned memory buffer that's suitable for USB transfers.
|
/// Returns a pointer to a heap-allocated, page-aligned memory buffer that's suitable for USB transfers.
|
||||||
void *usbAllocatePageAlignedBuffer(size_t size);
|
void *usbAllocatePageAlignedBuffer(size_t size);
|
||||||
|
|
||||||
/// Performs a handshake with the host device. Returns true if the host device replies with valid data within a certain time span.
|
/// Starts a data transfer session with the connected host device. Returns true if the host device replies with valid data within a certain time span.
|
||||||
/// This should be called before usbSendFileProperties().
|
/// This should be called before usbSendFileProperties().
|
||||||
bool usbPerformHandshake(void);
|
bool usbStartSession(void);
|
||||||
|
|
||||||
/// Sends file properties to the host device before starting a file data transfer. Must be called before usbSendFileData(), and after usbPerformHandshake().
|
/// Sends file properties to the host device before starting a file data transfer. Must be called before usbSendFileData(), and after usbStartSession().
|
||||||
bool usbSendFileProperties(u64 file_size, const char *filename);
|
bool usbSendFileProperties(u64 file_size, const char *filename);
|
||||||
|
|
||||||
/// Performs a file data transfer. Must be continuously called after usbSendFileProperties() until all file data has been transferred.
|
/// 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, u64 data_size);
|
bool usbSendFileData(void *data, u64 data_size);
|
||||||
|
|
||||||
|
/// Ends a previously started data transfer session with the connected host device.
|
||||||
|
void usbEndSession(void);
|
||||||
|
|
||||||
#endif /* __USB_H__ */
|
#endif /* __USB_H__ */
|
||||||
|
|
Loading…
Reference in a new issue