IOPMPowerNotifications.c [plain text]
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <IOKit/IOReturn.h>
#include "IOPMLibPrivate.h"
#include <notify.h>
#define kMySCIdentity CFSTR("IOKit Power")
static CFStringRef scKeyForIOKitString(CFStringRef str)
{
CFStringRef keyForString = NULL;
if (CFEqual(str, CFSTR(kIOPMThermalLevelWarningKey)))
{
keyForString = CFSTR("ThermalWarning");
} else if (CFEqual(str, CFSTR(kIOPMCPUPowerLimitsKey))) {
keyForString = CFSTR("CPUPower");
}
if (!keyForString)
return NULL;
return SCDynamicStoreKeyCreate(kCFAllocatorDefault,
CFSTR("%@%@/%@"),
kSCDynamicStoreDomainState,
CFSTR("/IOKit/Power"),
keyForString);
}
static const char * notifyKeyForIOKitString(CFStringRef str)
{
if (CFEqual(str, CFSTR(kIOPMThermalLevelWarningKey)))
{
return kIOPMThermalWarningNotificationKey;
} else if (CFEqual(str, CFSTR(kIOPMCPUPowerLimitsKey)))
{
return kIOPMCPUPowerNotificationKey;
}
return NULL;
}
IOReturn IOPMCopyCPUPowerStatus(CFDictionaryRef *cpuPowerStatus)
{
SCDynamicStoreRef store = NULL;
CFStringRef cpu_power_key = NULL;
IOReturn ret = kIOReturnError;
if (!cpuPowerStatus) {
ret = kIOReturnBadArgument;
goto exit;
}
store = SCDynamicStoreCreate(kCFAllocatorDefault,
kMySCIdentity, NULL, NULL);
if (!store) {
goto exit;
}
cpu_power_key = scKeyForIOKitString(CFSTR(kIOPMCPUPowerLimitsKey));
if (!cpu_power_key) {
ret = kIOReturnInternalError;
goto exit;
}
*cpuPowerStatus = SCDynamicStoreCopyValue(store, cpu_power_key);
if (isA_CFDictionary(*cpuPowerStatus)) {
ret = kIOReturnSuccess;
} else {
if (NULL != *cpuPowerStatus) {
CFRelease(*cpuPowerStatus);
*cpuPowerStatus = NULL;
}
ret = kIOReturnNotFound;
}
exit:
if (cpu_power_key)
CFRelease(cpu_power_key);
if (store)
CFRelease(store);
return ret;
}
IOReturn IOPMGetThermalWarningLevel(uint32_t *thermalLevel)
{
SCDynamicStoreRef store = NULL;
CFStringRef thermal_key = NULL;
CFNumberRef warning_level_num = NULL;
IOReturn ret = kIOReturnError;
if (!thermalLevel) {
ret = kIOReturnBadArgument;
goto exit;
}
store = SCDynamicStoreCreate(kCFAllocatorDefault,
kMySCIdentity, NULL, NULL);
if (!store) {
goto exit;
}
thermal_key = scKeyForIOKitString(CFSTR(kIOPMThermalLevelWarningKey));
if (!thermal_key) {
ret = kIOReturnInternalError;
goto exit;
}
warning_level_num = isA_CFNumber(SCDynamicStoreCopyValue(store, thermal_key));
if (!warning_level_num) {
ret = kIOReturnNotFound;
goto exit;
}
CFNumberGetValue(warning_level_num, kCFNumberIntType, thermalLevel);
ret = kIOReturnSuccess;
exit:
if (warning_level_num)
CFRelease(warning_level_num);
if (thermal_key)
CFRelease(thermal_key);
if (store)
CFRelease(store);
return ret;
}
IOReturn IOPMSystemPowerEventOccurred(
CFStringRef typeString,
CFTypeRef eventValue)
{
IOReturn ret = kIOReturnError;
SCDynamicStoreRef store = NULL;
CFStringRef writeToKey = NULL;
CFDictionaryRef cpu_data = NULL;
CFMutableDictionaryRef adjusted_cpu_data = NULL;
const char *notify3Key = NULL;
if( !typeString
|| !eventValue)
{
ret = kIOReturnBadArgument;
goto exit;
}
store = SCDynamicStoreCreate(kCFAllocatorDefault,
kMySCIdentity, NULL, NULL);
if(!store) {
goto exit;
}
writeToKey = scKeyForIOKitString(typeString);
if(!SCDynamicStoreSetValue(store, writeToKey, eventValue))
{
if(kSCStatusAccessError == SCError())
ret = kIOReturnNotPrivileged;
else
ret = kIOReturnInternalError;
goto exit;
}
notify3Key = notifyKeyForIOKitString(typeString);
ret = kIOReturnSuccess;
exit:
if (store)
CFRelease(store);
if (writeToKey)
CFRelease(writeToKey);
if (cpu_data)
CFRelease(cpu_data);
if (adjusted_cpu_data)
CFRelease(adjusted_cpu_data);
if (notify3Key)
notify_post(notify3Key);
return ret;
}