/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #define kIOPMRepeatingAppName "Repeating" /* * SCPreferences file format * com.apple.AutoWake.xml * * - CFSTR(kIOPMRepeatingPowerOnKey) * - CFSTR(kIOPMPowerEventTimeKey) = CFNumberRef (kCFNumberIntType) * - CFSTR(kIOPMDaysOfWeekKey) = CFNumberRef (kCFNumberIntType) * - CFSTR(kIOPMPowerEventTypeKey) = CFStringRef (kIOPMAutoSleep, kIOPMAutoShutdown, kIOPMAutoPowerOn, kIOPMAutoWake) * - CFSTR(kIOPMRepeatingPowerOffKey) * - CFSTR(kIOPMPowerEventTimeKey) = CFNumberRef (kCFNumberIntType) * - CFSTR(kIOPMDaysOfWeekKey) = CFNumberRef (kCFNumberIntType) * - CFSTR(kIOPMPowerEventTypeKey) = CFStringRef (kIOPMAutoSleep, kIOPMAutoShutdown, kIOPMAutoPowerOn, kIOPMAutoWake) */ static bool is_valid_repeating_dictionary(CFDictionaryRef event) { CFNumberRef tmp_num; CFStringRef tmp_str; int val; if(NULL == event) return true; if(!isA_CFDictionary(event)) return false; tmp_num = (CFNumberRef)CFDictionaryGetValue(event, CFSTR(kIOPMPowerEventTimeKey)); if(!isA_CFNumber(tmp_num)) return false; CFNumberGetValue(tmp_num, kCFNumberIntType, &val); if(val < 0 || val >= (24*60)) return false; tmp_num = (CFNumberRef)CFDictionaryGetValue(event, CFSTR(kIOPMDaysOfWeekKey)); if(!isA_CFNumber(tmp_num)) return false; tmp_str = (CFStringRef)CFDictionaryGetValue(event, CFSTR(kIOPMPowerEventTypeKey)); if(!isA_CFString(tmp_str)) return false; if( (kCFCompareEqualTo != CFStringCompare(tmp_str, CFSTR(kIOPMAutoSleep), 0)) && (kCFCompareEqualTo != CFStringCompare(tmp_str, CFSTR(kIOPMAutoShutdown), 0)) && (kCFCompareEqualTo != CFStringCompare(tmp_str, CFSTR(kIOPMAutoWakeOrPowerOn), 0)) && (kCFCompareEqualTo != CFStringCompare(tmp_str, CFSTR(kIOPMAutoPowerOn), 0)) && (kCFCompareEqualTo != CFStringCompare(tmp_str, CFSTR(kIOPMAutoWake), 0)) ) { return false; } return true; } extern IOReturn IOPMScheduleRepeatingPowerEvent(CFDictionaryRef events) { SCPreferencesRef prefs = 0; IOReturn ret = kIOReturnError; CFDictionaryRef repeating_on, repeating_off; // Validate our inputs if(!isA_CFDictionary(events)) return kIOReturnBadArgument; repeating_on = CFDictionaryGetValue(events, CFSTR(kIOPMRepeatingPowerOnKey)); repeating_off = CFDictionaryGetValue(events, CFSTR(kIOPMRepeatingPowerOffKey)); if(!is_valid_repeating_dictionary(repeating_on) || !is_valid_repeating_dictionary(repeating_off)) return kIOReturnBadArgument; // Toss 'em out to the disk and to PM configd. configd will do the heavy lifting. prefs = SCPreferencesCreate(0, CFSTR("IOKit-AutoWake"), CFSTR(kIOPMAutoWakePrefsPath)); if(!prefs || !SCPreferencesLock(prefs, true)) { if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged; else ret = kIOReturnError; goto exit; } if(repeating_on) SCPreferencesSetValue(prefs, CFSTR(kIOPMRepeatingPowerOnKey), repeating_on); else SCPreferencesRemoveValue(prefs, CFSTR(kIOPMRepeatingPowerOnKey)); if(repeating_off) SCPreferencesSetValue(prefs, CFSTR(kIOPMRepeatingPowerOffKey), repeating_off); else SCPreferencesRemoveValue(prefs, CFSTR(kIOPMRepeatingPowerOffKey)); if(!SCPreferencesCommitChanges(prefs)) { ret = kIOReturnError; goto exit; } ret = kIOReturnSuccess; exit: if(prefs) SCPreferencesUnlock(prefs); if(prefs) CFRelease(prefs); return ret; } extern CFDictionaryRef IOPMCopyRepeatingPowerEvents(void) { SCPreferencesRef prefs; CFMutableDictionaryRef return_dict = NULL; CFDictionaryRef rep_power_on_dict; CFDictionaryRef rep_power_off_dict; // Open SCPreferences // Open the prefs file and grab the current array prefs = SCPreferencesCreate(0, CFSTR("IOKit-AutoWake"), CFSTR(kIOPMAutoWakePrefsPath)); if(!prefs) { return_dict = NULL; goto exit; } rep_power_on_dict = isA_CFDictionary(SCPreferencesGetValue(prefs, CFSTR(kIOPMRepeatingPowerOnKey))); rep_power_off_dict = isA_CFDictionary(SCPreferencesGetValue(prefs, CFSTR(kIOPMRepeatingPowerOffKey))); if(rep_power_on_dict || rep_power_off_dict) { return_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Toss them into a new dictionary if(rep_power_on_dict) CFDictionaryAddValue(return_dict, CFSTR(kIOPMRepeatingPowerOnKey), rep_power_on_dict); if(rep_power_off_dict) CFDictionaryAddValue(return_dict, CFSTR(kIOPMRepeatingPowerOffKey), rep_power_off_dict); } else { // No repeating events - just return NULL return_dict = NULL; } exit: if(prefs) CFRelease(prefs); return return_dict; } extern IOReturn IOPMCancelAllRepeatingPowerEvents(void) { SCPreferencesRef prefs = 0; IOReturn ret = kIOReturnError; prefs = SCPreferencesCreate(0, CFSTR("IOKit-AutoWake"), CFSTR(kIOPMAutoWakePrefsPath)); if(!prefs || !SCPreferencesLock(prefs, true)) { if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged; else ret = kIOReturnError; goto exit; } SCPreferencesRemoveValue(prefs, CFSTR(kIOPMRepeatingPowerOnKey)); SCPreferencesRemoveValue(prefs, CFSTR(kIOPMRepeatingPowerOffKey)); if(!SCPreferencesCommitChanges(prefs)) { ret = kIOReturnError; goto exit; } ret = kIOReturnSuccess; exit: if(prefs) SCPreferencesUnlock(prefs); if(prefs) CFRelease(prefs); return ret; }