- Rename ENVSYS_BATTERY_STATE units to ENVSYS_BATTERY_CAPACITY and

introduce ENVSYS_BATTERY_CHARGE, which is the same than an Indicator and
  it's used to know if the battery is currently charging or discharging.

- Require two sensors at least for SME_CLASS_BATTERY to make the low-power
  condition work: a ENVSYS_BATTERY_CAPACITY plus ENVSYS_BATTERY_CHARGE.

- Simplify sme_event_check_lowpower() and make it check the required
  sensors in the SME_CLASS_ACADAPTER and SME_CLASS_BATTERY classes.
  If the acadapter is not ready, trust the state returned by the battery
  device.

Based on suggestion from joerg@.
This commit is contained in:
xtraeme 2007-11-03 23:05:21 +00:00
parent ad0f60a40b
commit 4e10a84855
7 changed files with 127 additions and 104 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_bat.c,v 1.60 2007/11/02 19:21:29 plunky Exp $ */
/* $NetBSD: acpi_bat.c,v 1.61 2007/11/03 23:05:22 xtraeme Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -86,7 +86,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.60 2007/11/02 19:21:29 plunky Exp $");
__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.61 2007/11/03 23:05:22 xtraeme Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -469,7 +469,7 @@ acpibat_get_status(device_t dv)
}
sc->sc_data[ACPIBAT_CHARGE_STATE].value_cur =
ENVSYS_BATTERY_STATE_NORMAL;
ENVSYS_BATTERY_CAPACITY_NORMAL;
sc->sc_data[ACPIBAT_CAPACITY].value_cur = p2[2].Integer.Value * 1000;
sc->sc_data[ACPIBAT_CAPACITY].state = ENVSYS_SVALID;
@ -482,20 +482,20 @@ acpibat_get_status(device_t dv)
sc->sc_data[ACPIBAT_WCAPACITY].value_cur) {
sc->sc_data[ACPIBAT_CAPACITY].state = ENVSYS_SWARNUNDER;
sc->sc_data[ACPIBAT_CHARGE_STATE].value_cur =
ENVSYS_BATTERY_STATE_WARNING;
ENVSYS_BATTERY_CAPACITY_WARNING;
}
if (sc->sc_data[ACPIBAT_CAPACITY].value_cur <
sc->sc_data[ACPIBAT_LCAPACITY].value_cur) {
sc->sc_data[ACPIBAT_CAPACITY].state = ENVSYS_SCRITUNDER;
sc->sc_data[ACPIBAT_CHARGE_STATE].value_cur =
ENVSYS_BATTERY_STATE_LOW;
ENVSYS_BATTERY_CAPACITY_LOW;
}
if (status & ACPIBAT_ST_CRITICAL) {
sc->sc_data[ACPIBAT_CAPACITY].state = ENVSYS_SCRITICAL;
sc->sc_data[ACPIBAT_CHARGE_STATE].value_cur =
ENVSYS_BATTERY_STATE_CRITICAL;
ENVSYS_BATTERY_CAPACITY_CRITICAL;
}
mutex_exit(&sc->sc_mtx);
@ -706,8 +706,8 @@ acpibat_init_envsys(device_t dv)
INITDATA(ACPIBAT_CHARGERATE, rateunit, "charge rate");
INITDATA(ACPIBAT_DISCHARGERATE, rateunit, "discharge rate");
INITDATA(ACPIBAT_CAPACITY, capunit, "charge");
INITDATA(ACPIBAT_CHARGING, ENVSYS_INDICATOR, "charging");
INITDATA(ACPIBAT_CHARGE_STATE, ENVSYS_BATTERY_STATE, "charge state");
INITDATA(ACPIBAT_CHARGING, ENVSYS_BATTERY_CHARGE, "charging");
INITDATA(ACPIBAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state");
#undef INITDATA

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys.c,v 1.70 2007/11/02 19:21:29 plunky Exp $ */
/* $NetBSD: sysmon_envsys.c,v 1.71 2007/11/03 23:05:21 xtraeme Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
@ -64,7 +64,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.70 2007/11/02 19:21:29 plunky Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.71 2007/11/03 23:05:21 xtraeme Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -382,6 +382,9 @@ sysmonioctl_envsys(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
tred->min.data_s = edata->value_min;
tred->avg.data_us = edata->value_avg;
tred->avg.data_s = edata->value_avg;
if (edata->units == ENVSYS_BATTERY_CHARGE)
tred->units = ENVSYS_INDICATOR;
else
tred->units = edata->units;
tred->validflags |= ENVSYS_FVALID;
@ -429,6 +432,9 @@ sysmonioctl_envsys(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
binfo->validflags |= ENVSYS_FVALID;
if (binfo->sensor < sme->sme_nsensors) {
if (edata->units == ENVSYS_BATTERY_CHARGE)
binfo->units = ENVSYS_INDICATOR;
else
binfo->units = edata->units;
/*
@ -1000,14 +1006,15 @@ sme_add_sensor_dictionary(struct sysmon_envsys *sme, prop_array_t array,
* <true/>
* ...
*
* always false on Battery state, Drive and Indicator types.
* always false on Battery {capacity,charge}, Drive and Indicator types.
* They cannot be monitored.
*
*/
if ((edata->flags & ENVSYS_FMONNOTSUPP) ||
(edata->units == ENVSYS_INDICATOR) ||
(edata->units == ENVSYS_DRIVE) ||
(edata->units == ENVSYS_BATTERY_STATE)) {
(edata->units == ENVSYS_BATTERY_CAPACITY) ||
(edata->units == ENVSYS_BATTERY_CHARGE)) {
if (sme_sensor_upbool(dict, "monitoring-supported", false))
goto out;
} else {
@ -1050,20 +1057,20 @@ sme_add_sensor_dictionary(struct sysmon_envsys *sme, prop_array_t array,
/*
* Add the battery-state object for battery state sensors:
* Add the object for battery capacity sensors:
*
* ...
* <key>battery-state</key>
* <key>battery-capacity</key>
* <string>NORMAL</string>
* ...
*/
if (edata->units == ENVSYS_BATTERY_STATE) {
sdt = sme_get_description_table(SME_DESC_BATTERY_STATES);
if (edata->units == ENVSYS_BATTERY_CAPACITY) {
sdt = sme_get_description_table(SME_DESC_BATTERY_CAPACITY);
for (j = 0; sdt[j].type != -1; j++)
if (sdt[j].type == edata->value_cur)
break;
if (sme_sensor_upstring(dict, "battery-state", sdt[j].desc))
if (sme_sensor_upstring(dict, "battery-capacity", sdt[j].desc))
goto out;
}
@ -1271,11 +1278,12 @@ sme_update_dictionary(struct sysmon_envsys *sme)
break;
/*
* Integer and Indicator types do not the following
* values, so skip them.
* Battery charge, Integer and Indicator types do not
* need the following objects, so skip them.
*/
if (edata->units == ENVSYS_INTEGER ||
edata->units == ENVSYS_INDICATOR)
edata->units == ENVSYS_INDICATOR ||
edata->units == ENVSYS_BATTERY_CHARGE)
continue;
/* update sensor flags */
@ -1344,16 +1352,16 @@ sme_update_dictionary(struct sysmon_envsys *sme)
break;
}
/* update 'battery-state' only in ENVSYS_BATTERY_STATE. */
if (edata->units == ENVSYS_BATTERY_STATE) {
/* update 'battery-capacity' only in ENVSYS_BATTERY_CAPACITY. */
if (edata->units == ENVSYS_BATTERY_CAPACITY) {
sdt =
sme_get_description_table(SME_DESC_BATTERY_STATES);
sme_get_description_table(SME_DESC_BATTERY_CAPACITY);
for (j = 0; sdt[j].type != -1; j++)
if (sdt[j].type == edata->value_cur)
break;
error = sme_sensor_upstring(dict,
"battery-state",
"battery-capacity",
sdt[j].desc);
if (error)
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys_events.c,v 1.43 2007/10/23 21:36:03 xtraeme Exp $ */
/* $NetBSD: sysmon_envsys_events.c,v 1.44 2007/11/03 23:05:21 xtraeme Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.43 2007/10/23 21:36:03 xtraeme Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.44 2007/11/03 23:05:21 xtraeme Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -75,7 +75,8 @@ static int sme_events_timeout = 10;
static int sme_events_timeout_sysctl(SYSCTLFN_PROTO);
#define SME_EVTIMO (sme_events_timeout * hz)
static int sme_event_check_low_power(void);
static bool sme_event_check_low_power(void);
static bool sme_battery_critical(envsys_data_t *);
/*
* sysctl(9) stuff to handle the refresh value in the callout
@ -598,10 +599,10 @@ do { \
sdt = sme_get_description_table(SME_DESC_DRIVE_STATES);
state = ENVSYS_DRIVE_ONLINE;
break;
case ENVSYS_BATTERY_STATE:
case ENVSYS_BATTERY_CAPACITY:
sdt =
sme_get_description_table(SME_DESC_BATTERY_STATES);
state = ENVSYS_BATTERY_STATE_NORMAL;
sme_get_description_table(SME_DESC_BATTERY_CAPACITY);
state = ENVSYS_BATTERY_CAPACITY_NORMAL;
break;
default:
panic("%s: invalid units for ENVSYS_FMONSTCHANGED",
@ -649,19 +650,18 @@ out:
mutex_exit(&sme_mtx);
}
static int
static bool
sme_event_check_low_power(void)
{
struct sysmon_envsys *sme;
envsys_data_t *edata;
int i, batteries_cnt, batteries_discharged;
bool acadapter_on, acadapter_sensor_found;
acadapter_on = acadapter_sensor_found = false;
batteries_cnt = batteries_discharged = 0;
int i;
bool battery, batterycap, batterycharge;
KASSERT(mutex_owned(&sme_mtx));
battery = batterycap = batterycharge = false;
LIST_FOREACH(sme, &sysmon_envsys_list, sme_list)
if (sme->sme_class == SME_CLASS_ACADAPTER)
break;
@ -670,50 +670,59 @@ sme_event_check_low_power(void)
* No AC Adapter devices were found, do nothing.
*/
if (!sme)
return 0;
return false;
/*
* If there's an AC Adapter connected, there's no need
* to continue...
*/
for (i = 0; i < sme->sme_nsensors; i++) {
edata = &sme->sme_sensor_data[i];
if (edata->units == ENVSYS_INDICATOR) {
acadapter_sensor_found = true;
if (edata->value_cur) {
acadapter_on = true;
break;
}
if (edata->value_cur)
return false;
}
}
/*
* There's an AC Adapter device connected or there wasn't
* any sensor capable of returning its state.
* Check for battery devices and its state.
*/
if (acadapter_on || !acadapter_sensor_found)
return 0;
#define IS_BATTERY_DISCHARGED() \
do { \
if (((edata->units == ENVSYS_BATTERY_STATE) && \
((edata->value_cur == ENVSYS_BATTERY_STATE_CRITICAL) || \
(edata->value_cur == ENVSYS_BATTERY_STATE_LOW)))) { \
batteries_discharged++; \
break; \
} \
} while (/* CONSTCOND */ 0)
LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) {
if (sme->sme_class == SME_CLASS_BATTERY) {
batteries_cnt++;
for (i = 0; i < sme->sme_nsensors; i++) {
edata = &sme->sme_sensor_data[i];
IS_BATTERY_DISCHARGED();
if (sme->sme_class != SME_CLASS_BATTERY)
continue;
/*
* We've found a battery device...
*/
battery = true;
for (i = 0; i < sme->sme_nsensors; i++) {
edata = &sme->sme_sensor_data[i];
if (edata->units == ENVSYS_BATTERY_CAPACITY) {
batterycap = true;
if (!sme_battery_critical(edata))
return false;
} else if (edata->units == ENVSYS_BATTERY_CHARGE) {
batterycharge = true;
if (edata->value_cur)
return false;
}
}
}
if (!battery || !batterycap || !batterycharge)
return false;
/*
* All batteries are discharged?
* All batteries in low/critical capacity and discharging.
*/
if (batteries_cnt == batteries_discharged)
return 1;
return 0;
return true;
}
static bool
sme_battery_critical(envsys_data_t *edata)
{
if (edata->value_cur == ENVSYS_BATTERY_CAPACITY_CRITICAL ||
edata->value_cur == ENVSYS_BATTERY_CAPACITY_LOW)
return true;
return false;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys_tables.c,v 1.2 2007/10/07 04:11:15 xtraeme Exp $ */
/* $NetBSD: sysmon_envsys_tables.c,v 1.3 2007/11/03 23:05:21 xtraeme Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_tables.c,v 1.2 2007/10/07 04:11:15 xtraeme Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_tables.c,v 1.3 2007/11/03 23:05:21 xtraeme Exp $");
#include <sys/types.h>
@ -49,7 +49,8 @@ static const struct sme_description_table sme_units_description[] = {
{ ENVSYS_INDICATOR, PENVSYS_TYPE_INDICATOR, "Indicator" },
{ ENVSYS_INTEGER, PENVSYS_TYPE_INDICATOR, "Integer" },
{ ENVSYS_DRIVE, PENVSYS_TYPE_DRIVE, "Drive" },
{ ENVSYS_BATTERY_STATE, PENVSYS_TYPE_BATTERY, "Battery state" },
{ ENVSYS_BATTERY_CAPACITY, PENVSYS_TYPE_BATTERY,"Battery capacity" },
{ ENVSYS_BATTERY_CHARGE, -1, "Battery charge" },
{ -1, -1, "unknown" }
};
@ -85,13 +86,13 @@ static const struct sme_description_table sme_drivestate_description[] = {
};
/*
* Available battery state descriptions.
* Available battery capacity descriptions.
*/
static const struct sme_description_table sme_batterystate_description[] = {
{ ENVSYS_BATTERY_STATE_NORMAL, -1, "NORMAL" },
{ ENVSYS_BATTERY_STATE_WARNING, -1, "WARNING" },
{ ENVSYS_BATTERY_STATE_CRITICAL, -1, "CRITICAL" },
{ ENVSYS_BATTERY_STATE_LOW, -1, "LOW" },
static const struct sme_description_table sme_batterycap_description[] = {
{ ENVSYS_BATTERY_CAPACITY_NORMAL, -1, "NORMAL" },
{ ENVSYS_BATTERY_CAPACITY_WARNING, -1, "WARNING" },
{ ENVSYS_BATTERY_CAPACITY_CRITICAL, -1, "CRITICAL" },
{ ENVSYS_BATTERY_CAPACITY_LOW, -1, "LOW" },
{ -1, -1, "UNKNOWN" }
};
@ -104,8 +105,7 @@ sme_get_description_table(int type)
const struct sme_description_table *ud = sme_units_description;
const struct sme_description_table *sd = sme_state_description;
const struct sme_description_table *dd = sme_drivestate_description;
const struct sme_description_table *bd = sme_batterystate_description;
const struct sme_description_table *bd = sme_batterycap_description;
switch (type) {
case SME_DESC_UNITS:
return ud;
@ -113,7 +113,7 @@ sme_get_description_table(int type)
return sd;
case SME_DESC_DRIVE_STATES:
return dd;
case SME_DESC_BATTERY_STATES:
case SME_DESC_BATTERY_CAPACITY:
return bd;
default:
return NULL;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsysvar.h,v 1.22 2007/10/23 21:36:03 xtraeme Exp $ */
/* $NetBSD: sysmon_envsysvar.h,v 1.23 2007/11/03 23:05:22 xtraeme Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
@ -44,7 +44,7 @@ enum sme_description_types {
SME_DESC_UNITS = 1,
SME_DESC_STATES,
SME_DESC_DRIVE_STATES,
SME_DESC_BATTERY_STATES
SME_DESC_BATTERY_CAPACITY
};
#ifdef ENVSYS_DEBUG
@ -114,6 +114,7 @@ int sme_update_dictionary(struct sysmon_envsys *);
int sme_userset_dictionary(struct sysmon_envsys *,
prop_dictionary_t, prop_array_t);
prop_dictionary_t sme_sensor_dictionary_get(prop_array_t, const char *);
struct sysmon_envsys *sysmon_envsys_find(const char *);
/* functions to handle sysmon envsys events */
int sme_event_register(prop_dictionary_t, envsys_data_t *, const char *,

View File

@ -1,4 +1,4 @@
/* $NetBSD: envsys.h,v 1.17 2007/10/07 04:11:15 xtraeme Exp $ */
/* $NetBSD: envsys.h,v 1.18 2007/11/03 23:05:21 xtraeme Exp $ */
/*-
* Copyright (c) 1999, 2007 The NetBSD Foundation, Inc.
@ -53,7 +53,7 @@
#define ENVSYS_MAXSENSORS 512
#define ENVSYS_DESCLEN 32
/* struct used by a device sensor */
/* struct used by a sensor */
struct envsys_data {
uint32_t sensor; /* sensor number */
uint32_t units; /* type of sensor */
@ -86,7 +86,8 @@ enum envsys_units {
ENVSYS_INDICATOR, /* Indicator */
ENVSYS_INTEGER, /* Integer */
ENVSYS_DRIVE, /* Drive */
ENVSYS_BATTERY_STATE, /* Battery state */
ENVSYS_BATTERY_CAPACITY, /* Battery capacity */
ENVSYS_BATTERY_CHARGE, /* Battery charging/discharging */
ENVSYS_NSENSORS
};
@ -115,12 +116,12 @@ enum envsys_drive_states {
ENVSYS_DRIVE_PFAIL /* drive is degraded */
};
/* sensor battery states */
enum envsys_battery_states {
ENVSYS_BATTERY_STATE_NORMAL = 1, /* normal cap in battery */
ENVSYS_BATTERY_STATE_WARNING, /* warning cap in battery */
ENVSYS_BATTERY_STATE_CRITICAL, /* critical cap in battery */
ENVSYS_BATTERY_STATE_LOW /* low cap in battery */
/* sensor battery capacity states */
enum envsys_battery_capacity_states {
ENVSYS_BATTERY_CAPACITY_NORMAL = 1, /* normal cap in battery */
ENVSYS_BATTERY_CAPACITY_WARNING, /* warning cap in battery */
ENVSYS_BATTERY_CAPACITY_CRITICAL, /* critical cap in battery */
ENVSYS_BATTERY_CAPACITY_LOW /* low cap in battery */
};
/* sensor flags */
@ -140,9 +141,9 @@ enum envsys_battery_states {
#define ENVSYS_FMONNOTSUPP 0x00000800 /* monitoring not supported */
#define ENVSYS_FNOTVALID 0x00001000 /* sensor is invalid */
#define ENVSYS_GETDICTIONARY _IOWR('E', 0, struct plistref)
#define ENVSYS_SETDICTIONARY _IOWR('E', 1, struct plistref)
#define ENVSYS_REMOVEPROPS _IOWR('E', 2, struct plistref)
#define ENVSYS_GETDICTIONARY _IOWR('E', 0, struct plistref)
#define ENVSYS_SETDICTIONARY _IOWR('E', 1, struct plistref)
#define ENVSYS_REMOVEPROPS _IOWR('E', 2, struct plistref)
/*
* Compatibility with old interface. Only ENVSYS_GTREDATA

View File

@ -1,4 +1,4 @@
/* $NetBSD: envstat.c,v 1.56 2007/10/07 04:16:48 xtraeme Exp $ */
/* $NetBSD: envstat.c,v 1.57 2007/11/03 23:05:22 xtraeme Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: envstat.c,v 1.56 2007/10/07 04:16:48 xtraeme Exp $");
__RCSID("$NetBSD: envstat.c,v 1.57 2007/11/03 23:05:22 xtraeme Exp $");
#endif /* not lint */
#include <stdio.h>
@ -74,7 +74,7 @@ struct envsys_sensor {
char desc[ENVSYS_DESCLEN];
char type[ENVSYS_DESCLEN];
char drvstate[ENVSYS_DESCLEN];
char battstate[ENVSYS_DESCLEN];
char battcap[ENVSYS_DESCLEN];
char dvname[ENVSYS_DESCLEN];
};
@ -431,12 +431,12 @@ find_sensors(prop_array_t array, const char *dvname)
prop_string_cstring_nocopy(obj1),
sizeof(gesen[gnelems].drvstate));
/* get current battery state string */
obj1 = prop_dictionary_get(obj, "battery-state");
/* get current battery capacity string */
obj1 = prop_dictionary_get(obj, "battery-capacity");
if (obj1)
(void)strlcpy(gesen[gnelems].battstate,
(void)strlcpy(gesen[gnelems].battcap,
prop_string_cstring_nocopy(obj1),
sizeof(gesen[gnelems].battstate));
sizeof(gesen[gnelems].battcap));
/* get current value */
obj1 = prop_dictionary_get(obj, "cur-value");
@ -602,7 +602,11 @@ print_sensors(struct envsys_sensor *es, size_t nelems, const char *dvname)
continue;
}
if (strcmp(es[i].type, "Indicator") == 0) {
/*
* Indicator and Battery charge sensors.
*/
if ((strcmp(es[i].type, "Indicator") == 0) ||
(strcmp(es[i].type, "Battery charge") == 0)) {
(void)printf(": %10s", es[i].cur_value ? "ON" : "OFF");
@ -664,10 +668,10 @@ do { \
(void)printf(": %10s", es[i].drvstate);
/* Battery state */
} else if (strcmp(es[i].type, "Battery state") == 0) {
/* Battery capacity */
} else if (strcmp(es[i].type, "Battery capacity") == 0) {
(void)printf(": %10s", es[i].battstate);
(void)printf(": %10s", es[i].battcap);
/* everything else */
} else {