idk validation isn't working...

This commit is contained in:
HookedBehemoth 2019-11-17 16:01:06 +01:00
parent 0910512d24
commit fe18b58f9a
24 changed files with 582 additions and 86 deletions

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

@ -40,12 +40,12 @@ 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;
virtual void RetrieveHeader();
virtual const PFS0BaseHeader* GetBaseHeader();
virtual void BufferNCAHeader(void* buf, NcmContentId placeholderId);
virtual u64 GetDataOffset();
virtual const PFS0FileEntry* GetFileEntry(unsigned int index);

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

@ -3,6 +3,7 @@
#include "ui/mainPage.hpp"
#include "ui/netInstPage.hpp"
#include "ui/nspInstPage.hpp"
#include "ui/usbInstPage.hpp"
#include "ui/instPage.hpp"
#include "ui/optionsPage.hpp"
@ -15,6 +16,7 @@ namespace inst::ui {
MainPage::Ref mainPage;
netInstPage::Ref netinstPage;
nspInstPage::Ref nspinstPage;
usbInstPage::Ref usbinstPage;
instPage::Ref instpage;
optionsPage::Ref optionspage;
};

View file

@ -0,0 +1,30 @@
#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:
static std::vector<std::string> ourNsps;
static std::vector<std::string> selectedNsps;
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;
void drawMenuItems(bool clearItems);
void selectNsp(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 installNspUsb(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

@ -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

@ -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);
@ -133,7 +126,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);
}
@ -150,7 +143,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);
//consoleUpdate(NULL);
}

View file

@ -230,9 +230,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)
{
@ -249,9 +249,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
{
@ -263,7 +263,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

@ -164,7 +164,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));
}
@ -186,7 +186,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

@ -69,7 +69,6 @@ namespace tin::install::nsp
cnmtContentInfo.content_id = cnmtContentId;
*(u64*)&cnmtContentInfo.size = cnmtNcaSize & 0xFFFFFFFFFFFF;
cnmtContentInfo.content_type = NcmContentType_Meta;
//consoleUpdate(NULL);
return { tin::util::GetContentMetaFromNCA(cnmtNCAFullPath), cnmtContentInfo };
}
@ -115,7 +114,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

@ -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)
@ -134,6 +134,13 @@ namespace tin::install::nsp
return reinterpret_cast<PFS0BaseHeader*>(m_headerBytes.data());
}
void RemoteNSP::BufferNCAHeader(void* buf, NcmContentId placeholderId)
{
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
u64 pfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
this->BufferData(buf, pfs0Offset, 0xc00);
}
u64 RemoteNSP::GetDataOffset()
{
if (m_headerBytes.empty())

145
source/install/usb_nsp.cpp Normal file
View file

@ -0,0 +1,145 @@
#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"
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)
{
LOG_DEBUG("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);
LOG_DEBUG("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);
}
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, "%");
}
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);
}
}

View file

@ -64,8 +64,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();
}

View file

@ -9,11 +9,13 @@ namespace inst::ui {
this->mainPage = MainPage::New();
this->netinstPage = netInstPage::New();
this->nspinstPage = nspInstPage::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->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

@ -116,5 +116,8 @@ namespace inst::ui {
this->eggImage->SetVisible(false);
if (!inst::config::gayMode) this->awooImage->SetVisible(true);
}
if (Down & KEY_Y) {
mainApp->usbinstPage->startUsb();
}
}
}

