16573Sphitran /***************************************************************************
26573Sphitran *
36573Sphitran * acpi.c : Main routines for setting battery, AC adapter, and lid properties
46573Sphitran *
56573Sphitran * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
66573Sphitran * Use is subject to license terms.
76573Sphitran *
86573Sphitran * Licensed under the Academic Free License version 2.1
96573Sphitran *
106573Sphitran **************************************************************************/
116573Sphitran
126573Sphitran #ifdef HAVE_CONFIG_H
136573Sphitran #include <config.h>
146573Sphitran #endif
156573Sphitran
166573Sphitran #include <unistd.h>
176573Sphitran #include <strings.h>
186573Sphitran #include <string.h>
196573Sphitran #include <kstat.h>
206573Sphitran #include <fcntl.h>
216573Sphitran #include <errno.h>
226573Sphitran #include <sys/acpi_drv.h>
236573Sphitran
246573Sphitran #include <libhal.h>
256573Sphitran #include "../hald/device_info.h"
266573Sphitran #include "../hald/hald_dbus.h"
276573Sphitran #include "../hald/logger.h"
286573Sphitran #include "../hald/util_pm.h"
296573Sphitran #include "acpi.h"
306573Sphitran
316573Sphitran
326573Sphitran static void
my_dbus_error_free(DBusError * error)336573Sphitran my_dbus_error_free(DBusError *error)
346573Sphitran {
356573Sphitran if (dbus_error_is_set(error)) {
366573Sphitran dbus_error_free(error);
376573Sphitran }
386573Sphitran }
396573Sphitran
406573Sphitran gboolean
laptop_panel_update(LibHalContext * ctx,const char * udi,int fd)416573Sphitran laptop_panel_update(LibHalContext *ctx, const char *udi, int fd)
426573Sphitran {
436573Sphitran LibHalChangeSet *cs;
446573Sphitran DBusError error;
456573Sphitran struct acpi_drv_output_info inf;
466573Sphitran
476573Sphitran HAL_DEBUG(("laptop_panel_update() enter"));
486573Sphitran
496573Sphitran dbus_error_init(&error);
506573Sphitran if (!libhal_device_query_capability(ctx, udi, "laptop_panel", &error)) {
516573Sphitran bzero(&inf, sizeof (inf));
526573Sphitran if ((ioctl(fd, ACPI_DRV_IOC_INFO, &inf) < 0) ||
536573Sphitran (inf.nlev == 0)) {
546573Sphitran return (FALSE);
556573Sphitran }
566573Sphitran
576573Sphitran my_dbus_error_free(&error);
586573Sphitran libhal_device_add_capability(ctx, udi, "laptop_panel", &error);
596573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) {
606573Sphitran my_dbus_error_free(&error);
616573Sphitran return (FALSE);
626573Sphitran }
636573Sphitran libhal_changeset_set_property_string(cs, "info.product",
646573Sphitran "Generic Backlight Device");
656573Sphitran libhal_changeset_set_property_string(cs, "info.category",
666573Sphitran "laptop_panel");
676573Sphitran libhal_changeset_set_property_int(cs, "laptop_panel.num_levels",
686573Sphitran inf.nlev);
696573Sphitran my_dbus_error_free(&error);
706573Sphitran libhal_device_commit_changeset(ctx, cs, &error);
716573Sphitran libhal_device_free_changeset(cs);
726573Sphitran }
736573Sphitran my_dbus_error_free(&error);
746573Sphitran HAL_DEBUG(("ac_adapter_present() exit"));
756573Sphitran return (TRUE);
766573Sphitran }
776573Sphitran
786573Sphitran gboolean
lid_update(LibHalContext * ctx,const char * udi,int fd)796573Sphitran lid_update(LibHalContext *ctx, const char *udi, int fd)
806573Sphitran {
816573Sphitran LibHalChangeSet *cs;
826573Sphitran DBusError error;
83*7651SPhi.Tran@Sun.COM int lid_state;
846573Sphitran
856573Sphitran HAL_DEBUG(("lid_update() enter"));
866573Sphitran
87*7651SPhi.Tran@Sun.COM if ((cs = libhal_device_new_changeset(udi)) == NULL) {
88*7651SPhi.Tran@Sun.COM return (FALSE);
89*7651SPhi.Tran@Sun.COM }
906573Sphitran dbus_error_init(&error);
916573Sphitran if (!libhal_device_query_capability(ctx, udi, "button", &error)) {
926573Sphitran my_dbus_error_free(&error);
936573Sphitran libhal_device_add_capability(ctx, udi, "button", &error);
94*7651SPhi.Tran@Sun.COM my_dbus_error_free(&error);
95*7651SPhi.Tran@Sun.COM libhal_changeset_set_property_bool(cs, "button.has_state",
96*7651SPhi.Tran@Sun.COM TRUE);
97*7651SPhi.Tran@Sun.COM
98*7651SPhi.Tran@Sun.COM if (ioctl(fd, ACPI_DRV_IOC_LID_STATUS, &lid_state) < 0) {
996573Sphitran return (FALSE);
1006573Sphitran }
101*7651SPhi.Tran@Sun.COM if (lid_state != 0) {
102*7651SPhi.Tran@Sun.COM /* lid open */
103*7651SPhi.Tran@Sun.COM libhal_changeset_set_property_bool(cs,
104*7651SPhi.Tran@Sun.COM "button.state.value", FALSE);
105*7651SPhi.Tran@Sun.COM } else {
106*7651SPhi.Tran@Sun.COM /* lid closed */
107*7651SPhi.Tran@Sun.COM libhal_changeset_set_property_bool(cs,
108*7651SPhi.Tran@Sun.COM "button.state.value", TRUE);
109*7651SPhi.Tran@Sun.COM }
110*7651SPhi.Tran@Sun.COM libhal_changeset_set_property_bool(cs, "button.workaround",
1116573Sphitran TRUE);
1126573Sphitran libhal_changeset_set_property_string(cs, "button.type",
1136573Sphitran "lid");
1146573Sphitran libhal_changeset_set_property_string(cs, "info.product",
1156573Sphitran "Lid Switch");
1166573Sphitran libhal_changeset_set_property_string(cs, "info.category",
1176573Sphitran "button");
118*7651SPhi.Tran@Sun.COM } else {
1196573Sphitran my_dbus_error_free(&error);
120*7651SPhi.Tran@Sun.COM if (ioctl(fd, ACPI_DRV_IOC_LID_UPDATE, &lid_state) < 0) {
121*7651SPhi.Tran@Sun.COM return (FALSE);
122*7651SPhi.Tran@Sun.COM }
123*7651SPhi.Tran@Sun.COM if (lid_state != 0) {
124*7651SPhi.Tran@Sun.COM /* lid open */
125*7651SPhi.Tran@Sun.COM libhal_changeset_set_property_bool(cs,
126*7651SPhi.Tran@Sun.COM "button.state.value", FALSE);
127*7651SPhi.Tran@Sun.COM } else {
128*7651SPhi.Tran@Sun.COM /* lid closed */
129*7651SPhi.Tran@Sun.COM libhal_changeset_set_property_bool(cs,
130*7651SPhi.Tran@Sun.COM "button.state.value", TRUE);
131*7651SPhi.Tran@Sun.COM }
1326573Sphitran }
133*7651SPhi.Tran@Sun.COM
134*7651SPhi.Tran@Sun.COM libhal_device_commit_changeset(ctx, cs, &error);
135*7651SPhi.Tran@Sun.COM libhal_device_free_changeset(cs);
1366573Sphitran my_dbus_error_free(&error);
1376573Sphitran HAL_DEBUG(("update_lid() exit"));
1386573Sphitran return (TRUE);
1396573Sphitran }
1406573Sphitran
1416573Sphitran static void
ac_adapter_present(LibHalContext * ctx,const char * udi,int fd)1426573Sphitran ac_adapter_present(LibHalContext *ctx, const char *udi, int fd)
1436573Sphitran {
1446573Sphitran int pow;
1456573Sphitran LibHalChangeSet *cs;
1466573Sphitran DBusError error;
1476573Sphitran
1486573Sphitran HAL_DEBUG(("ac_adapter_present() enter"));
1496573Sphitran if (ioctl(fd, ACPI_DRV_IOC_POWER_STATUS, &pow) < 0) {
1506573Sphitran return;
1516573Sphitran }
1526573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1536573Sphitran return;
1546573Sphitran }
1556573Sphitran if (pow > 0) {
1566573Sphitran libhal_changeset_set_property_bool(cs, "ac_adapter.present",
1576573Sphitran TRUE);
1586573Sphitran } else {
1596573Sphitran libhal_changeset_set_property_bool(cs, "ac_adapter.present",
1606573Sphitran FALSE);
1616573Sphitran }
1626573Sphitran
1636573Sphitran dbus_error_init(&error);
1646573Sphitran libhal_device_commit_changeset(ctx, cs, &error);
1656573Sphitran libhal_device_free_changeset(cs);
1666573Sphitran my_dbus_error_free(&error);
1676573Sphitran HAL_DEBUG(("ac_adapter_present() exit"));
1686573Sphitran }
1696573Sphitran
1706573Sphitran static void
battery_remove(LibHalContext * ctx,const char * udi)1716573Sphitran battery_remove(LibHalContext *ctx, const char *udi)
1726573Sphitran {
1736573Sphitran DBusError error;
1746573Sphitran
1756573Sphitran HAL_DEBUG(("battery_remove() enter"));
1766573Sphitran dbus_error_init(&error);
1776573Sphitran libhal_device_remove_property(ctx, udi, "battery.remaining_time",
1786573Sphitran &error);
1796573Sphitran my_dbus_error_free(&error);
1806573Sphitran libhal_device_remove_property(ctx, udi,
1816573Sphitran "battery.charge_level.percentage", &error);
1826573Sphitran my_dbus_error_free(&error);
1836573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.rate",
1846573Sphitran &error);
1856573Sphitran my_dbus_error_free(&error);
1866573Sphitran libhal_device_remove_property(ctx, udi,
1876573Sphitran "battery.charge_level.last_full", &error);
1886573Sphitran my_dbus_error_free(&error);
1896573Sphitran libhal_device_remove_property(ctx, udi,
1906573Sphitran "battery.charge_level.current", &error);
1916573Sphitran my_dbus_error_free(&error);
1926573Sphitran libhal_device_remove_property(ctx, udi, "battery.voltage.present",
1936573Sphitran &error);
1946573Sphitran my_dbus_error_free(&error);
1956573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.rate",
1966573Sphitran &error);
1976573Sphitran my_dbus_error_free(&error);
1986573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.current",
1996573Sphitran &error);
2006573Sphitran my_dbus_error_free(&error);
2016573Sphitran libhal_device_remove_property(ctx, udi,
2026573Sphitran "battery.rechargeable.is_discharging", &error);
2036573Sphitran my_dbus_error_free(&error);
2046573Sphitran libhal_device_remove_property(ctx, udi,
2056573Sphitran "battery.rechargeable.is_charging", &error);
2066573Sphitran my_dbus_error_free(&error);
2076573Sphitran libhal_device_remove_property(ctx, udi, "battery.is_rechargeable",
2086573Sphitran &error);
2096573Sphitran my_dbus_error_free(&error);
2106573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.unit",
2116573Sphitran &error);
2126573Sphitran my_dbus_error_free(&error);
2136573Sphitran libhal_device_remove_property(ctx, udi,
2146573Sphitran "battery.charge_level.granularity_2", &error);
2156573Sphitran my_dbus_error_free(&error);
2166573Sphitran libhal_device_remove_property(ctx, udi,
2176573Sphitran "battery.charge_level.granularity_1", &error);
2186573Sphitran my_dbus_error_free(&error);
2196573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.low",
2206573Sphitran &error);
2216573Sphitran my_dbus_error_free(&error);
2226573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.warning",
2236573Sphitran &error);
2246573Sphitran my_dbus_error_free(&error);
2256573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.design",
2266573Sphitran &error);
2276573Sphitran my_dbus_error_free(&error);
2286573Sphitran libhal_device_remove_property(ctx, udi, "battery.voltage.design",
2296573Sphitran &error);
2306573Sphitran my_dbus_error_free(&error);
2316573Sphitran libhal_device_remove_property(ctx, udi,
2326573Sphitran "battery.reporting.granularity_2", &error);
2336573Sphitran my_dbus_error_free(&error);
2346573Sphitran libhal_device_remove_property(ctx, udi,
2356573Sphitran "battery.reporting.granularity_1", &error);
2366573Sphitran my_dbus_error_free(&error);
2376573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.low",
2386573Sphitran &error);
2396573Sphitran my_dbus_error_free(&error);
2406573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.warning",
2416573Sphitran &error);
2426573Sphitran my_dbus_error_free(&error);
2436573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.design",
2446573Sphitran &error);
2456573Sphitran my_dbus_error_free(&error);
2466573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.last_full",
2476573Sphitran &error);
2486573Sphitran my_dbus_error_free(&error);
2496573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.unit",
2506573Sphitran &error);
2516573Sphitran my_dbus_error_free(&error);
2526573Sphitran libhal_device_remove_property(ctx, udi, "battery.technology", &error);
2536573Sphitran my_dbus_error_free(&error);
2546573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.technology",
2556573Sphitran &error);
2566573Sphitran my_dbus_error_free(&error);
2576573Sphitran libhal_device_remove_property(ctx, udi, "battery.serial", &error);
2586573Sphitran my_dbus_error_free(&error);
2596573Sphitran libhal_device_remove_property(ctx, udi, "battery.model", &error);
2606573Sphitran my_dbus_error_free(&error);
2616573Sphitran libhal_device_remove_property(ctx, udi, "battery.vendor", &error);
2626573Sphitran my_dbus_error_free(&error);
2636573Sphitran HAL_DEBUG(("battery_remove() exit"));
2646573Sphitran }
2656573Sphitran
2666573Sphitran static void
battery_last_full(LibHalChangeSet * cs,int fd)2676573Sphitran battery_last_full(LibHalChangeSet *cs, int fd)
2686573Sphitran {
2696573Sphitran acpi_bif_t bif;
2706573Sphitran
2716573Sphitran bzero(&bif, sizeof (bif));
2726573Sphitran if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) {
2736573Sphitran return;
2746573Sphitran }
2756573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting_last_full",
2766573Sphitran bif.bif_last_cap);
2776573Sphitran }
2786573Sphitran
2796573Sphitran static void
battery_dynamic_update(LibHalContext * ctx,const char * udi,int fd)2806573Sphitran battery_dynamic_update(LibHalContext *ctx, const char *udi, int fd)
2816573Sphitran {
2826573Sphitran int reporting_rate;
2836573Sphitran int reporting_current;
2846573Sphitran int reporting_lastfull;
2856573Sphitran int design_voltage;
2866573Sphitran int present_voltage;
2876573Sphitran char *reporting_unit;
2886573Sphitran int remaining_time;
2896573Sphitran int remaining_percentage;
2906573Sphitran gboolean charging;
2916573Sphitran gboolean discharging;
2926573Sphitran acpi_bst_t bst;
2936573Sphitran LibHalChangeSet *cs;
2946573Sphitran DBusError error;
2956573Sphitran static int counter = 0;
2966573Sphitran
2976573Sphitran HAL_DEBUG(("battery_dynamic_update() enter"));
2986573Sphitran bzero(&bst, sizeof (bst));
2996573Sphitran if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) {
3006573Sphitran return;
3016573Sphitran }
3026573Sphitran
3036573Sphitran charging = bst.bst_state & ACPI_DRV_BST_CHARGING ? TRUE : FALSE;
3046573Sphitran discharging = bst.bst_state & ACPI_DRV_BST_DISCHARGING ? TRUE : FALSE;
3056573Sphitran /* No need to continue if battery is essentially idle. */
3066573Sphitran if (counter && !charging && !discharging) {
3076573Sphitran return;
3086573Sphitran }
3096573Sphitran dbus_error_init(&error);
3106573Sphitran libhal_device_set_property_bool(ctx, udi, "battery.is_rechargeable",
3116573Sphitran TRUE, &error);
3126573Sphitran my_dbus_error_free(&error);
3136573Sphitran if (libhal_device_property_exists(ctx, udi,
3146573Sphitran "battery.charge_level.percentage", &error)) {
3156573Sphitran remaining_percentage = libhal_device_get_property_int(ctx, udi,
3166573Sphitran "battery.charge_level.percentage", &error);
3176573Sphitran if ((remaining_percentage == 100) && charging) {
3186573Sphitran charging = FALSE;
3196573Sphitran }
3206573Sphitran }
3216573Sphitran libhal_device_set_property_bool(ctx, udi,
3226573Sphitran "battery.rechargeable.is_charging", charging, &error);
3236573Sphitran my_dbus_error_free(&error);
3246573Sphitran libhal_device_set_property_bool(ctx, udi,
3256573Sphitran "battery.rechargeable.is_discharging", discharging, &error);
3266573Sphitran my_dbus_error_free(&error);
3276573Sphitran reporting_current = bst.bst_rem_cap;
3286573Sphitran libhal_device_set_property_int(ctx, udi, "battery.reporting.current",
3296573Sphitran bst.bst_rem_cap, &error);
3306573Sphitran my_dbus_error_free(&error);
3316573Sphitran reporting_rate = bst.bst_rate;
3326573Sphitran libhal_device_set_property_int(ctx, udi, "battery.reporting.rate",
3336573Sphitran bst.bst_rate, &error);
3346573Sphitran my_dbus_error_free(&error);
3356573Sphitran present_voltage = bst.bst_voltage;
3366573Sphitran libhal_device_set_property_int(ctx, udi, "battery.voltage.present",
3376573Sphitran bst.bst_voltage, &error);
3386573Sphitran /* get all the data we know */
3396573Sphitran my_dbus_error_free(&error);
3406573Sphitran reporting_unit = libhal_device_get_property_string(ctx, udi,
3416573Sphitran "battery.reporting.unit", &error);
3426573Sphitran my_dbus_error_free(&error);
3436573Sphitran reporting_lastfull = libhal_device_get_property_int(ctx, udi,
3446573Sphitran "battery.reporting.last_full", &error);
3456573Sphitran
3466573Sphitran /*
3476573Sphitran * Convert mAh to mWh since util_compute_time_remaining() works
3486573Sphitran * for mWh.
3496573Sphitran */
3506573Sphitran if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) {
3516573Sphitran my_dbus_error_free(&error);
3526573Sphitran design_voltage = libhal_device_get_property_int(ctx, udi,
3536573Sphitran "battery.voltage.design", &error);
3546573Sphitran /*
3556573Sphitran * If the present_voltage is inaccurate, set it to the
3566573Sphitran * design_voltage.
3576573Sphitran */
3586573Sphitran if (((present_voltage * 10) < design_voltage) ||
3596573Sphitran (present_voltage <= 0) ||
3606573Sphitran (present_voltage > design_voltage)) {
3616573Sphitran present_voltage = design_voltage;
3626573Sphitran }
3636573Sphitran reporting_rate = (reporting_rate * present_voltage) / 1000;
3646573Sphitran reporting_lastfull = (reporting_lastfull * present_voltage) /
3656573Sphitran 1000;
3666573Sphitran reporting_current = (reporting_current * present_voltage) /
3676573Sphitran 1000;
3686573Sphitran }
3696573Sphitran
3706573Sphitran /* Make sure the current charge does not exceed the full charge */
3716573Sphitran if (reporting_current > reporting_lastfull) {
3726573Sphitran reporting_current = reporting_lastfull;
3736573Sphitran }
3746573Sphitran if (!charging && !discharging) {
3756573Sphitran counter++;
3766573Sphitran reporting_rate = 0;
3776573Sphitran }
3786573Sphitran
3796573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) {
3806573Sphitran HAL_DEBUG(("Cannot allocate changeset"));
3816573Sphitran libhal_free_string(reporting_unit);
3826573Sphitran my_dbus_error_free(&error);
3836573Sphitran return;
3846573Sphitran }
3856573Sphitran
3866573Sphitran libhal_changeset_set_property_int(cs, "battery.charge_level.rate",
3876573Sphitran reporting_rate);
3886573Sphitran libhal_changeset_set_property_int(cs,
3896573Sphitran "battery.charge_level.last_full", reporting_lastfull);
3906573Sphitran libhal_changeset_set_property_int(cs,
3916573Sphitran "battery.charge_level.current", reporting_current);
3926573Sphitran
3936573Sphitran remaining_percentage = util_compute_percentage_charge(udi,
3946573Sphitran reporting_current, reporting_lastfull);
3956573Sphitran remaining_time = util_compute_time_remaining(udi, reporting_rate,
3966573Sphitran reporting_current, reporting_lastfull, discharging, charging, 0);
3976573Sphitran /*
3986573Sphitran * Some batteries give bad remaining_time estimates relative to
3996573Sphitran * the charge level.
4006573Sphitran */
4016573Sphitran if (charging && ((remaining_time < 30) || ((remaining_time < 300) &&
4026573Sphitran (remaining_percentage < 95)) || (remaining_percentage > 97))) {
4036573Sphitran remaining_time = util_compute_time_remaining(udi,
4046573Sphitran reporting_rate, reporting_current, reporting_lastfull,
4056573Sphitran discharging, charging, 1);
4066573Sphitran }
4076573Sphitran
4086573Sphitran if (remaining_percentage > 0) {
4096573Sphitran libhal_changeset_set_property_int(cs,
4106573Sphitran "battery.charge_level.percentage", remaining_percentage);
4116573Sphitran } else {
4126573Sphitran my_dbus_error_free(&error);
4136573Sphitran libhal_device_remove_property(ctx, udi,
4146573Sphitran "battery.charge_level.percentage", &error);
4156573Sphitran }
4166573Sphitran if ((remaining_percentage == 100) && charging) {
4176573Sphitran battery_last_full(cs, fd);
4186573Sphitran }
4196573Sphitran /*
4206573Sphitran * remaining_percentage is more accurate so we handle cases
4216573Sphitran * where the remaining_time cannot be correct.
4226573Sphitran */
4236573Sphitran if ((!charging && !discharging) || ((remaining_percentage == 100) &&
4246573Sphitran !discharging)) {
4256573Sphitran remaining_time = 0;
4266573Sphitran }
4276573Sphitran if (remaining_time < 0) {
4286573Sphitran my_dbus_error_free(&error);
4296573Sphitran libhal_device_remove_property(ctx, udi,
4306573Sphitran "battery.remaining_time", &error);
4316573Sphitran } else if (remaining_time >= 0) {
4326573Sphitran libhal_changeset_set_property_int(cs,
4336573Sphitran "battery.remaining_time", remaining_time);
4346573Sphitran }
4356573Sphitran
4366573Sphitran my_dbus_error_free(&error);
4376573Sphitran libhal_device_commit_changeset(ctx, cs, &error);
4386573Sphitran libhal_device_free_changeset(cs);
4396573Sphitran libhal_free_string(reporting_unit);
4406573Sphitran my_dbus_error_free(&error);
4416573Sphitran HAL_DEBUG(("battery_dynamic_update() exit"));
4426573Sphitran }
4436573Sphitran
4446573Sphitran static gboolean
battery_static_update(LibHalContext * ctx,const char * udi,int fd)4456573Sphitran battery_static_update(LibHalContext *ctx, const char *udi, int fd)
4466573Sphitran {
4476573Sphitran const char *technology;
4486573Sphitran int reporting_design;
4496573Sphitran int reporting_warning;
4506573Sphitran int reporting_low;
4516573Sphitran int reporting_gran1;
4526573Sphitran int reporting_gran2;
4536573Sphitran int voltage_design;
4546573Sphitran char reporting_unit[10];
4556573Sphitran acpi_bif_t bif;
4566573Sphitran LibHalChangeSet *cs;
4576573Sphitran DBusError error;
4586573Sphitran
4596573Sphitran HAL_DEBUG(("battery_static_update() enter"));
4606573Sphitran bzero(&bif, sizeof (bif));
4616573Sphitran if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) {
4626573Sphitran return (FALSE);
4636573Sphitran }
4646573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) {
4656573Sphitran HAL_DEBUG(("Cannot allocate changeset"));
4666573Sphitran return (FALSE);
4676573Sphitran }
4686573Sphitran
4696573Sphitran libhal_changeset_set_property_string(cs, "battery.vendor",
4706573Sphitran bif.bif_oem_info);
4716573Sphitran technology = bif.bif_type;
4726573Sphitran if (technology != NULL) {
4736573Sphitran libhal_changeset_set_property_string(cs,
4746573Sphitran "battery.reporting.technology", technology);
4756573Sphitran libhal_changeset_set_property_string(cs, "battery.technology",
4766573Sphitran util_get_battery_technology(technology));
4776573Sphitran }
4786573Sphitran libhal_changeset_set_property_string(cs, "battery.serial",
4796573Sphitran bif.bif_serial);
4806573Sphitran libhal_changeset_set_property_string(cs, "battery.model",
4816573Sphitran bif.bif_model);
4826573Sphitran
4836573Sphitran if (bif.bif_unit) {
4846573Sphitran libhal_changeset_set_property_string(cs,
4856573Sphitran "battery.reporting.unit", "mAh");
4866573Sphitran strlcpy(reporting_unit, "mAh", sizeof (reporting_unit));
4876573Sphitran } else {
4886573Sphitran libhal_changeset_set_property_string(cs,
4896573Sphitran "battery.reporting.unit", "mWh");
4906573Sphitran strlcpy(reporting_unit, "mWh", sizeof (reporting_unit));
4916573Sphitran }
4926573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.last_full",
4936573Sphitran bif.bif_last_cap);
4946573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.design",
4956573Sphitran bif.bif_design_cap);
4966573Sphitran reporting_design = bif.bif_design_cap;
4976573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.warning",
4986573Sphitran bif.bif_warn_cap);
4996573Sphitran reporting_warning = bif.bif_warn_cap;
5006573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.low",
5016573Sphitran bif.bif_low_cap);
5026573Sphitran reporting_low = bif.bif_low_cap;
5036573Sphitran libhal_changeset_set_property_int(cs,
5046573Sphitran "battery.reporting.granularity_1", bif.bif_gran1_cap);
5056573Sphitran reporting_gran1 = bif.bif_gran1_cap;
5066573Sphitran libhal_changeset_set_property_int(cs,
5076573Sphitran "battery.reporting.granularity_2", bif.bif_gran2_cap);
5086573Sphitran reporting_gran2 = bif.bif_gran2_cap;
5096573Sphitran libhal_changeset_set_property_int(cs, "battery.voltage.design",
5106573Sphitran bif.bif_voltage);
5116573Sphitran voltage_design = bif.bif_voltage;
5126573Sphitran
5136573Sphitran if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) {
5146573Sphitran /* convert to mWh */
5156573Sphitran libhal_changeset_set_property_string(cs,
5166573Sphitran "battery.charge_level.unit", "mWh");
5176573Sphitran libhal_changeset_set_property_int(cs,
5186573Sphitran "battery.charge_level.design",
5196573Sphitran (reporting_design * voltage_design) / 1000);
5206573Sphitran libhal_changeset_set_property_int(cs,
5216573Sphitran "battery.charge_level.warning",
5226573Sphitran (reporting_warning * voltage_design) / 1000);
5236573Sphitran libhal_changeset_set_property_int(cs,
5246573Sphitran "battery.charge_level.low",
5256573Sphitran (reporting_low * voltage_design) / 1000);
5266573Sphitran libhal_changeset_set_property_int(cs,
5276573Sphitran "battery.charge_level.granularity_1",
5286573Sphitran (reporting_gran1 * voltage_design) / 1000);
5296573Sphitran libhal_changeset_set_property_int(cs,
5306573Sphitran "battery.charge_level.granularity_2",
5316573Sphitran (reporting_gran2 * voltage_design) / 1000);
5326573Sphitran } else {
5336573Sphitran if (reporting_unit && strcmp(reporting_unit, "mWh") == 0) {
5346573Sphitran libhal_changeset_set_property_string(cs,
5356573Sphitran "battery.charge_level.unit", "mWh");
5366573Sphitran }
5376573Sphitran libhal_changeset_set_property_int(cs,
5386573Sphitran "battery.charge_level.design", reporting_design);
5396573Sphitran libhal_changeset_set_property_int(cs,
5406573Sphitran "battery.charge_level.warning", reporting_warning);
5416573Sphitran libhal_changeset_set_property_int(cs,
5426573Sphitran "battery.charge_level.low", reporting_low);
5436573Sphitran libhal_changeset_set_property_int(cs,
5446573Sphitran "battery.charge_level.granularity_1", reporting_gran1);
5456573Sphitran libhal_changeset_set_property_int(cs,
5466573Sphitran "battery.charge_level.granularity_2", reporting_gran2);
5476573Sphitran }
5486573Sphitran
5496573Sphitran
5506573Sphitran dbus_error_init(&error);
5516573Sphitran libhal_device_commit_changeset(ctx, cs, &error);
5526573Sphitran libhal_device_free_changeset(cs);
5536573Sphitran my_dbus_error_free(&error);
5546573Sphitran HAL_DEBUG(("battery_static_update() exit"));
5556573Sphitran return (TRUE);
5566573Sphitran }
5576573Sphitran
5586573Sphitran gboolean
battery_update(LibHalContext * ctx,const char * udi,int fd)5596573Sphitran battery_update(LibHalContext *ctx, const char *udi, int fd)
5606573Sphitran {
5616573Sphitran acpi_bst_t bst;
5626573Sphitran DBusError error;
5636573Sphitran
5646573Sphitran HAL_DEBUG(("battery_update() enter"));
5656573Sphitran dbus_error_init(&error);
5666573Sphitran libhal_device_set_property_string(ctx, udi, "info.product",
5676573Sphitran "Battery Bay", &error);
5686573Sphitran my_dbus_error_free(&error);
5696573Sphitran libhal_device_set_property_string(ctx, udi, "info.category", "battery",
5706573Sphitran &error);
5716573Sphitran
5726573Sphitran bzero(&bst, sizeof (bst));
5736573Sphitran if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) {
5746573Sphitran if (errno == ENXIO) {
5756573Sphitran my_dbus_error_free(&error);
5766573Sphitran libhal_device_set_property_bool(ctx, udi,
5776573Sphitran "battery.present", FALSE, &error);
5786573Sphitran } else {
5796573Sphitran my_dbus_error_free(&error);
5806573Sphitran return (FALSE);
5816573Sphitran }
5826573Sphitran } else {
5836573Sphitran my_dbus_error_free(&error);
5846573Sphitran libhal_device_set_property_bool(ctx, udi, "battery.present",
5856573Sphitran TRUE, &error);
5866573Sphitran }
5876573Sphitran
5886573Sphitran my_dbus_error_free(&error);
5896573Sphitran if (!libhal_device_get_property_bool(ctx, udi, "battery.present",
5906573Sphitran &error)) {
5916573Sphitran HAL_DEBUG(("battery_update(): battery is NOT present"));
5926573Sphitran battery_remove(ctx, udi);
5936573Sphitran } else {
5946573Sphitran HAL_DEBUG(("battery_update(): battery is present"));
5956573Sphitran my_dbus_error_free(&error);
5966573Sphitran libhal_device_set_property_string(ctx, udi, "battery.type",
5976573Sphitran "primary", &error);
5986573Sphitran my_dbus_error_free(&error);
5996573Sphitran libhal_device_add_capability(ctx, udi, "battery", &error);
6006573Sphitran my_dbus_error_free(&error);
6016573Sphitran if (libhal_device_get_property_type(ctx, udi, "battery.vendor",
6026573Sphitran &error) == LIBHAL_PROPERTY_TYPE_INVALID) {
6036573Sphitran battery_static_update(ctx, udi, fd);
6046573Sphitran }
6056573Sphitran battery_dynamic_update(ctx, udi, fd);
6066573Sphitran }
6076573Sphitran my_dbus_error_free(&error);
6086573Sphitran HAL_DEBUG(("battery_update() exit"));
6096573Sphitran return (TRUE);
6106573Sphitran }
6116573Sphitran
6126573Sphitran static gboolean
battery_update_all(LibHalContext * ctx)6136573Sphitran battery_update_all(LibHalContext *ctx)
6146573Sphitran {
6156573Sphitran int i;
6166573Sphitran int num_devices;
6176573Sphitran char **battery_devices;
6186573Sphitran int fd;
6196573Sphitran DBusError error;
6206573Sphitran
6216573Sphitran HAL_DEBUG(("battery_update_all() enter"));
6226573Sphitran
6236573Sphitran dbus_error_init(&error);
6246573Sphitran if ((battery_devices = libhal_manager_find_device_string_match
6256573Sphitran (ctx, "info.category", "battery", &num_devices, &error)) !=
6266573Sphitran NULL) {
6276573Sphitran for (i = 0; i < num_devices; i++) {
6286573Sphitran my_dbus_error_free(&error);
6296573Sphitran if (libhal_device_get_property_bool(ctx,
6306573Sphitran battery_devices[i], "battery.present", &error)) {
6316573Sphitran if ((fd = open_device(ctx,
6326573Sphitran battery_devices[i])) == -1) {
6336573Sphitran continue;
6346573Sphitran }
6356573Sphitran battery_dynamic_update(ctx, battery_devices[i],
6366573Sphitran fd);
6376573Sphitran close(fd);
6386573Sphitran }
6396573Sphitran }
6406573Sphitran libhal_free_string_array(battery_devices);
6416573Sphitran }
6426573Sphitran my_dbus_error_free(&error);
6436573Sphitran HAL_DEBUG(("battery_update_all() exit"));
6446573Sphitran return (TRUE);
6456573Sphitran }
6466573Sphitran
6476573Sphitran gboolean
ac_adapter_update(LibHalContext * ctx,const char * udi,int fd)6486573Sphitran ac_adapter_update(LibHalContext *ctx, const char *udi, int fd)
6496573Sphitran {
6506573Sphitran LibHalChangeSet *cs;
6516573Sphitran DBusError error;
6526573Sphitran
6536573Sphitran HAL_DEBUG(("ac_adapter_update() enter"));
6546573Sphitran dbus_error_init(&error);
6556573Sphitran if (!libhal_device_query_capability(ctx, udi, "ac_adapter", &error)) {
6566573Sphitran my_dbus_error_free(&error);
6576573Sphitran libhal_device_add_capability(ctx, udi, "ac_adapter", &error);
6586573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) {
6596573Sphitran my_dbus_error_free(&error);
6606573Sphitran return (FALSE);
6616573Sphitran }
6626573Sphitran libhal_changeset_set_property_string(cs, "info.product",
6636573Sphitran "AC Adapter");
6646573Sphitran libhal_changeset_set_property_string(cs, "info.category",
6656573Sphitran "ac_adapter");
6666573Sphitran my_dbus_error_free(&error);
6676573Sphitran libhal_device_commit_changeset(ctx, cs, &error);
6686573Sphitran libhal_device_free_changeset(cs);
6696573Sphitran }
6706573Sphitran ac_adapter_present(ctx, udi, fd);
6716573Sphitran battery_update_all(ctx);
6726573Sphitran
6736573Sphitran my_dbus_error_free(&error);
6746573Sphitran HAL_DEBUG(("ac_adapter_update() exit"));
6756573Sphitran return (TRUE);
6766573Sphitran }
6776573Sphitran
6786573Sphitran static gboolean
ac_adapter_update_all(LibHalContext * ctx)6796573Sphitran ac_adapter_update_all(LibHalContext *ctx)
6806573Sphitran {
6816573Sphitran int i;
6826573Sphitran int num_devices;
6836573Sphitran char **ac_adapter_devices;
6846573Sphitran int fd;
6856573Sphitran DBusError error;
6866573Sphitran
6876573Sphitran HAL_DEBUG(("ac_adapter_update_all() enter"));
6886573Sphitran dbus_error_init(&error);
6896573Sphitran if ((ac_adapter_devices = libhal_manager_find_device_string_match(
6906573Sphitran ctx, "info.category", "ac_adapter", &num_devices, &error)) !=
6916573Sphitran NULL) {
6926573Sphitran for (i = 0; i < num_devices; i++) {
6936573Sphitran if ((fd = open_device(ctx, ac_adapter_devices[i]))
6946573Sphitran == -1) {
6956573Sphitran continue;
6966573Sphitran }
6976573Sphitran ac_adapter_present(ctx, ac_adapter_devices[i], fd);
6986573Sphitran close(fd);
6996573Sphitran }
7006573Sphitran libhal_free_string_array(ac_adapter_devices);
7016573Sphitran }
7026573Sphitran my_dbus_error_free(&error);
7036573Sphitran HAL_DEBUG(("ac_adapter_update_all() exit"));
7046573Sphitran return (TRUE);
7056573Sphitran }
7066573Sphitran
7076573Sphitran gboolean
update_devices(gpointer data)7086573Sphitran update_devices(gpointer data)
7096573Sphitran {
7106573Sphitran LibHalContext *ctx = (LibHalContext *)data;
7116573Sphitran
7126573Sphitran HAL_DEBUG(("update_devices() enter"));
7136573Sphitran ac_adapter_update_all(ctx);
7146573Sphitran battery_update_all(ctx);
7156573Sphitran HAL_DEBUG(("update_devices() exit"));
7166573Sphitran return (TRUE);
7176573Sphitran }
7186573Sphitran
7196573Sphitran int
open_device(LibHalContext * ctx,char * udi)7206573Sphitran open_device(LibHalContext *ctx, char *udi)
7216573Sphitran {
7226573Sphitran char path[HAL_PATH_MAX] = "/devices";
7236573Sphitran char *devfs_path;
7246573Sphitran DBusError error;
7256573Sphitran
7266573Sphitran dbus_error_init(&error);
7276573Sphitran devfs_path = libhal_device_get_property_string(ctx, udi,
7286573Sphitran "solaris.devfs_path", &error);
7296573Sphitran my_dbus_error_free(&error);
7306573Sphitran if (devfs_path == NULL) {
7316573Sphitran return (-1);
7326573Sphitran }
7336573Sphitran strlcat(path, devfs_path, HAL_PATH_MAX);
7346573Sphitran libhal_free_string(devfs_path);
7356573Sphitran return (open(path, O_RDONLY | O_NONBLOCK));
7366573Sphitran }
737