mirror of
https://github.com/cathery/sys-con.git
synced 2024-10-04 13:29:43 +00:00
Reimplement config loading behavior
This commit is contained in:
parent
1771b42ade
commit
9de5e87c4f
322
source/Sysmodule/source/config_handler.cpp
Normal file
322
source/Sysmodule/source/config_handler.cpp
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
#include "switch.h"
|
||||||
|
#include "config_handler.h"
|
||||||
|
#include "Controllers.h"
|
||||||
|
#include "ControllerConfig.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "ini.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "usb_module.h"
|
||||||
|
|
||||||
|
namespace syscon::config
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
ControllerConfig tempConfig;
|
||||||
|
GlobalConfig tempGlobalConfig;
|
||||||
|
RGBAColor tempColor;
|
||||||
|
char firmwarePath[100];
|
||||||
|
|
||||||
|
UTimer filecheckTimer;
|
||||||
|
Waiter filecheckTimerWaiter = waiterForUTimer(&filecheckTimer);
|
||||||
|
|
||||||
|
void ConfigChangedCheckThreadFunc(void *arg);
|
||||||
|
|
||||||
|
ams::os::StaticThread<0x2'000> g_config_changed_check_thread(&ConfigChangedCheckThreadFunc, nullptr, 0x3F);
|
||||||
|
|
||||||
|
bool is_config_changed_check_thread_running = false;
|
||||||
|
|
||||||
|
constexpr const char *keyNames[NUM_CONTROLLERBUTTONS]
|
||||||
|
{
|
||||||
|
"FACE_UP",
|
||||||
|
"FACE_RIGHT",
|
||||||
|
"FACE_DOWN",
|
||||||
|
"FACE_LEFT",
|
||||||
|
"LSTICK_CLICK",
|
||||||
|
"RSTICK_CLICK",
|
||||||
|
"LEFT_BUMPER",
|
||||||
|
"RIGHT_BUMPER",
|
||||||
|
"LEFT_TRIGGER",
|
||||||
|
"RIGHT_TRIGGER",
|
||||||
|
"BACK",
|
||||||
|
"START",
|
||||||
|
"DPAD_UP",
|
||||||
|
"DPAD_RIGHT",
|
||||||
|
"DPAD_DOWN",
|
||||||
|
"DPAD_LEFT",
|
||||||
|
"SYNC",
|
||||||
|
"GUIDE",
|
||||||
|
"TOUCHPAD",
|
||||||
|
};
|
||||||
|
|
||||||
|
ControllerButton StringToKey(const char *text)
|
||||||
|
{
|
||||||
|
for (int i = 0; i != NUM_CONTROLLERBUTTONS; ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(keyNames[i], text) == 0)
|
||||||
|
{
|
||||||
|
return static_cast<ControllerButton>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBAColor DecodeColorValue(const char *value)
|
||||||
|
{
|
||||||
|
RGBAColor color{255};
|
||||||
|
uint8_t counter = 0;
|
||||||
|
int charIndex = 0;
|
||||||
|
while (value[charIndex] != '\0')
|
||||||
|
{
|
||||||
|
if (charIndex == 0)
|
||||||
|
color.values[counter++] = atoi(value + charIndex++);
|
||||||
|
if (value[charIndex++] == ',')
|
||||||
|
{
|
||||||
|
color.values[counter++] = atoi(value + charIndex);
|
||||||
|
if (counter == 4)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseConfigLine(void *dummy, const char *section, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
if (strcmp(section, "global") == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "use_dualshock_2nd_generation") == 0)
|
||||||
|
{
|
||||||
|
tempGlobalConfig.dualshock4_productID = (strcmp(value, "true") ? PRODUCT_DUALSHOCK4_1X : PRODUCT_DUALSHOCK4_2X);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strncmp(name, "key_", 4) == 0)
|
||||||
|
{
|
||||||
|
ControllerButton button = StringToKey(name + 4);
|
||||||
|
ControllerButton buttonValue = StringToKey(value);
|
||||||
|
tempConfig.buttons[button] = buttonValue;
|
||||||
|
tempConfig.buttons[buttonValue] = button;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "left_stick_deadzone") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.leftStickDeadzonePercent = atoi(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "right_stick_deadzone") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.rightStickDeadzonePercent = atoi(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "left_stick_rotation") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.leftStickRotationDegrees = atoi(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "right_stick_rotation") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.rightStickRotationDegrees = atoi(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "trigger_deadzone") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.triggerDeadzonePercent = atoi(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "swap_dpad_and_lstick") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.swapDPADandLSTICK = (strcmp(value, "true") ? false : true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "firmware_path") == 0)
|
||||||
|
{
|
||||||
|
strcpy(firmwarePath, value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strncmp(name, "color_", 6) == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(name + 6, "body") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.bodyColor = DecodeColorValue(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name + 6, "buttons") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.buttonsColor = DecodeColorValue(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name + 6, "leftGrip") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.leftGripColor = DecodeColorValue(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name + 6, "rightGrip") == 0)
|
||||||
|
{
|
||||||
|
tempConfig.rightGripColor = DecodeColorValue(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(name + 6, "led") == 0)
|
||||||
|
{
|
||||||
|
tempColor = DecodeColorValue(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ReadFromConfig(const char *path)
|
||||||
|
{
|
||||||
|
tempConfig = ControllerConfig{};
|
||||||
|
for (int i = 0; i != NUM_CONTROLLERBUTTONS; ++i)
|
||||||
|
{
|
||||||
|
tempConfig.buttons[i] = NOT_SET;
|
||||||
|
}
|
||||||
|
return ini_parse(path, ParseConfigLine, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigChangedCheckThreadFunc(void *arg)
|
||||||
|
{
|
||||||
|
while (is_config_changed_check_thread_running)
|
||||||
|
{
|
||||||
|
if (R_SUCCEEDED(waitSingle(filecheckTimerWaiter, 0)))
|
||||||
|
{
|
||||||
|
if (config::CheckForFileChanges())
|
||||||
|
{
|
||||||
|
WriteToLog("File check succeeded! Loading configs...");
|
||||||
|
config::LoadAllConfigs();
|
||||||
|
usb::ReloadDualshock4Event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadGlobalConfig(const GlobalConfig &config)
|
||||||
|
{
|
||||||
|
config::globalConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadAllConfigs()
|
||||||
|
{
|
||||||
|
if (R_SUCCEEDED(ReadFromConfig(GLOBALCONFIG)))
|
||||||
|
{
|
||||||
|
LoadGlobalConfig(tempGlobalConfig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WriteToLog("Failed to read from global config!");
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ReadFromConfig(XBOXCONFIG)))
|
||||||
|
{
|
||||||
|
XboxController::LoadConfig(&tempConfig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WriteToLog("Failed to read from xbox orig config!");
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ReadFromConfig(XBOXONECONFIG)))
|
||||||
|
XboxOneController::LoadConfig(&tempConfig);
|
||||||
|
else
|
||||||
|
WriteToLog("Failed to read from xbox one config!");
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ReadFromConfig(XBOX360CONFIG)))
|
||||||
|
{
|
||||||
|
Xbox360Controller::LoadConfig(&tempConfig);
|
||||||
|
Xbox360WirelessController::LoadConfig(&tempConfig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WriteToLog("Failed to read from xbox 360 config!");
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ReadFromConfig(DUALSHOCK3CONFIG)))
|
||||||
|
Dualshock3Controller::LoadConfig(&tempConfig);
|
||||||
|
else
|
||||||
|
WriteToLog("Failed to read from dualshock 3 config!");
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ReadFromConfig(DUALSHOCK4CONFIG)))
|
||||||
|
Dualshock4Controller::LoadConfig(&tempConfig, tempColor);
|
||||||
|
else
|
||||||
|
WriteToLog("Failed to read from dualshock 4 config!");
|
||||||
|
}
|
||||||
|
bool CheckForFileChanges()
|
||||||
|
{
|
||||||
|
static u64 globalConfigLastModified;
|
||||||
|
static u64 xboxConfigLastModified;
|
||||||
|
static u64 xbox360ConfigLastModified;
|
||||||
|
static u64 xboxOneConfigLastModified;
|
||||||
|
static u64 dualshock3ConfigLastModified;
|
||||||
|
static u64 dualshock4ConfigLastModified;
|
||||||
|
|
||||||
|
// Maybe this should be called only once when initializing?
|
||||||
|
// I left it here in case this would cause issues when ejecting the SD card
|
||||||
|
FsFileSystem *fs = fsdevGetDeviceFileSystem("sdmc");
|
||||||
|
|
||||||
|
if (fs == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool filesChanged = false;
|
||||||
|
FsTimeStampRaw timestamp;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsGetFileTimeStampRaw(fs, GLOBALCONFIG, ×tamp)))
|
||||||
|
if (globalConfigLastModified != timestamp.modified)
|
||||||
|
{
|
||||||
|
globalConfigLastModified = timestamp.modified;
|
||||||
|
filesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsGetFileTimeStampRaw(fs, XBOXCONFIG, ×tamp)))
|
||||||
|
if (xboxConfigLastModified != timestamp.modified)
|
||||||
|
{
|
||||||
|
xboxConfigLastModified = timestamp.modified;
|
||||||
|
filesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsGetFileTimeStampRaw(fs, XBOX360CONFIG, ×tamp)))
|
||||||
|
if (xbox360ConfigLastModified != timestamp.modified)
|
||||||
|
{
|
||||||
|
xbox360ConfigLastModified = timestamp.modified;
|
||||||
|
filesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsGetFileTimeStampRaw(fs, XBOXONECONFIG, ×tamp)))
|
||||||
|
if (xboxOneConfigLastModified != timestamp.modified)
|
||||||
|
{
|
||||||
|
xboxOneConfigLastModified = timestamp.modified;
|
||||||
|
filesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsGetFileTimeStampRaw(fs, DUALSHOCK3CONFIG, ×tamp)))
|
||||||
|
if (dualshock3ConfigLastModified != timestamp.modified)
|
||||||
|
{
|
||||||
|
dualshock3ConfigLastModified = timestamp.modified;
|
||||||
|
filesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsGetFileTimeStampRaw(fs, DUALSHOCK4CONFIG, ×tamp)))
|
||||||
|
if (dualshock4ConfigLastModified != timestamp.modified)
|
||||||
|
{
|
||||||
|
dualshock4ConfigLastModified = timestamp.modified;
|
||||||
|
filesChanged = true;
|
||||||
|
}
|
||||||
|
return filesChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Initialize()
|
||||||
|
{
|
||||||
|
config::LoadAllConfigs();
|
||||||
|
utimerCreate(&filecheckTimer, 1e+9L, TimerType_Repeating);
|
||||||
|
utimerStart(&filecheckTimer);
|
||||||
|
is_config_changed_check_thread_running = true;
|
||||||
|
return g_config_changed_check_thread.Start().GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Exit()
|
||||||
|
{
|
||||||
|
is_config_changed_check_thread_running = true;
|
||||||
|
utimerStop(&filecheckTimer);
|
||||||
|
g_config_changed_check_thread.CancelSynchronization();
|
||||||
|
g_config_changed_check_thread.Join();
|
||||||
|
}
|
||||||
|
}
|
31
source/Sysmodule/source/config_handler.h
Normal file
31
source/Sysmodule/source/config_handler.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ControllerTypes.h"
|
||||||
|
|
||||||
|
#define CONFIG_PATH "/config/sys-con/"
|
||||||
|
|
||||||
|
#define GLOBALCONFIG CONFIG_PATH "config_global.ini"
|
||||||
|
#define XBOXCONFIG CONFIG_PATH "config_xboxorig.ini"
|
||||||
|
#define XBOX360CONFIG CONFIG_PATH "config_xbox360.ini"
|
||||||
|
#define XBOXONECONFIG CONFIG_PATH "config_xboxone.ini"
|
||||||
|
#define DUALSHOCK3CONFIG CONFIG_PATH "config_dualshock3.ini"
|
||||||
|
#define DUALSHOCK4CONFIG CONFIG_PATH "config_dualshock4.ini"
|
||||||
|
|
||||||
|
namespace syscon::config
|
||||||
|
{
|
||||||
|
struct GlobalConfig
|
||||||
|
{
|
||||||
|
uint16_t dualshock4_productID;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline GlobalConfig globalConfig
|
||||||
|
{
|
||||||
|
.dualshock4_productID = PRODUCT_DUALSHOCK4_1X,
|
||||||
|
};
|
||||||
|
|
||||||
|
void LoadGlobalConfig(const GlobalConfig &config);
|
||||||
|
void LoadAllConfigs();
|
||||||
|
bool CheckForFileChanges();
|
||||||
|
|
||||||
|
Result Initialize();
|
||||||
|
void Exit();
|
||||||
|
};
|
@ -1,11 +1,10 @@
|
|||||||
#include "switch.h"
|
#include "switch.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mainLoop.h"
|
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
#include "usb_module.h"
|
#include "usb_module.h"
|
||||||
#include "controller_handler.h"
|
#include "controller_handler.h"
|
||||||
#include "configFile.h"
|
#include "config_handler.h"
|
||||||
|
|
||||||
#define APP_VERSION "0.6.0"
|
#define APP_VERSION "0.6.0"
|
||||||
|
|
||||||
@ -78,11 +77,10 @@ using namespace syscon;
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
WriteToLog("\n\nNew sysmodule session started on version " APP_VERSION);
|
WriteToLog("\n\nNew sysmodule session started on version " APP_VERSION);
|
||||||
|
config::Initialize();
|
||||||
handler::Initialize();
|
handler::Initialize();
|
||||||
usb::Initialize();
|
usb::Initialize();
|
||||||
|
|
||||||
LoadAllConfigs();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
svcSleepThread(1e+8L);
|
svcSleepThread(1e+8L);
|
||||||
@ -90,4 +88,5 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
usb::Exit();
|
usb::Exit();
|
||||||
handler::Exit();
|
handler::Exit();
|
||||||
|
config::Exit();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "switch.h"
|
#include "switch.h"
|
||||||
#include "usb_module.h"
|
#include "usb_module.h"
|
||||||
#include "controller_handler.h"
|
#include "controller_handler.h"
|
||||||
|
#include "config_handler.h"
|
||||||
|
|
||||||
|
|
||||||
#include "SwitchUSBDevice.h"
|
#include "SwitchUSBDevice.h"
|
||||||
@ -22,7 +23,7 @@ namespace syscon::usb
|
|||||||
void UsbInterfaceChangeThreadFunc(void *arg);
|
void UsbInterfaceChangeThreadFunc(void *arg);
|
||||||
|
|
||||||
ams::os::StaticThread<0x2'000> g_usb_event_thread(&UsbEventThreadFunc, nullptr, 0x20);
|
ams::os::StaticThread<0x2'000> g_usb_event_thread(&UsbEventThreadFunc, nullptr, 0x20);
|
||||||
ams::os::StaticThread<0x2'000> g_usb_interface_change_thread(&UsbInterfaceChangeThreadFunc, nullptr, 0x20);
|
ams::os::StaticThread<0x2'000> g_usb_interface_change_thread(&UsbInterfaceChangeThreadFunc, nullptr, 0x21);
|
||||||
|
|
||||||
bool is_usb_event_thread_running = false;
|
bool is_usb_event_thread_running = false;
|
||||||
bool is_usb_interface_change_thread_running = false;
|
bool is_usb_interface_change_thread_running = false;
|
||||||
@ -157,10 +158,10 @@ namespace syscon::usb
|
|||||||
|
|
||||||
Result CreateDualshock4AvailableEvent()
|
Result CreateDualshock4AvailableEvent()
|
||||||
{
|
{
|
||||||
constexpr UsbHsInterfaceFilter filter {
|
const UsbHsInterfaceFilter filter{
|
||||||
.Flags = UsbHsInterfaceFilterFlags_idVendor | UsbHsInterfaceFilterFlags_idProduct,
|
.Flags = UsbHsInterfaceFilterFlags_idVendor | UsbHsInterfaceFilterFlags_idProduct,
|
||||||
.idVendor = VENDOR_SONY,
|
.idVendor = VENDOR_SONY,
|
||||||
.idProduct = PRODUCT_DUALSHOCK4_2X,
|
.idProduct = config::globalConfig.dualshock4_productID,
|
||||||
};
|
};
|
||||||
return usbHsCreateInterfaceAvailableEvent(&g_usbDualshock4Event, true, Dualshock4EventIndex, &filter);
|
return usbHsCreateInterfaceAvailableEvent(&g_usbDualshock4Event, true, Dualshock4EventIndex, &filter);
|
||||||
}
|
}
|
||||||
@ -210,4 +211,10 @@ namespace syscon::usb
|
|||||||
|
|
||||||
handler::Reset();
|
handler::Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ReloadDualshock4Event()
|
||||||
|
{
|
||||||
|
usbHsDestroyInterfaceAvailableEvent(&g_usbDualshock4Event, Dualshock4EventIndex);
|
||||||
|
return CreateDualshock4AvailableEvent();
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,4 +8,6 @@ namespace syscon::usb {
|
|||||||
|
|
||||||
Result Enable();
|
Result Enable();
|
||||||
void Disable();
|
void Disable();
|
||||||
|
|
||||||
|
Result ReloadDualshock4Event();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user