1N/A/***************************************************************************
1N/A *
1N/A * acpi.c : Main routines for setting battery, AC adapter, and lid properties
1N/A *
1N/A * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
1N/A *
1N/A * This file is licensed under either the Academic Free License
1N/A * version 2.1 or The GNU General Public License version 2.
1N/A *
1N/A **************************************************************************/
1N/A
1N/A#ifdef HAVE_CONFIG_H
1N/A#include <config.h>
1N/A#endif
1N/A
1N/A#include <unistd.h>
1N/A#include <strings.h>
1N/A#include <string.h>
1N/A#include <kstat.h>
1N/A#include <fcntl.h>
1N/A#include <errno.h>
1N/A#include <sys/acpi_drv.h>
1N/A
1N/A#include <libhal.h>
1N/A#include "../hald/device_info.h"
1N/A#include "../hald/hald_dbus.h"
1N/A#include "../hald/logger.h"
1N/A#include "../hald/util_pm.h"
1N/A#include "acpi.h"
1N/A
1N/A
1N/Astatic void
1N/Amy_dbus_error_free(DBusError *error)
1N/A{
1N/A if (dbus_error_is_set(error)) {
1N/A dbus_error_free(error);
1N/A }
1N/A}
1N/A
1N/Agboolean
1N/Alaptop_panel_update(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A LibHalChangeSet *cs;
1N/A DBusError error;
1N/A struct acpi_drv_output_info inf;
1N/A
1N/A HAL_DEBUG(("laptop_panel_update() enter"));
1N/A
1N/A dbus_error_init(&error);
1N/A if (!libhal_device_query_capability(ctx, udi, "laptop_panel", &error)) {
1N/A bzero(&inf, sizeof (inf));
1N/A if ((ioctl(fd, ACPI_DRV_IOC_INFO, &inf) < 0) ||
1N/A (inf.nlev == 0)) {
1N/A return (FALSE);
1N/A }
1N/A
1N/A my_dbus_error_free(&error);
1N/A libhal_device_add_capability(ctx, udi, "laptop_panel", &error);
1N/A if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1N/A my_dbus_error_free(&error);
1N/A return (FALSE);
1N/A }
1N/A libhal_changeset_set_property_string(cs, "info.product",
1N/A "Generic Backlight Device");
1N/A libhal_changeset_set_property_string(cs, "info.category",
1N/A "laptop_panel");
1N/A libhal_changeset_set_property_int(cs, "laptop_panel.num_levels",
1N/A inf.nlev);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_commit_changeset(ctx, cs, &error);
1N/A libhal_device_free_changeset(cs);
1N/A }
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("ac_adapter_present() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Agboolean
1N/Alid_update(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A LibHalChangeSet *cs;
1N/A DBusError error;
1N/A int lid_state;
1N/A
1N/A HAL_DEBUG(("lid_update() enter"));
1N/A
1N/A if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1N/A return (FALSE);
1N/A }
1N/A dbus_error_init(&error);
1N/A if (!libhal_device_query_capability(ctx, udi, "button", &error)) {
1N/A my_dbus_error_free(&error);
1N/A libhal_device_add_capability(ctx, udi, "button", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_changeset_set_property_bool(cs, "button.has_state",
1N/A TRUE);
1N/A
1N/A if (ioctl(fd, ACPI_DRV_IOC_LID_STATUS, &lid_state) < 0) {
1N/A return (FALSE);
1N/A }
1N/A if (lid_state != 0) {
1N/A /* lid open */
1N/A libhal_changeset_set_property_bool(cs,
1N/A "button.state.value", FALSE);
1N/A } else {
1N/A /* lid closed */
1N/A libhal_changeset_set_property_bool(cs,
1N/A "button.state.value", TRUE);
1N/A }
1N/A libhal_changeset_set_property_bool(cs, "button.workaround",
1N/A TRUE);
1N/A libhal_changeset_set_property_string(cs, "button.type",
1N/A "lid");
1N/A libhal_changeset_set_property_string(cs, "info.product",
1N/A "Lid Switch");
1N/A libhal_changeset_set_property_string(cs, "info.category",
1N/A "button");
1N/A } else {
1N/A my_dbus_error_free(&error);
1N/A if (ioctl(fd, ACPI_DRV_IOC_LID_UPDATE, &lid_state) < 0) {
1N/A return (FALSE);
1N/A }
1N/A if (lid_state != 0) {
1N/A /* lid open */
1N/A libhal_changeset_set_property_bool(cs,
1N/A "button.state.value", FALSE);
1N/A } else {
1N/A /* lid closed */
1N/A libhal_changeset_set_property_bool(cs,
1N/A "button.state.value", TRUE);
1N/A }
1N/A }
1N/A
1N/A libhal_device_commit_changeset(ctx, cs, &error);
1N/A libhal_device_free_changeset(cs);
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("update_lid() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Astatic void
1N/Aac_adapter_present(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A int pow;
1N/A LibHalChangeSet *cs;
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("ac_adapter_present() enter"));
1N/A if (ioctl(fd, ACPI_DRV_IOC_POWER_STATUS, &pow) < 0) {
1N/A return;
1N/A }
1N/A if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1N/A return;
1N/A }
1N/A if (pow > 0) {
1N/A libhal_changeset_set_property_bool(cs, "ac_adapter.present",
1N/A TRUE);
1N/A } else {
1N/A libhal_changeset_set_property_bool(cs, "ac_adapter.present",
1N/A FALSE);
1N/A }
1N/A
1N/A dbus_error_init(&error);
1N/A libhal_device_commit_changeset(ctx, cs, &error);
1N/A libhal_device_free_changeset(cs);
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("ac_adapter_present() exit"));
1N/A}
1N/A
1N/Astatic void
1N/Abattery_remove(LibHalContext *ctx, const char *udi)
1N/A{
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("battery_remove() enter"));
1N/A dbus_error_init(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.remaining_time",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.charge_level.percentage", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.charge_level.rate",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.charge_level.last_full", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.charge_level.current", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.voltage.present",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.rate",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.current",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.rechargeable.is_discharging", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.rechargeable.is_charging", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.is_rechargeable",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.charge_level.unit",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.charge_level.granularity_2", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.charge_level.granularity_1", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.charge_level.low",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.charge_level.warning",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.charge_level.design",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.voltage.design",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.reporting.granularity_2", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.reporting.granularity_1", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.low",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.warning",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.design",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.last_full",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.unit",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.technology", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.reporting.technology",
1N/A &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.serial", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.model", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi, "battery.vendor", &error);
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("battery_remove() exit"));
1N/A}
1N/A
1N/Astatic void
1N/Abattery_last_full(LibHalChangeSet *cs, int fd)
1N/A{
1N/A acpi_bif_t bif;
1N/A
1N/A bzero(&bif, sizeof (bif));
1N/A if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) {
1N/A return;
1N/A }
1N/A libhal_changeset_set_property_int(cs, "battery.reporting_last_full",
1N/A bif.bif_last_cap);
1N/A}
1N/A
1N/Astatic void
1N/Abattery_dynamic_update(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A int reporting_rate;
1N/A int reporting_current;
1N/A int reporting_lastfull;
1N/A int design_voltage;
1N/A int present_voltage;
1N/A char *reporting_unit;
1N/A int remaining_time;
1N/A int remaining_percentage;
1N/A gboolean charging;
1N/A gboolean discharging;
1N/A acpi_bst_t bst;
1N/A LibHalChangeSet *cs;
1N/A DBusError error;
1N/A static int counter = 0;
1N/A
1N/A HAL_DEBUG(("battery_dynamic_update() enter"));
1N/A bzero(&bst, sizeof (bst));
1N/A if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) {
1N/A return;
1N/A }
1N/A
1N/A charging = bst.bst_state & ACPI_DRV_BST_CHARGING ? TRUE : FALSE;
1N/A discharging = bst.bst_state & ACPI_DRV_BST_DISCHARGING ? TRUE : FALSE;
1N/A /* No need to continue if battery is essentially idle. */
1N/A if (counter && !charging && !discharging) {
1N/A return;
1N/A }
1N/A dbus_error_init(&error);
1N/A libhal_device_set_property_bool(ctx, udi, "battery.is_rechargeable",
1N/A TRUE, &error);
1N/A my_dbus_error_free(&error);
1N/A if (libhal_device_property_exists(ctx, udi,
1N/A "battery.charge_level.percentage", &error)) {
1N/A remaining_percentage = libhal_device_get_property_int(ctx, udi,
1N/A "battery.charge_level.percentage", &error);
1N/A if ((remaining_percentage == 100) && charging) {
1N/A charging = FALSE;
1N/A }
1N/A }
1N/A libhal_device_set_property_bool(ctx, udi,
1N/A "battery.rechargeable.is_charging", charging, &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_set_property_bool(ctx, udi,
1N/A "battery.rechargeable.is_discharging", discharging, &error);
1N/A my_dbus_error_free(&error);
1N/A reporting_current = bst.bst_rem_cap;
1N/A libhal_device_set_property_int(ctx, udi, "battery.reporting.current",
1N/A bst.bst_rem_cap, &error);
1N/A my_dbus_error_free(&error);
1N/A reporting_rate = bst.bst_rate;
1N/A libhal_device_set_property_int(ctx, udi, "battery.reporting.rate",
1N/A bst.bst_rate, &error);
1N/A my_dbus_error_free(&error);
1N/A present_voltage = bst.bst_voltage;
1N/A libhal_device_set_property_int(ctx, udi, "battery.voltage.present",
1N/A bst.bst_voltage, &error);
1N/A /* get all the data we know */
1N/A my_dbus_error_free(&error);
1N/A reporting_unit = libhal_device_get_property_string(ctx, udi,
1N/A "battery.reporting.unit", &error);
1N/A my_dbus_error_free(&error);
1N/A reporting_lastfull = libhal_device_get_property_int(ctx, udi,
1N/A "battery.reporting.last_full", &error);
1N/A
1N/A /*
1N/A * Convert mAh to mWh since util_compute_time_remaining() works
1N/A * for mWh.
1N/A */
1N/A if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) {
1N/A my_dbus_error_free(&error);
1N/A design_voltage = libhal_device_get_property_int(ctx, udi,
1N/A "battery.voltage.design", &error);
1N/A /*
1N/A * If the present_voltage is inaccurate, set it to the
1N/A * design_voltage.
1N/A */
1N/A if (((present_voltage * 10) < design_voltage) ||
1N/A (present_voltage <= 0) ||
1N/A (present_voltage > design_voltage)) {
1N/A present_voltage = design_voltage;
1N/A }
1N/A reporting_rate = (reporting_rate * present_voltage) / 1000;
1N/A reporting_lastfull = (reporting_lastfull * present_voltage) /
1N/A 1000;
1N/A reporting_current = (reporting_current * present_voltage) /
1N/A 1000;
1N/A }
1N/A
1N/A /* Make sure the current charge does not exceed the full charge */
1N/A if (reporting_current > reporting_lastfull) {
1N/A reporting_current = reporting_lastfull;
1N/A }
1N/A if (!charging && !discharging) {
1N/A counter++;
1N/A reporting_rate = 0;
1N/A }
1N/A
1N/A if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1N/A HAL_DEBUG(("Cannot allocate changeset"));
1N/A libhal_free_string(reporting_unit);
1N/A my_dbus_error_free(&error);
1N/A return;
1N/A }
1N/A
1N/A libhal_changeset_set_property_int(cs, "battery.charge_level.rate",
1N/A reporting_rate);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.last_full", reporting_lastfull);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.current", reporting_current);
1N/A
1N/A remaining_percentage = util_compute_percentage_charge(udi,
1N/A reporting_current, reporting_lastfull);
1N/A remaining_time = util_compute_time_remaining(udi, reporting_rate,
1N/A reporting_current, reporting_lastfull, discharging, charging, 0);
1N/A /*
1N/A * Some batteries give bad remaining_time estimates relative to
1N/A * the charge level.
1N/A */
1N/A if (charging && ((remaining_time < 30) || ((remaining_time < 300) &&
1N/A (remaining_percentage < 95)) || (remaining_percentage > 97))) {
1N/A remaining_time = util_compute_time_remaining(udi,
1N/A reporting_rate, reporting_current, reporting_lastfull,
1N/A discharging, charging, 1);
1N/A }
1N/A
1N/A if (remaining_percentage > 0) {
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.percentage", remaining_percentage);
1N/A } else {
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.charge_level.percentage", &error);
1N/A }
1N/A if ((remaining_percentage == 100) && charging) {
1N/A battery_last_full(cs, fd);
1N/A }
1N/A /*
1N/A * remaining_percentage is more accurate so we handle cases
1N/A * where the remaining_time cannot be correct.
1N/A */
1N/A if ((!charging && !discharging) || ((remaining_percentage == 100) &&
1N/A !discharging)) {
1N/A remaining_time = 0;
1N/A }
1N/A if (remaining_time < 0) {
1N/A my_dbus_error_free(&error);
1N/A libhal_device_remove_property(ctx, udi,
1N/A "battery.remaining_time", &error);
1N/A } else if (remaining_time >= 0) {
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.remaining_time", remaining_time);
1N/A }
1N/A
1N/A my_dbus_error_free(&error);
1N/A libhal_device_commit_changeset(ctx, cs, &error);
1N/A libhal_device_free_changeset(cs);
1N/A libhal_free_string(reporting_unit);
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("battery_dynamic_update() exit"));
1N/A}
1N/A
1N/Astatic gboolean
1N/Abattery_static_update(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A const char *technology;
1N/A int reporting_design;
1N/A int reporting_warning;
1N/A int reporting_low;
1N/A int reporting_gran1;
1N/A int reporting_gran2;
1N/A int voltage_design;
1N/A char reporting_unit[10];
1N/A acpi_bif_t bif;
1N/A LibHalChangeSet *cs;
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("battery_static_update() enter"));
1N/A bzero(&bif, sizeof (bif));
1N/A if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) {
1N/A return (FALSE);
1N/A }
1N/A if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1N/A HAL_DEBUG(("Cannot allocate changeset"));
1N/A return (FALSE);
1N/A }
1N/A
1N/A libhal_changeset_set_property_string(cs, "battery.vendor",
1N/A bif.bif_oem_info);
1N/A technology = bif.bif_type;
1N/A if (technology != NULL) {
1N/A libhal_changeset_set_property_string(cs,
1N/A "battery.reporting.technology", technology);
1N/A libhal_changeset_set_property_string(cs, "battery.technology",
1N/A util_get_battery_technology(technology));
1N/A }
1N/A libhal_changeset_set_property_string(cs, "battery.serial",
1N/A bif.bif_serial);
1N/A libhal_changeset_set_property_string(cs, "battery.model",
1N/A bif.bif_model);
1N/A
1N/A if (bif.bif_unit) {
1N/A libhal_changeset_set_property_string(cs,
1N/A "battery.reporting.unit", "mAh");
1N/A strlcpy(reporting_unit, "mAh", sizeof (reporting_unit));
1N/A } else {
1N/A libhal_changeset_set_property_string(cs,
1N/A "battery.reporting.unit", "mWh");
1N/A strlcpy(reporting_unit, "mWh", sizeof (reporting_unit));
1N/A }
1N/A libhal_changeset_set_property_int(cs, "battery.reporting.last_full",
1N/A bif.bif_last_cap);
1N/A libhal_changeset_set_property_int(cs, "battery.reporting.design",
1N/A bif.bif_design_cap);
1N/A reporting_design = bif.bif_design_cap;
1N/A libhal_changeset_set_property_int(cs, "battery.reporting.warning",
1N/A bif.bif_warn_cap);
1N/A reporting_warning = bif.bif_warn_cap;
1N/A libhal_changeset_set_property_int(cs, "battery.reporting.low",
1N/A bif.bif_low_cap);
1N/A reporting_low = bif.bif_low_cap;
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.reporting.granularity_1", bif.bif_gran1_cap);
1N/A reporting_gran1 = bif.bif_gran1_cap;
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.reporting.granularity_2", bif.bif_gran2_cap);
1N/A reporting_gran2 = bif.bif_gran2_cap;
1N/A libhal_changeset_set_property_int(cs, "battery.voltage.design",
1N/A bif.bif_voltage);
1N/A voltage_design = bif.bif_voltage;
1N/A
1N/A if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) {
1N/A /* convert to mWh */
1N/A libhal_changeset_set_property_string(cs,
1N/A "battery.charge_level.unit", "mWh");
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.design",
1N/A (reporting_design * voltage_design) / 1000);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.warning",
1N/A (reporting_warning * voltage_design) / 1000);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.low",
1N/A (reporting_low * voltage_design) / 1000);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.granularity_1",
1N/A (reporting_gran1 * voltage_design) / 1000);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.granularity_2",
1N/A (reporting_gran2 * voltage_design) / 1000);
1N/A } else {
1N/A if (reporting_unit && strcmp(reporting_unit, "mWh") == 0) {
1N/A libhal_changeset_set_property_string(cs,
1N/A "battery.charge_level.unit", "mWh");
1N/A }
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.design", reporting_design);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.warning", reporting_warning);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.low", reporting_low);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.granularity_1", reporting_gran1);
1N/A libhal_changeset_set_property_int(cs,
1N/A "battery.charge_level.granularity_2", reporting_gran2);
1N/A }
1N/A
1N/A
1N/A dbus_error_init(&error);
1N/A libhal_device_commit_changeset(ctx, cs, &error);
1N/A libhal_device_free_changeset(cs);
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("battery_static_update() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Agboolean
1N/Abattery_update(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A acpi_bst_t bst;
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("battery_update() enter"));
1N/A dbus_error_init(&error);
1N/A libhal_device_set_property_string(ctx, udi, "info.product",
1N/A "Battery Bay", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_set_property_string(ctx, udi, "info.category", "battery",
1N/A &error);
1N/A
1N/A bzero(&bst, sizeof (bst));
1N/A if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) {
1N/A if (errno == ENXIO) {
1N/A my_dbus_error_free(&error);
1N/A libhal_device_set_property_bool(ctx, udi,
1N/A "battery.present", FALSE, &error);
1N/A } else {
1N/A my_dbus_error_free(&error);
1N/A return (FALSE);
1N/A }
1N/A } else {
1N/A my_dbus_error_free(&error);
1N/A libhal_device_set_property_bool(ctx, udi, "battery.present",
1N/A TRUE, &error);
1N/A }
1N/A
1N/A my_dbus_error_free(&error);
1N/A if (!libhal_device_get_property_bool(ctx, udi, "battery.present",
1N/A &error)) {
1N/A HAL_DEBUG(("battery_update(): battery is NOT present"));
1N/A battery_remove(ctx, udi);
1N/A } else {
1N/A HAL_DEBUG(("battery_update(): battery is present"));
1N/A my_dbus_error_free(&error);
1N/A libhal_device_set_property_string(ctx, udi, "battery.type",
1N/A "primary", &error);
1N/A my_dbus_error_free(&error);
1N/A libhal_device_add_capability(ctx, udi, "battery", &error);
1N/A my_dbus_error_free(&error);
1N/A if (libhal_device_get_property_type(ctx, udi, "battery.vendor",
1N/A &error) == LIBHAL_PROPERTY_TYPE_INVALID) {
1N/A battery_static_update(ctx, udi, fd);
1N/A }
1N/A battery_dynamic_update(ctx, udi, fd);
1N/A }
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("battery_update() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Astatic gboolean
1N/Abattery_update_all(LibHalContext *ctx)
1N/A{
1N/A int i;
1N/A int num_devices;
1N/A char **battery_devices;
1N/A int fd;
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("battery_update_all() enter"));
1N/A
1N/A dbus_error_init(&error);
1N/A if ((battery_devices = libhal_manager_find_device_string_match
1N/A (ctx, "info.category", "battery", &num_devices, &error)) !=
1N/A NULL) {
1N/A for (i = 0; i < num_devices; i++) {
1N/A my_dbus_error_free(&error);
1N/A if (libhal_device_get_property_bool(ctx,
1N/A battery_devices[i], "battery.present", &error)) {
1N/A if ((fd = open_device(ctx,
1N/A battery_devices[i])) == -1) {
1N/A continue;
1N/A }
1N/A battery_dynamic_update(ctx, battery_devices[i],
1N/A fd);
1N/A close(fd);
1N/A }
1N/A }
1N/A libhal_free_string_array(battery_devices);
1N/A }
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("battery_update_all() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Agboolean
1N/Aac_adapter_update(LibHalContext *ctx, const char *udi, int fd)
1N/A{
1N/A LibHalChangeSet *cs;
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("ac_adapter_update() enter"));
1N/A dbus_error_init(&error);
1N/A if (!libhal_device_query_capability(ctx, udi, "ac_adapter", &error)) {
1N/A my_dbus_error_free(&error);
1N/A libhal_device_add_capability(ctx, udi, "ac_adapter", &error);
1N/A if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1N/A my_dbus_error_free(&error);
1N/A return (FALSE);
1N/A }
1N/A libhal_changeset_set_property_string(cs, "info.product",
1N/A "AC Adapter");
1N/A libhal_changeset_set_property_string(cs, "info.category",
1N/A "ac_adapter");
1N/A my_dbus_error_free(&error);
1N/A libhal_device_commit_changeset(ctx, cs, &error);
1N/A libhal_device_free_changeset(cs);
1N/A }
1N/A ac_adapter_present(ctx, udi, fd);
1N/A battery_update_all(ctx);
1N/A
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("ac_adapter_update() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Astatic gboolean
1N/Aac_adapter_update_all(LibHalContext *ctx)
1N/A{
1N/A int i;
1N/A int num_devices;
1N/A char **ac_adapter_devices;
1N/A int fd;
1N/A DBusError error;
1N/A
1N/A HAL_DEBUG(("ac_adapter_update_all() enter"));
1N/A dbus_error_init(&error);
1N/A if ((ac_adapter_devices = libhal_manager_find_device_string_match(
1N/A ctx, "info.category", "ac_adapter", &num_devices, &error)) !=
1N/A NULL) {
1N/A for (i = 0; i < num_devices; i++) {
1N/A if ((fd = open_device(ctx, ac_adapter_devices[i]))
1N/A == -1) {
1N/A continue;
1N/A }
1N/A ac_adapter_present(ctx, ac_adapter_devices[i], fd);
1N/A close(fd);
1N/A }
1N/A libhal_free_string_array(ac_adapter_devices);
1N/A }
1N/A my_dbus_error_free(&error);
1N/A HAL_DEBUG(("ac_adapter_update_all() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Agboolean
1N/Aupdate_devices(gpointer data)
1N/A{
1N/A LibHalContext *ctx = (LibHalContext *)data;
1N/A
1N/A HAL_DEBUG(("update_devices() enter"));
1N/A ac_adapter_update_all(ctx);
1N/A battery_update_all(ctx);
1N/A HAL_DEBUG(("update_devices() exit"));
1N/A return (TRUE);
1N/A}
1N/A
1N/Aint
1N/Aopen_device(LibHalContext *ctx, char *udi)
1N/A{
1N/A char path[HAL_PATH_MAX] = "/devices";
1N/A char *devfs_path;
1N/A DBusError error;
1N/A
1N/A dbus_error_init(&error);
1N/A devfs_path = libhal_device_get_property_string(ctx, udi,
1N/A "solaris.devfs_path", &error);
1N/A my_dbus_error_free(&error);
1N/A if (devfs_path == NULL) {
1N/A return (-1);
1N/A }
1N/A strlcat(path, devfs_path, HAL_PATH_MAX);
1N/A libhal_free_string(devfs_path);
1N/A return (open(path, O_RDONLY | O_NONBLOCK));
1N/A}