Provide apm(4/arm64) with battery information
authorkn <kn@openbsd.org>
Thu, 25 Mar 2021 12:18:27 +0000 (12:18 +0000)
committerkn <kn@openbsd.org>
Thu, 25 Mar 2021 12:18:27 +0000 (12:18 +0000)
apm merely provides an all zero/unknown stub for those values, e.g. apm(8)
output is useless.

Hardware sensors however provide this information:

hw.sensors.cwfg0.volt0=3.76 VDC (battery voltage)
hw.sensors.cwfg0.raw0=259 (battery remaining minutes)
hw.sensors.cwfg0.percent0=58.00% (battery percent)

Make cwfg(4) copy those over using apm_setinfohook() for apm to show it:

Battery state: high, 58% remaining, 259 minutes life estimate
A/C adapter state: not known
Performance adjustment mode: auto (408 MHz)

In cwfg's update routine, to keep values coherent, always reset them to
zero/unknown and only set those that came from a valid reading.

Input OK jca

sys/dev/fdt/cwfg.c

index 1a69064..b08c56e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cwfg.c,v 1.2 2021/03/22 18:37:26 kn Exp $ */
+/* $OpenBSD: cwfg.c,v 1.3 2021/03/25 12:18:27 kn Exp $ */
 /* $NetBSD: cwfg.c,v 1.1 2020/01/03 18:00:05 jmcneill Exp $ */
 /*-
  * Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
 #include <sys/malloc.h>
 #include <sys/sensors.h>
 
+#include <machine/apmvar.h>
 #include <machine/fdt.h>
 
 #include <dev/ofw/openfirm.h>
 
 #include <dev/i2c/i2cvar.h>
 
+#include "apm.h"
+
 #define        VERSION_REG             0x00
 #define        VCELL_HI_REG            0x02
 #define         VCELL_HI_MASK                  0x3f
@@ -119,6 +122,22 @@ struct cfdriver cwfg_cd = {
        NULL, "cwfg", DV_DULL
 };
 
+#if NAPM > 0
+struct apm_power_info cwfg_power = {
+       .battery_state = APM_BATT_UNKNOWN,
+       .ac_state = APM_AC_UNKNOWN,
+       .battery_life = 0,
+       .minutes_left = -1,
+};
+
+int
+cwfg_apminfo(struct apm_power_info *info)
+{
+       memcpy(info, &cwfg_power, sizeof(*info));
+       return 0;
+}
+#endif
+
 int
 cwfg_match(struct device *parent, void *match, void *aux)
 {
@@ -202,6 +221,10 @@ cwfg_attach(struct device *parent, struct device *self, void *aux)
 
        sensor_task_register(sc, cwfg_update_sensors, 5);
 
+#if NAPM > 0
+       apm_setinfohook(cwfg_apminfo);
+#endif
+
        printf("\n");
 }
 
@@ -325,6 +348,15 @@ cwfg_update_sensors(void *arg)
        uint8_t val;
        int error, n;
 
+#if NAPM > 0
+       /* reset previous reads so apm(4) never gets stale values
+        * in case of transient cwfg_read() failures below */
+       cwfg_power.battery_state = APM_BATT_UNKNOWN;
+       cwfg_power.ac_state = APM_AC_UNKNOWN;
+       cwfg_power.battery_life = 0;
+       cwfg_power.minutes_left = -1;
+#endif
+
        if ((error = cwfg_lock(sc)) != 0)
                return;
 
@@ -350,6 +382,11 @@ cwfg_update_sensors(void *arg)
        if (val != 0xff) {
                sc->sc_sensor[CWFG_SENSOR_SOC].value = val * 1000;
                sc->sc_sensor[CWFG_SENSOR_SOC].flags &= ~SENSOR_FINVALID;
+#if NAPM > 0
+               cwfg_power.battery_state = val > sc->sc_alert_level ?
+                   APM_BATT_HIGH : APM_BATT_LOW;
+               cwfg_power.battery_life = val;
+#endif
        }
 
        /* RTT */
@@ -362,6 +399,9 @@ cwfg_update_sensors(void *arg)
        if (rtt != 0x1fff) {
                sc->sc_sensor[CWFG_SENSOR_RTT].value = rtt;
                sc->sc_sensor[CWFG_SENSOR_RTT].flags &= ~SENSOR_FINVALID;
+#if NAPM > 0
+               cwfg_power.minutes_left = rtt;
+#endif
        }
 
 done: