2013-09-26 17:14:40 +02:00

201 lines
4.9 KiB
Plaintext

$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);