diff options
author | Christian Göttsche <cgzones@googlemail.com> | 2021-12-08 20:27:54 +0100 |
---|---|---|
committer | BenBE <BenBE@geshi.org> | 2021-12-08 20:50:11 +0100 |
commit | 1e94b92226007bac939e59b7f6b75b23b177b9c6 (patch) | |
tree | 2ac30dcd5bd715287ae3c584df564d91205c157e /linux | |
parent | 63fafb4844dd619793ba1d318e2b06518666dd37 (diff) |
Linux: read generic sysfs batteries
Not all batteries entries in /sys/class/power_supply start with either
BAT or AC, but might have device specific names, e.g. CMB1.
Detect the types of those entries and parse them accordingly.
Closes: #881
Fixes: 3e70de64 ("Code clean up for reading battery info")
Diffstat (limited to 'linux')
-rw-r--r-- | linux/Platform.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/linux/Platform.c b/linux/Platform.c index 1e412be0..8253817a 100644 --- a/linux/Platform.c +++ b/linux/Platform.c @@ -70,6 +70,10 @@ in the source distribution for its full text. #include "LibSensors.h" #endif +#ifndef O_PATH +#define O_PATH 010000000 // declare for ancient glibc versions +#endif + #ifdef HAVE_LIBCAP enum CapMode { @@ -725,18 +729,47 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) { uint64_t totalFull = 0; uint64_t totalRemain = 0; - struct dirent* dirEntry = NULL; + const struct dirent* dirEntry; while ((dirEntry = readdir(dir))) { const char* entryName = dirEntry->d_name; +#ifdef HAVE_OPENAT + int entryFd = openat(dirfd(dir), entryName, O_DIRECTORY | O_PATH); + if (entryFd < 0) + continue; +#else + char entryFd[4096]; + xSnprintf(entryFd, sizeof(entryFd), SYS_POWERSUPPLY_DIR "/%s", entryName); +#endif + + enum { AC, BAT } type; if (String_startsWith(entryName, "BAT")) { - char buffer[1024] = {0}; - char filePath[256]; - xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName); + type = BAT; + } else if (String_startsWith(entryName, "AC")) { + type = AC; + } else { + char buffer[32]; + ssize_t ret = xReadfileat(entryFd, "type", buffer, sizeof(buffer)); + if (ret <= 0) + goto next; + + /* drop optional trailing newlines */ + for (char* buf = &buffer[(size_t)ret - 1]; *buf == '\n'; buf--) + *buf = '\0'; + + if (String_eq(buffer, "Battery")) + type = BAT; + else if (String_eq(buffer, "Mains")) + type = AC; + else + goto next; + } - ssize_t r = xReadfile(filePath, buffer, sizeof(buffer)); + if (type == BAT) { + char buffer[1024]; + ssize_t r = xReadfileat(entryFd, "uevent", buffer, sizeof(buffer)); if (r < 0) - continue; + goto next; bool full = false; bool now = false; @@ -778,18 +811,15 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) { if (!now && full && !isnan(capacityLevel)) totalRemain += capacityLevel * fullCharge; - } else if (String_startsWith(entryName, "AC")) { - char buffer[2] = {0}; + } else if (type == AC) { if (*isOnAC != AC_ERROR) - continue; - - char filePath[256]; - xSnprintf(filePath, sizeof(filePath), SYS_POWERSUPPLY_DIR "/%s/online", entryName); + goto next; - ssize_t r = xReadfile(filePath, buffer, sizeof(buffer)); + char buffer[2]; + ssize_t r = xReadfileat(entryFd, "online", buffer, sizeof(buffer)); if (r < 1) { *isOnAC = AC_ERROR; - continue; + goto next; } if (buffer[0] == '0') @@ -797,6 +827,9 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) { else if (buffer[0] == '1') *isOnAC = AC_PRESENT; } + +next: + Compat_openatArgClose(entryFd); } closedir(dir); |