blob: 19e4c0b9cda75965feb3b5ac5e9908a903de4ed4 [file] [log] [blame] [raw]
/*
htop - darwin/Battery.c
(C) 2015 David C. Hunt
(C) 2015 Hisham H. Muhammad
Copyright 2015-2022 Rivoreo
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "BatteryMeter.h"
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFString.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
void Battery_getData(double* level, ACPresence* isOnAC) {
*level = -1;
*isOnAC = AC_ERROR;
CFTypeRef power_sources_info = IOPSCopyPowerSourcesInfo();
if(!power_sources_info) return;
CFArrayRef list = IOPSCopyPowerSourcesList(power_sources_info);
if(!list) {
CFRelease(power_sources_info);
return;
}
double total_capacity = 0;
double total_max_capacity = 0;
/* Iterate all batteries */
int len = CFArrayGetCount(list);
for(int i = 0; i < len; i++) {
CFDictionaryRef power_source =
IOPSGetPowerSourceDescription(power_sources_info, CFArrayGetValueAtIndex(list, i));
if(!power_source) continue;
CFStringRef type = CFDictionaryGetValue(power_source, CFSTR(kIOPSTransportTypeKey));
if(!type) continue;
if(CFStringCompare(type, CFSTR(kIOPSInternalType), 0) != kCFCompareEqualTo) continue;
if(*isOnAC != AC_PRESENT) {
CFStringRef power_state = CFDictionaryGetValue(power_source, CFSTR(kIOPSPowerSourceStateKey));
if(power_state) {
*isOnAC =
CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo ?
AC_PRESENT : AC_ABSENT;
}
}
double capacity, max_capacity;
CFNumberRef cfn = CFDictionaryGetValue(power_source, CFSTR(kIOPSCurrentCapacityKey));
if(!cfn) continue;
CFNumberGetValue(cfn, kCFNumberDoubleType, &capacity);
cfn = CFDictionaryGetValue(power_source, CFSTR(kIOPSMaxCapacityKey));
if(!cfn) continue;
CFNumberGetValue(cfn, kCFNumberDoubleType, &max_capacity);
total_capacity += capacity;
total_max_capacity += max_capacity;
}
CFRelease(list);
CFRelease(power_sources_info);
if(total_max_capacity > 0) *level = total_capacity / total_max_capacity * 100;
}