#include <sys/cdefs.h>
#include <TargetConditionals.h>
#include "IOSystemConfiguration.h"
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPowerSourcesPrivate.h>
#include <IOKit/IOCFSerialize.h>
#include <IOKit/IOHibernatePrivate.h>
#include <servers/bootstrap.h>
#include <sys/syslog.h>
#include "IOPMLib.h"
#include "IOPMLibPrivate.h"
#include "powermanagement.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <mach/mach.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#define kIOPMPrefsPath CFSTR("com.apple.PowerManagement.xml")
#define kIOPMAppName CFSTR("PowerManagement configd")
#define kIOPMSystemPowerKey CFSTR("SystemPowerSettings")
#define kIOPMCustomProfileKey CFSTR("Custom Profile")
#define kACMinutesToDim 5
#define kACMinutesToSpin 10
#define kACMinutesToSleep 10
#define kACWakeOnRing 0
#define kACAutomaticRestart 0
#define kACWakeOnLAN 1
#define kACReduceProcessorSpeed 0
#define kACDynamicPowerStep 1
#define kACSleepOnPowerButton 1
#define kACWakeOnClamshell 1
#define kACWakeOnACChange 0
#define kACReduceBrightness 0
#define kACDisplaySleepUsesDim 1
#define kACMobileMotionModule 1
#define kBatteryMinutesToDim 5
#define kBatteryMinutesToSpin 5
#define kBatteryMinutesToSleep 5
#define kBatteryWakeOnRing 0
#define kBatteryAutomaticRestart 0
#define kBatteryWakeOnLAN 0
#define kBatteryReduceProcessorSpeed 0
#define kBatteryDynamicPowerStep 1
#define kBatterySleepOnPowerButton 0
#define kBatteryWakeOnClamshell 1
#define kBatteryWakeOnACChange 0
#define kBatteryReduceBrightness 1
#define kBatteryDisplaySleepUsesDim 1
#define kBatteryMobileMotionModule 1
#define kUPSMinutesToDim kACMinutesToDim
#define kUPSMinutesToSpin kACMinutesToSpin
#define kUPSMinutesToSleep kACMinutesToSleep
#define kUPSWakeOnRing kACWakeOnRing
#define kUPSAutomaticRestart kACAutomaticRestart
#define kUPSWakeOnLAN kACWakeOnLAN
#define kUPSReduceProcessorSpeed kACReduceProcessorSpeed
#define kUPSDynamicPowerStep kACDynamicPowerStep
#define kUPSSleepOnPowerButton kACSleepOnPowerButton
#define kUPSWakeOnClamshell kACWakeOnClamshell
#define kUPSWakeOnACChange kACWakeOnACChange
#define kUPSReduceBrightness kACReduceBrightness
#define kUPSDisplaySleepUsesDim kACDisplaySleepUsesDim
#define kUPSMobileMotionModule kACMobileMotionModule
#define kTTYSPreventSleepDefault 1
#define kIOHibernateDefaultFile "/var/vm/sleepimage"
enum { kIOHibernateMinFreeSpace = 750*1024ULL*1024ULL };
#define kIOPMNumPMFeatures 16
static char *energy_features_array[kIOPMNumPMFeatures] = {
kIOPMDisplaySleepKey,
kIOPMDiskSleepKey,
kIOPMSystemSleepKey,
kIOPMWakeOnRingKey,
kIOPMRestartOnPowerLossKey,
kIOPMWakeOnLANKey,
kIOPMReduceSpeedKey,
kIOPMDynamicPowerStepKey,
kIOPMSleepOnPowerButtonKey,
kIOPMWakeOnClamshellKey,
kIOPMWakeOnACChangeKey,
kIOPMReduceBrightnessKey,
kIOPMDisplaySleepUsesDimKey,
kIOPMMobileMotionModuleKey,
kIOHibernateModeKey,
kIOPMTTYSPreventSleepKey
};
static const unsigned int battery_defaults_array[] = {
kBatteryMinutesToDim,
kBatteryMinutesToSpin,
kBatteryMinutesToSleep,
kBatteryWakeOnRing,
kBatteryAutomaticRestart,
kBatteryWakeOnLAN,
kBatteryReduceProcessorSpeed,
kBatteryDynamicPowerStep,
kBatterySleepOnPowerButton,
kBatteryWakeOnClamshell,
kBatteryWakeOnACChange,
kBatteryReduceBrightness,
kBatteryDisplaySleepUsesDim,
kBatteryMobileMotionModule,
kIOHibernateModeOn | kIOHibernateModeSleep,
kTTYSPreventSleepDefault
};
static const unsigned int ac_defaults_array[] = {
kACMinutesToDim,
kACMinutesToSpin,
kACMinutesToSleep,
kACWakeOnRing,
kACAutomaticRestart,
kACWakeOnLAN,
kACReduceProcessorSpeed,
kACDynamicPowerStep,
kACSleepOnPowerButton,
kACWakeOnClamshell,
kACWakeOnACChange,
kACReduceBrightness,
kACDisplaySleepUsesDim,
kACMobileMotionModule,
kIOHibernateModeOn | kIOHibernateModeSleep,
kTTYSPreventSleepDefault
};
static const unsigned int ups_defaults_array[] = {
kUPSMinutesToDim,
kUPSMinutesToSpin,
kUPSMinutesToSleep,
kUPSWakeOnRing,
kUPSAutomaticRestart,
kUPSWakeOnLAN,
kUPSReduceProcessorSpeed,
kUPSDynamicPowerStep,
kUPSSleepOnPowerButton,
kUPSWakeOnClamshell,
kUPSWakeOnACChange,
kUPSReduceBrightness,
kUPSDisplaySleepUsesDim,
kUPSMobileMotionModule,
kIOHibernateModeOn | kIOHibernateModeSleep,
kTTYSPreventSleepDefault
};
#define kIOPMPrefsPath CFSTR("com.apple.PowerManagement.xml")
#define kIOPMAppName CFSTR("PowerManagement configd")
#define kIOPMSystemDefaultProfilesKey "SystemPowerProfiles"
#define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
#define kCheetahDimKey CFSTR("MinutesUntilDisplaySleeps")
#define kCheetahDiskKey CFSTR("MinutesUntilHardDiskSleeps")
#define kCheetahSleepKey CFSTR("MinutesUntilSystemSleeps")
#define kCheetahRestartOnPowerLossKey CFSTR("RestartOnPowerLoss")
#define kCheetahWakeForNetworkAccessKey CFSTR("WakeForNetworkAdministrativeAccess")
#define kCheetahWakeOnRingKey CFSTR("WakeOnRing")
enum {
kIOPMSupportedOnAC = 1<<0,
kIOPMSupportedOnBatt = 1<<1,
kIOPMSupportedOnUPS = 1<<2
};
#define kPowerSourcesCount 3
#define kPowerProfilesCount 5
enum {
kIOPMKeepUnsupportedPreferences = false,
kIOPMRemoveUnsupportedPreferences = true
};
typedef struct {
unsigned int fMinutesToDim;
unsigned int fMinutesToSpin;
unsigned int fMinutesToSleep;
unsigned int fWakeOnLAN;
unsigned int fWakeOnRing;
unsigned int fAutomaticRestart;
unsigned int fSleepOnPowerButton;
unsigned int fWakeOnClamshell;
unsigned int fWakeOnACChange;
unsigned int fDisplaySleepUsesDimming;
unsigned int fMobileMotionModule;
} IOPMAggressivenessFactors;
typedef struct {
IOPMPrefsCallbackType callback;
void *context;
} user_callback_context;
static CFStringRef getPowerSourceString(int i);
static int addDefaultEnergySettings(
CFMutableDictionaryRef sys );
static void addSystemProfileEnergySettings(
CFDictionaryRef user_profile_selections,
CFMutableDictionaryRef passed_in);
static io_registry_entry_t getPMRootDomainRef(void);
static int ProcessHibernateSettings(
CFDictionaryRef dict,
io_registry_entry_t rootDomain);
static int sendEnergySettingsToKernel(
CFDictionaryRef System,
CFStringRef prof,
bool removeUnsupportedSettings,
IOPMAggressivenessFactors *p);
static bool getAggressivenessValue(
CFDictionaryRef dict,
CFStringRef key,
CFNumberType type,
uint32_t *ret);
static int getAggressivenessFactorsFromProfile(
CFDictionaryRef System,
CFStringRef prof,
IOPMAggressivenessFactors *agg);
static CFStringRef supportedNameForPMName( CFStringRef pm_name );
static bool featureSupportsPowerSource(
CFTypeRef featureDetails,
CFStringRef power_source);
static void IOPMRemoveIrrelevantProperties(
CFMutableDictionaryRef energyPrefs);
static int getCheetahPumaEnergySettings(
CFMutableDictionaryRef energyPrefs);
static void mergeDictIntoMutable(
CFMutableDictionaryRef target,
CFDictionaryRef overrides,
bool overwrite);
static CFDictionaryRef _copyActivePMPreferences(
bool removeUnsupportedSettings);
static CFArrayRef _copySystemProvidedProfiles(void);
static CFArrayRef _createDefaultSystemProfiles(void);
static CFDictionaryRef _createDefaultProfileSelections(void);
static CFDictionaryRef _createAllCustomProfileSelections(void);
static int _isActiveProfileDictValid( CFDictionaryRef p );
static void _purgeUnsupportedPowerSources( CFMutableDictionaryRef p );
static void ioCallout(
SCDynamicStoreRef store __unused,
CFArrayRef keys __unused,
void *ctxt);
static IOReturn readAllPMPlistSettings(
bool removeUnsupportedSettings,
CFMutableDictionaryRef *customSettings,
CFDictionaryRef *profileSelections);
Boolean _IOReadBytesFromFile(
CFAllocatorRef alloc,
const char *path,
void **bytes,
CFIndex *length,
CFIndex maxLength);
CFDictionaryRef IOPMCopyCustomPMPreferences(void)
{
CFMutableDictionaryRef copiedPMPrefs = NULL;
CFDictionaryRef immutableRetPrefs = NULL;
copiedPMPrefs = IOPMCopyPMPreferences();
if( copiedPMPrefs ) {
immutableRetPrefs = CFDictionaryCreateCopy(
kCFAllocatorDefault, (CFDictionaryRef)copiedPMPrefs );
CFRelease(copiedPMPrefs);
return immutableRetPrefs;
} else {
return NULL;
}
}
CFMutableDictionaryRef IOPMCopyPMPreferences(void)
{
IOReturn ret;
CFMutableDictionaryRef settings = NULL;
ret = readAllPMPlistSettings(
kIOPMRemoveUnsupportedPreferences,
&settings,
NULL );
if(kIOReturnSuccess == ret) {
return settings;
} else {
return NULL;
}
}
CFDictionaryRef IOPMCopyActivePMPreferences(void)
{
return _copyActivePMPreferences(kIOPMRemoveUnsupportedPreferences);
}
CFDictionaryRef IOPMCopyUnabridgedActivePMPreferences(void)
{
return _copyActivePMPreferences(kIOPMKeepUnsupportedPreferences);
}
static CFDictionaryRef _copyActivePMPreferences(
bool removeUnsupportedSettings)
{
CFDictionaryRef active_profiles = NULL;
CFArrayRef system_profiles = NULL;
CFMutableDictionaryRef custom_settings = NULL;
CFMutableDictionaryRef return_val = NULL;
CFStringRef *active_profile_dict_keys = NULL;
CFNumberRef *active_profile_dict_values = NULL;
IOReturn ret;
int ps_count;
int i;
system_profiles = IOPMCopyPowerProfiles();
if(!system_profiles) {
return NULL;
}
ret = readAllPMPlistSettings( removeUnsupportedSettings,
&custom_settings,
&active_profiles );
if( kIOReturnSuccess != ret )
{
goto exit;
}
if(!active_profiles || !system_profiles || !custom_settings) goto exit;
return_val = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
ps_count = CFDictionaryGetCount(active_profiles);
active_profile_dict_keys =
(CFStringRef *)malloc(ps_count*sizeof(CFStringRef));
active_profile_dict_values =
(CFNumberRef *)malloc(ps_count*sizeof(CFNumberRef));
if(!active_profile_dict_keys || !active_profile_dict_values) goto exit;
CFDictionaryGetKeysAndValues(
active_profiles,
(const void **)active_profile_dict_keys,
(const void **)active_profile_dict_values);
for(i=0; i<ps_count; i++)
{
int profile_index;
CFDictionaryRef settings_per_power_source;
CFDictionaryRef sys_profile;
CFDictionaryRef tmp_settings;
if(!CFNumberGetValue(active_profile_dict_values[i],
kCFNumberIntType, &profile_index)) continue;
if(-1 == profile_index) {
settings_per_power_source = CFDictionaryGetValue(
custom_settings, active_profile_dict_keys[i]);
} else {
if( (profile_index < 0) || (profile_index > 4) ) continue;
sys_profile = isA_CFDictionary(
CFArrayGetValueAtIndex(system_profiles, profile_index));
if(!sys_profile) continue;
settings_per_power_source = CFDictionaryGetValue(sys_profile,
active_profile_dict_keys[i]);
}
if(!settings_per_power_source) {
continue;
}
tmp_settings = CFDictionaryCreateCopy(kCFAllocatorDefault,
settings_per_power_source);
if(!tmp_settings) continue;
CFDictionarySetValue(return_val, active_profile_dict_keys[i],
tmp_settings);
CFRelease(tmp_settings);
}
exit:
if(active_profile_dict_keys) free(active_profile_dict_keys);
if(active_profile_dict_values) free(active_profile_dict_values);
if(active_profiles) CFRelease(active_profiles);
if(system_profiles) CFRelease(system_profiles);
if(custom_settings) CFRelease(custom_settings);
return return_val;
}
IOReturn IOPMActivatePMPreference(
CFDictionaryRef SystemProfiles,
CFStringRef profile,
bool removeUnsupportedSettings)
{
IOPMAggressivenessFactors *agg = NULL;
CFDictionaryRef activePMPrefs = NULL;
CFDictionaryRef newPMPrefs = NULL;
SCDynamicStoreRef dynamic_store = NULL;
if(0 == isA_CFDictionary(SystemProfiles) || 0 == isA_CFString(profile)) {
return kIOReturnBadArgument;
}
agg = (IOPMAggressivenessFactors *)malloc(sizeof(IOPMAggressivenessFactors));
getAggressivenessFactorsFromProfile(SystemProfiles, profile, agg);
sendEnergySettingsToKernel( SystemProfiles, profile,
removeUnsupportedSettings, agg);
free(agg);
dynamic_store = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("IOKit User Library"),
NULL, NULL);
if(dynamic_store == NULL) return kIOReturnError;
activePMPrefs = isA_CFDictionary(SCDynamicStoreCopyValue(dynamic_store,
CFSTR(kIOPMDynamicStoreSettingsKey)));
newPMPrefs = isA_CFDictionary(CFDictionaryGetValue(SystemProfiles, profile));
if( !activePMPrefs || (newPMPrefs && !CFEqual(activePMPrefs, newPMPrefs)) )
{
SCDynamicStoreSetValue(dynamic_store,
CFSTR(kIOPMDynamicStoreSettingsKey),
newPMPrefs);
}
if(activePMPrefs) CFRelease(activePMPrefs);
CFRelease(dynamic_store);
return kIOReturnSuccess;
}
IOReturn IOPMSetCustomPMPreferences(CFDictionaryRef ESPrefs)
{
return IOPMSetPMPreferences(ESPrefs);
}
IOReturn IOPMSetPMPreferences(CFDictionaryRef ESPrefs)
{
IOReturn ret = kIOReturnError;
SCPreferencesRef energyPrefs = NULL;
CFStringRef energyPrefsKey = NULL;
SCDynamicStoreRef ds = NULL;
if(NULL == ESPrefs)
{
ds = SCDynamicStoreCreate( kCFAllocatorDefault,
CFSTR("IOKit User Library"),
NULL, NULL);
if(!ds) ret = kIOReturnInternalError;
energyPrefsKey = SCDynamicStoreKeyCreatePreferences(
NULL, kIOPMPrefsPath,
kSCPreferencesKeyCommit);
if(!energyPrefsKey) ret = kIOReturnInternalError;
if(!SCDynamicStoreNotifyValue(ds, energyPrefsKey)) {
if(kSCStatusAccessError == SCError()) {
ret = kIOReturnNotPrivileged;
} else {
ret = kIOReturnError;
}
goto commandTouchExit;
}
ret = kIOReturnSuccess;
commandTouchExit:
if(ds) CFRelease(ds);
if(energyPrefsKey) CFRelease(energyPrefsKey);
return ret;
}
energyPrefs = SCPreferencesCreate( kCFAllocatorDefault,
kIOPMAppName, kIOPMPrefsPath );
if(!energyPrefs) return kIOReturnError;
if(!SCPreferencesLock(energyPrefs, true))
{
if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged;
else ret = kIOReturnError;
goto exit;
}
if(!SCPreferencesSetValue(energyPrefs, CFSTR("Custom Profile"), ESPrefs))
{
ret = kIOReturnError;
goto exit;
}
SCPreferencesRemoveValue(energyPrefs, CFSTR(kIOPMACPowerKey));
SCPreferencesRemoveValue(energyPrefs, CFSTR(kIOPMBatteryPowerKey));
SCPreferencesRemoveValue(energyPrefs, CFSTR(kIOPMUPSPowerKey));
if(!SCPreferencesCommitChanges(energyPrefs))
{
if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged;
else ret = kIOReturnError;
goto exit;
}
ret = kIOReturnSuccess;
exit:
if(energyPrefs) {
SCPreferencesUnlock(energyPrefs);
CFRelease(energyPrefs);
}
return ret;
}
#if TARGET_OS_EMBEDDED
#define CACHE_FEATURES 1
#else
#define CACHE_FEATURES 0
#endif
bool IOPMFeatureIsAvailable(CFStringRef PMFeature, CFStringRef power_source)
{
#if CACHE_FEATURES
static
#endif
CFDictionaryRef supportedFeatures = NULL;
CFStringRef supportedString = NULL;
CFTypeRef featureDetails = NULL;
CFArrayRef tmp_array = NULL;
io_registry_entry_t registry_entry = MACH_PORT_NULL;
bool ret = false;
if(!power_source) power_source = CFSTR(kIOPMACPowerKey);
if(CFEqual(PMFeature, CFSTR(kIOPMDisplaySleepKey))
|| CFEqual(PMFeature, CFSTR(kIOPMSystemSleepKey))
|| CFEqual(PMFeature, CFSTR(kIOPMDiskSleepKey)))
{
ret = true;
goto exit;
}
if( CFEqual(PMFeature, CFSTR(kIOPMTTYSPreventSleepKey)) )
{
ret = true;
goto exit;
}
if (!supportedFeatures)
{
registry_entry = getPMRootDomainRef();
if(!registry_entry) goto exit;
supportedFeatures = IORegistryEntryCreateCFProperty(
registry_entry, CFSTR("Supported Features"),
kCFAllocatorDefault, kNilOptions);
}
if(CFEqual(PMFeature, CFSTR(kIOPMSleepOnPowerButtonKey)))
{
#if CACHE_FEATURES
ret = false;
#else
IOReturn r = IOPMCopyBatteryInfo(kIOMasterPortDefault, &tmp_array);
if((r == kIOReturnSuccess) && tmp_array)
{
CFRelease(tmp_array);
ret = false;
} else ret = true;
#endif
goto exit;
}
if ( CFEqual(PMFeature, CFSTR(kIOPMReduceBrightnessKey)) )
{
CFTypeRef ps = IOPSCopyPowerSourcesInfo();
if( ps
&& ( IOPSGetActiveBattery(ps) || IOPSGetActiveUPS(ps) )
&& supportedFeatures
&& CFDictionaryGetValue(supportedFeatures, CFSTR("DisplayDims"))
&& !CFEqual(power_source, CFSTR(kIOPMACPowerKey)) )
{
ret = true;
} else {
ret = false;
}
if(ps) CFRelease(ps);
goto exit;
}
if(!supportedFeatures) {
ret = false;
goto exit;
}
supportedString = supportedNameForPMName( PMFeature );
if(!supportedString) {
ret = false;
goto exit;
}
featureDetails = CFDictionaryGetValue(supportedFeatures, supportedString);
if(!featureDetails) {
ret = false;
goto exit;
}
if(featureSupportsPowerSource(featureDetails, power_source))
{
ret = true;
}
exit:
#if !CACHE_FEATURES
if(supportedFeatures) CFRelease(supportedFeatures);
#endif
return ret;
}
CFDictionaryRef IOPMCopyActivePowerProfiles(void)
{
IOReturn ret;
CFDictionaryRef activeProfiles;
ret = readAllPMPlistSettings(
kIOPMRemoveUnsupportedPreferences,
NULL,
&activeProfiles);
if(kIOReturnSuccess == ret) {
return activeProfiles;
} else {
return NULL;
}
}
IOReturn IOPMSetActivePowerProfiles(CFDictionaryRef which_profile)
{
CFDataRef profiles_data;
vm_address_t profiles_buffer;
IOByteCount buffer_len;
kern_return_t kern_result;
IOReturn return_val = kIOReturnError;
mach_port_t server_port = MACH_PORT_NULL;
if(!_isActiveProfileDictValid(which_profile)) {
return kIOReturnBadArgument;
}
kern_result = bootstrap_look_up(bootstrap_port,
kIOPMServerBootstrapName, &server_port);
if(KERN_SUCCESS != kern_result) {
return kIOReturnError;
}
profiles_data = IOCFSerialize(which_profile, 0);
profiles_buffer = (vm_address_t) CFDataGetBytePtr(profiles_data);
buffer_len = CFDataGetLength(profiles_data);
kern_result = io_pm_set_active_profile(server_port,
profiles_buffer, buffer_len,
&return_val);
mach_port_destroy(mach_task_self(), server_port);
CFRelease(profiles_data);
if(KERN_SUCCESS == kern_result) {
return return_val;
} else {
return kIOReturnInternalError;
}
}
CFRunLoopSourceRef IOPMPrefsNotificationCreateRunLoopSource(
IOPMPrefsCallbackType callback,
void *context)
{
SCDynamicStoreRef store = NULL;
CFStringRef EnergyPrefsKey = NULL;
CFRunLoopSourceRef SCDrls = NULL;
user_callback_context *ioContext = NULL;
SCDynamicStoreContext scContext = {0, NULL, CFRetain, CFRelease, NULL};
if(!callback) return NULL;
scContext.info = CFDataCreateMutable(NULL, sizeof(user_callback_context));
CFDataSetLength(scContext.info, sizeof(user_callback_context));
ioContext = (user_callback_context *)CFDataGetBytePtr(scContext.info);
ioContext->context = context;
ioContext->callback = callback;
store = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("IOKit Preferences Copy"), ioCallout, (void *)&scContext);
if(!store) return NULL;
EnergyPrefsKey = SCDynamicStoreKeyCreatePreferences(
NULL,
kIOPMPrefsPath,
kSCPreferencesKeyApply);
if(EnergyPrefsKey) {
SCDynamicStoreAddWatchedKey(store, EnergyPrefsKey, FALSE);
CFRelease(EnergyPrefsKey);
}
SCDrls = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0);
CFRelease(store);
return SCDrls;
}
static int addDefaultEnergySettings(CFMutableDictionaryRef sys)
{
CFMutableDictionaryRef batt = NULL;
CFMutableDictionaryRef ac = NULL;
CFMutableDictionaryRef ups = NULL;
int i;
CFNumberRef val;
CFStringRef key;
batt=(CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMBatteryPowerKey));
ac=(CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMACPowerKey));
ups=(CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMUPSPowerKey));
if(batt) {
for(i=0; i<kIOPMNumPMFeatures; i++)
{
key = CFStringCreateWithCString(kCFAllocatorDefault,
energy_features_array[i], kCFStringEncodingMacRoman);
val = CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &battery_defaults_array[i]);
CFDictionaryAddValue(batt, key, val);
CFRelease(key);
CFRelease(val);
}
CFDictionaryAddValue(batt, CFSTR(kIOHibernateFileKey),
CFSTR(kIOHibernateDefaultFile));
CFDictionarySetValue(sys, CFSTR(kIOPMBatteryPowerKey), batt);
}
if(ac)
{
for(i=0; i<kIOPMNumPMFeatures; i++)
{
key = CFStringCreateWithCString(kCFAllocatorDefault, energy_features_array[i], kCFStringEncodingMacRoman);
val = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ac_defaults_array[i]);
CFDictionaryAddValue(ac, key, val);
CFRelease(key);
CFRelease(val);
}
CFDictionaryAddValue(ac, CFSTR(kIOHibernateFileKey),
CFSTR(kIOHibernateDefaultFile));
CFDictionarySetValue(sys, CFSTR(kIOPMACPowerKey), ac);
}
if(ups) {
for(i=0; i<kIOPMNumPMFeatures; i++)
{
key = CFStringCreateWithCString(kCFAllocatorDefault,
energy_features_array[i], kCFStringEncodingMacRoman);
val = CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &ups_defaults_array[i]);
CFDictionaryAddValue(ups, key, val);
CFRelease(key);
CFRelease(val);
}
CFDictionaryAddValue(ups, CFSTR(kIOHibernateFileKey),
CFSTR(kIOHibernateDefaultFile));
CFDictionarySetValue(sys, CFSTR(kIOPMUPSPowerKey), ups);
}
return 0;
}
static void addSystemProfileEnergySettings(
CFDictionaryRef user_profile_selections,
CFMutableDictionaryRef passed_in)
{
CFArrayRef system_profiles = NULL;
CFDictionaryRef profile_at_idx = NULL;
CFDictionaryRef finally_actual_settings = NULL;
CFNumberRef this_profile_choice = NULL;
CFNumberRef default_profile_choice = NULL;
CFDictionaryRef default_profile_selections = NULL;
int int_profile_choice = 0;
CFMutableDictionaryRef ps_passed_in = NULL;
CFStringRef this_power_source = NULL;
int i;
if(!user_profile_selections) return;
default_profile_selections = _createDefaultProfileSelections();
system_profiles = IOPMCopyPowerProfiles();
if(!system_profiles) goto exit_cleanup;
for(i = 0; i<kPowerSourcesCount; i++)
{
this_power_source = getPowerSourceString(i);
if(!this_power_source) continue;
this_profile_choice = isA_CFNumber( CFDictionaryGetValue(
user_profile_selections, this_power_source));
if(this_profile_choice) {
CFNumberGetValue( this_profile_choice,
kCFNumberIntType, &int_profile_choice);
}
if( -1 == int_profile_choice ) {
default_profile_choice = isA_CFNumber( CFDictionaryGetValue(
default_profile_selections, this_power_source));
if(default_profile_choice) {
CFNumberGetValue( default_profile_choice,
kCFNumberIntType, &int_profile_choice);
}
}
if ( (int_profile_choice < 0)
|| (int_profile_choice > kPowerProfilesCount) )
{
int_profile_choice = 2;
}
profile_at_idx = CFArrayGetValueAtIndex( system_profiles,
int_profile_choice);
if(!profile_at_idx) continue;
finally_actual_settings = CFDictionaryGetValue(
profile_at_idx, this_power_source);
ps_passed_in = (CFMutableDictionaryRef)
CFDictionaryGetValue(passed_in, this_power_source);
if(!finally_actual_settings || !ps_passed_in) continue;
mergeDictIntoMutable( ps_passed_in,
finally_actual_settings,
false);
}
exit_cleanup:
if(default_profile_selections) CFRelease(default_profile_selections);
if(system_profiles) CFRelease(system_profiles);
return;
}
static io_registry_entry_t getPMRootDomainRef(void)
{
static io_registry_entry_t cached_root_domain = MACH_PORT_NULL;
if( MACH_PORT_NULL == cached_root_domain ) {
cached_root_domain = IORegistryEntryFromPath( kIOMasterPortDefault,
kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain");
}
return cached_root_domain;
}
typedef struct
{
int fd;
uint64_t size;
} CleanHibernateFileArgs;
static void *
CleanHibernateFile(void * args)
{
char * buf;
size_t size, bufSize = 128 * 1024;
int fd = ((CleanHibernateFileArgs *) args)->fd;
uint64_t fileSize = ((CleanHibernateFileArgs *) args)->size;
(void) fcntl(fd, F_NOCACHE, 1);
lseek(fd, 0ULL, SEEK_SET);
buf = calloc(bufSize, sizeof(char));
if (!buf)
return (NULL);
size = bufSize;
while (fileSize)
{
if (fileSize < size)
size = fileSize;
if (size != (size_t) write(fd, buf, size))
break;
fileSize -= size;
}
close(fd);
free(buf);
return (NULL);
}
#define VM_PREFS_PLIST "/Library/Preferences/com.apple.virtualMemory.plist"
#define VM_PREFS_ENCRYPT_SWAP_KEY "UseEncryptedSwap"
__private_extern__ CFMutableDictionaryRef
readPlist(const char * path, UInt32 key);
static boolean_t
EncryptedSwap(void)
{
CFMutableDictionaryRef propertyList;
boolean_t result = FALSE;
propertyList = readPlist(VM_PREFS_PLIST, 0);
if (propertyList)
{
result = ((CFDictionaryGetTypeID() == CFGetTypeID(propertyList))
&& (kCFBooleanTrue == CFDictionaryGetValue(propertyList, CFSTR(VM_PREFS_ENCRYPT_SWAP_KEY))));
CFRelease(propertyList);
}
return (result);
}
static int
ProcessHibernateSettings(CFDictionaryRef dict, io_registry_entry_t rootDomain)
{
IOReturn ret;
CFTypeRef obj;
CFNumberRef modeNum;
SInt32 modeValue = 0;
CFURLRef url = NULL;
Boolean createFile = false;
Boolean haveFile = false;
struct stat statBuf;
char path[MAXPATHLEN];
int fd;
long long size;
size_t len;
fstore_t prealloc;
off_t filesize;
if ( !IOPMFeatureIsAvailable( CFSTR(kIOHibernateFeatureKey), NULL ) )
{
return 0;
}
if ((modeNum = CFDictionaryGetValue(dict, CFSTR(kIOHibernateModeKey)))
&& isA_CFNumber(modeNum))
CFNumberGetValue(modeNum, kCFNumberSInt32Type, &modeValue);
else
modeNum = NULL;
if (modeValue
&& (obj = CFDictionaryGetValue(dict, CFSTR(kIOHibernateFileKey)))
&& isA_CFString(obj))
do
{
url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
obj, kCFURLPOSIXPathStyle, true);
if (!url || !CFURLGetFileSystemRepresentation(url, TRUE, (UInt8 *) path, MAXPATHLEN))
break;
len = sizeof(size);
if (sysctlbyname("hw.memsize", &size, &len, NULL, 0))
break;
filesize = size;
if (0 == stat(path, &statBuf))
{
if ((S_IFBLK == (S_IFMT & statBuf.st_mode))
|| (S_IFCHR == (S_IFMT & statBuf.st_mode)))
{
haveFile = true;
}
else if (S_IFREG == (S_IFMT & statBuf.st_mode))
{
if (statBuf.st_size >= filesize)
haveFile = true;
else
createFile = true;
}
else
break;
}
else
createFile = true;
if (createFile)
{
do
{
char * patchpath, save = 0;
struct statfs sfs;
u_int64_t fsfree;
fd = -1;
if ((patchpath = strrchr(path, '/')))
{
save = *patchpath;
*patchpath = 0;
}
if (-1 == statfs(path, &sfs))
break;
fsfree = ((u_int64_t)sfs.f_bfree * (u_int64_t)sfs.f_bsize);
if ((fsfree - filesize) < kIOHibernateMinFreeSpace)
break;
if (patchpath)
*patchpath = save;
fd = open(path, O_CREAT | O_TRUNC | O_RDWR);
if (-1 == fd)
break;
if (-1 == fchmod(fd, 01600))
break;
prealloc.fst_flags = F_ALLOCATEALL; prealloc.fst_posmode = F_PEOFPOSMODE;
prealloc.fst_offset = 0;
prealloc.fst_length = filesize;
if (((-1 == fcntl(fd, F_PREALLOCATE, &prealloc))
|| (-1 == fcntl(fd, F_SETSIZE, &prealloc.fst_length)))
&& (-1 == ftruncate(fd, prealloc.fst_length)))
break;
haveFile = true;
}
while (false);
if (-1 != fd)
{
close(fd);
if (!haveFile)
unlink(path);
}
}
if (!haveFile)
break;
if (EncryptedSwap() && !createFile)
{
fd = open(path, O_RDWR);
if (-1 != fd) do
{
static CleanHibernateFileArgs args;
IOHibernateImageHeader header;
pthread_attr_t attr;
pthread_t tid;
len = read(fd, &header, sizeof(IOHibernateImageHeader));
if (len != sizeof(IOHibernateImageHeader))
break;
if ((kIOHibernateHeaderSignature != header.signature)
&& (kIOHibernateHeaderInvalidSignature != header.signature))
break;
if (header.encryptStart)
break;
args.fd = fd;
args.size = header.imageSize;
if (pthread_attr_init(&attr))
break;
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
break;
if (pthread_create(&tid, &attr, &CleanHibernateFile, &args))
break;
pthread_attr_destroy(&attr);
fd = -1;
}
while (false);
if (-1 != fd)
close(fd);
}
#if defined (__i386__) || defined(__x86_64__)
#define kBootXPath "/System/Library/CoreServices/boot.efi"
#define kBootXSignaturePath "/System/Library/Caches/com.apple.bootefisignature"
#else
#define kBootXPath "/System/Library/CoreServices/BootX"
#define kBootXSignaturePath "/System/Library/Caches/com.apple.bootxsignature"
#endif
#define kCachesPath "/System/Library/Caches"
#define kGenSignatureCommand "/bin/cat " kBootXPath " | /usr/bin/openssl dgst -sha1 -hex -out " kBootXSignaturePath
struct stat bootx_stat_buf;
struct stat bootsignature_stat_buf;
if (0 != stat(kBootXPath, &bootx_stat_buf))
break;
if ((0 != stat(kBootXSignaturePath, &bootsignature_stat_buf))
|| (bootsignature_stat_buf.st_mtime != bootx_stat_buf.st_mtime))
{
if (-1 == stat(kCachesPath, &bootsignature_stat_buf))
{
mkdir(kCachesPath, 0777);
chmod(kCachesPath, 0777);
}
if (0 != system(kGenSignatureCommand))
break;
struct timeval fileTimes[2];
TIMESPEC_TO_TIMEVAL(&fileTimes[0], &bootx_stat_buf.st_atimespec);
TIMESPEC_TO_TIMEVAL(&fileTimes[1], &bootx_stat_buf.st_mtimespec);
if ((0 != utimes(kBootXSignaturePath, fileTimes)))
break;
}
CFAllocatorRef alloc;
void * sigBytes;
CFIndex sigLen;
alloc = CFRetain(CFAllocatorGetDefault());
if (_IOReadBytesFromFile(alloc, kBootXSignaturePath, &sigBytes, &sigLen, 0))
ret = sysctlbyname("kern.bootsignature", NULL, NULL, sigBytes, sigLen);
else
ret = -1;
CFAllocatorDeallocate(alloc, sigBytes);
CFRelease(alloc);
if (0 != ret)
break;
ret = IORegistryEntrySetCFProperty(rootDomain, CFSTR(kIOHibernateFileKey), obj);
}
while (false);
if (modeNum)
ret = IORegistryEntrySetCFProperty(rootDomain, CFSTR(kIOHibernateModeKey), modeNum);
if ((obj = CFDictionaryGetValue(dict, CFSTR(kIOHibernateFreeRatioKey)))
&& isA_CFNumber(obj))
{
ret = IORegistryEntrySetCFProperty(rootDomain, CFSTR(kIOHibernateFreeRatioKey), obj);
}
if ((obj = CFDictionaryGetValue(dict, CFSTR(kIOHibernateFreeTimeKey)))
&& isA_CFNumber(obj))
{
ret = IORegistryEntrySetCFProperty(rootDomain, CFSTR(kIOHibernateFreeTimeKey), obj);
}
if (url)
CFRelease(url);
return (0);
}
static int sendEnergySettingsToKernel(
CFDictionaryRef System,
CFStringRef prof,
bool removeUnsupportedSettings,
IOPMAggressivenessFactors *p
)
{
io_registry_entry_t PMRootDomain = MACH_PORT_NULL;
io_connect_t PM_connection = MACH_PORT_NULL;
CFTypeRef power_source_info = NULL;
CFStringRef providing_power = NULL;
IOReturn err;
IOReturn ret;
CFNumberRef number1;
CFNumberRef number0;
CFNumberRef tmp_num;
int type;
uint32_t i;
i = 1;
number1 = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
i = 0;
number0 = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
if(!number0 || !number1) return -1;
PMRootDomain = getPMRootDomainRef();
if(!PMRootDomain) return -1;
PM_connection = IOPMFindPowerManagement(0);
if ( !PM_connection ) return -1;
power_source_info = IOPSCopyPowerSourcesInfo();
if(power_source_info) {
providing_power = IOPSGetProvidingPowerSourceType(power_source_info);
}
IOPMSetAggressiveness(PM_connection, kPMMinutesToSleep, p->fMinutesToSleep);
IOPMSetAggressiveness(PM_connection, kPMMinutesToSpinDown, p->fMinutesToSpin);
IOPMSetAggressiveness(PM_connection, kPMMinutesToDim, p->fMinutesToDim);
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnLANKey), providing_power))
{
type = kPMEthernetWakeOnLANSettings;
err = IOPMSetAggressiveness(PM_connection, type, p->fWakeOnLAN);
} else {
type = kPMEthernetWakeOnLANSettings;
err = IOPMSetAggressiveness(PM_connection, type, 0);
}
if ( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMDisplaySleepUsesDimKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingDisplaySleepUsesDimKey),
(p->fDisplaySleepUsesDimming?number1:number0));
}
if( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnRingKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingWakeOnRingKey),
(p->fWakeOnRing?number1:number0));
}
if( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMRestartOnPowerLossKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingRestartOnPowerLossKey),
(p->fAutomaticRestart?number1:number0));
}
if( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnACChangeKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingWakeOnACChangeKey),
(p->fWakeOnACChange?number1:number0));
}
if( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMSleepOnPowerButtonKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingSleepOnPowerButtonKey),
(p->fSleepOnPowerButton?kCFBooleanFalse:kCFBooleanTrue));
}
if( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnClamshellKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingWakeOnClamshellKey),
(p->fWakeOnClamshell?number1:number0));
}
if( !removeUnsupportedSettings
|| IOPMFeatureIsAvailable(CFSTR(kIOPMMobileMotionModuleKey), providing_power))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain,
CFSTR(kIOPMSettingMobileMotionModuleKey),
(p->fMobileMotionModule?number1:number0));
}
CFDictionaryRef dict = NULL;
if((dict = CFDictionaryGetValue(System, prof)) )
{
ProcessHibernateSettings(dict, PMRootDomain);
}
CFRelease(number0);
CFRelease(number1);
if(power_source_info) CFRelease(power_source_info);
IOServiceClose(PM_connection);
return 0;
}
static bool getAggressivenessValue(
CFDictionaryRef dict,
CFStringRef key,
CFNumberType type,
uint32_t *ret)
{
CFTypeRef obj = CFDictionaryGetValue(dict, key);
*ret = 0;
if (isA_CFNumber(obj))
{
CFNumberGetValue(obj, type, ret);
return true;
}
else if (isA_CFBoolean(obj))
{
*ret = CFBooleanGetValue(obj);
return true;
}
return false;
}
static int getAggressivenessFactorsFromProfile(
CFDictionaryRef System,
CFStringRef prof,
IOPMAggressivenessFactors *agg)
{
CFDictionaryRef p = NULL;
if( !(p = CFDictionaryGetValue(System, prof)) )
{
return -1;
}
if(!agg) return -1;
getAggressivenessValue(p, CFSTR(kIOPMDisplaySleepKey),
kCFNumberSInt32Type, &agg->fMinutesToDim);
getAggressivenessValue(p, CFSTR(kIOPMDiskSleepKey),
kCFNumberSInt32Type, &agg->fMinutesToSpin);
getAggressivenessValue(p, CFSTR(kIOPMSystemSleepKey),
kCFNumberSInt32Type, &agg->fMinutesToSleep);
getAggressivenessValue(p, CFSTR(kIOPMWakeOnLANKey),
kCFNumberSInt32Type, &agg->fWakeOnLAN);
getAggressivenessValue(p, CFSTR(kIOPMWakeOnRingKey),
kCFNumberSInt32Type, &agg->fWakeOnRing);
getAggressivenessValue(p, CFSTR(kIOPMRestartOnPowerLossKey),
kCFNumberSInt32Type, &agg->fAutomaticRestart);
getAggressivenessValue(p, CFSTR(kIOPMSleepOnPowerButtonKey),
kCFNumberSInt32Type, &agg->fSleepOnPowerButton);
getAggressivenessValue(p, CFSTR(kIOPMWakeOnClamshellKey),
kCFNumberSInt32Type, &agg->fWakeOnClamshell);
getAggressivenessValue(p, CFSTR(kIOPMWakeOnACChangeKey),
kCFNumberSInt32Type, &agg->fWakeOnACChange);
getAggressivenessValue(p, CFSTR(kIOPMDisplaySleepUsesDimKey),
kCFNumberSInt32Type, &agg->fDisplaySleepUsesDimming);
getAggressivenessValue(p, CFSTR(kIOPMMobileMotionModuleKey),
kCFNumberSInt32Type, &agg->fMobileMotionModule);
return 0;
}
static CFStringRef
supportedNameForPMName( CFStringRef pm_name )
{
#if TARGET_OS_EMBEDDED
if( CFEqual(pm_name, CFSTR(kIOPMReduceBrightnessKey))
|| CFEqual(pm_name, CFSTR(kIOPMDisplaySleepUsesDimKey)) )
#else
if(CFEqual(pm_name, CFSTR(kIOPMDisplaySleepUsesDimKey)))
#endif
{
return CFSTR("DisplayDims");
}
if(CFEqual(pm_name, CFSTR(kIOPMWakeOnLANKey)))
{
return CFSTR("WakeOnMagicPacket");
}
if(CFEqual(pm_name, CFSTR(kIOPMMobileMotionModuleKey)))
{
return CFSTR("MobileMotionModule");
}
if( CFEqual(pm_name, CFSTR(kIOHibernateModeKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFreeRatioKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFreeTimeKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFileKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFeatureKey)))
{
return CFSTR(kIOHibernateFeatureKey);
}
return pm_name;
}
static bool
featureSupportsPowerSource(CFTypeRef featureDetails, CFStringRef power_source)
{
CFNumberRef featureNum = NULL;
CFNumberRef tempNum = NULL;
CFArrayRef featureArr = NULL;
uint32_t ps_support = 0;
uint32_t tmp;
unsigned int i;
if( (featureNum = isA_CFNumber(featureDetails)) )
{
CFNumberGetValue(featureNum, kCFNumberSInt32Type, &ps_support);
} else if( (featureArr = isA_CFArray(featureDetails)) )
{
unsigned int arrayCount = CFArrayGetCount(featureArr);
for(i = 0; i<arrayCount; i++)
{
tempNum = isA_CFNumber(CFArrayGetValueAtIndex(featureArr, i));
if(tempNum) {
CFNumberGetValue(tempNum, kCFNumberSInt32Type, &tmp);
ps_support |= tmp;
}
}
}
if(!power_source) {
return (ps_support ? true : false);
}
if(CFEqual(CFSTR(kIOPMACPowerKey), power_source) )
{
return (ps_support & kIOPMSupportedOnAC) ? true : false;
} else if(CFEqual(CFSTR(kIOPMBatteryPowerKey), power_source) )
{
return (ps_support & kIOPMSupportedOnBatt) ? true : false;
} else if(CFEqual(CFSTR(kIOPMUPSPowerKey), power_source) )
{
return (ps_support & kIOPMSupportedOnUPS) ? true : false;
} else {
return false;
}
}
static void IOPMRemoveIrrelevantProperties(CFMutableDictionaryRef energyPrefs)
{
int profile_count = 0;
int dict_count = 0;
CFStringRef *profile_keys = NULL;
CFDictionaryRef *profile_vals = NULL;
CFStringRef *dict_keys = NULL;
CFDictionaryRef *dict_vals = NULL;
CFMutableDictionaryRef this_profile;
CFTypeRef ps_snapshot;
ps_snapshot = IOPSCopyPowerSourcesInfo();
profile_count = CFDictionaryGetCount(energyPrefs);
profile_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * profile_count);
profile_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * profile_count);
if(!profile_keys || !profile_vals) return;
CFDictionaryGetKeysAndValues(energyPrefs, (const void **)profile_keys,
(const void **)profile_vals);
while(--profile_count >= 0)
{
if(kCFBooleanTrue != IOPSPowerSourceSupported(ps_snapshot, profile_keys[profile_count]))
{
CFDictionaryRemoveValue(energyPrefs, profile_keys[profile_count]);
} else {
this_profile = (CFMutableDictionaryRef)isA_CFDictionary(
CFDictionaryGetValue(energyPrefs, profile_keys[profile_count]));
if(!this_profile) continue;
this_profile = CFDictionaryCreateMutableCopy(NULL, 0, this_profile);
if(!this_profile) continue;
CFDictionarySetValue(energyPrefs, profile_keys[profile_count], this_profile);
CFRelease(this_profile);
dict_count = CFDictionaryGetCount(this_profile);
dict_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * dict_count);
dict_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * dict_count);
if(!dict_keys || !dict_vals) continue;
CFDictionaryGetKeysAndValues(this_profile,
(const void **)dict_keys, (const void **)dict_vals);
while(--dict_count >= 0)
{
if( !IOPMFeatureIsAvailable((CFStringRef)dict_keys[dict_count],
(CFStringRef)profile_keys[profile_count]) )
{
CFDictionaryRemoveValue(this_profile,
(CFStringRef)dict_keys[dict_count]);
}
}
free(dict_keys);
free(dict_vals);
}
}
free(profile_keys);
free(profile_vals);
if(ps_snapshot) CFRelease(ps_snapshot);
return;
}
static int getCheetahPumaEnergySettings(CFMutableDictionaryRef energyPrefs)
{
SCPreferencesRef CheetahPrefs = NULL;
CFMutableDictionaryRef s = NULL;
CFNumberRef n;
CFBooleanRef b;
if(!energyPrefs) return 0;
CheetahPrefs = SCPreferencesCreate (kCFAllocatorDefault,
CFSTR("I/O Kit PM Library"),
CFSTR("/Library/Preferences/com.apple.PowerManagement.plist"));
if(!CheetahPrefs) return 0;
s = (CFMutableDictionaryRef)CFDictionaryGetValue( energyPrefs,
CFSTR(kIOPMBatteryPowerKey));
if(!s)
{
CFRelease(CheetahPrefs);
return 0;
}
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDimKey);
if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDisplaySleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDiskKey);
if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDiskSleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahSleepKey);
if(n) CFDictionaryAddValue(s, CFSTR(kIOPMSystemSleepKey), n);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahRestartOnPowerLossKey);
if(b) CFDictionaryAddValue(s, CFSTR(kIOPMRestartOnPowerLossKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeForNetworkAccessKey);
if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnLANKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeOnRingKey);
if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnRingKey), b);
s = (CFMutableDictionaryRef)CFDictionaryGetValue(energyPrefs, CFSTR(kIOPMACPowerKey));
if(!s)
{
CFRelease(CheetahPrefs);
return 0;
}
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDimKey);
if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDisplaySleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDiskKey);
if(n) CFDictionaryAddValue(s, CFSTR(kIOPMDiskSleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahSleepKey);
if(n) CFDictionaryAddValue(s, CFSTR(kIOPMSystemSleepKey), n);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahRestartOnPowerLossKey);
if(b) CFDictionaryAddValue(s, CFSTR(kIOPMRestartOnPowerLossKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeForNetworkAccessKey);
if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnLANKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeOnRingKey);
if(b) CFDictionaryAddValue(s, CFSTR(kIOPMWakeOnRingKey), b);
CFRelease(CheetahPrefs);
return 1; }
IOReturn IOPMActivateSystemPowerSettings( void )
{
io_registry_entry_t rootdomain = MACH_PORT_NULL;
CFDictionaryRef settings = NULL;
IOReturn ret = kIOReturnSuccess;
bool disable_sleep = false;
settings = IOPMCopySystemPowerSettings();
if(!settings) {
goto exit;
}
disable_sleep = (kCFBooleanTrue ==
CFDictionaryGetValue( settings, kIOPMSleepDisabledKey ));
rootdomain = getPMRootDomainRef();
ret = IORegistryEntrySetCFProperty( rootdomain, kIOPMSleepDisabledKey,
(disable_sleep ? kCFBooleanTrue : kCFBooleanFalse));
exit:
if(settings) CFRelease( settings );
return ret;
}
CFDictionaryRef IOPMCopySystemPowerSettings(void)
{
CFMutableDictionaryRef systemPowerDictionary = NULL;
CFDictionaryRef tmp_dict = NULL;
SCPreferencesRef energyPrefs = NULL;
energyPrefs = SCPreferencesCreate( kCFAllocatorDefault,
kIOPMAppName, kIOPMPrefsPath );
if(!energyPrefs) {
return NULL;
}
tmp_dict = isA_CFDictionary(SCPreferencesGetValue( energyPrefs,
CFSTR("SystemPowerSettings")));
if(!tmp_dict) {
goto exit;
}
systemPowerDictionary = CFDictionaryCreateCopy(0, tmp_dict);
exit:
if(energyPrefs) CFRelease(energyPrefs);
return systemPowerDictionary;
}
IOReturn IOPMSetSystemPowerSetting( CFStringRef key, CFTypeRef value)
{
IOReturn ret = kIOReturnError;
SCPreferencesRef energyPrefs = NULL;
CFMutableDictionaryRef systemPowerDictionary = NULL;
CFDictionaryRef tmp_dict = NULL;
energyPrefs = SCPreferencesCreate( 0, kIOPMAppName, kIOPMPrefsPath );
if(!energyPrefs) return kIOReturnError;
if(!SCPreferencesLock(energyPrefs, true))
{
if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged;
else ret = kIOReturnError;
goto exit;
}
tmp_dict = IOPMCopySystemPowerSettings();
if(tmp_dict) {
systemPowerDictionary = CFDictionaryCreateMutableCopy(0, 0, tmp_dict);
CFRelease(tmp_dict);
tmp_dict = NULL;
} else {
systemPowerDictionary = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if(!systemPowerDictionary) {
goto exit;
}
CFDictionarySetValue( systemPowerDictionary, key, value);
ret = kIOReturnSuccess;
if(!SCPreferencesSetValue( energyPrefs,
CFSTR("SystemPowerSettings"),
systemPowerDictionary))
{
ret = kIOReturnError;
goto exit;
}
if(!SCPreferencesCommitChanges(energyPrefs))
{
if(kSCStatusAccessError == SCError()) ret = kIOReturnNotPrivileged;
else ret = kIOReturnError;
goto exit;
}
ret = kIOReturnSuccess;
exit:
if(energyPrefs) {
SCPreferencesUnlock(energyPrefs);
CFRelease(energyPrefs);
}
return ret;
}
static void mergeDictIntoMutable(
CFMutableDictionaryRef target,
CFDictionaryRef overrides,
bool overwrite)
{
const CFStringRef *keys;
const CFTypeRef *objs;
int count;
int i;
count = CFDictionaryGetCount(overrides);
if(0 == count) return;
keys = (CFStringRef *)malloc(sizeof(CFStringRef) * count);
objs = (CFTypeRef *)malloc(sizeof(CFTypeRef) * count);
if(!keys || !objs) return;
CFDictionaryGetKeysAndValues(overrides,
(const void **)keys, (const void **)objs);
for(i=0; i<count; i++)
{
if(overwrite) {
CFDictionarySetValue(target, keys[i], objs[i]);
} else {
CFDictionaryAddValue(target, keys[i], objs[i]);
}
}
free((void *)keys);
free((void *)objs);
}
static CFArrayRef _copySystemProvidedProfiles()
{
io_registry_entry_t registry_entry = MACH_PORT_NULL;
CFTypeRef cftype_total_prof_override = NULL;
CFTypeRef cftype_overrides = NULL;
CFArrayRef retArray = NULL;
CFDictionaryRef overrides = NULL;
CFDictionaryRef ac_over = NULL;
CFDictionaryRef batt_over = NULL;
CFDictionaryRef ups_over = NULL;
CFArrayRef sysPowerProfiles = NULL;
CFMutableArrayRef mArrProfs = NULL;
int count = 0;
int i = 0;
registry_entry = getPMRootDomainRef();
if(MACH_PORT_NULL == registry_entry) return NULL;
cftype_overrides = IORegistryEntryCreateCFProperty(registry_entry,
CFSTR(kIOPMSystemDefaultOverrideKey),
kCFAllocatorDefault, 0);
if( !(overrides = isA_CFDictionary(cftype_overrides)) ) {
if(cftype_overrides) {
CFRelease(cftype_overrides); cftype_overrides = NULL;
}
goto TrySystemDefaultProfiles;
}
ac_over = CFDictionaryGetValue(overrides, CFSTR(kIOPMACPowerKey));
batt_over = CFDictionaryGetValue(overrides, CFSTR(kIOPMBatteryPowerKey));
ups_over = CFDictionaryGetValue(overrides, CFSTR(kIOPMUPSPowerKey));
if(ac_over && batt_over && ups_over)
{
} else if(!ac_over && !batt_over && !ups_over)
{
ac_over = batt_over = ups_over = overrides;
} else {
goto TrySystemDefaultProfiles;
}
sysPowerProfiles = _createDefaultSystemProfiles();
if(!sysPowerProfiles) goto exit;
count = CFArrayGetCount(sysPowerProfiles);
mArrProfs = CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks);
for(i=0; i<count; i++)
{
CFMutableDictionaryRef mSettingsAC;
CFMutableDictionaryRef mSettingsBatt;
CFMutableDictionaryRef mSettingsUPS;
CFMutableDictionaryRef mProfile;
CFDictionaryRef _profile;
CFDictionaryRef tmp;
_profile = (CFDictionaryRef)CFArrayGetValueAtIndex(sysPowerProfiles, i);
if(!_profile) continue;
mProfile = CFDictionaryCreateMutable(0,
CFDictionaryGetCount(_profile),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if(!mProfile) continue;
CFArraySetValueAtIndex(mArrProfs, i, mProfile);
CFRelease(mProfile);
tmp = (CFDictionaryRef)CFDictionaryGetValue(_profile,
CFSTR(kIOPMACPowerKey));
if(!tmp) continue;
mSettingsAC = CFDictionaryCreateMutableCopy(0,
CFDictionaryGetCount(tmp), tmp);
tmp = (CFDictionaryRef)CFDictionaryGetValue(_profile,
CFSTR(kIOPMBatteryPowerKey));
if(!tmp) continue;
mSettingsBatt = CFDictionaryCreateMutableCopy(0,
CFDictionaryGetCount(tmp), tmp);
tmp = (CFDictionaryRef)CFDictionaryGetValue(_profile,
CFSTR(kIOPMUPSPowerKey));
if(!tmp) continue;
mSettingsUPS = CFDictionaryCreateMutableCopy(0,
CFDictionaryGetCount(tmp), tmp);
if( !(mSettingsAC && mSettingsBatt && mSettingsUPS) ) {
if(sysPowerProfiles) {
CFRelease(sysPowerProfiles); sysPowerProfiles = NULL;
}
if(mSettingsAC) {
CFRelease(mSettingsAC); mSettingsAC = NULL;
}
if(mSettingsBatt) {
CFRelease(mSettingsBatt); mSettingsBatt = NULL;
}
if(mSettingsUPS) {
CFRelease(mSettingsUPS); mSettingsUPS = NULL;
}
if(mArrProfs) {
CFRelease(mArrProfs); mArrProfs = NULL;
}
goto TrySystemDefaultProfiles;
}
CFDictionarySetValue(mProfile,
CFSTR(kIOPMACPowerKey),
mSettingsAC);
CFDictionarySetValue(mProfile,
CFSTR(kIOPMBatteryPowerKey),
mSettingsBatt);
CFDictionarySetValue(mProfile,
CFSTR(kIOPMUPSPowerKey),
mSettingsUPS);
mergeDictIntoMutable(mSettingsAC, ac_over, true);
mergeDictIntoMutable(mSettingsBatt, batt_over, true);
mergeDictIntoMutable(mSettingsUPS, ups_over, true);
CFRelease(mSettingsAC); mSettingsAC = NULL;
CFRelease(mSettingsBatt); mSettingsBatt = NULL;
CFRelease(mSettingsUPS); mSettingsUPS = NULL;
}
retArray = (CFArrayRef)mArrProfs;
goto exit;
TrySystemDefaultProfiles:
cftype_total_prof_override = IORegistryEntryCreateCFProperty(registry_entry,
CFSTR(kIOPMSystemDefaultProfilesKey),
kCFAllocatorDefault, 0);
if( isA_CFArray(cftype_total_prof_override) ) {
retArray = (CFArrayRef)cftype_total_prof_override;
goto exit;
} else {
if(cftype_total_prof_override) {
CFRelease(cftype_total_prof_override);
cftype_total_prof_override = NULL;
}
}
exit:
if(sysPowerProfiles) {
CFRelease(sysPowerProfiles); sysPowerProfiles = NULL;
}
if(cftype_overrides) {
CFRelease(cftype_overrides); cftype_overrides = NULL;
}
return retArray;
}
static CFArrayRef _createDefaultSystemProfiles()
{
CFURLRef pm_bundle_url = 0;
CFBundleRef pm_bundle = 0;
CFURLRef profiles_url = 0;
CFStringRef profiles_path = 0;
CFArrayRef system_default_profiles = 0;
CFArrayRef return_array = 0;
SCPreferencesRef open_file = 0;
pm_bundle_url = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,
CFSTR("/System/Library/SystemConfiguration/PowerManagement.bundle"),
kCFURLPOSIXPathStyle,
1);
if(!pm_bundle_url) {
goto exit;
}
pm_bundle = CFBundleCreate(
kCFAllocatorDefault,
pm_bundle_url);
if(!pm_bundle) {
goto exit;
}
profiles_url = CFBundleCopyResourceURL(
pm_bundle,
CFSTR("com.apple.SystemPowerProfileDefaults.plist"),
NULL,
NULL);
if(!profiles_url) {
goto exit;
}
profiles_path = CFURLCopyPath(profiles_url);
open_file = SCPreferencesCreate(
kCFAllocatorDefault,
CFSTR("PowerManagementPreferences"),
profiles_path);
if(!open_file) {
goto exit;
}
system_default_profiles = SCPreferencesGetValue(
open_file,
CFSTR("SystemProfileDefaults"));
if(!isA_CFArray(system_default_profiles)) {
goto exit;
}
return_array = CFArrayCreateCopy(0, system_default_profiles);
exit:
if(pm_bundle_url) CFRelease(pm_bundle_url);
if(pm_bundle) CFRelease(pm_bundle);
if(profiles_url) CFRelease(profiles_url);
if(profiles_path) CFRelease(profiles_path);
if(open_file) CFRelease(open_file);
if(!return_array) {
syslog(LOG_INFO, "Power Management error: unable to load default System Power Profiles.\n");
}
return return_array;
}
static CFDictionaryRef _createDefaultProfileSelections(void)
{
CFURLRef pm_bundle_url = 0;
CFBundleRef pm_bundle = 0;
CFURLRef profiles_url = 0;
CFStringRef profiles_path = 0;
CFDictionaryRef default_profiles_selection = 0;
CFDictionaryRef return_dict = 0;
SCPreferencesRef open_file = 0;
pm_bundle_url = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,
CFSTR("/System/Library/SystemConfiguration/PowerManagement.bundle"),
kCFURLPOSIXPathStyle,
1);
if(!pm_bundle_url) {
goto exit;
}
pm_bundle = CFBundleCreate(
kCFAllocatorDefault,
pm_bundle_url);
if(!pm_bundle) {
goto exit;
}
profiles_url = CFBundleCopyResourceURL(
pm_bundle,
CFSTR("com.apple.SystemPowerProfileDefaults.plist"),
NULL,
NULL);
if(!profiles_url) {
goto exit;
}
profiles_path = CFURLCopyPath(profiles_url);
open_file = SCPreferencesCreate(
kCFAllocatorDefault,
CFSTR("PowerManagementPreferences"),
profiles_path);
if(!open_file) {
goto exit;
}
default_profiles_selection = SCPreferencesGetValue(
open_file,
CFSTR("DefaultProfileChoices"));
if(!isA_CFDictionary(default_profiles_selection)) {
goto exit;
}
return_dict = CFDictionaryCreateCopy(kCFAllocatorDefault, default_profiles_selection);
exit:
if(pm_bundle_url) CFRelease(pm_bundle_url);
if(pm_bundle) CFRelease(pm_bundle);
if(profiles_url) CFRelease(profiles_url);
if(profiles_path) CFRelease(profiles_path);
if(open_file) CFRelease(open_file);
if(!return_dict) {
syslog(LOG_INFO, "Power Management error: unable to load default profiles selections.\n");
}
return return_dict;
}
static CFDictionaryRef _createAllCustomProfileSelections(void)
{
int j = -1;
CFNumberRef n;
CFMutableDictionaryRef custom_dict = NULL;
custom_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 3,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
n = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &j);
if(!custom_dict || !n) return NULL;
CFDictionarySetValue(custom_dict, CFSTR(kIOPMACPowerKey), n);
CFDictionarySetValue(custom_dict, CFSTR(kIOPMBatteryPowerKey), n);
CFDictionarySetValue(custom_dict, CFSTR(kIOPMUPSPowerKey), n);
CFRelease(n);
return custom_dict;
}
CFArrayRef IOPMCopyPowerProfiles(void)
{
CFArrayRef power_profiles = 0;
CFMutableArrayRef mutable_power_profiles = 0;
CFDictionaryRef tmp;
CFMutableDictionaryRef mutable_profile;
int i, p_count;
power_profiles = _copySystemProvidedProfiles();
if(!power_profiles) {
power_profiles = _createDefaultSystemProfiles();
}
if(!power_profiles) return NULL;
mutable_power_profiles = CFArrayCreateMutableCopy(0, 0, power_profiles);
if(!mutable_power_profiles) goto exit;
p_count = CFArrayGetCount(mutable_power_profiles);
for(i=0; i<p_count; i++)
{
tmp = CFArrayGetValueAtIndex(power_profiles, i);
if(!tmp) continue;
mutable_profile = CFDictionaryCreateMutableCopy(
kCFAllocatorDefault,
0,
tmp);
if(!mutable_profile) continue;
IOPMRemoveIrrelevantProperties(mutable_profile);
CFArraySetValueAtIndex(mutable_power_profiles, i, mutable_profile);
CFRelease(mutable_profile);
}
exit:
if(power_profiles) CFRelease(power_profiles);
return mutable_power_profiles;
}
static int _isActiveProfileDictValid(CFDictionaryRef p)
{
CFNumberRef val;
int j;
if(!p) return 0;
val = CFDictionaryGetValue(p, CFSTR(kIOPMACPowerKey));
if(!val) return 0;
CFNumberGetValue(val, kCFNumberIntType, &j);
if(j<-1 || j>= kIOPMNumPowerProfiles) return 0;
val = CFDictionaryGetValue(p, CFSTR(kIOPMBatteryPowerKey));
if(val) {
CFNumberGetValue(val, kCFNumberIntType, &j);
if(j<-1 || j>= kIOPMNumPowerProfiles) return 0;
}
val = CFDictionaryGetValue(p, CFSTR(kIOPMUPSPowerKey));
if(val) {
CFNumberGetValue(val, kCFNumberIntType, &j);
if(j<-1 || j>= kIOPMNumPowerProfiles) return 0;
}
return 1;
}
static void _purgeUnsupportedPowerSources(CFMutableDictionaryRef p)
{
CFStringRef *ps_names = NULL;
CFTypeRef ps_snap = NULL;
int count;
int i;
ps_snap = IOPSCopyPowerSourcesInfo();
if(!ps_snap) return;
count = CFDictionaryGetCount(p);
ps_names = (CFStringRef *)malloc(count*sizeof(CFStringRef));
if(!ps_names) goto exit;
CFDictionaryGetKeysAndValues(p, (CFTypeRef *)ps_names, NULL);
for(i=0; i<count; i++)
{
if(kCFBooleanTrue != IOPSPowerSourceSupported(ps_snap, ps_names[i])) {
CFDictionaryRemoveValue(p, ps_names[i]);
}
}
exit:
if(ps_snap) CFRelease(ps_snap);
if(ps_names) free(ps_names);
}
static CFStringRef getPowerSourceString(int i)
{
if(i == 1) return CFSTR(kIOPMBatteryPowerKey);
if(i == 2) return CFSTR(kIOPMUPSPowerKey);
return CFSTR(kIOPMACPowerKey);
}
static void ioCallout(
SCDynamicStoreRef store __unused,
CFArrayRef keys __unused,
void *ctxt)
{
user_callback_context *c;
IOPowerSourceCallbackType cb;
c = (user_callback_context *)CFDataGetBytePtr((CFDataRef)ctxt);
if(!c) return;
cb = c->callback;
if(!cb) return;
(*cb)(c->context);
}
IOReturn readAllPMPlistSettings(
bool removeUnsupportedSettings,
CFMutableDictionaryRef *customSettings,
CFDictionaryRef *profileSelections)
{
CFMutableDictionaryRef energyDict = NULL;
CFDictionaryRef tmp_dict = NULL;
SCPreferencesRef energyPrefs = NULL;
CFMutableDictionaryRef batterySettings = NULL;
CFMutableDictionaryRef ACSettings = NULL;
CFMutableDictionaryRef UPSSettings = NULL;
bool usingDefaults = true;
bool prefsSuccess = false;
CFDictionaryRef tmp = NULL;
CFDictionaryRef defaultProfiles = NULL;
CFStringRef *profileKeys = NULL;
CFNumberRef *profileValues = NULL;
bool activeProfilesSpecified = false;
int profileCount;
int i;
bool profilesSuccess = false;
CFMutableDictionaryRef acquiredProfiles = NULL;
energyPrefs = SCPreferencesCreate( 0, kIOPMAppName, kIOPMPrefsPath );
if(!energyPrefs) {
if(customSettings) *customSettings = NULL;
if(profileSelections) *profileSelections = NULL;
return kIOReturnNotOpen;
}
tmp = SCPreferencesGetValue(energyPrefs, CFSTR("ActivePowerProfiles"));
if(tmp && _isActiveProfileDictValid(tmp)) {
acquiredProfiles = CFDictionaryCreateMutableCopy(0, 0, tmp);
activeProfilesSpecified = true;
} else {
acquiredProfiles = NULL;
}
tmp_dict = isA_CFDictionary(SCPreferencesGetValue(energyPrefs,
CFSTR("Custom Profile")));
if(tmp_dict)
{
usingDefaults = false;
energyDict = CFDictionaryCreateMutableCopy(
kCFAllocatorDefault,
0,
tmp_dict);
if(!energyDict) goto prefsExit;
} else {
batterySettings = (CFMutableDictionaryRef)isA_CFDictionary(
SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMBatteryPowerKey)));
ACSettings = (CFMutableDictionaryRef)isA_CFDictionary(
SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMACPowerKey)));
UPSSettings = (CFMutableDictionaryRef)isA_CFDictionary(
SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMUPSPowerKey)));
if ( batterySettings || ACSettings || UPSSettings )
usingDefaults = false;
energyDict = CFDictionaryCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if(!energyDict) goto prefsExit;
if(batterySettings) {
CFDictionaryAddValue(energyDict, CFSTR(kIOPMBatteryPowerKey),
batterySettings);
}
if(ACSettings) {
CFDictionaryAddValue(energyDict, CFSTR(kIOPMACPowerKey),
ACSettings);
}
if(UPSSettings) {
CFDictionaryAddValue(energyDict, CFSTR(kIOPMUPSPowerKey),
UPSSettings);
}
}
tmp = isA_CFDictionary(CFDictionaryGetValue(
energyDict, CFSTR(kIOPMBatteryPowerKey)));
if(tmp) {
batterySettings = CFDictionaryCreateMutableCopy(0, 0, tmp);
} else {
batterySettings = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if(batterySettings)
{
CFDictionarySetValue(energyDict, CFSTR(kIOPMBatteryPowerKey),
batterySettings);
CFRelease(batterySettings);
} else goto prefsExit;
tmp = isA_CFDictionary(CFDictionaryGetValue(
energyDict, CFSTR(kIOPMACPowerKey)));
if(tmp) {
ACSettings = CFDictionaryCreateMutableCopy(0, 0, tmp);
} else {
ACSettings = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if(ACSettings) {
CFDictionarySetValue(energyDict, CFSTR(kIOPMACPowerKey), ACSettings);
CFRelease(ACSettings);
} else goto prefsExit;
tmp = isA_CFDictionary(CFDictionaryGetValue(
energyDict, CFSTR(kIOPMUPSPowerKey)));
if(tmp) {
UPSSettings = CFDictionaryCreateMutableCopy(0, 0, tmp);
} else {
UPSSettings = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if(UPSSettings) {
CFDictionarySetValue(energyDict, CFSTR(kIOPMUPSPowerKey), UPSSettings);
CFRelease(UPSSettings);
} else goto prefsExit;
getCheetahPumaEnergySettings(energyDict);
addSystemProfileEnergySettings(acquiredProfiles, energyDict);
addDefaultEnergySettings(energyDict);
if (removeUnsupportedSettings)
{
IOPMRemoveIrrelevantProperties(energyDict);
}
if(usingDefaults) {
CFDictionarySetValue(energyDict, CFSTR(kIOPMDefaultPreferencesKey),
kCFBooleanTrue);
}
prefsSuccess = true;
if( customSettings ) {
*customSettings = energyDict;
}
prefsExit:
if ( !prefsSuccess && customSettings) {
*customSettings = NULL;
}
if( !profileSelections ) {
profilesSuccess = true;
} else {
if(!acquiredProfiles) {
acquiredProfiles = CFDictionaryCreateMutable(0, 3,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if(!activeProfilesSpecified && !usingDefaults)
{
defaultProfiles = _createAllCustomProfileSelections();
} else {
defaultProfiles = _createDefaultProfileSelections();
}
if(isA_CFDictionary(defaultProfiles))
{
profileCount = CFDictionaryGetCount(defaultProfiles);
profileKeys = malloc(sizeof(CFStringRef)*profileCount);
profileValues = malloc(sizeof(CFNumberRef)*profileCount);
if ( !profileKeys || !profileValues ) goto profilesExit;
CFDictionaryGetKeysAndValues(defaultProfiles,
(const void **)profileKeys, (const void **)profileValues);
for(i=0; i<profileCount; i++)
{
if( isA_CFString(profileKeys[i]) &&
isA_CFNumber(profileValues[i]) )
{
CFDictionaryAddValue(acquiredProfiles, profileKeys[i],
profileValues[i]);
}
}
free(profileKeys);
free(profileValues);
}
_purgeUnsupportedPowerSources(acquiredProfiles);
*profileSelections = acquiredProfiles;
profilesSuccess = true;
profilesExit:
if(defaultProfiles) CFRelease(defaultProfiles);
if(!profilesSuccess) *profileSelections = NULL;
}
if( energyPrefs ) CFRelease(energyPrefs);
if( !customSettings && energyDict )
{
CFRelease(energyDict);
}
if( !profileSelections && acquiredProfiles )
{
CFRelease(acquiredProfiles);
}
if( prefsSuccess && profilesSuccess) {
return kIOReturnSuccess;
} else {
return kIOReturnError;
}
}