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