Added hid-mitm config UI

This commit is contained in:
WerWolv 2019-03-23 16:45:32 +01:00
parent 1b2ba3d7a4
commit 543152de3a
14 changed files with 332 additions and 159 deletions

BIN
KosmosToolbox-source.zip Normal file

Binary file not shown.

View File

@ -39,7 +39,7 @@ APP_AUTHOR := WerWolv
APP_VERSION := ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}
TARGET := $(notdir $(CURDIR))
OUTDIR := out
OUTDIR := out
BUILD := build
SOURCES := source source/ini
DATA := data

BIN
data/switch.bin Normal file

Binary file not shown.

View File

@ -26,7 +26,8 @@ enum gui_t {
GUI_INVALID,
GUI_MAIN,
GUI_SM_SELECT,
GUI_HEKATE
GUI_HEKATE,
GUI_HID_MITM
};
class Gui {

27
include/gui_hid_mitm.hpp Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include "gui.hpp"
#include <vector>
#include <string>
#include <map>
#include "utils.hpp"
#include "ini/ini.hpp"
class GuiHIDMitm : public Gui {
public:
GuiHIDMitm();
~GuiHIDMitm();
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
private:
Ini *m_configFile;
std::map<std::string, std::string> m_hidConfig;
s32 m_selectedButton = -1;
};

20
include/hid_extra.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <switch.h>
// hid-mitm communication
// Initializes the special hid-ipc by hid-mitm
Result hidExtraInitialize();
void hidExtraExit();
// Reloads hid-mitm rebind config
Result hidExtraReloadConfig();
// Pauses hid-mitm until the next config-reload
Result hidExtraPause();
bool hidMitmInstalled();
Result hidSysAcquireHomeButtonEventHandle(Event* event, bool autoclear);

View File

@ -1,29 +0,0 @@
#pragma once
#include <switch.h>
#include <string>
#include <map>
#include <memory>
#include <vector>
class Title {
public:
static inline std::map<u64, Title*> g_titles;
Title(FsSaveDataInfo& saveInfo);
~Title();
std::string getTitleName();
std::string getTitleAuthor();
std::string getTitleVersion();
u64 getTitleID();
static Result getSaveList(std::vector<FsSaveDataInfo> & saveInfoList);
private:
u64 m_titleID;
std::string m_titleName;
std::string m_titleAuthor;
std::string m_titleVersion;
u8 m_errorCode;
};

View File

@ -4,9 +4,10 @@
#include <string>
#include <vector>
#define LOADER_INI "sdmc:/atmosphere/loader.ini"
#define HEKATE_INI "sdmc:/bootloader/hekate_ipl.ini"
#define INI_PATH "sdmc:/bootloader/ini/"
#define LOADER_INI "sdmc:/atmosphere/loader.ini"
#define HEKATE_INI "sdmc:/bootloader/hekate_ipl.ini"
#define INI_PATH "sdmc:/bootloader/ini/"
#define HID_MITM_INI "sdmc:/modules/hid_mitm/config.ini"
typedef struct {
std::string name;

135
source/gui_hid_mitm.cpp Normal file
View File

@ -0,0 +1,135 @@
#include "gui_hid_mitm.hpp"
#include "button.hpp"
extern "C" {
#include "hid_extra.h"
}
#include <stdio.h>
#include <dirent.h>
#include <sstream>
#include <fstream>
#include <utility>
#include <math.h>
#include "threads.hpp"
#include "switch_bin.h"
const char * const keyNames[16] = { "KEY_A", "KEY_B", "KEY_X", "KEY_Y", "KEY_LSTICK", "KEY_RSTICK", "KEY_L", "KEY_R", "KEY_ZL", "KEY_ZR", "KEY_PLUS", "KEY_MINUS", "KEY_DLEFT", "KEY_DUP", "KEY_DRIGHT", "KEY_DDOWN" };
GuiHIDMitm::GuiHIDMitm() : Gui() {
hidExtraPause();
m_configFile = Ini::parseFile(HID_MITM_INI);
if (m_configFile != nullptr && m_configFile->findSection("player1") != nullptr) {
for (u8 i = 0; i < m_configFile->findSection("player1")->options.size(); i++) {
m_hidConfig[m_configFile->findSection("player1")->options[i]->key] = m_configFile->findSection("player1")->options[i]->value;
}
}
new Button(400, 400, Gui::g_framebuffer_width - 800, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated){
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 50, currTheme.textColor, "Touch to save config", ALIGNED_CENTER);
}, [&](u32 kdown, bool *isActivated){
if (kdown & KEY_A) {
Gui::g_nextGui = GUI_SM_SELECT;
hidExtraReloadConfig();
for (u16 i = 0; i < m_hidConfig.size(); i++)
m_configFile->findSection("player1")->options[i]->value = m_hidConfig[m_configFile->findSection("player1")->options[i]->key];
}
}, { -1, -1, -1, -1 }, false, []() -> bool {return true;});
}
GuiHIDMitm::~GuiHIDMitm() {
m_configFile->writeToFile(HID_MITM_INI);
Button::g_buttons.clear();
}
static std::string configToButtonName(std::string configName) {
if (configName == "KEY_A") return "\uE0E0";
else if (configName == "KEY_B") return "\uE0E1";
else if (configName == "KEY_X") return "\uE0E2";
else if (configName == "KEY_Y") return "\uE0E3";
else if (configName == "KEY_LSTICK") return "\uE104";
else if (configName == "KEY_RSTICK") return "\uE105";
else if (configName == "KEY_L") return "\uE0E4";
else if (configName == "KEY_R") return "\uE0E5";
else if (configName == "KEY_ZL") return "\uE0E6";
else if (configName == "KEY_ZR") return "\uE0E7";
else if (configName == "KEY_PLUS") return "\uE0EF";
else if (configName == "KEY_MINUS") return "\uE0F0";
else if (configName == "KEY_DLEFT") return "\uE0ED";
else if (configName == "KEY_DUP") return "\uE0EB";
else if (configName == "KEY_DRIGHT") return "\uE0EE";
else if (configName == "KEY_DDOWN") return "\uE0EC";
else return "\uE0E0";
}
void GuiHIDMitm::update() {
Gui::update();
}
void GuiHIDMitm::draw() {
Gui::beginDraw();
Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, currTheme.backgroundColor);
Gui::drawRectangle((u32)((Gui::g_framebuffer_width - 1220) / 2), 87, 1220, 1, currTheme.textColor);
Gui::drawRectangle((u32)((Gui::g_framebuffer_width - 1220) / 2), Gui::g_framebuffer_height - 73, 1220, 1, currTheme.textColor);
Gui::drawTextAligned(fontIcons, 70, 68, currTheme.textColor, "\uE130", ALIGNED_LEFT);
Gui::drawTextAligned(font24, 70, 58, currTheme.textColor, " Kosmos Toolbox", ALIGNED_LEFT);
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE122 Remap", ALIGNED_RIGHT);
Gui::drawImage(Gui::g_framebuffer_width / 2 - 500, Gui::g_framebuffer_height / 2 - 220, 1001, 441, switch_bin, IMAGE_MODE_RGBA32);
Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 250, COLOR_WHITE, "This menu remaps one joycon button to another. \n First press the button you want to remap and \n then the button to remap it to.", ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1100, 264, m_selectedButton == 0 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_A"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1066, 297, m_selectedButton == 1 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_B"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1066, 228, m_selectedButton == 2 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_X"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1031, 262, m_selectedButton == 3 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_Y"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 218, 264, m_selectedButton == 4 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_LSTICK"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1063, 381, m_selectedButton == 5 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_RSTICK"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 246, 135, m_selectedButton == 6 ? currTheme.selectedColor : currTheme.textColor, configToButtonName(m_hidConfig["KEY_L"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1038, 135, m_selectedButton == 7 ? currTheme.selectedColor : currTheme.textColor, configToButtonName(m_hidConfig["KEY_R"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 153, 163, m_selectedButton == 8 ? currTheme.selectedColor : currTheme.textColor, configToButtonName(m_hidConfig["KEY_ZL"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1132, 163, m_selectedButton == 9 ? currTheme.selectedColor : currTheme.textColor, configToButtonName(m_hidConfig["KEY_ZR"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 1023, 189, m_selectedButton == 10 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_PLUS"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 259, 186, m_selectedButton == 11 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_MINUS"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 184, 379, m_selectedButton == 12 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_DLEFT"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 218, 344, m_selectedButton == 13 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_DUP"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 253, 379, m_selectedButton == 14 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_DRIGHT"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 218, 414, m_selectedButton == 15 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_DDOWN"]).c_str(), ALIGNED_CENTER);
for(Button *btn : Button::g_buttons)
btn->draw(this);
Gui::endDraw();
}
void GuiHIDMitm::onInput(u32 kdown) {
if (m_selectedButton == -1) {
if (kdown <= KEY_DDOWN)
m_selectedButton = log2(kdown);
}
else {
if (kdown <= KEY_DDOWN) {
m_hidConfig[keyNames[m_selectedButton]] = keyNames[static_cast<u32>(log2(kdown))];
m_selectedButton = -1;
}
}
}
void GuiHIDMitm::onTouch(touchPosition &touch) {
for(Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiHIDMitm::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}

View File

@ -12,8 +12,6 @@ extern "C" {
#include "pm_dmnt.h"
}
#define SYS_FTPD_TID 0x420000000000000E
extern bool g_exitApplet;
bool exitDisabled = false;
@ -21,15 +19,6 @@ static std::vector<std::string> autobootNames;
static u16 currAutoBootEntryIndex;
GuiMain::GuiMain() : Gui() {
pmshellInitialize();
pmdmntInitialize();
pmdmntInitialize_mod();
u64 ftpd_pid;
pmdmntGetTitlePid(&ftpd_pid, SYS_FTPD_TID);
m_sysftpdRunning = ftpd_pid != 0;
Ini *ini = Ini::parseFile(LOADER_INI);
keyCharsToKey(ini->findSection("hbl_config")->findFirstOption("override_key")->value, &m_overrideKeyCombo, &m_overrideByDefault);
@ -133,10 +122,6 @@ GuiMain::GuiMain() : Gui() {
}
GuiMain::~GuiMain() {
pmshellExit();
pmdmntExit();
pmdmntExit_mod();
Button::g_buttons.clear();
}

View File

@ -15,6 +15,7 @@ using json = nlohmann::json;
extern "C" {
#include "pm_dmnt.h"
#include "hid_extra.h"
}
static u64 cur_val, lim_val;
@ -26,7 +27,7 @@ GuiSysmodule::GuiSysmodule() : Gui() {
pmdmntGetCurrentLimitInfo(&cur_val, &lim_val, 0, 0);
std::ifstream configFile("/switch/KosmosToolbox/config.json");
std::ifstream configFile("sdmc:/switch/KosmosToolbox/config.json");
if (configFile.fail()) {
Gui::g_nextGui = GUI_MAIN;
@ -59,7 +60,7 @@ GuiSysmodule::GuiSysmodule() : Gui() {
u32 sysmoduleCnt = this->m_sysmodules.size();
for (auto &sysmodule : this->m_sysmodules) {
new Button(100 + xOffset, 2503 + yOffset, 500, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated){
new Button(100 + xOffset, 250 + yOffset, 500, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated){
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, sysmodule.second.name.c_str(), ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 420, y + 50, this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end() ? currTheme.selectedColor : Gui::makeColor(0xB8, 0xBB, 0xC2, 0xFF), this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end() ? "On" : "Off", ALIGNED_LEFT);
}, [&](u32 kdown, bool *isActivated){
@ -127,12 +128,17 @@ void GuiSysmodule::draw() {
Gui::drawRectangle((u32)((Gui::g_framebuffer_width - 1220) / 2), Gui::g_framebuffer_height - 73, 1220, 1, currTheme.textColor);
Gui::drawTextAligned(fontIcons, 70, 68, currTheme.textColor, "\uE130", ALIGNED_LEFT);
Gui::drawTextAligned(font24, 70, 58, currTheme.textColor, " Kosmos Toolbox", ALIGNED_LEFT);
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE0E1 Back \uE0E0 Ok", ALIGNED_RIGHT);
if (hidMitmInstalled())
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE0E2 Key configuration \uE0E1 Back \uE0E0 Ok", ALIGNED_RIGHT);
else
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE0E1 Back \uE0E0 Ok", ALIGNED_RIGHT);
Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 150, currTheme.textColor, "Select the background services (sysmodules) that should be running. \n Because of memory restraints it may be not possible to start all services at once.", ALIGNED_CENTER);
for(Button *btn : Button::g_buttons)
btn->draw(this);
Gui::endDraw();
}
@ -145,6 +151,9 @@ void GuiSysmodule::onInput(u32 kdown) {
if (kdown & KEY_B)
Gui::g_nextGui = GUI_MAIN;
if (hidMitmInstalled() && kdown & KEY_X)
Gui::g_nextGui = GUI_HID_MITM;
}
void GuiSysmodule::onTouch(touchPosition &touch) {

115
source/hid_extra.c Normal file
View File

@ -0,0 +1,115 @@
#include <switch.h>
#include "hid_extra.h"
static Service hid_service;
static bool hidExtraPaused = false;
Result hidExtraReloadConfig()
{
IpcCommand c;
ipcInitialize(&c);
struct
{
u64 magic;
u64 cmd_id;
} * raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65000;
Result rc = serviceIpcDispatch(&hid_service);
if (R_SUCCEEDED(rc))
{
IpcParsedCommand r;
ipcParse(&r);
struct
{
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
hidExtraPaused = false;
svcSleepThread(1e9L/50); // Need to wait for hid to be polled again
return rc;
}
Result hidExtraPause()
{
// we don't want to spam hid-mitm unnecessarily
if(hidExtraPaused)
return 0;
IpcCommand c;
ipcInitialize(&c);
struct
{
u64 magic;
u64 cmd_id;
} * raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65001;
Result rc = serviceIpcDispatch(&hid_service);
if (R_SUCCEEDED(rc))
{
IpcParsedCommand r;
ipcParse(&r);
struct
{
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
svcSleepThread(1e9L/50); // Need to wait for hid to be polled again
hidExtraPaused = true;
return rc;
}
static bool hidExtraActive = false;
bool hidMitmInstalled()
{
return hidExtraActive;
}
Result hidExtraInitialize()
{
Result rc = smGetService(&hid_service, "hid");
if (R_SUCCEEDED(rc))
rc = hidExtraReloadConfig();
if (R_SUCCEEDED(rc))
hidExtraActive = true;
if (R_FAILED(rc))
serviceClose(&hid_service);
return rc;
}
void hidExtraExit()
{
if (hidExtraActive)
serviceClose(&hid_service);
hidExtraActive = false;
}

View File

@ -8,9 +8,13 @@
#include "gui_main.hpp"
#include "gui_sysmodule.hpp"
#include "gui_hekate.hpp"
#include "gui_hid_mitm.hpp"
#include "threads.hpp"
#include "title.hpp"
extern "C" {
#include "hid_extra.h"
}
static Gui *currGui = nullptr;
static bool updateThreadRunning = false;
@ -41,6 +45,8 @@ int main(int argc, char **argv){
socketInitializeDefault();
nxlinkStdio();
hidExtraInitialize();
setsysInitialize();
ColorSetId colorSetId;
setsysGetColorSetId(&colorSetId);
@ -50,14 +56,6 @@ int main(int argc, char **argv){
framebufferCreate(&Gui::g_fb_obj, nwindowGetDefault(), 1280, 720, PIXEL_FORMAT_RGBA_8888, 2);
framebufferMakeLinear(&Gui::g_fb_obj);
std::vector<FsSaveDataInfo> saveInfoList;
Title::getSaveList(saveInfoList);
for (auto saveInfo : saveInfoList) {
if (Title::g_titles.find(saveInfo.titleID) == Title::g_titles.end())
Title::g_titles.insert({(u64)saveInfo.titleID, new Title(saveInfo)});
}
Gui::g_nextGui = GUI_MAIN;
mutexInit(&mutexCurrGui);
@ -86,6 +84,9 @@ int main(int argc, char **argv){
case GUI_HEKATE:
currGui = new GuiHekate();
break;
case GUI_HID_MITM:
currGui = new GuiHIDMitm();
break;
}
mutexUnlock(&mutexCurrGui);
Gui::g_nextGui = GUI_INVALID;
@ -117,10 +118,16 @@ int main(int argc, char **argv){
}
}
if (currGui != nullptr)
delete currGui;
updateThreadRunning = false;
Threads::joinAll();
socketExit();
hidExtraExit();
framebufferClose(&Gui::g_fb_obj);
appletEndBlockingHomeButton();
return 0;
}

View File

@ -1,98 +0,0 @@
#include "title.hpp"
#include <cstring>
Title::Title(FsSaveDataInfo& saveInfo) {
Result rc=0;
std::unique_ptr<NsApplicationControlData> buf = std::make_unique<NsApplicationControlData>();
size_t outsize=0;
NacpLanguageEntry *langentry = nullptr;
if (buf == nullptr) {
m_errorCode = 1;
return;
}
memset(buf.get(), 0, sizeof(NsApplicationControlData));
rc = nsInitialize();
if (R_FAILED(rc)) {
m_errorCode = 2;
return;
}
rc = nsGetApplicationControlData(1, saveInfo.titleID, buf.get(), sizeof(NsApplicationControlData), &outsize);
if (R_FAILED(rc)) {
m_errorCode = 3;
return;
}
if (outsize < sizeof(buf->nacp)) {
m_errorCode = 4;
return;
}
rc = nacpGetLanguageEntry(&buf->nacp, &langentry);
if (R_FAILED(rc) || langentry == nullptr) {
m_errorCode = 5;
return;
}
m_titleName = std::string(langentry->name);
m_titleAuthor = std::string(langentry->author);
m_titleVersion = std::string(buf->nacp.version);
m_titleID = saveInfo.titleID;
nsExit();
}
Title::~Title() {
}
std::string Title::getTitleName() {
return m_titleName;
}
std::string Title::getTitleAuthor() {
return m_titleAuthor;
}
std::string Title::getTitleVersion() {
return m_titleVersion;
}
u64 Title::getTitleID() {
return m_titleID;
}
Result Title::getSaveList(std::vector<FsSaveDataInfo> & saveInfoList) {
Result rc=0;
FsSaveDataIterator iterator;
size_t total_entries=0;
FsSaveDataInfo info;
rc = fsOpenSaveDataIterator(&iterator, FsSaveDataSpaceId_NandUser);//See libnx fs.h.
if (R_FAILED(rc)) {
printf("fsOpenSaveDataIterator() failed: 0x%x\n", rc);
return rc;
}
rc = fsSaveDataIteratorRead(&iterator, &info, 1, &total_entries);//See libnx fs.h.
if (R_FAILED(rc))
return rc;
if (total_entries == 0)
return MAKERESULT(Module_Libnx, LibnxError_NotFound);
for (; R_SUCCEEDED(rc) && total_entries > 0;
rc = fsSaveDataIteratorRead(&iterator, &info, 1, &total_entries)) {
if (info.SaveDataType == FsSaveDataType_SaveData) {
saveInfoList.push_back(info);
}
}
fsSaveDataIteratorClose(&iterator);
return 0;
}