xref: /illumos-gate/usr/src/cmd/hal/hald/device_store.c (revision 18c2aff7)
1*18c2aff7Sartem /***************************************************************************
2*18c2aff7Sartem  * CVSID: $Id$
3*18c2aff7Sartem  *
4*18c2aff7Sartem  * device_store.c : HalDeviceStore 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 "device_store.h"
35*18c2aff7Sartem #include "hald_marshal.h"
36*18c2aff7Sartem #include "logger.h"
37*18c2aff7Sartem 
38*18c2aff7Sartem static GObjectClass *parent_class;
39*18c2aff7Sartem 
40*18c2aff7Sartem enum {
41*18c2aff7Sartem 	STORE_CHANGED,
42*18c2aff7Sartem 	DEVICE_PROPERTY_CHANGED,
43*18c2aff7Sartem 	DEVICE_CAPABILITY_ADDED,
44*18c2aff7Sartem 	LAST_SIGNAL
45*18c2aff7Sartem };
46*18c2aff7Sartem 
47*18c2aff7Sartem static guint signals[LAST_SIGNAL] = { 0 };
48*18c2aff7Sartem 
49*18c2aff7Sartem static void
50*18c2aff7Sartem hal_device_store_finalize (GObject *obj)
51*18c2aff7Sartem {
52*18c2aff7Sartem 	HalDeviceStore *store = HAL_DEVICE_STORE (obj);
53*18c2aff7Sartem 
54*18c2aff7Sartem 	g_slist_foreach (store->devices, (GFunc) g_object_unref, NULL);
55*18c2aff7Sartem 
56*18c2aff7Sartem 	if (parent_class->finalize)
57*18c2aff7Sartem 		parent_class->finalize (obj);
58*18c2aff7Sartem }
59*18c2aff7Sartem 
60*18c2aff7Sartem static void
61*18c2aff7Sartem hal_device_store_class_init (HalDeviceStoreClass *klass)
62*18c2aff7Sartem {
63*18c2aff7Sartem 	GObjectClass *obj_class = (GObjectClass *) klass;
64*18c2aff7Sartem 
65*18c2aff7Sartem 	parent_class = g_type_class_peek_parent (klass);
66*18c2aff7Sartem 
67*18c2aff7Sartem 	obj_class->finalize = hal_device_store_finalize;
68*18c2aff7Sartem 
69*18c2aff7Sartem 	signals[STORE_CHANGED] =
70*18c2aff7Sartem 		g_signal_new ("store_changed",
71*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
72*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
73*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceStoreClass,
74*18c2aff7Sartem 					       store_changed),
75*18c2aff7Sartem 			      NULL, NULL,
76*18c2aff7Sartem 			      hald_marshal_VOID__OBJECT_BOOL,
77*18c2aff7Sartem 			      G_TYPE_NONE, 2,
78*18c2aff7Sartem 			      G_TYPE_OBJECT,
79*18c2aff7Sartem 			      G_TYPE_BOOLEAN);
80*18c2aff7Sartem 
81*18c2aff7Sartem 	signals[DEVICE_PROPERTY_CHANGED] =
82*18c2aff7Sartem 		g_signal_new ("device_property_changed",
83*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
84*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
85*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceStoreClass,
86*18c2aff7Sartem 					       device_property_changed),
87*18c2aff7Sartem 			      NULL, NULL,
88*18c2aff7Sartem 			      hald_marshal_VOID__OBJECT_STRING_BOOL_BOOL,
89*18c2aff7Sartem 			      G_TYPE_NONE, 4,
90*18c2aff7Sartem 			      G_TYPE_OBJECT,
91*18c2aff7Sartem 			      G_TYPE_STRING,
92*18c2aff7Sartem 			      G_TYPE_BOOLEAN,
93*18c2aff7Sartem 			      G_TYPE_BOOLEAN);
94*18c2aff7Sartem 
95*18c2aff7Sartem 	signals[DEVICE_CAPABILITY_ADDED] =
96*18c2aff7Sartem 		g_signal_new ("device_capability_added",
97*18c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
98*18c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
99*18c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceStoreClass,
100*18c2aff7Sartem 					       device_capability_added),
101*18c2aff7Sartem 			      NULL, NULL,
102*18c2aff7Sartem 			      hald_marshal_VOID__OBJECT_STRING,
103*18c2aff7Sartem 			      G_TYPE_NONE, 2,
104*18c2aff7Sartem 			      G_TYPE_OBJECT,
105*18c2aff7Sartem 			      G_TYPE_STRING);
106*18c2aff7Sartem }
107*18c2aff7Sartem 
108*18c2aff7Sartem static void
109*18c2aff7Sartem hal_device_store_init (HalDeviceStore *device)
110*18c2aff7Sartem {
111*18c2aff7Sartem }
112*18c2aff7Sartem 
113*18c2aff7Sartem GType
114*18c2aff7Sartem hal_device_store_get_type (void)
115*18c2aff7Sartem {
116*18c2aff7Sartem 	static GType type = 0;
117*18c2aff7Sartem 
118*18c2aff7Sartem 	if (!type) {
119*18c2aff7Sartem 		static GTypeInfo type_info = {
120*18c2aff7Sartem 			sizeof (HalDeviceStoreClass),
121*18c2aff7Sartem 			NULL, NULL,
122*18c2aff7Sartem 			(GClassInitFunc) hal_device_store_class_init,
123*18c2aff7Sartem 			NULL, NULL,
124*18c2aff7Sartem 			sizeof (HalDeviceStore),
125*18c2aff7Sartem 			0,
126*18c2aff7Sartem 			(GInstanceInitFunc) hal_device_store_init
127*18c2aff7Sartem 		};
128*18c2aff7Sartem 
129*18c2aff7Sartem 		type = g_type_register_static (G_TYPE_OBJECT,
130*18c2aff7Sartem 					       "HalDeviceStore",
131*18c2aff7Sartem 					       &type_info,
132*18c2aff7Sartem 					       0);
133*18c2aff7Sartem 	}
134*18c2aff7Sartem 
135*18c2aff7Sartem 	return type;
136*18c2aff7Sartem }
137*18c2aff7Sartem 
138*18c2aff7Sartem HalDeviceStore *
139*18c2aff7Sartem hal_device_store_new (void)
140*18c2aff7Sartem {
141*18c2aff7Sartem 	HalDeviceStore *store;
142*18c2aff7Sartem 
143*18c2aff7Sartem 	store = g_object_new (HAL_TYPE_DEVICE_STORE, NULL, NULL);
144*18c2aff7Sartem 
145*18c2aff7Sartem 	return store;
146*18c2aff7Sartem }
147*18c2aff7Sartem 
148*18c2aff7Sartem static void
149*18c2aff7Sartem emit_device_property_changed (HalDevice *device,
150*18c2aff7Sartem 			      const char *key,
151*18c2aff7Sartem 			      gboolean added,
152*18c2aff7Sartem 			      gboolean removed,
153*18c2aff7Sartem 			      gpointer data)
154*18c2aff7Sartem {
155*18c2aff7Sartem 	HalDeviceStore *store = HAL_DEVICE_STORE (data);
156*18c2aff7Sartem 
157*18c2aff7Sartem 	g_signal_emit (store, signals[DEVICE_PROPERTY_CHANGED], 0,
158*18c2aff7Sartem 		       device, key, added, removed);
159*18c2aff7Sartem }
160*18c2aff7Sartem 
161*18c2aff7Sartem static void
162*18c2aff7Sartem emit_device_capability_added (HalDevice *device,
163*18c2aff7Sartem 			      const char *capability,
164*18c2aff7Sartem 			      gpointer data)
165*18c2aff7Sartem {
166*18c2aff7Sartem 	HalDeviceStore *store = HAL_DEVICE_STORE (data);
167*18c2aff7Sartem 
168*18c2aff7Sartem 	g_signal_emit (store, signals[DEVICE_CAPABILITY_ADDED], 0,
169*18c2aff7Sartem 		       device, capability);
170*18c2aff7Sartem }
171*18c2aff7Sartem 
172*18c2aff7Sartem void
173*18c2aff7Sartem hal_device_store_add (HalDeviceStore *store, HalDevice *device)
174*18c2aff7Sartem {
175*18c2aff7Sartem 	const char buf[] = "/org/freedesktop/Hal/devices/";
176*18c2aff7Sartem 
177*18c2aff7Sartem 	if (strncmp(device->udi, buf, sizeof (buf) - 1) != 0) {
178*18c2aff7Sartem 
179*18c2aff7Sartem 		HAL_ERROR(("Can't add HalDevice with incorrect UDI. Valid "
180*18c2aff7Sartem 			   "UDI must start with '/org/freedesktop/Hal/devices/'"));
181*18c2aff7Sartem 		goto out;
182*18c2aff7Sartem 	}
183*18c2aff7Sartem 	store->devices = g_slist_prepend (store->devices,
184*18c2aff7Sartem 					  g_object_ref (device));
185*18c2aff7Sartem 
186*18c2aff7Sartem 	g_signal_connect (device, "property_changed",
187*18c2aff7Sartem 			  G_CALLBACK (emit_device_property_changed), store);
188*18c2aff7Sartem 	g_signal_connect (device, "capability_added",
189*18c2aff7Sartem 			  G_CALLBACK (emit_device_capability_added), store);
190*18c2aff7Sartem 
191*18c2aff7Sartem 	g_signal_emit (store, signals[STORE_CHANGED], 0, device, TRUE);
192*18c2aff7Sartem 
193*18c2aff7Sartem out:
194*18c2aff7Sartem 	;
195*18c2aff7Sartem }
196*18c2aff7Sartem 
197*18c2aff7Sartem gboolean
198*18c2aff7Sartem hal_device_store_remove (HalDeviceStore *store, HalDevice *device)
199*18c2aff7Sartem {
200*18c2aff7Sartem 	if (!g_slist_find (store->devices, device))
201*18c2aff7Sartem 		return FALSE;
202*18c2aff7Sartem 
203*18c2aff7Sartem 	store->devices = g_slist_remove (store->devices, device);
204*18c2aff7Sartem 
205*18c2aff7Sartem 	g_signal_handlers_disconnect_by_func (device,
206*18c2aff7Sartem 					      (gpointer)emit_device_property_changed,
207*18c2aff7Sartem 					      store);
208*18c2aff7Sartem 	g_signal_handlers_disconnect_by_func (device,
209*18c2aff7Sartem 					      (gpointer)emit_device_capability_added,
210*18c2aff7Sartem 					      store);
211*18c2aff7Sartem 
212*18c2aff7Sartem 	g_signal_emit (store, signals[STORE_CHANGED], 0, device, FALSE);
213*18c2aff7Sartem 
214*18c2aff7Sartem 	g_object_unref (device);
215*18c2aff7Sartem 
216*18c2aff7Sartem 	return TRUE;
217*18c2aff7Sartem }
218*18c2aff7Sartem 
219*18c2aff7Sartem HalDevice *
220*18c2aff7Sartem hal_device_store_find (HalDeviceStore *store, const char *udi)
221*18c2aff7Sartem {
222*18c2aff7Sartem 	GSList *iter;
223*18c2aff7Sartem 
224*18c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
225*18c2aff7Sartem 		HalDevice *d = iter->data;
226*18c2aff7Sartem 
227*18c2aff7Sartem 		if (strcmp (hal_device_get_udi (d), udi) == 0)
228*18c2aff7Sartem 			return d;
229*18c2aff7Sartem 	}
230*18c2aff7Sartem 
231*18c2aff7Sartem 	return NULL;
232*18c2aff7Sartem }
233*18c2aff7Sartem 
234*18c2aff7Sartem void
235*18c2aff7Sartem hal_device_store_foreach (HalDeviceStore *store,
236*18c2aff7Sartem 			  HalDeviceStoreForeachFn callback,
237*18c2aff7Sartem 			  gpointer user_data)
238*18c2aff7Sartem {
239*18c2aff7Sartem 	GSList *iter;
240*18c2aff7Sartem 
241*18c2aff7Sartem 	g_return_if_fail (store != NULL);
242*18c2aff7Sartem 	g_return_if_fail (callback != NULL);
243*18c2aff7Sartem 
244*18c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
245*18c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
246*18c2aff7Sartem 		gboolean cont;
247*18c2aff7Sartem 
248*18c2aff7Sartem 		cont = callback (store, d, user_data);
249*18c2aff7Sartem 
250*18c2aff7Sartem 		if (cont == FALSE)
251*18c2aff7Sartem 			return;
252*18c2aff7Sartem 	}
253*18c2aff7Sartem }
254*18c2aff7Sartem 
255*18c2aff7Sartem static gboolean
256*18c2aff7Sartem hal_device_store_print_foreach_fn (HalDeviceStore *store,
257*18c2aff7Sartem 				   HalDevice *device,
258*18c2aff7Sartem 				   gpointer user_data)
259*18c2aff7Sartem {
260*18c2aff7Sartem 	fprintf (stderr, "----\n");
261*18c2aff7Sartem 	hal_device_print (device);
262*18c2aff7Sartem 	fprintf (stderr, "----\n");
263*18c2aff7Sartem 	return TRUE;
264*18c2aff7Sartem }
265*18c2aff7Sartem 
266*18c2aff7Sartem void
267*18c2aff7Sartem hal_device_store_print (HalDeviceStore *store)
268*18c2aff7Sartem {
269*18c2aff7Sartem 	fprintf (stderr, "===============================================\n");
270*18c2aff7Sartem         fprintf (stderr, "Dumping %d devices\n",
271*18c2aff7Sartem 		 g_slist_length (store->devices));
272*18c2aff7Sartem 	fprintf (stderr, "===============================================\n");
273*18c2aff7Sartem 	hal_device_store_foreach (store,
274*18c2aff7Sartem 				  hal_device_store_print_foreach_fn,
275*18c2aff7Sartem 				  NULL);
276*18c2aff7Sartem 	fprintf (stderr, "===============================================\n");
277*18c2aff7Sartem }
278*18c2aff7Sartem 
279*18c2aff7Sartem HalDevice *
280*18c2aff7Sartem hal_device_store_match_key_value_string (HalDeviceStore *store,
281*18c2aff7Sartem 					 const char *key,
282*18c2aff7Sartem 					 const char *value)
283*18c2aff7Sartem {
284*18c2aff7Sartem 	GSList *iter;
285*18c2aff7Sartem 
286*18c2aff7Sartem 	g_return_val_if_fail (store != NULL, NULL);
287*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
288*18c2aff7Sartem 	g_return_val_if_fail (value != NULL, NULL);
289*18c2aff7Sartem 
290*18c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
291*18c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
292*18c2aff7Sartem 		int type;
293*18c2aff7Sartem 
294*18c2aff7Sartem 		if (!hal_device_has_property (d, key))
295*18c2aff7Sartem 			continue;
296*18c2aff7Sartem 
297*18c2aff7Sartem 		type = hal_device_property_get_type (d, key);
298*18c2aff7Sartem 		if (type != HAL_PROPERTY_TYPE_STRING)
299*18c2aff7Sartem 			continue;
300*18c2aff7Sartem 
301*18c2aff7Sartem 		if (strcmp (hal_device_property_get_string (d, key),
302*18c2aff7Sartem 			    value) == 0)
303*18c2aff7Sartem 			return d;
304*18c2aff7Sartem 	}
305*18c2aff7Sartem 
306*18c2aff7Sartem 	return NULL;
307*18c2aff7Sartem }
308*18c2aff7Sartem 
309*18c2aff7Sartem HalDevice *
310*18c2aff7Sartem hal_device_store_match_key_value_int (HalDeviceStore *store,
311*18c2aff7Sartem 				      const char *key,
312*18c2aff7Sartem 				      int value)
313*18c2aff7Sartem {
314*18c2aff7Sartem 	GSList *iter;
315*18c2aff7Sartem 
316*18c2aff7Sartem 	g_return_val_if_fail (store != NULL, NULL);
317*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
318*18c2aff7Sartem 
319*18c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
320*18c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
321*18c2aff7Sartem 		int type;
322*18c2aff7Sartem 
323*18c2aff7Sartem 		if (!hal_device_has_property (d, key))
324*18c2aff7Sartem 			continue;
325*18c2aff7Sartem 
326*18c2aff7Sartem 		type = hal_device_property_get_type (d, key);
327*18c2aff7Sartem 		if (type != HAL_PROPERTY_TYPE_INT32)
328*18c2aff7Sartem 			continue;
329*18c2aff7Sartem 
330*18c2aff7Sartem 		if (hal_device_property_get_int (d, key) == value)
331*18c2aff7Sartem 			return d;
332*18c2aff7Sartem 	}
333*18c2aff7Sartem 
334*18c2aff7Sartem 	return NULL;
335*18c2aff7Sartem }
336*18c2aff7Sartem 
337*18c2aff7Sartem GSList *
338*18c2aff7Sartem hal_device_store_match_multiple_key_value_string (HalDeviceStore *store,
339*18c2aff7Sartem 						  const char *key,
340*18c2aff7Sartem 						  const char *value)
341*18c2aff7Sartem {
342*18c2aff7Sartem 	GSList *iter;
343*18c2aff7Sartem 	GSList *matches = NULL;
344*18c2aff7Sartem 
345*18c2aff7Sartem 	g_return_val_if_fail (store != NULL, NULL);
346*18c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
347*18c2aff7Sartem 	g_return_val_if_fail (value != NULL, NULL);
348*18c2aff7Sartem 
349*18c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
350*18c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
351*18c2aff7Sartem 		int type;
352*18c2aff7Sartem 
353*18c2aff7Sartem 		if (!hal_device_has_property (d, key))
354*18c2aff7Sartem 			continue;
355*18c2aff7Sartem 
356*18c2aff7Sartem 		type = hal_device_property_get_type (d, key);
357*18c2aff7Sartem 		if (type != HAL_PROPERTY_TYPE_STRING)
358*18c2aff7Sartem 			continue;
359*18c2aff7Sartem 
360*18c2aff7Sartem 		if (strcmp (hal_device_property_get_string (d, key),
361*18c2aff7Sartem 			    value) == 0)
362*18c2aff7Sartem 			matches = g_slist_prepend (matches, d);
363*18c2aff7Sartem 	}
364*18c2aff7Sartem 
365*18c2aff7Sartem 	return matches;
366*18c2aff7Sartem }
367*18c2aff7Sartem 
368*18c2aff7Sartem typedef struct {
369*18c2aff7Sartem 	HalDeviceStore *store;
370*18c2aff7Sartem 	char *key;
371*18c2aff7Sartem 	char *value;
372*18c2aff7Sartem 	HalDeviceStoreAsyncCallback callback;
373*18c2aff7Sartem 	gpointer user_data;
374*18c2aff7Sartem 
375*18c2aff7Sartem 	guint prop_signal_id;
376*18c2aff7Sartem 	guint store_signal_id;
377*18c2aff7Sartem 	guint timeout_id;
378*18c2aff7Sartem } AsyncMatchInfo;
379*18c2aff7Sartem 
380*18c2aff7Sartem static void
381*18c2aff7Sartem destroy_async_match_info (AsyncMatchInfo *info)
382*18c2aff7Sartem {
383*18c2aff7Sartem 	g_object_unref (info->store);
384*18c2aff7Sartem 
385*18c2aff7Sartem 	g_free (info->key);
386*18c2aff7Sartem 	g_free (info->value);
387*18c2aff7Sartem 
388*18c2aff7Sartem 	g_signal_handler_disconnect (info->store, info->prop_signal_id);
389*18c2aff7Sartem 	g_signal_handler_disconnect (info->store, info->store_signal_id);
390*18c2aff7Sartem 	g_source_remove (info->timeout_id);
391*18c2aff7Sartem 
392*18c2aff7Sartem 	g_free (info);
393*18c2aff7Sartem }
394*18c2aff7Sartem 
395*18c2aff7Sartem static void
396*18c2aff7Sartem match_device_async (HalDeviceStore *store, HalDevice *device,
397*18c2aff7Sartem 		    const char *key, gboolean removed, gboolean added,
398*18c2aff7Sartem 		    gpointer user_data)
399*18c2aff7Sartem {
400*18c2aff7Sartem 	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
401*18c2aff7Sartem 
402*18c2aff7Sartem 	/* Only want to do it for added or changed properties */
403*18c2aff7Sartem 	if (removed)
404*18c2aff7Sartem 		return;
405*18c2aff7Sartem 
406*18c2aff7Sartem 	/* Keys have to match */
407*18c2aff7Sartem 	if (strcmp (info->key, key) != 0)
408*18c2aff7Sartem 		return;
409*18c2aff7Sartem 
410*18c2aff7Sartem 	/* Values have to match */
411*18c2aff7Sartem 	if (strcmp (hal_device_property_get_string (device, key),
412*18c2aff7Sartem 		    info->value) != 0)
413*18c2aff7Sartem 		return;
414*18c2aff7Sartem 
415*18c2aff7Sartem 	info->callback (store, device, info->user_data);
416*18c2aff7Sartem 
417*18c2aff7Sartem 	destroy_async_match_info (info);
418*18c2aff7Sartem }
419*18c2aff7Sartem 
420*18c2aff7Sartem static void
421*18c2aff7Sartem store_changed (HalDeviceStore *store, HalDevice *device,
422*18c2aff7Sartem 	       gboolean added, gpointer user_data)
423*18c2aff7Sartem {
424*18c2aff7Sartem 	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
425*18c2aff7Sartem 
426*18c2aff7Sartem 	if (!added)
427*18c2aff7Sartem 		return;
428*18c2aff7Sartem 
429*18c2aff7Sartem 	if (!hal_device_has_property (device, info->key))
430*18c2aff7Sartem 		return;
431*18c2aff7Sartem 
432*18c2aff7Sartem 	if (strcmp (hal_device_property_get_string (device, info->key),
433*18c2aff7Sartem 		    info->value) != 0)
434*18c2aff7Sartem 		return;
435*18c2aff7Sartem 
436*18c2aff7Sartem 	info->callback (store, device, info->user_data);
437*18c2aff7Sartem 
438*18c2aff7Sartem 	destroy_async_match_info (info);
439*18c2aff7Sartem }
440*18c2aff7Sartem 
441*18c2aff7Sartem static gboolean
442*18c2aff7Sartem match_device_async_timeout (gpointer user_data)
443*18c2aff7Sartem {
444*18c2aff7Sartem 	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
445*18c2aff7Sartem 
446*18c2aff7Sartem 	info->callback (info->store, NULL, info->user_data);
447*18c2aff7Sartem 
448*18c2aff7Sartem 	destroy_async_match_info (info);
449*18c2aff7Sartem 
450*18c2aff7Sartem 	return FALSE;
451*18c2aff7Sartem }
452*18c2aff7Sartem 
453*18c2aff7Sartem void
454*18c2aff7Sartem hal_device_store_match_key_value_string_async (HalDeviceStore *store,
455*18c2aff7Sartem 					       const char *key,
456*18c2aff7Sartem 					       const char *value,
457*18c2aff7Sartem 					       HalDeviceStoreAsyncCallback callback,
458*18c2aff7Sartem 					       gpointer user_data,
459*18c2aff7Sartem 					       int timeout)
460*18c2aff7Sartem {
461*18c2aff7Sartem 	HalDevice *device;
462*18c2aff7Sartem 	AsyncMatchInfo *info;
463*18c2aff7Sartem 
464*18c2aff7Sartem 	/* First check to see if it's already there */
465*18c2aff7Sartem 	device = hal_device_store_match_key_value_string (store, key, value);
466*18c2aff7Sartem 
467*18c2aff7Sartem 	if (device != NULL || timeout == 0) {
468*18c2aff7Sartem 		callback (store, device, user_data);
469*18c2aff7Sartem 
470*18c2aff7Sartem 		return;
471*18c2aff7Sartem 	}
472*18c2aff7Sartem 
473*18c2aff7Sartem 	info = g_new0 (AsyncMatchInfo, 1);
474*18c2aff7Sartem 
475*18c2aff7Sartem 	info->store = g_object_ref (store);
476*18c2aff7Sartem 	info->key = g_strdup (key);
477*18c2aff7Sartem 	info->value = g_strdup (value);
478*18c2aff7Sartem 	info->callback = callback;
479*18c2aff7Sartem 	info->user_data = user_data;
480*18c2aff7Sartem 
481*18c2aff7Sartem 	info->prop_signal_id = g_signal_connect (store,
482*18c2aff7Sartem 						 "device_property_changed",
483*18c2aff7Sartem 						 G_CALLBACK (match_device_async),
484*18c2aff7Sartem 						 info);
485*18c2aff7Sartem 	info->store_signal_id = g_signal_connect (store,
486*18c2aff7Sartem 						  "store_changed",
487*18c2aff7Sartem 						  G_CALLBACK (store_changed),
488*18c2aff7Sartem 						  info);
489*18c2aff7Sartem 
490*18c2aff7Sartem 	info->timeout_id = g_timeout_add (timeout,
491*18c2aff7Sartem 					  match_device_async_timeout,
492*18c2aff7Sartem 					  info);
493*18c2aff7Sartem }
494