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