#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCPreferencesPrivate.h>
#include <SystemConfiguration/SCDynamicStorePrivate.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPowerSourcesPrivate.h>
#include "IOPMLib.h"
#include "IOPMLibPrivate.h"
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/network/IONetworkLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#define kIOPMPrefsPath CFSTR("com.apple.PowerManagement.xml")
#define kIOPMAppName CFSTR("PowerManagement configd")
#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 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 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 kIOPMNumPMFeatures 11
static char *energy_features_array[kIOPMNumPMFeatures] = {
kIOPMDisplaySleepKey,
kIOPMDiskSleepKey,
kIOPMSystemSleepKey,
kIOPMWakeOnRingKey,
kIOPMRestartOnPowerLossKey,
kIOPMWakeOnLANKey,
kIOPMReduceSpeedKey,
kIOPMDynamicPowerStepKey,
kIOPMSleepOnPowerButtonKey,
kIOPMWakeOnClamshellKey,
kIOPMWakeOnACChangeKey
};
static const unsigned int battery_defaults_array[] = {
kBatteryMinutesToDim,
kBatteryMinutesToSpin,
kBatteryMinutesToSleep,
kBatteryWakeOnRing,
kBatteryAutomaticRestart,
kBatteryWakeOnLAN,
kBatteryReduceProcessorSpeed,
kBatteryDynamicPowerStep,
kBatterySleepOnPowerButton,
kBatteryWakeOnClamshell,
kBatteryWakeOnACChange
};
static const unsigned int ac_defaults_array[] = {
kACMinutesToDim,
kACMinutesToSpin,
kACMinutesToSleep,
kACWakeOnRing,
kACAutomaticRestart,
kACWakeOnLAN,
kACReduceProcessorSpeed,
kACDynamicPowerStep,
kACSleepOnPowerButton,
kACWakeOnClamshell,
kACWakeOnACChange
};
static const unsigned int ups_defaults_array[] = {
kUPSMinutesToDim,
kUPSMinutesToSpin,
kUPSMinutesToSleep,
kUPSWakeOnRing,
kUPSAutomaticRestart,
kUPSWakeOnLAN,
kUPSReduceProcessorSpeed,
kUPSDynamicPowerStep,
kUPSSleepOnPowerButton,
kUPSWakeOnClamshell,
kUPSWakeOnACChange
};
#define kCheetahDimKey CFSTR("MinutesUntilDisplaySleeps")
#define kCheetahDiskKey CFSTR("MinutesUntilHardDiskSleeps")
#define kCheetahSleepKey CFSTR("MinutesUntilSystemSleeps")
#define kCheetahRestartOnPowerLossKey CFSTR("RestartOnPowerLoss")
#define kCheetahWakeForNetworkAccessKey CFSTR("WakeForNetworkAdministrativeAccess")
#define kCheetahWakeOnRingKey CFSTR("WakeOnRing")
#define kApplePMUUserClientMagicCookie 0x0101BEEF
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;
} IOPMAggressivenessFactors;
static CFArrayRef _copySystemProvidedPreferences()
{
io_registry_entry_t registry_entry;
io_iterator_t tmp;
CFTypeRef ret_type;
IOServiceGetMatchingServices(NULL, IOServiceNameMatching("IOPMrootDomain"), &tmp);
registry_entry = IOIteratorNext(tmp);
IOObjectRelease(tmp);
ret_type = IORegistryEntryCreateCFProperty(registry_entry, CFSTR("SystemPowerProfiles"),
kCFAllocatorDefault, 0);
if(!isA_CFArray(ret_type)) ret_type = 0;
IOObjectRelease(registry_entry);
return (CFArrayRef)ret_type;
}
static void _mergeUnspecifiedSettingsInto(
CFMutableDictionaryRef mergee,
CFDictionaryRef merger)
{
int i;
int count;
CFStringRef *keys;
CFTypeRef *vals;
CFTypeRef safe_val;
CFNumberRef n1, n0;
if(!isA_CFDictionary(mergee) || !isA_CFDictionary(merger)) return;
i=1;
n1 = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
i=0;
n0 = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
count = CFDictionaryGetCount(merger);
keys = (CFStringRef *)malloc(sizeof(CFStringRef)*count);
vals = (CFTypeRef *)malloc(sizeof(CFTypeRef)*count);
if(!keys || !vals) return;
CFDictionaryGetKeysAndValues(merger, (void **)keys, (void **)vals);
for(i=0; i<count; i++)
{
if(isA_CFBoolean(vals[i])) {
safe_val = (kCFBooleanTrue == vals[i] ? n1:n0);
} else {
safe_val = vals[i];
}
CFDictionaryAddValue(mergee, keys[i], safe_val);
}
free(keys);
free(vals);
}
static int getDefaultEnergySettings(CFMutableDictionaryRef sys)
{
CFMutableDictionaryRef batt = NULL;
CFMutableDictionaryRef ac = NULL;
CFMutableDictionaryRef ups = NULL;
CFArrayRef platform_defaults = NULL;
int i;
CFNumberRef val;
CFStringRef key;
if((batt=(CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMBatteryPowerKey))))
{
CFRetain(batt); } else {
batt = CFDictionaryCreateMutable(kCFAllocatorDefault,
0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
};
if((ac=(CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMACPowerKey))))
{
CFRetain(ac);
} else {
ac = CFDictionaryCreateMutable(kCFAllocatorDefault,
0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
};
if((ups=(CFMutableDictionaryRef)CFDictionaryGetValue(sys, CFSTR(kIOPMUPSPowerKey))))
{
CFRetain(ups); } else {
ups = CFDictionaryCreateMutable(kCFAllocatorDefault,
0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
};
platform_defaults = _copySystemProvidedPreferences();
if(platform_defaults && (1 == CFArrayGetCount(platform_defaults)) )
{
CFDictionaryRef profile = CFArrayGetValueAtIndex(platform_defaults, 0);
CFDictionaryRef sys_default_batt;
CFDictionaryRef sys_default_ac;
CFDictionaryRef sys_default_ups;
sys_default_batt = CFDictionaryGetValue(profile, CFSTR(kIOPMBatteryPowerKey));
_mergeUnspecifiedSettingsInto(batt, sys_default_batt);
sys_default_ac = CFDictionaryGetValue(profile, CFSTR(kIOPMBatteryPowerKey));
_mergeUnspecifiedSettingsInto(ac, sys_default_ac);
sys_default_ups = CFDictionaryGetValue(profile, CFSTR(kIOPMBatteryPowerKey));
_mergeUnspecifiedSettingsInto(ups, sys_default_ups);
CFRelease(platform_defaults);
} else {
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);
}
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);
}
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);
}
}
CFDictionarySetValue(sys, CFSTR(kIOPMBatteryPowerKey), batt);
CFDictionarySetValue(sys, CFSTR(kIOPMACPowerKey), ac);
CFDictionarySetValue(sys, CFSTR(kIOPMUPSPowerKey), ups);
CFRelease(batt);
CFRelease(ac);
CFRelease(ups);
return 0;
}
static io_registry_entry_t getCudaPMURef(void)
{
io_iterator_t tmp = NULL;
io_registry_entry_t cudaPMU = NULL;
mach_port_t masterPort;
IOMasterPort(bootstrap_port,&masterPort);
IOServiceGetMatchingServices(masterPort, IOServiceNameMatching("ApplePMU"), &tmp);
if(tmp) {
cudaPMU = IOIteratorNext(tmp);
IOObjectRelease(tmp);
}
if(!cudaPMU) {
IOServiceGetMatchingServices(masterPort, IOServiceNameMatching("AppleCuda"), &tmp);
if(tmp) {
cudaPMU = IOIteratorNext(tmp);
IOObjectRelease(tmp);
}
}
return cudaPMU;
}
static io_registry_entry_t getPMRootDomainRef(void)
{
io_registry_entry_t registry_entry;
io_iterator_t tmp;
IOServiceGetMatchingServices(NULL, IOServiceNameMatching("IOPMrootDomain"), &tmp);
registry_entry = IOIteratorNext(tmp);
IOObjectRelease(tmp);
return registry_entry;
}
static int sendEnergySettingsToKernel(IOPMAggressivenessFactors *p)
{
io_registry_entry_t cudaPMU = NULL;
io_registry_entry_t PMRootDomain = NULL;
io_connect_t PM_connection = NULL;
io_connect_t connection;
kern_return_t kr;
IOReturn err;
IOReturn ret;
CFDataRef on;
CFNumberRef number1;
CFNumberRef number0;
int type;
UInt32 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;
type = kPMMinutesToDim;
err = IOPMSetAggressiveness(PM_connection, type, p->fMinutesToDim);
type = kPMMinutesToSpinDown;
err = IOPMSetAggressiveness(PM_connection, type, p->fMinutesToSpin);
type = kPMMinutesToSleep;
err = IOPMSetAggressiveness(PM_connection, type, p->fMinutesToSleep);
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnLANKey), NULL))
{
type = kPMEthernetWakeOnLANSettings;
err = IOPMSetAggressiveness(PM_connection, type, p->fWakeOnLAN);
}
IOServiceClose(PM_connection);
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnRingKey), NULL))
{
cudaPMU = getCudaPMURef();
if(cudaPMU)
{
ret = IOServiceOpen((io_service_t)cudaPMU, mach_task_self(), kApplePMUUserClientMagicCookie, &connection);
if(p->fWakeOnRing) i = 0xFFFFFFFF;
else i = 0x0;
on = CFDataCreate(kCFAllocatorDefault, (void *)&i, 4);
ret = IOConnectSetCFProperty(connection, CFSTR("WakeOnRing"), on);
CFRelease(on);
IOServiceClose(connection);
IOObjectRelease(cudaPMU);
} else {
ret = IORegistryEntrySetCFProperty(PMRootDomain, CFSTR("WakeOnRing"),
(p->fWakeOnRing?number1:number0));
}
}
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMRestartOnPowerLossKey), NULL))
{
cudaPMU = getCudaPMURef();
if(cudaPMU)
{
ret = IOServiceOpen((io_service_t)cudaPMU, mach_task_self(), kApplePMUUserClientMagicCookie, &connection);
if(p->fAutomaticRestart) i = 0xFFFFFFFF;
else i = 0x0;
on = CFDataCreate(kCFAllocatorDefault, (void *)&i, 4);
ret = IOConnectSetCFProperty(connection, CFSTR("FileServer"), on);
CFRelease(on);
IOServiceClose(connection);
IOObjectRelease(cudaPMU);
} else {
ret = IORegistryEntrySetCFProperty(PMRootDomain, CFSTR("AutoRestartOnPowerLoss"),
(p->fAutomaticRestart?number1:number0));
}
}
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnACChangeKey), NULL))
{
cudaPMU = getCudaPMURef();
if(cudaPMU)
{
ret = IOServiceOpen((io_service_t)cudaPMU, mach_task_self(), kApplePMUUserClientMagicCookie, &connection);
if(p->fWakeOnACChange) i = 0xFFFFFFFF;
else i = 0x0;
on = CFDataCreate(kCFAllocatorDefault, (void *)&i, 4);
ret = IOConnectSetCFProperty(connection, CFSTR("WakeOnACchange"), on);
CFRelease(on);
IOServiceClose(connection);
IOObjectRelease(cudaPMU);
} else {
ret = IORegistryEntrySetCFProperty(PMRootDomain, CFSTR("WakeOnACChange"),
(p->fWakeOnACChange?number1:number0));
}
}
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMSleepOnPowerButtonKey), NULL))
{
ret = IORegistryEntrySetCFProperty(PMRootDomain, CFSTR("DisablePowerButtonSleep"),
(p->fSleepOnPowerButton?kCFBooleanFalse:kCFBooleanTrue));
}
if(true == IOPMFeatureIsAvailable(CFSTR(kIOPMWakeOnClamshellKey), NULL))
{
cudaPMU = getCudaPMURef();
if(cudaPMU)
{
ret = IOServiceOpen((io_service_t)cudaPMU, mach_task_self(), kApplePMUUserClientMagicCookie, &connection);
if(p->fWakeOnClamshell) i = 0xFFFFFFFF;
else i = 0x0;
on = CFDataCreate(kCFAllocatorDefault, (void *)&i, 4);
ret = IOConnectSetCFProperty(connection, CFSTR("WakeOnLid"), on);
CFRelease(on);
IOServiceClose(connection);
IOObjectRelease(cudaPMU);
} else {
ret = IORegistryEntrySetCFProperty(PMRootDomain, CFSTR("WakeOnLid"),
(p->fWakeOnClamshell?number1:number0));
}
}
CFRelease(number0);
CFRelease(number1);
IOObjectRelease(PMRootDomain);
return 0;
}
#define GetAggressivenessValue(obj, type, ret) \
do { \
if (isA_CFNumber(obj)){ \
CFNumberGetValue(obj, type, &ret); \
break; \
} \
else if (isA_CFBoolean(obj)){ \
ret = CFBooleanGetValue(obj); \
break; \
} \
} while (false);
static int getAggressivenessFactorsFromProfile(CFDictionaryRef System, CFStringRef prof, IOPMAggressivenessFactors *agg)
{
CFDictionaryRef p = NULL;
if( !(p = CFDictionaryGetValue(System, prof)) )
{
printf("IOPMconfigd: error getting agg factors from profile!\n");
return -1;
}
if(!agg) return -1;
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMDisplaySleepKey)),
kCFNumberSInt32Type, agg->fMinutesToDim);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMDiskSleepKey)),
kCFNumberSInt32Type, agg->fMinutesToSpin);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMSystemSleepKey)),
kCFNumberSInt32Type, agg->fMinutesToSleep);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMWakeOnLANKey)),
kCFNumberSInt32Type, agg->fWakeOnLAN);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMWakeOnRingKey)),
kCFNumberSInt32Type, agg->fWakeOnRing);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMRestartOnPowerLossKey)),
kCFNumberSInt32Type, agg->fAutomaticRestart);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMSleepOnPowerButtonKey)),
kCFNumberSInt32Type, agg->fSleepOnPowerButton);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMWakeOnClamshellKey)),
kCFNumberSInt32Type, agg->fWakeOnClamshell);
GetAggressivenessValue(CFDictionaryGetValue(p, CFSTR(kIOPMWakeOnACChangeKey)),
kCFNumberSInt32Type, agg->fWakeOnACChange);
return 0;
}
extern bool IOPMFeatureIsAvailable(CFStringRef f, CFStringRef power_source)
{
CFDictionaryRef supportedFeatures = NULL;
CFArrayRef tmp_array;
io_registry_entry_t registry_entry;
io_iterator_t tmp;
mach_port_t masterPort;
bool ret = false;
IOMasterPort(bootstrap_port, &masterPort);
IOServiceGetMatchingServices(masterPort, IOServiceNameMatching("IOPMrootDomain"), &tmp);
registry_entry = IOIteratorNext(tmp);
IOObjectRelease(tmp);
supportedFeatures = IORegistryEntryCreateCFProperty(registry_entry, CFSTR("Supported Features"),
kCFAllocatorDefault, NULL);
IOObjectRelease(registry_entry);
if(CFEqual(f, CFSTR(kIOPMDisplaySleepKey))
|| CFEqual(f, CFSTR(kIOPMSystemSleepKey))
|| CFEqual(f, CFSTR(kIOPMDiskSleepKey)))
{
ret = true;
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMReduceSpeedKey)))
{
if(!supportedFeatures) return false;
if(CFDictionaryGetValue(supportedFeatures, f))
ret = true;
else ret = false;
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMDynamicPowerStepKey)))
{
if(!supportedFeatures) return false;
if(CFDictionaryGetValue(supportedFeatures, f))
ret = true;
else ret = false;
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMWakeOnLANKey)))
{
if(supportedFeatures && CFDictionaryGetValue(supportedFeatures, CFSTR("WakeOnMagicPacket"))
&& (!power_source || !CFEqual(CFSTR(kIOPMBatteryPowerKey), power_source)))
{
ret = true;
} else {
ret = false;
}
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMWakeOnRingKey)))
{
if(supportedFeatures && CFDictionaryGetValue(supportedFeatures, CFSTR("WakeOnRing")))
{
ret = true;
} else {
ret = false;
}
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMRestartOnPowerLossKey)))
{
if(supportedFeatures && CFDictionaryGetValue(supportedFeatures, CFSTR("FileServer")))
{
ret = true;
} else {
ret = false;
}
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMWakeOnACChangeKey)))
{
if(supportedFeatures && CFDictionaryGetValue(supportedFeatures, CFSTR("WakeOnACchange")))
{
ret = true;
} else {
ret = false;
}
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMSleepOnPowerButtonKey)))
{
IOReturn r = IOPMCopyBatteryInfo(NULL, &tmp_array);
if((r == kIOReturnSuccess) && tmp_array)
{
CFRelease(tmp_array);
ret = false;
} else ret = true;
goto IOPMFeatureIsAvailable_exitpoint;
}
if(CFEqual(f, CFSTR(kIOPMWakeOnClamshellKey)))
{
if(!supportedFeatures) return false;
if(CFDictionaryGetValue(supportedFeatures, CFSTR("WakeOnLid")))
ret = true;
else ret = false;
goto IOPMFeatureIsAvailable_exitpoint;
}
IOPMFeatureIsAvailable_exitpoint:
if(supportedFeatures) CFRelease(supportedFeatures);
IOObjectRelease(masterPort);
return ret;
}
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)CFDictionaryGetValue(energyPrefs, profile_keys[profile_count]);
dict_count = CFDictionaryGetCount(this_profile);
dict_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * dict_count);
dict_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * dict_count);
CFDictionaryGetKeysAndValues(this_profile, (const void **)dict_keys, (const void **)dict_vals);
while(--dict_count >= 0)
if(false == 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;
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));
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDimKey);
if(n) CFDictionarySetValue(s, CFSTR(kIOPMDisplaySleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDiskKey);
if(n) CFDictionarySetValue(s, CFSTR(kIOPMDiskSleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahSleepKey);
if(n) CFDictionarySetValue(s, CFSTR(kIOPMSystemSleepKey), n);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahRestartOnPowerLossKey);
if(b) CFDictionarySetValue(s, CFSTR(kIOPMRestartOnPowerLossKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeForNetworkAccessKey);
if(b) CFDictionarySetValue(s, CFSTR(kIOPMWakeOnLANKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeOnRingKey);
if(b) CFDictionarySetValue(s, CFSTR(kIOPMWakeOnRingKey), b);
CFDictionarySetValue(energyPrefs, CFSTR(kIOPMBatteryPowerKey), s);
s = (CFMutableDictionaryRef)CFDictionaryGetValue(energyPrefs, CFSTR(kIOPMACPowerKey));
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDimKey);
if(n) CFDictionarySetValue(s, CFSTR(kIOPMDisplaySleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahDiskKey);
if(n) CFDictionarySetValue(s, CFSTR(kIOPMDiskSleepKey), n);
n = (CFNumberRef)SCPreferencesGetValue(CheetahPrefs, kCheetahSleepKey);
if(n) CFDictionarySetValue(s, CFSTR(kIOPMSystemSleepKey), n);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahRestartOnPowerLossKey);
if(b) CFDictionarySetValue(s, CFSTR(kIOPMRestartOnPowerLossKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeForNetworkAccessKey);
if(b) CFDictionarySetValue(s, CFSTR(kIOPMWakeOnLANKey), b);
b = (CFBooleanRef)SCPreferencesGetValue(CheetahPrefs, kCheetahWakeOnRingKey);
if(b) CFDictionarySetValue(s, CFSTR(kIOPMWakeOnRingKey), b);
CFDictionarySetValue(energyPrefs, CFSTR(kIOPMACPowerKey), s);
CFRelease(CheetahPrefs);
return 1; }
extern CFMutableDictionaryRef IOPMCopyPMPreferences(void)
{
CFMutableDictionaryRef energyDict = NULL;
SCPreferencesRef energyPrefs = NULL;
CFDictionaryRef batterySettings = NULL;
CFDictionaryRef ACSettings = NULL;
CFDictionaryRef UPSSettings = NULL;
energyDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
energyPrefs = SCPreferencesCreate( kCFAllocatorDefault, kIOPMAppName, kIOPMPrefsPath );
if(energyPrefs == 0) {
if(energyDict != 0) CFRelease(energyDict);
return NULL;
}
batterySettings = isA_CFDictionary(SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMBatteryPowerKey)));
ACSettings = isA_CFDictionary(SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMACPowerKey)));
UPSSettings = isA_CFDictionary(SCPreferencesGetValue(energyPrefs, CFSTR(kIOPMUPSPowerKey)));
if( batterySettings || ACSettings || UPSSettings)
{
if(batterySettings)
CFDictionaryAddValue(energyDict, CFSTR(kIOPMBatteryPowerKey), batterySettings);
if(ACSettings)
CFDictionaryAddValue(energyDict, CFSTR(kIOPMACPowerKey), ACSettings);
if(UPSSettings)
CFDictionaryAddValue(energyDict, CFSTR(kIOPMUPSPowerKey), UPSSettings);
getDefaultEnergySettings(energyDict);
} else {
getDefaultEnergySettings(energyDict);
getCheetahPumaEnergySettings(energyDict);
}
IOPMRemoveIrrelevantProperties(energyDict);
CFRelease(energyPrefs);
return energyDict;
}
extern IOReturn IOPMActivatePMPreference(CFDictionaryRef SystemProfiles, CFStringRef profile)
{
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(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;
}
extern IOReturn IOPMSetPMPreferences(CFDictionaryRef ESPrefs)
{
SCPreferencesRef energyPrefs = NULL;
int i;
int dict_count = 0;
CFStringRef *dict_keys;
CFDictionaryRef *dict_vals;
energyPrefs = SCPreferencesCreate( kCFAllocatorDefault, kIOPMAppName, kIOPMPrefsPath );
if(!energyPrefs) return kIOReturnError;
dict_count = CFDictionaryGetCount(ESPrefs);
dict_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * dict_count);
dict_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * dict_count);
CFDictionaryGetKeysAndValues(ESPrefs, (const void **)dict_keys, (const void **)dict_vals);
if(!dict_keys || !dict_vals) return kIOReturnError;
for(i=0; i<dict_count; i++)
{
if(!SCPreferencesSetValue(energyPrefs, dict_keys[i], dict_vals[i]))
{
return kIOReturnError;
}
}
if(!SCPreferencesCommitChanges(energyPrefs))
{
if(kSCStatusAccessError == SCError()) return kIOReturnNotPrivileged;
return kIOReturnError;
}
if(!SCPreferencesApplyChanges(energyPrefs))
{
if(kSCStatusAccessError == SCError()) return kIOReturnNotPrivileged;
return kIOReturnError;
}
CFRelease(energyPrefs);
return kIOReturnSuccess;
}
typedef struct {
IOPMPrefsCallbackType callback;
void *context;
} user_callback_context;
typedef struct {
SCDynamicStoreRef store;
CFRunLoopSourceRef SCDSrls;
user_callback_context *user_callback;
} my_cfrls_context;
static void my_dynamic_store_call(SCDynamicStoreRef store, CFArrayRef keys, void *ctxt) {
user_callback_context *c = (user_callback_context *)ctxt;
IOPowerSourceCallbackType cb;
if(!c) return;
cb = c->callback;
if(!cb) return;
(*cb)(c->context);
}
static void
rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
{
my_cfrls_context *c = (my_cfrls_context *)info;
CFRunLoopAddSource(CFRunLoopGetCurrent(), c->SCDSrls, mode);
return;
}
static void
rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode)
{
my_cfrls_context *c = (my_cfrls_context *)info;
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), c->SCDSrls, mode);
return;
}
static void
rlsRelease(void *info)
{
my_cfrls_context *c = (my_cfrls_context *)info;
if(!c) return;
if(c->SCDSrls) CFRelease(c->SCDSrls);
if(c->store) CFRelease(c->store);
if(c->user_callback) free(c->user_callback);
free(c);
return;
}
CFRunLoopSourceRef IOPMPrefsNotificationCreateRunLoopSource(IOPMPrefsCallbackType callback, void *context) {
SCDynamicStoreRef store = NULL;
CFStringRef EnergyPrefsKey = NULL;
CFRunLoopSourceRef SCDrls = NULL;
CFRunLoopSourceRef ourSource = NULL;
CFRunLoopSourceContext rlsContext;
SCDynamicStoreContext scdsctxt;
user_callback_context *callback_state = NULL;
my_cfrls_context *runloop_state = NULL;
callback_state = malloc(sizeof(user_callback_context));
callback_state->context = context;
callback_state->callback = callback;
bzero(&scdsctxt, sizeof(SCDynamicStoreContext));
scdsctxt.info = callback_state;
store = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("IOKit Power Source Copy"), my_dynamic_store_call, (void *)&scdsctxt);
if(!store) return NULL;
EnergyPrefsKey = SCDynamicStoreKeyCreatePreferences(NULL, kIOPMPrefsPath, kSCPreferencesKeyApply);
if(EnergyPrefsKey)
SCDynamicStoreAddWatchedKey(store, EnergyPrefsKey, FALSE);
SCDrls = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0);
runloop_state = malloc(sizeof(my_cfrls_context));
runloop_state->store = store;
runloop_state->SCDSrls = SCDrls;
runloop_state->user_callback = callback_state;
bzero(&rlsContext, sizeof(CFRunLoopSourceContext));
rlsContext.version = 0;
rlsContext.info = (void *)runloop_state;
rlsContext.schedule = rlsSchedule;
rlsContext.cancel = rlsCancel;
rlsContext.release = rlsRelease;
ourSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &rlsContext);
return ourSource;
}