1
0
mirror of https://github.com/cathery/sys-con.git synced 2025-03-12 22:14:30 +00:00

Merge branch 'master' into dev

yes
This commit is contained in:
cathery 2020-07-04 10:23:45 +03:00
commit 9cc04f8876
13 changed files with 96 additions and 62 deletions

View File

@ -3,7 +3,7 @@
{
"name": "AArch64 libnx",
"includePath": [
"${DEVKITPRO}/devkitA64/lib/gcc/aarch64-none-elf/9.2.0/include",
"${DEVKITPRO}/devkitA64/lib/gcc/aarch64-none-elf/10.1.0/include",
"${DEVKITPRO}/devkitA64/aarch64-none-elf/include",
"${DEVKITPRO}/portlibs/switch/include",
"${DEVKITPRO}/libnx/include",
@ -17,12 +17,14 @@
"SWITCH",
"__SWITCH__",
"ATMOSPHERE_BOARD_NINTENDO_SWITCH",
"ATMOSPHERE_IS_STRATOSPHERE"
"ATMOSPHERE_IS_STRATOSPHERE",
"ATMOSPHERE_ARCH_ARM64",
"ATMOSPHERE_OS_HORIZON"
],
"compilerPath": "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "gcc-x64"
"cStandard": "gnu18",
"cppStandard": "gnu++20",
"intelliSenseMode": "gcc-arm64"
}
],
"version": 4

View File

@ -58,6 +58,7 @@
"map": "cpp",
"set": "cpp",
"mutex": "cpp",
"shared_mutex": "cpp"
"shared_mutex": "cpp",
"span": "cpp"
},
}

2
.vscode/tasks.json vendored
View File

