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
17 #include "sleep.h"
18 #include "utility.h"
19
20 #if defined(__APPLE__)
21 #include <IOKit/pwr_mgt/IOPMLib.h>
22 #include <IOKit/IOMessage.h>
23
24 struct
25 {
26 io_connect_t connection;
27 IONotificationPortRef port;
28 io_object_t iterator;
29 } sleepInfo;
30
31 void sleepCallback(void* refcon, io_service_t service, natural_t messageType,
32 void* messageArgument);
33
sleepCallback(void * refcon UNUSED,io_service_t service UNUSED,natural_t messageType,void * messageArgument)34 void sleepCallback(void* refcon UNUSED, io_service_t service UNUSED,
35 natural_t messageType, void* messageArgument)
36 {
37
38 IOReturn result;
39 /*
40 service -- The IOService whose state has changed.
41 messageType -- A messageType enum, defined by IOKit/IOMessage.h or by the
42 IOService's family. messageArgument -- An argument for the message,
43 dependent on the messageType.
44 */
45 switch (messageType)
46 {
47 case kIOMessageSystemWillSleep:
48 // Handle demand sleep (such as sleep caused by running out of
49 // batteries, closing the lid of a laptop, or selecting
50 // sleep from the Apple menu.
51 IOAllowPowerChange(sleepInfo.connection, (long)messageArgument);
52 vlog("Hard sleep occurred.\n");
53 break;
54 case kIOMessageCanSystemSleep:
55 // In this case, the computer has been idle for several minutes
56 // and will sleep soon so you must either allow or cancel
57 // this notification. Important: if you don’t respond, there will
58 // be a 30-second timeout before the computer sleeps.
59 // IOCancelPowerChange(root_port,(long)messageArgument);
60 result = IOCancelPowerChange(sleepInfo.connection,
61 (long)messageArgument);
62 if (kIOReturnSuccess != result)
63 vlog("sleep prevention failed. (%d)\n", result);
64 break;
65 case kIOMessageSystemHasPoweredOn:
66 // Handle wakeup.
67 break;
68 }
69 }
70 #endif
71
72
PreventSleep(void)73 void PreventSleep(void)
74 {
75 #if defined(__APPLE__)
76 vlog("Disabling sleep... ");
77 sleepInfo.iterator = (io_object_t)0;
78 sleepInfo.port = NULL;
79 sleepInfo.connection = IORegisterForSystemPower(
80 &sleepInfo, // void * refcon,
81 &sleepInfo.port, // IONotificationPortRef * thePortRef,
82 sleepCallback, // IOServiceInterestCallback callback,
83 &sleepInfo.iterator // io_object_t * notifier
84 );
85
86 if ((io_connect_t)0 == sleepInfo.connection)
87 vlog("failed.\n");
88 else
89 vlog("done.\n");
90
91 CFRunLoopAddSource(CFRunLoopGetCurrent(),
92 IONotificationPortGetRunLoopSource(sleepInfo.port),
93 kCFRunLoopDefaultMode);
94 #else
95 vlog("*** PreventSleep() is not implemented on this platform.\n");
96 #endif
97 }
98
ResumeSleep(void)99 void ResumeSleep(void)
100 {
101 #if defined(__APPLE__)
102 IOReturn result = IODeregisterForSystemPower(&sleepInfo.iterator);
103 if (0 != result)
104 vlog("Got error %d restoring sleep \n", result);
105 else
106 vlog("Sleep restored.\n");
107 #else
108 vlog("*** ResumeSleep() is not implemented on this platform.\n");
109 #endif
110 }
111