| // |
| // Copyright (c) 2017 The Khronos Group Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "sleep.h" |
| #include "utility.h" |
| |
| #if defined(__APPLE__) |
| #include <IOKit/pwr_mgt/IOPMLib.h> |
| #include <IOKit/IOMessage.h> |
| |
| struct |
| { |
| io_connect_t connection; |
| IONotificationPortRef port; |
| io_object_t iterator; |
| } sleepInfo; |
| |
| void sleepCallback(void* refcon, io_service_t service, natural_t messageType, |
| void* messageArgument); |
| |
| void sleepCallback(void* refcon UNUSED, io_service_t service UNUSED, |
| natural_t messageType, void* messageArgument) |
| { |
| |
| IOReturn result; |
| /* |
| service -- The IOService whose state has changed. |
| messageType -- A messageType enum, defined by IOKit/IOMessage.h or by the |
| IOService's family. messageArgument -- An argument for the message, |
| dependent on the messageType. |
| */ |
| switch (messageType) |
| { |
| case kIOMessageSystemWillSleep: |
| // Handle demand sleep (such as sleep caused by running out of |
| // batteries, closing the lid of a laptop, or selecting |
| // sleep from the Apple menu. |
| IOAllowPowerChange(sleepInfo.connection, (long)messageArgument); |
| vlog("Hard sleep occurred.\n"); |
| break; |
| case kIOMessageCanSystemSleep: |
| // In this case, the computer has been idle for several minutes |
| // and will sleep soon so you must either allow or cancel |
| // this notification. Important: if you don’t respond, there will |
| // be a 30-second timeout before the computer sleeps. |
| // IOCancelPowerChange(root_port,(long)messageArgument); |
| result = IOCancelPowerChange(sleepInfo.connection, |
| (long)messageArgument); |
| if (kIOReturnSuccess != result) |
| vlog("sleep prevention failed. (%d)\n", result); |
| break; |
| case kIOMessageSystemHasPoweredOn: |
| // Handle wakeup. |
| break; |
| } |
| } |
| #endif |
| |
| |
| void PreventSleep(void) |
| { |
| #if defined(__APPLE__) |
| vlog("Disabling sleep... "); |
| sleepInfo.iterator = (io_object_t)0; |
| sleepInfo.port = NULL; |
| sleepInfo.connection = IORegisterForSystemPower( |
| &sleepInfo, // void * refcon, |
| &sleepInfo.port, // IONotificationPortRef * thePortRef, |
| sleepCallback, // IOServiceInterestCallback callback, |
| &sleepInfo.iterator // io_object_t * notifier |
| ); |
| |
| if ((io_connect_t)0 == sleepInfo.connection) |
| vlog("failed.\n"); |
| else |
| vlog("done.\n"); |
| |
| CFRunLoopAddSource(CFRunLoopGetCurrent(), |
| IONotificationPortGetRunLoopSource(sleepInfo.port), |
| kCFRunLoopDefaultMode); |
| #else |
| vlog("*** PreventSleep() is not implemented on this platform.\n"); |
| #endif |
| } |
| |
| void ResumeSleep(void) |
| { |
| #if defined(__APPLE__) |
| IOReturn result = IODeregisterForSystemPower(&sleepInfo.iterator); |
| if (0 != result) |
| vlog("Got error %d restoring sleep \n", result); |
| else |
| vlog("Sleep restored.\n"); |
| #else |
| vlog("*** ResumeSleep() is not implemented on this platform.\n"); |
| #endif |
| } |