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