]> Chaos Git - corbenik/ctrulib.git/commitdiff
Add synchronization mechanism for entering sleep mode.
authorStapleButter <thetotalworm@gmail.com>
Thu, 18 Sep 2014 20:09:15 +0000 (22:09 +0200)
committerStapleButter <thetotalworm@gmail.com>
Thu, 18 Sep 2014 20:09:15 +0000 (22:09 +0200)
When the APT status is APP_PREPARE_SLEEPMODE, the application main thread should call aptSignalReadyForSleep() to signal that it is ready to enter sleep mode, and then call aptWaitStatusEvent() as usual.

Example code:

APP_STATUS status;
while ((status = aptGetStatus()) != APP_EXITING)
{
if(status==APP_RUNNING)
{
// application logic here
}
else if(status == APP_SUSPENDING)
{
aptReturnToMenu();
}
else if(status == APP_PREPARE_SLEEPMODE)
{
aptSignalReadyForSleep();
aptWaitStatusEvent();
}
}

This maybe isn't the proper/recommended way to do sleep mode, but I tested it multiple times and it always worked reliably.

(note: maybe the sample code above will not work if GPU drawing is done in a separate thread, haven't tested that)

libctru/include/3ds/services/apt.h
libctru/source/services/apt.c

index 9377c0ba1234bee38dae39776dcc79570dfab316..b8c05d9d12837f353805d7578ce791274350e4e8 100644 (file)
@@ -48,6 +48,7 @@ u32 aptGetStatusPower();//This can be used when the status is APP_SUSPEND* to ch
 void aptSetStatusPower(u32 status);
 void aptReturnToMenu();//This should be called by the user application when aptGetStatus() returns APP_SUSPENDING, not calling this will result in return-to-menu being disabled with the status left at APP_SUSPENDING. This function will not return until the system returns to the application, or when the status was changed to APP_EXITING.
 void aptWaitStatusEvent();
+void aptSignalReadyForSleep();
 NS_APPID aptGetMenuAppID();
 
 Result APT_GetLockHandle(Handle* handle, u16 flags, Handle* lockHandle);
index d2f65d90696c187af4dbbcd7ccc600aad27073a2..3c8de84dcb0b6eb3b605956569fa8355a24a5d8a 100644 (file)
@@ -26,6 +26,7 @@ Handle aptStatusEvent = 0;
 APP_STATUS aptStatus = APP_NOTINITIALIZED;
 APP_STATUS aptStatusBeforeSleep = APP_NOTINITIALIZED;
 u32 aptStatusPower = 0;
+Handle aptSleepSync = 0;
 
 u32 aptParameters[0x1000/4]; //TEMP
 
@@ -204,21 +205,24 @@ static void __handle_notification() {
        case APTSIGNAL_PREPARESLEEP:
                // Reply to sleep-request.
                aptStatusBeforeSleep = aptGetStatus();
+               aptSetStatus(APP_PREPARE_SLEEPMODE);
+               svcWaitSynchronization(aptSleepSync, U64_MAX);
+               svcClearEvent(aptSleepSync);
+               
                aptOpenSession();
                APT_ReplySleepQuery(NULL, currentAppId, 0x1);
                aptCloseSession();
-
-               aptSetStatus(APP_PREPARE_SLEEPMODE);
                break;
 
        case APTSIGNAL_ENTERSLEEP:
                if(aptGetStatus() == APP_PREPARE_SLEEPMODE)
                {
                        // Report into sleep-mode.
+                       aptSetStatus(APP_SLEEPMODE);
+                       
                        aptOpenSession();
                        APT_ReplySleepNotificationComplete(NULL, currentAppId);
                        aptCloseSession();
-                       aptSetStatus(APP_SLEEPMODE);
                }
                break;
 
@@ -319,6 +323,7 @@ Result aptInit(void)
        }
 
        svcCreateEvent(&aptStatusEvent, 0);
+       svcCreateEvent(&aptSleepSync, 0);
        return 0;
 }
 
@@ -344,6 +349,8 @@ void aptExit()
                APT_CloseApplication(NULL, 0x0, 0x0, 0x0);
                aptCloseSession();
        }
+       
+       svcCloseHandle(aptSleepSync);
 
        svcCloseHandle(aptStatusMutex);
        //svcCloseHandle(aptLockHandle);
@@ -421,7 +428,7 @@ void aptSetStatus(APP_STATUS status)
 
        svcWaitSynchronization(aptStatusMutex, U64_MAX);
 
-       prevstatus = status;
+       prevstatus = aptStatus;
        aptStatus = status;
 
        if(prevstatus != APP_NOTINITIALIZED)
@@ -461,6 +468,11 @@ void aptCloseSession()
        svcReleaseMutex(aptLockHandle);
 }
 
+void aptSignalReadyForSleep()
+{
+       svcSignalEvent(aptSleepSync);
+}
+
 Result APT_GetLockHandle(Handle* handle, u16 flags, Handle* lockHandle)
 {
        if(!handle)handle=&aptuHandle;