mirror of https://github.com/xzeldon/htop.git
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")
This commit is contained in:
parent
63fafb4844
commit
1e94b92226
|
@ -70,6 +70,10 @@ in the source distribution for its full text.
|
||||||
#include "LibSensors.h"
|
#include "LibSensors.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef O_PATH
|
||||||
|
#define O_PATH 010000000 // declare for ancient glibc versions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBCAP
|
#ifdef HAVE_LIBCAP
|
||||||
enum CapMode {
|
enum CapMode {
|
||||||
|
@ -725,18 +729,47 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
|
||||||
uint64_t totalFull = 0;
|
uint64_t totalFull = 0;
|
||||||
uint64_t totalRemain = 0;
|
uint64_t totalRemain = 0;
|
||||||
|
|
||||||
struct dirent* dirEntry = NULL;
|
const struct dirent* dirEntry;
|
||||||
while ((dirEntry = readdir(dir))) {
|
while ((dirEntry = readdir(dir))) {
|
||||||
const char* entryName = dirEntry->d_name;
|
const char* entryName = dirEntry->d_name;
|
||||||
|
|
||||||
if (String_startsWith(entryName, "BAT")) {
|
#ifdef HAVE_OPENAT
|
||||||
char buffer[1024] = {0};
|
int entryFd = openat(dirfd(dir), entryName, O_DIRECTORY | O_PATH);
|
||||||
char filePath[256];
|
if (entryFd < 0)
|
||||||
xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName);
|
|
||||||
|
|
||||||
ssize_t r = xReadfile(filePath, buffer, sizeof(buffer));
|
|
||||||
if (r < 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
#else
|
||||||
|
char entryFd[4096];
|
||||||
|
xSnprintf(entryFd, sizeof(entryFd), SYS_POWERSUPPLY_DIR "/%s", entryName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { AC, BAT } type;
|
||||||
|
if (String_startsWith(entryName, "BAT")) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == BAT) {
|
||||||
|
char buffer[1024];
|
||||||
|
ssize_t r = xReadfileat(entryFd, "uevent", buffer, sizeof(buffer));
|
||||||
|
if (r < 0)
|
||||||
|
goto next;
|
||||||
|
|
||||||
bool full = false;
|
bool full = false;
|
||||||
bool now = false;
|
bool now = false;
|
||||||
|
@ -778,18 +811,15 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
|
||||||
if (!now && full && !isnan(capacityLevel))
|
if (!now && full && !isnan(capacityLevel))
|
||||||
totalRemain += capacityLevel * fullCharge;
|
totalRemain += capacityLevel * fullCharge;
|
||||||
|
|
||||||
} else if (String_startsWith(entryName, "AC")) {
|
} else if (type == AC) {
|
||||||
char buffer[2] = {0};
|
|
||||||
if (*isOnAC != AC_ERROR)
|
if (*isOnAC != AC_ERROR)
|
||||||
continue;
|
goto next;
|
||||||
|
|
||||||
char filePath[256];
|
char buffer[2];
|
||||||
xSnprintf(filePath, sizeof(filePath), SYS_POWERSUPPLY_DIR "/%s/online", entryName);
|
ssize_t r = xReadfileat(entryFd, "online", buffer, sizeof(buffer));
|
||||||
|
|
||||||
ssize_t r = xReadfile(filePath, buffer, sizeof(buffer));
|
|
||||||
if (r < 1) {
|
if (r < 1) {
|
||||||
*isOnAC = AC_ERROR;
|
*isOnAC = AC_ERROR;
|
||||||
continue;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer[0] == '0')
|
if (buffer[0] == '0')
|
||||||
|
@ -797,6 +827,9 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
|
||||||
else if (buffer[0] == '1')
|
else if (buffer[0] == '1')
|
||||||
*isOnAC = AC_PRESENT;
|
*isOnAC = AC_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
Compat_openatArgClose(entryFd);
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
Loading…
Reference in New Issue