From e889c6e00ccca8b2460a165c809cbd77a951b335 Mon Sep 17 00:00:00 2001 From: cathery Date: Sun, 24 Nov 2019 05:25:14 +0300 Subject: [PATCH] Implement PSC module for cleaning up resources before going to sleep --- source/main.cpp | 5 + source/mainLoop.cpp | 364 +++++++++++++++++++++++++++----------------- 2 files changed, 228 insertions(+), 141 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 27f5f6d..4f9aaf4 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -62,6 +62,10 @@ extern "C" if (R_FAILED(rc)) fatalThrow(rc); + rc = pscmInitialize(); + if (R_FAILED(rc)) + fatalThrow(rc); + #ifndef __APPLET__ rc = hidInitialize(); if (R_FAILED(rc)) @@ -74,6 +78,7 @@ extern "C" #ifndef __APPLET__ hidExit(); #endif + pscmExit(); usbHsExit(); hiddbgReleaseHdlsWorkBuffer(); hiddbgExit(); diff --git a/source/mainLoop.cpp b/source/mainLoop.cpp index 9060aa9..07164d6 100644 --- a/source/mainLoop.cpp +++ b/source/mainLoop.cpp @@ -58,10 +58,6 @@ Result CreateDualshck3AvailableEvent(Event &out) filter.idVendor = VENDOR_SONY; filter.idProduct = PRODUCT_DUALSHOCK3; Result rc = usbHsCreateInterfaceAvailableEvent(&out, true, DS3EVENT_INDEX, &filter); - if (R_FAILED(rc)) - WriteToLog("Failed to open event for Dualshock 3"); - else - WriteToLog("Successfully created event for Dualshock 3"); return rc; } @@ -72,10 +68,6 @@ Result CreateDualshock4AvailableEvent(Event &out) filter.idVendor = VENDOR_SONY; filter.idProduct = _globalConfig.dualshock4_productID; Result rc = usbHsCreateInterfaceAvailableEvent(&out, true, DS4EVENT_INDEX, &filter); - if (R_FAILED(rc)) - WriteToLog("Failed to open event for Dualshock 4 0x", std::hex, _globalConfig.dualshock4_productID); - else - WriteToLog("Successfully created event for Dualshock 4 0x", std::hex, _globalConfig.dualshock4_productID); return rc; } @@ -85,10 +77,6 @@ Result CreateAllAvailableEvent(Event &out) filter.Flags = UsbHsInterfaceFilterFlags_bcdDevice_Min; filter.bcdDevice_Min = 0; Result rc = usbHsCreateInterfaceAvailableEvent(&out, true, ALLEVENT_INDEX, &filter); - if (R_FAILED(rc)) - WriteToLog("Failed to open catch-all event"); - else - WriteToLog("Successfully created catch-all event"); return rc; } @@ -119,6 +107,75 @@ Result QueryVendorProduct(UsbHsInterface *interfaces, size_t interfaces_size, s3 return 1; } +Event catchAllEvent; +Event ds3Event; +Event ds4Event; + +Result inline OpenEvents() +{ + Result rc = CreateAllAvailableEvent(catchAllEvent); + if (R_FAILED(rc)) + return 3; + rc = CreateDualshck3AvailableEvent(ds3Event); + if (R_FAILED(rc)) + return 1; + rc = CreateDualshock4AvailableEvent(ds4Event); + if (R_FAILED(rc)) + return 2; + + return 0; +} + +void inline CloseEvents() +{ + usbHsDestroyInterfaceAvailableEvent(&ds3Event, DS3EVENT_INDEX); + usbHsDestroyInterfaceAvailableEvent(&ds4Event, DS4EVENT_INDEX); + usbHsDestroyInterfaceAvailableEvent(&catchAllEvent, ALLEVENT_INDEX); +} + +struct PSCLoopBuffer +{ + PscPmModule &pscModule; + bool &pscLoopRunning; + bool &shouldSleep; +}; + +void pscLoop(void *buffer) +{ + + Waiter pscModuleWaiter = waiterForEvent(&static_cast(buffer)->pscModule.event); + PscPmState pscState; + u32 out_flags; + + while (static_cast(buffer)->pscLoopRunning) + { + Result rc = waitSingle(pscModuleWaiter, U64_MAX); + if (R_SUCCEEDED(rc)) + { + rc = pscPmModuleGetRequest(&static_cast(buffer)->pscModule, &pscState, &out_flags); + if (R_SUCCEEDED(rc)) + { + switch (pscState) + { + case PscPmState_ReadyAwaken: + OpenEvents(); + static_cast(buffer)->shouldSleep = false; + break; + case PscPmState_ReadySleep: + case PscPmState_ReadyShutdown: + CloseEvents(); + static_cast(buffer)->shouldSleep = true; + //controllerInterfaces.clear(); + break; + default: + break; + } + pscPmModuleAcknowledge(&static_cast(buffer)->pscModule, pscState); + } + } + } +}; + Result mainLoop() { WriteToLog("\n\nNew sysmodule session started on version " APP_VERSION); @@ -131,174 +188,194 @@ Result mainLoop() utimerCreate(&filecheckTimer, 1e+9L, TimerType_Repeating); utimerStart(&filecheckTimer); + PscPmModule pscModule; + const uint16_t dependencies[] = {PscPmModuleId_Usb}; + + rc = pscmGetPmModule(&pscModule, static_cast(126), dependencies, sizeof(dependencies) / sizeof(uint16_t), true); + WriteToLog("Get module result: 0x", std::hex, rc); + //Waiter pscModuleWaiter = waiterForEvent(&pscModule.event); + + bool pscLoopRunning = true; + bool shouldSleep = false; + Thread pscThread; + PSCLoopBuffer loopBuffer{pscModule, pscLoopRunning, shouldSleep}; + + threadCreate(&pscThread, pscLoop, &loopBuffer, NULL, 0x2000, 0x3B, -2); + + rc = threadStart(&pscThread); + WriteToLog("PSC thread start: 0x", std::hex, rc); + CheckForFileChanges(); LoadAllConfigs(); - Event catchAllEvent; - Event ds3Event; - Event ds4Event; - - CreateDualshck3AvailableEvent(ds3Event); - CreateAllAvailableEvent(catchAllEvent); - CreateDualshock4AvailableEvent(ds4Event); + rc = OpenEvents(); + if (R_FAILED(rc)) + WriteToLog("Failed to open events: ", rc); controllerInterfaces.reserve(10); while (appletMainLoop()) { + if (!shouldSleep) + { #ifdef __APPLET__ - hidScanInput(); - u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); + hidScanInput(); + u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); - for (int i = 0; i != 8; ++i) - { - u64 kHeld = hidKeysDown(static_cast(i)); - if (kHeld != 0) - WriteToLog("Player ", i + 1, ": ", kHeld); - } - - if (kDown & KEY_B) - break; - - for (auto &&handler : controllerInterfaces) - { - if (handler->GetController()->m_UpdateCalled) + for (int i = 0; i != 8; ++i) { - for (int i = 0; i != 64; ++i) - printf("0x%02X ", handler->GetController()->m_inputData[i]); - printf("\n"); - handler->GetController()->m_UpdateCalled = false; + u64 kHeld = hidKeysDown(static_cast(i)); + if (kHeld != 0) + WriteToLog("Player ", i + 1, ": ", kHeld); } - } -#endif - rc = eventWait(&catchAllEvent, 0); - if (R_SUCCEEDED(rc)) - { - WriteToLog("Catch-all event went off"); - if (controllerInterfaces.size() >= 10) - WriteToLog("But the controllers table reached its max size!"); - else + + if (kDown & KEY_B) + break; + + for (auto &&handler : controllerInterfaces) { - - UsbHsInterface interfaces[8]; - s32 total_entries; - - if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 93, 1))) + if (handler->GetController()->m_UpdateCalled) { - WriteToLog("Registering Xbox 360 controller"); - controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); + for (int i = 0; i != 64; ++i) + printf("0x%02X ", handler->GetController()->m_inputData[i]); + printf("\n"); + handler->GetController()->m_UpdateCalled = false; } - else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 93, 129))) + } +#endif + rc = eventWait(&catchAllEvent, 0); + if (R_SUCCEEDED(rc)) + { + WriteToLog("Catch-all event went off"); + if (controllerInterfaces.size() >= 10) + WriteToLog("But the controllers table reached its max size!"); + else { - WriteToLog("Registering Xbox 360 Wireless adapter"); - for (int i = 0; i != total_entries; ++i) + + UsbHsInterface interfaces[8]; + s32 total_entries; + + if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 93, 1))) { - controllerPtr = std::make_unique(std::make_unique(interfaces + i, 1)); - CallInitHandler(controllerPtr); + WriteToLog("Registering Xbox 360 controller"); + controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); } - } - else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, 0x58, 0x42, 0x00))) - { - WriteToLog("Registering Xbox One controller"); - controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); - } - else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 71, 208))) - { - WriteToLog("Registering Xbox One controller"); - controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); - } - /* + else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 93, 129))) + { + WriteToLog("Registering Xbox 360 Wireless adapter"); + for (int i = 0; i != total_entries; ++i) + { + controllerPtr = std::make_unique(std::make_unique(interfaces + i, 1)); + CallInitHandler(controllerPtr); + } + } + else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, 0x58, 0x42, 0x00))) + { + WriteToLog("Registering Xbox One controller"); + controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); + } + else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 71, 208))) + { + WriteToLog("Registering Xbox One controller"); + controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); + } + /* else if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_VENDOR_SPEC, 255, 255))) { WriteToLog("Registering Xbox One adapter"); controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); } */ + } } - } - rc = eventWait(&ds3Event, 0); - if (R_SUCCEEDED(rc)) - { - WriteToLog("Dualshock 3 event went off"); - UsbHsInterface interfaces[4]; - s32 total_entries; - - if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_HID, 0, 0))) - { - WriteToLog("Registering DS3 controller"); - controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); - } - } - rc = eventWait(&ds4Event, 0); - if (R_SUCCEEDED(rc)) - { - WriteToLog("Dualshock 4 event went off"); - UsbHsInterface interfaces[4]; - s32 total_entries; - - if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_HID, 0, 0))) - { - WriteToLog("Registering DS4 controller"); - controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); - } - } - CallInitHandler(controllerPtr); - - //On interface change event, check if any devices were removed, and erase them from memory appropriately - rc = eventWait(usbHsGetInterfaceStateChangeEvent(), 0); - if (R_SUCCEEDED(rc)) - { - WriteToLog("Interface state was changed"); - eventClear(usbHsGetInterfaceStateChangeEvent()); - - UsbHsInterface interfaces[16]; - s32 total_entries; - - rc = usbHsQueryAcquiredInterfaces(interfaces, sizeof(interfaces), &total_entries); + rc = eventWait(&ds3Event, 0); if (R_SUCCEEDED(rc)) { - for (auto it = controllerInterfaces.begin(); it != controllerInterfaces.end(); ++it) - { - bool found_flag = false; + WriteToLog("Dualshock 3 event went off"); + UsbHsInterface interfaces[4]; + s32 total_entries; - for (auto &&ptr : (*it)->GetController()->GetDevice()->GetInterfaces()) + if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_HID, 0, 0))) + { + WriteToLog("Registering DS3 controller"); + controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); + } + } + rc = eventWait(&ds4Event, 0); + if (R_SUCCEEDED(rc)) + { + WriteToLog("Dualshock 4 event went off"); + UsbHsInterface interfaces[4]; + s32 total_entries; + + if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_HID, 0, 0))) + { + WriteToLog("Registering DS4 controller"); + controllerPtr = std::make_unique(std::make_unique(interfaces, total_entries)); + } + } + CallInitHandler(controllerPtr); + + //On interface change event, check if any devices were removed, and erase them from memory appropriately + rc = eventWait(usbHsGetInterfaceStateChangeEvent(), 0); + if (R_SUCCEEDED(rc)) + { + WriteToLog("Interface state was changed"); + eventClear(usbHsGetInterfaceStateChangeEvent()); + + UsbHsInterface interfaces[16]; + s32 total_entries; + + rc = usbHsQueryAcquiredInterfaces(interfaces, sizeof(interfaces), &total_entries); + if (R_SUCCEEDED(rc)) + { + for (auto it = controllerInterfaces.begin(); it != controllerInterfaces.end(); ++it) { - //We check if a device was removed by comparing the controller's interfaces and the currently acquired interfaces - //If we didn't find a single matching interface ID, we consider a controller removed - for (int i = 0; i != total_entries; ++i) + bool found_flag = false; + + for (auto &&ptr : (*it)->GetController()->GetDevice()->GetInterfaces()) { - if (interfaces[i].inf.ID == static_cast(ptr.get())->GetID()) + //We check if a device was removed by comparing the controller's interfaces and the currently acquired interfaces + //If we didn't find a single matching interface ID, we consider a controller removed + for (int i = 0; i != total_entries; ++i) { - found_flag = true; - break; + if (interfaces[i].inf.ID == static_cast(ptr.get())->GetID()) + { + found_flag = true; + break; + } } } - } - if (!found_flag) - { - WriteToLog("Erasing controller! ", (*it)->GetController()->GetType()); - controllerInterfaces.erase(it--); - WriteToLog("Controller erased!"); + if (!found_flag) + { + WriteToLog("Erasing controller! ", (*it)->GetController()->GetType()); + controllerInterfaces.erase(it--); + WriteToLog("Controller erased!"); + } } } } - } - //Checks every 1 second for any changes in config files, then reloads them - rc = waitSingle(filecheckTimerWaiter, 0); - if (R_SUCCEEDED(rc)) - { - if (CheckForFileChanges()) + //Checks every 1 second for any changes in config files, then reloads them + rc = waitSingle(filecheckTimerWaiter, 0); + if (R_SUCCEEDED(rc)) { - WriteToLog("File check succeeded! Loading configs..."); - LoadAllConfigs(); - usbHsDestroyInterfaceAvailableEvent(&ds4Event, DS4EVENT_INDEX); - CreateDualshock4AvailableEvent(ds4Event); + if (CheckForFileChanges()) + { + WriteToLog("File check succeeded! Loading configs..."); + LoadAllConfigs(); + usbHsDestroyInterfaceAvailableEvent(&ds4Event, DS4EVENT_INDEX); + CreateDualshock4AvailableEvent(ds4Event); + } } } - + else if (controllerInterfaces.size() != 0) + { + WriteToLog("Clearing interfaces before going to sleep"); + controllerInterfaces.clear(); + } #ifdef __APPLET__ consoleUpdate(nullptr); #else @@ -308,9 +385,14 @@ Result mainLoop() //After we break out of the loop, close all events and exit WriteToLog("Destroying events"); - usbHsDestroyInterfaceAvailableEvent(&ds3Event, DS3EVENT_INDEX); - usbHsDestroyInterfaceAvailableEvent(&ds4Event, DS4EVENT_INDEX); - usbHsDestroyInterfaceAvailableEvent(&catchAllEvent, ALLEVENT_INDEX); + CloseEvents(); + + pscPmModuleFinalize(&pscModule); + pscPmModuleClose(&pscModule); + + pscLoopRunning = false; + threadWaitForExit(&pscThread); + threadClose(&pscThread); controllerInterfaces.clear(); return rc;