Merge branch 'real_usb' into xci

This commit is contained in:
HookedBehemoth 2019-11-30 17:12:45 +01:00
commit 3cebefb785
45 changed files with 943 additions and 230 deletions

View file

@ -55,9 +55,10 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ -D__DEBUG__ -DNXLINK_DEBUG
CFLAGS += $(INCLUDE) -D__SWITCH__ -D__DEBUG__ -Wall
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++17 -Wall
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
@ -166,17 +167,17 @@ all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
#comment this out if you are hacking on the code or compilation will take for ever
$(MAKE) --no-print-directory -C include/Plutonium -f Makefile lib-switch
#$(MAKE) --no-print-directory -C include/Plutonium -f Makefile lib-switch
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
ifeq ($(strip $(APP_JSON)),)
@$(MAKE) --no-print-directory -C include/Plutonium/Plutonium -f Makefile clean
#@$(MAKE) --no-print-directory -C include/Plutonium/Plutonium -f Makefile clean
@rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
else
@$(MAKE) --no-print-directory -C include/Plutonium/Plutonium -f Makefile clean
#@$(MAKE) --no-print-directory -C include/Plutonium/Plutonium -f Makefile clean
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
endif

View file

@ -34,7 +34,6 @@ namespace tin::install::nsp
HTTPNSP(std::string url);
virtual void BufferNCAHeader(void* buf, NcmContentId placeholderId) override;
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) override;
virtual void BufferData(void* buf, off_t offset, size_t size) override;
};

View file

@ -41,7 +41,7 @@ namespace tin::install::xci
void InstallTicketCert() override;
public:
XCIInstallTask(tin::install::xci::XCI& xci, NcmStorageId destStorageId, bool ignoreReqFirmVersion);
XCIInstallTask(NcmStorageId destStorageId, bool ignoreReqFirmVersion, tin::install::xci::XCI* xci);
};
};

View file

@ -31,7 +31,7 @@ namespace tin::install
u8 _0x148[0xB8]; /* Padding. */
} PACKED;
static_assert(sizeof(NcaFsHeader) == 0x200, "PFS0FileEntry must be 0x18");
static_assert(sizeof(NcaFsHeader) == 0x200, "NcaFsHeader must be 0x200");
struct NcaSectionEntry
{
@ -40,7 +40,7 @@ namespace tin::install
u8 _0x8[0x8]; /* Padding. */
} PACKED;
static_assert(sizeof(NcaSectionEntry) == 0x10, "PFS0FileEntry must be 0x18");
static_assert(sizeof(NcaSectionEntry) == 0x10, "NcaSectionEntry must be 0x10");
struct NcaHeader
{
@ -73,5 +73,5 @@ namespace tin::install
NcaFsHeader fs_headers[4]; /* FS section headers. */
} PACKED;
static_assert(sizeof(NcaHeader) == 0xc00, "PFS0FileEntry must be 0x18");
static_assert(sizeof(NcaHeader) == 0xc00, "NcaHeader must be 0xc00");
}

View file

@ -40,7 +40,6 @@ namespace tin::install::nsp
RemoteNSP();
public:
virtual void BufferNCAHeader(void* buf, NcmContentId placeholderId) = 0;
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) = 0;
virtual void BufferData(void* buf, off_t offset, size_t size) = 0;

View file

@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "install/remote_nsp.hpp"
namespace tin::install::nsp
{
class USBNSP : public RemoteNSP
{
private:
std::string m_nspName;
public:
USBNSP(std::string nspName);
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) override;
virtual void BufferData(void* buf, off_t offset, size_t size) override;
};
}

View file

@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "install/xci.hpp"
namespace tin::install::xci
{
class USBXCI : public XCI
{
private:
std::string m_xciName;
public:
USBXCI(std::string xciName);
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) override;
virtual void BufferData(void* buf, off_t offset, size_t size) override;
};
}

View file

@ -21,6 +21,6 @@ SOFTWARE.
*/
namespace netInstStuff {
void installNspLan(std::vector<std::string> ourUrlList, int ourStorage, std::vector<std::string> urlListAltNames);
void installTitleNet(std::vector<std::string> ourUrlList, int ourStorage, std::vector<std::string> urlListAltNames);
std::vector<std::string> OnSelected();
}

View file

@ -2,7 +2,8 @@
#include <pu/Plutonium>
#include "ui/mainPage.hpp"
#include "ui/netInstPage.hpp"
#include "ui/nspInstPage.hpp"
#include "ui/sdInstPage.hpp"
#include "ui/usbInstPage.hpp"
#include "ui/instPage.hpp"
#include "ui/optionsPage.hpp"
@ -14,7 +15,8 @@ namespace inst::ui {
void OnLoad() override;
MainPage::Ref mainPage;
netInstPage::Ref netinstPage;
nspInstPage::Ref nspinstPage;
sdInstPage::Ref sdinstPage;
usbInstPage::Ref usbinstPage;
instPage::Ref instpage;
optionsPage::Ref optionspage;
};

View file

@ -10,6 +10,7 @@ namespace inst::ui {
PU_SMART_CTOR(MainPage)
void installMenuItem_Click();
void netInstallMenuItem_Click();
void usbInstallMenuItem_Click();
void sigPatchesMenuItem_Click();
void settingsMenuItem_Click();
void exitMenuItem_Click();
@ -24,6 +25,7 @@ namespace inst::ui {
pu::ui::elm::Menu::Ref optionMenu;
pu::ui::elm::MenuItem::Ref installMenuItem;
pu::ui::elm::MenuItem::Ref netInstallMenuItem;
pu::ui::elm::MenuItem::Ref usbInstallMenuItem;
pu::ui::elm::MenuItem::Ref sigPatchesMenuItem;
pu::ui::elm::MenuItem::Ref settingsMenuItem;
pu::ui::elm::MenuItem::Ref exitMenuItem;

View file

@ -13,9 +13,9 @@ namespace inst::ui {
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos);
TextBlock::Ref pageInfoText;
private:
static std::vector<std::string> ourUrls;
static std::vector<std::string> selectedUrls;
static std::vector<std::string> alternativeNames;
std::vector<std::string> ourUrls;
std::vector<std::string> selectedUrls;
std::vector<std::string> alternativeNames;
TextBlock::Ref butText;
Rectangle::Ref topRect;
Rectangle::Ref infoRect;
@ -25,6 +25,6 @@ namespace inst::ui {
pu::ui::elm::Menu::Ref menu;
Image::Ref infoImage;
void drawMenuItems(bool clearItems);
void selectNsp(int selectedIndex);
void selectTitle(int selectedIndex);
};
}

View file

@ -4,21 +4,21 @@
using namespace pu::ui::elm;
namespace inst::ui {
class nspInstPage : public pu::ui::Layout
class sdInstPage : public pu::ui::Layout
{
public:
nspInstPage();
PU_SMART_CTOR(nspInstPage)
sdInstPage();
PU_SMART_CTOR(sdInstPage)
pu::ui::elm::Menu::Ref menu;
void startInstall();
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos);
TextBlock::Ref pageInfoText;
void drawMenuItems(bool clearItems, std::filesystem::path ourPath);
private:
static std::vector<std::filesystem::path> ourDirectories;
static std::vector<std::filesystem::path> ourFiles;
static std::vector<std::filesystem::path> selectedNsps;
static std::filesystem::path currentDir;
std::vector<std::filesystem::path> ourDirectories;
std::vector<std::filesystem::path> ourFiles;
std::vector<std::filesystem::path> selectedTitles;
std::filesystem::path currentDir;
TextBlock::Ref butText;
Rectangle::Ref topRect;
Rectangle::Ref infoRect;

31
include/ui/usbInstPage.hpp Executable file
View file

@ -0,0 +1,31 @@
#pragma once
#include <pu/Plutonium>
using namespace pu::ui::elm;
namespace inst::ui {
class usbInstPage : public pu::ui::Layout
{
public:
usbInstPage();
PU_SMART_CTOR(usbInstPage)
void startInstall();
void startUsb();
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos);
TextBlock::Ref pageInfoText;
private:
std::vector<std::string> ourTitles;
std::vector<std::string> selectedTitles;
std::string lastUrl;
std::string lastFileID;
TextBlock::Ref butText;
Rectangle::Ref topRect;
Rectangle::Ref infoRect;
Rectangle::Ref botRect;
Image::Ref titleImage;
TextBlock::Ref appVersionText;
pu::ui::elm::Menu::Ref menu;
Image::Ref infoImage;
void drawMenuItems(bool clearItems);
void selectTitle(int selectedIndex);
};
}

8
include/usbInstall.hpp Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include <vector>
#include <string>
namespace usbInstStuff {
std::vector<std::string> OnSelected();
void installTitleUsb(std::vector<std::string> ourNspList, int ourStorage);
}

View file

@ -29,12 +29,7 @@ extern "C" {
#include <stdio.h>
#include <switch/types.h>
extern FILE *nxlinkout;
int nxLinkInitialize(void);
void nxLinkExit(void);
void printBytes(FILE* out, u8 *bytes, size_t size, bool includeHeader);
void printBytes(u8 *bytes, size_t size, bool includeHeader);
#ifdef __cplusplus
}

View file

@ -33,7 +33,7 @@ SOFTWARE.
strncat(error_prefix, formatted_msg, 512-1); throw std::runtime_error(error_prefix); }
#ifdef NXLINK_DEBUG
#define LOG_DEBUG(format, ...) { fprintf(nxlinkout, "%s:%u: ", __func__, __LINE__); fprintf(nxlinkout, format, ##__VA_ARGS__); }
#define LOG_DEBUG(format, ...) { printf("%s:%u: ", __func__, __LINE__); printf(format, ##__VA_ARGS__); }
#else
#define LOG_DEBUG(format, ...) ;
#endif

