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