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 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 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 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 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 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 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 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 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 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 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 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 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 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 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