#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;
} 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, CFRunLoopRef rl, CFStringRef mode)
{
my_cfrls_context *c = (my_cfrls_context *)info;
printf("rlsRelease called\n"); fflush(stdout);
return;
}
static void
rlsRetain(void *info, CFRunLoopRef rl, CFStringRef mode)
{
my_cfrls_context *c = (my_cfrls_context *)info;
printf("rlsRelease called\n"); fflush(stdout);
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 = NULL;
SCDynamicStoreContext *scdsctxt = NULL;
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;
scdsctxt = (SCDynamicStoreContext *)malloc(sizeof(SCDynamicStoreContext));
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;
rlsContext = (CFRunLoopSourceContext *)malloc(sizeof(CFRunLoopSourceContext));
bzero(rlsContext, sizeof(CFRunLoopSourceContext));
rlsContext->version = 0;
rlsContext->info = (void *)runloop_state;
rlsContext->schedule = rlsSchedule;
rlsContext->cancel = rlsCancel;
ourSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, rlsContext);
return ourSource;
}