xref: /illumos-gate/usr/src/cmd/hal/hald/device_store.c (revision 55fea89d)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  * CVSID: $Id$
318c2aff7Sartem  *
418c2aff7Sartem  * device_store.c : HalDeviceStore methods
518c2aff7Sartem  *
618c2aff7Sartem  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
718c2aff7Sartem  * Copyright (C) 2004 Novell, Inc.
818c2aff7Sartem  *
918c2aff7Sartem  * Licensed under the Academic Free License version 2.1
1018c2aff7Sartem  *
1118c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
1218c2aff7Sartem  * it under the terms of the GNU General Public License as published by
1318c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
1418c2aff7Sartem  * (at your option) any later version.
1518c2aff7Sartem  *
1618c2aff7Sartem  * This program is distributed in the hope that it will be useful,
1718c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1818c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1918c2aff7Sartem  * GNU General Public License for more details.
2018c2aff7Sartem  *
2118c2aff7Sartem  * You should have received a copy of the GNU General Public License
2218c2aff7Sartem  * along with this program; if not, write to the Free Software
2318c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2418c2aff7Sartem  *
2518c2aff7Sartem  **************************************************************************/
2618c2aff7Sartem 
2718c2aff7Sartem #ifdef HAVE_CONFIG_H
2818c2aff7Sartem #  include <config.h>
2918c2aff7Sartem #endif
3018c2aff7Sartem 
3118c2aff7Sartem #include <stdio.h>
3218c2aff7Sartem #include <string.h>
3318c2aff7Sartem 
3418c2aff7Sartem #include "device_store.h"
3518c2aff7Sartem #include "hald_marshal.h"
3618c2aff7Sartem #include "logger.h"
3718c2aff7Sartem 
3818c2aff7Sartem static GObjectClass *parent_class;
3918c2aff7Sartem 
4018c2aff7Sartem enum {
4118c2aff7Sartem 	STORE_CHANGED,
4218c2aff7Sartem 	DEVICE_PROPERTY_CHANGED,
4318c2aff7Sartem 	DEVICE_CAPABILITY_ADDED,
4418c2aff7Sartem 	LAST_SIGNAL
4518c2aff7Sartem };
4618c2aff7Sartem 
4718c2aff7Sartem static guint signals[LAST_SIGNAL] = { 0 };
4818c2aff7Sartem 
4918c2aff7Sartem static void
hal_device_store_finalize(GObject * obj)5018c2aff7Sartem hal_device_store_finalize (GObject *obj)
5118c2aff7Sartem {
5218c2aff7Sartem 	HalDeviceStore *store = HAL_DEVICE_STORE (obj);
5318c2aff7Sartem 
5418c2aff7Sartem 	g_slist_foreach (store->devices, (GFunc) g_object_unref, NULL);
5518c2aff7Sartem 
5618c2aff7Sartem 	if (parent_class->finalize)
5718c2aff7Sartem 		parent_class->finalize (obj);
5818c2aff7Sartem }
5918c2aff7Sartem 
6018c2aff7Sartem static void
hal_device_store_class_init(HalDeviceStoreClass * klass)6118c2aff7Sartem hal_device_store_class_init (HalDeviceStoreClass *klass)
6218c2aff7Sartem {
6318c2aff7Sartem 	GObjectClass *obj_class = (GObjectClass *) klass;
6418c2aff7Sartem 
6518c2aff7Sartem 	parent_class = g_type_class_peek_parent (klass);
6618c2aff7Sartem 
6718c2aff7Sartem 	obj_class->finalize = hal_device_store_finalize;
6818c2aff7Sartem 
6918c2aff7Sartem 	signals[STORE_CHANGED] =
7018c2aff7Sartem 		g_signal_new ("store_changed",
7118c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
7218c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
7318c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceStoreClass,
7418c2aff7Sartem 					       store_changed),
7518c2aff7Sartem 			      NULL, NULL,
76*9dca21dfSAndy Fiddaman 			      hald_marshal_VOID__OBJECT_BOOLEAN,
7718c2aff7Sartem 			      G_TYPE_NONE, 2,
7818c2aff7Sartem 			      G_TYPE_OBJECT,
7918c2aff7Sartem 			      G_TYPE_BOOLEAN);
8018c2aff7Sartem 
8118c2aff7Sartem 	signals[DEVICE_PROPERTY_CHANGED] =
8218c2aff7Sartem 		g_signal_new ("device_property_changed",
8318c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
8418c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
8518c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceStoreClass,
8618c2aff7Sartem 					       device_property_changed),
8718c2aff7Sartem 			      NULL, NULL,
88*9dca21dfSAndy Fiddaman 			      hald_marshal_VOID__OBJECT_STRING_BOOLEAN_BOOLEAN,
8918c2aff7Sartem 			      G_TYPE_NONE, 4,
9018c2aff7Sartem 			      G_TYPE_OBJECT,
9118c2aff7Sartem 			      G_TYPE_STRING,
9218c2aff7Sartem 			      G_TYPE_BOOLEAN,
9318c2aff7Sartem 			      G_TYPE_BOOLEAN);
9418c2aff7Sartem 
9518c2aff7Sartem 	signals[DEVICE_CAPABILITY_ADDED] =
9618c2aff7Sartem 		g_signal_new ("device_capability_added",
9718c2aff7Sartem 			      G_TYPE_FROM_CLASS (klass),
9818c2aff7Sartem 			      G_SIGNAL_RUN_LAST,
9918c2aff7Sartem 			      G_STRUCT_OFFSET (HalDeviceStoreClass,
10018c2aff7Sartem 					       device_capability_added),
10118c2aff7Sartem 			      NULL, NULL,
10218c2aff7Sartem 			      hald_marshal_VOID__OBJECT_STRING,
10318c2aff7Sartem 			      G_TYPE_NONE, 2,
10418c2aff7Sartem 			      G_TYPE_OBJECT,
10518c2aff7Sartem 			      G_TYPE_STRING);
10618c2aff7Sartem }
10718c2aff7Sartem 
10818c2aff7Sartem static void
hal_device_store_init(HalDeviceStore * device)10918c2aff7Sartem hal_device_store_init (HalDeviceStore *device)
11018c2aff7Sartem {
11118c2aff7Sartem }
11218c2aff7Sartem 
11318c2aff7Sartem GType
hal_device_store_get_type(void)11418c2aff7Sartem hal_device_store_get_type (void)
11518c2aff7Sartem {
11618c2aff7Sartem 	static GType type = 0;
11718c2aff7Sartem 
11818c2aff7Sartem 	if (!type) {
11918c2aff7Sartem 		static GTypeInfo type_info = {
12018c2aff7Sartem 			sizeof (HalDeviceStoreClass),
12118c2aff7Sartem 			NULL, NULL,
12218c2aff7Sartem 			(GClassInitFunc) hal_device_store_class_init,
12318c2aff7Sartem 			NULL, NULL,
12418c2aff7Sartem 			sizeof (HalDeviceStore),
12518c2aff7Sartem 			0,
12618c2aff7Sartem 			(GInstanceInitFunc) hal_device_store_init
12718c2aff7Sartem 		};
12818c2aff7Sartem 
12918c2aff7Sartem 		type = g_type_register_static (G_TYPE_OBJECT,
13018c2aff7Sartem 					       "HalDeviceStore",
13118c2aff7Sartem 					       &type_info,
13218c2aff7Sartem 					       0);
13318c2aff7Sartem 	}
13418c2aff7Sartem 
13518c2aff7Sartem 	return type;
13618c2aff7Sartem }
13718c2aff7Sartem 
13818c2aff7Sartem HalDeviceStore *
hal_device_store_new(void)13918c2aff7Sartem hal_device_store_new (void)
14018c2aff7Sartem {
14118c2aff7Sartem 	HalDeviceStore *store;
14218c2aff7Sartem 
14318c2aff7Sartem 	store = g_object_new (HAL_TYPE_DEVICE_STORE, NULL, NULL);
14418c2aff7Sartem 
14518c2aff7Sartem 	return store;
14618c2aff7Sartem }
14718c2aff7Sartem 
14818c2aff7Sartem static void
emit_device_property_changed(HalDevice * device,const char * key,gboolean added,gboolean removed,gpointer data)14918c2aff7Sartem emit_device_property_changed (HalDevice *device,
15018c2aff7Sartem 			      const char *key,
15118c2aff7Sartem 			      gboolean added,
15218c2aff7Sartem 			      gboolean removed,
15318c2aff7Sartem 			      gpointer data)
15418c2aff7Sartem {
15518c2aff7Sartem 	HalDeviceStore *store = HAL_DEVICE_STORE (data);
15618c2aff7Sartem 
15718c2aff7Sartem 	g_signal_emit (store, signals[DEVICE_PROPERTY_CHANGED], 0,
15818c2aff7Sartem 		       device, key, added, removed);
15918c2aff7Sartem }
16018c2aff7Sartem 
16118c2aff7Sartem static void
emit_device_capability_added(HalDevice * device,const char * capability,gpointer data)16218c2aff7Sartem emit_device_capability_added (HalDevice *device,
16318c2aff7Sartem 			      const char *capability,
16418c2aff7Sartem 			      gpointer data)
16518c2aff7Sartem {
16618c2aff7Sartem 	HalDeviceStore *store = HAL_DEVICE_STORE (data);
16718c2aff7Sartem 
16818c2aff7Sartem 	g_signal_emit (store, signals[DEVICE_CAPABILITY_ADDED], 0,
16918c2aff7Sartem 		       device, capability);
17018c2aff7Sartem }
17118c2aff7Sartem 
17218c2aff7Sartem void
hal_device_store_add(HalDeviceStore * store,HalDevice * device)17318c2aff7Sartem hal_device_store_add (HalDeviceStore *store, HalDevice *device)
17418c2aff7Sartem {
17518c2aff7Sartem 	const char buf[] = "/org/freedesktop/Hal/devices/";
17618c2aff7Sartem 
17718c2aff7Sartem 	if (strncmp(device->udi, buf, sizeof (buf) - 1) != 0) {
17818c2aff7Sartem 
17918c2aff7Sartem 		HAL_ERROR(("Can't add HalDevice with incorrect UDI. Valid "
18018c2aff7Sartem 			   "UDI must start with '/org/freedesktop/Hal/devices/'"));
18118c2aff7Sartem 		goto out;
18218c2aff7Sartem 	}
18318c2aff7Sartem 	store->devices = g_slist_prepend (store->devices,
18418c2aff7Sartem 					  g_object_ref (device));
18518c2aff7Sartem 
18618c2aff7Sartem 	g_signal_connect (device, "property_changed",
18718c2aff7Sartem 			  G_CALLBACK (emit_device_property_changed), store);
18818c2aff7Sartem 	g_signal_connect (device, "capability_added",
18918c2aff7Sartem 			  G_CALLBACK (emit_device_capability_added), store);
19018c2aff7Sartem 
19118c2aff7Sartem 	g_signal_emit (store, signals[STORE_CHANGED], 0, device, TRUE);
19218c2aff7Sartem 
19318c2aff7Sartem out:
19418c2aff7Sartem 	;
19518c2aff7Sartem }
19618c2aff7Sartem 
19718c2aff7Sartem gboolean
hal_device_store_remove(HalDeviceStore * store,HalDevice * device)19818c2aff7Sartem hal_device_store_remove (HalDeviceStore *store, HalDevice *device)
19918c2aff7Sartem {
20018c2aff7Sartem 	if (!g_slist_find (store->devices, device))
20118c2aff7Sartem 		return FALSE;
20218c2aff7Sartem 
20318c2aff7Sartem 	store->devices = g_slist_remove (store->devices, device);
20418c2aff7Sartem 
20518c2aff7Sartem 	g_signal_handlers_disconnect_by_func (device,
20618c2aff7Sartem 					      (gpointer)emit_device_property_changed,
20718c2aff7Sartem 					      store);
20818c2aff7Sartem 	g_signal_handlers_disconnect_by_func (device,
20918c2aff7Sartem 					      (gpointer)emit_device_capability_added,
21018c2aff7Sartem 					      store);
21118c2aff7Sartem 
21218c2aff7Sartem 	g_signal_emit (store, signals[STORE_CHANGED], 0, device, FALSE);
21318c2aff7Sartem 
21418c2aff7Sartem 	g_object_unref (device);
21518c2aff7Sartem 
21618c2aff7Sartem 	return TRUE;
21718c2aff7Sartem }
21818c2aff7Sartem 
21918c2aff7Sartem HalDevice *
hal_device_store_find(HalDeviceStore * store,const char * udi)22018c2aff7Sartem hal_device_store_find (HalDeviceStore *store, const char *udi)
22118c2aff7Sartem {
22218c2aff7Sartem 	GSList *iter;
22318c2aff7Sartem 
22418c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
22518c2aff7Sartem 		HalDevice *d = iter->data;
22618c2aff7Sartem 
22718c2aff7Sartem 		if (strcmp (hal_device_get_udi (d), udi) == 0)
22818c2aff7Sartem 			return d;
22918c2aff7Sartem 	}
23018c2aff7Sartem 
23118c2aff7Sartem 	return NULL;
23218c2aff7Sartem }
23318c2aff7Sartem 
23418c2aff7Sartem void
hal_device_store_foreach(HalDeviceStore * store,HalDeviceStoreForeachFn callback,gpointer user_data)23518c2aff7Sartem hal_device_store_foreach (HalDeviceStore *store,
23618c2aff7Sartem 			  HalDeviceStoreForeachFn callback,
23718c2aff7Sartem 			  gpointer user_data)
23818c2aff7Sartem {
23918c2aff7Sartem 	GSList *iter;
24018c2aff7Sartem 
24118c2aff7Sartem 	g_return_if_fail (store != NULL);
24218c2aff7Sartem 	g_return_if_fail (callback != NULL);
24318c2aff7Sartem 
24418c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
24518c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
24618c2aff7Sartem 		gboolean cont;
24718c2aff7Sartem 
24818c2aff7Sartem 		cont = callback (store, d, user_data);
24918c2aff7Sartem 
25018c2aff7Sartem 		if (cont == FALSE)
25118c2aff7Sartem 			return;
25218c2aff7Sartem 	}
25318c2aff7Sartem }
25418c2aff7Sartem 
25518c2aff7Sartem static gboolean
hal_device_store_print_foreach_fn(HalDeviceStore * store,HalDevice * device,gpointer user_data)25618c2aff7Sartem hal_device_store_print_foreach_fn (HalDeviceStore *store,
25718c2aff7Sartem 				   HalDevice *device,
25818c2aff7Sartem 				   gpointer user_data)
25918c2aff7Sartem {
26018c2aff7Sartem 	fprintf (stderr, "----\n");
26118c2aff7Sartem 	hal_device_print (device);
26218c2aff7Sartem 	fprintf (stderr, "----\n");
26318c2aff7Sartem 	return TRUE;
26418c2aff7Sartem }
26518c2aff7Sartem 
26618c2aff7Sartem void
hal_device_store_print(HalDeviceStore * store)26718c2aff7Sartem hal_device_store_print (HalDeviceStore *store)
26818c2aff7Sartem {
26918c2aff7Sartem 	fprintf (stderr, "===============================================\n");
27018c2aff7Sartem         fprintf (stderr, "Dumping %d devices\n",
27118c2aff7Sartem 		 g_slist_length (store->devices));
27218c2aff7Sartem 	fprintf (stderr, "===============================================\n");
27318c2aff7Sartem 	hal_device_store_foreach (store,
27418c2aff7Sartem 				  hal_device_store_print_foreach_fn,
27518c2aff7Sartem 				  NULL);
27618c2aff7Sartem 	fprintf (stderr, "===============================================\n");
27718c2aff7Sartem }
27818c2aff7Sartem 
27918c2aff7Sartem HalDevice *
hal_device_store_match_key_value_string(HalDeviceStore * store,const char * key,const char * value)28018c2aff7Sartem hal_device_store_match_key_value_string (HalDeviceStore *store,
28118c2aff7Sartem 					 const char *key,
28218c2aff7Sartem 					 const char *value)
28318c2aff7Sartem {
28418c2aff7Sartem 	GSList *iter;
28518c2aff7Sartem 
28618c2aff7Sartem 	g_return_val_if_fail (store != NULL, NULL);
28718c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
28818c2aff7Sartem 	g_return_val_if_fail (value != NULL, NULL);
28918c2aff7Sartem 
29018c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
29118c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
29218c2aff7Sartem 		int type;
29318c2aff7Sartem 
29418c2aff7Sartem 		if (!hal_device_has_property (d, key))
29518c2aff7Sartem 			continue;
29618c2aff7Sartem 
29718c2aff7Sartem 		type = hal_device_property_get_type (d, key);
29818c2aff7Sartem 		if (type != HAL_PROPERTY_TYPE_STRING)
29918c2aff7Sartem 			continue;
30018c2aff7Sartem 
30118c2aff7Sartem 		if (strcmp (hal_device_property_get_string (d, key),
30218c2aff7Sartem 			    value) == 0)
30318c2aff7Sartem 			return d;
30418c2aff7Sartem 	}
30518c2aff7Sartem 
30618c2aff7Sartem 	return NULL;
30718c2aff7Sartem }
30818c2aff7Sartem 
30918c2aff7Sartem HalDevice *
hal_device_store_match_key_value_int(HalDeviceStore * store,const char * key,int value)31018c2aff7Sartem hal_device_store_match_key_value_int (HalDeviceStore *store,
31118c2aff7Sartem 				      const char *key,
31218c2aff7Sartem 				      int value)
31318c2aff7Sartem {
31418c2aff7Sartem 	GSList *iter;
31518c2aff7Sartem 
31618c2aff7Sartem 	g_return_val_if_fail (store != NULL, NULL);
31718c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
31818c2aff7Sartem 
31918c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
32018c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
32118c2aff7Sartem 		int type;
32218c2aff7Sartem 
32318c2aff7Sartem 		if (!hal_device_has_property (d, key))
32418c2aff7Sartem 			continue;
32518c2aff7Sartem 
32618c2aff7Sartem 		type = hal_device_property_get_type (d, key);
32718c2aff7Sartem 		if (type != HAL_PROPERTY_TYPE_INT32)
32818c2aff7Sartem 			continue;
32918c2aff7Sartem 
33018c2aff7Sartem 		if (hal_device_property_get_int (d, key) == value)
33118c2aff7Sartem 			return d;
33218c2aff7Sartem 	}
33318c2aff7Sartem 
33418c2aff7Sartem 	return NULL;
33518c2aff7Sartem }
33618c2aff7Sartem 
33718c2aff7Sartem GSList *
hal_device_store_match_multiple_key_value_string(HalDeviceStore * store,const char * key,const char * value)33818c2aff7Sartem hal_device_store_match_multiple_key_value_string (HalDeviceStore *store,
33918c2aff7Sartem 						  const char *key,
34018c2aff7Sartem 						  const char *value)
34118c2aff7Sartem {
34218c2aff7Sartem 	GSList *iter;
34318c2aff7Sartem 	GSList *matches = NULL;
34418c2aff7Sartem 
34518c2aff7Sartem 	g_return_val_if_fail (store != NULL, NULL);
34618c2aff7Sartem 	g_return_val_if_fail (key != NULL, NULL);
34718c2aff7Sartem 	g_return_val_if_fail (value != NULL, NULL);
34818c2aff7Sartem 
34918c2aff7Sartem 	for (iter = store->devices; iter != NULL; iter = iter->next) {
35018c2aff7Sartem 		HalDevice *d = HAL_DEVICE (iter->data);
35118c2aff7Sartem 		int type;
35218c2aff7Sartem 
35318c2aff7Sartem 		if (!hal_device_has_property (d, key))
35418c2aff7Sartem 			continue;
35518c2aff7Sartem 
35618c2aff7Sartem 		type = hal_device_property_get_type (d, key);
35718c2aff7Sartem 		if (type != HAL_PROPERTY_TYPE_STRING)
35818c2aff7Sartem 			continue;
35918c2aff7Sartem 
36018c2aff7Sartem 		if (strcmp (hal_device_property_get_string (d, key),
36118c2aff7Sartem 			    value) == 0)
36218c2aff7Sartem 			matches = g_slist_prepend (matches, d);
36318c2aff7Sartem 	}
36418c2aff7Sartem 
36518c2aff7Sartem 	return matches;
36618c2aff7Sartem }
36718c2aff7Sartem 
36818c2aff7Sartem typedef struct {
36918c2aff7Sartem 	HalDeviceStore *store;
37018c2aff7Sartem 	char *key;
37118c2aff7Sartem 	char *value;
37218c2aff7Sartem 	HalDeviceStoreAsyncCallback callback;
37318c2aff7Sartem 	gpointer user_data;
37418c2aff7Sartem 
37518c2aff7Sartem 	guint prop_signal_id;
37618c2aff7Sartem 	guint store_signal_id;
37718c2aff7Sartem 	guint timeout_id;
37818c2aff7Sartem } AsyncMatchInfo;
37918c2aff7Sartem 
38018c2aff7Sartem static void
destroy_async_match_info(AsyncMatchInfo * info)38118c2aff7Sartem destroy_async_match_info (AsyncMatchInfo *info)
38218c2aff7Sartem {
38318c2aff7Sartem 	g_object_unref (info->store);
38418c2aff7Sartem 
38518c2aff7Sartem 	g_free (info->key);
38618c2aff7Sartem 	g_free (info->value);
38718c2aff7Sartem 
38818c2aff7Sartem 	g_signal_handler_disconnect (info->store, info->prop_signal_id);
38918c2aff7Sartem 	g_signal_handler_disconnect (info->store, info->store_signal_id);
39018c2aff7Sartem 	g_source_remove (info->timeout_id);
39118c2aff7Sartem 
39218c2aff7Sartem 	g_free (info);
39318c2aff7Sartem }
39418c2aff7Sartem 
39518c2aff7Sartem static void
match_device_async(HalDeviceStore * store,HalDevice * device,const char * key,gboolean removed,gboolean added,gpointer user_data)39618c2aff7Sartem match_device_async (HalDeviceStore *store, HalDevice *device,
39718c2aff7Sartem 		    const char *key, gboolean removed, gboolean added,
39818c2aff7Sartem 		    gpointer user_data)
39918c2aff7Sartem {
40018c2aff7Sartem 	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
40118c2aff7Sartem 
40218c2aff7Sartem 	/* Only want to do it for added or changed properties */
40318c2aff7Sartem 	if (removed)
40418c2aff7Sartem 		return;
40518c2aff7Sartem 
40618c2aff7Sartem 	/* Keys have to match */
40718c2aff7Sartem 	if (strcmp (info->key, key) != 0)
40818c2aff7Sartem 		return;
40918c2aff7Sartem 
41018c2aff7Sartem 	/* Values have to match */
41118c2aff7Sartem 	if (strcmp (hal_device_property_get_string (device, key),
41218c2aff7Sartem 		    info->value) != 0)
41318c2aff7Sartem 		return;
41418c2aff7Sartem 
41518c2aff7Sartem 	info->callback (store, device, info->user_data);
41618c2aff7Sartem 
41718c2aff7Sartem 	destroy_async_match_info (info);
41818c2aff7Sartem }
41918c2aff7Sartem 
42018c2aff7Sartem static void
store_changed(HalDeviceStore * store,HalDevice * device,gboolean added,gpointer user_data)42118c2aff7Sartem store_changed (HalDeviceStore *store, HalDevice *device,
42218c2aff7Sartem 	       gboolean added, gpointer user_data)
42318c2aff7Sartem {
42418c2aff7Sartem 	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
42518c2aff7Sartem 
42618c2aff7Sartem 	if (!added)
42718c2aff7Sartem 		return;
42818c2aff7Sartem 
42918c2aff7Sartem 	if (!hal_device_has_property (device, info->key))
43018c2aff7Sartem 		return;
43118c2aff7Sartem 
43218c2aff7Sartem 	if (strcmp (hal_device_property_get_string (device, info->key),
43318c2aff7Sartem 		    info->value) != 0)
43418c2aff7Sartem 		return;
43518c2aff7Sartem 
43618c2aff7Sartem 	info->callback (store, device, info->user_data);
43718c2aff7Sartem 
43818c2aff7Sartem 	destroy_async_match_info (info);
43918c2aff7Sartem }
44018c2aff7Sartem 
44118c2aff7Sartem static gboolean
match_device_async_timeout(gpointer user_data)44218c2aff7Sartem match_device_async_timeout (gpointer user_data)
44318c2aff7Sartem {
44418c2aff7Sartem 	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
44518c2aff7Sartem 
44618c2aff7Sartem 	info->callback (info->store, NULL, info->user_data);
44718c2aff7Sartem 
44818c2aff7Sartem 	destroy_async_match_info (info);
44918c2aff7Sartem 
45018c2aff7Sartem 	return FALSE;
45118c2aff7Sartem }
45218c2aff7Sartem 
45318c2aff7Sartem void
hal_device_store_match_key_value_string_async(HalDeviceStore * store,const char * key,const char * value,HalDeviceStoreAsyncCallback callback,gpointer user_data,int timeout)45418c2aff7Sartem hal_device_store_match_key_value_string_async (HalDeviceStore *store,
45518c2aff7Sartem 					       const char *key,
45618c2aff7Sartem 					       const char *value,
45718c2aff7Sartem 					       HalDeviceStoreAsyncCallback callback,
45818c2aff7Sartem 					       gpointer user_data,
45918c2aff7Sartem 					       int timeout)
46018c2aff7Sartem {
46118c2aff7Sartem 	HalDevice *device;
46218c2aff7Sartem 	AsyncMatchInfo *info;
46318c2aff7Sartem 
46418c2aff7Sartem 	/* First check to see if it's already there */
46518c2aff7Sartem 	device = hal_device_store_match_key_value_string (store, key, value);
46618c2aff7Sartem 
46718c2aff7Sartem 	if (device != NULL || timeout == 0) {
46818c2aff7Sartem 		callback (store, device, user_data);
46918c2aff7Sartem 
47018c2aff7Sartem 		return;
47118c2aff7Sartem 	}
47218c2aff7Sartem 
47318c2aff7Sartem 	info = g_new0 (AsyncMatchInfo, 1);
47418c2aff7Sartem 
47518c2aff7Sartem 	info->store = g_object_ref (store);
47618c2aff7Sartem 	info->key = g_strdup (key);
47718c2aff7Sartem 	info->value = g_strdup (value);
47818c2aff7Sartem 	info->callback = callback;
47918c2aff7Sartem 	info->user_data = user_data;
48018c2aff7Sartem 
48118c2aff7Sartem 	info->prop_signal_id = g_signal_connect (store,
48218c2aff7Sartem 						 "device_property_changed",
48318c2aff7Sartem 						 G_CALLBACK (match_device_async),
48418c2aff7Sartem 						 info);
48518c2aff7Sartem 	info->store_signal_id = g_signal_connect (store,
48618c2aff7Sartem 						  "store_changed",
48718c2aff7Sartem 						  G_CALLBACK (store_changed),
48818c2aff7Sartem 						  info);
48918c2aff7Sartem 
49018c2aff7Sartem 	info->timeout_id = g_timeout_add (timeout,
49118c2aff7Sartem 					  match_device_async_timeout,
49218c2aff7Sartem 					  info);
49318c2aff7Sartem }
494