#include <sys/cdefs.h>
#include <notify.h>
#include <CoreFoundation/CoreFoundation.h>
#include "IOSystemConfiguration.h"
#include "IOPSKeys.h"
#include "IOPowerSources.h"
#include <notify.h>
#ifndef kIOPSDynamicStorePathKey
#define kIOPSDynamicStorePathKey kIOPSDynamicStorePath
#endif
#ifndef kIOPSDynamicStoreLowBattPathKey
#define kIOPSDynamicStoreLowBattPathKey "/IOKit/LowBatteryWarning"
#endif
#ifndef kIOPSDynamicStorePowerAdapterKey
#define kIOPSDynamicStorePowerAdapterKey "/IOKit/PowerAdapter"
#endif
IOPSLowBatteryWarningLevel IOPSGetBatteryWarningLevel(void)
{
SCDynamicStoreRef store = NULL;
CFStringRef key = NULL;
CFNumberRef scWarnValue = NULL;
int return_level = kIOPSLowBatteryWarningNone;
store = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("IOKit Power Source Copy"), NULL, NULL);
if (!store)
goto SAD_EXIT;
key = SCDynamicStoreKeyCreate(
kCFAllocatorDefault,
CFSTR("%@%@"),
kSCDynamicStoreDomainState,
CFSTR(kIOPSDynamicStoreLowBattPathKey));
if (!key)
goto SAD_EXIT;
scWarnValue = isA_CFNumber(SCDynamicStoreCopyValue(store, key));
if (scWarnValue) {
CFNumberGetValue(scWarnValue, kCFNumberIntType, &return_level);
CFRelease(scWarnValue);
scWarnValue = NULL;
}
SAD_EXIT:
if (store) CFRelease(store);
if (key) CFRelease(key);
return return_level;
}
CFDictionaryRef IOPSCopyExternalPowerAdapterDetails(void)
{
SCDynamicStoreRef store = NULL;
CFStringRef key = NULL;
CFDictionaryRef ret_dict = NULL;
store = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("IOKit Power Source Copy"), NULL, NULL);
if (!store)
goto SAD_EXIT;
key = SCDynamicStoreKeyCreate(
kCFAllocatorDefault,
CFSTR("%@%@"),
kSCDynamicStoreDomainState,
CFSTR(kIOPSDynamicStorePowerAdapterKey));
if (!key)
goto SAD_EXIT;
ret_dict = isA_CFDictionary(SCDynamicStoreCopyValue(store, key));
SAD_EXIT:
if (store) CFRelease(store);
if (key) CFRelease(key);
return ret_dict;
}
CFTypeRef IOPSCopyPowerSourcesInfo(void) {
SCDynamicStoreRef store = NULL;
CFStringRef ps_match = NULL;
CFMutableArrayRef ps_arr = NULL;
CFDictionaryRef power_sources = NULL;
store = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("IOKit Power Source Copy"), NULL, NULL);
if(!store) {
goto exit;
}
ps_match = SCDynamicStoreKeyCreate(kCFAllocatorDefault, CFSTR("%@%@/%@"),
kSCDynamicStoreDomainState, CFSTR(kIOPSDynamicStorePathKey), kSCCompAnyRegex);
if(!ps_match) {
goto exit;
}
ps_arr = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if(!ps_arr) {
goto exit;
}
CFArrayAppendValue(ps_arr, ps_match);
power_sources = SCDynamicStoreCopyMultiple(store, NULL, ps_arr);
exit:
if (ps_match)
CFRelease(ps_match);
if (ps_arr)
CFRelease(ps_arr);
if (store)
CFRelease(store);
if(!power_sources) {
power_sources = CFDictionaryCreate( kCFAllocatorDefault,
NULL, NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
return (CFTypeRef)power_sources;
}
CFArrayRef IOPSCopyPowerSourcesList(CFTypeRef blob) {
int count;
void **keys;
CFArrayRef arr;
bool failure = false;
if( !blob
|| (CFGetTypeID(blob) != CFDictionaryGetTypeID()) )
{
failure = true;
goto exit;
}
count = CFDictionaryGetCount((CFDictionaryRef)blob);
keys = (void **)malloc(count * sizeof(void *));
if(!keys) {
failure = true;
goto exit;
}
CFDictionaryGetKeysAndValues((CFDictionaryRef)blob, (const void **)keys, NULL);
arr = CFArrayCreate(kCFAllocatorDefault, (const void **)keys, count, &kCFTypeArrayCallBacks);
free(keys);
exit:
if(failure) {
arr = CFArrayCreate( 0, NULL, 0, &kCFTypeArrayCallBacks);
}
return arr;
}
CFDictionaryRef IOPSGetPowerSourceDescription(CFTypeRef blob, CFTypeRef ps) {
if( !(blob && (CFGetTypeID(blob)==CFDictionaryGetTypeID())) )
return NULL;
if( !(ps && (CFGetTypeID(ps)==CFStringGetTypeID())) )
return NULL;
return CFDictionaryGetValue(blob, ps);
}
typedef struct {
IOPowerSourceCallbackType callback;
void *context;
} user_callback_context;
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);
}
CFRunLoopSourceRef IOPSNotificationCreateRunLoopSource(IOPowerSourceCallbackType callback, void *context) {
SCDynamicStoreRef store = NULL;
CFStringRef ps_match = NULL;
CFMutableArrayRef ps_arr = 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 Power Source Copy"), ioCallout, (void *)&scContext);
if(!store) return NULL;
ps_match = SCDynamicStoreKeyCreate(
kCFAllocatorDefault,
CFSTR("%@%@/%@"),
kSCDynamicStoreDomainState,
CFSTR(kIOPSDynamicStorePath),
kSCCompAnyRegex);
if(!ps_match) return NULL;
ps_arr = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if(!ps_arr) return NULL;
CFArrayAppendValue(ps_arr, ps_match);
CFRelease(ps_match);
SCDynamicStoreSetNotificationKeys(store, NULL, ps_arr);
CFRelease(ps_arr);
SCDrls = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0);
CFRelease(store);
return SCDrls;
}