diff options
author | Nathan Scott <nathans@redhat.com> | 2020-11-17 18:12:38 +1100 |
---|---|---|
committer | Nathan Scott <nathans@redhat.com> | 2020-11-18 10:17:33 +1100 |
commit | ea9622b8c9444d92007f24fc54597f83c498f11d (patch) | |
tree | 13cb45909d2c873b7b09ec59580d6a8db4676b0b | |
parent | e3af8d0d0851dd6ce25446a7f9a99e2127795a78 (diff) |
Merge individual Battery.[ch] files into Platform.[ch]
Consistent with everything else involving platform-specific
calls from core htop code.
-rw-r--r-- | BatteryMeter.c | 4 | ||||
-rw-r--r-- | Makefile.am | 26 | ||||
-rw-r--r-- | darwin/Battery.c | 73 | ||||
-rw-r--r-- | darwin/Battery.h | 8 | ||||
-rw-r--r-- | darwin/Platform.c | 68 | ||||
-rw-r--r-- | darwin/Platform.h | 2 | ||||
-rw-r--r-- | dragonflybsd/Battery.c | 30 | ||||
-rw-r--r-- | dragonflybsd/Battery.h | 15 | ||||
-rw-r--r-- | dragonflybsd/Platform.c | 16 | ||||
-rw-r--r-- | dragonflybsd/Platform.h | 2 | ||||
-rw-r--r-- | freebsd/Battery.c | 29 | ||||
-rw-r--r-- | freebsd/Battery.h | 14 | ||||
-rw-r--r-- | freebsd/Platform.c | 16 | ||||
-rw-r--r-- | freebsd/Platform.h | 2 | ||||
-rw-r--r-- | linux/Battery.c | 366 | ||||
-rw-r--r-- | linux/Battery.h | 17 | ||||
-rw-r--r-- | linux/Platform.c | 323 | ||||
-rw-r--r-- | linux/Platform.h | 3 | ||||
-rw-r--r-- | openbsd/Battery.c | 74 | ||||
-rw-r--r-- | openbsd/Battery.h | 15 | ||||
-rw-r--r-- | openbsd/Platform.c | 59 | ||||
-rw-r--r-- | solaris/Battery.c | 8 | ||||
-rw-r--r-- | solaris/Battery.h | 8 | ||||
-rw-r--r-- | solaris/Platform.c | 5 | ||||
-rw-r--r-- | solaris/Platform.h | 2 | ||||
-rw-r--r-- | unsupported/Battery.c | 8 | ||||
-rw-r--r-- | unsupported/Battery.h | 8 | ||||
-rw-r--r-- | unsupported/Platform.c | 5 | ||||
-rw-r--r-- | unsupported/Platform.h | 2 |
29 files changed, 515 insertions, 693 deletions
diff --git a/BatteryMeter.c b/BatteryMeter.c index ac126cea..cd8439c4 100644 --- a/BatteryMeter.c +++ b/BatteryMeter.c @@ -11,7 +11,7 @@ This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). #include <math.h> -#include "Battery.h" +#include "Platform.h" #include "CRT.h" #include "Object.h" #include "XUtils.h" @@ -25,7 +25,7 @@ static void BatteryMeter_updateValues(Meter* this, char* buffer, int len) { ACPresence isOnAC; double percent; - Battery_getData(&percent, &isOnAC); + Platform_getBattery(&percent, &isOnAC); if (isnan(percent)) { this->values[0] = NAN; diff --git a/Makefile.am b/Makefile.am index 41d8c9fb..aa044e82 100644 --- a/Makefile.am +++ b/Makefile.am @@ -124,7 +124,6 @@ myhtopheaders = \ # ----- linux_platform_headers = \ - linux/Battery.h \ linux/IOPriority.h \ linux/IOPriorityPanel.h \ linux/LinuxProcess.h \ @@ -142,7 +141,6 @@ linux_platform_headers = \ if HTOP_LINUX AM_LDFLAGS += -rdynamic myhtopplatsources = \ - linux/Battery.c \ linux/IOPriorityPanel.c \ linux/LinuxProcess.c \ linux/LinuxProcessList.c \ @@ -165,7 +163,6 @@ freebsd_platform_headers = \ freebsd/Platform.h \ freebsd/FreeBSDProcessList.h \ freebsd/FreeBSDProcess.h \ - freebsd/Battery.h \ zfs/ZfsArcMeter.h \ zfs/ZfsCompressedArcMeter.h \ zfs/ZfsArcStats.h \ @@ -173,7 +170,7 @@ freebsd_platform_headers = \ if HTOP_FREEBSD myhtopplatsources = freebsd/Platform.c freebsd/FreeBSDProcessList.c \ -freebsd/FreeBSDProcess.c freebsd/Battery.c \ +freebsd/FreeBSDProcess.c \ zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c myhtopplatheaders = $(freebsd_platform_headers) @@ -185,13 +182,12 @@ endif dragonflybsd_platform_headers = \ dragonflybsd/Platform.h \ dragonflybsd/DragonFlyBSDProcessList.h \ - dragonflybsd/DragonFlyBSDProcess.h \ - dragonflybsd/Battery.h + dragonflybsd/DragonFlyBSDProcess.h if HTOP_DRAGONFLYBSD AM_LDFLAGS += -lkvm -lkinfo myhtopplatsources = dragonflybsd/Platform.c dragonflybsd/DragonFlyBSDProcessList.c \ -dragonflybsd/DragonFlyBSDProcess.c dragonflybsd/Battery.c +dragonflybsd/DragonFlyBSDProcess.c myhtopplatheaders = $(dragonflybsd_platform_headers) endif @@ -202,12 +198,11 @@ endif openbsd_platform_headers = \ openbsd/Platform.h \ openbsd/OpenBSDProcessList.h \ - openbsd/OpenBSDProcess.h \ - openbsd/Battery.h + openbsd/OpenBSDProcess.h if HTOP_OPENBSD myhtopplatsources = openbsd/Platform.c openbsd/OpenBSDProcessList.c \ -openbsd/OpenBSDProcess.c openbsd/Battery.c +openbsd/OpenBSDProcess.c myhtopplatheaders = $(openbsd_platform_headers) endif @@ -219,7 +214,6 @@ darwin_platform_headers = \ darwin/Platform.h \ darwin/DarwinProcess.h \ darwin/DarwinProcessList.h \ - darwin/Battery.h \ zfs/ZfsArcMeter.h \ zfs/ZfsCompressedArcMeter.h \ zfs/ZfsArcStats.h \ @@ -228,7 +222,7 @@ darwin_platform_headers = \ if HTOP_DARWIN AM_LDFLAGS += -framework IOKit -framework CoreFoundation myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \ -darwin/DarwinProcessList.c darwin/Battery.c \ +darwin/DarwinProcessList.c \ zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c myhtopplatheaders = $(darwin_platform_headers) @@ -241,7 +235,6 @@ solaris_platform_headers = \ solaris/Platform.h \ solaris/SolarisProcess.h \ solaris/SolarisProcessList.h \ - solaris/Battery.h \ zfs/ZfsArcMeter.h \ zfs/ZfsCompressedArcMeter.h \ zfs/ZfsArcStats.h @@ -249,7 +242,6 @@ solaris_platform_headers = \ if HTOP_SOLARIS myhtopplatsources = solaris/Platform.c \ solaris/SolarisProcess.c solaris/SolarisProcessList.c \ -solaris/Battery.c \ zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c myhtopplatheaders = $(solaris_platform_headers) @@ -261,13 +253,11 @@ endif unsupported_platform_headers = \ unsupported/Platform.h \ unsupported/UnsupportedProcess.h \ - unsupported/UnsupportedProcessList.h \ - unsupported/Battery.h + unsupported/UnsupportedProcessList.h if HTOP_UNSUPPORTED myhtopplatsources = unsupported/Platform.c \ -unsupported/UnsupportedProcess.c unsupported/UnsupportedProcessList.c \ -unsupported/Battery.c +unsupported/UnsupportedProcess.c unsupported/UnsupportedProcessList.c myhtopplatheaders = $(unsupported_platform_headers) endif diff --git a/darwin/Battery.c b/darwin/Battery.c deleted file mode 100644 index c89f5b30..00000000 --- a/darwin/Battery.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "Battery.h" - -#include <math.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) { - CFTypeRef power_sources = IOPSCopyPowerSourcesInfo(); - - *level = NAN; - *isOnAC = AC_ERROR; - - if (NULL == power_sources) { - return; - } - - CFArrayRef list = IOPSCopyPowerSourcesList(power_sources); - CFDictionaryRef battery = NULL; - int len; - - if (NULL == list) { - CFRelease(power_sources); - - return; - } - - len = CFArrayGetCount(list); - - /* Get the battery */ - for (int i = 0; i < len && battery == NULL; ++i) { - CFDictionaryRef candidate = IOPSGetPowerSourceDescription(power_sources, - CFArrayGetValueAtIndex(list, i)); /* GET rule */ - CFStringRef type; - - if (NULL != candidate) { - type = (CFStringRef) CFDictionaryGetValue(candidate, - CFSTR(kIOPSTransportTypeKey)); /* GET rule */ - - if (kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { - CFRetain(candidate); - battery = candidate; - } - } - } - - if (NULL != battery) { - /* Determine the AC state */ - CFStringRef power_state = CFDictionaryGetValue(battery, CFSTR(kIOPSPowerSourceStateKey)); - - *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) - ? AC_PRESENT - : AC_ABSENT; - - /* Get the percentage remaining */ - double current; - double max; - - CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey)), - kCFNumberDoubleType, ¤t); - CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey)), - kCFNumberDoubleType, &max); - - *level = (current * 100.0) / max; - - CFRelease(battery); - } - - CFRelease(list); - CFRelease(power_sources); -} diff --git a/darwin/Battery.h b/darwin/Battery.h deleted file mode 100644 index 74a27fc5..00000000 --- a/darwin/Battery.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery - -#include "BatteryMeter.h" - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/darwin/Platform.c b/darwin/Platform.c index be71360c..bf9645b3 100644 --- a/darwin/Platform.c +++ b/darwin/Platform.c @@ -26,6 +26,10 @@ in the source distribution for its full text. #include <math.h> #include <stdlib.h> +#include <CoreFoundation/CoreFoundation.h> +#include <CoreFoundation/CFString.h> +#include <IOKit/ps/IOPowerSources.h> +#include <IOKit/ps/IOPSKeys.h> ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; @@ -341,3 +345,67 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = 0; return false; } + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + CFTypeRef power_sources = IOPSCopyPowerSourcesInfo(); + + *level = NAN; + *isOnAC = AC_ERROR; + + if (NULL == power_sources) + return; + + CFArrayRef list = IOPSCopyPowerSourcesList(power_sources); + CFDictionaryRef battery = NULL; + int len; + + if (NULL == list) { + CFRelease(power_sources); + + return; + } + + len = CFArrayGetCount(list); + + /* Get the battery */ + for (int i = 0; i < len && battery == NULL; ++i) { + CFDictionaryRef candidate = IOPSGetPowerSourceDescription(power_sources, + CFArrayGetValueAtIndex(list, i)); /* GET rule */ + CFStringRef type; + + if (NULL != candidate) { + type = (CFStringRef) CFDictionaryGetValue(candidate, + CFSTR(kIOPSTransportTypeKey)); /* GET rule */ + + if (kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { + CFRetain(candidate); + battery = candidate; + } + } + } + + if (NULL != battery) { + /* Determine the AC state */ + CFStringRef power_state = CFDictionaryGetValue(battery, CFSTR(kIOPSPowerSourceStateKey)); + + *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) + ? AC_PRESENT + : AC_ABSENT; + + /* Get the percentage remaining */ + double current; + double max; + + CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey)), + kCFNumberDoubleType, ¤t); + CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey)), + kCFNumberDoubleType, &max); + + *level = (current * 100.0) / max; + + CFRelease(battery); + } + + CFRelease(list); + CFRelease(power_sources); +} diff --git a/darwin/Platform.h b/darwin/Platform.h index f42b7209..40b7d730 100644 --- a/darwin/Platform.h +++ b/darwin/Platform.h @@ -65,4 +65,6 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, unsigned long int* bytesTransmitted, unsigned long int* packetsTransmitted); +void Platform_getBattery(double *percent, ACPresence *isOnAC); + #endif diff --git a/dragonflybsd/Battery.c b/dragonflybsd/Battery.c deleted file mode 100644 index 1a690ee3..00000000 --- a/dragonflybsd/Battery.c +++ /dev/null @@ -1,30 +0,0 @@ -/* -htop - dragonflybsd/Battery.c -(C) 2015 Hisham H. Muhammad -(C) 2017 Diederik de Groot -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Battery.h" - -#include <math.h> -#include <sys/sysctl.h> - -void Battery_getData(double* level, ACPresence* isOnAC) { - int life; - size_t life_len = sizeof(life); - if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) { - *level = NAN; - } else { - *level = life; - } - - int acline; - size_t acline_len = sizeof(acline); - if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) { - *isOnAC = AC_ERROR; - } else { - *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; - } -} diff --git a/dragonflybsd/Battery.h b/dragonflybsd/Battery.h deleted file mode 100644 index eed0f630..00000000 --- a/dragonflybsd/Battery.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery -/* -htop - dragonflybsd/Battery.h -(C) 2015 Hisham H. Muhammad -(C) 2017 Diederik de Groot -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "BatteryMeter.h" - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/dragonflybsd/Platform.c b/dragonflybsd/Platform.c index dd36bf0a..c6966c11 100644 --- a/dragonflybsd/Platform.c +++ b/dragonflybsd/Platform.c @@ -234,3 +234,19 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = 0; return false; } + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + int life; + size_t life_len = sizeof(life); + if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) + *level = NAN; + else + *level = life; + + int acline; + size_t acline_len = sizeof(acline); + if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) + *isOnAC = AC_ERROR; + else + *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; +} diff --git a/dragonflybsd/Platform.h b/dragonflybsd/Platform.h index 1da8811b..267b8f37 100644 --- a/dragonflybsd/Platform.h +++ b/dragonflybsd/Platform.h @@ -56,4 +56,6 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, unsigned long int* bytesTransmitted, unsigned long int* packetsTransmitted); +void Platform_getBattery(double* level, ACPresence* isOnAC); + #endif diff --git a/freebsd/Battery.c b/freebsd/Battery.c deleted file mode 100644 index 26b42da9..00000000 --- a/freebsd/Battery.c +++ /dev/null @@ -1,29 +0,0 @@ -/* -htop - freebsd/Battery.c -(C) 2015 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Battery.h" - -#include <math.h> -#include <sys/sysctl.h> - -void Battery_getData(double* level, ACPresence* isOnAC) { - int life; - size_t life_len = sizeof(life); - if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) { - *level = NAN; - } else { - *level = life; - } - - int acline; - size_t acline_len = sizeof(acline); - if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) { - *isOnAC = AC_ERROR; - } else { - *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; - } -} diff --git a/freebsd/Battery.h b/freebsd/Battery.h deleted file mode 100644 index 98adb6ee..00000000 --- a/freebsd/Battery.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery -/* -htop - freebsd/Battery.h -(C) 2015 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "BatteryMeter.h" - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/freebsd/Platform.c b/freebsd/Platform.c index 2fc9ccc9..8efa4e68 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -338,3 +338,19 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = packetsTransmittedSum; return true; } + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + int life; + size_t life_len = sizeof(life); + if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) + *level = NAN; + else + *level = life; + + int acline; + size_t acline_len = sizeof(acline); + if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) + *isOnAC = AC_ERROR; + else + *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; +} diff --git a/freebsd/Platform.h b/freebsd/Platform.h index 72e964aa..5e3b29fb 100644 --- a/freebsd/Platform.h +++ b/freebsd/Platform.h @@ -59,4 +59,6 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, unsigned long int* bytesTransmitted, unsigned long int* packetsTransmitted); +void Platform_getBattery(double* level, ACPresence* isOnAC); + #endif diff --git a/linux/Battery.c b/linux/Battery.c deleted file mode 100644 index ba7d153a..00000000 --- a/linux/Battery.c +++ /dev/null @@ -1,366 +0,0 @@ -/* -htop - linux/Battery.c -(C) 2004-2014 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. - -Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). -*/ - -#include "config.h" // IWYU pragma: keep - -#include "Battery.h" - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <math.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include "BatteryMeter.h" -#include "Macros.h" -#include "XUtils.h" - - -#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply" - -// ---------------------------------------- -// READ FROM /proc -// ---------------------------------------- - -// This implementation reading from from /proc/acpi is really inefficient, -// but I think this is on the way out so I did not rewrite it. -// The /sys implementation below does things the right way. - -static unsigned long int parseBatInfo(const char* fileName, const unsigned short int lineNum, const unsigned short int wordNum) { - const char batteryPath[] = PROCDIR "/acpi/battery/"; - DIR* batteryDir = opendir(batteryPath); - if (!batteryDir) - return 0; - - #define MAX_BATTERIES 64 - char* batteries[MAX_BATTERIES]; - unsigned int nBatteries = 0; - memset(batteries, 0, MAX_BATTERIES * sizeof(char*)); - - while (nBatteries < MAX_BATTERIES) { - struct dirent* dirEntry = readdir(batteryDir); - if (!dirEntry) - break; - - char* entryName = dirEntry->d_name; - if (!String_startsWith(entryName, "BAT")) - continue; - - batteries[nBatteries] = xStrdup(entryName); - nBatteries++; - } - closedir(batteryDir); - - unsigned long int total = 0; - for (unsigned int i = 0; i < nBatteries; i++) { - char infoPath[30]; - xSnprintf(infoPath, sizeof infoPath, "%s%s/%s", batteryPath, batteries[i], fileName); - - FILE* file = fopen(infoPath, "r"); - if (!file) { - break; - } - - char* line = NULL; - for (unsigned short int j = 0; j < lineNum; j++) { - free(line); - line = String_readLine(file); - if (!line) - break; - } - - fclose(file); - - if (!line) - break; - - char* foundNumStr = String_getToken(line, wordNum); - const unsigned long int foundNum = atoi(foundNumStr); - free(foundNumStr); - free(line); - - total += foundNum; - } - - for (unsigned int i = 0; i < nBatteries; i++) { - free(batteries[i]); - } - - return total; -} - -static ACPresence procAcpiCheck(void) { - ACPresence isOn = AC_ERROR; - const char* power_supplyPath = PROCDIR "/acpi/ac_adapter"; - DIR* dir = opendir(power_supplyPath); - if (!dir) { - return AC_ERROR; - } - - for (;;) { - struct dirent* dirEntry = readdir(dir); - if (!dirEntry) - break; - - const char* entryName = dirEntry->d_name; - - if (entryName[0] != 'A') - continue; - - char statePath[256]; - xSnprintf(statePath, sizeof(statePath), "%s/%s/state", power_supplyPath, entryName); - FILE* file = fopen(statePath, "r"); - if (!file) { - isOn = AC_ERROR; - continue; - } - char* line = String_readLine(file); - - fclose(file); - - if (!line) - continue; - - char* isOnline = String_getToken(line, 2); - free(line); - - if (String_eq(isOnline, "on-line")) { - isOn = AC_PRESENT; - } else { - isOn = AC_ABSENT; - } - free(isOnline); - if (isOn == AC_PRESENT) { - break; - } - } - - if (dir) { - closedir(dir); - } - - return isOn; -} - -static double Battery_getProcBatData(void) { - const unsigned long int totalFull = parseBatInfo("info", 3, 4); - if (totalFull == 0) - return NAN; - - const unsigned long int totalRemain = parseBatInfo("state", 5, 3); - if (totalRemain == 0) - return NAN; - - return totalRemain * 100.0 / (double) totalFull; -} - -static void Battery_getProcData(double* level, ACPresence* isOnAC) { - *isOnAC = procAcpiCheck(); - *level = AC_ERROR != *isOnAC ? Battery_getProcBatData() : NAN; -} - -// ---------------------------------------- -// READ FROM /sys -// ---------------------------------------- - -static inline ssize_t xread(int fd, void* buf, size_t count) { - // Read some bytes. Retry on EINTR and when we don't get as many bytes as we requested. - size_t alreadyRead = 0; - for (;;) { - ssize_t res = read(fd, buf, count); - if (res == -1) { - if (errno == EINTR) - continue; - return -1; - } - - if (res > 0) { - buf = ((char*)buf) + res; - count -= res; - alreadyRead += res; - } - - if (count == 0 || res == 0) { - return alreadyRead; - } - } -} - -static void Battery_getSysData(double* level, ACPresence* isOnAC) { - - *level = NAN; - *isOnAC = AC_ERROR; - - DIR* dir = opendir(SYS_POWERSUPPLY_DIR); - if (!dir) - return; - - unsigned long int totalFull = 0; - unsigned long int totalRemain = 0; - - for (;;) { - struct dirent* dirEntry = readdir(dir); - if (!dirEntry) - break; - - const char* entryName = dirEntry->d_name; - char filePath[256]; - - xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/type", entryName); - int fd1 = open(filePath, O_RDONLY); - if (fd1 == -1) - continue; - - char type[8]; - ssize_t typelen = xread(fd1, type, 7); - close(fd1); - if (typelen < 1) - continue; - - if (type[0] == 'B' && type[1] == 'a' && type[2] == 't') { - xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName); - int fd2 = open(filePath, O_RDONLY); - if (fd2 == -1) { - closedir(dir); - return; - } - char buffer[1024]; - ssize_t buflen = xread(fd2, buffer, 1023); - close(fd2); - if (buflen < 1) { - closedir(dir); - return; - } - buffer[buflen] = '\0'; - char* buf = buffer; - char* line = NULL; - bool full = false; - bool now = false; - int fullSize = 0; - double capacityLevel = NAN; - - #define match(str,prefix) \ - (String_startsWith(str,prefix) ? (str) + strlen(prefix) : NULL) - - while ((line = strsep(&buf, "\n")) != NULL) { - const char* ps = match(line, "POWER_SUPPLY_"); - if (!ps) { - continue; - } - const char* capacity = match(ps, "CAPACITY="); - if (capacity) { - capacityLevel = atoi(capacity) / 100.0; - } - const char* energy = match(ps, "ENERGY_"); - if (!energy) { - energy = match(ps, "CHARGE_"); - } - if (!energy) { - continue; - } - const char* value = (!full) ? match(energy, "FULL=") : NULL; - if (value) { - fullSize = atoi(value); - totalFull += fullSize; - full = true; - if (now) { - break; - } - continue; - } - value = (!now) ? match(energy, "NOW=") : NULL; - if (value) { - totalRemain += atoi(value); - now = true; - if (full) { - break; - } - continue; - } - } - - #undef match - - if (!now && full && !isnan(capacityLevel)) { - totalRemain += (capacityLevel * fullSize); - } - } else if (entryName[0] == 'A') { - if (*isOnAC != AC_ERROR) { - continue; - } - - xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/online", entryName); - int fd3 = open(filePath, O_RDONLY); - if (fd3 == -1) { - closedir(dir); - return; - } - char buffer[2] = ""; - for (;;) { - ssize_t res = read(fd3, buffer, 1); - if (res == -1 && errno == EINTR) { - continue; - } - break; - } - close(fd3); - if (buffer[0] == '0') { - *isOnAC = AC_ABSENT; - } else if (buffer[0] == '1') { - *isOnAC = AC_PRESENT; - } - } - } - closedir(dir); - - *level = totalFull > 0 ? ((double) totalRemain * 100.0) / (double) totalFull : NAN; -} - -static enum { BAT_PROC, BAT_SYS, BAT_ERR } Battery_method = BAT_PROC; - -static time_t Battery_cacheTime = 0; -static double Battery_cacheLevel = NAN; -static ACPresence Battery_cacheIsOnAC = 0; - -void Battery_getData(double* level, ACPresence* isOnAC) { - time_t now = time(NULL); - // update battery reading is slow. Update it each 10 seconds only. - if (now < Battery_cacheTime + 10) { - *level = Battery_cacheLevel; - *isOnAC = Battery_cacheIsOnAC; - return; - } - - if (Battery_method == BAT_PROC) { - Battery_getProcData(level, isOnAC); - if (isnan(*level)) { - Battery_method = BAT_SYS; - } - } - if (Battery_method == BAT_SYS) { - Battery_getSysData(level, isOnAC); - if (isnan(*level)) { - Battery_method = BAT_ERR; - } - } - if (Battery_method == BAT_ERR) { - *level = NAN; - *isOnAC = AC_ERROR; - } else { - *level = CLAMP(*level, 0.0, 100.0); - } - Battery_cacheLevel = *level; - Battery_cacheIsOnAC = *isOnAC; - Battery_cacheTime = now; -} diff --git a/linux/Battery.h b/linux/Battery.h deleted file mode 100644 index 18b0dab6..00000000 --- a/linux/Battery.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery -/* -htop - linux/Battery.h -(C) 2004-2014 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. - -Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). -*/ - -#include "BatteryMeter.h" - - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/linux/Platform.c b/linux/Platform.c index 97d713ae..f5baa24c 100644 --- a/linux/Platform.c +++ b/linux/Platform.c @@ -17,6 +17,8 @@ in the source distribution for its full text. #include <limits.h> #include <math.h> #include <stdio.h> +#include <errno.h> +#include <unistd.h> #include "BatteryMeter.h" #include "ClockMeter.h" @@ -293,6 +295,7 @@ void Platform_setZfsCompressedArcValues(Meter* this) { ZfsCompressedArcMeter_readStats(this, &(lpl->zfs)); } + char* Platform_getProcessEnv(pid_t pid) { char procname[128]; xSnprintf(procname, sizeof(procname), PROCDIR "/%d/environ", pid); @@ -544,3 +547,323 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = packetsTransmittedSum; return true; } + +// Linux battery reading by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). + +#define MAX_BATTERIES 64 +#define PROC_BATTERY_DIR PROCDIR "/acpi/battery" +#define PROC_POWERSUPPLY_DIR PROCDIR "/acpi/ac_adapter" +#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply" + +// ---------------------------------------- +// READ FROM /proc +// ---------------------------------------- + +static unsigned long int parseBatInfo(const char* fileName, const unsigned short int lineNum, const unsigned short int wordNum) { + const char batteryPath[] = PROC_BATTERY_DIR; + DIR* batteryDir = opendir(batteryPath); + if (!batteryDir) + return 0; + + char* batteries[MAX_BATTERIES]; + unsigned int nBatteries = 0; + memset(batteries, 0, MAX_BATTERIES * sizeof(char*)); + + while (nBatteries < MAX_BATTERIES) { + struct dirent* dirEntry = readdir(batteryDir); + if (!dirEntry) + break; + + char* entryName = dirEntry->d_name; + if (!String_startsWith(entryName, "BAT")) + continue; + + batteries[nBatteries] = xStrdup(entryName); + nBatteries++; + } + closedir(batteryDir); + + unsigned long int total = 0; + for (unsigned int i = 0; i < nBatteries; i++) { + char infoPath[30]; + xSnprintf(infoPath, sizeof infoPath, "%s%s/%s", batteryPath, batteries[i], fileName); + + FILE* file = fopen(infoPath, "r"); + if (!file) + break; + + char* line = NULL; + for (unsigned short int j = 0; j < lineNum; j++) { + free(line); + line = String_readLine(file); + if (!line) + break; + } + + fclose(file); + + if (!line) + break; + + char* foundNumStr = String_getToken(line, wordNum); + const unsigned long int foundNum = atoi(foundNumStr); + free(foundNumStr); + free(line); + + total += foundNum; + } + + for (unsigned int i = 0; i < nBatteries; i++) + free(batteries[i]); + + return total; +} + +static ACPresence procAcpiCheck(void) { + ACPresence isOn = AC_ERROR; + const char* power_supplyPath = PROC_POWERSUPPLY_DIR; + DIR* dir = opendir(power_supplyPath); + if (!dir) + return AC_ERROR; + + for (;;) { + struct dirent* dirEntry = readdir(dir); + if (!dirEntry) + break; + + const char* entryName = dirEntry->d_name; + + if (entryName[0] != 'A') + continue; + + char statePath[256]; + xSnprintf(statePath, sizeof(statePath), "%s/%s/state", power_supplyPath, entryName); + FILE* file = fopen(statePath, "r"); + if (!file) { + isOn = AC_ERROR; + continue; + } + char* line = String_readLine(file); + + fclose(file); + + if (!line) + continue; + + char* isOnline = String_getToken(line, 2); + free(line); + + if (String_eq(isOnline, "on-line")) + isOn = AC_PRESENT; + else + isOn = AC_ABSENT; + free(isOnline); + if (isOn == AC_PRESENT) + break; + } + + if (dir) + closedir(dir); + + return isOn; +} + +static double Platform_Battery_getProcBatInfo(void) { + const unsigned long int totalFull = parseBatInfo("info", 3, 4); + if (totalFull == 0) + return NAN; + + const unsigned long int totalRemain = parseBatInfo("state", 5, 3); + if (totalRemain == 0) + return NAN; + + return totalRemain * 100.0 / (double) totalFull; +} + +static void Platform_Battery_getProcData(double* level, ACPresence* isOnAC) { + *isOnAC = procAcpiCheck(); + *level = AC_ERROR != *isOnAC ? Platform_Battery_getProcBatInfo() : NAN; +} + +// ---------------------------------------- +// READ FROM /sys +// ---------------------------------------- + +static inline ssize_t xread(int fd, void* buf, size_t count) { + // Read some bytes. Retry on EINTR and when we don't get as many bytes as we requested. + size_t alreadyRead = 0; + for (;;) { + ssize_t res = read(fd, buf, count); + if (res == -1) { + if (errno == EINTR) + continue; + return -1; + } + + if (res > 0) { + buf = ((char*)buf) + res; + count -= res; + alreadyRead += res; + } + + if (count == 0 || res == 0) + return alreadyRead; + } +} + +static void Platform_Battery_getSysData(double* level, ACPresence* isOnAC) { + + *level = NAN; + *isOnAC = AC_ERROR; + + DIR* dir = opendir(SYS_POWERSUPPLY_DIR); + if (!dir) + return; + + unsigned long int totalFull = 0; + unsigned long int totalRemain = 0; + + for (;;) { + struct dirent* dirEntry = readdir(dir); + if (!dirEntry) + break; + + const char* entryName = dirEntry->d_name; + char filePath[256]; + + xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/type", entryName); + int fd1 = open(filePath, O_RDONLY); + if (fd1 == -1) + continue; + + char type[8]; + ssize_t typelen = xread(fd1, type, 7); + close(fd1); + if (typelen < 1) + continue; + + if (type[0] == 'B' && type[1] == 'a' && type[2] == 't') { + xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName); + int fd2 = open(filePath, O_RDONLY); + if (fd2 == -1) { + closedir(dir); + return; + } + char buffer[1024]; + ssize_t buflen = xread(fd2, buffer, 1023); + close(fd2); + if (buflen < 1) { + closedir(dir); + return; + } + buffer[buflen] = '\0'; + char* buf = buffer; + char* line = NULL; + bool full = false; + bool now = false; + int fullSize = 0; + double capacityLevel = NAN; + + #define match(str,prefix) \ + (String_startsWith(str,prefix) ? (str) + strlen(prefix) : NULL) + + while ((line = strsep(&buf, "\n")) != NULL) { + const char* ps = match(line, "POWER_SUPPLY_"); + if (!ps) + continue; + const char* capacity = match(ps, "CAPACITY="); + if (capacity) + capacityLevel = atoi(capacity) / 100.0; + const char* energy = match(ps, "ENERGY_"); + if (!energy) + energy = match(ps, "CHARGE_"); + if (!energy) + continue; + const char* value = (!full) ? match(energy, "FULL=") : NULL; + if (value) { + fullSize = atoi(value); + totalFull += fullSize; + full = true; + if (now) + break; + continue; + } + value = (!now) ? match(energy, "NOW=") : NULL; + if (value) { + totalRemain += atoi(value); + now = true; + if (full) + break; + continue; + } + } + + #undef match + + if (!now && full && !isnan(capacityLevel)) + totalRemain += (capacityLevel * fullSize); + + } else if (entryName[0] == 'A') { + if (*isOnAC != AC_ERROR) + continue; + + xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/online", entryName); + int fd3 = open(filePath, O_RDONLY); + if (fd3 == -1) { + closedir(dir); + return; + } + char buffer[2] = ""; + for (;;) { + ssize_t res = read(fd3, buffer, 1); + if (res == -1 && errno == EINTR) + continue; + break; + } + close(fd3); + if (buffer[0] == '0') + *isOnAC = AC_ABSENT; + else if (buffer[0] == '1') + *isOnAC = AC_PRESENT; + } + } + closedir(dir); + + *level = totalFull > 0 ? ((double) totalRemain * 100.0) / (double) totalFull : NAN; +} + +static enum { BAT_PROC, BAT_SYS, BAT_ERR } Platform_Battery_method = BAT_PROC; + +static time_t Platform_Battery_cacheTime; +static double Platform_Battery_cacheLevel = NAN; +static ACPresence Platform_Battery_cacheIsOnAC; + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + time_t now = time(NULL); + // update battery reading is slow. Update it each 10 seconds only. + if (now < Platform_Battery_cacheTime + 10) { + *level = Platform_Battery_cacheLevel; + *isOnAC = Platform_Battery_cacheIsOnAC; + return; + } + + if (Platform_Battery_method == BAT_PROC) { + Platform_Battery_getProcData(level, isOnAC); + if (isnan(*level)) + Platform_Battery_method = BAT_SYS; + } + if (Platform_Battery_method == BAT_SYS) { + Platform_Battery_getSysData(level, isOnAC); + if (isnan(*level)) + Platform_Battery_method = BAT_ERR; + } + if (Platform_Battery_method == BAT_ERR) { + *level = NAN; + *isOnAC = AC_ERROR; + } else { + *level = CLAMP(*level, 0.0, 100.0); + } + Platform_Battery_cacheLevel = *level; + Platform_Battery_cacheIsOnAC = *isOnAC; + Platform_Battery_cacheTime = now; +} diff --git a/linux/Platform.h b/linux/Platform.h index fc249095..dbd6bb46 100644 --- a/linux/Platform.h +++ b/linux/Platform.h @@ -11,6 +11,7 @@ in the source distribution for its full text. #include <sys/types.h> #include "Action.h" +#include "BatteryMeter.h" #include "DiskIOMeter.h" #include "Meter.h" #include "Process.h" @@ -62,4 +63,6 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, unsigned long int* bytesTransmitted, unsigned long int* packetsTransmitted); +void Platform_getBattery(double *percent, ACPresence *isOnAC); + #endif diff --git a/openbsd/Battery.c b/openbsd/Battery.c deleted file mode 100644 index b72253e0..00000000 --- a/openbsd/Battery.c +++ /dev/null @@ -1,74 +0,0 @@ -/* -htop - openbsd/Battery.c -(C) 2015 Hisham H. Muhammad -(C) 2015 Michael McConville -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Battery.h" - -#include <sys/sysctl.h> -#include <sys/sensors.h> -#include <errno.h> -#include <math.h> -#include <string.h> - -static bool findDevice(const char* name, int* mib, struct sensordev* snsrdev, size_t* sdlen) { - for (int devn = 0;; devn++) { - mib[2] = devn; - if (sysctl(mib, 3, snsrdev, sdlen, NULL, 0) == -1) { - if (errno == ENXIO) - continue; - if (errno == ENOENT) - return false; - } - if (strcmp(name, snsrdev->xname) == 0) { - return true; - } - } -} - -void Battery_getData(double* level, ACPresence* isOnAC) { - static int mib[] = {CTL_HW, HW_SENSORS, 0, 0, 0}; - struct sensor s; - size_t slen = sizeof(struct sensor); - struct sensordev snsrdev; - size_t sdlen = sizeof(struct sensordev); - - bool found = findDevice("acpibat0", mib, &snsrdev, &sdlen); - - *level = NAN; - if (found) { - /* last full capacity */ - mib[3] = 7; - mib[4] = 0; - double last_full_capacity = 0; - if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) { - last_full_capacity = s.value; - } - if (last_full_capacity > 0) { - /* remaining capacity */ - mib[3] = 7; - mib[4] = 3; - if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) { - double charge = s.value; - *level = 100 * (charge / last_full_capacity); - if (charge >= last_full_capacity) { - *level = 100; - } - } - } - } - - found = findDevice("acpiac0", mib, &snsrdev, &sdlen); - - *isOnAC = AC_ERROR; - if (found) { - mib[3] = 9; - mib[4] = 0; - if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) { - *isOnAC = s.value; - } - } -} diff --git a/openbsd/Battery.h b/openbsd/Battery.h deleted file mode 100644 index 60b632d2..00000000 --- a/openbsd/Battery.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery -/* -htop - openbsd/Battery.h -(C) 2015 Hisham H. Muhammad -(C) 2015 Michael McConville -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "BatteryMeter.h" - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/openbsd/Platform.c b/openbsd/Platform.c index 5601048d..bf045396 100644 --- a/openbsd/Platform.c +++ b/openbsd/Platform.c @@ -25,6 +25,7 @@ in the source distribution for its full text. #include <sys/param.h> #include <sys/sysctl.h> +#include <sys/sensors.h> #include <sys/swap.h> #include <unistd.h> @@ -38,6 +39,7 @@ in the source distribution for its full text. #include <fcntl.h> #include <kvm.h> #include <limits.h> +#include <errno.h> #include <math.h> @@ -322,3 +324,60 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = 0; return false; } + +static bool findDevice(const char* name, int* mib, struct sensordev* snsrdev, size_t* sdlen) { + for (int devn = 0;; devn++) { + mib[2] = devn; + if (sysctl(mib, 3, snsrdev, sdlen, NULL, 0) == -1) { + if (errno == ENXIO) + continue; + if (errno == ENOENT) + return false; + } + if (strcmp(name, snsrdev->xname) == 0) { + return true; + } + } +} + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + static int mib[] = {CTL_HW, HW_SENSORS, 0, 0, 0}; + struct sensor s; + size_t slen = sizeof(struct sensor); + struct sensordev snsrdev; + size_t sdlen = sizeof(struct sensordev); + + bool found = findDevice("acpibat0", mib, &snsrdev, &sdlen); + + *level = NAN; + if (found) { + /* last full capacity */ + mib[3] = 7; + mib[4] = 0; + double last_full_capacity = 0; + if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) + last_full_capacity = s.value; + if (last_full_capacity > 0) { + /* remaining capacity */ + mib[3] = 7; + mib[4] = 3; + if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) { + double charge = s.value; + *level = 100 * (charge / last_full_capacity); + if (charge >= last_full_capacity) { + *level = 100; + } + } + } + } + + found = findDevice("acpiac0", mib, &snsrdev, &sdlen); + + *isOnAC = AC_ERROR; + if (found) { + mib[3] = 9; + mib[4] = 0; + if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) + *isOnAC = s.value; + } +} diff --git a/solaris/Battery.c b/solaris/Battery.c deleted file mode 100644 index c824df24..00000000 --- a/solaris/Battery.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "Battery.h" - -#include <math.h> - -void Battery_getData(double* level, ACPresence* isOnAC) { - *level = NAN; - *isOnAC = AC_ERROR; -} diff --git a/solaris/Battery.h b/solaris/Battery.h deleted file mode 100644 index 74a27fc5..00000000 --- a/solaris/Battery.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery - -#include "BatteryMeter.h" - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/solaris/Platform.c b/solaris/Platform.c index 2329590f..7eff2d5f 100644 --- a/solaris/Platform.c +++ b/solaris/Platform.c @@ -301,3 +301,8 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = 0; return false; } + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + *level = NAN; + *isOnAC = AC_ERROR; +} diff --git a/solaris/Platform.h b/solaris/Platform.h index 4d83dc7e..051a64da 100644 --- a/solaris/Platform.h +++ b/solaris/Platform.h @@ -80,4 +80,6 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, unsigned long int* bytesTransmitted, unsigned long int* packetsTransmitted); +void Platform_getBattery(double* level, ACPresence* isOnAC); + #endif diff --git a/unsupported/Battery.c b/unsupported/Battery.c deleted file mode 100644 index c824df24..00000000 --- a/unsupported/Battery.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "Battery.h" - -#include <math.h> - -void Battery_getData(double* level, ACPresence* isOnAC) { - *level = NAN; - *isOnAC = AC_ERROR; -} diff --git a/unsupported/Battery.h b/unsupported/Battery.h deleted file mode 100644 index 74a27fc5..00000000 --- a/unsupported/Battery.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery - -#include "BatteryMeter.h" - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/unsupported/Platform.c b/unsupported/Platform.c index 2492aa2f..6646398d 100644 --- a/unsupported/Platform.c +++ b/unsupported/Platform.c @@ -168,3 +168,8 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, *packetsTransmitted = 0; return false; } + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + *level = NAN; + *isOnAC = AC_ERROR; +} diff --git a/unsupported/Platform.h b/unsupported/Platform.h index a00f644e..c75a283a 100644 --- a/unsupported/Platform.h +++ b/unsupported/Platform.h @@ -60,4 +60,6 @@ bool Platform_getNetworkIO(unsigned long int* bytesReceived, unsigned long int* bytesTransmitted, unsigned long int* packetsTransmitted); +void Platform_getBattery(double *percent, ACPresence *isOnAC); + #endif |