37
include/util/usb_util.hpp Normal file
View file

@ -0,0 +1,37 @@
#pragma once
#include <switch.h>
#include <string>
namespace tin::util
{
enum USBCmdType : u8
{
REQUEST = 0,
RESPONSE = 1
};
struct USBCmdHeader
{
u32 magic;
USBCmdType type;
u8 padding[0x3] = {0};
u32 cmdId;
u64 dataSize;
u8 reserved[0xC] = {0};
} PACKED;
static_assert(sizeof(USBCmdHeader) == 0x20, "USBCmdHeader must be 0x20!");
class USBCmdManager
{
public:
static void SendCmdHeader(u32 cmdId, size_t dataSize);
static void SendExitCmd();
static USBCmdHeader SendFileRangeCmd(std::string nspName, u64 offset, u64 size);
};
size_t USBRead(void* out, size_t len);
size_t USBWrite(const void* in, size_t len);
}

View file

@ -17,4 +17,5 @@ namespace inst::util {
std::string getDriveFileName(std::string fileId);
std::vector<uint32_t> setClockSpeed(int deviceToClock, uint32_t clockSpeed);
std::string getIPAddress();
int getUsbState();
}

BIN
romfs/usb-connection-waiting.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
romfs/usb-port.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -208,7 +208,7 @@ namespace tin::data
for (int i = 0; i < NUM_BUFFER_SEGMENTS; i++)
{
printf("Buffer %u:\n", i);
printBytes(nxlinkout, m_bufferSegments[i].data, BUFFER_SEGMENT_DATA_SIZE, true);
printBytes(m_bufferSegments[i].data, BUFFER_SEGMENT_DATA_SIZE, true);
}
}
}

View file

@ -49,7 +49,7 @@ namespace tin::data
void ByteBuffer::DebugPrintContents()
{
fprintf(nxlinkout, "Buffer Size: 0x%lx\n", this->GetSize());
printBytes(nxlinkout, this->GetData(), this->GetSize(), true);
printf("Buffer Size: 0x%lx\n", this->GetSize());
printBytes(this->GetData(), this->GetSize(), true);
}
}

View file

@ -28,7 +28,7 @@ SOFTWARE.
#include "util/title_util.hpp"
#include "util/error.hpp"
#include "util/debug.h"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
#include "util/util.hpp"
namespace tin::install::nsp
@ -80,13 +80,6 @@ namespace tin::install::nsp
return 0;
}
void HTTPNSP::BufferNCAHeader(void* buf, NcmContentId placeholderId)
{
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
u64 pfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
this->BufferData(buf, pfs0Offset, 0xc00);
}
void HTTPNSP::StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId)
{
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
@ -131,7 +124,7 @@ namespace tin::install::nsp
u64 downloadSizeMB = bufferedPlaceholderWriter.GetSizeBuffered() / 1000000;
int downloadProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeBuffered() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
//printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
inst::ui::setInstInfoText("Downloading " + inst::util::formatUrlString(ncaFileName) + " at " + std::to_string(speed).substr(0, std::to_string(speed).size()-4) + "MB/s");
inst::ui::setInstBarPerc((double)downloadProgress);
}
@ -147,7 +140,7 @@ namespace tin::install::nsp
u64 installSizeMB = bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / 1000000;
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
//printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
inst::ui::setInstBarPerc((double)installProgress);
}
inst::ui::setInstBarPerc(100);

View file

@ -25,7 +25,7 @@ SOFTWARE.
#include <threads.h>
#include "data/buffered_placeholder_writer.hpp"
#include "util/error.hpp"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
#include "util/util.hpp"
namespace tin::install::xci

View file

