Overall remaining battery power is currently the average of the
remaining power (in percents) of each battery.  This is misleading if
your laptop uses a large external battery which drains out first, and
a smaller internal battery (common scheme on eg thinkpad machines).
Overall battery power decreases much faster when you switch to the
smaller battery.  This odd behavior was reported by a friend a few weeks
ago.

The diff below attempts to fix this: compute the sum of the remaining
power and capacity, *then* compute the overall remaining percentage.
No regression on my thinkpad x270 with two batteries of similar
capacity.  I don't know whether the original reporter will be able to
test this soon.

The code touches the acpisbs(4) bits, hopefully without changing the
current behavior.  acpisbs(4) currently doesn't support multiple
batteries.

Test reports, feedback, oks welcome.


Index: acpi.c
===================================================================
RCS file: /d/cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.383
diff -u -p -p -u -r1.383 acpi.c
--- acpi.c      8 May 2020 11:18:01 -0000       1.383
+++ acpi.c      8 May 2020 15:04:50 -0000
@@ -3503,7 +3503,7 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t
        struct acpi_sbs *sbs;
        struct apm_power_info *pi = (struct apm_power_info *)data;
        int bats;
-       unsigned int remaining, rem, minutes, rate;
+       unsigned int capacity, remaining, minutes, rate;
        int s;
 
        if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 ||
@@ -3554,7 +3554,8 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t
                pi->battery_life = 0;
                pi->minutes_left = 0;
                bats = 0;
-               remaining = rem = 0;
+               capacity = 0;
+               remaining = 0;
                minutes = 0;
                rate = 0;
                SLIST_FOREACH(bat, &sc->sc_bat, aba_link) {
@@ -3565,11 +3566,9 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t
                                continue;
 
                        bats++;
-                       rem = (bat->aba_softc->sc_bst.bst_capacity * 100) /
-                           bat->aba_softc->sc_bix.bix_last_capacity;
-                       if (rem > 100)
-                               rem = 100;
-                       remaining += rem;
+                       capacity += bat->aba_softc->sc_bix.bix_last_capacity;
+                       remaining += min(bat->aba_softc->sc_bst.bst_capacity,
+                           bat->aba_softc->sc_bix.bix_last_capacity);
 
                        if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN)
                                continue;
@@ -3587,10 +3586,9 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t
                                continue;
 
                        bats++;
-                       rem = sbs->asbs_softc->sc_battery.rel_charge;
-                       if (rem > 100)
-                               rem = 100;
-                       remaining += rem;
+                       capacity += 100;
+                       remaining += min(100,
+                           sbs->asbs_softc->sc_battery.rel_charge);
 
                        if (sbs->asbs_softc->sc_battery.run_time ==
                            ACPISBS_VALUE_UNKNOWN)
@@ -3613,7 +3611,7 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t
                        pi->minutes_left = 60 * minutes / rate;
 
                /* running on battery */
-               pi->battery_life = remaining / bats;
+               pi->battery_life = remaining * 100 / capacity;
                if (pi->battery_life > 50)
                        pi->battery_state = APM_BATT_HIGH;
                else if (pi->battery_life > 25)

-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to