#include <string.h>
#include <kstat.h>
#include <errno.h>
#include "powertop.h"
#define mW2W(value) ((value) / 1000)
typedef struct battery_state {
uint32_t exist;
uint32_t power_unit;
uint32_t bst_state;
double present_rate;
double remain_cap;
double last_cap;
} battery_state_t;
static char *kstat_batt_mod[3] = {NULL, "battery", "acpi_drv"};
static uint_t kstat_batt_idx;
static battery_state_t battery_state;
static int pt_battery_stat_snapshot(void);
void
pt_battery_mod_lookup(void)
{
kstat_ctl_t *kc = kstat_open();
if (kstat_lookup(kc, kstat_batt_mod[1], 0, NULL))
kstat_batt_idx = 1;
else
if (kstat_lookup(kc, kstat_batt_mod[2], 0, NULL))
kstat_batt_idx = 2;
else
kstat_batt_idx = 0;
(void) kstat_close(kc);
}
void
pt_battery_print(void)
{
int err;
(void) memset(&battery_state, 0, sizeof (battery_state_t));
if (kstat_batt_idx > 0) {
if ((err = pt_battery_stat_snapshot()) < 0)
pt_error("battery kstat not found (%d)\n", err);
}
pt_display_acpi_power(battery_state.exist, battery_state.present_rate,
battery_state.remain_cap, battery_state.last_cap,
battery_state.bst_state);
}
static int
pt_battery_stat_snapshot(void)
{
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *knp;
kc = kstat_open();
ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
"battery BIF0");
if (ksp == NULL) {
(void) kstat_close(kc);
return (-1);
}
(void) kstat_read(kc, ksp, NULL);
knp = kstat_data_lookup(ksp, "bif_unit");
if (knp == NULL) {
(void) kstat_close(kc);
return (-1);
}
battery_state.power_unit = knp->value.ui32;
ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
"battery BST0");
if (ksp == NULL) {
(void) kstat_close(kc);
return (-1);
}
(void) kstat_read(kc, ksp, NULL);
knp = kstat_data_lookup(ksp, "bst_rate");
if (knp == NULL) {
(void) kstat_close(kc);
return (-1);
}
if (knp->value.ui32 == 0xFFFFFFFF)
battery_state.present_rate = 0;
else {
battery_state.exist = 1;
battery_state.present_rate = mW2W((double)(knp->value.ui32));
}
ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
"battery BIF0");
if (ksp == NULL) {
(void) kstat_close(kc);
return (-1);
}
(void) kstat_read(kc, ksp, NULL);
knp = kstat_data_lookup(ksp, "bif_last_cap");
if (knp == NULL) {
(void) kstat_close(kc);
return (-1);
}
battery_state.last_cap = mW2W((double)(knp->value.ui32));
ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
"battery BST0");
if (ksp == NULL) {
(void) kstat_close(kc);
return (-1);
}
(void) kstat_read(kc, ksp, NULL);
knp = kstat_data_lookup(ksp, "bst_rem_cap");
if (knp == NULL) {
(void) kstat_close(kc);
return (-1);
}
battery_state.remain_cap = mW2W((double)(knp->value.ui32));
ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
"battery BST0");
if (ksp == NULL) {
(void) kstat_close(kc);
return (-1);
}
(void) kstat_read(kc, ksp, NULL);
knp = kstat_data_lookup(ksp, "bst_state");
if (knp == NULL) {
(void) kstat_close(kc);
return (-1);
}
battery_state.bst_state = knp->value.ui32;
(void) kstat_close(kc);
return (0);
}