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 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 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*57fa6b4fSAndy 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*57fa6b4fSAndy 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 10918c2aff7Sartem hal_device_store_init (HalDeviceStore *device) 11018c2aff7Sartem { 11118c2aff7Sartem } 11218c2aff7Sartem 11318c2aff7Sartem GType 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 * 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 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 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 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 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 * 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 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 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 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 * 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 * 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 * 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 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 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 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 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 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