@ -233,9 +233,9 @@ namespace tin::install
}
printf("Application content meta key: \n");
printBytes(nxlinkout, (u8*)&latestApplicationContentMetaKey, sizeof(NcmContentMetaKey), true);
printBytes((u8*)&latestApplicationContentMetaKey, sizeof(NcmContentMetaKey), true);
printf("Application content meta: \n");
printBytes(nxlinkout, appContentRecordBuf.get(), appContentRecordSize, true);
printBytes(appContentRecordBuf.get(), appContentRecordSize, true);
if (hasUpdate)
{
@ -252,9 +252,9 @@ namespace tin::install
}
printf("Patch content meta key: \n");
printBytes(nxlinkout, (u8*)&latestPatchContentMetaKey, sizeof(NcmContentMetaKey), true);
printBytes((u8*)&latestPatchContentMetaKey, sizeof(NcmContentMetaKey), true);
printf("Patch content meta: \n");
printBytes(nxlinkout, patchContentRecordBuf.get(), patchContentRecordsSize, true);
printBytes(patchContentRecordBuf.get(), patchContentRecordsSize, true);
}
else
{
@ -266,7 +266,7 @@ namespace tin::install
ASSERT_OK(nsListApplicationRecordContentMeta(0, baseTitleId, appRecordBuf.get(), 0x100, &numEntriesRead), "Failed to list application record content meta");
printf("Application record content meta: \n");
printBytes(nxlinkout, appRecordBuf.get(), 0x100, true);
printBytes(appRecordBuf.get(), 0x100, true);
}
catch (std::runtime_error& e)
{

View file

@ -38,7 +38,7 @@ SOFTWARE.
#include "util/error.hpp"
#include "util/file_util.hpp"
#include "util/title_util.hpp"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
#include "ui/MainApplication.hpp"
namespace inst::ui {
@ -162,7 +162,7 @@ namespace tin::install::nsp
progress = (float)fileOff / (float)ncaSize;
if (fileOff % (0x400000 * 3) == 0) {
printf("> Progress: %lu/%lu MB (%d%s)\r", (fileOff / 1000000), (ncaSize / 1000000), (int)(progress * 100.0), "%");
//printf("> Progress: %lu/%lu MB (%d%s)\r", (fileOff / 1000000), (ncaSize / 1000000), (int)(progress * 100.0), "%");
inst::ui::setInstBarPerc((double)(progress * 100.0));
}
@ -183,7 +183,7 @@ namespace tin::install::nsp
writer.close();
// Clean up the line for whatever comes next
printf(" \r");
//printf(" \r");
printf("Registering placeholder...\n");
if (!failed)

View file

@ -94,15 +94,16 @@ namespace tin::install::nsp
if (inst::config::validateNCAs && !declinedValidation)
{
tin::install::NcaHeader header;
m_remoteNSP->BufferNCAHeader(&header, ncaId);
Crypto::AesXtr decryptor(Crypto::Keys().headerKey, false);
decryptor.decrypt(&header, &header, sizeof(header), 0, 0x200);
tin::install::NcaHeader* header = new NcaHeader;
m_remoteNSP->BufferData(header, m_remoteNSP->GetDataOffset() + fileEntry->dataOffset, sizeof(tin::install::NcaHeader));
if (header.magic != MAGIC_NCA3)
Crypto::AesXtr crypto(Crypto::Keys().headerKey, false);
crypto.decrypt(header, header, sizeof(tin::install::NcaHeader), 0, 0x200);
if (header->magic != MAGIC_NCA3)
THROW_FORMAT("Invalid NCA magic");
if (!Crypto::rsa2048PssVerify(&header.magic, 0x200, header.fixed_key_sig, Crypto::NCAHeaderSignature))
if (!Crypto::rsa2048PssVerify(&header->magic, 0x200, header->fixed_key_sig, Crypto::NCAHeaderSignature))
{
int rc = inst::ui::mainApp->CreateShowDialog("Invalid NCA signature detected!", "Improperly signed software should only be installed from trustworthy\nsources. Files containing cartridge repacks and DLC unlockers will always\nshow this warning. You can disable this check in Awoo Installer's settings.\n\nAre you sure you want to continue the installation?", {"Cancel", "Yes, I understand the risks"}, false);
if (rc != 1)
@ -114,7 +115,7 @@ namespace tin::install::nsp
m_remoteNSP->StreamToPlaceholder(contentStorage, ncaId);
// Clean up the line for whatever comes next
printf(" \r");
//printf(" \r");
printf("Registering placeholder...\n");
try

View file

@ -28,7 +28,7 @@ SOFTWARE.
#include "util/config.hpp"
#include "util/crypto.hpp"
#include "install/nca.hpp"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
#include "ui/MainApplication.hpp"
namespace inst::ui {
@ -37,8 +37,8 @@ namespace inst::ui {
namespace tin::install::xci
{
XCIInstallTask::XCIInstallTask(tin::install::xci::XCI& xci, NcmStorageId destStorageId, bool ignoreReqFirmVersion) :
Install(destStorageId, ignoreReqFirmVersion), m_xci(&xci)
XCIInstallTask::XCIInstallTask(NcmStorageId destStorageId, bool ignoreReqFirmVersion, tin::install::xci::XCI* xci) :
Install(destStorageId, ignoreReqFirmVersion), m_xci(xci)
{
m_xci->RetrieveHeader();
}

View file

@ -2,7 +2,7 @@
#include "error.hpp"
#include "debug.h"
#include "nx/nca_writer.h"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
namespace tin::install::xci
{

View file

@ -45,7 +45,7 @@ namespace tin::install::nsp
this->BufferData(m_headerBytes.data(), 0x0, sizeof(PFS0BaseHeader));
printf("Base header: \n");
printBytes(nxlinkout, m_headerBytes.data(), sizeof(PFS0BaseHeader), true);
printBytes(m_headerBytes.data(), sizeof(PFS0BaseHeader), true);
// Retrieve the full header
size_t remainingHeaderSize = this->GetBaseHeader()->numFiles * sizeof(PFS0FileEntry) + this->GetBaseHeader()->stringTableSize;
@ -53,7 +53,7 @@ namespace tin::install::nsp
this->BufferData(m_headerBytes.data() + sizeof(PFS0BaseHeader), sizeof(PFS0BaseHeader), remainingHeaderSize);
printf("Full header: \n");
printBytes(nxlinkout, m_headerBytes.data(), m_headerBytes.size(), true);
printBytes(m_headerBytes.data(), m_headerBytes.size(), true);
}
const PFS0FileEntry* RemoteNSP::GetFileEntry(unsigned int index)

150
source/install/usb_nsp.cpp Executable file
View file

@ -0,0 +1,150 @@
#include "install/usb_nsp.hpp"
#include <switch.h>
#include <algorithm>
#include <malloc.h>
#include <threads.h>
#include "data/byte_buffer.hpp"
#include "data/buffered_placeholder_writer.hpp"
#include "util/usb_util.hpp"
#include "error.hpp"
#include "debug.h"
#include "sdInstall.hpp"
#include "util/util.hpp"
namespace tin::install::nsp
{
USBNSP::USBNSP(std::string nspName) :
m_nspName(nspName)
{
}
struct USBFuncArgs
{
std::string nspName;
tin::data::BufferedPlaceholderWriter* bufferedPlaceholderWriter;
u64 pfs0Offset;
u64 ncaSize;
};
int USBThreadFunc(void* in)
{
USBFuncArgs* args = reinterpret_cast<USBFuncArgs*>(in);
tin::util::USBCmdHeader header = tin::util::USBCmdManager::SendFileRangeCmd(args->nspName, args->pfs0Offset, args->ncaSize);
u8* buf = (u8*)memalign(0x1000, 0x800000);
u64 sizeRemaining = header.dataSize;
size_t tmpSizeRead = 0;
try
{
while (sizeRemaining)
{
tmpSizeRead = usbCommsRead(buf, std::min(sizeRemaining, (u64)0x800000));
sizeRemaining -= tmpSizeRead;
while (true)
{
if (args->bufferedPlaceholderWriter->CanAppendData(tmpSizeRead))
break;
}
args->bufferedPlaceholderWriter->AppendData(buf, tmpSizeRead);
}
}
catch (std::exception& e)
{
printf("An error occurred:\n%s", e.what());
}
free(buf);
return 0;
}
int USBPlaceholderWriteFunc(void* in)
{
USBFuncArgs* args = reinterpret_cast<USBFuncArgs*>(in);
while (!args->bufferedPlaceholderWriter->IsPlaceholderComplete())
{
if (args->bufferedPlaceholderWriter->CanWriteSegmentToPlaceholder())
args->bufferedPlaceholderWriter->WriteSegmentToPlaceholder();
}
return 0;
}
void USBNSP::StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId)
{
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
std::string ncaFileName = this->GetFileEntryName(fileEntry);
printf("Retrieving %s\n", ncaFileName.c_str());
size_t ncaSize = fileEntry->fileSize;
tin::data::BufferedPlaceholderWriter bufferedPlaceholderWriter(contentStorage, placeholderId, ncaSize);
USBFuncArgs args;
args.nspName = m_nspName;
args.bufferedPlaceholderWriter = &bufferedPlaceholderWriter;
args.pfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
args.ncaSize = ncaSize;
thrd_t usbThread;
thrd_t writeThread;
thrd_create(&usbThread, USBThreadFunc, &args);
thrd_create(&writeThread, USBPlaceholderWriteFunc, &args);
u64 freq = armGetSystemTickFreq();
u64 startTime = armGetSystemTick();
size_t startSizeBuffered = 0;
double speed = 0.0;
while (!bufferedPlaceholderWriter.IsBufferDataComplete())
{
u64 newTime = armGetSystemTick();
if (newTime - startTime >= freq)
{
size_t newSizeBuffered = bufferedPlaceholderWriter.GetSizeBuffered();
double mbBuffered = (newSizeBuffered / 1000000.0) - (startSizeBuffered / 1000000.0);
double duration = ((double)(newTime - startTime) / (double)freq);
speed = mbBuffered / duration;
startTime = newTime;
startSizeBuffered = newSizeBuffered;
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
u64 downloadSizeMB = bufferedPlaceholderWriter.GetSizeBuffered() / 1000000;
int downloadProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeBuffered() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
inst::ui::setInstInfoText("Downloading " + inst::util::formatUrlString(ncaFileName) + " at " + std::to_string(speed).substr(0, std::to_string(speed).size()-4) + "MB/s");
inst::ui::setInstBarPerc((double)downloadProgress);
}
}
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
while (!bufferedPlaceholderWriter.IsPlaceholderComplete())
{
u64 installSizeMB = bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / 1000000;
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
inst::ui::setInstBarPerc((double)installProgress);
}
thrd_join(usbThread, NULL);
thrd_join(writeThread, NULL);
}
void USBNSP::BufferData(void* buf, off_t offset, size_t size)
{
printf("buffering 0x%lx-0x%lx", offset, offset + size);
tin::util::USBCmdHeader header = tin::util::USBCmdManager::SendFileRangeCmd(m_nspName, offset, size);
tin::util::USBRead(buf, header.dataSize);
}
}

150
source/install/usb_xci.cpp Normal file
View file

@ -0,0 +1,150 @@
#include "install/usb_xci.hpp"
#include <switch.h>
#include <algorithm>
#include <malloc.h>
#include <threads.h>
#include "data/byte_buffer.hpp"
#include "data/buffered_placeholder_writer.hpp"
#include "util/usb_util.hpp"
#include "error.hpp"
#include "debug.h"
#include "sdInstall.hpp"
#include "util/util.hpp"
namespace tin::install::xci
{
USBXCI::USBXCI(std::string xciName) :
m_xciName(xciName)
{
}
struct USBFuncArgs
{
std::string xciName;
tin::data::BufferedPlaceholderWriter* bufferedPlaceholderWriter;
u64 hfs0Offset;
u64 ncaSize;
};
int USBThreadFunc(void* in)
{
USBFuncArgs* args = reinterpret_cast<USBFuncArgs*>(in);
tin::util::USBCmdHeader header = tin::util::USBCmdManager::SendFileRangeCmd(args->xciName, args->hfs0Offset, args->ncaSize);
u8* buf = (u8*)memalign(0x1000, 0x800000);
u64 sizeRemaining = header.dataSize;
size_t tmpSizeRead = 0;
try
{
while (sizeRemaining)
{
tmpSizeRead = usbCommsRead(buf, std::min(sizeRemaining, (u64)0x800000));
sizeRemaining -= tmpSizeRead;
while (true)
{
if (args->bufferedPlaceholderWriter->CanAppendData(tmpSizeRead))
break;
}
args->bufferedPlaceholderWriter->AppendData(buf, tmpSizeRead);
}
}
catch (std::exception& e)
{
printf("An error occurred:\n%s", e.what());
}
free(buf);
return 0;
}
int USBPlaceholderWriteFunc(void* in)
{
USBFuncArgs* args = reinterpret_cast<USBFuncArgs*>(in);
while (!args->bufferedPlaceholderWriter->IsPlaceholderComplete())
{
if (args->bufferedPlaceholderWriter->CanWriteSegmentToPlaceholder())
args->bufferedPlaceholderWriter->WriteSegmentToPlaceholder();
}
return 0;
}
void USBXCI::StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId)
{
const HFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
std::string ncaFileName = this->GetFileEntryName(fileEntry);
printf("Retrieving %s\n", ncaFileName.c_str());
size_t ncaSize = fileEntry->fileSize;
tin::data::BufferedPlaceholderWriter bufferedPlaceholderWriter(contentStorage, placeholderId, ncaSize);
USBFuncArgs args;
args.xciName = m_xciName;
args.bufferedPlaceholderWriter = &bufferedPlaceholderWriter;
args.hfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
args.ncaSize = ncaSize;
thrd_t usbThread;
thrd_t writeThread;
thrd_create(&usbThread, USBThreadFunc, &args);
thrd_create(&writeThread, USBPlaceholderWriteFunc, &args);
u64 freq = armGetSystemTickFreq();
u64 startTime = armGetSystemTick();
size_t startSizeBuffered = 0;
double speed = 0.0;
while (!bufferedPlaceholderWriter.IsBufferDataComplete())
{
u64 newTime = armGetSystemTick();
if (newTime - startTime >= freq)
{
size_t newSizeBuffered = bufferedPlaceholderWriter.GetSizeBuffered();
double mbBuffered = (newSizeBuffered / 1000000.0) - (startSizeBuffered / 1000000.0);
double duration = ((double)(newTime - startTime) / (double)freq);
speed = mbBuffered / duration;
startTime = newTime;
startSizeBuffered = newSizeBuffered;
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
u64 downloadSizeMB = bufferedPlaceholderWriter.GetSizeBuffered() / 1000000;
int downloadProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeBuffered() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
inst::ui::setInstInfoText("Downloading " + inst::util::formatUrlString(ncaFileName) + " at " + std::to_string(speed).substr(0, std::to_string(speed).size()-4) + "MB/s");
inst::ui::setInstBarPerc((double)downloadProgress);
}
}
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
while (!bufferedPlaceholderWriter.IsPlaceholderComplete())
{
u64 installSizeMB = bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / 1000000;
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
inst::ui::setInstBarPerc((double)installProgress);
}
thrd_join(usbThread, NULL);
thrd_join(writeThread, NULL);
}
void USBXCI::BufferData(void* buf, off_t offset, size_t size)
{
printf("buffering 0x%lx-0x%lx", offset, offset + size);
tin::util::USBCmdHeader header = tin::util::USBCmdManager::SendFileRangeCmd(m_xciName, offset, size);
tin::util::USBRead(buf, header.dataSize);
}
}

View file

@ -44,7 +44,7 @@ namespace tin::install::xci
this->BufferData(m_headerBytes.data(), hfs0Offset, sizeof(HFS0BaseHeader));
printf("Base header: \n");
printBytes(nxlinkout, m_headerBytes.data(), sizeof(HFS0BaseHeader), true);
printBytes(m_headerBytes.data(), sizeof(HFS0BaseHeader), true);
// Retrieve full header
HFS0BaseHeader *header = reinterpret_cast<HFS0BaseHeader*>(m_headerBytes.data());
@ -56,7 +56,7 @@ namespace tin::install::xci
this->BufferData(m_headerBytes.data() + sizeof(HFS0BaseHeader), hfs0Offset + sizeof(HFS0BaseHeader), remainingHeaderSize);
printf("Base header: \n");
printBytes(nxlinkout, m_headerBytes.data(), sizeof(HFS0BaseHeader) + remainingHeaderSize, true);
printBytes(m_headerBytes.data(), sizeof(HFS0BaseHeader) + remainingHeaderSize, true);
// Find Secure partition
header = reinterpret_cast<HFS0BaseHeader*>(m_headerBytes.data());
@ -73,7 +73,7 @@ namespace tin::install::xci
this->BufferData(m_secureHeaderBytes.data(), m_secureHeaderOffset, sizeof(HFS0BaseHeader));
printf("Secure header: \n");
printBytes(nxlinkout, m_secureHeaderBytes.data(), sizeof(HFS0BaseHeader), true);
printBytes(m_secureHeaderBytes.data(), sizeof(HFS0BaseHeader), true);
if (this->GetSecureHeader()->magic != MAGIC_HFS0)
THROW_FORMAT("hfs0 magic doesn't match at 0x%lx\n", m_secureHeaderOffset);

View file

@ -38,7 +38,7 @@ SOFTWARE.
#include "ui/MainApplication.hpp"
#include "netInstall.hpp"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
#include "util/config.hpp"
#include "util/util.hpp"
#include "util/curl.hpp"
@ -113,7 +113,7 @@ namespace netInstStuff{
curl_global_cleanup();
}
void installNspLan(std::vector<std::string> ourUrlList, int ourStorage, std::vector<std::string> urlListAltNames)
void installTitleNet(std::vector<std::string> ourUrlList, int ourStorage, std::vector<std::string> urlListAltNames)
{
inst::util::initInstallServices();
if (appletGetAppletType() == AppletType_Application || appletGetAppletType() == AppletType_SystemApplication) appletBeginBlockingHomeButton(0);
@ -144,35 +144,25 @@ namespace netInstStuff{
try {
for (urlItr = 0; urlItr < ourUrlList.size(); urlItr++) {
printf("%s %s\n", "Install request from", ourUrlList[urlItr].c_str());
inst::ui::setTopInstInfoText("Installing " + urlNames[urlItr]);
tin::install::Install* installTask;
if (inst::curl::downloadToBuffer(ourUrlList[urlItr], 0x100, 0x103) == "HEAD") {
inst::ui::setTopInstInfoText("Installing " + urlNames[urlItr]);
tin::install::xci::HTTPXCI httpXCI(ourUrlList[urlItr]);
printf("%s %s\n", "Install request from", ourUrlList[urlItr].c_str());
tin::install::xci::XCIInstallTask install(httpXCI, m_destStorageId, inst::config::ignoreReqVers);
printf("%s\n", "Preparing installation");
inst::ui::setInstInfoText("Preparing installation...");
inst::ui::setInstBarPerc(0);
install.Prepare();
install.Begin();
auto httpXCI = new tin::install::xci::HTTPXCI(ourUrlList[urlItr]);
installTask = new tin::install::xci::XCIInstallTask(m_destStorageId, inst::config::ignoreReqVers, httpXCI);
} else {
inst::ui::setTopInstInfoText("Installing " + urlNames[urlItr]);
tin::install::nsp::HTTPNSP httpNSP(ourUrlList[urlItr]);
printf("%s %s\n", "Install request from", ourUrlList[urlItr].c_str());
tin::install::nsp::RemoteNSPInstall install(m_destStorageId, inst::config::ignoreReqVers, &httpNSP);
printf("%s\n", "Preparing installation");
inst::ui::setInstInfoText("Preparing installation...");
inst::ui::setInstBarPerc(0);
install.Prepare();
install.Begin();
auto httpNSP = new tin::install::nsp::HTTPNSP(ourUrlList[urlItr]);
installTask = new tin::install::nsp::RemoteNSPInstall(m_destStorageId, inst::config::ignoreReqVers, httpNSP);
}
printf("%s\n", "Preparing installation");
inst::ui::setInstInfoText("Preparing installation...");
inst::ui::setInstBarPerc(0);
installTask->Prepare();
installTask->Begin();
}
}
catch (std::exception& e) {

View file

@ -34,7 +34,7 @@ SOFTWARE.
#include "util/error.hpp"
#include "ui/MainApplication.hpp"
#include "nspInstall.hpp"
#include "sdInstall.hpp"
#include "util/config.hpp"
#include "util/util.hpp"
@ -66,8 +66,7 @@ namespace inst::ui {
mainApp->instpage->installInfoText->SetText("");
mainApp->instpage->installBar->SetProgress(0);
mainApp->instpage->installBar->SetVisible(false);
if (inst::config::gayMode) mainApp->instpage->awooImage->SetVisible(false);
else mainApp->instpage->awooImage->SetVisible(true);
mainApp->instpage->awooImage->SetVisible(!inst::config::gayMode);
mainApp->LoadLayout(mainApp->instpage);
mainApp->CallForRender();
}
@ -81,7 +80,7 @@ namespace nspInstStuff {
return(finishMessages[rand() % finishMessages.size()]);
}
void installNspFromFile(std::vector<std::filesystem::path> ourNspList, int whereToInstall)
void installNspFromFile(std::vector<std::filesystem::path> ourTitleList, int whereToInstall)
{
inst::util::initInstallServices();
if (appletGetAppletType() == AppletType_Application || appletGetAppletType() == AppletType_SystemApplication) appletBeginBlockingHomeButton(0);
@ -92,7 +91,7 @@ namespace nspInstStuff {
std::vector<std::string> oldNamesOfFiles = {};
if (whereToInstall) m_destStorageId = NcmStorageId_BuiltInUser;
unsigned int nspItr;
unsigned int titleItr;
std::vector<int> previousClockValues;
if (inst::config::overClock) {
@ -103,45 +102,43 @@ namespace nspInstStuff {
try
{
for (nspItr = 0; nspItr < ourNspList.size(); nspItr++) {
if (ourNspList[nspItr].extension() == ".xci" || ourNspList[nspItr].extension() == ".xcz") {
inst::ui::setTopInstInfoText("Installing " + inst::util::shortenString(ourNspList[nspItr].filename().string(), 42, true));
for (titleItr = 0; titleItr < ourTitleList.size(); titleItr++) {
inst::ui::setTopInstInfoText("Installing " + inst::util::shortenString(ourTitleList[titleItr].filename().string(), 42, true));
tin::install::Install* installTask;
tin::install::xci::LocalXCI xci(ourNspList[nspItr]);
tin::install::xci::XCIInstallTask task(xci, m_destStorageId, inst::config::ignoreReqVers);
inst::ui::mainApp->CreateShowDialog(ourTitleList[titleItr].filename().string(), ourTitleList[titleItr].filename().string(), {ourTitleList[titleItr].filename().string()}, true);
if (ourTitleList[titleItr].extension() == ".xci" || ourTitleList[titleItr].extension() == ".xcz") {
auto localXCI = new tin::install::xci::LocalXCI(ourTitleList[titleItr]);
installTask = new tin::install::xci::XCIInstallTask(m_destStorageId, inst::config::ignoreReqVers, localXCI);
printf("Preparing installation\n");
inst::ui::setInstInfoText("Preparing installation...");
inst::ui::setInstBarPerc(0);
task.Prepare();
installTask->Prepare();
task.Begin();
installTask->Begin();
} else {
inst::ui::setTopInstInfoText("Installing " + inst::util::shortenString(ourNspList[nspItr].filename().string(), 42, true));
if (ourNspList[nspItr].extension() == ".nsz") {
oldNamesOfFiles.push_back(ourNspList[nspItr]);
std::string newfilename = ourNspList[nspItr].string().substr(0, ourNspList[nspItr].string().find_last_of('.'))+"_temp.nsp";
rename(ourNspList[nspItr], newfilename);
if (ourTitleList[titleItr].extension() == ".nsz") {
oldNamesOfFiles.push_back(ourTitleList[titleItr]);
std::string newfilename = ourTitleList[titleItr].string().substr(0, ourTitleList[titleItr].string().find_last_of('.'))+"_temp.nsp";
rename(ourTitleList[titleItr], newfilename);
filesToBeRenamed.push_back(newfilename);
ourNspList[nspItr] = newfilename;
ourTitleList[titleItr] = newfilename;
}
std::string path = "@Sdcard://" + ourNspList[nspItr].string().erase(0, 6);
std::string path = "@Sdcard://" + ourTitleList[titleItr].string().erase(0, 6);
nx::fs::IFileSystem fileSystem;
fileSystem.OpenFileSystemWithId(path, FsFileSystemType_ApplicationPackage, 0);
tin::install::nsp::SimpleFileSystem simpleFS(fileSystem, "/", path + "/");
tin::install::nsp::NSPInstallTask task(simpleFS, m_destStorageId, inst::config::ignoreReqVers);
installTask = new tin::install::nsp::NSPInstallTask(simpleFS, m_destStorageId, inst::config::ignoreReqVers);
printf("Preparing installation\n");
inst::ui::setInstInfoText("Preparing installation...");
inst::ui::setInstBarPerc(0);
task.Prepare();
installTask->Prepare();
task.Begin();
installTask->Begin();
}
}
}
catch (std::exception& e)
@ -149,9 +146,9 @@ namespace nspInstStuff {
printf("Failed to install");
printf("%s", e.what());
fprintf(stdout, "%s", e.what());
inst::ui::setInstInfoText("Failed to install " + inst::util::shortenString(ourNspList[nspItr].filename().string(), 42, true));
inst::ui::setInstInfoText("Failed to install " + inst::util::shortenString(ourTitleList[titleItr].filename().string(), 42, true));
inst::ui::setInstBarPerc(0);
inst::ui::mainApp->CreateShowDialog("Failed to install " + inst::util::shortenString(ourNspList[nspItr].filename().string(), 42, true) + "!", "Partially installed contents can be removed from the System Settings applet.\n\n" + (std::string)e.what(), {"OK"}, true);
inst::ui::mainApp->CreateShowDialog("Failed to install " + inst::util::shortenString(ourTitleList[titleItr].filename().string(), 42, true) + "!", "Partially installed contents can be removed from the System Settings applet.\n\n" + (std::string)e.what(), {"OK"}, true);
nspInstalled = false;
}
@ -162,7 +159,7 @@ namespace nspInstStuff {
}
for (unsigned int i = 0; i < filesToBeRenamed.size(); i++) {
if (ourNspList.size() == 1) ourNspList[0] = oldNamesOfFiles[i];
if (ourTitleList.size() == 1) ourTitleList[0] = oldNamesOfFiles[i];
if (std::filesystem::exists(filesToBeRenamed[i])) {
rename(filesToBeRenamed[i].c_str(), oldNamesOfFiles[i].c_str());
}
@ -171,18 +168,18 @@ namespace nspInstStuff {
if(nspInstalled) {
inst::ui::setInstInfoText("Install complete");
inst::ui::setInstBarPerc(100);
if (ourNspList.size() > 1) {
if (ourTitleList.size() > 1) {
if (inst::config::deletePrompt) {
if(inst::ui::mainApp->CreateShowDialog(std::to_string(ourNspList.size()) + " files installed successfully! Delete them from the SD card?", "The original files aren't needed anymore after they've been installed", {"No","Yes"}, false) == 1) {
for (long unsigned int i = 0; i < ourNspList.size(); i++) {
if (std::filesystem::exists(ourNspList[i])) std::filesystem::remove(ourNspList[i]);
if(inst::ui::mainApp->CreateShowDialog(std::to_string(ourTitleList.size()) + " files installed successfully! Delete them from the SD card?", "The original files aren't needed anymore after they've been installed", {"No","Yes"}, false) == 1) {
for (long unsigned int i = 0; i < ourTitleList.size(); i++) {
if (std::filesystem::exists(ourTitleList[i])) std::filesystem::remove(ourTitleList[i]);
}
}
} else inst::ui::mainApp->CreateShowDialog(std::to_string(ourNspList.size()) + " files installed successfully!", nspInstStuff::finishedMessage(), {"OK"}, true);
} else inst::ui::mainApp->CreateShowDialog(std::to_string(ourTitleList.size()) + " files installed successfully!", nspInstStuff::finishedMessage(), {"OK"}, true);
} else {
if (inst::config::deletePrompt) {
if(inst::ui::mainApp->CreateShowDialog(inst::util::shortenString(ourNspList[0].filename().string(), 32, true) + " installed! Delete it from the SD card?", "The original file isn't needed anymore after it's been installed", {"No","Yes"}, false) == 1) if (std::filesystem::exists(ourNspList[0])) std::filesystem::remove(ourNspList[0]);
} else inst::ui::mainApp->CreateShowDialog(inst::util::shortenString(ourNspList[0].filename().string(), 42, true) + " installed!", nspInstStuff::finishedMessage(), {"OK"}, true);
if(inst::ui::mainApp->CreateShowDialog(inst::util::shortenString(ourTitleList[0].filename().string(), 32, true) + " installed! Delete it from the SD card?", "The original file isn't needed anymore after it's been installed", {"No","Yes"}, false) == 1) if (std::filesystem::exists(ourTitleList[0])) std::filesystem::remove(ourTitleList[0]);
} else inst::ui::mainApp->CreateShowDialog(inst::util::shortenString(ourTitleList[0].filename().string(), 42, true) + " installed!", nspInstStuff::finishedMessage(), {"OK"}, true);
}
}

View file

@ -8,12 +8,14 @@ namespace inst::ui {
this->mainPage = MainPage::New();
this->netinstPage = netInstPage::New();
this->nspinstPage = nspInstPage::New();
this->sdinstPage = sdInstPage::New();
this->usbinstPage = usbInstPage::New();
this->instpage = instPage::New();
this->optionspage = optionsPage::New();
this->mainPage->SetOnInput(std::bind(&MainPage::onInput, this->mainPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->netinstPage->SetOnInput(std::bind(&netInstPage::onInput, this->netinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->nspinstPage->SetOnInput(std::bind(&nspInstPage::onInput, this->nspinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->sdinstPage->SetOnInput(std::bind(&sdInstPage::onInput, this->sdinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->usbinstPage->SetOnInput(std::bind(&usbInstPage::onInput, this->usbinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->instpage->SetOnInput(std::bind(&instPage::onInput, this->instpage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->optionspage->SetOnInput(std::bind(&optionsPage::onInput, this->optionspage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->LoadLayout(this->mainPage);

View file

@ -21,7 +21,7 @@ namespace inst::ui {
this->appVersionText->SetColor(COLOR("#FFFFFFFF"));
this->butText = TextBlock::New(10, 678, "\ue0e0 Select \ue0e1 Exit ", 24);
this->butText->SetColor(COLOR("#FFFFFFFF"));
this->optionMenu = pu::ui::elm::Menu::New(0, 93, 1280, COLOR("#67000000"), 113, (567 / 113));
this->optionMenu = pu::ui::elm::Menu::New(0, 93, 1280, COLOR("#67000000"), 94, (567 / 94));
this->optionMenu->SetOnFocusColor(COLOR("#00000033"));
this->optionMenu->SetScrollbarColor(COLOR("#170909FF"));
this->installMenuItem = pu::ui::elm::MenuItem::New("Install from SD card");
@ -30,6 +30,9 @@ namespace inst::ui {
this->netInstallMenuItem = pu::ui::elm::MenuItem::New("Install over LAN or internet");
this->netInstallMenuItem->SetColor(COLOR("#FFFFFFFF"));
this->netInstallMenuItem->SetIcon("romfs:/cloud-download.png");
this->usbInstallMenuItem = pu::ui::elm::MenuItem::New("Install Over USB");
this->usbInstallMenuItem->SetColor(COLOR("#FFFFFFFF"));
this->usbInstallMenuItem->SetIcon("romfs:/usb-port.png");
this->sigPatchesMenuItem = pu::ui::elm::MenuItem::New("Manage signature patches");
this->sigPatchesMenuItem->SetColor(COLOR("#FFFFFFFF"));
this->sigPatchesMenuItem->SetIcon("romfs:/wrench.png");
@ -49,6 +52,7 @@ namespace inst::ui {
this->Add(this->butText);
this->optionMenu->AddItem(this->installMenuItem);
this->optionMenu->AddItem(this->netInstallMenuItem);
this->optionMenu->AddItem(this->usbInstallMenuItem);
this->optionMenu->AddItem(this->sigPatchesMenuItem);
this->optionMenu->AddItem(this->settingsMenuItem);
this->optionMenu->AddItem(this->exitMenuItem);
@ -60,9 +64,9 @@ namespace inst::ui {
}
void MainPage::installMenuItem_Click() {
mainApp->nspinstPage->drawMenuItems(true, "sdmc:/");
mainApp->nspinstPage->menu->SetSelectedIndex(0);
mainApp->LoadLayout(mainApp->nspinstPage);
mainApp->sdinstPage->drawMenuItems(true, "sdmc:/");
mainApp->sdinstPage->menu->SetSelectedIndex(0);
mainApp->LoadLayout(mainApp->sdinstPage);
}
void MainPage::netInstallMenuItem_Click() {
@ -73,6 +77,14 @@ namespace inst::ui {
mainApp->netinstPage->startNetwork();
}
void MainPage::usbInstallMenuItem_Click() {
if (inst::util::getUsbState() == 5) mainApp->usbinstPage->startUsb();
else {
mainApp->CreateShowDialog("No USB connection detected", "Plug in to a compatible device to install over USB", {"OK"}, true);
return;
}
}
void MainPage::sigPatchesMenuItem_Click() {
sig::installSigPatches();
}
@ -98,13 +110,16 @@ namespace inst::ui {
this->netInstallMenuItem_Click();
break;
case 2:
this->sigPatchesMenuItem_Click();
MainPage::usbInstallMenuItem_Click();
break;
case 3:
this->settingsMenuItem_Click();
MainPage::sigPatchesMenuItem_Click();
break;
case 4:
this->exitMenuItem_Click();
MainPage::settingsMenuItem_Click();
break;
case 5:
MainPage::exitMenuItem_Click();
break;
default:
break;

View file

@ -13,9 +13,6 @@
namespace inst::ui {
extern MainApplication *mainApp;
std::vector<std::string> netInstPage::ourUrls;
std::vector<std::string> netInstPage::selectedUrls;
std::vector<std::string> netInstPage::alternativeNames;
std::string lastUrl = "https://";
std::string lastFileID = "";
@ -66,7 +63,7 @@ namespace inst::ui {
}
}
void netInstPage::selectNsp(int selectedIndex) {
void netInstPage::selectTitle(int selectedIndex) {
if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/check-box-outline.png") {
for (long unsigned int i = 0; i < this->selectedUrls.size(); i++) {
if (this->selectedUrls[i] == this->ourUrls[selectedIndex]) this->selectedUrls.erase(this->selectedUrls.begin() + i);
@ -139,7 +136,7 @@ namespace inst::ui {
this->startNetwork();
return;
}
netInstStuff::installNspLan(this->selectedUrls, dialogResult, this->alternativeNames);
netInstStuff::installTitleNet(this->selectedUrls, dialogResult, this->alternativeNames);
return;
}
@ -148,7 +145,7 @@ namespace inst::ui {
mainApp->LoadLayout(mainApp->mainPage);
}
if ((Down & KEY_A) || (Up & KEY_TOUCH)) {
this->selectNsp(this->menu->GetSelectedIndex());
this->selectTitle(this->menu->GetSelectedIndex());
if (this->menu->GetItems().size() == 1 && this->selectedUrls.size() == 1) {
this->startInstall(false);
}
@ -158,14 +155,14 @@ namespace inst::ui {
else {
for (long unsigned int i = 0; i < this->menu->GetItems().size(); i++) {
if (this->menu->GetItems()[i]->GetIcon() == "romfs:/check-box-outline.png") continue;
else this->selectNsp(i);
else this->selectTitle(i);
}
this->drawMenuItems(false);
}
}
if (Down & KEY_PLUS) {
if (this->selectedUrls.size() == 0) {
this->selectNsp(this->menu->GetSelectedIndex());
this->selectTitle(this->menu->GetSelectedIndex());
this->startInstall(false);
return;
}

View file

@ -1,8 +1,8 @@
#include <filesystem>
#include "ui/MainApplication.hpp"
#include "ui/mainPage.hpp"
#include "ui/nspInstPage.hpp"
#include "nspInstall.hpp"
#include "ui/sdInstPage.hpp"
#include "sdInstall.hpp"
#include "util/util.hpp"
#include "util/config.hpp"
@ -11,12 +11,7 @@
namespace inst::ui {
extern MainApplication *mainApp;
std::vector<std::filesystem::path> nspInstPage::ourDirectories;
std::vector<std::filesystem::path> nspInstPage::ourFiles;
std::vector<std::filesystem::path> nspInstPage::selectedNsps;
std::filesystem::path nspInstPage::currentDir;
nspInstPage::nspInstPage() : Layout::Layout() {
sdInstPage::sdInstPage() : Layout::Layout() {
this->SetBackgroundColor(COLOR("#670000FF"));
if (std::filesystem::exists(inst::config::appDir + "/background.png")) this->SetBackgroundImage(inst::config::appDir + "/background.png");
else this->SetBackgroundImage("romfs:/background.jpg");
@ -43,8 +38,8 @@ namespace inst::ui {
this->Add(this->menu);
}
void nspInstPage::drawMenuItems(bool clearItems, std::filesystem::path ourPath) {
if (clearItems) this->selectedNsps = {};
void sdInstPage::drawMenuItems(bool clearItems, std::filesystem::path ourPath) {
if (clearItems) this->selectedTitles = {};
if (ourPath == "sdmc:") this->currentDir = std::filesystem::path(ourPath.string() + "/");
else this->currentDir = ourPath;
this->menu->ClearItems();
@ -75,8 +70,8 @@ namespace inst::ui {
auto ourEntry = pu::ui::elm::MenuItem::New(itm);
ourEntry->SetColor(COLOR("#FFFFFFFF"));
ourEntry->SetIcon("romfs:/checkbox-blank-outline.png");
for (long unsigned int i = 0; i < this->selectedNsps.size(); i++) {
if (this->selectedNsps[i] == file) {
for (long unsigned int i = 0; i < this->selectedTitles.size(); i++) {
if (this->selectedTitles[i] == file) {
ourEntry->SetIcon("romfs:/check-box-outline.png");
}
}
@ -84,7 +79,7 @@ namespace inst::ui {
}
}
void nspInstPage::followDirectory() {
void sdInstPage::followDirectory() {
int selectedIndex = this->menu->GetSelectedIndex();
int dirListSize = this->ourDirectories.size();
if (this->currentDir != "sdmc:/") {
@ -101,14 +96,14 @@ namespace inst::ui {
}
}
void nspInstPage::selectNsp(int selectedIndex) {
void sdInstPage::selectNsp(int selectedIndex) {
int dirListSize = this->ourDirectories.size();
if (this->currentDir != "sdmc:/") dirListSize++;
if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/check-box-outline.png") {
for (long unsigned int i = 0; i < this->selectedNsps.size(); i++) {
if (this->selectedNsps[i] == this->ourFiles[selectedIndex - dirListSize]) this->selectedNsps.erase(this->selectedNsps.begin() + i);
for (long unsigned int i = 0; i < this->selectedTitles.size(); i++) {
if (this->selectedTitles[i] == this->ourFiles[selectedIndex - dirListSize]) this->selectedTitles.erase(this->selectedTitles.begin() + i);
}
} else if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/checkbox-blank-outline.png") this->selectedNsps.push_back(this->ourFiles[selectedIndex - dirListSize]);
} else if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/checkbox-blank-outline.png") this->selectedTitles.push_back(this->ourFiles[selectedIndex - dirListSize]);
else {
this->followDirectory();
return;
@ -116,27 +111,27 @@ namespace inst::ui {
this->drawMenuItems(false, currentDir);
}
void nspInstPage::startInstall() {
void sdInstPage::startInstall() {
int dialogResult = -1;
if (this->selectedNsps.size() == 1) {
dialogResult = mainApp->CreateShowDialog("Where should " + inst::util::shortenString(std::filesystem::path(this->selectedNsps[0]).filename().string(), 32, true) + " be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
} else dialogResult = mainApp->CreateShowDialog("Where should the selected " + std::to_string(this->selectedNsps.size()) + " files be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
if (this->selectedTitles.size() == 1) {
dialogResult = mainApp->CreateShowDialog("Where should " + inst::util::shortenString(std::filesystem::path(this->selectedTitles[0]).filename().string(), 32, true) + " be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
} else dialogResult = mainApp->CreateShowDialog("Where should the selected " + std::to_string(this->selectedTitles.size()) + " files be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
if (dialogResult == -1) return;
nspInstStuff::installNspFromFile(this->selectedNsps, dialogResult);
nspInstStuff::installNspFromFile(this->selectedTitles, dialogResult);
}
void nspInstPage::onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos) {
void sdInstPage::onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos) {
if (Down & KEY_B) {
mainApp->LoadLayout(mainApp->mainPage);
}
if ((Down & KEY_A) || (Up & KEY_TOUCH)) {
this->selectNsp(this->menu->GetSelectedIndex());
if (this->ourFiles.size() == 1 && this->selectedNsps.size() == 1) {
if (this->ourFiles.size() == 1 && this->selectedTitles.size() == 1) {
this->startInstall();
}
}
if ((Down & KEY_Y)) {
if (this->selectedNsps.size() == this->ourFiles.size()) this->drawMenuItems(true, currentDir);
if (this->selectedTitles.size() == this->ourFiles.size()) this->drawMenuItems(true, currentDir);
else {
int topDir = 0;
if (this->currentDir != "sdmc:/") topDir++;
@ -151,10 +146,10 @@ namespace inst::ui {
inst::ui::mainApp->CreateShowDialog("Help", "Copy your NSP, NSZ, XCI, or XCZ files to your SD card, browse to and\nselect the ones you want to install, then press the Plus button.", {"OK"}, true);
}
if (Down & KEY_PLUS) {
if (this->selectedNsps.size() == 0 && this->menu->GetItems()[this->menu->GetSelectedIndex()]->GetIcon() == "romfs:/checkbox-blank-outline.png") {
if (this->selectedTitles.size() == 0 && this->menu->GetItems()[this->menu->GetSelectedIndex()]->GetIcon() == "romfs:/checkbox-blank-outline.png") {
this->selectNsp(this->menu->GetSelectedIndex());
}
if (this->selectedNsps.size() > 0) this->startInstall();
if (this->selectedTitles.size() > 0) this->startInstall();
}
}
}

127
source/ui/usbInstPage.cpp Executable file
View file

@ -0,0 +1,127 @@
#include "ui/usbInstPage.hpp"
#include "ui/MainApplication.hpp"
#include "util/util.hpp"
#include "util/config.hpp"
#include "usbInstall.hpp"
#define COLOR(hex) pu::ui::Color::FromHex(hex)
namespace inst::ui {
extern MainApplication *mainApp;
usbInstPage::usbInstPage() : Layout::Layout() {
this->SetBackgroundColor(COLOR("#670000FF"));
this->SetBackgroundImage("romfs:/background.jpg");
this->topRect = Rectangle::New(0, 0, 1280, 93, COLOR("#170909FF"));
this->infoRect = Rectangle::New(0, 93, 1280, 60, COLOR("#17090980"));
this->botRect = Rectangle::New(0, 660, 1280, 60, COLOR("#17090980"));
this->titleImage = Image::New(0, 0, "romfs:/logo.png");
this->appVersionText = TextBlock::New(480, 49, "v" + inst::config::appVersion, 22);
this->appVersionText->SetColor(COLOR("#FFFFFFFF"));
this->pageInfoText = TextBlock::New(10, 109, "", 30);
this->pageInfoText->SetColor(COLOR("#FFFFFFFF"));
this->butText = TextBlock::New(10, 678, "", 24);
this->butText->SetColor(COLOR("#FFFFFFFF"));
this->menu = pu::ui::elm::Menu::New(0, 154, 1280, COLOR("#FFFFFF00"), 84, (506 / 84));
this->menu->SetOnFocusColor(COLOR("#00000033"));
this->menu->SetScrollbarColor(COLOR("#17090980"));
this->infoImage = Image::New(460, 332, "romfs:/usb-connection-waiting.png");
this->Add(this->topRect);
this->Add(this->infoRect);
this->Add(this->botRect);
this->Add(this->titleImage);
this->Add(this->appVersionText);
this->Add(this->butText);
this->Add(this->pageInfoText);
this->Add(this->menu);
this->Add(this->infoImage);
}
void usbInstPage::drawMenuItems(bool clearItems) {
if (clearItems) this->selectedTitles = {};
this->menu->ClearItems();
for (auto& url: this->ourTitles) {
pu::String itm = inst::util::shortenString(inst::util::formatUrlString(url), 56, true);
auto ourEntry = pu::ui::elm::MenuItem::New(itm);
ourEntry->SetColor(COLOR("#FFFFFFFF"));
ourEntry->SetIcon("romfs:/checkbox-blank-outline.png");
for (long unsigned int i = 0; i < this->selectedTitles.size(); i++) {
if (this->selectedTitles[i] == url) {
ourEntry->SetIcon("romfs:/check-box-outline.png");
}
}
this->menu->AddItem(ourEntry);
}
}
void usbInstPage::selectTitle(int selectedIndex) {
if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/check-box-outline.png") {
for (long unsigned int i = 0; i < this->selectedTitles.size(); i++) {
if (this->selectedTitles[i] == this->ourTitles[selectedIndex]) this->selectedTitles.erase(this->selectedTitles.begin() + i);
}
} else this->selectedTitles.push_back(this->ourTitles[selectedIndex]);
this->drawMenuItems(false);
}
void usbInstPage::startUsb() {
this->pageInfoText->SetText("USB connection successful! Waiting for files to be sent...");
this->butText->SetText("");
this->menu->SetVisible(false);
this->menu->ClearItems();
this->infoImage->SetVisible(true);
mainApp->LoadLayout(mainApp->usbinstPage);
mainApp->CallForRender();
this->ourTitles = usbInstStuff::OnSelected();
if (!this->ourTitles.size()) {
mainApp->LoadLayout(mainApp->mainPage);
return;
} else {
this->pageInfoText->SetText("Select what files you want to install over USB, then press the Plus button!");
this->butText->SetText("\ue0e0 Select File \ue0e3 Select All \ue0ef Install File(s) \ue0e1 Cancel ");
this->drawMenuItems(true);
}
this->infoImage->SetVisible(false);
this->menu->SetVisible(true);
return;
}
void usbInstPage::startInstall() {
int dialogResult = -1;
if (this->selectedTitles.size() == 1) dialogResult = mainApp->CreateShowDialog("Where should " + selectedTitles[0] + " be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
else dialogResult = mainApp->CreateShowDialog("Where should the selected " + std::to_string(this->selectedTitles.size()) + " files be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
if (dialogResult == -1) return;
usbInstStuff::installTitleUsb(this->selectedTitles, dialogResult);
return;
}
void usbInstPage::onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos) {
if (Down & KEY_B) {
mainApp->LoadLayout(mainApp->mainPage);
}
if ((Down & KEY_A) || (Up & KEY_TOUCH)) {
this->selectTitle(this->menu->GetSelectedIndex());
if (this->menu->GetItems().size() == 1 && this->selectedTitles.size() == 1) {
this->startInstall();
}
}
if ((Down & KEY_Y)) {
if (this->selectedTitles.size() == this->menu->GetItems().size()) this->drawMenuItems(true);
else {
for (long unsigned int i = 0; i < this->menu->GetItems().size(); i++) {
if (this->menu->GetItems()[i]->GetIcon() == "romfs:/check-box-outline.png") continue;
else this->selectTitle(i);
}
this->drawMenuItems(false);
}
}
if (Down & KEY_PLUS) {
if (this->selectedTitles.size() == 0) {
this->selectTitle(this->menu->GetSelectedIndex());
this->startInstall();
return;
}
this->startInstall();
}
}
}

139
source/usbInstall.cpp Executable file
View file

@ -0,0 +1,139 @@
#include <string>
#include "usbInstall.hpp"
#include "install/usb_nsp.hpp"
#include "install/install_nsp_remote.hpp"
#include "util/usb_util.hpp"
#include "util/util.hpp"
#include "util/config.hpp"
#include "ui/usbInstPage.hpp"
#include "install/usb_xci.hpp"
#include "install/install_xci.hpp"
#include "sdInstall.hpp"
#include "ui/MainApplication.hpp"
namespace inst::ui {
extern MainApplication *mainApp;
void setUsbInfoText(std::string ourText){
mainApp->usbinstPage->pageInfoText->SetText(ourText);
mainApp->CallForRender();
}
}
namespace usbInstStuff {
struct TUSHeader
{
u32 magic; // TUL0 (Tinfoil Usb List 0)
u32 titleListSize;
u64 padding;
} PACKED;
std::vector<std::string> OnSelected() {
Result rc = 0;
while(true) {
rc = usbDsWaitReady(1000000);
if (R_SUCCEEDED(rc)) break;
else if ((rc & 0x3FFFFF) != 0xEA01)
return {};
}
TUSHeader header;
tin::util::USBRead(&header, sizeof(TUSHeader));
if (header.magic != 0x304C5554)
return {};
auto titleListBuf = std::make_unique<char[]>(header.titleListSize+1);
std::vector<std::string> titleNames;
memset(titleListBuf.get(), 0, header.titleListSize+1);
tin::util::USBRead(titleListBuf.get(), header.titleListSize);
// Split the string up into individual title names
std::stringstream titleNamesStream(titleListBuf.get());
std::string segment;
while (std::getline(titleNamesStream, segment, '\n')) {
titleNames.push_back(segment);
}
return titleNames;
}
void installTitleUsb(std::vector<std::string> ourTitleList, int ourStorage)
{
inst::util::initInstallServices();
inst::ui::loadInstallScreen();
bool nspInstalled = true;
NcmStorageId m_destStorageId = NcmStorageId_SdCard;
if (ourStorage) m_destStorageId = NcmStorageId_BuiltInUser;
unsigned int fileItr;
std::vector<std::string> fileNames;
for (long unsigned int i = 0; i < ourTitleList.size(); i++) {
fileNames.push_back(inst::util::shortenString(ourTitleList[i], 42, true));
}
/*
std::vector<int> previousClockValues;
if (inst::config::overClock) {
previousClockValues.push_back(inst::util::setClockSpeed(0, 1785000000)[0]);
previousClockValues.push_back(inst::util::setClockSpeed(1, 76800000)[0]);
previousClockValues.push_back(inst::util::setClockSpeed(2, 1600000000)[0]);
}
*/
try {
for (fileItr = 0; fileItr < ourTitleList.size(); fileItr++) {
inst::ui::setTopInstInfoText("Installing " + fileNames[fileItr]);
tin::install::Install* installTask;
if (ourTitleList[fileItr].compare(ourTitleList[fileItr].size() - 3, 2, "xc") == 0) {
auto usbXCI = new tin::install::xci::USBXCI(ourTitleList[fileItr]);
installTask = new tin::install::xci::XCIInstallTask(m_destStorageId, inst::config::ignoreReqVers, usbXCI);
} else {
auto usbNSP = new tin::install::nsp::USBNSP(ourTitleList[fileItr]);
installTask = new tin::install::nsp::RemoteNSPInstall(m_destStorageId, inst::config::ignoreReqVers, usbNSP);
}
printf("%s\n", "Preparing installation");
inst::ui::setInstInfoText("Preparing installation...");
inst::ui::setInstBarPerc(0);
installTask->Prepare();
installTask->Begin();
}
}
catch (std::exception& e) {
printf("Failed to install");
printf("%s", e.what());
fprintf(stdout, "%s", e.what());
inst::ui::setInstInfoText("Failed to install " + fileNames[fileItr]);
inst::ui::setInstBarPerc(0);
inst::ui::mainApp->CreateShowDialog("Failed to install " + fileNames[fileItr] + "!", "Partially installed contents can be removed from the System Settings applet.\n\n" + (std::string)e.what(), {"OK"}, true);
nspInstalled = false;
}
tin::util::USBCmdManager::SendExitCmd();
/*
if (previousClockValues.size() > 0) {
inst::util::setClockSpeed(0, previousClockValues[0]);
inst::util::setClockSpeed(1, previousClockValues[1]);
inst::util::setClockSpeed(2, previousClockValues[2]);
}
*/
if(nspInstalled) {
inst::ui::setInstInfoText("Install complete");
inst::ui::setInstBarPerc(100);
if (ourTitleList.size() > 1) inst::ui::mainApp->CreateShowDialog(std::to_string(ourTitleList.size()) + " files installed successfully!", nspInstStuff::finishedMessage(), {"OK"}, true);
else inst::ui::mainApp->CreateShowDialog(fileNames[0] + " installed!", nspInstStuff::finishedMessage(), {"OK"}, true);
}
printf("Done");
inst::ui::loadMainMenu();
inst::util::deinitInstallServices();
return;
}
}

View file

@ -29,69 +29,23 @@ SOFTWARE.
#include <arpa/inet.h>
#include <unistd.h>
#include <switch/runtime/nxlink.h>
#ifdef NXLINK_DEBUG
static int sock = -1;
#endif
FILE *nxlinkout;
int nxLinkInitialize(void)
void printBytes(u8 *bytes, size_t size, bool includeHeader)
{
#ifdef NXLINK_DEBUG
int ret = -1;
struct sockaddr_in srv_addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (!sock) {
return ret;
}
bzero(&srv_addr, sizeof srv_addr);
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr = __nxlink_host;
srv_addr.sin_port = htons(NXLINK_CLIENT_PORT);
ret = connect(sock, (struct sockaddr *) &srv_addr, sizeof(srv_addr));
if (ret != 0) {
close(sock);
return -1;
}
fflush(nxlinkout);
nxlinkout = fdopen(sock, "w");
setvbuf(nxlinkout, NULL, _IONBF, 0);
#endif
return 0;
}
void nxLinkExit(void)
{
#ifdef NXLINK_DEBUG
fclose(nxlinkout);
#endif
}
void printBytes(FILE* out, u8 *bytes, size_t size, bool includeHeader)
{
if (out == NULL)
return;
int count = 0;
if (includeHeader)
{
fprintf(out, "\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
fprintf(out, "-----------------------------------------------\n");
printf("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
printf("-----------------------------------------------\n");
}
for (int i = 0; i < size; i++)
{
fprintf(out, "%02x ", bytes[i]);
printf("%02x ", bytes[i]);
count++;
if ((count % 16) == 0)
fprintf(out, "\n");
printf("\n");
}
fprintf(out, "\n");
printf("\n");
}

82
source/util/usb_util.cpp Executable file
View file

@ -0,0 +1,82 @@
#include "util/usb_util.hpp"
#include "data/byte_buffer.hpp"
#include "debug.h"
#include "error.hpp"
namespace tin::util
{
void USBCmdManager::SendCmdHeader(u32 cmdId, size_t dataSize)
{
USBCmdHeader header;
header.magic = 0x30435554; // TUC0 (Tinfoil USB Command 0)
header.type = USBCmdType::REQUEST;
header.cmdId = cmdId;
header.dataSize = dataSize;
USBWrite(&header, sizeof(USBCmdHeader));
}
void USBCmdManager::SendExitCmd()
{
USBCmdManager::SendCmdHeader(0, 0);
}
USBCmdHeader USBCmdManager::SendFileRangeCmd(std::string nspName, u64 offset, u64 size)
{
struct FileRangeCmdHeader
{
u64 size;
u64 offset;
u64 nspNameLen;
u64 padding;
} fRangeHeader;
fRangeHeader.size = size;
fRangeHeader.offset = offset;
fRangeHeader.nspNameLen = nspName.size();
fRangeHeader.padding = 0;
USBCmdManager::SendCmdHeader(1, sizeof(FileRangeCmdHeader) + fRangeHeader.nspNameLen);
USBWrite(&fRangeHeader, sizeof(FileRangeCmdHeader));
USBWrite(nspName.c_str(), fRangeHeader.nspNameLen);
USBCmdHeader responseHeader;
USBRead(&responseHeader, sizeof(USBCmdHeader));
return responseHeader;
}
size_t USBRead(void* out, size_t len)
{
u8* tmpBuf = (u8*)out;
size_t sizeRemaining = len;
size_t tmpSizeRead = 0;
while (sizeRemaining)
{
tmpSizeRead = usbCommsRead(tmpBuf, sizeRemaining);
tmpBuf += tmpSizeRead;
sizeRemaining -= tmpSizeRead;
}
return len;
}
size_t USBWrite(const void* in, size_t len)
{
const u8 *bufptr = (const u8 *)in;
size_t cursize = len;
size_t tmpsize = 0;
while (cursize)
{
tmpsize = usbCommsWrite(bufptr, cursize);
//LOG_DEBUG("USB Bytes Written: \n");
//printBytes((u8*)bufptr, tmpsize, true);
bufptr += tmpsize;
cursize -= tmpsize;
}
return len;
}
}

View file

@ -28,10 +28,12 @@ namespace inst::util {
#ifdef __DEBUG__
nxlinkStdio();
#endif
usbCommsInitialize();
}
void deinitApp () {
socketExit();
usbCommsExit();
}
void initInstallServices() {
@ -255,4 +257,10 @@ namespace inst::util {
struct in_addr addr = {(in_addr_t) gethostid()};
return inet_ntoa(addr);
}
int getUsbState() {
u32 usbState = 0;
usbDsGetState(&usbState);
return usbState;
}
}