pkgsrc/sysutils/asapm/patches/patch-af
wiz 7129823311 Add patch from Michael Eriksson in PR 26438:
The patches for asapm to try sysmon if APM fails, only support battery
info in units of Watts and Watt hours. However, some machines like my
Compaq Presario X1007EA laptop uses units of Amperes and Ampere hours.

Bump PKGREVISION.
2004-07-26 23:25:19 +00:00

200 lines
4.9 KiB
Text

$NetBSD: patch-af,v 1.5 2004/07/26 23:25:19 wiz Exp $
--- apm_read.c.orig 2001-11-23 23:07:19.000000000 +0200
+++ apm_read.c
@@ -31,6 +31,7 @@
/* file -> APM device */
extern char apm_device_file[];
+extern char sysmon_device_file[];
#include "state.h"
extern struct apm_state state;
@@ -136,18 +137,185 @@
state.time_left = info.ai_batt_time / 60;
}
#elif defined(__NetBSD__)||defined(__OpenBSD__)
+
+#include <sys/envsys.h>
+
+/* We cannot use ifdef ENVSYS_SWATTHOUR etc as it is enum. The
+ ENVSYS_FFRACVALID was added at the same time as WATTHOUR and INDICATOR, so
+ we use it to see if we have the support for those. */
+#ifdef ENVSYS_FFRACVALID
+#define HAVE_ENVSYS_SWATTHOUR
+#define HAVE_ENVSYS_INDICATOR
+#endif /* ENVSYS_FFRACVALID */
+
+int match_end(const char *str, const char *end_part)
+{
+ int len1, len2;
+ len1 = strlen(str);
+ len2 = strlen(end_part);
+ if (len1 < len2)
+ return 0;
+ return strcmp(str + len1 - len2, end_part) == 0;
+}
+
+void TrySysmonDevice( )
+{
+ int fd;
+ int count = 0;
+ envsys_basic_info_t ebis;
+ envsys_tre_data_t etds;
+ int32_t design, charge, warn_cap, low_cap, discharge_rate, charge_rate;
+ int connected, charging, percent, time_units, battery_status;
+
+ if ((fd = open(sysmon_device_file, O_RDONLY)) == -1) {
+ error_handle(1, "");
+ return;
+ }
+
+ design = 0;
+ charge = 0;
+ warn_cap = 0;
+ low_cap = 0;
+ charge_rate = 0;
+ discharge_rate = 0;
+ connected = 0;
+ charging = 0;
+ percent = 0;
+ time_units = 0;
+
+ for(etds.sensor = 0; ; etds.sensor++) {
+ if (ioctl(fd, ENVSYS_GTREDATA, &etds) == -1) {
+ error_handle(4, "");
+ close(fd);
+ return;
+ }
+ if (!(etds.validflags & ENVSYS_FVALID))
+ break;
+
+ ebis.sensor = etds.sensor;
+ if (ioctl(fd, ENVSYS_GTREINFO, &ebis) == -1) {
+ error_handle(4, "");
+ close(fd);
+ return;
+ }
+
+ if (etds.units != ebis.units) {
+ error_handle(6, "units does not match");
+ }
+
+ if (!(etds.validflags & ENVSYS_FCURVALID))
+ continue;
+
+#ifdef HAVE_ENVSYS_SWATTHOUR
+ if (etds.units == ENVSYS_SWATTHOUR ||
+ etds.units == ENVSYS_SAMPHOUR) {
+ /* Watt or amp hours, this must be battery cap info. */
+ if (match_end(ebis.desc, " design cap")) {
+ design += etds.cur.data_s;
+ } else if (match_end(ebis.desc, " charge")) {
+ charge += etds.cur.data_s;
+ } else if (match_end(ebis.desc, " warn cap")) {
+ warn_cap += etds.cur.data_s;
+ } else if (match_end(ebis.desc, " low cap")) {
+ low_cap += etds.cur.data_s;
+ }
+ }
+#endif /* HAVE_ENVSYS_SWATTHOUR */
+#ifdef HAVE_ENVSYS_INDICATOR
+ if (etds.units == ENVSYS_INDICATOR) {
+ /* Indicator of something, check for connected. */
+ if (match_end(ebis.desc, " connected")) {
+ connected = etds.cur.data_us;
+ } else if (match_end(ebis.desc, " charging")) {
+ charging = etds.cur.data_us;
+ }
+
+ }
+#endif /* HAVE_ENVSYS_INDICATOR */
+ if (etds.units == ENVSYS_SWATTS ||
+ etds.units == ENVSYS_SAMPS) {
+ /* Watts or apms, this must discharge rate. */
+ if (match_end(ebis.desc, " discharge rate")) {
+ discharge_rate += etds.cur.data_s;
+ } else if (match_end(ebis.desc, " charge rate")) {
+ charge_rate += etds.cur.data_s;
+ }
+
+ }
+ }
+
+ if (state.ac_line_status != connected) {
+ state.ac_line_status = connected ? AC_ONLINE : AC_BATTERY;
+ ++state.update;
+ if ( state.ac_line_status == AC_ONLINE )
+ state.flags |= CHANGE_AC_ON;
+ else
+ state.flags |= CHANGE_AC_OFF;
+ }
+ if (charging) {
+ battery_status = BATTERY_CHARGING;
+ } else {
+ if (charge > warn_cap) {
+ battery_status = BATTERY_HIGH;
+ } else if (charge > low_cap) {
+ battery_status = BATTERY_LOW;
+ } else {
+ battery_status = BATTERY_CRITICAL;
+ }
+ }
+
+ if (state.battery_status != battery_status) {
+ state.battery_status = battery_status;
+ ++state.update;
+ }
+
+ if (design != 0) {
+ percent = charge / (design / 100);
+ if (percent > 100) {
+ percent = 100;
+ }
+ else if (percent < 0) {
+ percent = 0;
+ }
+ }
+ if (state.percent != percent) {
+ if ( state.percent < percent )
+ state.flags |= CHANGE_POWER_UP;
+ else
+ state.flags |= CHANGE_POWER_DOWN;
+ state.percent = percent;
+ ++state.update;
+ }
+
+ if (discharge_rate > 0) {
+ time_units = charge / (discharge_rate / 60);
+ } else if (charge_rate > 0 && design > 0 && charging) {
+ time_units = (design - charge) / (charge_rate / 60);
+ }
+
+ /* we can display maximum 99:59 */
+ if ( time_units > 5999 )
+ time_units = 5999;
+ if (state.time_left != time_units) {
+ state.time_left = time_units;
+ ++state.update;
+ }
+ close(fd);
+ return;
+}
+
void ReadAPMDevice( ) /* NetBSD version */
{
int fd;
struct apm_power_info info;
memset(&info, 0, sizeof(info));
if ((fd = open(apm_device_file, O_RDONLY)) == -1) {
- error_handle(1, "");
+ TrySysmonDevice();
return;
}
if (ioctl(fd, APM_IOC_GETPOWER, &info) == -1) {
- error_handle(4, "");
close(fd);
+ TrySysmonDevice();
return;
}
close(fd);