From a5f5dd2569c3a7e7e2ac620af31689526bda8d6e Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 4 Jul 2011 10:32:16 +0300 Subject: [PATCH] bluetooth: Remove data in all situations If an adapter or device is removed any data associate should be removed, otherwise the next time they appear/are created the drivers may not asssociate again. --- plugins/bluetooth.c | 79 ++++++++++++++++++++++++++++++++------------- plugins/bluetooth.h | 4 +-- plugins/hfp_hf.c | 30 ++++++++++------- 3 files changed, 78 insertions(+), 35 deletions(-) diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index 7e0705fd..1fdb579d 100644 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -258,6 +258,28 @@ static void parse_string(DBusMessageIter *iter, gpointer user_data) dbus_message_iter_get_basic(iter, str); } +static void bluetooth_probe(GSList *uuids, const char *path, + const char *device, const char *adapter, + const char *alias) +{ + for (; uuids; uuids = uuids->next) { + struct bluetooth_profile *driver; + const char *uuid = uuids->data; + int err; + + driver = g_hash_table_lookup(uuid_hash, uuid); + if (driver == NULL) + continue; + + err = driver->probe(path, device, adapter, alias); + if (err == 0) + continue; + + ofono_error("%s probe: %s (%d)", driver->name, strerror(-err), + -err); + } +} + static void device_properties_cb(DBusPendingCall *call, gpointer user_data) { DBusMessage *reply; @@ -291,19 +313,10 @@ static void device_properties_cb(DBusPendingCall *call, gpointer user_data) adapter_addr = g_hash_table_lookup(adapter_address_hash, adapter); - if (!device_addr && !adapter_addr) + if (!device_addr || !adapter_addr) goto done; - for (; uuids; uuids = uuids->next) { - struct bluetooth_profile *profile; - const char *uuid = uuids->data; - - profile = g_hash_table_lookup(uuid_hash, uuid); - if (profile == NULL || profile->create == NULL) - continue; - - profile->create(path, device_addr, adapter_addr, alias); - } + bluetooth_probe(uuids, path, device_addr, adapter_addr, alias); done: g_slist_free(uuids); @@ -697,14 +710,38 @@ static gboolean adapter_added(DBusConnection *connection, DBusMessage *message, return TRUE; } +static void bluetooth_remove(gpointer key, gpointer value, gpointer user_data) +{ + struct bluetooth_profile *profile = value; + + profile->remove(user_data); +} + static gboolean adapter_removed(DBusConnection *connection, DBusMessage *message, void *user_data) { const char *path; if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == TRUE) - g_hash_table_remove(adapter_address_hash, path); + DBUS_TYPE_INVALID) == FALSE) + return FALSE; + + g_hash_table_foreach(uuid_hash, bluetooth_remove, (gpointer) path); + g_hash_table_remove(adapter_address_hash, path); + + return TRUE; +} + +static gboolean device_removed(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + const char *path; + + if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID) == FALSE) + return FALSE; + + g_hash_table_foreach(uuid_hash, bluetooth_remove, (gpointer) path); return TRUE; } @@ -761,14 +798,6 @@ done: dbus_message_unref(reply); } -static void bluetooth_remove_all_modem(gpointer key, gpointer value, - gpointer user_data) -{ - struct bluetooth_profile *profile = value; - - profile->remove_all(); -} - static void bluetooth_connect(DBusConnection *connection, void *user_data) { bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties", @@ -786,7 +815,7 @@ static void bluetooth_disconnect(DBusConnection *connection, void *user_data) if (uuid_hash == NULL) return; - g_hash_table_foreach(uuid_hash, bluetooth_remove_all_modem, NULL); + g_hash_table_foreach(uuid_hash, bluetooth_remove, NULL); g_slist_foreach(server_list, (GFunc) remove_service_handle, NULL); } @@ -794,6 +823,7 @@ static void bluetooth_disconnect(DBusConnection *connection, void *user_data) static guint bluetooth_watch; static guint adapter_added_watch; static guint adapter_removed_watch; +static guint device_removed_watch; static guint property_watch; static void bluetooth_ref(void) @@ -817,6 +847,11 @@ static void bluetooth_ref(void) "AdapterRemoved", adapter_removed, NULL, NULL); + device_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_ADAPTER_INTERFACE, + "DeviceRemoved", + device_removed, NULL, NULL); + property_watch = g_dbus_add_signal_watch(connection, NULL, NULL, BLUEZ_DEVICE_INTERFACE, "PropertyChanged", diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h index ff0ea52b..7f9f8101 100644 --- a/plugins/bluetooth.h +++ b/plugins/bluetooth.h @@ -32,9 +32,9 @@ struct bluetooth_profile { const char *name; - int (*create)(const char *device, const char *dev_addr, + int (*probe)(const char *device, const char *dev_addr, const char *adapter_addr, const char *alias); - void (*remove_all)(void); + void (*remove)(const char *prefix); void (*set_alias)(const char *device, const char *); }; diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c index 8a76701f..b0b1ccf5 100644 --- a/plugins/hfp_hf.c +++ b/plugins/hfp_hf.c @@ -393,7 +393,7 @@ static GDBusMethodTable agent_methods[] = { { NULL, NULL, NULL, NULL } }; -static int hfp_create_modem(const char *device, const char *dev_addr, +static int hfp_hf_probe(const char *device, const char *dev_addr, const char *adapter_addr, const char *alias) { struct ofono_modem *modem; @@ -443,25 +443,33 @@ free: return -ENOMEM; } -static gboolean hfp_remove_each_modem(gpointer key, gpointer value, +static gboolean hfp_remove_modem(gpointer key, gpointer value, gpointer user_data) { struct ofono_modem *modem = value; + const char *device = key; + const char *prefix = user_data; + + if (prefix && g_str_has_prefix(device, prefix) == FALSE) + return FALSE; ofono_modem_remove(modem); return TRUE; } -static void hfp_remove_all_modem(void) +static void hfp_hf_remove(const char *prefix) { + DBG("%s", prefix); + if (modem_hash == NULL) return; - g_hash_table_foreach_remove(modem_hash, hfp_remove_each_modem, NULL); + g_hash_table_foreach_remove(modem_hash, hfp_remove_modem, + (gpointer) prefix); } -static void hfp_set_alias(const char *device, const char *alias) +static void hfp_hf_set_alias(const char *device, const char *alias) { struct ofono_modem *modem; @@ -675,11 +683,11 @@ static struct ofono_modem_driver hfp_driver = { .post_sim = hfp_post_sim, }; -static struct bluetooth_profile hfp_profile = { - .name = "hfp", - .create = hfp_create_modem, - .remove_all = hfp_remove_all_modem, - .set_alias = hfp_set_alias, +static struct bluetooth_profile hfp_hf = { + .name = "hfp_hf", + .probe = hfp_hf_probe, + .remove = hfp_hf_remove, + .set_alias = hfp_hf_set_alias, }; static int hfp_init(void) @@ -695,7 +703,7 @@ static int hfp_init(void) if (err < 0) return err; - err = bluetooth_register_uuid(HFP_AG_UUID, &hfp_profile); + err = bluetooth_register_uuid(HFP_AG_UUID, &hfp_hf); if (err < 0) { ofono_modem_driver_unregister(&hfp_driver); return err;