commit 4c4d53c669a3f09e2e1b4b9a92736085840d6c91
parent 84a2f117a32f0796045941260cdc4b69852b41e0
Author: Santtu Lakkala <inz@inz.fi>
Date: Wed, 23 Feb 2022 08:49:58 +0200
Multiple battery support
If a device has multiple batteries, the overall capacity is not
available directly, instead loop through batteries and add up the
energy/charge levels.
Diffstat:
3 files changed, 52 insertions(+), 15 deletions(-)
diff --git a/components/battery.c b/components/battery.c
@@ -10,15 +10,21 @@
#include <unistd.h>
static const char *
- pick(const char *bat, const char *f1, const char *f2, char *path,
- size_t length)
+ pick(const char *f1, const char *f2, char *path,
+ size_t length, ...)
{
- if (esnprintf(path, length, f1, bat) > 0 &&
+ va_list a1;
+ va_list a2;
+
+ va_start(a1, length);
+ va_copy(a2, a1);
+
+ if (evsnprintf(path, length, f1, a1) > 0 &&
access(path, R_OK) == 0) {
return f1;
}
- if (esnprintf(path, length, f2, bat) > 0 &&
+ if (evsnprintf(path, length, f2, a2) > 0 &&
access(path, R_OK) == 0) {
return f2;
}
@@ -32,12 +38,41 @@
int perc;
char path[PATH_MAX];
- if (esnprintf(path, sizeof(path),
- "/sys/class/power_supply/%s/capacity", bat) < 0) {
- return NULL;
- }
- if (pscanf(path, "%d", &perc) != 1) {
- return NULL;
+ if (bat) {
+ if (esnprintf(path, sizeof(path),
+ "/sys/class/power_supply/%s/capacity", bat) < 0) {
+ return NULL;
+ }
+ if (pscanf(path, "%d", &perc) != 1) {
+ return NULL;
+ }
+ } else {
+ int bi;
+ int ef = 0;
+ int en = 0;
+ for (bi = 0;; bi++) {
+ int f;
+ int n;
+
+ if (!pick("/sys/class/power_supply/BAT%d/charge_full",
+ "/sys/class/power_supply/BAT%d/energy_full",
+ path, sizeof(path), bi))
+ break;
+ if (pscanf(path, "%d", &f) != 1)
+ return NULL;
+ if (!pick("/sys/class/power_supply/BAT%d/charge_now",
+ "/sys/class/power_supply/BAT%d/energy_now",
+ path, sizeof(path), bi))
+ break;
+ if (pscanf(path, "%d", &n) != 1)
+ return NULL;
+
+ ef += f;
+ en += n;
+ }
+ if (ef == 0)
+ return NULL;
+ perc = (en + ef / 200) / (ef / 100);
}
return bprintf("%d", perc);
@@ -88,17 +123,17 @@
return NULL;
}
- if (!pick(bat, "/sys/class/power_supply/%s/charge_now",
+ if (!pick("/sys/class/power_supply/%s/charge_now",
"/sys/class/power_supply/%s/energy_now", path,
- sizeof(path)) ||
+ sizeof(path), bat) ||
pscanf(path, "%ju", &charge_now) < 0) {
return NULL;
}
if (!strcmp(state, "Discharging")) {
- if (!pick(bat, "/sys/class/power_supply/%s/current_now",
+ if (!pick("/sys/class/power_supply/%s/current_now",
"/sys/class/power_supply/%s/power_now", path,
- sizeof(path)) ||
+ sizeof(path), bat) ||
pscanf(path, "%ju", ¤t_now) < 0) {
return NULL;
}
diff --git a/util.c b/util.c
@@ -49,7 +49,7 @@ die(const char *fmt, ...)
exit(1);
}
-static int
+int
evsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
int ret;
diff --git a/util.h b/util.h
@@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */
#include <stdint.h>
+#include <stdarg.h>
extern char buf[1024];
@@ -10,6 +11,7 @@ extern char *argv0;
void warn(const char *, ...);
void die(const char *, ...);
+int evsnprintf(char *str, size_t size, const char *fmt, va_list ap);
int esnprintf(char *str, size_t size, const char *fmt, ...);
const char *bprintf(const char *fmt, ...);
const char *fmt_human(uintmax_t num, int base);