Open outpaddling opened 3 years ago
I dug into the code and discovered that battery monitoring is implemented by shelling out an apm command. Biggest problem here is that apm does not exist on powerpc, arm, or riscv. It's also an inefficient way to get battery info and has been superseded by the ACPI interface.
The patches below should work on any platform and perform better.
src-cpp/framework-OSInterface-FreeBSD.cpp does not appear to be used anymore, but I patched it just in case.
I was also getting intermittent false alarms about low battery with the apm implementation when the system was under heavy load and I'm hoping this will eliminate those as well. I'll report back if the false alarms continue.
--- ../src-cpp/framework-OSInterface-FreeBSD.cpp.orig 2021-12-25 20:33:45.000000000 -0600
+++ ../src-cpp/framework-OSInterface-FreeBSD.cpp 2022-02-17 08:14:20.413578000 -0600
@@ -21,24 +21,34 @@
bool OSInterface::OS_batteryAvailable(){
static int bat_avail = -1; //this will not change during a single session - keep later calls fast
if(bat_avail < 0){
- int val = getCmdOutput("apm -l").join("").toInt();
- bat_avail = ((val >= 0 && val <= 100) ? 1 : 0 );
+ bat_avail = (sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) == 0);
}
return (bat_avail==1);
}
float OSInterface::OS_batteryCharge(){
- int charge = getCmdOutput("apm -l").join("").toInt();
- if(charge > 100){ charge = -1; } //invalid charge
- return charge;
+ int life;
+ if ( (sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) != 0) ||
+ (life > 100) )
+ life = -1
+ return life;
}
bool OSInterface::OS_batteryCharging(){
- return (getCmdOutput("apm -a").join("").simplified() == "1");
+ if ( (sysctlbyname("hw.acpi.battery.state", &state, &len, NULL, 0) == 0) &&
+ (state == ACPI_BATT_STAT_CHARGING) )
+ return true;
+ else
+ return false;
}
double OSInterface::OS_batterySecondsLeft(){ //Returns: estimated number of seconds remaining
- return getCmdOutput("apm -t").join("").toDouble();
+ int min, sec;
+ if ( sysctlbyname("hw.acpi.battery.time", &min, &len, NULL, 0) == 0 )
+ sec = min * 60;
+ else
+ sec = -1
+ return sec;
}
// = Volume =
...skipping...
--- libLumina/LuminaOS-FreeBSD.cpp.orig 2021-12-26 02:33:45 UTC
+++ libLumina/LuminaOS-FreeBSD.cpp
@@ -9,6 +9,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
+#include <dev/acpica/acpiio.h>
#include <QDebug>
//can't read xbrightness settings - assume invalid until set
@@ -289,31 +290,52 @@ void LOS::systemSuspend(){
}
//Battery Availability
+// apm command is not available on powerpc or arm
bool LOS::hasBattery(){
static int hasbat = -1;
+ int life;
+ size_t len = sizeof(life);
if(hasbat < 0 ){
- int val = batteryCharge();
- if(val >= 0 && val <= 100){ hasbat = 1; }
- else{ hasbat = 0; }
+ if ( sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) == 0 )
+ hasbat = 1;
+ else
+ hasbat = 0;
}
return (hasbat==1);
}
//Battery Charge Level
+// apm command is not available on powerpc or arm
int LOS::batteryCharge(){ //Returns: percent charge (0-100), anything outside that range is counted as an error
- int charge = LUtils::getCmdOutput("apm -l").join("").toInt();
- if(charge > 100){ charge = -1; } //invalid charge
- return charge;
+ int life; // sysctl name
+ size_t len = sizeof(life);
+ if ( (sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) != 0) ||
+ (life > 100) )
+ life = -1; //invalid charge
+ return life;
}
//Battery Charging State
+// apm command is not available on powerpc or arm
bool LOS::batteryIsCharging(){
- return (LUtils::getCmdOutput("apm -a").join("").simplified() == "1");
+ int state;
+ size_t len = sizeof(state);
+ if ( (sysctlbyname("hw.acpi.battery.state", &state, &len, NULL, 0) == 0) &&
+ (state == ACPI_BATT_STAT_CHARGING) )
+ return true;
+ else
+ return false;
}
//Battery Time Remaining
+// apm command is not available on powerpc or arm
int LOS::batterySecondsLeft(){ //Returns: estimated number of seconds remaining
- return LUtils::getCmdOutput("apm -t").join("").toInt();
+ int min;
+ size_t len = sizeof(min);
+ if ( sysctlbyname("hw.acpi.battery.time", &min, &len, NULL, 0) == 0 )
+ return min * 60;
+ else
+ return -1;
}
//File Checksums
Also relates to #349.
FYI, this seems to have eliminated the minor CPU spikes (usually to around 3%) I had always seen under "top". Since reinstalling with these patches, the CPU stays consistently at a small fraction of a percent.
The patched 1.6.2 port is here, BTW: https://github.com/outpaddling/freebsd-ports-wip/tree/master/lumina-core
Just installed Lumina on an iMac G5 via desktop-installer. Works just about perfectly, except for thinking that the system should have a battery and stunning me with the gulag firing squad drum roll every time I log in.
"sysctl -a | grep batt" shows nothing, so I'm wondering how Lumina determines that a system has a battery?