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