1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #if defined( __APPLE__ )
17 
18     #include "Sleep.h"
19     #include <IOKit/pwr_mgt/IOPMLib.h>
20     #include <IOKit/IOMessage.h>
21     #include "basic_test_conversions.h"
22 
23     #define UNUSED  __attribute__((unused))
24 
25     struct
26     {
27         io_connect_t            connection;
28         IONotificationPortRef    port;
29         io_object_t                iterator;
30     }sleepInfo;
31 
32     void sleepCallback(    void *            refcon,
33                         io_service_t        service,
34                         natural_t        messageType,
35                         void *            messageArgument );
36 
sleepCallback(void * refcon UNUSED,io_service_t service UNUSED,natural_t messageType,void * messageArgument)37     void sleepCallback(    void *            refcon UNUSED,
38                         io_service_t        service UNUSED,
39                         natural_t        messageType,
40                         void *            messageArgument )
41     {
42 
43         IOReturn result;
44     /*
45     service -- The IOService whose state has changed.
46     messageType -- A messageType enum, defined by IOKit/IOMessage.h or by the IOService's family.
47     messageArgument -- An argument for the message, dependent on the messageType.
48     */
49         switch ( messageType )
50         {
51             case kIOMessageSystemWillSleep:
52                 // Handle demand sleep (such as sleep caused by running out of
53                 // batteries, closing the lid of a laptop, or selecting
54                 // sleep from the Apple menu.
55                 IOAllowPowerChange(sleepInfo.connection,(long)messageArgument);
56                 vlog( "Hard sleep occurred.\n" );
57                 break;
58             case kIOMessageCanSystemSleep:
59                 // In this case, the computer has been idle for several minutes
60                 // and will sleep soon so you must either allow or cancel
61                 // this notification. Important: if you don’t respond, there will
62                 // be a 30-second timeout before the computer sleeps.
63                 // IOCancelPowerChange(root_port,(long)messageArgument);
64                 result = IOCancelPowerChange(sleepInfo.connection,(long)messageArgument);
65                 if( kIOReturnSuccess != result )
66                     vlog( "sleep prevention failed. (%d)\n", result);
67             break;
68             case kIOMessageSystemHasPoweredOn:
69                 // Handle wakeup.
70                 break;
71         }
72     }
73 
PreventSleep(void)74     void PreventSleep( void )
75     {
76         vlog( "Disabling sleep... " );
77         sleepInfo.iterator = (io_object_t) 0;
78         sleepInfo.port = NULL;
79         sleepInfo.connection = IORegisterForSystemPower
80                                 (
81                                     &sleepInfo,                    //void * refcon,
82                                     &sleepInfo.port,            //IONotificationPortRef * thePortRef,
83                                     sleepCallback,                //IOServiceInterestCallback callback,
84                                     &sleepInfo.iterator            //io_object_t * notifier
85                                 );
86 
87         if( (io_connect_t) 0 == sleepInfo.connection )
88             vlog( "failed.\n" );
89         else
90             vlog( "done.\n" );
91 
92         CFRunLoopAddSource(CFRunLoopGetCurrent(),
93                             IONotificationPortGetRunLoopSource(sleepInfo.port),
94                             kCFRunLoopDefaultMode);
95     }
96 
ResumeSleep(void)97     void ResumeSleep( void )
98     {
99         IOReturn result = IODeregisterForSystemPower ( &sleepInfo.iterator );
100         if( 0 != result )
101             vlog( "Got error %d restoring sleep \n", result );
102         else
103             vlog( "Sleep restored.\n" );
104     }
105 
106 #else  /* not __APPLE__ */
PreventSleep(void)107     void PreventSleep( void )  {}
ResumeSleep(void)108     void ResumeSleep( void )   {}
109 
110 #endif
111 
112 
113