mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
Added UMS interface based around libusbhsfs.
Also normalized Initialized -> Init in names from global variables.
This commit is contained in:
parent
5a070f624c
commit
ae12e48678
5 changed files with 311 additions and 26 deletions
249
source/ums.c
Normal file
249
source/ums.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* ums.c
|
||||
*
|
||||
* Copyright (c) 2020, DarkMatterCore <pabloacurielz@gmail.com>.
|
||||
*
|
||||
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
|
||||
*
|
||||
* nxdumptool is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* nxdumptool is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
static Mutex g_umsMutex = 0;
|
||||
static bool g_umsInterfaceInit = false;
|
||||
|
||||
static Thread g_umsDetectionThread = {0};
|
||||
static UEvent *g_umsStatusChangeEvent = NULL, g_umsDetectionThreadExitEvent = {0};
|
||||
static bool g_umsDetectionThreadCreated = false, g_umsDeviceInfoUpdated = false;
|
||||
|
||||
static u32 g_umsDeviceCount = 0;
|
||||
static UsbHsFsDevice *g_umsDevices = NULL;
|
||||
|
||||
/* Function prototypes. */
|
||||
|
||||
static bool umsCreateDetectionThread(void);
|
||||
static void umsDestroyDetectionThread(void);
|
||||
static void umsDetectionThreadFunc(void *arg);
|
||||
|
||||
static void umsFreeDeviceData(void);
|
||||
|
||||
bool umsInitialize(void)
|
||||
{
|
||||
mutexLock(&g_umsMutex);
|
||||
|
||||
Result rc = 0;
|
||||
|
||||
bool ret = g_umsInterfaceInit;
|
||||
if (ret) goto end;
|
||||
|
||||
/* Initialize USB Mass Storage Host interface. */
|
||||
rc = usbHsFsInitialize(0);
|
||||
if (R_FAILED(rc))
|
||||
{
|
||||
LOGFILE("usbHsFsInitialize failed! (0x%08X).", rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Get USB Mass Storage status change event. */
|
||||
g_umsStatusChangeEvent = usbHsFsGetStatusChangeUserEvent();
|
||||
|
||||
/* Create user-mode exit event. */
|
||||
ueventCreate(&g_umsDetectionThreadExitEvent, true);
|
||||
|
||||
/* Create USB Mass Storage detection thread. */
|
||||
if (!(g_umsDetectionThreadCreated = umsCreateDetectionThread())) goto end;
|
||||
|
||||
ret = g_umsInterfaceInit = true;
|
||||
|
||||
end:
|
||||
mutexUnlock(&g_umsMutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void umsExit(void)
|
||||
{
|
||||
mutexLock(&g_umsMutex);
|
||||
|
||||
if (!g_umsInterfaceInit) goto end;
|
||||
|
||||
/* Destroy USB Mass Storage detection thread. */
|
||||
if (g_umsDetectionThreadCreated)
|
||||
{
|
||||
umsDestroyDetectionThread();
|
||||
g_umsDetectionThreadCreated = false;
|
||||
}
|
||||
|
||||
/* Close USB Mass Storage Host interface. */
|
||||
usbHsFsExit();
|
||||
|
||||
g_umsInterfaceInit = false;
|
||||
|
||||
end:
|
||||
mutexUnlock(&g_umsMutex);
|
||||
}
|
||||
|
||||
bool umsIsDeviceInfoUpdated(void)
|
||||
{
|
||||
mutexLock(&g_umsMutex);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (g_umsInterfaceInit && g_umsDeviceInfoUpdated)
|
||||
{
|
||||
ret = true;
|
||||
g_umsDeviceInfoUpdated = false;
|
||||
}
|
||||
|
||||
mutexUnlock(&g_umsMutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 umsGetDeviceCount(void)
|
||||
{
|
||||
mutexLock(&g_umsMutex);
|
||||
u32 count = (g_umsInterfaceInit ? g_umsDeviceCount : 0);
|
||||
mutexUnlock(&g_umsMutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
bool umsGetDeviceByIndex(u32 idx, UsbHsFsDevice *out_device)
|
||||
{
|
||||
mutexLock(&g_umsMutex);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (!g_umsInterfaceInit || !g_umsDeviceCount || !g_umsDevices || idx >= g_umsDeviceCount || !out_device)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Copy device data. */
|
||||
memcpy(out_device, &(g_umsDevices[idx]), sizeof(UsbHsFsDevice));
|
||||
|
||||
ret = true;
|
||||
|
||||
end:
|
||||
mutexUnlock(&g_umsMutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool umsCreateDetectionThread(void)
|
||||
{
|
||||
if (!utilsCreateThread(&g_umsDetectionThread, umsDetectionThreadFunc, NULL, 1))
|
||||
{
|
||||
LOGFILE("Failed to create USB Mass Storage detection thread!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void umsDestroyDetectionThread(void)
|
||||
{
|
||||
/* Signal the exit event to terminate the USB Mass Storage detection thread. */
|
||||
ueventSignal(&g_umsDetectionThreadExitEvent);
|
||||
|
||||
/* Wait for the USB Mass Storage detection thread to exit. */
|
||||
utilsJoinThread(&g_umsDetectionThread);
|
||||
}
|
||||
|
||||
static void umsDetectionThreadFunc(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
Result rc = 0;
|
||||
int idx = 0;
|
||||
u32 listed_device_count = 0;
|
||||
|
||||
Waiter status_change_event_waiter = waiterForUEvent(g_umsStatusChangeEvent);
|
||||
Waiter exit_event_waiter = waiterForUEvent(&g_umsDetectionThreadExitEvent);
|
||||
|
||||
while(true)
|
||||
{
|
||||
/* Wait until an event is triggered. */
|
||||
rc = waitMulti(&idx, -1, status_change_event_waiter, exit_event_waiter);
|
||||
if (R_FAILED(rc)) continue;
|
||||
|
||||
/* Exit event triggered. */
|
||||
if (idx == 1) break;
|
||||
|
||||
mutexLock(&g_umsMutex);
|
||||
|
||||
/* Free USB Mass Storage device data. */
|
||||
umsFreeDeviceData();
|
||||
|
||||
/* Get mounted device count. */
|
||||
g_umsDeviceCount = usbHsFsGetMountedDeviceCount();
|
||||
LOGFILE("USB Mass Storage status change event triggered! Mounted USB Mass Storage device count: %u.", g_umsDeviceCount);
|
||||
|
||||
if (g_umsDeviceCount)
|
||||
{
|
||||
bool fail = false;
|
||||
|
||||
/* Allocate mounted devices buffer. */
|
||||
g_umsDevices = calloc(g_umsDeviceCount, sizeof(UsbHsFsDevice));
|
||||
if (g_umsDevices)
|
||||
{
|
||||
/* List mounted devices. */
|
||||
if ((listed_device_count = usbHsFsListMountedDevices(g_umsDevices, g_umsDeviceCount)))
|
||||
{
|
||||
/* Check if we got as many devices as we expected. */
|
||||
if (listed_device_count == g_umsDeviceCount)
|
||||
{
|
||||
/* Update USB Mass Storage device info updated flag. */
|
||||
g_umsDeviceInfoUpdated = true;
|
||||
} else {
|
||||
LOGFILE("USB Mass Storage device count mismatch! (%u != %u).", listed_device_count, g_umsDeviceCount);
|
||||
fail = true;
|
||||
}
|
||||
} else {
|
||||
LOGFILE("Failed to list mounted USB Mass Storage devices!");
|
||||
fail = true;
|
||||
}
|
||||
} else {
|
||||
LOGFILE("Failed to allocate memory for mounted USB Mass Storage devices buffer!");
|
||||
fail = true;
|
||||
}
|
||||
|
||||
/* Free USB Mass Storage device data if something went wrong. */
|
||||
if (fail) umsFreeDeviceData();
|
||||
}
|
||||
|
||||
mutexUnlock(&g_umsMutex);
|
||||
}
|
||||
|
||||
/* Free USB Mass Storage device data. */
|
||||
umsFreeDeviceData();
|
||||
|
||||
threadExit();
|
||||
}
|
||||
|
||||
static void umsFreeDeviceData(void)
|
||||
{
|
||||
/* Free devices buffer. */
|
||||
if (g_umsDevices)
|
||||
{
|
||||
free(g_umsDevices);
|
||||
g_umsDevices = NULL;
|
||||
}
|
||||
|
||||
/* Reset device count. */
|
||||
g_umsDeviceCount = 0;
|
||||
}
|
41
source/ums.h
Normal file
41
source/ums.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* ums.h
|
||||
*
|
||||
* Copyright (c) 2020, DarkMatterCore <pabloacurielz@gmail.com>.
|
||||
*
|
||||
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
|
||||
*
|
||||
* nxdumptool is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* nxdumptool is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __UMS_H__
|
||||
#define __UMS_H__
|
||||
|
||||
/// Initializes the USB Mass Storage interface.
|
||||
bool umsInitialize(void);
|
||||
|
||||
/// Closes the USB Mass Storage interface.
|
||||
void umsExit(void);
|
||||
|
||||
/// Returns true if USB Mass Storage device info has been updated.
|
||||
bool umsIsDeviceInfoUpdated(void);
|
||||
|
||||
/// Returns the available USB Mass Storage device count.
|
||||
u32 umsGetDeviceCount(void);
|
||||
|
||||
/// Saves USB Mass Storage device info to 'out_device' using the provided index.
|
||||
bool umsGetDeviceByIndex(u32 idx, UsbHsFsDevice *out_device);
|
||||
|
||||
#endif /* __UMS_H__ */
|
20
source/usb.c
20
source/usb.c
|
@ -107,7 +107,7 @@ typedef struct {
|
|||
|
||||
static RwLock g_usbDeviceLock = {0};
|
||||
static usbDeviceInterface g_usbDeviceInterface = {0};
|
||||
static bool g_usbDeviceInterfaceInitialized = false;
|
||||
static bool g_usbDeviceInterfaceInit = false;
|
||||
|
||||
static Event *g_usbStateChangeEvent = NULL;
|
||||
static Thread g_usbDetectionThread = {0};
|
||||
|
@ -250,7 +250,7 @@ bool usbSendFileProperties(u64 file_size, const char *filename, u32 nsp_header_s
|
|||
u32 status = UsbStatusType_Success;
|
||||
size_t filename_length = 0;
|
||||
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || !filename || \
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInit || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || !filename || \
|
||||
!(filename_length = strlen(filename)) || filename_length >= FS_MAX_PATH || (!g_nspTransferMode && ((file_size && nsp_header_size >= file_size) || g_usbTransferRemainingSize)) || \
|
||||
(g_nspTransferMode && nsp_header_size))
|
||||
{
|
||||
|
@ -299,7 +299,7 @@ bool usbSendFileData(void *data, u64 data_size)
|
|||
UsbStatus *cmd_status = NULL;
|
||||
bool ret = false, zlt_required = false;
|
||||
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || !g_usbTransferRemainingSize || !data || \
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInit || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || !g_usbTransferRemainingSize || !data || \
|
||||
!data_size || data_size > USB_TRANSFER_BUFFER_SIZE || data_size > g_usbTransferRemainingSize)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
|
@ -398,7 +398,7 @@ bool usbSendNspHeader(void *nsp_header, u32 nsp_header_size)
|
|||
u32 status = UsbStatusType_Success;
|
||||
bool ret = false, zlt_required = false;
|
||||
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || g_usbTransferRemainingSize || \
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInit || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || g_usbTransferRemainingSize || \
|
||||
!g_nspTransferMode || !nsp_header || !nsp_header_size || nsp_header_size > (USB_TRANSFER_BUFFER_SIZE - sizeof(UsbCommandHeader)))
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
|
@ -441,7 +441,7 @@ void usbCancelFileTransfer(void)
|
|||
rwlockWriteLock(&(g_usbDeviceInterface.lock));
|
||||
rwlockWriteLock(&(g_usbDeviceInterface.lock_in));
|
||||
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || (!g_usbTransferRemainingSize && \
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInit || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted || (!g_usbTransferRemainingSize && \
|
||||
!g_nspTransferMode)) goto end;
|
||||
|
||||
/* Reset variables. */
|
||||
|
@ -555,7 +555,7 @@ static bool usbStartSession(void)
|
|||
size_t cmd_size = 0;
|
||||
u32 status = UsbStatusType_Success;
|
||||
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized)
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInit || !g_usbDeviceInterface.initialized)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
return false;
|
||||
|
@ -598,7 +598,7 @@ static bool usbStartSession(void)
|
|||
|
||||
static void usbEndSession(void)
|
||||
{
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInitialized || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted)
|
||||
if (!g_usbTransferBuffer || !g_usbDeviceInterfaceInit || !g_usbDeviceInterface.initialized || !g_usbHostAvailable || !g_usbSessionStarted)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
return;
|
||||
|
@ -705,7 +705,7 @@ static bool usbInitializeComms(void)
|
|||
{
|
||||
Result rc = 0;
|
||||
|
||||
bool ret = (g_usbDeviceInterfaceInitialized && g_usbDeviceInterface.initialized);
|
||||
bool ret = (g_usbDeviceInterfaceInit && g_usbDeviceInterface.initialized);
|
||||
if (ret) goto end;
|
||||
|
||||
rc = usbDsInitialize();
|
||||
|
@ -858,7 +858,7 @@ static bool usbInitializeComms(void)
|
|||
}
|
||||
}
|
||||
|
||||
ret = g_usbDeviceInterfaceInitialized = true;
|
||||
ret = g_usbDeviceInterfaceInit = true;
|
||||
|
||||
end:
|
||||
if (!ret) usbCloseComms();
|
||||
|
@ -869,7 +869,7 @@ end:
|
|||
static void usbCloseComms(void)
|
||||
{
|
||||
usbDsExit();
|
||||
g_usbDeviceInterfaceInitialized = false;
|
||||
g_usbDeviceInterfaceInit = false;
|
||||
usbFreeDeviceInterface();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*/
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include <usbhsfs.h>
|
||||
|
||||
#include "utils.h"
|
||||
//#include "freetype_helper.h"
|
||||
|
@ -30,6 +29,7 @@
|
|||
#include "services.h"
|
||||
#include "nca.h"
|
||||
#include "usb.h"
|
||||
#include "ums.h"
|
||||
#include "title.h"
|
||||
#include "bfttf.h"
|
||||
#include "fatfs/ff.h"
|
||||
|
@ -38,7 +38,7 @@
|
|||
|
||||
/* Global variables. */
|
||||
|
||||
static bool g_resourcesInitialized = false, g_isDevUnit = false;
|
||||
static bool g_resourcesInit = false, g_isDevUnit = false;
|
||||
static Mutex g_resourcesMutex = 0;
|
||||
|
||||
static PadState g_padState = {0};
|
||||
|
@ -78,8 +78,7 @@ bool utilsInitializeResources(void)
|
|||
{
|
||||
mutexLock(&g_resourcesMutex);
|
||||
|
||||
Result rc = 0;
|
||||
bool ret = g_resourcesInitialized;
|
||||
bool ret = g_resourcesInit;
|
||||
if (ret) goto end;
|
||||
|
||||
/* Configure input. */
|
||||
|
@ -118,13 +117,8 @@ bool utilsInitializeResources(void)
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* Initialize USB Mass Storage Host interface. */
|
||||
rc = usbHsFsInitialize(0);
|
||||
if (R_FAILED(rc))
|
||||
{
|
||||
LOGFILE("Failed to initialize USB host FS interface! (0x%08X).", rc);
|
||||
goto end;
|
||||
}
|
||||
/* Initialize USB Mass Storage interface. */
|
||||
if (!umsInitialize()) goto end;
|
||||
|
||||
/* Load NCA keyset. */
|
||||
if (!keysLoadNcaKeyset())
|
||||
|
@ -190,7 +184,7 @@ bool utilsInitializeResources(void)
|
|||
/* Initialize LVGL. */
|
||||
//if (!lvglHelperInitialize()) return false;
|
||||
|
||||
ret = g_resourcesInitialized = true;
|
||||
ret = g_resourcesInit = true;
|
||||
|
||||
end:
|
||||
mutexUnlock(&g_resourcesMutex);
|
||||
|
@ -235,8 +229,8 @@ void utilsCloseResources(void)
|
|||
/* Free NCA crypto buffer. */
|
||||
ncaFreeCryptoBuffer();
|
||||
|
||||
/* Close USB Mass Storage Host interface. */
|
||||
usbHsFsExit();
|
||||
/* Close USB Mass Storage interface. */
|
||||
umsExit();
|
||||
|
||||
/* Close USB interface. */
|
||||
usbExit();
|
||||
|
@ -244,7 +238,7 @@ void utilsCloseResources(void)
|
|||
/* Close initialized services. */
|
||||
servicesClose();
|
||||
|
||||
g_resourcesInitialized = false;
|
||||
g_resourcesInit = false;
|
||||
|
||||
mutexUnlock(&g_resourcesMutex);
|
||||
}
|
||||
|
@ -330,7 +324,7 @@ void utilsJoinThread(Thread *thread)
|
|||
bool utilsIsDevelopmentUnit(void)
|
||||
{
|
||||
mutexLock(&g_resourcesMutex);
|
||||
bool ret = (g_resourcesInitialized && g_isDevUnit);
|
||||
bool ret = (g_resourcesInit && g_isDevUnit);
|
||||
mutexUnlock(&g_resourcesMutex);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <stdatomic.h>
|
||||
#include <switch.h>
|
||||
#include <usbhsfs.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue