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