SDHotSwapModule/source/main.cpp

106 lines
2.6 KiB
C++

#include "exports.h"
#include "logger.h"
#include "sdcard.h"
#include <condition_variable>
#include <coreinit/cache.h>
#include <coreinit/filesystem.h>
#include <coreinit/thread.h>
#include <mutex>
#include <sdutils/sdutils.h>
#include <thread>
#include <wums.h>
WUMS_MODULE_EXPORT_NAME("homebrew_sdhotswap");
WUMS_MODULE_SKIP_INIT_FINI();
// This NEEDS to be on the heap. Global DTOR are never called for modules
// but we need a fresh instance of this condition_variable on each app change.
std::condition_variable *cv = nullptr;
std::mutex *cv_m = nullptr;
std::thread *mountThread = nullptr;
bool sStopThread = false;
bool sIsSDInsertedAndMounted = false;
int mount_thread() {
std::unique_lock<std::mutex> lk(*cv_m);
// Wait until the main thread has checked the sd status once.
cv->wait(lk);
while (!sStopThread) {
auto newStatus = IsSDCardInserted();
if (newStatus != sIsSDInsertedAndMounted) {
if (newStatus) {
if (MountSDCard()) {
callAttachCallbacks(SDUTILS_ATTACH_MOUNTED);
sIsSDInsertedAndMounted = true;
}
} else {
if (UnmountSDCard()) {
callAttachCallbacks(SDUTILS_ATTACH_UNMOUNTED);
sIsSDInsertedAndMounted = false;
}
}
OSMemoryBarrier();
}
OSSleepTicks(OSMillisecondsToTicks(100));
}
return 0;
}
WUMS_APPLICATION_STARTS() {
initLogging();
sStopThread = false;
cv = new std::condition_variable;
cv_m = new std::mutex;
OSMemoryBarrier();
mountThread = new std::thread(mount_thread);
auto nativeHandle = (OSThread *) mountThread->native_handle();
OSSetThreadName(nativeHandle, "SDHotSwapModuleThread");
while (!OSSetThreadAffinity(nativeHandle, OS_THREAD_ATTRIB_AFFINITY_CPU2)) {
OSSleepTicks(OSMillisecondsToTicks(16));
}
auto check = InitialSDCheck();
if (check < 0) {
// On error stop thread.
sStopThread = true;
} else {
// Otherwise it retuns the current status.
sIsSDInsertedAndMounted = check == 1;
}
OSMemoryBarrier();
DEBUG_FUNCTION_LINE("Wake up the thread");
// Now we can wake up the thread!
cv->notify_all();
}
WUMS_APPLICATION_ENDS() {
sStopThread = true;
OSMemoryBarrier();
cv->notify_all();
if (mountThread != nullptr) {
mountThread->join();
delete mountThread;
mountThread = nullptr;
}
DeInitSDCheck();
delete cv;
delete cv_m;
cv = nullptr;
cv_m = nullptr;
OSMemoryBarrier();
deinitLogging();
}