xref: /titanic_53/usr/src/cmd/hal/hald/device.c (revision 18c2aff776a775d34a4c9893a4c72e0434d68e36)
1*18c2aff7Sartem /***************************************************************************
2*18c2aff7Sartem  * CVSID: $Id$
3*18c2aff7Sartem  *
4*18c2aff7Sartem  * device.c : HalDevice methods
5*18c2aff7Sartem  *
6*18c2aff7Sartem  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7*18c2aff7Sartem  * Copyright (C) 2004 Novell, Inc.
8*18c2aff7Sartem  *
9*18c2aff7Sartem  * Licensed under the Academic Free License version 2.1
10*18c2aff7Sartem  *
11*18c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
12*18c2aff7Sartem  * it under the terms of the GNU General Public License as published by
13*18c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
14*18c2aff7Sartem  * (at your option) any later version.
15*18c2aff7Sartem  *
16*18c2aff7Sartem  * This program is distributed in the hope that it will be useful,
17*18c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*18c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19*18c2aff7Sartem  * GNU General Public License for more details.
20*18c2aff7Sartem  *
21*18c2aff7Sartem  * You should have received a copy of the GNU General Public License
22*18c2aff7Sartem  * along with this program; if not, write to the Free Software
23*18c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24*18c2aff7Sartem  *
25*18c2aff7Sartem  **************************************************************************/
26*18c2aff7Sartem 
27*18c2aff7Sartem #ifdef HAVE_CONFIG_H
28*18c2aff7Sartem #  include <config.h>
29*18c2aff7Sartem #endif
30*18c2aff7Sartem 
31*18c2aff7Sartem #include <stdio.h>
32*18c2aff7Sartem #include <string.h>
33*18c2aff7Sartem 
34*18c2aff7Sartem #include "hald.h"
35*18c2aff7Sartem #include "device.h"
36*18c2aff7Sartem #include "hald_marshal.h"
37*18c2aff7Sartem #include "logger.h"
38*18c2aff7Sartem #include "hald_runner.h"
39*18c2aff7Sartem 
40*18c2aff7Sartem static GObjectClass *parent_class;
41*18c2aff7Sartem 
42*18c2aff7Sartem enum {
43*18c2aff7Sartem 	PROPERTY_CHANGED,
44*18c2aff7Sartem 	CAPABILITY_ADDED,
45*18c2aff7Sartem 	CALLOUTS_FINISHED,
46*18c2aff7Sartem 	CANCELLED,
47*18c2aff7Sartem 	LAST_SIGNAL
48*18c2aff7Sartem };
49*18c2aff7Sartem 
50*18c2aff7Sartem static guint signals[LAST_SIGNAL] = { 0 };
51*18c2aff7Sartem 
52*18c2aff7Sartem #ifdef HALD_MEMLEAK_DBG
53*18c2aff7Sartem int dbg_hal_device_object_delta = 0;
54*18c2aff7Sartem #endif
55*18c2aff7Sartem 
56*18c2aff7Sartem static void
57*18c2aff7Sartem hal_device_finalize (GObject *obj)
58*18c2aff7Sartem {
59*18c2aff7Sartem 	HalDevice *device = HAL_DEVICE (obj);
60*18c2aff7Sartem 
61*18c2aff7Sartem 	runner_device_finalized (device);
62*18c2aff7Sartem 
63*18c2aff7Sartem #ifdef HALD_MEMLEAK_DBG
64*18c2aff7Sartem 	dbg_hal_device_object_delta--;
65*18c2aff7Sartem 	printf ("************* in finalize for udi=%s\n", device->udi);
66*18c2aff7Sartem #endif
67*18c2aff7Sartem 
68*18c2aff7Sartem 
69*18c2aff7Sartem 	g_slist_foreach (device->properties, (GFunc) hal_property_free, NULL);
70*18c2aff7Sartem 
71*18c2aff7Sartem 	g_free (device->udi);
72*18c2aff7Sartem 
73*18c2aff7Sartem 	if (parent_class->finalize)
74*18c2aff7Sartem 		parent_class->finalize (obj);
75*18c2aff7Sartem 
76*18c2aff7Sartem }
77*18c2aff7Sartem 
78*18c2aff7Sartem static void
79*18c2aff7Sartem hal_device_class_init (HalDeviceClass *klass)
80*18c2aff7Sartem {
81*18c2aff7Sartem 	GObjectClass *obj_class = (GObjectClass *) klass;
82*18c2aff7Sartem 
83*18c2aff7Sartem 	parent_class = g_type_class_peek_parent (klass);
84*18c2aff7Sartem 
85*18c2aff7Sartem 	obj_class->finalize = hal_device_finalize;
86*18c2aff7Sartem 
87*18c2aff7Sartem 	signals[PROPERTY_CHANGED] =
88*18c2aff7Sartem 		g_signal_new ("property_changed",
89*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
90*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
91*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceClass,
92*18c2aff7Sartem 					       property_changed),
93*18c2aff7Sartem 			      NULL, NULL,
94*18c2aff7Sartem 			      hald_marshal_VOID__STRING_BOOL_BOOL,
95*18c2aff7Sartem 			      G_TYPE_NONE, 3,
96*18c2aff7Sartem 			      G_TYPE_STRING,
97*18c2aff7Sartem 			      G_TYPE_BOOLEAN,
98*18c2aff7Sartem 			      G_TYPE_BOOLEAN);
99*18c2aff7Sartem 
100*18c2aff7Sartem 	signals[CAPABILITY_ADDED] =
101*18c2aff7Sartem 		g_signal_new ("capability_added",
102*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
103*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
104*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceClass,
105*18c2aff7Sartem 					       capability_added),
106*18c2aff7Sartem 			      NULL, NULL,
107*18c2aff7Sartem 			      hald_marshal_VOID__STRING,
108*18c2aff7Sartem 			      G_TYPE_NONE, 1,
109*18c2aff7Sartem 			      G_TYPE_STRING);
110*18c2aff7Sartem 
111*18c2aff7Sartem 	signals[CALLOUTS_FINISHED] =
112*18c2aff7Sartem 		g_signal_new ("callouts_finished",
113*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
114*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
115*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceClass,
116*18c2aff7Sartem 					       callouts_finished),
117*18c2aff7Sartem 			      NULL, NULL,
118*18c2aff7Sartem 			      hald_marshal_VOID__VOID,
119*18c2aff7Sartem 			      G_TYPE_NONE, 0);
120*18c2aff7Sartem 
121*18c2aff7Sartem 	signals[CANCELLED] =
122*18c2aff7Sartem 		g_signal_new ("cancelled",
123*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
124*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
125*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceClass,
126*18c2aff7Sartem 					       cancelled),
127*18c2aff7Sartem 			      NULL, NULL,
128*18c2aff7Sartem 			      hald_marshal_VOID__VOID,
129*18c2aff7Sartem 			      G_TYPE_NONE, 0);
130*18c2aff7Sartem }
131*18c2aff7Sartem 
132*18c2aff7Sartem static void
133*18c2aff7Sartem hal_device_init (HalDevice *device)
134*18c2aff7Sartem {
135*18c2aff7Sartem 	static int temp_device_counter = 0;
136*18c2aff7Sartem 
137*18c2aff7Sartem 	device->udi = g_strdup_printf ("/org/freedesktop/Hal/devices/temp/%d",
138*18c2aff7Sartem 				       temp_device_counter++);
139*18c2aff7Sartem 	device->num_addons = 0;
140*18c2aff7Sartem 	device->num_addons_ready = 0;
141*18c2aff7Sartem }
142*18c2aff7Sartem 
143*18c2aff7Sartem GType
144*18c2aff7Sartem hal_device_get_type (void)
145*18c2aff7Sartem {
146*18c2aff7Sartem 	static GType type = 0;
147*18c2aff7Sartem 
148*18c2aff7Sartem 	if (!type) {
149*18c2aff7Sartem 		static GTypeInfo type_info = {
150*18c2aff7Sartem 			sizeof (HalDeviceClass),
151*18c2aff7Sartem 			NULL, NULL,
152*18c2aff7Sartem 			(GClassInitFunc) hal_device_class_init,
153*18c2aff7Sartem 			NULL, NULL,
154*18c2aff7Sartem 			sizeof (HalDevice),
155*18c2aff7Sartem 			0,
156*18c2aff7Sartem 			(GInstanceInitFunc) hal_device_init,
157*18c2aff7Sartem 			NULL
158*18c2aff7Sartem 		};
159*18c2aff7Sartem 
160*18c2aff7Sartem 		type = g_type_register_static (G_TYPE_OBJECT,
161*18c2aff7Sartem 					       "HalDevice",
162*18c2aff7Sartem 					       &type_info,
163*18c2aff7Sartem 					       0);
164*18c2aff7Sartem 	}
165*18c2aff7Sartem 
166*18c2aff7Sartem 	return type;
167*18c2aff7Sartem }
168*18c2aff7Sartem 
169*18c2aff7Sartem 
170*18c2aff7Sartem HalDevice *
171*18c2aff7Sartem hal_device_new (void)
172*18c2aff7Sartem {
173*18c2aff7Sartem 	HalDevice *device;
174*18c2aff7Sartem 
175*18c2aff7Sartem 	device = g_object_new (HAL_TYPE_DEVICE, NULL, NULL);
176*18c2aff7Sartem 
177*18c2aff7Sartem #ifdef HALD_MEMLEAK_DBG
178*18c2aff7Sartem 	dbg_hal_device_object_delta++;
179*18c2aff7Sartem #endif
180*18c2aff7Sartem 	return device;
181*18c2aff7Sartem }
182*18c2aff7Sartem 
183*18c2aff7Sartem /** Merge all properties from source where the key starts with
184*18c2aff7Sartem  *  source_namespace and put them onto target replacing source_namespace
185*18c2aff7Sartem  *  with target_namespace
186*18c2aff7Sartem  *
187*18c2aff7Sartem  *  @param  target              Device to put properties onto
188*18c2aff7Sartem  *  @param  source              Device to retrieve properties from
189*18c2aff7Sartem  *  @param  target_namespace    Replace source namespace with this namespace
190*18c2aff7Sartem  *  @param  source_namespace    Source namespace that property keys must match
191*18c2aff7Sartem  */
192*18c2aff7Sartem void
193*18c2aff7Sartem hal_device_merge_with_rewrite  (HalDevice    *target,
194*18c2aff7Sartem 				HalDevice    *source,
195*18c2aff7Sartem 				const char   *target_namespace,
196*18c2aff7Sartem 				const char   *source_namespace)
197*18c2aff7Sartem {
198*18c2aff7Sartem 	GSList *iter;
199*18c2aff7Sartem 	size_t source_ns_len;
200*18c2aff7Sartem 
201*18c2aff7Sartem 	source_ns_len = strlen (source_namespace);
202*18c2aff7Sartem 
203*18c2aff7Sartem 	/* doesn't handle info.capabilities */
204*18c2aff7Sartem 
205*18c2aff7Sartem 	/* device_property_atomic_update_begin (); */
206*18c2aff7Sartem 
207*18c2aff7Sartem 	for (iter = source->properties; iter != NULL; iter = iter->next) {
208*18c2aff7Sartem 		HalProperty *p = iter->data;
209*18c2aff7Sartem 		int type;
210*18c2aff7Sartem 		const char *key;
211*18c2aff7Sartem 		int target_type;
212*18c2aff7Sartem 		gchar *target_key;
213*18c2aff7Sartem 
214*18c2aff7Sartem 		key = hal_property_get_key (p);
215*18c2aff7Sartem 
216*18c2aff7Sartem 		/* only care about properties that match source namespace */
217*18c2aff7Sartem 		if (strncmp(key, source_namespace, source_ns_len) != 0)
218*18c2aff7Sartem 			continue;
219*18c2aff7Sartem 
220*18c2aff7Sartem 		target_key = g_strdup_printf("%s%s", target_namespace,
221*18c2aff7Sartem 					     key+source_ns_len);
222*18c2aff7Sartem 
223*18c2aff7Sartem 		type = hal_property_get_type (p);
224*18c2aff7Sartem 
225*18c2aff7Sartem 		/* only remove target if it exists with a different type */
226*18c2aff7Sartem 		target_type = hal_device_property_get_type (target, key);
227*18c2aff7Sartem 		if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type)
228*18c2aff7Sartem 			hal_device_property_remove (target, key);
229*18c2aff7Sartem 
230*18c2aff7Sartem 		switch (type) {
231*18c2aff7Sartem 
232*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_STRING:
233*18c2aff7Sartem 			hal_device_property_set_string (
234*18c2aff7Sartem 				target, target_key,
235*18c2aff7Sartem 				hal_property_get_string (p));
236*18c2aff7Sartem 			break;
237*18c2aff7Sartem 
238*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_INT32:
239*18c2aff7Sartem 			hal_device_property_set_int (
240*18c2aff7Sartem 				target, target_key,
241*18c2aff7Sartem 				hal_property_get_int (p));
242*18c2aff7Sartem 			break;
243*18c2aff7Sartem 
244*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_UINT64:
245*18c2aff7Sartem 			hal_device_property_set_uint64 (
246*18c2aff7Sartem 				target, target_key,
247*18c2aff7Sartem 				hal_property_get_uint64 (p));
248*18c2aff7Sartem 			break;
249*18c2aff7Sartem 
250*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_BOOLEAN:
251*18c2aff7Sartem 			hal_device_property_set_bool (
252*18c2aff7Sartem 				target, target_key,
253*18c2aff7Sartem 				hal_property_get_bool (p));
254*18c2aff7Sartem 			break;
255*18c2aff7Sartem 
256*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_DOUBLE:
257*18c2aff7Sartem 			hal_device_property_set_double (
258*18c2aff7Sartem 				target, target_key,
259*18c2aff7Sartem 				hal_property_get_double (p));
260*18c2aff7Sartem 			break;
261*18c2aff7Sartem 
262*18c2aff7Sartem 		default:
263*18c2aff7Sartem 			HAL_WARNING (("Unknown property type %d", type));
264*18c2aff7Sartem 			break;
265*18c2aff7Sartem 		}
266*18c2aff7Sartem 
267*18c2aff7Sartem 		g_free (target_key);
268*18c2aff7Sartem 	}
269*18c2aff7Sartem 
270*18c2aff7Sartem 	/* device_property_atomic_update_end (); */
271*18c2aff7Sartem 
272*18c2aff7Sartem }
273*18c2aff7Sartem 
274*18c2aff7Sartem void
275*18c2aff7Sartem hal_device_merge (HalDevice *target, HalDevice *source)
276*18c2aff7Sartem {
277*18c2aff7Sartem 	GSList *iter;
278*18c2aff7Sartem 	GSList *caps;
279*18c2aff7Sartem 
280*18c2aff7Sartem 	/* device_property_atomic_update_begin (); */
281*18c2aff7Sartem 
282*18c2aff7Sartem 	for (iter = source->properties; iter != NULL; iter = iter->next) {
283*18c2aff7Sartem 		HalProperty *p = iter->data;
284*18c2aff7Sartem 		int type;
285*18c2aff7Sartem 		const char *key;
286*18c2aff7Sartem 		int target_type;
287*18c2aff7Sartem 
288*18c2aff7Sartem 		key = hal_property_get_key (p);
289*18c2aff7Sartem 		type = hal_property_get_type (p);
290*18c2aff7Sartem 
291*18c2aff7Sartem 		/* handle info.capabilities in a special way */
292*18c2aff7Sartem 		if (strcmp (key, "info.capabilities") == 0)
293*18c2aff7Sartem 			continue;
294*18c2aff7Sartem 
295*18c2aff7Sartem 		/* only remove target if it exists with a different type */
296*18c2aff7Sartem 		target_type = hal_device_property_get_type (target, key);
297*18c2aff7Sartem 		if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type)
298*18c2aff7Sartem 			hal_device_property_remove (target, key);
299*18c2aff7Sartem 
300*18c2aff7Sartem 		switch (type) {
301*18c2aff7Sartem 
302*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_STRING:
303*18c2aff7Sartem 			hal_device_property_set_string (
304*18c2aff7Sartem 				target, key,
305*18c2aff7Sartem 				hal_property_get_string (p));
306*18c2aff7Sartem 			break;
307*18c2aff7Sartem 
308*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_INT32:
309*18c2aff7Sartem 			hal_device_property_set_int (
310*18c2aff7Sartem 				target, key,
311*18c2aff7Sartem 				hal_property_get_int (p));
312*18c2aff7Sartem 			break;
313*18c2aff7Sartem 
314*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_UINT64:
315*18c2aff7Sartem 			hal_device_property_set_uint64 (
316*18c2aff7Sartem 				target, key,
317*18c2aff7Sartem 				hal_property_get_uint64 (p));
318*18c2aff7Sartem 			break;
319*18c2aff7Sartem 
320*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_BOOLEAN:
321*18c2aff7Sartem 			hal_device_property_set_bool (
322*18c2aff7Sartem 				target, key,
323*18c2aff7Sartem 				hal_property_get_bool (p));
324*18c2aff7Sartem 			break;
325*18c2aff7Sartem 
326*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_DOUBLE:
327*18c2aff7Sartem 			hal_device_property_set_double (
328*18c2aff7Sartem 				target, key,
329*18c2aff7Sartem 				hal_property_get_double (p));
330*18c2aff7Sartem 			break;
331*18c2aff7Sartem 
332*18c2aff7Sartem 		default:
333*18c2aff7Sartem 			HAL_WARNING (("Unknown property type %d", type));
334*18c2aff7Sartem 			break;
335*18c2aff7Sartem 		}
336*18c2aff7Sartem 	}
337*18c2aff7Sartem 
338*18c2aff7Sartem 	/* device_property_atomic_update_end (); */
339*18c2aff7Sartem 
340*18c2aff7Sartem 	caps = hal_device_property_get_strlist (source, "info.capabilities");
341*18c2aff7Sartem 	for (iter = caps; iter != NULL; iter = iter->next) {
342*18c2aff7Sartem 		if (!hal_device_has_capability (target, iter->data))
343*18c2aff7Sartem 			hal_device_add_capability (target, iter->data);
344*18c2aff7Sartem 	}
345*18c2aff7Sartem }
346*18c2aff7Sartem 
347*18c2aff7Sartem gboolean
348*18c2aff7Sartem hal_device_matches (HalDevice *device1, HalDevice *device2,
349*18c2aff7Sartem 		    const char *namespace)
350*18c2aff7Sartem {
351*18c2aff7Sartem 	int len;
352*18c2aff7Sartem 	GSList *iter;
353*18c2aff7Sartem 
354*18c2aff7Sartem 	len = strlen (namespace);
355*18c2aff7Sartem 
356*18c2aff7Sartem 	for (iter = device1->properties; iter != NULL; iter = iter->next) {
357*18c2aff7Sartem 		HalProperty *p;
358*18c2aff7Sartem 		const char *key;
359*18c2aff7Sartem 		int type;
360*18c2aff7Sartem 
361*18c2aff7Sartem 		p = (HalProperty *) iter->data;
362*18c2aff7Sartem 		key = hal_property_get_key (p);
363*18c2aff7Sartem 		type = hal_property_get_type (p);
364*18c2aff7Sartem 
365*18c2aff7Sartem 		if (strncmp (key, namespace, len) != 0)
366*18c2aff7Sartem 			continue;
367*18c2aff7Sartem 
368*18c2aff7Sartem 		if (!hal_device_has_property (device2, key))
369*18c2aff7Sartem 			return FALSE;
370*18c2aff7Sartem 
371*18c2aff7Sartem 		switch (type) {
372*18c2aff7Sartem 
373*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_STRING:
374*18c2aff7Sartem 			if (strcmp (hal_property_get_string (p),
375*18c2aff7Sartem 				    hal_device_property_get_string (device2,
376*18c2aff7Sartem 								    key)) != 0)
377*18c2aff7Sartem 				return FALSE;
378*18c2aff7Sartem 			break;
379*18c2aff7Sartem 
380*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_INT32:
381*18c2aff7Sartem 			if (hal_property_get_int (p) !=
382*18c2aff7Sartem 			    hal_device_property_get_int (device2, key))
383*18c2aff7Sartem 				return FALSE;
384*18c2aff7Sartem 			break;
385*18c2aff7Sartem 
386*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_UINT64:
387*18c2aff7Sartem 			if (hal_property_get_uint64 (p) !=
388*18c2aff7Sartem 				hal_device_property_get_uint64 (device2, key))
389*18c2aff7Sartem 				return FALSE;
390*18c2aff7Sartem 			break;
391*18c2aff7Sartem 
392*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_BOOLEAN:
393*18c2aff7Sartem 			if (hal_property_get_bool (p) !=
394*18c2aff7Sartem 			    hal_device_property_get_bool (device2, key))
395*18c2aff7Sartem 				return FALSE;
396*18c2aff7Sartem 			break;
397*18c2aff7Sartem 
398*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_DOUBLE:
399*18c2aff7Sartem 			if (hal_property_get_double (p) !=
400*18c2aff7Sartem 			    hal_device_property_get_double (device2, key))
401*18c2aff7Sartem 				return FALSE;
402*18c2aff7Sartem 			break;
403*18c2aff7Sartem 
404*18c2aff7Sartem 		default:
405*18c2aff7Sartem 			HAL_WARNING (("Unknown property type %d", type));
406*18c2aff7Sartem 			break;
407*18c2aff7Sartem 		}
408*18c2aff7Sartem 	}
409*18c2aff7Sartem 
410*18c2aff7Sartem 	return TRUE;
411*18c2aff7Sartem }
412*18c2aff7Sartem 
413*18c2aff7Sartem const char *
414*18c2aff7Sartem hal_device_get_udi (HalDevice *device)
415*18c2aff7Sartem {
416*18c2aff7Sartem 	return device->udi;
417*18c2aff7Sartem }
418*18c2aff7Sartem 
419*18c2aff7Sartem void
420*18c2aff7Sartem hal_device_set_udi (HalDevice *device, const char *udi)
421*18c2aff7Sartem {
422*18c2aff7Sartem 	if (device->udi != NULL)
423*18c2aff7Sartem 		g_free (device->udi);
424*18c2aff7Sartem 	device->udi = g_strdup (udi);
425*18c2aff7Sartem }
426*18c2aff7Sartem 
427*18c2aff7Sartem void
428*18c2aff7Sartem hal_device_add_capability (HalDevice *device, const char *capability)
429*18c2aff7Sartem {
430*18c2aff7Sartem 	if (hal_device_property_strlist_add (device, "info.capabilities", capability))
431*18c2aff7Sartem 		g_signal_emit (device, signals[CAPABILITY_ADDED], 0, capability);
432*18c2aff7Sartem }
433*18c2aff7Sartem 
434*18c2aff7Sartem gboolean
435*18c2aff7Sartem hal_device_has_capability (HalDevice *device, const char *capability)
436*18c2aff7Sartem {
437*18c2aff7Sartem 	GSList *caps;
438*18c2aff7Sartem 	GSList *iter;
439*18c2aff7Sartem 	gboolean matched = FALSE;
440*18c2aff7Sartem 
441*18c2aff7Sartem 	caps = hal_device_property_get_strlist (device, "info.capabilities");
442*18c2aff7Sartem 
443*18c2aff7Sartem 	if (caps == NULL)
444*18c2aff7Sartem 		return FALSE;
445*18c2aff7Sartem 
446*18c2aff7Sartem 	for (iter = caps; iter != NULL; iter = iter->next) {
447*18c2aff7Sartem 		if (strcmp (iter->data, capability) == 0) {
448*18c2aff7Sartem 			matched = TRUE;
449*18c2aff7Sartem 			break;
450*18c2aff7Sartem 		}
451*18c2aff7Sartem 	}
452*18c2aff7Sartem 
453*18c2aff7Sartem 	return matched;
454*18c2aff7Sartem }
455*18c2aff7Sartem 
456*18c2aff7Sartem gboolean
457*18c2aff7Sartem hal_device_has_property (HalDevice *device, const char *key)
458*18c2aff7Sartem {
459*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, FALSE);
460*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, FALSE);
461*18c2aff7Sartem 
462*18c2aff7Sartem 	return hal_device_property_find (device, key) != NULL;
463*18c2aff7Sartem }
464*18c2aff7Sartem 
465*18c2aff7Sartem int
466*18c2aff7Sartem hal_device_num_properties (HalDevice *device)
467*18c2aff7Sartem {
468*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, -1);
469*18c2aff7Sartem 
470*18c2aff7Sartem 	return g_slist_length (device->properties);
471*18c2aff7Sartem }
472*18c2aff7Sartem 
473*18c2aff7Sartem HalProperty *
474*18c2aff7Sartem hal_device_property_find (HalDevice *device, const char *key)
475*18c2aff7Sartem {
476*18c2aff7Sartem 	GSList *iter;
477*18c2aff7Sartem 
478*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, NULL);
479*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
480*18c2aff7Sartem 
481*18c2aff7Sartem 	for (iter = device->properties; iter != NULL; iter = iter->next) {
482*18c2aff7Sartem 		HalProperty *p = iter->data;
483*18c2aff7Sartem 
484*18c2aff7Sartem 		if (strcmp (hal_property_get_key (p), key) == 0)
485*18c2aff7Sartem 			return p;
486*18c2aff7Sartem 	}
487*18c2aff7Sartem 
488*18c2aff7Sartem 	return NULL;
489*18c2aff7Sartem }
490*18c2aff7Sartem 
491*18c2aff7Sartem char *
492*18c2aff7Sartem hal_device_property_to_string (HalDevice *device, const char *key)
493*18c2aff7Sartem {
494*18c2aff7Sartem 	HalProperty *prop;
495*18c2aff7Sartem 
496*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
497*18c2aff7Sartem 	if (!prop)
498*18c2aff7Sartem 		return NULL;
499*18c2aff7Sartem 
500*18c2aff7Sartem 	return hal_property_to_string (prop);
501*18c2aff7Sartem }
502*18c2aff7Sartem 
503*18c2aff7Sartem void
504*18c2aff7Sartem hal_device_property_foreach (HalDevice *device,
505*18c2aff7Sartem 			     HalDevicePropertyForeachFn callback,
506*18c2aff7Sartem 			     gpointer user_data)
507*18c2aff7Sartem {
508*18c2aff7Sartem 	GSList *iter;
509*18c2aff7Sartem 
510*18c2aff7Sartem 	g_return_if_fail (device != NULL);
511*18c2aff7Sartem 	g_return_if_fail (callback != NULL);
512*18c2aff7Sartem 
513*18c2aff7Sartem 	for (iter = device->properties; iter != NULL; iter = iter->next) {
514*18c2aff7Sartem 		HalProperty *p = iter->data;
515*18c2aff7Sartem 		gboolean cont;
516*18c2aff7Sartem 
517*18c2aff7Sartem 		cont = callback (device, p, user_data);
518*18c2aff7Sartem 
519*18c2aff7Sartem 		if (cont == FALSE)
520*18c2aff7Sartem 			return;
521*18c2aff7Sartem 	}
522*18c2aff7Sartem }
523*18c2aff7Sartem 
524*18c2aff7Sartem int
525*18c2aff7Sartem hal_device_property_get_type (HalDevice *device, const char *key)
526*18c2aff7Sartem {
527*18c2aff7Sartem 	HalProperty *prop;
528*18c2aff7Sartem 
529*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, HAL_PROPERTY_TYPE_INVALID);
530*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, HAL_PROPERTY_TYPE_INVALID);
531*18c2aff7Sartem 
532*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
533*18c2aff7Sartem 
534*18c2aff7Sartem 	if (prop != NULL)
535*18c2aff7Sartem 		return hal_property_get_type (prop);
536*18c2aff7Sartem 	else
537*18c2aff7Sartem 		return HAL_PROPERTY_TYPE_INVALID;
538*18c2aff7Sartem }
539*18c2aff7Sartem 
540*18c2aff7Sartem const char *
541*18c2aff7Sartem hal_device_property_get_string (HalDevice *device, const char *key)
542*18c2aff7Sartem {
543*18c2aff7Sartem 	HalProperty *prop;
544*18c2aff7Sartem 
545*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, NULL);
546*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
547*18c2aff7Sartem 
548*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
549*18c2aff7Sartem 
550*18c2aff7Sartem 	if (prop != NULL)
551*18c2aff7Sartem 		return hal_property_get_string (prop);
552*18c2aff7Sartem 	else
553*18c2aff7Sartem 		return NULL;
554*18c2aff7Sartem }
555*18c2aff7Sartem 
556*18c2aff7Sartem const char *
557*18c2aff7Sartem hal_device_property_get_as_string (HalDevice *device, const char *key, char *buf, size_t bufsize)
558*18c2aff7Sartem {
559*18c2aff7Sartem 	HalProperty *prop;
560*18c2aff7Sartem 
561*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, NULL);
562*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
563*18c2aff7Sartem 	g_return_val_if_fail (buf != NULL, NULL);
564*18c2aff7Sartem 
565*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
566*18c2aff7Sartem 
567*18c2aff7Sartem 	if (prop != NULL) {
568*18c2aff7Sartem 		switch (hal_property_get_type (prop)) {
569*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_STRING:
570*18c2aff7Sartem 			strncpy (buf, hal_property_get_string (prop), bufsize);
571*18c2aff7Sartem 			break;
572*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_INT32:
573*18c2aff7Sartem 			snprintf (buf, bufsize, "%d", hal_property_get_int (prop));
574*18c2aff7Sartem 			break;
575*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_UINT64:
576*18c2aff7Sartem 			snprintf (buf, bufsize, "%llu", (long long unsigned int) hal_property_get_uint64 (prop));
577*18c2aff7Sartem 			break;
578*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_DOUBLE:
579*18c2aff7Sartem 			snprintf (buf, bufsize, "%f", hal_property_get_double (prop));
580*18c2aff7Sartem 			break;
581*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_BOOLEAN:
582*18c2aff7Sartem 			strncpy (buf, hal_property_get_bool (prop) ? "true" : "false", bufsize);
583*18c2aff7Sartem 			break;
584*18c2aff7Sartem 
585*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_STRLIST:
586*18c2aff7Sartem 			/* print out as "\tval1\tval2\val3\t" */
587*18c2aff7Sartem 		        {
588*18c2aff7Sartem 				GSList *iter;
589*18c2aff7Sartem 				guint i;
590*18c2aff7Sartem 
591*18c2aff7Sartem 				if (bufsize > 0)
592*18c2aff7Sartem 					buf[0] = '\t';
593*18c2aff7Sartem 				i = 1;
594*18c2aff7Sartem 				for (iter = hal_property_get_strlist (prop);
595*18c2aff7Sartem 				     iter != NULL && i < bufsize;
596*18c2aff7Sartem 				     iter = g_slist_next (iter)) {
597*18c2aff7Sartem 					guint len;
598*18c2aff7Sartem 					const char *str;
599*18c2aff7Sartem 
600*18c2aff7Sartem 					str = (const char *) iter->data;
601*18c2aff7Sartem 					len = strlen (str);
602*18c2aff7Sartem 					strncpy (buf + i, str, bufsize - i);
603*18c2aff7Sartem 					i += len;
604*18c2aff7Sartem 
605*18c2aff7Sartem 					if (i < bufsize) {
606*18c2aff7Sartem 						buf[i] = '\t';
607*18c2aff7Sartem 						i++;
608*18c2aff7Sartem 					}
609*18c2aff7Sartem 				}
610*18c2aff7Sartem 			}
611*18c2aff7Sartem 			break;
612*18c2aff7Sartem 		}
613*18c2aff7Sartem 		return buf;
614*18c2aff7Sartem 	} else {
615*18c2aff7Sartem 		buf[0] = '\0';
616*18c2aff7Sartem 		return NULL;
617*18c2aff7Sartem 	}
618*18c2aff7Sartem }
619*18c2aff7Sartem 
620*18c2aff7Sartem dbus_int32_t
621*18c2aff7Sartem hal_device_property_get_int (HalDevice *device, const char *key)
622*18c2aff7Sartem {
623*18c2aff7Sartem 	HalProperty *prop;
624*18c2aff7Sartem 
625*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, -1);
626*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, -1);
627*18c2aff7Sartem 
628*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
629*18c2aff7Sartem 
630*18c2aff7Sartem 	if (prop != NULL)
631*18c2aff7Sartem 		return hal_property_get_int (prop);
632*18c2aff7Sartem 	else
633*18c2aff7Sartem 		return -1;
634*18c2aff7Sartem }
635*18c2aff7Sartem 
636*18c2aff7Sartem dbus_uint64_t
637*18c2aff7Sartem hal_device_property_get_uint64 (HalDevice *device, const char *key)
638*18c2aff7Sartem {
639*18c2aff7Sartem 	HalProperty *prop;
640*18c2aff7Sartem 
641*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, -1);
642*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, -1);
643*18c2aff7Sartem 
644*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
645*18c2aff7Sartem 
646*18c2aff7Sartem 	if (prop != NULL)
647*18c2aff7Sartem 		return hal_property_get_uint64 (prop);
648*18c2aff7Sartem 	else
649*18c2aff7Sartem 		return -1;
650*18c2aff7Sartem }
651*18c2aff7Sartem 
652*18c2aff7Sartem dbus_bool_t
653*18c2aff7Sartem hal_device_property_get_bool (HalDevice *device, const char *key)
654*18c2aff7Sartem {
655*18c2aff7Sartem 	HalProperty *prop;
656*18c2aff7Sartem 
657*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, FALSE);
658*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, FALSE);
659*18c2aff7Sartem 
660*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
661*18c2aff7Sartem 
662*18c2aff7Sartem 	if (prop != NULL)
663*18c2aff7Sartem 		return hal_property_get_bool (prop);
664*18c2aff7Sartem 	else
665*18c2aff7Sartem 		return FALSE;
666*18c2aff7Sartem }
667*18c2aff7Sartem 
668*18c2aff7Sartem double
669*18c2aff7Sartem hal_device_property_get_double (HalDevice *device, const char *key)
670*18c2aff7Sartem {
671*18c2aff7Sartem 	HalProperty *prop;
672*18c2aff7Sartem 
673*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, -1.0);
674*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, -1.0);
675*18c2aff7Sartem 
676*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
677*18c2aff7Sartem 
678*18c2aff7Sartem 	if (prop != NULL)
679*18c2aff7Sartem 		return hal_property_get_double (prop);
680*18c2aff7Sartem 	else
681*18c2aff7Sartem 		return -1.0;
682*18c2aff7Sartem }
683*18c2aff7Sartem 
684*18c2aff7Sartem gboolean
685*18c2aff7Sartem hal_device_property_set_string (HalDevice *device, const char *key,
686*18c2aff7Sartem 				const char *value)
687*18c2aff7Sartem {
688*18c2aff7Sartem 	HalProperty *prop;
689*18c2aff7Sartem 
690*18c2aff7Sartem 	/* check if property already exists */
691*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
692*18c2aff7Sartem 
693*18c2aff7Sartem 	if (prop != NULL) {
694*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRING)
695*18c2aff7Sartem 			return FALSE;
696*18c2aff7Sartem 
697*18c2aff7Sartem 		/* don't bother setting the same value */
698*18c2aff7Sartem 		if (value != NULL &&
699*18c2aff7Sartem 		    strcmp (hal_property_get_string (prop), value) == 0)
700*18c2aff7Sartem 			return TRUE;
701*18c2aff7Sartem 
702*18c2aff7Sartem 		hal_property_set_string (prop, value);
703*18c2aff7Sartem 
704*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
705*18c2aff7Sartem 			       key, FALSE, FALSE);
706*18c2aff7Sartem 
707*18c2aff7Sartem 	} else {
708*18c2aff7Sartem 
709*18c2aff7Sartem 		prop = hal_property_new_string (key, value);
710*18c2aff7Sartem 
711*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
712*18c2aff7Sartem 
713*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
714*18c2aff7Sartem 			       key, FALSE, TRUE);
715*18c2aff7Sartem 	}
716*18c2aff7Sartem 
717*18c2aff7Sartem 	return TRUE;
718*18c2aff7Sartem }
719*18c2aff7Sartem 
720*18c2aff7Sartem gboolean
721*18c2aff7Sartem hal_device_property_set_int (HalDevice *device, const char *key,
722*18c2aff7Sartem 			     dbus_int32_t value)
723*18c2aff7Sartem {
724*18c2aff7Sartem 	HalProperty *prop;
725*18c2aff7Sartem 
726*18c2aff7Sartem 	/* check if property already exists */
727*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
728*18c2aff7Sartem 
729*18c2aff7Sartem 	if (prop != NULL) {
730*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_INT32)
731*18c2aff7Sartem 			return FALSE;
732*18c2aff7Sartem 
733*18c2aff7Sartem 		/* don't bother setting the same value */
734*18c2aff7Sartem 		if (hal_property_get_int (prop) == value)
735*18c2aff7Sartem 			return TRUE;
736*18c2aff7Sartem 
737*18c2aff7Sartem 		hal_property_set_int (prop, value);
738*18c2aff7Sartem 
739*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
740*18c2aff7Sartem 			       key, FALSE, FALSE);
741*18c2aff7Sartem 
742*18c2aff7Sartem 	} else {
743*18c2aff7Sartem 		prop = hal_property_new_int (key, value);
744*18c2aff7Sartem 
745*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
746*18c2aff7Sartem 
747*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
748*18c2aff7Sartem 			       key, FALSE, TRUE);
749*18c2aff7Sartem 	}
750*18c2aff7Sartem 
751*18c2aff7Sartem 	return TRUE;
752*18c2aff7Sartem }
753*18c2aff7Sartem 
754*18c2aff7Sartem gboolean
755*18c2aff7Sartem hal_device_property_set_uint64 (HalDevice *device, const char *key,
756*18c2aff7Sartem 			     dbus_uint64_t value)
757*18c2aff7Sartem {
758*18c2aff7Sartem 	HalProperty *prop;
759*18c2aff7Sartem 
760*18c2aff7Sartem 	/* check if property already exists */
761*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
762*18c2aff7Sartem 
763*18c2aff7Sartem 	if (prop != NULL) {
764*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_UINT64)
765*18c2aff7Sartem 			return FALSE;
766*18c2aff7Sartem 
767*18c2aff7Sartem 		/* don't bother setting the same value */
768*18c2aff7Sartem 		if (hal_property_get_uint64 (prop) == value)
769*18c2aff7Sartem 			return TRUE;
770*18c2aff7Sartem 
771*18c2aff7Sartem 		hal_property_set_uint64 (prop, value);
772*18c2aff7Sartem 
773*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
774*18c2aff7Sartem 			       key, FALSE, FALSE);
775*18c2aff7Sartem 
776*18c2aff7Sartem 	} else {
777*18c2aff7Sartem 		prop = hal_property_new_uint64 (key, value);
778*18c2aff7Sartem 
779*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
780*18c2aff7Sartem 
781*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
782*18c2aff7Sartem 			       key, FALSE, TRUE);
783*18c2aff7Sartem 	}
784*18c2aff7Sartem 
785*18c2aff7Sartem 	return TRUE;
786*18c2aff7Sartem }
787*18c2aff7Sartem 
788*18c2aff7Sartem gboolean
789*18c2aff7Sartem hal_device_property_set_bool (HalDevice *device, const char *key,
790*18c2aff7Sartem 			     dbus_bool_t value)
791*18c2aff7Sartem {
792*18c2aff7Sartem 	HalProperty *prop;
793*18c2aff7Sartem 
794*18c2aff7Sartem 	/* check if property already exists */
795*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
796*18c2aff7Sartem 
797*18c2aff7Sartem 	if (prop != NULL) {
798*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_BOOLEAN)
799*18c2aff7Sartem 			return FALSE;
800*18c2aff7Sartem 
801*18c2aff7Sartem 		/* don't bother setting the same value */
802*18c2aff7Sartem 		if (hal_property_get_bool (prop) == value)
803*18c2aff7Sartem 			return TRUE;
804*18c2aff7Sartem 
805*18c2aff7Sartem 		hal_property_set_bool (prop, value);
806*18c2aff7Sartem 
807*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
808*18c2aff7Sartem 			       key, FALSE, FALSE);
809*18c2aff7Sartem 
810*18c2aff7Sartem 	} else {
811*18c2aff7Sartem 		prop = hal_property_new_bool (key, value);
812*18c2aff7Sartem 
813*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
814*18c2aff7Sartem 
815*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
816*18c2aff7Sartem 			       key, FALSE, TRUE);
817*18c2aff7Sartem 	}
818*18c2aff7Sartem 
819*18c2aff7Sartem 	return TRUE;
820*18c2aff7Sartem }
821*18c2aff7Sartem 
822*18c2aff7Sartem gboolean
823*18c2aff7Sartem hal_device_property_set_double (HalDevice *device, const char *key,
824*18c2aff7Sartem 				double value)
825*18c2aff7Sartem {
826*18c2aff7Sartem 	HalProperty *prop;
827*18c2aff7Sartem 
828*18c2aff7Sartem 	/* check if property already exists */
829*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
830*18c2aff7Sartem 
831*18c2aff7Sartem 	if (prop != NULL) {
832*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_DOUBLE)
833*18c2aff7Sartem 			return FALSE;
834*18c2aff7Sartem 
835*18c2aff7Sartem 		/* don't bother setting the same value */
836*18c2aff7Sartem 		if (hal_property_get_double (prop) == value)
837*18c2aff7Sartem 			return TRUE;
838*18c2aff7Sartem 
839*18c2aff7Sartem 		hal_property_set_double (prop, value);
840*18c2aff7Sartem 
841*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
842*18c2aff7Sartem 			       key, FALSE, FALSE);
843*18c2aff7Sartem 
844*18c2aff7Sartem 	} else {
845*18c2aff7Sartem 		prop = hal_property_new_double (key, value);
846*18c2aff7Sartem 
847*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
848*18c2aff7Sartem 
849*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
850*18c2aff7Sartem 			       key, FALSE, TRUE);
851*18c2aff7Sartem 	}
852*18c2aff7Sartem 
853*18c2aff7Sartem 	return TRUE;
854*18c2aff7Sartem }
855*18c2aff7Sartem 
856*18c2aff7Sartem gboolean
857*18c2aff7Sartem hal_device_copy_property (HalDevice *from_device, const char *from, HalDevice *to_device, const char *to)
858*18c2aff7Sartem {
859*18c2aff7Sartem 	gboolean rc;
860*18c2aff7Sartem 
861*18c2aff7Sartem 	rc = FALSE;
862*18c2aff7Sartem 
863*18c2aff7Sartem 	if (hal_device_has_property (from_device, from)) {
864*18c2aff7Sartem 		switch (hal_device_property_get_type (from_device, from)) {
865*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_STRING:
866*18c2aff7Sartem 			rc = hal_device_property_set_string (
867*18c2aff7Sartem 				to_device, to, hal_device_property_get_string (from_device, from));
868*18c2aff7Sartem 			break;
869*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_INT32:
870*18c2aff7Sartem 			rc = hal_device_property_set_int (
871*18c2aff7Sartem 				to_device, to, hal_device_property_get_int (from_device, from));
872*18c2aff7Sartem 			break;
873*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_UINT64:
874*18c2aff7Sartem 			rc = hal_device_property_set_uint64 (
875*18c2aff7Sartem 				to_device, to, hal_device_property_get_uint64 (from_device, from));
876*18c2aff7Sartem 			break;
877*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_BOOLEAN:
878*18c2aff7Sartem 			rc = hal_device_property_set_bool (
879*18c2aff7Sartem 				to_device, to, hal_device_property_get_bool (from_device, from));
880*18c2aff7Sartem 			break;
881*18c2aff7Sartem 		case HAL_PROPERTY_TYPE_DOUBLE:
882*18c2aff7Sartem 			rc = hal_device_property_set_double (
883*18c2aff7Sartem 				to_device, to, hal_device_property_get_double (from_device, from));
884*18c2aff7Sartem 			break;
885*18c2aff7Sartem 		}
886*18c2aff7Sartem 	}
887*18c2aff7Sartem 
888*18c2aff7Sartem 	return rc;
889*18c2aff7Sartem }
890*18c2aff7Sartem 
891*18c2aff7Sartem gboolean
892*18c2aff7Sartem hal_device_property_remove (HalDevice *device, const char *key)
893*18c2aff7Sartem {
894*18c2aff7Sartem 	HalProperty *prop;
895*18c2aff7Sartem 
896*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
897*18c2aff7Sartem 
898*18c2aff7Sartem 	if (prop == NULL)
899*18c2aff7Sartem 		return FALSE;
900*18c2aff7Sartem 
901*18c2aff7Sartem 	device->properties = g_slist_remove (device->properties, prop);
902*18c2aff7Sartem 
903*18c2aff7Sartem 	hal_property_free (prop);
904*18c2aff7Sartem 
905*18c2aff7Sartem 	g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
906*18c2aff7Sartem 		       key, TRUE, FALSE);
907*18c2aff7Sartem 
908*18c2aff7Sartem 	return TRUE;
909*18c2aff7Sartem }
910*18c2aff7Sartem 
911*18c2aff7Sartem gboolean
912*18c2aff7Sartem hal_device_property_set_attribute (HalDevice *device,
913*18c2aff7Sartem 				   const char *key,
914*18c2aff7Sartem 				   enum PropertyAttribute attr,
915*18c2aff7Sartem 				   gboolean val)
916*18c2aff7Sartem {
917*18c2aff7Sartem 	HalProperty *prop;
918*18c2aff7Sartem 
919*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
920*18c2aff7Sartem 
921*18c2aff7Sartem 	if (prop == NULL)
922*18c2aff7Sartem 		return FALSE;
923*18c2aff7Sartem 
924*18c2aff7Sartem 	return TRUE;
925*18c2aff7Sartem }
926*18c2aff7Sartem 
927*18c2aff7Sartem void
928*18c2aff7Sartem hal_device_print (HalDevice *device)
929*18c2aff7Sartem {
930*18c2aff7Sartem 	GSList *iter;
931*18c2aff7Sartem 
932*18c2aff7Sartem         fprintf (stderr, "device udi = %s\n", hal_device_get_udi (device));
933*18c2aff7Sartem 
934*18c2aff7Sartem 	for (iter = device->properties; iter != NULL; iter = iter->next) {
935*18c2aff7Sartem 		HalProperty *p = iter->data;
936*18c2aff7Sartem                 int type;
937*18c2aff7Sartem                 const char *key;
938*18c2aff7Sartem 
939*18c2aff7Sartem                 key = hal_property_get_key (p);
940*18c2aff7Sartem                 type = hal_property_get_type (p);
941*18c2aff7Sartem 
942*18c2aff7Sartem                 switch (type) {
943*18c2aff7Sartem                 case HAL_PROPERTY_TYPE_STRING:
944*18c2aff7Sartem                         fprintf (stderr, "  %s = '%s'  (string)\n", key,
945*18c2aff7Sartem                                 hal_property_get_string (p));
946*18c2aff7Sartem                         break;
947*18c2aff7Sartem 
948*18c2aff7Sartem                 case HAL_PROPERTY_TYPE_INT32:
949*18c2aff7Sartem                         fprintf (stderr, "  %s = %d  0x%x  (int)\n", key,
950*18c2aff7Sartem                                 hal_property_get_int (p),
951*18c2aff7Sartem                                 hal_property_get_int (p));
952*18c2aff7Sartem                         break;
953*18c2aff7Sartem 
954*18c2aff7Sartem                 case HAL_PROPERTY_TYPE_UINT64:
955*18c2aff7Sartem                         fprintf (stderr, "  %s = %llu  0x%llx  (uint64)\n", key,
956*18c2aff7Sartem                                 (long long unsigned int) hal_property_get_uint64 (p),
957*18c2aff7Sartem                                 (long long unsigned int) hal_property_get_uint64 (p));
958*18c2aff7Sartem                         break;
959*18c2aff7Sartem 
960*18c2aff7Sartem                 case HAL_PROPERTY_TYPE_DOUBLE:
961*18c2aff7Sartem                         fprintf (stderr, "  %s = %g  (double)\n", key,
962*18c2aff7Sartem                                 hal_property_get_double (p));
963*18c2aff7Sartem                         break;
964*18c2aff7Sartem 
965*18c2aff7Sartem                 case HAL_PROPERTY_TYPE_BOOLEAN:
966*18c2aff7Sartem                         fprintf (stderr, "  %s = %s  (bool)\n", key,
967*18c2aff7Sartem                                 (hal_property_get_bool (p) ? "true" :
968*18c2aff7Sartem                                  "false"));
969*18c2aff7Sartem                         break;
970*18c2aff7Sartem 
971*18c2aff7Sartem                 default:
972*18c2aff7Sartem                         HAL_WARNING (("Unknown property type %d", type));
973*18c2aff7Sartem                         break;
974*18c2aff7Sartem                 }
975*18c2aff7Sartem         }
976*18c2aff7Sartem         fprintf (stderr, "\n");
977*18c2aff7Sartem }
978*18c2aff7Sartem 
979*18c2aff7Sartem 
980*18c2aff7Sartem typedef struct {
981*18c2aff7Sartem 	char *key;
982*18c2aff7Sartem 	HalDevice *device;
983*18c2aff7Sartem 	HalDeviceAsyncCallback callback;
984*18c2aff7Sartem 	gpointer user_data;
985*18c2aff7Sartem 
986*18c2aff7Sartem 	guint prop_signal_id;
987*18c2aff7Sartem 	guint timeout_id;
988*18c2aff7Sartem } AsyncMatchInfo;
989*18c2aff7Sartem 
990*18c2aff7Sartem static void
991*18c2aff7Sartem destroy_async_match_info (AsyncMatchInfo *ai)
992*18c2aff7Sartem {
993*18c2aff7Sartem 	g_free (ai->key);
994*18c2aff7Sartem 	g_signal_handler_disconnect (ai->device, ai->prop_signal_id);
995*18c2aff7Sartem 	g_source_remove (ai->timeout_id);
996*18c2aff7Sartem 	g_object_unref (ai->device);
997*18c2aff7Sartem 	g_free (ai);
998*18c2aff7Sartem }
999*18c2aff7Sartem 
1000*18c2aff7Sartem static void
1001*18c2aff7Sartem prop_changed_cb (HalDevice *device, const char *key,
1002*18c2aff7Sartem 		 gboolean removed, gboolean added, gpointer user_data)
1003*18c2aff7Sartem {
1004*18c2aff7Sartem 	AsyncMatchInfo *ai = user_data;
1005*18c2aff7Sartem 
1006*18c2aff7Sartem 	if (strcmp (key, ai->key) != 0)
1007*18c2aff7Sartem 		return;
1008*18c2aff7Sartem 
1009*18c2aff7Sartem 	/* the property is no longer there */
1010*18c2aff7Sartem 	if (removed)
1011*18c2aff7Sartem 		goto cleanup;
1012*18c2aff7Sartem 
1013*18c2aff7Sartem 
1014*18c2aff7Sartem 	ai->callback (ai->device, ai->user_data, TRUE);
1015*18c2aff7Sartem 
1016*18c2aff7Sartem cleanup:
1017*18c2aff7Sartem 	destroy_async_match_info (ai);
1018*18c2aff7Sartem }
1019*18c2aff7Sartem 
1020*18c2aff7Sartem 
1021*18c2aff7Sartem static gboolean
1022*18c2aff7Sartem async_wait_timeout (gpointer user_data)
1023*18c2aff7Sartem {
1024*18c2aff7Sartem 	AsyncMatchInfo *ai = (AsyncMatchInfo *) user_data;
1025*18c2aff7Sartem 
1026*18c2aff7Sartem 	ai->callback (ai->device, ai->user_data, FALSE);
1027*18c2aff7Sartem 
1028*18c2aff7Sartem 	destroy_async_match_info (ai);
1029*18c2aff7Sartem 
1030*18c2aff7Sartem 	return FALSE;
1031*18c2aff7Sartem }
1032*18c2aff7Sartem 
1033*18c2aff7Sartem void
1034*18c2aff7Sartem hal_device_async_wait_property (HalDevice    *device,
1035*18c2aff7Sartem 				const char   *key,
1036*18c2aff7Sartem 				HalDeviceAsyncCallback callback,
1037*18c2aff7Sartem 				gpointer     user_data,
1038*18c2aff7Sartem 				int          timeout)
1039*18c2aff7Sartem {
1040*18c2aff7Sartem 	HalProperty *prop;
1041*18c2aff7Sartem 	AsyncMatchInfo *ai;
1042*18c2aff7Sartem 
1043*18c2aff7Sartem 	/* check if property already exists */
1044*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1045*18c2aff7Sartem 
1046*18c2aff7Sartem 	if (prop != NULL || timeout==0) {
1047*18c2aff7Sartem 		callback (device, user_data, prop != NULL);
1048*18c2aff7Sartem 		return;
1049*18c2aff7Sartem 	}
1050*18c2aff7Sartem 
1051*18c2aff7Sartem 	ai = g_new0 (AsyncMatchInfo, 1);
1052*18c2aff7Sartem 
1053*18c2aff7Sartem 	ai->device = g_object_ref (device);
1054*18c2aff7Sartem 	ai->key = g_strdup (key);
1055*18c2aff7Sartem 	ai->callback = callback;
1056*18c2aff7Sartem 	ai->user_data = user_data;
1057*18c2aff7Sartem 
1058*18c2aff7Sartem 	ai->prop_signal_id = g_signal_connect (device, "property_changed",
1059*18c2aff7Sartem 					       G_CALLBACK (prop_changed_cb),
1060*18c2aff7Sartem 					       ai);
1061*18c2aff7Sartem 
1062*18c2aff7Sartem 	ai->timeout_id = g_timeout_add (timeout, async_wait_timeout, ai);
1063*18c2aff7Sartem }
1064*18c2aff7Sartem 
1065*18c2aff7Sartem void
1066*18c2aff7Sartem hal_device_callouts_finished (HalDevice *device)
1067*18c2aff7Sartem {
1068*18c2aff7Sartem 	g_signal_emit (device, signals[CALLOUTS_FINISHED], 0);
1069*18c2aff7Sartem }
1070*18c2aff7Sartem 
1071*18c2aff7Sartem /** Used when giving up on a device, e.g. if no device file appeared
1072*18c2aff7Sartem  */
1073*18c2aff7Sartem void
1074*18c2aff7Sartem hal_device_cancel (HalDevice *device)
1075*18c2aff7Sartem {
1076*18c2aff7Sartem 	HAL_INFO (("udi=%s", device->udi));
1077*18c2aff7Sartem 	g_signal_emit (device, signals[CANCELLED], 0);
1078*18c2aff7Sartem }
1079*18c2aff7Sartem 
1080*18c2aff7Sartem 
1081*18c2aff7Sartem 
1082*18c2aff7Sartem 
1083*18c2aff7Sartem GSList *
1084*18c2aff7Sartem hal_device_property_get_strlist (HalDevice    *device,
1085*18c2aff7Sartem 				 const char   *key)
1086*18c2aff7Sartem {
1087*18c2aff7Sartem 	HalProperty *prop;
1088*18c2aff7Sartem 
1089*18c2aff7Sartem 	g_return_val_if_fail (device != NULL, NULL);
1090*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
1091*18c2aff7Sartem 
1092*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1093*18c2aff7Sartem 
1094*18c2aff7Sartem 	if (prop != NULL)
1095*18c2aff7Sartem 		return hal_property_get_strlist (prop);
1096*18c2aff7Sartem 	else
1097*18c2aff7Sartem 		return NULL;
1098*18c2aff7Sartem }
1099*18c2aff7Sartem 
1100*18c2aff7Sartem const char *
1101*18c2aff7Sartem hal_device_property_get_strlist_elem (HalDevice    *device,
1102*18c2aff7Sartem 				      const char   *key,
1103*18c2aff7Sartem 				      guint index)
1104*18c2aff7Sartem {
1105*18c2aff7Sartem 	GSList *strlist;
1106*18c2aff7Sartem 	GSList *i;
1107*18c2aff7Sartem 
1108*18c2aff7Sartem 	strlist = hal_device_property_get_strlist (device, key);
1109*18c2aff7Sartem 	if (strlist == NULL)
1110*18c2aff7Sartem 		return NULL;
1111*18c2aff7Sartem 
1112*18c2aff7Sartem 	i = g_slist_nth (strlist, index);
1113*18c2aff7Sartem 	if (i == NULL)
1114*18c2aff7Sartem 		return NULL;
1115*18c2aff7Sartem 
1116*18c2aff7Sartem 	return (const char *) i->data;
1117*18c2aff7Sartem }
1118*18c2aff7Sartem 
1119*18c2aff7Sartem gboolean
1120*18c2aff7Sartem hal_device_property_strlist_append (HalDevice    *device,
1121*18c2aff7Sartem 				    const char   *key,
1122*18c2aff7Sartem 				    const char *value)
1123*18c2aff7Sartem {
1124*18c2aff7Sartem 	HalProperty *prop;
1125*18c2aff7Sartem 
1126*18c2aff7Sartem 	/* check if property already exists */
1127*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1128*18c2aff7Sartem 
1129*18c2aff7Sartem 	if (prop != NULL) {
1130*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
1131*18c2aff7Sartem 			return FALSE;
1132*18c2aff7Sartem 
1133*18c2aff7Sartem 		hal_property_strlist_append (prop, value);
1134*18c2aff7Sartem 
1135*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1136*18c2aff7Sartem 			       key, FALSE, FALSE);
1137*18c2aff7Sartem 
1138*18c2aff7Sartem 	} else {
1139*18c2aff7Sartem 		prop = hal_property_new_strlist (key);
1140*18c2aff7Sartem 		hal_property_strlist_append (prop, value);
1141*18c2aff7Sartem 
1142*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
1143*18c2aff7Sartem 
1144*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1145*18c2aff7Sartem 			       key, FALSE, TRUE);
1146*18c2aff7Sartem 	}
1147*18c2aff7Sartem 
1148*18c2aff7Sartem 	return TRUE;
1149*18c2aff7Sartem }
1150*18c2aff7Sartem 
1151*18c2aff7Sartem gboolean
1152*18c2aff7Sartem hal_device_property_strlist_prepend (HalDevice    *device,
1153*18c2aff7Sartem 				     const char   *key,
1154*18c2aff7Sartem 				     const char *value)
1155*18c2aff7Sartem {
1156*18c2aff7Sartem 	HalProperty *prop;
1157*18c2aff7Sartem 
1158*18c2aff7Sartem 	/* check if property already exists */
1159*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1160*18c2aff7Sartem 
1161*18c2aff7Sartem 	if (prop != NULL) {
1162*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
1163*18c2aff7Sartem 			return FALSE;
1164*18c2aff7Sartem 
1165*18c2aff7Sartem 		hal_property_strlist_prepend (prop, value);
1166*18c2aff7Sartem 
1167*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1168*18c2aff7Sartem 			       key, FALSE, FALSE);
1169*18c2aff7Sartem 
1170*18c2aff7Sartem 	} else {
1171*18c2aff7Sartem 		prop = hal_property_new_strlist (key);
1172*18c2aff7Sartem 		hal_property_strlist_prepend (prop, value);
1173*18c2aff7Sartem 
1174*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
1175*18c2aff7Sartem 
1176*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1177*18c2aff7Sartem 			       key, FALSE, TRUE);
1178*18c2aff7Sartem 	}
1179*18c2aff7Sartem 
1180*18c2aff7Sartem 	return TRUE;
1181*18c2aff7Sartem }
1182*18c2aff7Sartem 
1183*18c2aff7Sartem gboolean
1184*18c2aff7Sartem hal_device_property_strlist_remove_elem (HalDevice    *device,
1185*18c2aff7Sartem 					 const char   *key,
1186*18c2aff7Sartem 					 guint index)
1187*18c2aff7Sartem {
1188*18c2aff7Sartem 	HalProperty *prop;
1189*18c2aff7Sartem 
1190*18c2aff7Sartem 	/* check if property already exists */
1191*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1192*18c2aff7Sartem 
1193*18c2aff7Sartem 	if (prop == NULL)
1194*18c2aff7Sartem 		return FALSE;
1195*18c2aff7Sartem 
1196*18c2aff7Sartem 	if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
1197*18c2aff7Sartem 		return FALSE;
1198*18c2aff7Sartem 
1199*18c2aff7Sartem 	if (hal_property_strlist_remove_elem (prop, index)) {
1200*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1201*18c2aff7Sartem 			       key, FALSE, FALSE);
1202*18c2aff7Sartem 		return TRUE;
1203*18c2aff7Sartem 	}
1204*18c2aff7Sartem 
1205*18c2aff7Sartem 	return FALSE;
1206*18c2aff7Sartem }
1207*18c2aff7Sartem 
1208*18c2aff7Sartem gboolean
1209*18c2aff7Sartem hal_device_property_strlist_clear (HalDevice    *device,
1210*18c2aff7Sartem 				   const char   *key)
1211*18c2aff7Sartem {
1212*18c2aff7Sartem 	HalProperty *prop;
1213*18c2aff7Sartem 
1214*18c2aff7Sartem 	/* check if property already exists */
1215*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1216*18c2aff7Sartem 
1217*18c2aff7Sartem 	if (prop == NULL) {
1218*18c2aff7Sartem 		prop = hal_property_new_strlist (key);
1219*18c2aff7Sartem 
1220*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
1221*18c2aff7Sartem 
1222*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1223*18c2aff7Sartem 			       key, FALSE, TRUE);
1224*18c2aff7Sartem 
1225*18c2aff7Sartem 		return TRUE;
1226*18c2aff7Sartem 	}
1227*18c2aff7Sartem 
1228*18c2aff7Sartem 	if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
1229*18c2aff7Sartem 		return FALSE;
1230*18c2aff7Sartem 
1231*18c2aff7Sartem 	if (hal_property_strlist_clear (prop)) {
1232*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1233*18c2aff7Sartem 			       key, FALSE, FALSE);
1234*18c2aff7Sartem 		return TRUE;
1235*18c2aff7Sartem 	}
1236*18c2aff7Sartem 
1237*18c2aff7Sartem 	return FALSE;
1238*18c2aff7Sartem }
1239*18c2aff7Sartem 
1240*18c2aff7Sartem 
1241*18c2aff7Sartem gboolean
1242*18c2aff7Sartem hal_device_property_strlist_add (HalDevice *device,
1243*18c2aff7Sartem 				 const char *key,
1244*18c2aff7Sartem 				 const char *value)
1245*18c2aff7Sartem {
1246*18c2aff7Sartem 	HalProperty *prop;
1247*18c2aff7Sartem 	gboolean res;
1248*18c2aff7Sartem 
1249*18c2aff7Sartem 	res = FALSE;
1250*18c2aff7Sartem 
1251*18c2aff7Sartem 	/* check if property already exists */
1252*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1253*18c2aff7Sartem 
1254*18c2aff7Sartem 	if (prop != NULL) {
1255*18c2aff7Sartem 		if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
1256*18c2aff7Sartem 			goto out;
1257*18c2aff7Sartem 
1258*18c2aff7Sartem 		res = hal_property_strlist_add (prop, value);
1259*18c2aff7Sartem 		if (res) {
1260*18c2aff7Sartem 			g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1261*18c2aff7Sartem 				       key, FALSE, FALSE);
1262*18c2aff7Sartem 		}
1263*18c2aff7Sartem 
1264*18c2aff7Sartem 	} else {
1265*18c2aff7Sartem 		prop = hal_property_new_strlist (key);
1266*18c2aff7Sartem 		hal_property_strlist_prepend (prop, value);
1267*18c2aff7Sartem 
1268*18c2aff7Sartem 		device->properties = g_slist_prepend (device->properties, prop);
1269*18c2aff7Sartem 
1270*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1271*18c2aff7Sartem 			       key, FALSE, TRUE);
1272*18c2aff7Sartem 
1273*18c2aff7Sartem 		res = TRUE;
1274*18c2aff7Sartem 	}
1275*18c2aff7Sartem 
1276*18c2aff7Sartem out:
1277*18c2aff7Sartem 	return res;
1278*18c2aff7Sartem }
1279*18c2aff7Sartem 
1280*18c2aff7Sartem gboolean
1281*18c2aff7Sartem hal_device_property_strlist_remove (HalDevice *device,
1282*18c2aff7Sartem 				    const char *key,
1283*18c2aff7Sartem 				    const char *value)
1284*18c2aff7Sartem {
1285*18c2aff7Sartem 	HalProperty *prop;
1286*18c2aff7Sartem 
1287*18c2aff7Sartem 	/* check if property already exists */
1288*18c2aff7Sartem 	prop = hal_device_property_find (device, key);
1289*18c2aff7Sartem 
1290*18c2aff7Sartem 	if (prop == NULL)
1291*18c2aff7Sartem 		return FALSE;
1292*18c2aff7Sartem 
1293*18c2aff7Sartem 	if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
1294*18c2aff7Sartem 		return FALSE;
1295*18c2aff7Sartem 
1296*18c2aff7Sartem 	if (hal_property_strlist_remove (prop, value)) {
1297*18c2aff7Sartem 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
1298*18c2aff7Sartem 			       key, FALSE, FALSE);
1299*18c2aff7Sartem 	}
1300*18c2aff7Sartem 
1301*18c2aff7Sartem 	return TRUE;
1302*18c2aff7Sartem }
1303*18c2aff7Sartem 
1304*18c2aff7Sartem gboolean
1305*18c2aff7Sartem hal_device_property_strlist_is_empty (HalDevice    *device,
1306*18c2aff7Sartem 				      const char   *key)
1307*18c2aff7Sartem {
1308*18c2aff7Sartem 	GSList *strlist;
1309*18c2aff7Sartem 
1310*18c2aff7Sartem 	if ( hal_device_has_property (device, key)) {
1311*18c2aff7Sartem 		strlist = hal_device_property_get_strlist (device, key);
1312*18c2aff7Sartem 		if (strlist == NULL )
1313*18c2aff7Sartem 			return TRUE;
1314*18c2aff7Sartem 
1315*18c2aff7Sartem 		if (g_slist_length (strlist) > 0)
1316*18c2aff7Sartem 			return FALSE;
1317*18c2aff7Sartem 		else
1318*18c2aff7Sartem 			return TRUE;
1319*18c2aff7Sartem 	}
1320*18c2aff7Sartem 	return FALSE;
1321*18c2aff7Sartem }
1322*18c2aff7Sartem 
1323*18c2aff7Sartem void
1324*18c2aff7Sartem hal_device_inc_num_addons (HalDevice *device)
1325*18c2aff7Sartem {
1326*18c2aff7Sartem 	device->num_addons++;
1327*18c2aff7Sartem }
1328*18c2aff7Sartem 
1329*18c2aff7Sartem gboolean
1330*18c2aff7Sartem hal_device_inc_num_ready_addons (HalDevice *device)
1331*18c2aff7Sartem {
1332*18c2aff7Sartem 	if (hal_device_are_all_addons_ready (device)) {
1333*18c2aff7Sartem 		HAL_ERROR (("In hal_device_inc_num_ready_addons for udi=%s but all addons are already ready!",
1334*18c2aff7Sartem 			    device->udi));
1335*18c2aff7Sartem 		return FALSE;
1336*18c2aff7Sartem 	}
1337*18c2aff7Sartem 
1338*18c2aff7Sartem 	device->num_addons_ready++;
1339*18c2aff7Sartem 	return TRUE;
1340*18c2aff7Sartem }
1341*18c2aff7Sartem 
1342*18c2aff7Sartem gboolean
1343*18c2aff7Sartem hal_device_are_all_addons_ready (HalDevice *device)
1344*18c2aff7Sartem {
1345*18c2aff7Sartem 	if (device->num_addons_ready == device->num_addons) {
1346*18c2aff7Sartem 		return TRUE;
1347*18c2aff7Sartem 	} else {
1348*18c2aff7Sartem 		return FALSE;
1349*18c2aff7Sartem 	}
1350*18c2aff7Sartem }
1351