#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include "IOPSKeys.h"
#include "IOPowerSources.h"
#ifndef kIOPSDynamicStorePathKey
#define kIOPSDynamicStorePathKey kIOPSDynamicStorePath
#endif
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) return NULL;
ps_match = SCDynamicStoreKeyCreate(kCFAllocatorDefault, CFSTR("%@%@/%@"),
kSCDynamicStoreDomainState, CFSTR(kIOPSDynamicStorePathKey), 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);
power_sources = SCDynamicStoreCopyMultiple(store, NULL, ps_arr);
CFRelease(ps_arr);
CFRelease(store);
return (CFTypeRef)power_sources;
}
CFArrayRef IOPSCopyPowerSourcesList(CFTypeRef blob) {
int count;
void **keys;
void **values;
CFArrayRef arr;
if( !(blob && (CFGetTypeID(blob)==CFDictionaryGetTypeID())) )
return NULL;
count = CFDictionaryGetCount((CFDictionaryRef)blob);
keys = (void **)malloc(count * sizeof(void *));
values = (void **)malloc(count * sizeof(void *));
if(!(keys && values))
return NULL;
CFDictionaryGetKeysAndValues((CFDictionaryRef)blob, keys, values);
arr = CFArrayCreate(kCFAllocatorDefault, keys, count, &kCFTypeArrayCallBacks);
free(keys);
free(values);
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;
typedef struct {
SCDynamicStoreRef store;
CFRunLoopSourceRef SCDSrls;
user_callback_context *user_callback;
} my_cfrls_context;
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 IOPSNotificationCreateRunLoopSource(IOPowerSourceCallbackType callback, void *context) {
SCDynamicStoreRef store = NULL;
CFStringRef ps_match = NULL;
CFMutableArrayRef ps_arr = 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;
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);
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;
}