#include <syslog.h>
#include <sys/syslog.h>
#include "PMSettings.h"
#include "PrivateLib.h"
enum {
kIOPMUnabridgedSettings = false,
kIOPMRemoveUnsupportedSettings = true
};
static CFDictionaryRef energySettings = NULL;
static CFStringRef currentPowerSource = NULL;
static unsigned long g_overrides = 0;
static unsigned long gLastOverrideState = 0;
#if TARGET_OS_EMBEDDED
static long gSleepSetting = -1;
#endif
static io_connect_t gPowerManager;
static unsigned long deferredPSChangeNotify = 0;
static unsigned long _pmcfgd_impendingSleep = 0;
static CFDictionaryRef _copyPMSettings(
bool removeUnsupported);
static IOReturn activate_profiles(
CFDictionaryRef d,
CFStringRef s,
bool removeUnsupported);
__private_extern__ void
overrideSetting
(
int bit,
int val
)
{
if(val) {
g_overrides |= bit;
} else {
g_overrides &= ~bit;
}
}
__private_extern__ void
activateSettingOverrides(void)
{
if (!energySettings)
return;
if (gLastOverrideState != g_overrides)
{
#if TARGET_OS_EMBEDDED
if ((kPMPreventIdleSleep == (gLastOverrideState ^ g_overrides))
&& (-1 != gSleepSetting)) do
{
static io_connect_t gIOPMConnection = MACH_PORT_NULL;
IOReturn kr;
if (!gIOPMConnection) gIOPMConnection = IOPMFindPowerManagement(0);
if (!gIOPMConnection) break;
kr = IOPMSetAggressiveness(gIOPMConnection, kPMMinutesToSleep,
(kPMPreventIdleSleep & g_overrides) ? 0 : gSleepSetting);
if (kIOReturnSuccess != kr)
{
gIOPMConnection = MACH_PORT_NULL;
break;
}
gLastOverrideState = g_overrides;
return;
}
while (false);
#endif
gLastOverrideState = g_overrides;
activate_profiles( energySettings,
currentPowerSource,
kIOPMRemoveUnsupportedSettings);
}
}
__private_extern__ void
PMSettingsSleepWakeNotification(natural_t messageType)
{
switch (messageType) {
case kIOMessageSystemWillSleep:
_pmcfgd_impendingSleep = 1;
break;
case kIOMessageSystemHasPoweredOn:
_pmcfgd_impendingSleep = 0;
if(deferredPSChangeNotify)
{
deferredPSChangeNotify = 0;
_pmcfgd_impendingSleep = 0;
if(currentPowerSource && CFEqual(currentPowerSource, CFSTR(kIOPMACPowerKey)))
{
IOPMSetAggressiveness(gPowerManager, kPMPowerSource, kIOPMExternalPower);
} else {
IOPMSetAggressiveness(gPowerManager, kPMPowerSource, kIOPMInternalPower);
}
}
break;
}
return;
}
__private_extern__ CFDictionaryRef
PMSettings_CopyActivePMSettings(void)
{
CFDictionaryRef copy_all_settings;
CFDictionaryRef energySettings;
CFDictionaryRef return_val;
copy_all_settings = _copyPMSettings(kIOPMRemoveUnsupportedSettings);
if(!copy_all_settings) return NULL;
energySettings = isA_CFDictionary(CFDictionaryGetValue(copy_all_settings,currentPowerSource));
if(energySettings)
return_val = CFDictionaryCreateCopy(kCFAllocatorDefault, energySettings);
else
return_val = NULL;
CFRelease(copy_all_settings);
return return_val;
}
static CFDictionaryRef
_copyPMSettings(bool removeUnsupported)
{
if(removeUnsupported) {
return IOPMCopyActivePMPreferences();
} else {
return IOPMCopyUnabridgedActivePMPreferences();
}
}
static IOReturn
activate_profiles(CFDictionaryRef d, CFStringRef s, bool removeUnsupported)
{
CFDictionaryRef energy_settings;
CFMutableDictionaryRef profiles_activated;
CFMutableDictionaryRef tmp;
IOReturn ret;
CFNumberRef n1, n0;
int one = 1;
int zero = 0;
if(NULL == d) return kIOReturnBadArgument;
if(NULL == s) s = CFSTR(kIOPMACPowerKey);
energy_settings = (CFDictionaryRef)isA_CFDictionary(CFDictionaryGetValue(d, s));
if(!energy_settings) return kIOReturnError;
#if TARGET_OS_EMBEDDED
CFNumberRef sleepSetting;
sleepSetting = (CFNumberRef)isA_CFNumber(CFDictionaryGetValue(energy_settings, CFSTR(kIOPMSystemSleepKey)));
if (sleepSetting)
CFNumberGetValue(sleepSetting, kCFNumberLongType, &gSleepSetting);
#endif
if(g_overrides)
{
profiles_activated = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
CFDictionaryGetCount(energy_settings), energy_settings);
if(!profiles_activated) return kIOReturnError;
n1 = CFNumberCreate(0, kCFNumberIntType, &one);
n0 = CFNumberCreate(0, kCFNumberIntType, &zero);
if(g_overrides & kPMForceLowSpeedProfile)
{
if(n1) CFDictionarySetValue(profiles_activated, CFSTR(kIOPMReduceSpeedKey), n1);
}
if(g_overrides & kPMForceHighSpeed)
{
if(n0) CFDictionarySetValue(profiles_activated, CFSTR(kIOPMReduceSpeedKey), n0);
if(n0) CFDictionarySetValue(profiles_activated, CFSTR(kIOPMDynamicPowerStepKey), n0);
}
if(g_overrides & kPMPreventIdleSleep)
{
if(n0) CFDictionarySetValue(profiles_activated, CFSTR(kIOPMSystemSleepKey), n0);
}
if(g_overrides & kPMPreventDisplaySleep)
{
if(n0) CFDictionarySetValue(profiles_activated, CFSTR(kIOPMDisplaySleepKey), n0);
}
CFRelease(n0);
CFRelease(n1);
tmp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(tmp, s, profiles_activated);
ret = IOPMActivatePMPreference(tmp, s, removeUnsupported);
CFRelease(profiles_activated);
CFRelease(tmp);
} else {
ret = IOPMActivatePMPreference(d, s, removeUnsupported);
}
return ret;
}
__private_extern__ void
PMSettings_prime(void)
{
CFTypeRef ps_blob;
gPowerManager = IOPMFindPowerManagement(MACH_PORT_NULL);
if (gPowerManager == 0) return;
IOPMActivateSystemPowerSettings();
ps_blob = IOPSCopyPowerSourcesInfo();
if(ps_blob)
{
currentPowerSource = IOPSGetProvidingPowerSourceType(ps_blob);
CFRelease(ps_blob);
} else currentPowerSource = CFSTR(kIOPMACPowerKey);
energySettings = _copyPMSettings(kIOPMUnabridgedSettings);
if(energySettings) {
activate_profiles( energySettings,
currentPowerSource,
kIOPMUnabridgedSettings);
}
if(CFEqual(currentPowerSource, CFSTR(kIOPMACPowerKey)))
IOPMSetAggressiveness(gPowerManager, kPMPowerSource, kIOPMExternalPower);
else IOPMSetAggressiveness(gPowerManager, kPMPowerSource, kIOPMInternalPower);
}
__private_extern__ void
PMSettingsSupportedPrefsListHasChanged(void)
{
PMSettingsPrefsHaveChanged();
}
__private_extern__ void
PMSettingsPrefsHaveChanged(void)
{
IOPMActivateSystemPowerSettings();
if(energySettings) CFRelease(energySettings);
energySettings = isA_CFDictionary(_copyPMSettings(
kIOPMRemoveUnsupportedSettings));
if(energySettings) {
activate_profiles(energySettings,
currentPowerSource,
kIOPMRemoveUnsupportedSettings);
}
return;
}
__private_extern__ void PMSettingsPSChange(CFTypeRef ps_blob)
{
CFStringRef newPowerSource;
newPowerSource = IOPSGetProvidingPowerSourceType(ps_blob);
if(!CFEqual(currentPowerSource, newPowerSource))
{
currentPowerSource = newPowerSource;
if(!_pmcfgd_impendingSleep)
{
if(CFEqual(CFSTR(kIOPMACPowerKey), currentPowerSource))
{
IOPMSetAggressiveness(gPowerManager, kPMPowerSource, kIOPMExternalPower);
} else {
IOPMSetAggressiveness(gPowerManager, kPMPowerSource, kIOPMInternalPower);
}
} else {
deferredPSChangeNotify = 1;
}
if(energySettings) {
activate_profiles( energySettings,
currentPowerSource,
kIOPMRemoveUnsupportedSettings);
}
}
}
__private_extern__ void
PMSettingsBatteriesHaveChanged(CFArrayRef battery_info)
{
int flags;
int changed_flags;
int settings_changed = 0;
static int old_flags = 0;
io_iterator_t it;
static io_registry_entry_t root_domain = 0;
if(!root_domain)
{
IOServiceGetMatchingServices(0, IOServiceNameMatching("IOPMrootDomain"), &it);
root_domain = IOIteratorNext(it);
IOObjectRelease(it);
}
CFNumberGetValue(CFDictionaryGetValue(
CFArrayGetValueAtIndex((CFArrayRef)battery_info,0),
CFSTR("Flags")), kCFNumberSInt32Type,&flags);
changed_flags = flags ^ old_flags;
old_flags = flags;
if(changed_flags & kIOPMForceLowSpeed)
{
settings_changed = 1;
if(flags & kIOPMForceLowSpeed)
g_overrides |= kPMForceLowSpeedProfile;
else g_overrides &= ~kPMForceLowSpeedProfile;
}
if(settings_changed)
{
if(energySettings) {
activate_profiles( energySettings,
currentPowerSource,
kIOPMRemoveUnsupportedSettings);
}
}
}
__private_extern__ IOReturn
_activateForcedSettings(CFDictionaryRef forceSettings)
{
energySettings = CFDictionaryCreateCopy(0, forceSettings);
return activate_profiles( energySettings,
currentPowerSource,
kIOPMRemoveUnsupportedSettings);
}