@ -5,7 +5,7 @@
"label": "Build Release",
"type": "shell",
"promptOnClose": true,
"command": "make -j8",
"command": "make -j3",
"presentation": {
"reveal": "always",
"panel": "shared"

View File

@ -1,25 +1,19 @@
# sys-con
#### A Nintedo Switch sysmodule for third-party controller support. No man-in-the-middle required!
###### \[Switch FW 5.0.0+\]
#### A Nintendo Switch custom sysmodule for third-party controller support. No man-in-the-middle required!
###### \[Switch FW 5.0.0+\] [Atmosphère only]
## Description
This sysmodule aims to provide complete functionality for most popular game controllers not supported by Nintendo Switch.
At the current moment, **only USB connection** is supported.
At the current moment, **only USB connection** is supported.
This app is missing a lot of features. For more information, see the [issues page](https://github.com/cathery/sys-con/issues).
### ⚠ I can't support your generic 3rd party HID controller yet.
It is a limitation of the firmware and I'm looking to work around it.
### ⚠ If you get the error 2003-0008 (0x1003):
You're running too many sysmodules. Disable other memory demanding sysmodules like sys-ftpd or ldn_mitm.
### ⚠ If you have a second-generation Dualshock 4:
You need to go to `sdmc:/config/sys-con/config_global.ini` and change the value of `use_dualshock_2nd_generation` from **false** to **true**.
## Install
@ -45,9 +39,13 @@ sys-con comes with a config folder located at `sdmc:/config/sys-con/`. It contai
## Building (For developers)
Like all other switch projects, you need to have [devkitPro](https://switchbrew.org/wiki/Setting_up_Development_Environment) set up on your system.
Don't download the project as ZIP. It doesn't copy the submodules correctly and you will be left with empty folders.
This project uses libnx version 3.1.0 or later.
Instead, clone the repository **recursively** using any git client you have. (Git Bash, Git GUI, Github Desktop, etc.)
Like all other switch projects, you need to have [devkitA64](https://switchbrew.org/wiki/Setting_up_Development_Environment) set up on your system.
This project uses libnx version **3.3.0**.
If you have **Visual Studio Code**, you can open the project as a folder and run the build tasks from inside the program. It also has Intellisense configured for switch development, if you have DEVKITPRO correctly defined in your environment variables. Handy!

View File

@ -37,30 +37,34 @@ void SwitchVirtualGamepadHandler::OutputThreadLoop(void *handler)
Result SwitchVirtualGamepadHandler::InitInputThread()
{
R_TRY(m_inputThread.Initialize(&SwitchVirtualGamepadHandler::InputThreadLoop, this, 0x30).GetValue());
m_inputThreadIsRunning = true;
return m_inputThread.Start().GetValue();
R_ABORT_UNLESS(threadCreate(&m_inputThread, &SwitchVirtualGamepadHandler::InputThreadLoop, this, input_thread_stack, sizeof(input_thread_stack), 0x30, -2));
R_ABORT_UNLESS(threadStart(&m_inputThread));
return 0;
}
void SwitchVirtualGamepadHandler::ExitInputThread()
{
m_inputThreadIsRunning = false;
m_inputThread.CancelSynchronization();
m_inputThread.Join();
svcCancelSynchronization(m_inputThread.handle);
threadWaitForExit(&m_inputThread);
threadClose(&m_inputThread);
}
Result SwitchVirtualGamepadHandler::InitOutputThread()
{
R_TRY(m_outputThread.Initialize(&SwitchVirtualGamepadHandler::OutputThreadLoop, this, 0x30).GetValue());
m_outputThreadIsRunning = true;
return m_outputThread.Start().GetValue();
R_ABORT_UNLESS(threadCreate(&m_outputThread, &SwitchVirtualGamepadHandler::OutputThreadLoop, this, output_thread_stack, sizeof(output_thread_stack), 0x30, -2));
R_ABORT_UNLESS(threadStart(&m_outputThread));
return 0;
}
void SwitchVirtualGamepadHandler::ExitOutputThread()
{
m_outputThreadIsRunning = false;
m_outputThread.CancelSynchronization();
m_outputThread.Join();
svcCancelSynchronization(m_outputThread.handle);
threadWaitForExit(&m_outputThread);
threadClose(&m_outputThread);
}
static_assert(JOYSTICK_MAX == 32767 && JOYSTICK_MIN == -32767,

View File

@ -10,8 +10,11 @@ protected:
u32 m_vibrationDeviceHandle;
std::unique_ptr<IController> m_controller;
ams::os::StaticThread<0x1'000> m_inputThread;
ams::os::StaticThread<0x1'000> m_outputThread;
alignas(ams::os::ThreadStackAlignment) u8 input_thread_stack[0x1000];
alignas(ams::os::ThreadStackAlignment) u8 output_thread_stack[0x1000];
Thread m_inputThread;
Thread m_outputThread;
bool m_inputThreadIsRunning = false;
bool m_outputThreadIsRunning = false;

View File

@ -20,9 +20,11 @@ namespace syscon::config
UTimer filecheckTimer;
Waiter filecheckTimerWaiter = waiterForUTimer(&filecheckTimer);
// Thread to check for any config changes
void ConfigChangedCheckThreadFunc(void *arg);
ams::os::StaticThread<0x2'000> g_config_changed_check_thread(&ConfigChangedCheckThreadFunc, nullptr, 0x3E);
alignas(ams::os::ThreadStackAlignment) u8 config_thread_stack[0x2000];
Thread g_config_changed_check_thread;
bool is_config_changed_check_thread_running = false;
@ -338,14 +340,17 @@ namespace syscon::config
return 1;
utimerStart(&filecheckTimer);
is_config_changed_check_thread_running = true;
return g_config_changed_check_thread.Start().GetValue();
R_ABORT_UNLESS(threadCreate(&g_config_changed_check_thread, &ConfigChangedCheckThreadFunc, nullptr, config_thread_stack, sizeof(config_thread_stack), 0x3E, -2));
R_ABORT_UNLESS(threadStart(&g_config_changed_check_thread));
return 0;
}
void Disable()
{
is_config_changed_check_thread_running = false;
utimerStop(&filecheckTimer);
g_config_changed_check_thread.CancelSynchronization();
g_config_changed_check_thread.Join();
svcCancelSynchronization(g_config_changed_check_thread.handle);
threadWaitForExit(&g_config_changed_check_thread);
threadClose(&g_config_changed_check_thread);
}
} // namespace syscon::config

View File

@ -14,7 +14,7 @@ namespace syscon::controllers
constexpr size_t MaxControllerHandlersSize = 10;
std::vector<std::unique_ptr<SwitchVirtualGamepadHandler>> controllerHandlers;
bool UseAbstractedPad;
ams::os::Mutex controllerMutex;
ams::os::Mutex controllerMutex(false);
} // namespace
bool IsAtControllerLimit()

View File

@ -3,7 +3,7 @@
#include "config_handler.h"
#include <stratosphere.hpp>
static ams::os::Mutex printMutex;
static ams::os::Mutex printMutex(false);
void DiscardOldLogs()
{
@ -33,15 +33,12 @@ void WriteToLog(const char *fmt, ...)
{
std::scoped_lock printLock(printMutex);
u64 ts;
TimeCalendarTime caltime;
timeGetCurrentTime(TimeType_LocalSystemClock, &ts);
timeToCalendarTimeWithMyRule(ts, &caltime, nullptr);
ams::TimeSpan ts = ams::os::ConvertToTimeSpan(ams::os::GetSystemTick());
FILE *fp = fopen(LOG_PATH, "a");
//Print time
fprintf(fp, "%04i-%02i-%02i %02i:%02i:%02i: ", caltime.year, caltime.month, caltime.day, caltime.hour, caltime.minute, caltime.second);
fprintf(fp, "%02lid %02li:%02li:%02li: ", ts.GetDays(), ts.GetHours() % 24, ts.GetMinutes() % 60, ts.GetSeconds() % 60);
//Print the actual text
va_list va;

View File

@ -7,12 +7,17 @@
#include "config_handler.h"
#include "psc_module.h"
#define APP_VERSION "0.6.0"
#define APP_VERSION "0.6.2"
// libnx fake heap initialization
extern "C"
{
// We aren't an applet, so disable applet functionality.
u32 __nx_applet_type = AppletType_None;
// We are a sysmodule, so don't use more FS sessions than needed.
u32 __nx_fs_num_sessions = 1;
// We don't need to reserve memory for fsdev, so don't use it.
u32 __nx_fsdev_direntry_cache_size = 1;
#define INNER_HEAP_SIZE 0x40'000
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
@ -57,7 +62,6 @@ extern "C" void __appInit(void)
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
setsysExit();
R_ABORT_UNLESS(timeInitialize());
R_ABORT_UNLESS(hiddbgInitialize());
if (hosversionAtLeast(7, 0, 0))
R_ABORT_UNLESS(hiddbgAttachHdlsWorkBuffer());
@ -77,7 +81,6 @@ extern "C" void __appExit(void)
hiddbgExit();
fsdevUnmountAll();
fsExit();
timeExit();
}
using namespace syscon;

View File

@ -11,11 +11,13 @@ namespace syscon::psc
{
PscPmModule pscModule;
Waiter pscModuleWaiter;
const uint16_t dependencies[] = {PscPmModuleId_Usb};
const uint16_t dependencies[] = {PscPmModuleId_Fs};
//Thread to check for psc:pm state change (console waking up/going to sleep)
void PscThreadFunc(void *arg);
ams::os::StaticThread<0x1'000> g_psc_thread(&PscThreadFunc, nullptr, 0x2C);
alignas(ams::os::ThreadStackAlignment) u8 psc_thread_stack[0x1000];
Thread g_psc_thread;
bool is_psc_thread_running = false;
@ -31,6 +33,7 @@ namespace syscon::psc
{
switch (pscState)
{
case PscPmState_Awake:
case PscPmState_ReadyAwaken:
//usb::CreateUsbEvents();
break;
@ -53,7 +56,9 @@ namespace syscon::psc
R_TRY(pscmGetPmModule(&pscModule, PscPmModuleId(126), dependencies, sizeof(dependencies) / sizeof(uint16_t), true));
pscModuleWaiter = waiterForEvent(&pscModule.event);
is_psc_thread_running = true;
return g_psc_thread.Start().GetValue();
R_ABORT_UNLESS(threadCreate(&g_psc_thread, &PscThreadFunc, nullptr, psc_thread_stack, sizeof(psc_thread_stack), 0x2C, -2));
R_ABORT_UNLESS(threadStart(&g_psc_thread));
return 0;
}
void Exit()
@ -64,7 +69,8 @@ namespace syscon::psc
pscPmModuleClose(&pscModule);
eventClose(&pscModule.event);
g_psc_thread.CancelSynchronization();
g_psc_thread.Join();
svcCancelSynchronization(g_psc_thread.handle);
threadWaitForExit(&g_psc_thread);
threadClose(&g_psc_thread);
}
}; // namespace syscon::psc

View File

@ -19,15 +19,22 @@ namespace syscon::usb
constexpr size_t MaxUsbHsInterfacesSize = 16;
ams::os::Mutex usbMutex;
ams::os::Mutex usbMutex(false);
//Thread that waits on generic usb event
void UsbEventThreadFunc(void *arg);
//Thread that waits on sony vendor usb event
void UsbSonyEventThreadFunc(void *arg);
//Thread that waits on any disconnected usb devices
void UsbInterfaceChangeThreadFunc(void *arg);
ams::os::StaticThread<0x2'000> g_usb_event_thread(&UsbEventThreadFunc, nullptr, 0x3A);
ams::os::StaticThread<0x2'000> g_sony_event_thread(&UsbSonyEventThreadFunc, nullptr, 0x3B);
ams::os::StaticThread<0x2'000> g_usb_interface_change_thread(&UsbInterfaceChangeThreadFunc, nullptr, 0x2C);
alignas(ams::os::ThreadStackAlignment) u8 usb_event_thread_stack[0x2000];
alignas(ams::os::ThreadStackAlignment) u8 sony_event_thread_stack[0x2000];
alignas(ams::os::ThreadStackAlignment) u8 usb_interface_change_thread_stack[0x2000];
Thread g_usb_event_thread;
Thread g_sony_event_thread;
Thread g_usb_interface_change_thread;
bool is_usb_event_thread_running = false;
bool is_usb_interface_change_thread_running = false;
@ -198,9 +205,13 @@ namespace syscon::usb
is_usb_event_thread_running = true;
is_usb_interface_change_thread_running = true;
R_TRY(g_usb_event_thread.Start().GetValue());
R_TRY(g_sony_event_thread.Start().GetValue());
R_TRY(g_usb_interface_change_thread.Start().GetValue());
R_ABORT_UNLESS(threadCreate(&g_usb_event_thread, &UsbEventThreadFunc, nullptr, usb_event_thread_stack, sizeof(usb_event_thread_stack), 0x3A, -2));
R_ABORT_UNLESS(threadCreate(&g_sony_event_thread, &UsbSonyEventThreadFunc, nullptr, sony_event_thread_stack, sizeof(sony_event_thread_stack), 0x3B, -2));
R_ABORT_UNLESS(threadCreate(&g_usb_interface_change_thread, &UsbInterfaceChangeThreadFunc, nullptr, usb_interface_change_thread_stack, sizeof(usb_interface_change_thread_stack), 0x2C, -2));
R_ABORT_UNLESS(threadStart(&g_usb_event_thread));
R_ABORT_UNLESS(threadStart(&g_sony_event_thread));
R_ABORT_UNLESS(threadStart(&g_usb_interface_change_thread));
return 0;
}
@ -209,13 +220,17 @@ namespace syscon::usb
is_usb_event_thread_running = false;
is_usb_interface_change_thread_running = false;
g_usb_event_thread.CancelSynchronization();
g_sony_event_thread.CancelSynchronization();
g_usb_interface_change_thread.CancelSynchronization();
svcCancelSynchronization(g_usb_event_thread.handle);
threadWaitForExit(&g_usb_event_thread);
threadClose(&g_usb_event_thread);
g_usb_event_thread.Join();
g_sony_event_thread.Join();
g_usb_interface_change_thread.Join();
svcCancelSynchronization(g_sony_event_thread.handle);
threadWaitForExit(&g_sony_event_thread);
threadClose(&g_sony_event_thread);
svcCancelSynchronization(g_usb_interface_change_thread.handle);
threadWaitForExit(&g_usb_interface_change_thread);
threadClose(&g_usb_interface_change_thread);
DestroyUsbEvents();
controllers::Reset();

@ -1 +1 @@
Subproject commit 62f5667b5f020f4a871ccd8f0362f2625d92e616
Subproject commit 797dfa782e85173652d017de38066f9a5c88622a