int acpibat_notify(struct aml_node *node, int notify_type, void *arg) { struct acpibat_softc *sc = arg; int64_t sta; dnprintf(10, "acpibat_notify: %.2x %s\n", notify_type, sc->sc_devnode->name); /* Check if installed state of battery has changed */ if (aml_evalinteger(sc->sc_acpi, node, "_STA", 0, NULL, &sta) == 0) { if (sta & STA_BATTERY) sc->sc_bat_present = 1; else sc->sc_bat_present = 0; } switch (notify_type) { case 0x00: /* Poll sensors */ case 0x80: /* _BST changed */ acpibat_getbst(sc); break; case 0x81: /* _BIF changed */ acpibat_getbif(sc); break; default: break; } acpibat_refresh(sc); return (0); }
void acpibat_attach(struct device *parent, struct device *self, void *aux) { struct acpibat_softc *sc = (struct acpibat_softc *)self; struct acpi_attach_args *aa = aux; struct aml_value res; sc->sc_acpi = (struct acpi_softc *)parent; sc->sc_devnode = aa->aaa_node; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, &res)) { dnprintf(10, "%s: no _STA\n", DEVNAME(sc)); return; } if ((res.v_integer & STA_BATTERY) != 0) { sc->sc_bat_present = 1; acpibat_getbif(sc); acpibat_getbst(sc); printf(": %s", sc->sc_devnode->name); if (sc->sc_bif.bif_model[0]) printf(" model \"%s\"", sc->sc_bif.bif_model); if (sc->sc_bif.bif_serial[0]) printf(" serial %s", sc->sc_bif.bif_serial); if (sc->sc_bif.bif_type[0]) printf(" type %s", sc->sc_bif.bif_type); if (sc->sc_bif.bif_oem[0]) printf(" oem \"%s\"", sc->sc_bif.bif_oem); printf("\n"); } else { sc->sc_bat_present = 0; printf(": %s not present\n", sc->sc_devnode->name); } aml_freevalue(&res); /* create sensors */ acpibat_monitor(sc); /* populate sensors */ acpibat_refresh(sc); aml_register_notify(sc->sc_devnode, aa->aaa_dev, acpibat_notify, sc, ACPIDEV_POLL); }
void acpibat_refresh(void *arg) { struct acpibat_softc *sc = arg; int i; dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc), sc->sc_devnode->name); if (!sc->sc_bat_present) { for (i = 0; i < 8; i++) { sc->sc_sens[i].value = 0; sc->sc_sens[i].status = SENSOR_S_UNSPEC; sc->sc_sens[i].flags = SENSOR_FINVALID; } /* override state */ strlcpy(sc->sc_sens[4].desc, "battery removed", sizeof(sc->sc_sens[4].desc)); return; } /* * XXX don't really need _BIF but keep it here in case we * miss an insertion/removal event */ acpibat_getbif(sc); acpibat_getbst(sc); /* _BIF values are static, sensor 0..3 */ if (sc->sc_bif.bif_last_capacity == BIF_UNKNOWN) { sc->sc_sens[0].value = 0; sc->sc_sens[0].status = SENSOR_S_UNKNOWN; sc->sc_sens[0].flags = SENSOR_FUNKNOWN; } else { sc->sc_sens[0].value = sc->sc_bif.bif_last_capacity * 1000; sc->sc_sens[0].status = SENSOR_S_UNSPEC; sc->sc_sens[0].flags = 0; } sc->sc_sens[1].value = sc->sc_bif.bif_warning * 1000; sc->sc_sens[1].flags = 0; sc->sc_sens[2].value = sc->sc_bif.bif_low * 1000; sc->sc_sens[2].flags = 0; if (sc->sc_bif.bif_voltage == BIF_UNKNOWN) { sc->sc_sens[3].value = 0; sc->sc_sens[3].status = SENSOR_S_UNKNOWN; sc->sc_sens[3].flags = SENSOR_FUNKNOWN; } else { sc->sc_sens[3].value = sc->sc_bif.bif_voltage * 1000; sc->sc_sens[3].status = SENSOR_S_UNSPEC; sc->sc_sens[3].flags = 0; } /* _BST values are dynamic, sensor 4..7 */ sc->sc_sens[4].status = SENSOR_S_OK; sc->sc_sens[4].flags = 0; if (sc->sc_bif.bif_last_capacity == BIF_UNKNOWN || sc->sc_bst.bst_capacity == BST_UNKNOWN) { sc->sc_sens[4].status = SENSOR_S_UNKNOWN; sc->sc_sens[4].flags = SENSOR_FUNKNOWN; strlcpy(sc->sc_sens[4].desc, "battery unknown", sizeof(sc->sc_sens[4].desc)); } else if (sc->sc_bst.bst_capacity >= sc->sc_bif.bif_last_capacity) strlcpy(sc->sc_sens[4].desc, "battery full", sizeof(sc->sc_sens[4].desc)); else if (sc->sc_bst.bst_state & BST_DISCHARGE) strlcpy(sc->sc_sens[4].desc, "battery discharging", sizeof(sc->sc_sens[4].desc)); else if (sc->sc_bst.bst_state & BST_CHARGE) strlcpy(sc->sc_sens[4].desc, "battery charging", sizeof(sc->sc_sens[4].desc)); else if (sc->sc_bst.bst_state & BST_CRITICAL) { strlcpy(sc->sc_sens[4].desc, "battery critical", sizeof(sc->sc_sens[4].desc)); sc->sc_sens[4].status = SENSOR_S_CRIT; } else strlcpy(sc->sc_sens[4].desc, "battery idle", sizeof(sc->sc_sens[4].desc)); sc->sc_sens[4].value = sc->sc_bst.bst_state; if (sc->sc_bst.bst_rate == BST_UNKNOWN) { sc->sc_sens[5].value = 0; sc->sc_sens[5].status = SENSOR_S_UNKNOWN; sc->sc_sens[5].flags = SENSOR_FUNKNOWN; } else { sc->sc_sens[5].value = sc->sc_bst.bst_rate; sc->sc_sens[5].status = SENSOR_S_UNSPEC; sc->sc_sens[5].flags = 0; } if (sc->sc_bst.bst_capacity == BST_UNKNOWN) { sc->sc_sens[6].value = 0; sc->sc_sens[6].status = SENSOR_S_UNKNOWN; sc->sc_sens[6].flags = SENSOR_FUNKNOWN; } else { sc->sc_sens[6].value = sc->sc_bst.bst_capacity * 1000; sc->sc_sens[6].flags = 0; if (sc->sc_bst.bst_capacity < sc->sc_bif.bif_low) /* XXX we should shutdown the system */ sc->sc_sens[6].status = SENSOR_S_CRIT; else if (sc->sc_bst.bst_capacity < sc->sc_bif.bif_warning) sc->sc_sens[6].status = SENSOR_S_WARN; else sc->sc_sens[6].status = SENSOR_S_OK; } if (sc->sc_bst.bst_voltage == BST_UNKNOWN) { sc->sc_sens[7].value = 0; sc->sc_sens[7].status = SENSOR_S_UNKNOWN; sc->sc_sens[7].flags = SENSOR_FUNKNOWN; } else { sc->sc_sens[7].value = sc->sc_bst.bst_voltage * 1000; sc->sc_sens[7].status = SENSOR_S_UNSPEC; sc->sc_sens[7].flags = 0; } }