127
source/ui/usbInstPage.cpp Normal 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;
std::vector<std::string> usbInstPage::ourNsps;
std::vector<std::string> usbInstPage::selectedNsps;
usbInstPage::usbInstPage() : Layout::Layout() {
usbCommsInitialize();
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->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);
}
void usbInstPage::drawMenuItems(bool clearItems) {
if (clearItems) usbInstPage::selectedNsps = {};
this->menu->ClearItems();
for (auto& url: usbInstPage::ourNsps) {
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 < usbInstPage::selectedNsps.size(); i++) {
if (usbInstPage::selectedNsps[i] == url) {
ourEntry->SetIcon("romfs:/check-box-outline.png");
}
}
this->menu->AddItem(ourEntry);
}
}
void usbInstPage::selectNsp(int selectedIndex) {
if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/check-box-outline.png") {
for (long unsigned int i = 0; i < usbInstPage::selectedNsps.size(); i++) {
if (usbInstPage::selectedNsps[i] == usbInstPage::ourNsps[selectedIndex]) usbInstPage::selectedNsps.erase(usbInstPage::selectedNsps.begin() + i);
}
} else usbInstPage::selectedNsps.push_back(usbInstPage::ourNsps[selectedIndex]);
usbInstPage::drawMenuItems(false);
}
void usbInstPage::startUsb() {
this->pageInfoText->SetText("");
this->butText->SetText("\ue0e2 Help \ue0e1 Cancel ");
this->menu->SetVisible(false);
this->menu->ClearItems();
mainApp->LoadLayout(mainApp->usbinstPage);
usbInstPage::ourNsps = usbInstStuff::OnSelected();
if (!usbInstPage::ourNsps.size()) {
mainApp->LoadLayout(mainApp->mainPage);
return;
} else {
this->pageInfoText->SetText("Select what files you want to install from the usb, then press the Plus button!");
this->butText->SetText("\ue0e0 Select File \ue0e3 Select All \ue0ef Install File(s) \ue0e1 Cancel ");
usbInstPage::drawMenuItems(true);
}
this->menu->SetVisible(true);
return;
}
void usbInstPage::startInstall() {
int dialogResult = -1;
if (usbInstPage::selectedNsps.size() == 1) dialogResult = mainApp->CreateShowDialog("Where should " + selectedNsps[0] + " be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
else dialogResult = mainApp->CreateShowDialog("Where should the selected " + std::to_string(usbInstPage::selectedNsps.size()) + " files be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
if (dialogResult == -1) return;
usbInstStuff::installNspUsb(usbInstPage::selectedNsps, dialogResult);
return;
}
void usbInstPage::onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos) {
if (Down & KEY_B) {
usbCommsExit();
mainApp->LoadLayout(mainApp->mainPage);
}
if ((Down & KEY_A) || (Up & KEY_TOUCH)) {
usbInstPage::selectNsp(this->menu->GetSelectedIndex());
if (this->menu->GetItems().size() == 1 && usbInstPage::selectedNsps.size() == 1) {
usbInstPage::startInstall();
}
}
if ((Down & KEY_Y)) {
if (usbInstPage::selectedNsps.size() == this->menu->GetItems().size()) usbInstPage::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 usbInstPage::selectNsp(i);
}
usbInstPage::drawMenuItems(false);
}
}
if (Down & KEY_PLUS) {
if (usbInstPage::selectedNsps.size() == 0) {
usbInstPage::selectNsp(this->menu->GetSelectedIndex());
usbInstPage::startInstall();
return;
}
usbInstPage::startInstall();
}
}
}

95
source/usbInstall.cpp Normal file
View file

@ -0,0 +1,95 @@
#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 "nspInstall.hpp"
#include "ui/MainApplication.hpp"
namespace inst::ui {
extern MainApplication *mainApp;
}
namespace usbInstStuff {
struct TUSHeader
{
u32 magic; // TUL0 (Tinfoil Usb List 0)
u32 nspListSize;
u64 padding;
} PACKED;
std::vector<std::string> OnSelected() {
Result rc = 0;
inst::ui::setInstInfoText("waiting for usb...\n");
while(true) {
hidScanInput();
if (hidKeysDown(CONTROLLER_P1_AUTO) & KEY_B)
break;
rc = usbDsWaitReady(1000000);
if (R_SUCCEEDED(rc)) break;
else if ((rc & 0x3FFFFF) != 0xEA01)
return {};
}
inst::ui::setInstInfoText("USB install ready!\n");
TUSHeader header;
tin::util::USBRead(&header, sizeof(TUSHeader));
if (header.magic != 0x304C5554)
return {};
auto nspListBuf = std::make_unique<char[]>(header.nspListSize+1);
std::vector<std::string> nspNames;
memset(nspListBuf.get(), 0, header.nspListSize+1);
tin::util::USBRead(nspListBuf.get(), header.nspListSize);
// Split the string up into individual nsp names
std::stringstream nspNameStream(nspListBuf.get());
std::string segment;
std::string nspExt = ".nsp";
std::string nszExt = ".nsz";
while (std::getline(nspNameStream, segment, '\n')) {
if (segment.compare(segment.size() - nspExt.size(), nspExt.size(), nspExt) == 0 || segment.compare(segment.size() - nszExt.size(), nszExt.size(), nszExt) == 0)
nspNames.push_back(segment);
}
return nspNames;
}
void installNspUsb(std::vector<std::string> ourNspList, int ourStorage) {
inst::util::initInstallServices();
inst::ui::loadInstallScreen();
NcmStorageId m_destStorageId = NcmStorageId_SdCard;
if (ourStorage) m_destStorageId = NcmStorageId_BuiltInUser;
for (std::string nspName: ourNspList) {
try {
tin::install::nsp::USBNSP usbNSP(nspName);
inst::ui::setInstInfoText("installing" + nspName);
tin::install::nsp::RemoteNSPInstall install(m_destStorageId, inst::config::ignoreReqVers, &usbNSP);
install.Prepare();
install.Begin();
} catch(...) {
int rc = inst::ui::mainApp->CreateShowDialog("install failed", nspName + " failed\ndo you want to continue?", {"yes", "cancel"}, true);
if (rc == 1)
break;
}
}
tin::util::USBCmdManager::SendExitCmd();
inst::ui::setInstInfoText("finished installation");
inst::ui::mainApp->CreateShowDialog("Done", "Back to menu?", {"ok"}, true);
inst::ui::loadMainMenu();
inst::util::deinitInstallServices();
}
}

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 Normal 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;
}
}