1/* 2 * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <sys/cdefs.h> 25#include <TargetConditionals.h> 26 27#include "IOSystemConfiguration.h" 28#include <CoreFoundation/CoreFoundation.h> 29#include <IOKit/pwr_mgt/IOPM.h> 30#include <IOKit/pwr_mgt/IOPMPrivate.h> 31#include <IOKit/ps/IOPowerSources.h> 32#include <IOKit/ps/IOPowerSourcesPrivate.h> 33#include <IOKit/IOCFSerialize.h> 34#include <IOKit/IOHibernatePrivate.h> 35#include <servers/bootstrap.h> 36#include <bootstrap_priv.h> 37#include <sys/syslog.h> 38#include "IOPMLib.h" 39#include "IOPMLibPrivate.h" 40#include "powermanagement.h" 41 42#include <asl.h> 43#include <IOKit/IOKitLib.h> 44#include <IOKit/IOBSD.h> 45 46#include <mach/mach.h> 47#include <stdint.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <unistd.h> 51//#include <fcntl.h> 52//#include <pthread.h> 53//#include <sys/stat.h> 54//#include <sys/sysctl.h> 55//#include <sys/mount.h> 56 57#define kSecondsIn5Years 157680000 58 59typedef struct { 60 const char *keyName; 61 uint32_t defaultValueAC; 62 uint32_t defaultValueBattery; 63} PMSettingDescriptorStruct; 64#ifndef kIOPMAutoPowerOffEnabledKey 65#define kIOPMAutoPowerOffEnabledKey "poweroffenabled" 66#define kIOPMAutoPowerOffDelayKey "poweroffdelay" 67#endif 68PMSettingDescriptorStruct defaultSettings[] = 69{ /* Setting Name AC - Battery */ 70 {kIOPMDisplaySleepKey, 5, 5}, 71 {kIOPMDiskSleepKey, 10, 5}, 72 {kIOPMSystemSleepKey, 10, 5}, 73 {kIOPMWakeOnLANKey, 0, 0}, 74 {kIOPMWakeOnRingKey, 0, 0}, 75 {kIOPMRestartOnPowerLossKey, 0, 0}, 76 {kIOPMWakeOnACChangeKey, 0, 0}, 77 {kIOPMSleepOnPowerButtonKey, 1, 0}, 78 {kIOPMWakeOnClamshellKey, 1, 1}, 79 {kIOPMReduceBrightnessKey, 0, 1}, 80 {kIOPMDisplaySleepUsesDimKey, 1, 1}, 81 {kIOPMMobileMotionModuleKey, 1, 1}, 82 {kIOPMTTYSPreventSleepKey, 1, 1}, 83 {kIOPMGPUSwitchKey, 0, 1}, 84 {kIOPMPrioritizeNetworkReachabilityOverSleepKey, 0, 0}, 85 {kIOPMDeepSleepEnabledKey, 0, 0}, 86 {kIOPMDeepSleepDelayKey, 0, 0}, 87 {kIOPMDarkWakeBackgroundTaskKey, 1, 0}, 88 {kIOPMAutoPowerOffEnabledKey, 0, 0}, 89 {kIOPMAutoPowerOffDelayKey, 0, 0} 90}; 91 92static const int kPMSettingsCount = sizeof(defaultSettings)/sizeof(PMSettingDescriptorStruct); 93 94/* com.apple.PowerManagement.plist general keys 95 */ 96#define kIOPMPrefsPath CFSTR("com.apple.PowerManagement.xml") 97#define kIOPMAppName CFSTR("PowerManagement configd") 98 99#define kIOPMSystemPowerKey CFSTR("SystemPowerSettings") 100#define kIOPMCustomProfileKey CFSTR("Custom Profile") 101 102#define kIOHibernateDefaultFile "/var/vm/sleepimage" 103 104#define kIOPMPrefsPath CFSTR("com.apple.PowerManagement.xml") 105#define kIOPMAppName CFSTR("PowerManagement configd") 106 107/* IOPMRootDomain property keys for default settings 108 */ 109#define kIOPMSystemDefaultProfilesKey "SystemPowerProfiles" 110#define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict" 111 112/* Keys for Cheetah Energy Settings shim 113 */ 114#define kCheetahDimKey CFSTR("MinutesUntilDisplaySleeps") 115#define kCheetahDiskKey CFSTR("MinutesUntilHardDiskSleeps") 116#define kCheetahSleepKey CFSTR("MinutesUntilSystemSleeps") 117#define kCheetahRestartOnPowerLossKey CFSTR("RestartOnPowerLoss") 118#define kCheetahWakeForNetworkAccessKey CFSTR("WakeForNetworkAdministrativeAccess") 119#define kCheetahWakeOnRingKey CFSTR("WakeOnRing") 120 121// Supported Feature bitfields for IOPMrootDomain Supported Features 122enum { 123 kIOPMSupportedOnAC = 1<<0, 124 kIOPMSupportedOnBatt = 1<<1, 125 kIOPMSupportedOnUPS = 1<<2 126}; 127 128/* Power sources 129 * 130 */ 131#define kPowerSourcesCount 3 132#define kPowerProfilesCount 5 133 134enum { 135 kIOPMKeepUnsupportedPreferences = false, 136 kIOPMRemoveUnsupportedPreferences = true 137}; 138 139 140/* IOPMPrefsNotificationCreateRunLoopSource 141 * user_callback_context supports IOPMPrefsCallback 142 */ 143typedef struct { 144 IOPMPrefsCallbackType callback; 145 void *context; 146} user_callback_context; 147 148/******************************************************************************/ 149/******************************************************************************/ 150/******************************************************************************/ 151// Forwards 152 153static CFStringRef getPowerSourceString(int i); 154 155static void mergeUserDefaultOverriddenSettings( 156 CFMutableDictionaryRef es); 157static int addDefaultEnergySettings( 158 CFMutableDictionaryRef sys ); 159static void addSystemProfileEnergySettings( 160 CFDictionaryRef user_profile_selections, 161 CFMutableDictionaryRef passed_in); 162__private_extern__ io_registry_entry_t getPMRootDomainRef(void); 163static CFStringRef supportedNameForPMName( CFStringRef pm_name ); 164static bool featureSupportsPowerSource( 165 CFTypeRef featureDetails, 166 CFStringRef power_source); 167static void IOPMRemoveIrrelevantProperties( 168 CFMutableDictionaryRef energyPrefs); 169static int getCheetahPumaEnergySettings( 170 CFMutableDictionaryRef energyPrefs); 171 172#define kOverWriteDuplicates true 173#define kKeepOriginalValues false 174static void mergeDictIntoMutable( 175 CFMutableDictionaryRef target, 176 CFDictionaryRef overrides, 177 bool overwrite); 178static CFDictionaryRef _copyActivePMPreferences( 179 bool removeUnsupportedSettings); 180static CFArrayRef _copySystemProvidedProfiles(void); 181static CFArrayRef _createDefaultSystemProfiles(void); 182static CFDictionaryRef _createDefaultProfileSelections(void); 183static CFDictionaryRef _createAllCustomProfileSelections(void); 184static int _isActiveProfileDictValid( CFDictionaryRef p ); 185static void _purgeUnsupportedPowerSources( CFMutableDictionaryRef p ); 186static void ioCallout( 187 SCDynamicStoreRef store __unused, 188 CFArrayRef keys __unused, 189 void *ctxt); 190 191static IOReturn readAllPMPlistSettings( 192 bool removeUnsupportedSettings, 193 CFMutableDictionaryRef *customSettings, 194 CFDictionaryRef *profileSelections, 195 bool *defaultSettings); 196 197IOReturn _pm_connect(mach_port_t *newConnection); 198IOReturn _pm_disconnect(mach_port_t connection); 199/******************************************************************************/ 200/******************************************************************************/ 201/******************************************************************************/ 202 203 204/************************************************** 205* 206* Energy Saver Preferences 207* 208**************************************************/ 209 210CFDictionaryRef IOPMCopyCustomPMPreferences(void) 211{ 212 CFMutableDictionaryRef copiedPMPrefs = NULL; 213 CFDictionaryRef immutableRetPrefs = NULL; 214 215 /* IOPMCopyCustomPMPreferences returns the same thing IOPMCopyPMPreferences 216 * does. This is the recommended version to use; for clarity. 217 */ 218 219 copiedPMPrefs = IOPMCopyPMPreferences(); 220 if( copiedPMPrefs ) { 221 // Turn it from mutable to immutable 222 immutableRetPrefs = CFDictionaryCreateCopy( 223 kCFAllocatorDefault, (CFDictionaryRef)copiedPMPrefs ); 224 CFRelease(copiedPMPrefs); 225 return immutableRetPrefs; 226 } else { 227 return NULL; 228 } 229} 230 231/**************************************************/ 232 233CFMutableDictionaryRef IOPMCopyPMPreferences(void) 234{ 235 IOReturn ret; 236 CFMutableDictionaryRef settings = NULL; 237 238 ret = readAllPMPlistSettings( 239 kIOPMRemoveUnsupportedPreferences, 240 &settings, 241 NULL, NULL ); 242 243 if(kIOReturnSuccess == ret) { 244 return settings; 245 } else { 246 return NULL; 247 } 248} 249 250/**************************************************/ 251#if !TARGET_OS_IPHONE 252 253IOReturn IOPMCopyPMSetting( 254 CFStringRef key, 255 CFStringRef power_source, 256 CFTypeRef *outValue) 257{ 258 CFDictionaryRef ActiveSettings = NULL; 259 CFDictionaryRef perPS = NULL; 260 CFStringRef usePowerSource = power_source; 261 CFTypeRef psblob = NULL; 262 bool supported = false; 263 264 IOReturn ret; 265 266 if (!key || !outValue) { 267 ret = kIOReturnBadArgument; 268 goto exit; 269 } 270 271 *outValue = 0; 272 273 if (!usePowerSource) { 274 psblob = IOPSCopyPowerSourcesInfo(); 275 if (psblob) { 276 usePowerSource = IOPSGetProvidingPowerSourceType(psblob); 277 } else { 278 usePowerSource = CFSTR(kIOPMACPowerKey); 279 } 280 } 281 282 supported = IOPMFeatureIsAvailable(key, usePowerSource); 283 284 if (!supported) { 285 ret = kIOReturnUnsupported; 286 goto exit; 287 } 288 289 ActiveSettings = _copyActivePMPreferences(true); 290 if (ActiveSettings) { 291 perPS = (CFDictionaryRef)CFDictionaryGetValue( 292 ActiveSettings, usePowerSource); 293 294 if (perPS) { 295 *outValue = CFDictionaryGetValue(perPS, key); 296 } 297 } 298 299 if (*outValue) { 300 CFRetain(*outValue); 301 ret = kIOReturnSuccess; 302 } else { 303 ret = kIOReturnNotFound; 304 } 305 306 if (ActiveSettings) { 307 CFRelease(ActiveSettings); 308 } 309 310exit: 311 if (psblob) { 312 CFRelease(psblob); 313 } 314 return ret; 315} 316 317#endif 318/**************************************************/ 319 320CFDictionaryRef IOPMCopyActivePMPreferences(void) 321{ 322 return _copyActivePMPreferences(kIOPMRemoveUnsupportedPreferences); 323} 324 325CFDictionaryRef IOPMCopyUnabridgedActivePMPreferences(void) 326{ 327 return _copyActivePMPreferences(kIOPMKeepUnsupportedPreferences); 328} 329 330static CFDictionaryRef _copyActivePMPreferences( 331 bool removeUnsupportedSettings) 332{ 333 CFDictionaryRef active_profiles = NULL; 334 CFArrayRef system_profiles = NULL; 335 CFMutableDictionaryRef custom_settings = NULL; 336 CFMutableDictionaryRef return_val = NULL; 337 CFStringRef *active_profile_dict_keys = NULL; 338 CFNumberRef *active_profile_dict_values = NULL; 339 IOReturn ret; 340 int ps_count; 341 int i; 342 343 system_profiles = IOPMCopyPowerProfiles(); 344 if(!system_profiles) { 345 return NULL; 346 } 347 348 /* Depending on removeUnsupportedSettings argument, 349 * the returned custom_settings dictionary may have 350 * removed the settings lacking hardware support 351 * on this machine 352 */ 353 ret = readAllPMPlistSettings( removeUnsupportedSettings, 354 &custom_settings, 355 &active_profiles, NULL ); 356 if( kIOReturnSuccess != ret ) 357 { 358 goto exit; 359 } 360 361 if(!active_profiles || !system_profiles || !custom_settings) goto exit; 362 363 return_val = CFDictionaryCreateMutable(0, 0, 364 &kCFTypeDictionaryKeyCallBacks, 365 &kCFTypeDictionaryValueCallBacks); 366 367 ps_count = CFDictionaryGetCount(active_profiles); 368 active_profile_dict_keys = 369 (CFStringRef *)malloc(ps_count*sizeof(CFStringRef)); 370 active_profile_dict_values = 371 (CFNumberRef *)malloc(ps_count*sizeof(CFNumberRef)); 372 if(!active_profile_dict_keys || !active_profile_dict_values) goto exit; 373 374 CFDictionaryGetKeysAndValues( 375 active_profiles, 376 (const void **)active_profile_dict_keys, 377 (const void **)active_profile_dict_values); 378 379 for(i=0; i<ps_count; i++) 380 { 381 int profile_index; 382 CFDictionaryRef settings_per_power_source; 383 CFDictionaryRef sys_profile; 384 CFDictionaryRef tmp_settings; 385 386 if(!CFNumberGetValue(active_profile_dict_values[i], 387 kCFNumberIntType, &profile_index)) continue; 388 if(-1 == profile_index) { 389 // Custom profile for this power source 390 settings_per_power_source = CFDictionaryGetValue( 391 custom_settings, active_profile_dict_keys[i]); 392 } else { 393 // user has selected a system defined profile for this source 394 if( (profile_index < 0) || (profile_index > 4) ) continue; 395 sys_profile = isA_CFDictionary( 396 CFArrayGetValueAtIndex(system_profiles, profile_index)); 397 if(!sys_profile) continue; 398 settings_per_power_source = CFDictionaryGetValue(sys_profile, 399 active_profile_dict_keys[i]); 400 } 401 if(!settings_per_power_source) { 402 continue; 403 } 404 tmp_settings = CFDictionaryCreateCopy(kCFAllocatorDefault, 405 settings_per_power_source); 406 if(!tmp_settings) continue; 407 CFDictionarySetValue(return_val, active_profile_dict_keys[i], 408 tmp_settings); 409 CFRelease(tmp_settings); 410 } 411 412 413exit: 414 if(active_profile_dict_keys) free(active_profile_dict_keys); 415 if(active_profile_dict_values) free(active_profile_dict_values); 416 if(active_profiles) CFRelease(active_profiles); 417 if(system_profiles) CFRelease(system_profiles); 418 if(custom_settings) CFRelease(custom_settings); 419 return return_val; 420} 421 422/**************************************************/ 423 424 425// A duplicate function for IOPMSetPMPreferences 426// Provided as "IOPMSetCustomPMPreferences" for clarity 427IOReturn IOPMSetCustomPMPreferences(CFDictionaryRef ESPrefs) 428{ 429 return IOPMSetPMPreferences(ESPrefs); 430} 431/**************************************************/ 432 433IOReturn IOPMRevertPMPreferences(CFArrayRef keys_arr) 434{ 435 IOReturn ret = kIOReturnInternalError; 436 int keys_i = 0; 437 int keys_count = 0; 438 CFStringRef revert_this_setting = NULL; 439 bool these_are_defaults = false; 440 int csi = 0; 441 CFMutableDictionaryRef customSettings = NULL; 442 int customSettingsCount = 0; 443 CFDictionaryRef *customSettingsDicts = NULL; 444 CFStringRef *customSettingsKeys = NULL; 445 446 readAllPMPlistSettings(kIOPMRemoveUnsupportedPreferences, &customSettings, NULL, &these_are_defaults); 447 if (these_are_defaults) { 448 /* If the system has default settings, then there's nothing 449 * for us to revert to default. Good bye. 450 */ 451 ret = kIOReturnInvalid; 452 goto exit_and_free; 453 } 454 455 if (!keys_arr || (0 == (keys_count = CFArrayGetCount(keys_arr)))) { 456 /* Revert to OS Defaults 457 * PM tracks your current settings as indices into a now-defunct array of settings, called profiles. 458 * We "revert to defaults" by selecting profiles AC=2, Batt=1, UPS=1 459 * Note that "custom settings" are AC=-1, Batt=-1, UPS=-1 460 */ 461 462 CFDictionaryRef twooneoneprofiles = NULL; 463 464 CFStringRef tooKeys[kPowerSourcesCount] = { CFSTR(kIOPMACPowerKey), CFSTR(kIOPMBatteryPowerKey), CFSTR(kIOPMUPSPowerKey) }; 465 CFNumberRef tooVals[kPowerSourcesCount]; 466 int setVal = 0; 467 468 setVal = 2; 469 tooVals[0] = CFNumberCreate(0, kCFNumberIntType, &setVal); 470 setVal = 1; 471 tooVals[1] = CFNumberCreate(0, kCFNumberIntType, &setVal); 472 tooVals[2] = CFNumberCreate(0, kCFNumberIntType, &setVal); 473 474 twooneoneprofiles = CFDictionaryCreate(0, (const void **)tooKeys, (const void **)tooVals, kPowerSourcesCount, 475 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 476 477 if (twooneoneprofiles) { 478 IOPMSetActivePowerProfiles(twooneoneprofiles); 479 CFRelease(twooneoneprofiles); 480 } 481 482 CFRelease(tooVals[0]); 483 CFRelease(tooVals[1]); 484 CFRelease(tooVals[2]); 485 486 ret = kIOReturnSuccess; 487 goto exit_and_free; 488 } 489 490 customSettingsCount = CFDictionaryGetCount(customSettings); 491 customSettingsKeys = (CFStringRef *)malloc(customSettingsCount * sizeof(CFStringRef)); 492 customSettingsDicts = (CFDictionaryRef *)malloc(customSettingsCount * sizeof(CFDictionaryRef)); 493 CFDictionaryGetKeysAndValues(customSettings, (const void **)customSettingsKeys, (const void **)customSettingsDicts); 494 495 for (csi=0; csi<customSettingsCount; csi++) { 496 CFMutableDictionaryRef mutablePerPowerSourceCopy = NULL; 497 mutablePerPowerSourceCopy = CFDictionaryCreateMutableCopy(0, 0, customSettingsDicts[csi]); 498 if (!mutablePerPowerSourceCopy) { 499 continue; 500 } 501 502 // Remove each key in the caller's array from the PM Prefs dictionary 503 for (keys_i = 0; keys_i < keys_count; keys_i++) { 504 revert_this_setting = CFArrayGetValueAtIndex(keys_arr, keys_i); 505 if (isA_CFString(revert_this_setting)) { 506 CFDictionaryRemoveValue(mutablePerPowerSourceCopy, revert_this_setting); 507 } 508 } 509 510 CFDictionarySetValue(customSettings, customSettingsKeys[csi], mutablePerPowerSourceCopy); 511 CFRelease(mutablePerPowerSourceCopy); 512 } 513 514 ret = IOPMSetPMPreferences(customSettings); 515 516exit_and_free: 517 if (customSettings) { 518 CFRelease(customSettings); 519 } 520 if (customSettingsKeys) { 521 free(customSettingsKeys); 522 } 523 if (customSettingsDicts) { 524 free(customSettingsDicts); 525 } 526 return ret; 527} 528 529/**************************************************/ 530 531static IOReturn _doTouchEnergyPrefs(SCDynamicStoreRef ds) 532{ 533 CFStringRef energyPrefsKey = NULL; 534 IOReturn ret; 535 536 energyPrefsKey = SCDynamicStoreKeyCreatePreferences(NULL, kIOPMPrefsPath, kSCPreferencesKeyCommit); 537 538 if (!energyPrefsKey) { 539 return kIOReturnInternalError; 540 } 541 542 // Trigger a notification that the prefs have changed 543 544 if (!SCDynamicStoreNotifyValue(ds, energyPrefsKey)) 545 { 546 if(kSCStatusAccessError == SCError()) { 547 ret = kIOReturnNotPrivileged; 548 } else { 549 ret = kIOReturnError; 550 } 551 } else { 552 ret = kIOReturnSuccess; 553 } 554 555 if (energyPrefsKey) { 556 CFRelease(energyPrefsKey); 557 } 558 559 return ret; 560} 561 562// Sets (and activates) Custom power profile 563IOReturn IOPMSetPMPreferences(CFDictionaryRef ESPrefs) 564{ 565 IOReturn ret = kIOReturnError; 566 SCPreferencesRef energyPrefs = NULL; 567 568 if(NULL == ESPrefs) 569 { 570 SCDynamicStoreRef ds = NULL; 571 ds = SCDynamicStoreCreate(0, CFSTR("IOKit User Library - Touch"), NULL, NULL); 572 if(!ds) { 573 ret = kIOReturnInternalError; 574 } else { 575 ret = _doTouchEnergyPrefs(ds); 576 CFRelease(ds); 577 } 578 return ret; 579 } 580 581 energyPrefs = SCPreferencesCreate(0, kIOPMAppName, kIOPMPrefsPath); 582 if(!energyPrefs) { 583 return kIOReturnError; 584 } 585 586 if(!SCPreferencesLock(energyPrefs, true)) 587 { 588 // handle error 589 if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged; 590 else ret = kIOReturnError; 591 goto exit; 592 } 593 594 if(!SCPreferencesSetValue(energyPrefs, CFSTR("Custom Profile"), ESPrefs)) 595 { 596 ret = kIOReturnError; 597 goto exit; 598 } 599 600 // If older profiles exist, remove them in favor of the new format 601 SCPreferencesRemoveValue(energyPrefs, CFSTR(kIOPMACPowerKey)); 602 SCPreferencesRemoveValue(energyPrefs, CFSTR(kIOPMBatteryPowerKey)); 603 SCPreferencesRemoveValue(energyPrefs, CFSTR(kIOPMUPSPowerKey)); 604 605 if(!SCPreferencesCommitChanges(energyPrefs)) 606 { 607 // handle error 608 if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged; 609 else ret = kIOReturnError; 610 goto exit; 611 } 612 613 ret = kIOReturnSuccess; 614exit: 615 if(energyPrefs) { 616 SCPreferencesUnlock(energyPrefs); 617 CFRelease(energyPrefs); 618 } 619 return ret; 620} 621 622/**************************************************/ 623 624/* 625 * IOPMFeatureIsAvailable 626 ( 627 * @param PMFeature - Name of a PM feature (like "WakeOnRing" or "Reduce Processor Speed") 628 * @param power_source - The current power source (like "AC Power" or "Battery Power") 629 * @result true if the given PM feature is supported on the given power source, 630 * false if the feature is unsupported. 631 */ 632bool IOPMFeatureIsAvailable(CFStringRef PMFeature, CFStringRef power_source) 633{ 634 CFDictionaryRef supportedFeatures = NULL; 635 io_registry_entry_t registry_entry = MACH_PORT_NULL; 636 int return_this_value = 0; 637 638 if(!(registry_entry = getPMRootDomainRef())) 639 return false; 640 641 supportedFeatures = IORegistryEntryCreateCFProperty(registry_entry, CFSTR("Supported Features"), 642 kCFAllocatorDefault, kNilOptions); 643 644 if (!supportedFeatures) 645 return false; 646 647 if( CFEqual(PMFeature, CFSTR(kIOPMDarkWakeBackgroundTaskKey)) ) 648 { 649 650#if TARGET_OS_IPHONE 651 goto exit; 652#else 653 return_this_value = 0; 654 655 if (!power_source) 656 power_source = CFSTR(kIOPMACPowerKey); 657 658 // On new machines (late 2012 and beyond), IOPPF publishes PowerNap 659 // support using the kIOPMPowerNapSupportedKey 660 CFTypeRef pnDetails = CFDictionaryGetValue( supportedFeatures, 661 CFSTR(kIOPMPowerNapSupportedKey)); 662 if(featureSupportsPowerSource(pnDetails, power_source)) 663 { 664 return_this_value = 1; 665 goto exit; 666 } 667 668 669 CFTypeRef btdetails = CFDictionaryGetValue( supportedFeatures, 670 CFSTR(kIOPMDarkWakeBackgroundTaskKey)); 671 CFTypeRef ssdetails = CFDictionaryGetValue( supportedFeatures, 672 CFSTR(kIOPMSleepServicesKey)); 673 if(featureSupportsPowerSource(btdetails, power_source) || 674 featureSupportsPowerSource(ssdetails, power_source)) 675 { 676 return_this_value = 1; 677 } 678#endif 679 } 680 else 681 { 682 return_this_value = IOPMFeatureIsAvailableWithSupportedTable( 683 PMFeature, 684 power_source, 685 supportedFeatures); 686 } 687 688exit: 689 CFRelease(supportedFeatures); 690 691 return (return_this_value ? true:false); 692} 693 694 695bool IOPMFeatureIsAvailableWithSupportedTable( 696 CFStringRef PMFeature, 697 CFStringRef power_source, 698 CFDictionaryRef supportedFeatures) 699{ 700 CFStringRef supportedString = NULL; 701 CFTypeRef featureDetails = NULL; 702 bool ret = false; 703 704 if (!power_source) 705 power_source = CFSTR(kIOPMACPowerKey); 706 707 if (!supportedFeatures) 708 return false; 709 710 /* Basic sleep timer settings are always available * 711 * TTY connection ability to prevent sleep is always available */ 712 if (CFEqual(PMFeature, CFSTR(kIOPMDisplaySleepKey)) 713 || CFEqual(PMFeature, CFSTR(kIOPMSystemSleepKey)) 714 || CFEqual(PMFeature, CFSTR(kIOPMDiskSleepKey)) 715 || CFEqual(PMFeature, CFSTR(kIOPMTTYSPreventSleepKey))) 716 { 717 ret = true; 718 goto exit; 719 } 720 721 /* deprecated - kIOPMRestartOnKernelPanicKey 722 * 11195840 Remove "restart automatically if computer freezes" check-box 723 */ 724 if (CFEqual(PMFeature, CFSTR(kIOPMRestartOnKernelPanicKey))) { 725 ret = false; 726 goto exit; 727 } 728 729 // ********************************* 730 // Special case for PowerButtonSleep 731 732 if(CFEqual(PMFeature, CFSTR(kIOPMSleepOnPowerButtonKey))) 733 { 734#if TARGET_OS_IPHONE 735 ret = false; 736#else 737 CFArrayRef tmp_array = NULL; 738 // Pressing the power button only causes sleep on desktop PowerMacs, 739 // cubes, and iMacs. 740 // Therefore this feature is not supported on portables. 741 // We'll use the presence of a battery (or the capability for a battery) 742 // as evidence whether this is a portable or not. 743 IOReturn r = IOPMCopyBatteryInfo(kIOMasterPortDefault, &tmp_array); 744 if((r == kIOReturnSuccess) && tmp_array) 745 { 746 CFRelease(tmp_array); 747 ret = false; 748 } else ret = true; 749#endif 750 goto exit; 751 } 752 753 // ********************************* 754 // Special case for ReduceBrightness 755 756 if ( CFEqual(PMFeature, CFSTR(kIOPMReduceBrightnessKey)) ) 757 { 758 // ReduceBrightness feature is only supported on laptops 759 // and on desktops with UPS with brightness-adjustable LCD displays. 760 // These machines report a "DisplayDims" property in the 761 // supportedFeatures dictionary. 762 // ReduceBrightness is never supported on AC Power. 763 CFTypeRef ps = IOPSCopyPowerSourcesInfo(); 764 if ( ps 765 && ( IOPSGetActiveBattery(ps) || IOPSGetActiveUPS(ps) ) 766 && supportedFeatures 767 && CFDictionaryGetValue(supportedFeatures, CFSTR("DisplayDims")) 768 && !CFEqual(power_source, CFSTR(kIOPMACPowerKey)) ) 769 { 770 ret = true; 771 } else { 772 ret = false; 773 } 774 775 if (ps) 776 CFRelease(ps); 777 goto exit; 778 } 779 780 // *********************************** 781 // Generic code for all other settings 782 783 supportedString = supportedNameForPMName( PMFeature ); 784 if(!supportedString) { 785 ret = false; 786 goto exit; 787 } 788 789 featureDetails = CFDictionaryGetValue(supportedFeatures, supportedString); 790 if(!featureDetails) { 791 ret = false; 792 goto exit; 793 } 794 795 if(featureSupportsPowerSource(featureDetails, power_source)) 796 { 797 ret = true; 798 } 799 800 801exit: 802 return ret; 803} 804 805/**************************************************/ 806 807// How we determine what ActivePowerProfiles to return: 808// (1) If the user has specified any profiles in the 809// PM prefs file, we'll return those. 810// (2) If the user hasn't explicitly specified any 811// profiles, we'll look to their Custom settings: 812// (3) If, in the past, a user has specified any PM settings at 813// all (say from before an upgrade install), we'll return 814// (-1, -1, -1) and respect those settings as custom settings. 815// (4) If there are no specified profiles and no previous specified 816// custom settings, then we'll return (2, 1, 1) as specified 817// in PowerManagement.bundle's com.apple.SystemPowerProfileDefaults.plist 818// 819// Also, note that in the case of (1), we'll re-populate any settings not 820// specified for a particular power source (UPS's are easy to plug/unplug) 821// with the defaults obtained as in (4). 822// 823// For all steps above, we'll strip any irrelevant settings before 824// returning the dictionary (i.e. battery or UPS settings will not be 825// returned where unsupported) 826 827CFDictionaryRef IOPMCopyActivePowerProfiles(void) 828{ 829 IOReturn ret; 830 CFDictionaryRef activeProfiles; 831 832 ret = readAllPMPlistSettings( 833 kIOPMRemoveUnsupportedPreferences, 834 NULL, 835 &activeProfiles, NULL); 836 837 if(kIOReturnSuccess == ret) { 838 return activeProfiles; 839 } else { 840 return NULL; 841 } 842} 843 844/**************************************************/ 845 846IOReturn IOPMSetActivePowerProfiles(CFDictionaryRef which_profile) 847{ 848 CFDataRef profiles_data; 849 vm_address_t profiles_buffer; 850 IOByteCount buffer_len; 851 kern_return_t kern_result; 852 IOReturn return_val = kIOReturnError; 853 mach_port_t server_port = MACH_PORT_NULL; 854 855 if(!_isActiveProfileDictValid(which_profile)) { 856 return kIOReturnBadArgument; 857 } 858 859 // open reference to PM configd 860 kern_result = bootstrap_look_up2(bootstrap_port, 861 kIOPMServerBootstrapName, 862 &server_port, 863 0, 864 BOOTSTRAP_PRIVILEGED_SERVER); 865 if(KERN_SUCCESS != kern_result) { 866 return kIOReturnError; 867 } 868 869 profiles_data = IOCFSerialize(which_profile, 0); 870 profiles_buffer = (vm_address_t) CFDataGetBytePtr(profiles_data); 871 buffer_len = CFDataGetLength(profiles_data); 872 873 // toss dictionary over the wall to conigd via mig-generated interface 874 // configd will perform a permissions check. If the caller is root, 875 // admin, or console, configd will write the prefs file from its 876 // root context. 877 kern_result = io_pm_set_active_profile(server_port, 878 profiles_buffer, buffer_len, 879 &return_val); 880 881 mach_port_deallocate(mach_task_self(), server_port); 882 CFRelease(profiles_data); 883 884 if(KERN_SUCCESS == kern_result) { 885 return return_val; 886 } else { 887 return kIOReturnInternalError; 888 } 889} 890 891/**************************************************/ 892 893/*** 894 Returns a CFRunLoopSourceRef that notifies the caller when power source 895 information changes. 896 Arguments: 897 IOPowerSourceCallbackType callback - A function to be called whenever 898 ES prefs file on disk changes 899 void *context - Any user-defined pointer, passed to the callback. 900 Returns NULL if there were any problems. 901 Caller must CFRelease() the returned value. 902***/ 903CFRunLoopSourceRef IOPMPrefsNotificationCreateRunLoopSource( 904 IOPMPrefsCallbackType callback, 905 void *context) 906{ 907 SCDynamicStoreRef store = NULL; 908 CFStringRef EnergyPrefsKey = NULL; 909 CFRunLoopSourceRef SCDrls = NULL; 910 user_callback_context *ioContext = NULL; 911 SCDynamicStoreContext scContext = {0, NULL, CFRetain, CFRelease, NULL}; 912 913 if(!callback) return NULL; 914 915 scContext.info = CFDataCreateMutable(NULL, sizeof(user_callback_context)); 916 CFDataSetLength(scContext.info, sizeof(user_callback_context)); 917 ioContext = (user_callback_context *)CFDataGetBytePtr(scContext.info); 918 ioContext->context = context; 919 ioContext->callback = callback; 920 921 // Open connection to SCDynamicStore. User's callback as context. 922 store = SCDynamicStoreCreate(kCFAllocatorDefault, 923 CFSTR("IOKit Preferences Copy"), ioCallout, (void *)&scContext); 924 if(!store) return NULL; 925 926 // Setup notification for changes in Energy Saver prefences 927 EnergyPrefsKey = SCDynamicStoreKeyCreatePreferences( 928 NULL, 929 kIOPMPrefsPath, 930 kSCPreferencesKeyApply); 931 if(EnergyPrefsKey) { 932 SCDynamicStoreAddWatchedKey(store, EnergyPrefsKey, FALSE); 933 CFRelease(EnergyPrefsKey); 934 } 935 936 // Obtain the CFRunLoopSourceRef from this SCDynamicStoreRef session 937 SCDrls = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0); 938 CFRelease(store); 939 940 return SCDrls; 941} 942 943/******************************************************************************/ 944/******************************************************************************/ 945/******************************************************************************/ 946// Internals 947 948static void mergeUserDefaultOverriddenSettings(CFMutableDictionaryRef es) 949{ 950 CFMutableDictionaryRef batt = NULL; 951 CFMutableDictionaryRef ac = NULL; 952 CFMutableDictionaryRef ups = NULL; 953 CFDictionaryRef acOver = NULL; 954 CFDictionaryRef battOver = NULL; 955 CFDictionaryRef upsOver = NULL; 956 SCDynamicStoreRef dynamic_store = NULL; 957 CFDictionaryRef userOverrides = NULL; 958 959 /* 960 * There might be a CFDictionary in the SCDynamicStore at 961 * "State:/IOKit/PowerManagement/UserOverrides" 962 * == kIOPMDynamicStoreUserOverridesKey 963 * If there is, then we will prefer to use its settings 964 * as default settings, rather than our hard-coded defaults, 965 * for unspecified setting values. 966 */ 967 dynamic_store = SCDynamicStoreCreate(0, CFSTR("IOKit User Library - PM defaults"), NULL, NULL); 968 969 if (dynamic_store) 970 { 971 userOverrides = SCDynamicStoreCopyValue(dynamic_store, CFSTR(kIOPMDynamicStoreUserOverridesKey)); 972 CFRelease(dynamic_store); 973 } 974 975 if (NULL == userOverrides) 976 return; 977 978 if (!isA_CFDictionary(userOverrides)) { 979 CFRelease(userOverrides); 980 return; 981 } 982 983 acOver = CFDictionaryGetValue(userOverrides, CFSTR(kIOPMACPowerKey)); 984 battOver = CFDictionaryGetValue(userOverrides, CFSTR(kIOPMBatteryPowerKey)); 985 upsOver = CFDictionaryGetValue(userOverrides, CFSTR(kIOPMUPSPowerKey)); 986 987 // Overrides either contains 3 dictionaries of PM Settings keyed as 988 // AC, Battery, and UPS Power, or it is itself a dictionary of PM Settings. 989 if(acOver && battOver && upsOver) 990 { 991 // Good. All 3 power source settings types are represented. 992 // Do nothing here. 993 } else if(!acOver && !battOver && !upsOver) 994 { 995 // The dictionary didn't specify any per-power source overrides, which 996 // means that it's a flat dictionary strictly of PM settings. 997 // We duplicate it 3 ways, as each overridden setting in this dictionary 998 // will be applied to each power source's settings. 999 acOver = battOver = upsOver = userOverrides; 1000 } else { 1001 return; 1002 } 1003 1004 ac = (CFMutableDictionaryRef)CFDictionaryGetValue(es, CFSTR(kIOPMACPowerKey)); 1005 batt = (CFMutableDictionaryRef)CFDictionaryGetValue(es, CFSTR(kIOPMBatteryPowerKey)); 1006 ups = (CFMutableDictionaryRef)CFDictionaryGetValue(es, CFSTR(kIOPMUPSPowerKey)); 1007 1008 if (ac) { 1009 mergeDictIntoMutable(ac, acOver, kKeepOriginalValues); 1010 } 1011 1012 if (batt) { 1013 mergeDictIntoMutable(batt, battOver, kKeepOriginalValues); 1014 } 1015 1016 if (ups) { 1017 mergeDictIntoMutable(ups, upsOver, kKeepOriginalValues); 1018 } 1019 1020 CFRelease (userOverrides); 1021 1022 return; 1023} 1024 1025static int addDefaultEnergySettings(CFMutableDictionaryRef sys) 1026{ 1027 CFMutableDictionaryRef batt = NULL; 1028 CFMutableDictionaryRef ac = NULL; 1029 CFMutableDictionaryRef ups = NULL; 1030 int i; 1031 CFNumberRef val; 1032 CFStringRef key; 1033 1034 1035 batt = (CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMBatteryPowerKey)); 1036 ac = (CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMACPowerKey)); 1037 ups = (CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMUPSPowerKey)); 1038 1039 /* 1040 * Note that in the following "poplulation" loops, we're using 1041 * CFDictionaryAddValue rather than CFDictionarySetValue. If a value is 1042 * already present AddValue will not replace it. 1043 */ 1044 1045 /* 1046 * Populate default battery dictionary 1047 */ 1048 1049 if (batt) { 1050 for (i=0; i<kPMSettingsCount; i++) 1051 { 1052 key = CFStringCreateWithCString(0, defaultSettings[i].keyName, kCFStringEncodingMacRoman); 1053 val = CFNumberCreate(0, kCFNumberSInt32Type, &defaultSettings[i].defaultValueBattery); 1054 1055 CFDictionaryAddValue(batt, key, val); 1056 1057 CFRelease(key); 1058 CFRelease(val); 1059 } 1060 CFDictionaryAddValue(batt, CFSTR(kIOHibernateFileKey), CFSTR(kIOHibernateDefaultFile)); 1061 } 1062 1063 /* 1064 * Populate default AC dictionary 1065 */ 1066 if (ac) 1067 { 1068 for (i=0; i<kPMSettingsCount; i++) 1069 { 1070 key = CFStringCreateWithCString(0, defaultSettings[i].keyName, kCFStringEncodingMacRoman); 1071 val = CFNumberCreate(0, kCFNumberSInt32Type, &defaultSettings[i].defaultValueAC); 1072 1073 CFDictionaryAddValue(ac, key, val); 1074 1075 CFRelease(key); 1076 CFRelease(val); 1077 } 1078 1079 CFDictionaryAddValue(ac, CFSTR(kIOHibernateFileKey), CFSTR(kIOHibernateDefaultFile)); 1080 } 1081 1082 /* 1083 * Populate default UPS dictionary 1084 */ 1085 if (ups) { 1086 for (i=0; i<kPMSettingsCount; i++) 1087 { 1088 key = CFStringCreateWithCString(0, defaultSettings[i].keyName, kCFStringEncodingMacRoman); 1089 val = CFNumberCreate(0, kCFNumberSInt32Type, &defaultSettings[i].defaultValueAC); 1090 1091 CFDictionaryAddValue(ups, key, val); 1092 1093 CFRelease(key); 1094 CFRelease(val); 1095 } 1096 1097 CFDictionaryAddValue(ups, CFSTR(kIOHibernateFileKey), CFSTR(kIOHibernateDefaultFile)); 1098 } 1099 1100 return 0; 1101} 1102 1103static void addSystemProfileEnergySettings( 1104 CFDictionaryRef user_profile_selections, 1105 CFMutableDictionaryRef passed_in) 1106{ 1107 CFArrayRef system_profiles = NULL; 1108 CFDictionaryRef profile_at_idx = NULL; 1109 CFDictionaryRef finally_actual_settings = NULL; 1110 1111 CFNumberRef this_profile_choice = NULL; 1112 CFNumberRef default_profile_choice = NULL; 1113 CFDictionaryRef default_profile_selections = NULL; 1114 int int_profile_choice = 0; 1115 1116 CFMutableDictionaryRef ps_passed_in = NULL; 1117 CFStringRef this_power_source = NULL; 1118 int i; 1119 1120 // Does the user currently have any profiles selected? 1121 // If not, IOPMCopyActivePowerProfiles returns a (2,1,1) default 1122 if(!user_profile_selections) return; 1123 1124 default_profile_selections = _createDefaultProfileSelections(); 1125 if(!isA_CFDictionary(default_profile_selections)) 1126 return; 1127 1128 // Copy the full CFArray of system profiles 1129 system_profiles = IOPMCopyPowerProfiles(); 1130 if(!system_profiles) goto exit_cleanup; 1131 1132 // For each power source, 1133 for(i = 0; i<kPowerSourcesCount; i++) 1134 { 1135 this_power_source = getPowerSourceString(i); 1136 if(!this_power_source) continue; 1137 1138 // Grab the profile number from user_profile_selections 1139 this_profile_choice = isA_CFNumber( CFDictionaryGetValue( 1140 user_profile_selections, this_power_source)); 1141 if(this_profile_choice) { 1142 CFNumberGetValue( this_profile_choice, 1143 kCFNumberIntType, &int_profile_choice); 1144 } 1145 1146 /* -1 == Custom settings in use? 1147 Then we need to merge in the default settings [from profiles 2,1,1] 1148 for this power source. 1149 */ 1150 if( -1 == int_profile_choice ) { 1151 default_profile_choice = isA_CFNumber( CFDictionaryGetValue( 1152 default_profile_selections, this_power_source)); 1153 if(default_profile_choice) { 1154 CFNumberGetValue( default_profile_choice, 1155 kCFNumberIntType, &int_profile_choice); 1156 } 1157 } 1158 1159 // And if the integer profile index is outside the acceptable range, 1160 // we give it a sane value 1161 if ( (int_profile_choice < 0) 1162 || (int_profile_choice > kPowerProfilesCount) ) 1163 { 1164 int_profile_choice = 2; 1165 } 1166 1167 // Index into systemProfiles at profileNumber 1168 profile_at_idx = CFArrayGetValueAtIndex( system_profiles, 1169 int_profile_choice); 1170 if(!profile_at_idx) continue; 1171 1172 // From the profile's CFDictionary, extract the final actual 1173 // settings CFDictionary for "this profile number" and for 1174 // "this power source" 1175 finally_actual_settings = CFDictionaryGetValue( 1176 profile_at_idx, this_power_source); 1177 1178 // Gently merge this settings CFDictionary into the passed-in 1179 // settings dictionary's appropiate power-source specific dictionary 1180 1181 ps_passed_in = (CFMutableDictionaryRef) 1182 CFDictionaryGetValue(passed_in, this_power_source); 1183 1184 if(!finally_actual_settings || !ps_passed_in) continue; 1185 1186 mergeDictIntoMutable( ps_passed_in, 1187 finally_actual_settings, 1188 kKeepOriginalValues); 1189 } 1190 1191exit_cleanup: 1192// if(user_profile_selections) CFRelease(user_profile_selections); 1193 if(default_profile_selections) CFRelease(default_profile_selections); 1194 if(system_profiles) CFRelease(system_profiles); 1195 1196 return; 1197} 1198 1199 1200/* getPMRootDomainRef 1201 * 1202 * Caller should not release the returned io_registry_entry_t 1203 */ 1204__private_extern__ io_registry_entry_t getPMRootDomainRef(void) 1205{ 1206 static io_registry_entry_t cached_root_domain = MACH_PORT_NULL; 1207 1208 if( MACH_PORT_NULL == cached_root_domain ) { 1209 cached_root_domain = IORegistryEntryFromPath( kIOMasterPortDefault, 1210 kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain"); 1211 1212 } 1213 return cached_root_domain; 1214} 1215 1216 1217/* Maps a PowerManagement string constant 1218 * -> to its corresponding Supported Feature in IOPMrootDomain 1219 */ 1220static CFStringRef 1221supportedNameForPMName( CFStringRef pm_name ) 1222{ 1223#if TARGET_OS_IPHONE 1224 if( CFEqual(pm_name, CFSTR(kIOPMReduceBrightnessKey)) 1225 || CFEqual(pm_name, CFSTR(kIOPMDisplaySleepUsesDimKey)) ) 1226#else 1227 if(CFEqual(pm_name, CFSTR(kIOPMDisplaySleepUsesDimKey))) 1228#endif /* TARGET_OS_IPHONE */ 1229 { 1230 return CFSTR("DisplayDims"); 1231 } 1232 1233 if(CFEqual(pm_name, CFSTR(kIOPMWakeOnLANKey)) 1234 || CFEqual(pm_name, CFSTR(kIOPMPrioritizeNetworkReachabilityOverSleepKey))) 1235 { 1236 return CFSTR("WakeOnMagicPacket"); 1237 } 1238 1239 if(CFEqual(pm_name, CFSTR(kIOPMMobileMotionModuleKey))) 1240 { 1241 return CFSTR("MobileMotionModule"); 1242 } 1243 1244 if( CFEqual(pm_name, CFSTR(kIOHibernateModeKey)) 1245 || CFEqual(pm_name, CFSTR(kIOHibernateFreeRatioKey)) 1246 || CFEqual(pm_name, CFSTR(kIOHibernateFreeTimeKey)) 1247 || CFEqual(pm_name, CFSTR(kIOHibernateFileKey)) 1248 || CFEqual(pm_name, CFSTR(kIOHibernateFeatureKey))) 1249 { 1250 return CFSTR(kIOHibernateFeatureKey); 1251 } 1252 1253 if (CFEqual(pm_name, CFSTR(kIOPMDeepSleepEnabledKey)) 1254 || CFEqual(pm_name, CFSTR(kIOPMDeepSleepDelayKey))) 1255 { 1256 return CFSTR("DeepSleep"); 1257 } 1258 1259 if (CFEqual(pm_name, CFSTR(kIOPMAutoPowerOffEnabledKey)) 1260 || CFEqual(pm_name, CFSTR(kIOPMAutoPowerOffDelayKey))) 1261 { 1262 return CFSTR("AutoPowerOff"); 1263 } 1264 1265 return pm_name; 1266} 1267 1268// Helper for IOPMFeatureIsAvailable 1269static bool 1270featureSupportsPowerSource(CFTypeRef featureDetails, CFStringRef power_source) 1271{ 1272 CFNumberRef featureNum = NULL; 1273 CFNumberRef tempNum = NULL; 1274 CFArrayRef featureArr = NULL; 1275 uint32_t ps_support = 0; 1276 uint32_t tmp; 1277 unsigned int i; 1278 1279 if( (featureNum = isA_CFNumber(featureDetails)) ) 1280 { 1281 CFNumberGetValue(featureNum, kCFNumberSInt32Type, &ps_support); 1282 } else if( (featureArr = isA_CFArray(featureDetails)) ) 1283 { 1284 // If several entitites are asserting a given feature, we OR 1285 // together their supported power sources. 1286 1287 unsigned int arrayCount = CFArrayGetCount(featureArr); 1288 for(i = 0; i<arrayCount; i++) 1289 { 1290 tempNum = isA_CFNumber(CFArrayGetValueAtIndex(featureArr, i)); 1291 if(tempNum) { 1292 CFNumberGetValue(tempNum, kCFNumberSInt32Type, &tmp); 1293 ps_support |= tmp; 1294 } 1295 } 1296 } 1297 1298 if(!power_source) { 1299 1300 // Lack of a defined power source just gets a "true" return 1301 // if the setting is supported on ANY power source. 1302 1303 return (ps_support ? true : false); 1304 } 1305 1306 if(CFEqual(CFSTR(kIOPMACPowerKey), power_source) ) 1307 { 1308 return (ps_support & kIOPMSupportedOnAC) ? true : false; 1309 } else if(CFEqual(CFSTR(kIOPMBatteryPowerKey), power_source) ) 1310 { 1311 return (ps_support & kIOPMSupportedOnBatt) ? true : false; 1312 } else if(CFEqual(CFSTR(kIOPMUPSPowerKey), power_source) ) 1313 { 1314 return (ps_support & kIOPMSupportedOnUPS) ? true : false; 1315 } else { 1316 // unexpected power source argument 1317 return false; 1318 } 1319 1320} 1321 1322 1323/*** 1324 * removeIrrelevantPMProperties 1325 * 1326 * Prunes unsupported properties from the energy dictionary. 1327 * e.g. If your machine doesn't have a modem, this removes the Wake On Ring property. 1328 ***/ 1329static void IOPMRemoveIrrelevantProperties(CFMutableDictionaryRef energyPrefs) 1330{ 1331 int profile_count = 0; 1332 int dict_count = 0; 1333 CFStringRef *profile_keys = NULL; 1334 CFDictionaryRef *profile_vals = NULL; 1335 CFStringRef *dict_keys = NULL; 1336 CFDictionaryRef *dict_vals = NULL; 1337 CFMutableDictionaryRef this_profile = NULL; 1338 CFTypeRef ps_snapshot = NULL; 1339 CFDictionaryRef _supportedCached = NULL; 1340 io_registry_entry_t _rootDomain = IO_OBJECT_NULL; 1341 1342 ps_snapshot = IOPSCopyPowerSourcesInfo(); 1343 1344 // Grab a copy of RootDomain's supported energy saver settings 1345 _rootDomain = getPMRootDomainRef(); 1346 if (IO_OBJECT_NULL != _rootDomain) 1347 { 1348 _supportedCached = IORegistryEntryCreateCFProperty(_rootDomain, 1349 CFSTR("Supported Features"), 1350 kCFAllocatorDefault, kNilOptions); 1351 } 1352 1353 /* 1354 * Remove features when not supported - 1355 * Wake On Administrative Access, Dynamic Speed Step, etc. 1356 */ 1357 profile_count = CFDictionaryGetCount(energyPrefs); 1358 profile_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * profile_count); 1359 profile_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * profile_count); 1360 if (!profile_keys || !profile_vals) 1361 goto exit; 1362 1363 CFDictionaryGetKeysAndValues(energyPrefs, (const void **)profile_keys, 1364 (const void **)profile_vals); 1365 // For each CFDictionary at the top level (battery, AC) 1366 while(--profile_count >= 0) 1367 { 1368 if(kCFBooleanTrue != IOPSPowerSourceSupported(ps_snapshot, profile_keys[profile_count])) 1369 { 1370 // Remove dictionary if the whole power source isn't supported on this machine. 1371 CFDictionaryRemoveValue(energyPrefs, profile_keys[profile_count]); 1372 } else { 1373 1374 // Make a mutable copy of the prefs dictionary 1375 1376 this_profile = (CFMutableDictionaryRef)isA_CFDictionary( 1377 CFDictionaryGetValue(energyPrefs, profile_keys[profile_count])); 1378 if(!this_profile) 1379 continue; 1380 1381 this_profile = CFDictionaryCreateMutableCopy(NULL, 0, this_profile); 1382 if(!this_profile) 1383 continue; 1384 1385 CFDictionarySetValue(energyPrefs, profile_keys[profile_count], this_profile); 1386 CFRelease(this_profile); 1387 1388 // And prune unneeded settings from our new mutable property 1389 1390 dict_count = CFDictionaryGetCount(this_profile); 1391 dict_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * dict_count); 1392 dict_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * dict_count); 1393 if (!dict_keys || !dict_vals) 1394 continue; 1395 CFDictionaryGetKeysAndValues(this_profile, 1396 (const void **)dict_keys, (const void **)dict_vals); 1397 // For each specific property within each dictionary 1398 while(--dict_count >= 0) 1399 { 1400 if( CFEqual((CFStringRef)dict_keys[dict_count], CFSTR(kIOPMDarkWakeBackgroundTaskKey)) ) 1401 { 1402#if !TARGET_OS_IPHONE 1403 // We conditionalize PowerNap support on kIOPMPowerNapSupportedKey for all 1404 // machines late 2012 and beyond. The presence of this key is a sufficient 1405 // condition to support PowerNap 1406 bool supportsNewPNKey = false; 1407 if(IOPMFeatureIsAvailableWithSupportedTable( CFSTR(kIOPMPowerNapSupportedKey), 1408 (CFStringRef)profile_keys[profile_count], _supportedCached)) { 1409 supportsNewPNKey = true; 1410 } 1411 1412 // For legacy machines, we look for either the kIOPMDarkWakeBackgroundTaskKey or the 1413 // kIOPMSleepServicesKey 1414 if ( ((!IOPMFeatureIsAvailableWithSupportedTable( CFSTR(kIOPMDarkWakeBackgroundTaskKey), 1415 (CFStringRef)profile_keys[profile_count], _supportedCached) && 1416 !IOPMFeatureIsAvailableWithSupportedTable( CFSTR(kIOPMSleepServicesKey), 1417 (CFStringRef)profile_keys[profile_count], _supportedCached)) 1418 && !supportsNewPNKey 1419 ) 1420 { 1421 CFDictionaryRemoveValue(this_profile, (CFStringRef)dict_keys[dict_count]); 1422 } 1423#endif /* !TARGET_OS_IPHONE */ 1424 } 1425 else if( !IOPMFeatureIsAvailableWithSupportedTable((CFStringRef)dict_keys[dict_count], 1426 (CFStringRef)profile_keys[profile_count], _supportedCached) ) 1427 { 1428 // If the property isn't supported, remove it 1429 CFDictionaryRemoveValue(this_profile, 1430 (CFStringRef)dict_keys[dict_count]); 1431 } 1432 } 1433 free(dict_keys); 1434 free(dict_vals); 1435 } 1436 } 1437 1438exit: 1439 if (profile_keys) 1440 free(profile_keys); 1441 if (profile_vals) 1442 free(profile_vals); 1443 if (ps_snapshot) 1444 CFRelease(ps_snapshot); 1445 if (_supportedCached) 1446 CFRelease(_supportedCached); 1447 return; 1448} 1449 1450/*** 1451 * getCheetahPumaEnergySettings 1452 * 1453 * Reads the old Energy Saver preferences file from /Library/Preferences/com.apple.PowerManagement.xml 1454 * 1455 ***/ 1456static int getCheetahPumaEnergySettings(CFMutableDictionaryRef energyPrefs) 1457{ 1458 SCPreferencesRef CheetahPrefs = NULL; 1459 CFMutableDictionaryRef s = NULL; 1460 CFNumberRef n; 1461 CFBooleanRef b; 1462 1463 if(!energyPrefs) return 0; 1464 CheetahPrefs = SCPreferencesCreate (kCFAllocatorDefault, 1465 CFSTR("I/O Kit PM Library"), 1466 CFSTR("/Library/Preferences/com.apple.PowerManagement.plist")); 1467 1468 if(!CheetahPrefs) return 0; 1469 1470 s = (CFMutableDictionaryRef)CFDictionaryGetValue( energyPrefs, 1471 CFSTR(kIOPMBatteryPowerKey)); 1472 if(!s) 1473 { 1474 CFRelease(CheetahPrefs); 1475 return 0; 1476 } 1477 n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDimKey); 1478 if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDisplaySleepKey), n); 1479 n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDiskKey); 1480 if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDiskSleepKey), n); 1481 n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahSleepKey); 1482 if(n) CFDictionaryAddValue(s, CFSTR(kIOPMSystemSleepKey), n); 1483 b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahRestartOnPowerLossKey); 1484 if(b) CFDictionaryAddValue(s, CFSTR(kIOPMRestartOnPowerLossKey), b); 1485 b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeForNetworkAccessKey); 1486 if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnLANKey), b); 1487 b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeOnRingKey); 1488 if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnRingKey), b); 1489 1490 1491 s = (CFMutableDictionaryRef)CFDictionaryGetValue(energyPrefs, CFSTR(kIOPMACPowerKey)); 1492 if(!s) 1493 { 1494 CFRelease(CheetahPrefs); 1495 return 0; 1496 } 1497 n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDimKey); 1498 if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDisplaySleepKey), n); 1499 n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDiskKey); 1500 if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDiskSleepKey), n); 1501 n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahSleepKey); 1502 if(n) CFDictionaryAddValue(s, CFSTR(kIOPMSystemSleepKey), n); 1503 b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahRestartOnPowerLossKey); 1504 if(b) CFDictionaryAddValue(s, CFSTR(kIOPMRestartOnPowerLossKey), b); 1505 b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeForNetworkAccessKey); 1506 if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnLANKey), b); 1507 b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeOnRingKey); 1508 if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnRingKey), b); 1509 1510 1511 CFRelease(CheetahPrefs); 1512 1513 return 1; // success 1514} 1515 1516 1517/************************************************** 1518* 1519* System Power Settings 1520* 1521**************************************************/ 1522 1523IOReturn IOPMActivateSystemPowerSettings( void ) 1524{ 1525 io_registry_entry_t rootdomain = MACH_PORT_NULL; 1526 CFDictionaryRef settings = NULL; 1527 IOReturn ret = kIOReturnSuccess; 1528 bool disable_sleep = false; 1529 1530 settings = IOPMCopySystemPowerSettings(); 1531 if(!settings) { 1532 goto exit; 1533 } 1534 1535 // Disable Sleep? 1536 disable_sleep = (kCFBooleanTrue == 1537 CFDictionaryGetValue( settings, kIOPMSleepDisabledKey )); 1538 1539 rootdomain = getPMRootDomainRef(); 1540 ret = IORegistryEntrySetCFProperty( rootdomain, kIOPMSleepDisabledKey, 1541 (disable_sleep ? kCFBooleanTrue : kCFBooleanFalse)); 1542 1543#if !TARGET_OS_IPHONE 1544 bool avoid_keyStore = false; 1545 // Disable FDE Key Store on SMC 1546 avoid_keyStore = (kCFBooleanTrue == 1547 CFDictionaryGetValue( settings, CFSTR(kIOPMDestroyFVKeyOnStandbyKey) )); 1548 ret = IORegistryEntrySetCFProperty( rootdomain, CFSTR(kIOPMDestroyFVKeyOnStandbyKey), 1549 (avoid_keyStore ? kCFBooleanTrue : kCFBooleanFalse)); 1550 1551#endif 1552 1553exit: 1554 if(settings) CFRelease( settings ); 1555 return ret; 1556} 1557 1558CFDictionaryRef IOPMCopySystemPowerSettings(void) 1559{ 1560 CFDictionaryRef systemPowerDictionary = NULL; 1561 CFDictionaryRef tmp_dict = NULL; 1562 SCPreferencesRef energyPrefs = NULL; 1563 1564 energyPrefs = SCPreferencesCreate( kCFAllocatorDefault, 1565 kIOPMAppName, kIOPMPrefsPath ); 1566 if(!energyPrefs) { 1567 return NULL; 1568 } 1569 1570 tmp_dict = isA_CFDictionary(SCPreferencesGetValue( energyPrefs, 1571 CFSTR("SystemPowerSettings"))); 1572 1573 if(!tmp_dict) { 1574 goto exit; 1575 } 1576 1577 systemPowerDictionary = CFDictionaryCreateCopy(0, tmp_dict); 1578 1579exit: 1580 if(energyPrefs) CFRelease(energyPrefs); 1581 return systemPowerDictionary; 1582} 1583 1584IOReturn IOPMSetSystemPowerSetting( CFStringRef key, CFTypeRef value) 1585{ 1586 IOReturn ret = kIOReturnError; 1587 SCPreferencesRef energyPrefs = NULL; 1588 1589 CFMutableDictionaryRef systemPowerDictionary = NULL; 1590 CFDictionaryRef tmp_dict = NULL; 1591 1592 energyPrefs = SCPreferencesCreate( 0, kIOPMAppName, kIOPMPrefsPath ); 1593 if(!energyPrefs) 1594 { 1595 if(kSCStatusAccessError == SCError()) 1596 return kIOReturnNotPrivileged; 1597 else 1598 return kIOReturnError; 1599 } 1600 1601 /* We lock energyPrefs here to prevent multiple simultaneous writes 1602 * modifying the same data. Must lock energyPrefs before reading 1603 * systemPowerSettings in IOPMCopySystemPowerSettings. 1604 */ 1605 if(!SCPreferencesLock(energyPrefs, true)) 1606 { 1607 if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged; 1608 else ret = kIOReturnError; 1609 goto exit; 1610 } 1611 1612 tmp_dict = IOPMCopySystemPowerSettings(); 1613 if(tmp_dict) { 1614 systemPowerDictionary = CFDictionaryCreateMutableCopy(0, 0, tmp_dict); 1615 CFRelease(tmp_dict); 1616 tmp_dict = NULL; 1617 } else { 1618 systemPowerDictionary = CFDictionaryCreateMutable(0, 0, 1619 &kCFTypeDictionaryKeyCallBacks, 1620 &kCFTypeDictionaryValueCallBacks); 1621 } 1622 1623 if(!systemPowerDictionary) { 1624 goto exit; 1625 } 1626 1627 CFDictionarySetValue( systemPowerDictionary, key, value); 1628 1629 ret = kIOReturnSuccess; 1630 1631 if(!SCPreferencesSetValue( energyPrefs, 1632 CFSTR("SystemPowerSettings"), 1633 systemPowerDictionary)) 1634 { 1635 ret = kIOReturnError; 1636 goto exit; 1637 } 1638 1639 if(!SCPreferencesCommitChanges(energyPrefs)) 1640 { 1641 // handle error 1642 if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged; 1643 else ret = kIOReturnError; 1644 goto exit; 1645 } 1646 1647 ret = kIOReturnSuccess; 1648exit: 1649 if(energyPrefs) { 1650 SCPreferencesUnlock(energyPrefs); 1651 CFRelease(energyPrefs); 1652 } 1653 return ret; 1654 1655} 1656 1657 1658void IOPMOverrideDefaultPMPreferences(CFDictionaryRef overrideSettings) 1659{ 1660 SCDynamicStoreRef dynamic_store = NULL; 1661 1662 if(0 == isA_CFDictionary(overrideSettings)) { 1663 return; 1664 } 1665 1666 dynamic_store = SCDynamicStoreCreate(kCFAllocatorDefault, 1667 CFSTR("IOKit User Library - Override"), 1668 NULL, NULL); 1669 if(dynamic_store == NULL) 1670 return; 1671 1672 // This is the simplest possible implementation of IOPMOverrideDefaultPMPreferences. 1673 // This assumes only one caller. If called multiple times, the last caller will 1674 // overwrite all previous callers values. 1675 SCDynamicStoreSetValue(dynamic_store, CFSTR(kIOPMDynamicStoreUserOverridesKey), overrideSettings); 1676 1677 // And send a notification to anyone watching the preferences file. 1678 _doTouchEnergyPrefs(dynamic_store); 1679 1680 CFRelease(dynamic_store); 1681 return; 1682} 1683 1684 1685 1686 1687/************************************************** 1688* 1689* Power Profiles 1690* 1691* 1692**************************************************/ 1693 1694static void mergeDictIntoMutable( 1695 CFMutableDictionaryRef target, 1696 CFDictionaryRef overrides, 1697 bool overwrite) 1698{ 1699 const CFStringRef *keys; 1700 const CFTypeRef *objs; 1701 int count; 1702 int i; 1703 1704 count = CFDictionaryGetCount(overrides); 1705 if(0 == count) return; 1706 1707 keys = (CFStringRef *)malloc(sizeof(CFStringRef) * count); 1708 objs = (CFTypeRef *)malloc(sizeof(CFTypeRef) * count); 1709 if(!keys || !objs) return; 1710 1711 CFDictionaryGetKeysAndValues(overrides, 1712 (const void **)keys, (const void **)objs); 1713 for(i=0; i<count; i++) 1714 { 1715 if(overwrite) { 1716 CFDictionarySetValue(target, keys[i], objs[i]); 1717 } else { 1718 // no value added if key already present 1719 CFDictionaryAddValue(target, keys[i], objs[i]); 1720 } 1721 } 1722 free((void *)keys); 1723 free((void *)objs); 1724} 1725 1726/* _copySystemProvidedProfiles() 1727 * 1728 * The PlatformExpert kext on the system may conditionally override the Energy 1729 * Saver's profiles. Only the PlatformExpert should be setting these properties. 1730 * 1731 * We use two supported properties - kIOPMSystemDefaultOverrideKey & 1732 * kIOPMSystemDefaultProfilesKey. We check first for 1733 * kIOPMSystemDefaultOverrideKey (a partial settings defaults substitution), 1734 * and if it's not present we'll use kIOPMSystemDefaultProfilesKey 1735 * (a complete settings defaults substitution). 1736 * 1737 * Overrides are a single dictionary of PM settings merged into the 1738 * default PM profiles found on the root volume, under the PM bundle, as 1739 * com.apple.SystemPowerProfileDefaults.plist 1740 * 1741 * Alternatively, Overrides are a 3 dictionary set, each dictionary 1742 * being a proper PM settings dictionary. The 3 keys must be 1743 * "AC Power", "Battery Power" and "UPS Power" respectively. Each 1744 * dictionary under those keys should contain only PM settings. 1745 * 1746 * DefaultProfiles is a CFArray of size 5, containing CFDictionaries 1747 * which each contain 3 dictionaries in turn 1748 */ 1749static CFArrayRef _copySystemProvidedProfiles() 1750{ 1751 io_registry_entry_t registry_entry = MACH_PORT_NULL; 1752 CFTypeRef cftype_total_prof_override = NULL; 1753 CFTypeRef cftype_overrides = NULL; 1754 CFArrayRef retArray = NULL; 1755 CFDictionaryRef overrides = NULL; 1756 CFDictionaryRef ac_over = NULL; 1757 CFDictionaryRef batt_over = NULL; 1758 CFDictionaryRef ups_over = NULL; 1759 1760 CFArrayRef sysPowerProfiles = NULL; 1761 CFMutableArrayRef mArrProfs = NULL; 1762 int count = 0; 1763 int i = 0; 1764 1765 registry_entry = getPMRootDomainRef(); 1766 if(MACH_PORT_NULL == registry_entry) return NULL; 1767 1768 /* O v e r r i d e */ 1769 1770 cftype_overrides = IORegistryEntryCreateCFProperty(registry_entry, 1771 CFSTR(kIOPMSystemDefaultOverrideKey), 1772 kCFAllocatorDefault, 0); 1773 if( !(overrides = isA_CFDictionary(cftype_overrides)) ) { 1774 // Expect overrides to be a CFDictionary. If not, skip. 1775 if(cftype_overrides) { 1776 CFRelease(cftype_overrides); cftype_overrides = NULL; 1777 } 1778 goto TrySystemDefaultProfiles; 1779 } 1780 1781 ac_over = CFDictionaryGetValue(overrides, CFSTR(kIOPMACPowerKey)); 1782 batt_over = CFDictionaryGetValue(overrides, CFSTR(kIOPMBatteryPowerKey)); 1783 ups_over = CFDictionaryGetValue(overrides, CFSTR(kIOPMUPSPowerKey)); 1784 1785 // Overrides either contains 3 dictionaries of PM Settings keyed as 1786 // AC, Battery, and UPS Power, or it is itself a dictionary of PM Settings. 1787 if(ac_over && batt_over && ups_over) 1788 { 1789 // Good. All 3 power source settings types are represented. 1790 // Do nothing here. 1791 } else if(!ac_over && !batt_over && !ups_over) 1792 { 1793 // The dictionary didn't specify any per-power source overrides, which 1794 // means that it's a flat dictionary strictly of PM settings. 1795 // We duplicate it 3 ways, as each overridden setting in this dictionary 1796 // will be applied to each power source's settings. 1797 ac_over = batt_over = ups_over = overrides; 1798 } else { 1799 // Bad form for overrides dictionary. 1800 goto TrySystemDefaultProfiles; 1801 } 1802 1803 // ac_over, batt_over, ups_over now contain the PM settings to be merged 1804 // into the system's default profiles. The settings defined in ac_over, 1805 // batt_over, and ups_over, will override the system's defaults from file: 1806 // 1807 // com.apple.SystemPowerProfileDefaults.plist in PowerManagement.bundle 1808 1809 1810 sysPowerProfiles = _createDefaultSystemProfiles(); 1811 if(!sysPowerProfiles) goto exit; 1812 count = CFArrayGetCount(sysPowerProfiles); 1813 1814 mArrProfs = CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks); 1815 for(i=0; i<count; i++) 1816 { 1817 CFMutableDictionaryRef mSettingsAC; 1818 CFMutableDictionaryRef mSettingsBatt; 1819 CFMutableDictionaryRef mSettingsUPS; 1820 CFMutableDictionaryRef mProfile; 1821 CFDictionaryRef _profile; 1822 CFDictionaryRef tmp; 1823 1824 _profile = (CFDictionaryRef)CFArrayGetValueAtIndex(sysPowerProfiles, i); 1825 if(!_profile) continue; 1826 1827 // Create a new mutable profile to modify & override selected settings 1828 mProfile = CFDictionaryCreateMutable(0, 1829 CFDictionaryGetCount(_profile), 1830 &kCFTypeDictionaryKeyCallBacks, 1831 &kCFTypeDictionaryValueCallBacks); 1832 1833 if(!mProfile) continue; 1834 // Add new mutable profile to new mutable array of profiles 1835 CFArraySetValueAtIndex(mArrProfs, i, mProfile); 1836 CFRelease(mProfile); 1837 1838 tmp = (CFDictionaryRef)CFDictionaryGetValue(_profile, 1839 CFSTR(kIOPMACPowerKey)); 1840 if(!tmp) continue; 1841 mSettingsAC = CFDictionaryCreateMutableCopy(0, 1842 CFDictionaryGetCount(tmp), tmp); 1843 1844 1845 tmp = (CFDictionaryRef)CFDictionaryGetValue(_profile, 1846 CFSTR(kIOPMBatteryPowerKey)); 1847 if(!tmp) continue; 1848 mSettingsBatt = CFDictionaryCreateMutableCopy(0, 1849 CFDictionaryGetCount(tmp), tmp); 1850 1851 tmp = (CFDictionaryRef)CFDictionaryGetValue(_profile, 1852 CFSTR(kIOPMUPSPowerKey)); 1853 if(!tmp) continue; 1854 mSettingsUPS = CFDictionaryCreateMutableCopy(0, 1855 CFDictionaryGetCount(tmp), tmp); 1856 1857 if( !(mSettingsAC && mSettingsBatt && mSettingsUPS) ) { 1858 if(sysPowerProfiles) { 1859 CFRelease(sysPowerProfiles); sysPowerProfiles = NULL; 1860 } 1861 if(mSettingsAC) { 1862 CFRelease(mSettingsAC); mSettingsAC = NULL; 1863 } 1864 if(mSettingsBatt) { 1865 CFRelease(mSettingsBatt); mSettingsBatt = NULL; 1866 } 1867 if(mSettingsUPS) { 1868 CFRelease(mSettingsUPS); mSettingsUPS = NULL; 1869 } 1870 if(mArrProfs) { 1871 CFRelease(mArrProfs); mArrProfs = NULL; 1872 } 1873 goto TrySystemDefaultProfiles; 1874 } 1875 1876 // Add these new mutable dictionaries to our new mutable profile 1877 1878 CFDictionarySetValue(mProfile, 1879 CFSTR(kIOPMACPowerKey), 1880 mSettingsAC); 1881 1882 CFDictionarySetValue(mProfile, 1883 CFSTR(kIOPMBatteryPowerKey), 1884 mSettingsBatt); 1885 1886 CFDictionarySetValue(mProfile, 1887 CFSTR(kIOPMUPSPowerKey), 1888 mSettingsUPS); 1889 1890 // And now... what we've all been waiting for... merge in the system 1891 // platform expert's provided default profiles. 1892 // true == overwrite existing settings 1893 mergeDictIntoMutable(mSettingsAC, ac_over, kOverWriteDuplicates); 1894 mergeDictIntoMutable(mSettingsBatt, batt_over, kOverWriteDuplicates); 1895 mergeDictIntoMutable(mSettingsUPS, ups_over, kOverWriteDuplicates); 1896 1897 // And release... 1898 1899 CFRelease(mSettingsAC); mSettingsAC = NULL; 1900 CFRelease(mSettingsBatt); mSettingsBatt = NULL; 1901 CFRelease(mSettingsUPS); mSettingsUPS = NULL; 1902 } 1903 1904 // Currently holding one retain on mArrProfs 1905 retArray = (CFArrayRef)mArrProfs; 1906 1907 goto exit; 1908 1909TrySystemDefaultProfiles: 1910 1911 /* D e f a u l t P r o f i l e s */ 1912 1913 // If there were no override PM settings, we check for a complete 1914 // power profiles definition instead. If so, return the CFArray 1915 // it contains wholesale. 1916 1917 cftype_total_prof_override = IORegistryEntryCreateCFProperty(registry_entry, 1918 CFSTR(kIOPMSystemDefaultProfilesKey), 1919 kCFAllocatorDefault, 0); 1920 if( isA_CFArray(cftype_total_prof_override) ) { 1921 retArray = (CFArrayRef)cftype_total_prof_override; 1922 goto exit; 1923 } else { 1924 if(cftype_total_prof_override) { 1925 CFRelease(cftype_total_prof_override); 1926 cftype_total_prof_override = NULL; 1927 } 1928 } 1929 1930exit: 1931 if(sysPowerProfiles) { 1932 CFRelease(sysPowerProfiles); sysPowerProfiles = NULL; 1933 } 1934 if(cftype_overrides) { 1935 CFRelease(cftype_overrides); cftype_overrides = NULL; 1936 } 1937 return retArray; 1938} 1939 1940static CFArrayRef _createDefaultSystemProfiles() 1941{ 1942 CFURLRef pm_bundle_url = 0; 1943 CFBundleRef pm_bundle = 0; 1944 CFURLRef profiles_url = 0; 1945 CFStringRef profiles_path = 0; 1946 CFArrayRef system_default_profiles = 0; 1947 CFArrayRef return_array = 0; 1948 SCPreferencesRef open_file = 0; 1949 1950 pm_bundle_url = CFURLCreateWithFileSystemPath(0, CFSTR(kIOPMBundlePath), kCFURLPOSIXPathStyle, true); 1951 if(!pm_bundle_url) { 1952 goto exit; 1953 } 1954 1955 pm_bundle = CFBundleCreate(kCFAllocatorDefault, pm_bundle_url); 1956 if(!pm_bundle) { 1957 goto exit; 1958 } 1959 1960 profiles_url = CFBundleCopyResourceURL(pm_bundle, 1961 CFSTR("com.apple.SystemPowerProfileDefaults.plist"), NULL, NULL); 1962 if(!profiles_url) { 1963 goto exit; 1964 } 1965 profiles_path = CFURLCopyPath(profiles_url); 1966 1967 open_file = SCPreferencesCreate(0, CFSTR("PowerManagementPreferences"), profiles_path); 1968 if(!open_file) { 1969 goto exit; 1970 } 1971 1972 system_default_profiles = SCPreferencesGetValue(open_file, CFSTR("SystemProfileDefaults")); 1973 if(!isA_CFArray(system_default_profiles)) { 1974 goto exit; 1975 } 1976 1977 return_array = CFArrayCreateCopy(0, system_default_profiles); 1978 1979exit: 1980 if(pm_bundle_url) CFRelease(pm_bundle_url); 1981 if(pm_bundle) CFRelease(pm_bundle); 1982 if(profiles_url) CFRelease(profiles_url); 1983 if(profiles_path) CFRelease(profiles_path); 1984 if(open_file) CFRelease(open_file); 1985 1986 return return_array; 1987} 1988 1989static CFDictionaryRef _createDefaultProfileSelections(void) 1990{ 1991 CFURLRef pm_bundle_url = 0; 1992 CFBundleRef pm_bundle = 0; 1993 CFURLRef profiles_url = 0; 1994 CFStringRef profiles_path = 0; 1995 CFDictionaryRef default_profiles_selection = 0; 1996 CFDictionaryRef return_dict = 0; 1997 SCPreferencesRef open_file = 0; 1998 1999 pm_bundle_url = CFURLCreateWithFileSystemPath(0, CFSTR(kIOPMBundlePath), kCFURLPOSIXPathStyle, true); 2000 if(!pm_bundle_url) { 2001 goto exit; 2002 } 2003 2004 pm_bundle = CFBundleCreate( 2005 kCFAllocatorDefault, 2006 pm_bundle_url); 2007 if(!pm_bundle) { 2008 goto exit; 2009 } 2010 2011 profiles_url = CFBundleCopyResourceURL( 2012 pm_bundle, 2013 CFSTR("com.apple.SystemPowerProfileDefaults.plist"), 2014 NULL, 2015 NULL); 2016 if(!profiles_url) { 2017 //syslog(LOG_INFO, "Can't find path to profiles\n"); 2018 goto exit; 2019 } 2020 profiles_path = CFURLCopyPath(profiles_url); 2021 2022 open_file = SCPreferencesCreate( 2023 kCFAllocatorDefault, 2024 CFSTR("PowerManagementPreferences"), 2025 profiles_path); 2026 if(!open_file) { 2027 //syslog(LOG_INFO, "PM could not open System Profile defaults\n"); 2028 goto exit; 2029 } 2030 2031 default_profiles_selection = SCPreferencesGetValue( 2032 open_file, 2033 CFSTR("DefaultProfileChoices")); 2034 if(!isA_CFDictionary(default_profiles_selection)) { 2035 goto exit; 2036 } 2037 2038 return_dict = CFDictionaryCreateCopy(kCFAllocatorDefault, default_profiles_selection); 2039 2040exit: 2041 if(pm_bundle_url) CFRelease(pm_bundle_url); 2042 if(pm_bundle) CFRelease(pm_bundle); 2043 if(profiles_url) CFRelease(profiles_url); 2044 if(profiles_path) CFRelease(profiles_path); 2045 if(open_file) CFRelease(open_file); 2046 2047 return return_dict; 2048} 2049 2050static CFDictionaryRef _createAllCustomProfileSelections(void) 2051{ 2052 int j = -1; 2053 CFNumberRef n; 2054 CFMutableDictionaryRef custom_dict = NULL; 2055 2056 custom_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 3, 2057 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2058 n = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &j); 2059 if(!custom_dict || !n) return NULL; 2060 2061 CFDictionarySetValue(custom_dict, CFSTR(kIOPMACPowerKey), n); 2062 CFDictionarySetValue(custom_dict, CFSTR(kIOPMBatteryPowerKey), n); 2063 CFDictionarySetValue(custom_dict, CFSTR(kIOPMUPSPowerKey), n); 2064 2065 CFRelease(n); 2066 return custom_dict; 2067} 2068 2069 2070CFArrayRef IOPMCopyPowerProfiles(void) 2071{ 2072 CFArrayRef power_profiles = 0; 2073 CFMutableArrayRef mutable_power_profiles = 0; 2074 CFDictionaryRef tmp; 2075 CFMutableDictionaryRef mutable_profile; 2076 int i, p_count; 2077 2078 // Provide the platform expert driver a chance to define better default 2079 // power settings for the machine this code is running on. 2080 power_profiles = _copySystemProvidedProfiles(); 2081 if(!power_profiles) { 2082 power_profiles = _createDefaultSystemProfiles(); 2083 } 2084 if(!power_profiles) return NULL; 2085 2086 mutable_power_profiles = CFArrayCreateMutableCopy(0, 0, power_profiles); 2087 if(!mutable_power_profiles) goto exit; 2088 2089 // Prune unsupported power supplies and unsupported 2090 // settings 2091 p_count = CFArrayGetCount(mutable_power_profiles); 2092 for(i=0; i<p_count; i++) 2093 { 2094 tmp = CFArrayGetValueAtIndex(power_profiles, i); 2095 if(!tmp) 2096 continue; 2097 2098 mutable_profile = CFDictionaryCreateMutableCopy(0, 0, tmp); 2099 if(!mutable_profile) 2100 continue; 2101 2102 mergeUserDefaultOverriddenSettings(mutable_profile); 2103 2104 addDefaultEnergySettings(mutable_profile); 2105 2106 IOPMRemoveIrrelevantProperties(mutable_profile); 2107 2108 CFArraySetValueAtIndex(mutable_power_profiles, i, mutable_profile); 2109 CFRelease(mutable_profile); 2110 } 2111exit: 2112 if(power_profiles) CFRelease(power_profiles); 2113 return mutable_power_profiles; 2114} 2115 2116static int _isActiveProfileDictValid(CFDictionaryRef p) 2117{ 2118 CFNumberRef val; 2119 int j; 2120 2121 if(!p) return 0; 2122 2123 // AC value required 2124 val = CFDictionaryGetValue(p, CFSTR(kIOPMACPowerKey)); 2125 if(!val) return 0; 2126 CFNumberGetValue(val, kCFNumberIntType, &j); 2127 if(j<-1 || j>= kIOPMNumPowerProfiles) return 0; 2128 2129 // Battery value optional 2130 val = CFDictionaryGetValue(p, CFSTR(kIOPMBatteryPowerKey)); 2131 if(val) { 2132 CFNumberGetValue(val, kCFNumberIntType, &j); 2133 if(j<-1 || j>= kIOPMNumPowerProfiles) return 0; 2134 } 2135 2136 // UPS value optional 2137 val = CFDictionaryGetValue(p, CFSTR(kIOPMUPSPowerKey)); 2138 if(val) { 2139 CFNumberGetValue(val, kCFNumberIntType, &j); 2140 if(j<-1 || j>= kIOPMNumPowerProfiles) return 0; 2141 } 2142 2143 return 1; 2144} 2145 2146static void _purgeUnsupportedPowerSources(CFMutableDictionaryRef p) 2147{ 2148 CFStringRef *ps_names = NULL; 2149 CFTypeRef ps_snap = NULL; 2150 int count; 2151 int i; 2152 2153 ps_snap = IOPSCopyPowerSourcesInfo(); 2154 if(!ps_snap) return; 2155 count = CFDictionaryGetCount(p); 2156 ps_names = (CFStringRef *)malloc(count*sizeof(CFStringRef)); 2157 if(!ps_names) goto exit; 2158 CFDictionaryGetKeysAndValues(p, (CFTypeRef *)ps_names, NULL); 2159 for(i=0; i<count; i++) 2160 { 2161 if(kCFBooleanTrue != IOPSPowerSourceSupported(ps_snap, ps_names[i])) { 2162 CFDictionaryRemoveValue(p, ps_names[i]); 2163 } 2164 } 2165exit: 2166 if(ps_snap) CFRelease(ps_snap); 2167 if(ps_names) free(ps_names); 2168} 2169 2170static CFStringRef getPowerSourceString(int i) 2171{ 2172 if(i == 1) return CFSTR(kIOPMBatteryPowerKey); 2173 if(i == 2) return CFSTR(kIOPMUPSPowerKey); 2174 2175 return CFSTR(kIOPMACPowerKey); 2176} 2177 2178/************************************************** 2179* 2180* Support for IOPMPrefsNotificationCreateRunLoopSource 2181* 2182**************************************************/ 2183 2184/* SCDynamicStoreCallback */ 2185static void ioCallout( 2186 SCDynamicStoreRef store __unused, 2187 CFArrayRef keys __unused, 2188 void *ctxt) 2189{ 2190 user_callback_context *c; 2191 IOPowerSourceCallbackType cb; 2192 2193 c = (user_callback_context *)CFDataGetBytePtr((CFDataRef)ctxt); 2194 if(!c) return; 2195 cb = c->callback; 2196 if(!cb) return; 2197 2198 // Execute callback 2199 (*cb)(c->context); 2200} 2201 2202 2203/******************************************************************************* 2204**** 2205**** readAllPMPlistSettings 2206**** 2207*******************************************************************************/ 2208 2209IOReturn readAllPMPlistSettings( 2210 bool removeUnsupportedSettings, 2211 CFMutableDictionaryRef *customSettings, 2212 CFDictionaryRef *profileSelections, 2213 bool *returnDefaultSettings) 2214{ 2215 /* 2216 * Read Custom Settings 2217 */ 2218 CFMutableDictionaryRef energyDict = NULL; 2219 CFDictionaryRef tmp_dict = NULL; 2220 SCPreferencesRef energyPrefs = NULL; 2221 CFMutableDictionaryRef batterySettings = NULL; 2222 CFMutableDictionaryRef ACSettings = NULL; 2223 CFMutableDictionaryRef UPSSettings = NULL; 2224 bool usingDefaults = true; 2225 bool prefsSuccess = false; 2226 2227 /* 2228 * Read profiles 2229 */ 2230 CFDictionaryRef tmp = NULL; 2231 CFDictionaryRef defaultProfiles = NULL; 2232 CFStringRef *profileKeys = NULL; 2233 CFNumberRef *profileValues = NULL; 2234 bool activeProfilesSpecified = false; 2235 int profileCount; 2236 int i; 2237 bool profilesSuccess = false; 2238 CFMutableDictionaryRef acquiredProfiles = NULL; 2239 2240 2241 energyPrefs = SCPreferencesCreate( 0, kIOPMAppName, kIOPMPrefsPath ); 2242 2243 if(!energyPrefs) { 2244 // Utter failure!!! 2245 if(customSettings) *customSettings = NULL; 2246 if(profileSelections) *profileSelections = NULL; 2247 return kIOReturnNotOpen; 2248 } 2249 2250/******************************************************************************* 2251**** Read raw profiles com.apple.PowerManagement.plist 2252*******************************************************************************/ 2253 2254 tmp = SCPreferencesGetValue(energyPrefs, CFSTR("ActivePowerProfiles")); 2255 if(tmp && _isActiveProfileDictValid(tmp)) { 2256 acquiredProfiles = CFDictionaryCreateMutableCopy(0, 0, tmp); 2257 activeProfilesSpecified = true; 2258 } else { 2259 acquiredProfiles = NULL; 2260 } 2261 2262/******************************************************************************* 2263**** Read custom settings dictionary from com.apple.PowerManagement.plist 2264*******************************************************************************/ 2265 2266 // Attempt to read battery & AC settings 2267 tmp_dict = isA_CFDictionary(SCPreferencesGetValue(energyPrefs, 2268 CFSTR("Custom Profile"))); 2269 2270 // If com.apple.PowerManagement.xml opened correctly, read data from it 2271 if(tmp_dict) 2272 { 2273 usingDefaults = false; 2274 2275 // Tiger preferences file format 2276 energyDict = CFDictionaryCreateMutableCopy( 2277 kCFAllocatorDefault, 2278 0, 2279 tmp_dict); 2280 if(!energyDict) goto prefsExit; 2281 } else { 2282 // Try Panther/Jaguar prefs formats 2283 2284 batterySettings = (CFMutableDictionaryRef)isA_CFDictionary( 2285 SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMBatteryPowerKey))); 2286 ACSettings = (CFMutableDictionaryRef)isA_CFDictionary( 2287 SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMACPowerKey))); 2288 UPSSettings = (CFMutableDictionaryRef)isA_CFDictionary( 2289 SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMUPSPowerKey))); 2290 2291 if ( batterySettings || ACSettings || UPSSettings ) 2292 usingDefaults = false; 2293 2294 energyDict = CFDictionaryCreateMutable( 2295 kCFAllocatorDefault, 2296 0, 2297 &kCFTypeDictionaryKeyCallBacks, 2298 &kCFTypeDictionaryValueCallBacks); 2299 if(!energyDict) goto prefsExit; 2300 2301 if(batterySettings) { 2302 CFDictionaryAddValue(energyDict, CFSTR(kIOPMBatteryPowerKey), 2303 batterySettings); 2304 } 2305 if(ACSettings) { 2306 CFDictionaryAddValue(energyDict, CFSTR(kIOPMACPowerKey), 2307 ACSettings); 2308 } 2309 if(UPSSettings) { 2310 CFDictionaryAddValue(energyDict, CFSTR(kIOPMUPSPowerKey), 2311 UPSSettings); 2312 } 2313 } 2314 2315 // Make sure that the enclosed dictionaries are all mutable 2316 tmp = isA_CFDictionary(CFDictionaryGetValue( 2317 energyDict, CFSTR(kIOPMBatteryPowerKey))); 2318 if(tmp) { 2319 batterySettings = CFDictionaryCreateMutableCopy(0, 0, tmp); 2320 } else { 2321 batterySettings = CFDictionaryCreateMutable(0, 0, 2322 &kCFTypeDictionaryKeyCallBacks, 2323 &kCFTypeDictionaryValueCallBacks); 2324 } 2325 if(batterySettings) 2326 { 2327 CFDictionarySetValue(energyDict, CFSTR(kIOPMBatteryPowerKey), 2328 batterySettings); 2329 CFRelease(batterySettings); 2330 } else goto prefsExit; 2331 2332 tmp = isA_CFDictionary(CFDictionaryGetValue( 2333 energyDict, CFSTR(kIOPMACPowerKey))); 2334 if(tmp) { 2335 ACSettings = CFDictionaryCreateMutableCopy(0, 0, tmp); 2336 } else { 2337 ACSettings = CFDictionaryCreateMutable(0, 0, 2338 &kCFTypeDictionaryKeyCallBacks, 2339 &kCFTypeDictionaryValueCallBacks); 2340 } 2341 if(ACSettings) { 2342 CFDictionarySetValue(energyDict, CFSTR(kIOPMACPowerKey), ACSettings); 2343 CFRelease(ACSettings); 2344 } else goto prefsExit; 2345 2346 tmp = isA_CFDictionary(CFDictionaryGetValue( 2347 energyDict, CFSTR(kIOPMUPSPowerKey))); 2348 if(tmp) { 2349 UPSSettings = CFDictionaryCreateMutableCopy(0, 0, tmp); 2350 } else { 2351 UPSSettings = CFDictionaryCreateMutable(0, 0, 2352 &kCFTypeDictionaryKeyCallBacks, 2353 &kCFTypeDictionaryValueCallBacks); 2354 } 2355 if(UPSSettings) { 2356 CFDictionarySetValue(energyDict, CFSTR(kIOPMUPSPowerKey), UPSSettings); 2357 CFRelease(UPSSettings); 2358 } else goto prefsExit; 2359 2360 // INVARIANT: At this point we want a mutable dictionary energyDict 2361 // containing 3 mutable preferences dictionaries that are either 2362 // empty or contain some settings. 2363 2364 // Check for existence of Puma/Cheetah prefs format 2365 // And add settings defined there if present 2366 getCheetahPumaEnergySettings(energyDict); 2367 2368 // Fill in any undefined settings from the system's provided defaults 2369 // IOPlatformExpert may specify different profile defaults, so we must 2370 // respect those when present. 2371 addSystemProfileEnergySettings(acquiredProfiles, energyDict); 2372 2373 // Fill in any settings overriden by a user process. 2374 mergeUserDefaultOverriddenSettings(energyDict); 2375 2376 // Fill in any undefined settings with our defaults 2377 // If no current or legacy prefs files exist, addDefaultEnergySettings() 2378 // completely populates the default EnergySaver preferences. 2379 addDefaultEnergySettings(energyDict); 2380 2381 if (removeUnsupportedSettings) 2382 { 2383 // Remove any unsupported key/value pairs (including some of 2384 // those we just added in getDefaultEnergySettings) 2385 IOPMRemoveIrrelevantProperties(energyDict); 2386 } 2387 2388 if(usingDefaults) { 2389 // If we couldn't find any user-specified settings on disk, 2390 // tag this dictionary as "Defaults" so that BatteryMonitor and 2391 // EnergySaver can tell whether these are user-selected 2392 // values or just the system defaults. 2393 CFDictionarySetValue(energyDict, CFSTR(kIOPMDefaultPreferencesKey), 2394 kCFBooleanTrue); 2395 } 2396 2397 prefsSuccess = true; 2398 if( customSettings ) { 2399 *customSettings = energyDict; 2400 } 2401 2402prefsExit: 2403 2404 if ( !prefsSuccess && customSettings) { 2405 *customSettings = NULL; 2406 } 2407 2408/******************************************************************************* 2409 **** Read custom profiles dictionary from com.apple.PowerManagement.plist 2410 ******************************************************************************/ 2411 2412 if( !profileSelections ) { 2413 profilesSuccess = true; 2414 } else { 2415 // acquiredProfiles already contains the pre-read profiles data 2416 if(!acquiredProfiles) { 2417 acquiredProfiles = CFDictionaryCreateMutable(0, 3, 2418 &kCFTypeDictionaryKeyCallBacks, 2419 &kCFTypeDictionaryValueCallBacks); 2420 } 2421 2422 2423 if(!activeProfilesSpecified && !usingDefaults) 2424 { 2425 defaultProfiles = _createAllCustomProfileSelections(); 2426 } else { 2427 defaultProfiles = _createDefaultProfileSelections(); 2428 } 2429 2430 // Merge default profiles into active profiles 2431 // If the user has any specified Profiles, we'll merge in the defaults 2432 // for any power sources that aren't specified. If there weren't any 2433 // profile choices, we'll just merge in (-1, -1, -1) for all custom or 2434 // (2, 1, 1) to the empty dictionary, as described in comments above. 2435 2436 if(isA_CFDictionary(defaultProfiles)) 2437 { 2438 profileCount = CFDictionaryGetCount(defaultProfiles); 2439 profileKeys = malloc(sizeof(CFStringRef)*profileCount); 2440 profileValues = malloc(sizeof(CFNumberRef)*profileCount); 2441 if ( !profileKeys || !profileValues ) goto profilesExit; 2442 CFDictionaryGetKeysAndValues(defaultProfiles, 2443 (const void **)profileKeys, (const void **)profileValues); 2444 2445 for(i=0; i<profileCount; i++) 2446 { 2447 if( isA_CFString(profileKeys[i]) && 2448 isA_CFNumber(profileValues[i]) ) 2449 { 2450 // use the softer AddValue that won't replace any existing 2451 // settings in the existing chosen profiles dictionary. 2452 CFDictionaryAddValue(acquiredProfiles, profileKeys[i], 2453 profileValues[i]); 2454 } 2455 } 2456 free(profileKeys); 2457 free(profileValues); 2458 } 2459 2460 /* Note: removeUnsupportedSettings argument does not affect the pruning 2461 * of unsupported power sources; we prune these regardless. 2462 * And remove all the unsupported profiles that we just added. 2463 */ 2464 _purgeUnsupportedPowerSources(acquiredProfiles); 2465 2466 *profileSelections = acquiredProfiles; 2467 profilesSuccess = true; 2468 2469profilesExit: 2470 if(defaultProfiles) CFRelease(defaultProfiles); 2471 if(!profilesSuccess) *profileSelections = NULL; 2472 } 2473 2474// common exit 2475 2476 if( energyPrefs ) CFRelease(energyPrefs); 2477 2478 if( !customSettings && energyDict ) 2479 { 2480 // If the caller did not request a copy of the PM settings, we 2481 // release them here. Otherwise it's the caller's responsibility 2482 // to CFRelease(*customSettings); 2483 2484 CFRelease(energyDict); 2485 } 2486 2487 if( !profileSelections && acquiredProfiles ) 2488 { 2489 // If the caller did not request a copy of the profiles, we 2490 // release them here. Otherwise it's the caller's responsibility 2491 // to CFRelease(*profileSelections); 2492 2493 CFRelease(acquiredProfiles); 2494 } 2495 2496 if (returnDefaultSettings) { 2497 *returnDefaultSettings = usingDefaults; 2498 } 2499 2500 if( prefsSuccess && profilesSuccess) { 2501 return kIOReturnSuccess; 2502 } else { 2503 return kIOReturnError; 2504 } 2505} 2506 2507 2508 2509