1*6573Sphitran /*************************************************************************** 2*6573Sphitran * 3*6573Sphitran * acpi.c : Main routines for setting battery, AC adapter, and lid properties 4*6573Sphitran * 5*6573Sphitran * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 6*6573Sphitran * Use is subject to license terms. 7*6573Sphitran * 8*6573Sphitran * Licensed under the Academic Free License version 2.1 9*6573Sphitran * 10*6573Sphitran **************************************************************************/ 11*6573Sphitran 12*6573Sphitran #pragma ident "%Z%%M% %I% %E% SMI" 13*6573Sphitran 14*6573Sphitran #ifdef HAVE_CONFIG_H 15*6573Sphitran #include <config.h> 16*6573Sphitran #endif 17*6573Sphitran 18*6573Sphitran #include <unistd.h> 19*6573Sphitran #include <strings.h> 20*6573Sphitran #include <string.h> 21*6573Sphitran #include <kstat.h> 22*6573Sphitran #include <fcntl.h> 23*6573Sphitran #include <errno.h> 24*6573Sphitran #include <sys/acpi_drv.h> 25*6573Sphitran 26*6573Sphitran #include <libhal.h> 27*6573Sphitran #include "../hald/device_info.h" 28*6573Sphitran #include "../hald/hald_dbus.h" 29*6573Sphitran #include "../hald/logger.h" 30*6573Sphitran #include "../hald/util_pm.h" 31*6573Sphitran #include "acpi.h" 32*6573Sphitran 33*6573Sphitran 34*6573Sphitran static void 35*6573Sphitran my_dbus_error_free(DBusError *error) 36*6573Sphitran { 37*6573Sphitran if (dbus_error_is_set(error)) { 38*6573Sphitran dbus_error_free(error); 39*6573Sphitran } 40*6573Sphitran } 41*6573Sphitran 42*6573Sphitran gboolean 43*6573Sphitran laptop_panel_update(LibHalContext *ctx, const char *udi, int fd) 44*6573Sphitran { 45*6573Sphitran LibHalChangeSet *cs; 46*6573Sphitran DBusError error; 47*6573Sphitran struct acpi_drv_output_info inf; 48*6573Sphitran 49*6573Sphitran HAL_DEBUG(("laptop_panel_update() enter")); 50*6573Sphitran 51*6573Sphitran dbus_error_init(&error); 52*6573Sphitran if (!libhal_device_query_capability(ctx, udi, "laptop_panel", &error)) { 53*6573Sphitran bzero(&inf, sizeof (inf)); 54*6573Sphitran if ((ioctl(fd, ACPI_DRV_IOC_INFO, &inf) < 0) || 55*6573Sphitran (inf.nlev == 0)) { 56*6573Sphitran return (FALSE); 57*6573Sphitran } 58*6573Sphitran 59*6573Sphitran my_dbus_error_free(&error); 60*6573Sphitran libhal_device_add_capability(ctx, udi, "laptop_panel", &error); 61*6573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) { 62*6573Sphitran my_dbus_error_free(&error); 63*6573Sphitran return (FALSE); 64*6573Sphitran } 65*6573Sphitran libhal_changeset_set_property_string(cs, "info.product", 66*6573Sphitran "Generic Backlight Device"); 67*6573Sphitran libhal_changeset_set_property_string(cs, "info.category", 68*6573Sphitran "laptop_panel"); 69*6573Sphitran libhal_changeset_set_property_int(cs, "laptop_panel.num_levels", 70*6573Sphitran inf.nlev); 71*6573Sphitran my_dbus_error_free(&error); 72*6573Sphitran libhal_device_commit_changeset(ctx, cs, &error); 73*6573Sphitran libhal_device_free_changeset(cs); 74*6573Sphitran } 75*6573Sphitran my_dbus_error_free(&error); 76*6573Sphitran HAL_DEBUG(("ac_adapter_present() exit")); 77*6573Sphitran return (TRUE); 78*6573Sphitran } 79*6573Sphitran 80*6573Sphitran gboolean 81*6573Sphitran lid_update(LibHalContext *ctx, const char *udi, int fd) 82*6573Sphitran { 83*6573Sphitran LibHalChangeSet *cs; 84*6573Sphitran DBusError error; 85*6573Sphitran 86*6573Sphitran HAL_DEBUG(("lid_update() enter")); 87*6573Sphitran 88*6573Sphitran dbus_error_init(&error); 89*6573Sphitran if (!libhal_device_query_capability(ctx, udi, "button", &error)) { 90*6573Sphitran my_dbus_error_free(&error); 91*6573Sphitran libhal_device_add_capability(ctx, udi, "button", &error); 92*6573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) { 93*6573Sphitran my_dbus_error_free(&error); 94*6573Sphitran return (FALSE); 95*6573Sphitran } 96*6573Sphitran libhal_changeset_set_property_bool(cs, "button.has_state", 97*6573Sphitran TRUE); 98*6573Sphitran libhal_changeset_set_property_bool(cs, "button.state.value", 99*6573Sphitran FALSE); 100*6573Sphitran libhal_changeset_set_property_string(cs, "button.type", 101*6573Sphitran "lid"); 102*6573Sphitran libhal_changeset_set_property_string(cs, "info.product", 103*6573Sphitran "Lid Switch"); 104*6573Sphitran libhal_changeset_set_property_string(cs, "info.category", 105*6573Sphitran "button"); 106*6573Sphitran my_dbus_error_free(&error); 107*6573Sphitran libhal_device_commit_changeset(ctx, cs, &error); 108*6573Sphitran libhal_device_free_changeset(cs); 109*6573Sphitran } 110*6573Sphitran my_dbus_error_free(&error); 111*6573Sphitran HAL_DEBUG(("update_lid() exit")); 112*6573Sphitran return (TRUE); 113*6573Sphitran } 114*6573Sphitran 115*6573Sphitran static void 116*6573Sphitran ac_adapter_present(LibHalContext *ctx, const char *udi, int fd) 117*6573Sphitran { 118*6573Sphitran int pow; 119*6573Sphitran LibHalChangeSet *cs; 120*6573Sphitran DBusError error; 121*6573Sphitran 122*6573Sphitran HAL_DEBUG(("ac_adapter_present() enter")); 123*6573Sphitran if (ioctl(fd, ACPI_DRV_IOC_POWER_STATUS, &pow) < 0) { 124*6573Sphitran return; 125*6573Sphitran } 126*6573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) { 127*6573Sphitran return; 128*6573Sphitran } 129*6573Sphitran if (pow > 0) { 130*6573Sphitran libhal_changeset_set_property_bool(cs, "ac_adapter.present", 131*6573Sphitran TRUE); 132*6573Sphitran } else { 133*6573Sphitran libhal_changeset_set_property_bool(cs, "ac_adapter.present", 134*6573Sphitran FALSE); 135*6573Sphitran } 136*6573Sphitran 137*6573Sphitran dbus_error_init(&error); 138*6573Sphitran libhal_device_commit_changeset(ctx, cs, &error); 139*6573Sphitran libhal_device_free_changeset(cs); 140*6573Sphitran my_dbus_error_free(&error); 141*6573Sphitran HAL_DEBUG(("ac_adapter_present() exit")); 142*6573Sphitran } 143*6573Sphitran 144*6573Sphitran static void 145*6573Sphitran battery_remove(LibHalContext *ctx, const char *udi) 146*6573Sphitran { 147*6573Sphitran DBusError error; 148*6573Sphitran 149*6573Sphitran HAL_DEBUG(("battery_remove() enter")); 150*6573Sphitran dbus_error_init(&error); 151*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.remaining_time", 152*6573Sphitran &error); 153*6573Sphitran my_dbus_error_free(&error); 154*6573Sphitran libhal_device_remove_property(ctx, udi, 155*6573Sphitran "battery.charge_level.percentage", &error); 156*6573Sphitran my_dbus_error_free(&error); 157*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.rate", 158*6573Sphitran &error); 159*6573Sphitran my_dbus_error_free(&error); 160*6573Sphitran libhal_device_remove_property(ctx, udi, 161*6573Sphitran "battery.charge_level.last_full", &error); 162*6573Sphitran my_dbus_error_free(&error); 163*6573Sphitran libhal_device_remove_property(ctx, udi, 164*6573Sphitran "battery.charge_level.current", &error); 165*6573Sphitran my_dbus_error_free(&error); 166*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.voltage.present", 167*6573Sphitran &error); 168*6573Sphitran my_dbus_error_free(&error); 169*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.rate", 170*6573Sphitran &error); 171*6573Sphitran my_dbus_error_free(&error); 172*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.current", 173*6573Sphitran &error); 174*6573Sphitran my_dbus_error_free(&error); 175*6573Sphitran libhal_device_remove_property(ctx, udi, 176*6573Sphitran "battery.rechargeable.is_discharging", &error); 177*6573Sphitran my_dbus_error_free(&error); 178*6573Sphitran libhal_device_remove_property(ctx, udi, 179*6573Sphitran "battery.rechargeable.is_charging", &error); 180*6573Sphitran my_dbus_error_free(&error); 181*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.is_rechargeable", 182*6573Sphitran &error); 183*6573Sphitran my_dbus_error_free(&error); 184*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.unit", 185*6573Sphitran &error); 186*6573Sphitran my_dbus_error_free(&error); 187*6573Sphitran libhal_device_remove_property(ctx, udi, 188*6573Sphitran "battery.charge_level.granularity_2", &error); 189*6573Sphitran my_dbus_error_free(&error); 190*6573Sphitran libhal_device_remove_property(ctx, udi, 191*6573Sphitran "battery.charge_level.granularity_1", &error); 192*6573Sphitran my_dbus_error_free(&error); 193*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.low", 194*6573Sphitran &error); 195*6573Sphitran my_dbus_error_free(&error); 196*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.warning", 197*6573Sphitran &error); 198*6573Sphitran my_dbus_error_free(&error); 199*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.charge_level.design", 200*6573Sphitran &error); 201*6573Sphitran my_dbus_error_free(&error); 202*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.voltage.design", 203*6573Sphitran &error); 204*6573Sphitran my_dbus_error_free(&error); 205*6573Sphitran libhal_device_remove_property(ctx, udi, 206*6573Sphitran "battery.reporting.granularity_2", &error); 207*6573Sphitran my_dbus_error_free(&error); 208*6573Sphitran libhal_device_remove_property(ctx, udi, 209*6573Sphitran "battery.reporting.granularity_1", &error); 210*6573Sphitran my_dbus_error_free(&error); 211*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.low", 212*6573Sphitran &error); 213*6573Sphitran my_dbus_error_free(&error); 214*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.warning", 215*6573Sphitran &error); 216*6573Sphitran my_dbus_error_free(&error); 217*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.design", 218*6573Sphitran &error); 219*6573Sphitran my_dbus_error_free(&error); 220*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.last_full", 221*6573Sphitran &error); 222*6573Sphitran my_dbus_error_free(&error); 223*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.unit", 224*6573Sphitran &error); 225*6573Sphitran my_dbus_error_free(&error); 226*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.technology", &error); 227*6573Sphitran my_dbus_error_free(&error); 228*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.reporting.technology", 229*6573Sphitran &error); 230*6573Sphitran my_dbus_error_free(&error); 231*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.serial", &error); 232*6573Sphitran my_dbus_error_free(&error); 233*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.model", &error); 234*6573Sphitran my_dbus_error_free(&error); 235*6573Sphitran libhal_device_remove_property(ctx, udi, "battery.vendor", &error); 236*6573Sphitran my_dbus_error_free(&error); 237*6573Sphitran HAL_DEBUG(("battery_remove() exit")); 238*6573Sphitran } 239*6573Sphitran 240*6573Sphitran static void 241*6573Sphitran battery_last_full(LibHalChangeSet *cs, int fd) 242*6573Sphitran { 243*6573Sphitran acpi_bif_t bif; 244*6573Sphitran 245*6573Sphitran bzero(&bif, sizeof (bif)); 246*6573Sphitran if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) { 247*6573Sphitran return; 248*6573Sphitran } 249*6573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting_last_full", 250*6573Sphitran bif.bif_last_cap); 251*6573Sphitran } 252*6573Sphitran 253*6573Sphitran static void 254*6573Sphitran battery_dynamic_update(LibHalContext *ctx, const char *udi, int fd) 255*6573Sphitran { 256*6573Sphitran int reporting_rate; 257*6573Sphitran int reporting_current; 258*6573Sphitran int reporting_lastfull; 259*6573Sphitran int design_voltage; 260*6573Sphitran int present_voltage; 261*6573Sphitran char *reporting_unit; 262*6573Sphitran int remaining_time; 263*6573Sphitran int remaining_percentage; 264*6573Sphitran gboolean charging; 265*6573Sphitran gboolean discharging; 266*6573Sphitran acpi_bst_t bst; 267*6573Sphitran LibHalChangeSet *cs; 268*6573Sphitran DBusError error; 269*6573Sphitran static int counter = 0; 270*6573Sphitran 271*6573Sphitran HAL_DEBUG(("battery_dynamic_update() enter")); 272*6573Sphitran bzero(&bst, sizeof (bst)); 273*6573Sphitran if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) { 274*6573Sphitran return; 275*6573Sphitran } 276*6573Sphitran 277*6573Sphitran charging = bst.bst_state & ACPI_DRV_BST_CHARGING ? TRUE : FALSE; 278*6573Sphitran discharging = bst.bst_state & ACPI_DRV_BST_DISCHARGING ? TRUE : FALSE; 279*6573Sphitran /* No need to continue if battery is essentially idle. */ 280*6573Sphitran if (counter && !charging && !discharging) { 281*6573Sphitran return; 282*6573Sphitran } 283*6573Sphitran dbus_error_init(&error); 284*6573Sphitran libhal_device_set_property_bool(ctx, udi, "battery.is_rechargeable", 285*6573Sphitran TRUE, &error); 286*6573Sphitran my_dbus_error_free(&error); 287*6573Sphitran if (libhal_device_property_exists(ctx, udi, 288*6573Sphitran "battery.charge_level.percentage", &error)) { 289*6573Sphitran remaining_percentage = libhal_device_get_property_int(ctx, udi, 290*6573Sphitran "battery.charge_level.percentage", &error); 291*6573Sphitran if ((remaining_percentage == 100) && charging) { 292*6573Sphitran charging = FALSE; 293*6573Sphitran } 294*6573Sphitran } 295*6573Sphitran libhal_device_set_property_bool(ctx, udi, 296*6573Sphitran "battery.rechargeable.is_charging", charging, &error); 297*6573Sphitran my_dbus_error_free(&error); 298*6573Sphitran libhal_device_set_property_bool(ctx, udi, 299*6573Sphitran "battery.rechargeable.is_discharging", discharging, &error); 300*6573Sphitran my_dbus_error_free(&error); 301*6573Sphitran reporting_current = bst.bst_rem_cap; 302*6573Sphitran libhal_device_set_property_int(ctx, udi, "battery.reporting.current", 303*6573Sphitran bst.bst_rem_cap, &error); 304*6573Sphitran my_dbus_error_free(&error); 305*6573Sphitran reporting_rate = bst.bst_rate; 306*6573Sphitran libhal_device_set_property_int(ctx, udi, "battery.reporting.rate", 307*6573Sphitran bst.bst_rate, &error); 308*6573Sphitran my_dbus_error_free(&error); 309*6573Sphitran present_voltage = bst.bst_voltage; 310*6573Sphitran libhal_device_set_property_int(ctx, udi, "battery.voltage.present", 311*6573Sphitran bst.bst_voltage, &error); 312*6573Sphitran /* get all the data we know */ 313*6573Sphitran my_dbus_error_free(&error); 314*6573Sphitran reporting_unit = libhal_device_get_property_string(ctx, udi, 315*6573Sphitran "battery.reporting.unit", &error); 316*6573Sphitran my_dbus_error_free(&error); 317*6573Sphitran reporting_lastfull = libhal_device_get_property_int(ctx, udi, 318*6573Sphitran "battery.reporting.last_full", &error); 319*6573Sphitran 320*6573Sphitran /* 321*6573Sphitran * Convert mAh to mWh since util_compute_time_remaining() works 322*6573Sphitran * for mWh. 323*6573Sphitran */ 324*6573Sphitran if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) { 325*6573Sphitran my_dbus_error_free(&error); 326*6573Sphitran design_voltage = libhal_device_get_property_int(ctx, udi, 327*6573Sphitran "battery.voltage.design", &error); 328*6573Sphitran /* 329*6573Sphitran * If the present_voltage is inaccurate, set it to the 330*6573Sphitran * design_voltage. 331*6573Sphitran */ 332*6573Sphitran if (((present_voltage * 10) < design_voltage) || 333*6573Sphitran (present_voltage <= 0) || 334*6573Sphitran (present_voltage > design_voltage)) { 335*6573Sphitran present_voltage = design_voltage; 336*6573Sphitran } 337*6573Sphitran reporting_rate = (reporting_rate * present_voltage) / 1000; 338*6573Sphitran reporting_lastfull = (reporting_lastfull * present_voltage) / 339*6573Sphitran 1000; 340*6573Sphitran reporting_current = (reporting_current * present_voltage) / 341*6573Sphitran 1000; 342*6573Sphitran } 343*6573Sphitran 344*6573Sphitran /* Make sure the current charge does not exceed the full charge */ 345*6573Sphitran if (reporting_current > reporting_lastfull) { 346*6573Sphitran reporting_current = reporting_lastfull; 347*6573Sphitran } 348*6573Sphitran if (!charging && !discharging) { 349*6573Sphitran counter++; 350*6573Sphitran reporting_rate = 0; 351*6573Sphitran } 352*6573Sphitran 353*6573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) { 354*6573Sphitran HAL_DEBUG(("Cannot allocate changeset")); 355*6573Sphitran libhal_free_string(reporting_unit); 356*6573Sphitran my_dbus_error_free(&error); 357*6573Sphitran return; 358*6573Sphitran } 359*6573Sphitran 360*6573Sphitran libhal_changeset_set_property_int(cs, "battery.charge_level.rate", 361*6573Sphitran reporting_rate); 362*6573Sphitran libhal_changeset_set_property_int(cs, 363*6573Sphitran "battery.charge_level.last_full", reporting_lastfull); 364*6573Sphitran libhal_changeset_set_property_int(cs, 365*6573Sphitran "battery.charge_level.current", reporting_current); 366*6573Sphitran 367*6573Sphitran remaining_percentage = util_compute_percentage_charge(udi, 368*6573Sphitran reporting_current, reporting_lastfull); 369*6573Sphitran remaining_time = util_compute_time_remaining(udi, reporting_rate, 370*6573Sphitran reporting_current, reporting_lastfull, discharging, charging, 0); 371*6573Sphitran /* 372*6573Sphitran * Some batteries give bad remaining_time estimates relative to 373*6573Sphitran * the charge level. 374*6573Sphitran */ 375*6573Sphitran if (charging && ((remaining_time < 30) || ((remaining_time < 300) && 376*6573Sphitran (remaining_percentage < 95)) || (remaining_percentage > 97))) { 377*6573Sphitran remaining_time = util_compute_time_remaining(udi, 378*6573Sphitran reporting_rate, reporting_current, reporting_lastfull, 379*6573Sphitran discharging, charging, 1); 380*6573Sphitran } 381*6573Sphitran 382*6573Sphitran if (remaining_percentage > 0) { 383*6573Sphitran libhal_changeset_set_property_int(cs, 384*6573Sphitran "battery.charge_level.percentage", remaining_percentage); 385*6573Sphitran } else { 386*6573Sphitran my_dbus_error_free(&error); 387*6573Sphitran libhal_device_remove_property(ctx, udi, 388*6573Sphitran "battery.charge_level.percentage", &error); 389*6573Sphitran } 390*6573Sphitran if ((remaining_percentage == 100) && charging) { 391*6573Sphitran battery_last_full(cs, fd); 392*6573Sphitran } 393*6573Sphitran /* 394*6573Sphitran * remaining_percentage is more accurate so we handle cases 395*6573Sphitran * where the remaining_time cannot be correct. 396*6573Sphitran */ 397*6573Sphitran if ((!charging && !discharging) || ((remaining_percentage == 100) && 398*6573Sphitran !discharging)) { 399*6573Sphitran remaining_time = 0; 400*6573Sphitran } 401*6573Sphitran if (remaining_time < 0) { 402*6573Sphitran my_dbus_error_free(&error); 403*6573Sphitran libhal_device_remove_property(ctx, udi, 404*6573Sphitran "battery.remaining_time", &error); 405*6573Sphitran } else if (remaining_time >= 0) { 406*6573Sphitran libhal_changeset_set_property_int(cs, 407*6573Sphitran "battery.remaining_time", remaining_time); 408*6573Sphitran } 409*6573Sphitran 410*6573Sphitran my_dbus_error_free(&error); 411*6573Sphitran libhal_device_commit_changeset(ctx, cs, &error); 412*6573Sphitran libhal_device_free_changeset(cs); 413*6573Sphitran libhal_free_string(reporting_unit); 414*6573Sphitran my_dbus_error_free(&error); 415*6573Sphitran HAL_DEBUG(("battery_dynamic_update() exit")); 416*6573Sphitran } 417*6573Sphitran 418*6573Sphitran static gboolean 419*6573Sphitran battery_static_update(LibHalContext *ctx, const char *udi, int fd) 420*6573Sphitran { 421*6573Sphitran const char *technology; 422*6573Sphitran int reporting_design; 423*6573Sphitran int reporting_warning; 424*6573Sphitran int reporting_low; 425*6573Sphitran int reporting_gran1; 426*6573Sphitran int reporting_gran2; 427*6573Sphitran int voltage_design; 428*6573Sphitran char reporting_unit[10]; 429*6573Sphitran acpi_bif_t bif; 430*6573Sphitran LibHalChangeSet *cs; 431*6573Sphitran DBusError error; 432*6573Sphitran 433*6573Sphitran HAL_DEBUG(("battery_static_update() enter")); 434*6573Sphitran bzero(&bif, sizeof (bif)); 435*6573Sphitran if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) { 436*6573Sphitran return (FALSE); 437*6573Sphitran } 438*6573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) { 439*6573Sphitran HAL_DEBUG(("Cannot allocate changeset")); 440*6573Sphitran return (FALSE); 441*6573Sphitran } 442*6573Sphitran 443*6573Sphitran libhal_changeset_set_property_string(cs, "battery.vendor", 444*6573Sphitran bif.bif_oem_info); 445*6573Sphitran technology = bif.bif_type; 446*6573Sphitran if (technology != NULL) { 447*6573Sphitran libhal_changeset_set_property_string(cs, 448*6573Sphitran "battery.reporting.technology", technology); 449*6573Sphitran libhal_changeset_set_property_string(cs, "battery.technology", 450*6573Sphitran util_get_battery_technology(technology)); 451*6573Sphitran } 452*6573Sphitran libhal_changeset_set_property_string(cs, "battery.serial", 453*6573Sphitran bif.bif_serial); 454*6573Sphitran libhal_changeset_set_property_string(cs, "battery.model", 455*6573Sphitran bif.bif_model); 456*6573Sphitran 457*6573Sphitran if (bif.bif_unit) { 458*6573Sphitran libhal_changeset_set_property_string(cs, 459*6573Sphitran "battery.reporting.unit", "mAh"); 460*6573Sphitran strlcpy(reporting_unit, "mAh", sizeof (reporting_unit)); 461*6573Sphitran } else { 462*6573Sphitran libhal_changeset_set_property_string(cs, 463*6573Sphitran "battery.reporting.unit", "mWh"); 464*6573Sphitran strlcpy(reporting_unit, "mWh", sizeof (reporting_unit)); 465*6573Sphitran } 466*6573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.last_full", 467*6573Sphitran bif.bif_last_cap); 468*6573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.design", 469*6573Sphitran bif.bif_design_cap); 470*6573Sphitran reporting_design = bif.bif_design_cap; 471*6573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.warning", 472*6573Sphitran bif.bif_warn_cap); 473*6573Sphitran reporting_warning = bif.bif_warn_cap; 474*6573Sphitran libhal_changeset_set_property_int(cs, "battery.reporting.low", 475*6573Sphitran bif.bif_low_cap); 476*6573Sphitran reporting_low = bif.bif_low_cap; 477*6573Sphitran libhal_changeset_set_property_int(cs, 478*6573Sphitran "battery.reporting.granularity_1", bif.bif_gran1_cap); 479*6573Sphitran reporting_gran1 = bif.bif_gran1_cap; 480*6573Sphitran libhal_changeset_set_property_int(cs, 481*6573Sphitran "battery.reporting.granularity_2", bif.bif_gran2_cap); 482*6573Sphitran reporting_gran2 = bif.bif_gran2_cap; 483*6573Sphitran libhal_changeset_set_property_int(cs, "battery.voltage.design", 484*6573Sphitran bif.bif_voltage); 485*6573Sphitran voltage_design = bif.bif_voltage; 486*6573Sphitran 487*6573Sphitran if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) { 488*6573Sphitran /* convert to mWh */ 489*6573Sphitran libhal_changeset_set_property_string(cs, 490*6573Sphitran "battery.charge_level.unit", "mWh"); 491*6573Sphitran libhal_changeset_set_property_int(cs, 492*6573Sphitran "battery.charge_level.design", 493*6573Sphitran (reporting_design * voltage_design) / 1000); 494*6573Sphitran libhal_changeset_set_property_int(cs, 495*6573Sphitran "battery.charge_level.warning", 496*6573Sphitran (reporting_warning * voltage_design) / 1000); 497*6573Sphitran libhal_changeset_set_property_int(cs, 498*6573Sphitran "battery.charge_level.low", 499*6573Sphitran (reporting_low * voltage_design) / 1000); 500*6573Sphitran libhal_changeset_set_property_int(cs, 501*6573Sphitran "battery.charge_level.granularity_1", 502*6573Sphitran (reporting_gran1 * voltage_design) / 1000); 503*6573Sphitran libhal_changeset_set_property_int(cs, 504*6573Sphitran "battery.charge_level.granularity_2", 505*6573Sphitran (reporting_gran2 * voltage_design) / 1000); 506*6573Sphitran } else { 507*6573Sphitran if (reporting_unit && strcmp(reporting_unit, "mWh") == 0) { 508*6573Sphitran libhal_changeset_set_property_string(cs, 509*6573Sphitran "battery.charge_level.unit", "mWh"); 510*6573Sphitran } 511*6573Sphitran libhal_changeset_set_property_int(cs, 512*6573Sphitran "battery.charge_level.design", reporting_design); 513*6573Sphitran libhal_changeset_set_property_int(cs, 514*6573Sphitran "battery.charge_level.warning", reporting_warning); 515*6573Sphitran libhal_changeset_set_property_int(cs, 516*6573Sphitran "battery.charge_level.low", reporting_low); 517*6573Sphitran libhal_changeset_set_property_int(cs, 518*6573Sphitran "battery.charge_level.granularity_1", reporting_gran1); 519*6573Sphitran libhal_changeset_set_property_int(cs, 520*6573Sphitran "battery.charge_level.granularity_2", reporting_gran2); 521*6573Sphitran } 522*6573Sphitran 523*6573Sphitran 524*6573Sphitran dbus_error_init(&error); 525*6573Sphitran libhal_device_commit_changeset(ctx, cs, &error); 526*6573Sphitran libhal_device_free_changeset(cs); 527*6573Sphitran my_dbus_error_free(&error); 528*6573Sphitran HAL_DEBUG(("battery_static_update() exit")); 529*6573Sphitran return (TRUE); 530*6573Sphitran } 531*6573Sphitran 532*6573Sphitran gboolean 533*6573Sphitran battery_update(LibHalContext *ctx, const char *udi, int fd) 534*6573Sphitran { 535*6573Sphitran acpi_bst_t bst; 536*6573Sphitran DBusError error; 537*6573Sphitran 538*6573Sphitran HAL_DEBUG(("battery_update() enter")); 539*6573Sphitran dbus_error_init(&error); 540*6573Sphitran libhal_device_set_property_string(ctx, udi, "info.product", 541*6573Sphitran "Battery Bay", &error); 542*6573Sphitran my_dbus_error_free(&error); 543*6573Sphitran libhal_device_set_property_string(ctx, udi, "info.category", "battery", 544*6573Sphitran &error); 545*6573Sphitran 546*6573Sphitran bzero(&bst, sizeof (bst)); 547*6573Sphitran if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) { 548*6573Sphitran if (errno == ENXIO) { 549*6573Sphitran my_dbus_error_free(&error); 550*6573Sphitran libhal_device_set_property_bool(ctx, udi, 551*6573Sphitran "battery.present", FALSE, &error); 552*6573Sphitran } else { 553*6573Sphitran my_dbus_error_free(&error); 554*6573Sphitran return (FALSE); 555*6573Sphitran } 556*6573Sphitran } else { 557*6573Sphitran my_dbus_error_free(&error); 558*6573Sphitran libhal_device_set_property_bool(ctx, udi, "battery.present", 559*6573Sphitran TRUE, &error); 560*6573Sphitran } 561*6573Sphitran 562*6573Sphitran my_dbus_error_free(&error); 563*6573Sphitran if (!libhal_device_get_property_bool(ctx, udi, "battery.present", 564*6573Sphitran &error)) { 565*6573Sphitran HAL_DEBUG(("battery_update(): battery is NOT present")); 566*6573Sphitran battery_remove(ctx, udi); 567*6573Sphitran } else { 568*6573Sphitran HAL_DEBUG(("battery_update(): battery is present")); 569*6573Sphitran my_dbus_error_free(&error); 570*6573Sphitran libhal_device_set_property_string(ctx, udi, "battery.type", 571*6573Sphitran "primary", &error); 572*6573Sphitran my_dbus_error_free(&error); 573*6573Sphitran libhal_device_add_capability(ctx, udi, "battery", &error); 574*6573Sphitran my_dbus_error_free(&error); 575*6573Sphitran if (libhal_device_get_property_type(ctx, udi, "battery.vendor", 576*6573Sphitran &error) == LIBHAL_PROPERTY_TYPE_INVALID) { 577*6573Sphitran battery_static_update(ctx, udi, fd); 578*6573Sphitran } 579*6573Sphitran battery_dynamic_update(ctx, udi, fd); 580*6573Sphitran } 581*6573Sphitran my_dbus_error_free(&error); 582*6573Sphitran HAL_DEBUG(("battery_update() exit")); 583*6573Sphitran return (TRUE); 584*6573Sphitran } 585*6573Sphitran 586*6573Sphitran static gboolean 587*6573Sphitran battery_update_all(LibHalContext *ctx) 588*6573Sphitran { 589*6573Sphitran int i; 590*6573Sphitran int num_devices; 591*6573Sphitran char **battery_devices; 592*6573Sphitran int fd; 593*6573Sphitran DBusError error; 594*6573Sphitran 595*6573Sphitran HAL_DEBUG(("battery_update_all() enter")); 596*6573Sphitran 597*6573Sphitran dbus_error_init(&error); 598*6573Sphitran if ((battery_devices = libhal_manager_find_device_string_match 599*6573Sphitran (ctx, "info.category", "battery", &num_devices, &error)) != 600*6573Sphitran NULL) { 601*6573Sphitran for (i = 0; i < num_devices; i++) { 602*6573Sphitran my_dbus_error_free(&error); 603*6573Sphitran if (libhal_device_get_property_bool(ctx, 604*6573Sphitran battery_devices[i], "battery.present", &error)) { 605*6573Sphitran if ((fd = open_device(ctx, 606*6573Sphitran battery_devices[i])) == -1) { 607*6573Sphitran continue; 608*6573Sphitran } 609*6573Sphitran battery_dynamic_update(ctx, battery_devices[i], 610*6573Sphitran fd); 611*6573Sphitran close(fd); 612*6573Sphitran } 613*6573Sphitran } 614*6573Sphitran libhal_free_string_array(battery_devices); 615*6573Sphitran } 616*6573Sphitran my_dbus_error_free(&error); 617*6573Sphitran HAL_DEBUG(("battery_update_all() exit")); 618*6573Sphitran return (TRUE); 619*6573Sphitran } 620*6573Sphitran 621*6573Sphitran gboolean 622*6573Sphitran ac_adapter_update(LibHalContext *ctx, const char *udi, int fd) 623*6573Sphitran { 624*6573Sphitran LibHalChangeSet *cs; 625*6573Sphitran DBusError error; 626*6573Sphitran 627*6573Sphitran HAL_DEBUG(("ac_adapter_update() enter")); 628*6573Sphitran dbus_error_init(&error); 629*6573Sphitran if (!libhal_device_query_capability(ctx, udi, "ac_adapter", &error)) { 630*6573Sphitran my_dbus_error_free(&error); 631*6573Sphitran libhal_device_add_capability(ctx, udi, "ac_adapter", &error); 632*6573Sphitran if ((cs = libhal_device_new_changeset(udi)) == NULL) { 633*6573Sphitran my_dbus_error_free(&error); 634*6573Sphitran return (FALSE); 635*6573Sphitran } 636*6573Sphitran libhal_changeset_set_property_string(cs, "info.product", 637*6573Sphitran "AC Adapter"); 638*6573Sphitran libhal_changeset_set_property_string(cs, "info.category", 639*6573Sphitran "ac_adapter"); 640*6573Sphitran my_dbus_error_free(&error); 641*6573Sphitran libhal_device_commit_changeset(ctx, cs, &error); 642*6573Sphitran libhal_device_free_changeset(cs); 643*6573Sphitran } 644*6573Sphitran ac_adapter_present(ctx, udi, fd); 645*6573Sphitran battery_update_all(ctx); 646*6573Sphitran 647*6573Sphitran my_dbus_error_free(&error); 648*6573Sphitran HAL_DEBUG(("ac_adapter_update() exit")); 649*6573Sphitran return (TRUE); 650*6573Sphitran } 651*6573Sphitran 652*6573Sphitran static gboolean 653*6573Sphitran ac_adapter_update_all(LibHalContext *ctx) 654*6573Sphitran { 655*6573Sphitran int i; 656*6573Sphitran int num_devices; 657*6573Sphitran char **ac_adapter_devices; 658*6573Sphitran int fd; 659*6573Sphitran DBusError error; 660*6573Sphitran 661*6573Sphitran HAL_DEBUG(("ac_adapter_update_all() enter")); 662*6573Sphitran dbus_error_init(&error); 663*6573Sphitran if ((ac_adapter_devices = libhal_manager_find_device_string_match( 664*6573Sphitran ctx, "info.category", "ac_adapter", &num_devices, &error)) != 665*6573Sphitran NULL) { 666*6573Sphitran for (i = 0; i < num_devices; i++) { 667*6573Sphitran if ((fd = open_device(ctx, ac_adapter_devices[i])) 668*6573Sphitran == -1) { 669*6573Sphitran continue; 670*6573Sphitran } 671*6573Sphitran ac_adapter_present(ctx, ac_adapter_devices[i], fd); 672*6573Sphitran close(fd); 673*6573Sphitran } 674*6573Sphitran libhal_free_string_array(ac_adapter_devices); 675*6573Sphitran } 676*6573Sphitran my_dbus_error_free(&error); 677*6573Sphitran HAL_DEBUG(("ac_adapter_update_all() exit")); 678*6573Sphitran return (TRUE); 679*6573Sphitran } 680*6573Sphitran 681*6573Sphitran gboolean 682*6573Sphitran update_devices(gpointer data) 683*6573Sphitran { 684*6573Sphitran LibHalContext *ctx = (LibHalContext *)data; 685*6573Sphitran 686*6573Sphitran HAL_DEBUG(("update_devices() enter")); 687*6573Sphitran ac_adapter_update_all(ctx); 688*6573Sphitran battery_update_all(ctx); 689*6573Sphitran HAL_DEBUG(("update_devices() exit")); 690*6573Sphitran return (TRUE); 691*6573Sphitran } 692*6573Sphitran 693*6573Sphitran int 694*6573Sphitran open_device(LibHalContext *ctx, char *udi) 695*6573Sphitran { 696*6573Sphitran char path[HAL_PATH_MAX] = "/devices"; 697*6573Sphitran char *devfs_path; 698*6573Sphitran DBusError error; 699*6573Sphitran 700*6573Sphitran dbus_error_init(&error); 701*6573Sphitran devfs_path = libhal_device_get_property_string(ctx, udi, 702*6573Sphitran "solaris.devfs_path", &error); 703*6573Sphitran my_dbus_error_free(&error); 704*6573Sphitran if (devfs_path == NULL) { 705*6573Sphitran return (-1); 706*6573Sphitran } 707*6573Sphitran strlcat(path, devfs_path, HAL_PATH_MAX); 708*6573Sphitran libhal_free_string(devfs_path); 709*6573Sphitran return (open(path, O_RDONLY | O_NONBLOCK)); 710*6573Sphitran } 711