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