From ad37d886cc54a9a975f0f5322165bbb2855dac7f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 22 Dec 2008 19:33:41 -0300 Subject: Cleanup adapters on exit. When bluetoothd is terminated any remaining registered adapters should be unregistered (including proper D-Bus signal emition) and have their drivers removed. The adapters should also be brought down unless they were already up upon initialization. --- src/adapter.c | 16 +++++++++- src/adapter.h | 3 +- src/dbus-common.c | 3 +- src/main.c | 18 ++++++----- src/manager.c | 90 ++++++++++++++++++++++++++++--------------------------- src/manager.h | 2 +- 6 files changed, 77 insertions(+), 55 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index 5eaf729a..dc6f8e9c 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -120,6 +120,7 @@ struct btd_adapter { gboolean pairable; /* pairable state */ gboolean initialized; + gboolean already_up; /* adapter was already up on init */ }; static void adapter_set_pairable_timeout(struct btd_adapter *adapter, @@ -2912,7 +2913,8 @@ static void adapter_free(gpointer user_data) return; } -struct btd_adapter *adapter_create(DBusConnection *conn, int id) +struct btd_adapter *adapter_create(DBusConnection *conn, int id, + gboolean devup) { char path[MAX_PATH_LENGTH]; struct btd_adapter *adapter; @@ -2933,6 +2935,7 @@ struct btd_adapter *adapter_create(DBusConnection *conn, int id) adapter->dev_id = id; adapter->state |= RESOLVE_NAME; adapter->path = g_strdup(path); + adapter->already_up = devup; if (!g_dbus_register_interface(conn, path, ADAPTER_INTERFACE, adapter_methods, adapter_signals, NULL, @@ -2958,6 +2961,17 @@ void adapter_remove(struct btd_adapter *adapter) device_remove(connection, l->data); g_slist_free(adapter->devices); + /* Return adapter to down state if it was not up on init */ + if (adapter->up && !adapter->already_up) { + int dd = hci_open_dev(adapter->dev_id); + if (dd < 0) + goto done; + + ioctl(dd, HCIDEVDOWN, adapter->dev_id); + hci_close_dev(dd); + } + +done: g_dbus_unregister_interface(connection, path, ADAPTER_INTERFACE); g_free(path); diff --git a/src/adapter.h b/src/adapter.h index 118ec4f9..d6f8b6c7 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -129,7 +129,8 @@ void adapter_remove_auth_request(struct btd_adapter *adapter, bdaddr_t *dba); struct pending_auth_info *adapter_new_auth_request(struct btd_adapter *adapter, bdaddr_t *dba, auth_type_t type); -struct btd_adapter *adapter_create(DBusConnection *conn, int id); +struct btd_adapter *adapter_create(DBusConnection *conn, int id, + gboolean devup); void adapter_remove(struct btd_adapter *adapter); uint16_t adapter_get_dev_id(struct btd_adapter *adapter); const gchar *adapter_get_path(struct btd_adapter *adapter); diff --git a/src/dbus-common.c b/src/dbus-common.c index de42769e..e4587256 100644 --- a/src/dbus-common.c +++ b/src/dbus-common.c @@ -143,8 +143,9 @@ static gboolean system_bus_reconnect(void *data) /* reset the default device */ manager_set_default_adapter(-1); + /* FIXME: it shouldn't be needed to register adapters again */ for (i = 0; i < dl->dev_num; i++, dr++) - manager_register_adapter(dr->dev_id); + manager_register_adapter(dr->dev_id, TRUE); ret_val = FALSE; diff --git a/src/main.c b/src/main.c index fb917c89..d67a2477 100644 --- a/src/main.c +++ b/src/main.c @@ -474,7 +474,7 @@ fail: exit(1); } -static void device_devreg_setup(int dev_id) +static void device_devreg_setup(int dev_id, gboolean devup) { struct hci_dev_info di; @@ -484,7 +484,7 @@ static void device_devreg_setup(int dev_id) return; if (!hci_test_bit(HCI_RAW, &di.flags)) - manager_register_adapter(dev_id); + manager_register_adapter(dev_id, devup); } static void device_devup_setup(int dev_id) @@ -521,9 +521,13 @@ static void init_all_devices(int ctl) } for (i = 0; i < dl->dev_num; i++, dr++) { + gboolean devup; + + devup = hci_test_bit(HCI_UP, &dr->dev_opt); + info("HCI dev %d registered", dr->dev_id); - device_devreg_setup(dr->dev_id); - if (hci_test_bit(HCI_UP, &dr->dev_opt)) { + device_devreg_setup(dr->dev_id, devup); + if (devup) { info("HCI dev %d already up", dr->dev_id); device_devup_setup(dr->dev_id); } @@ -553,7 +557,7 @@ static inline void device_event(GIOChannel *chan, evt_stack_internal *si) switch (sd->event) { case HCI_DEV_REG: info("HCI dev %d registered", sd->dev_id); - device_devreg_setup(sd->dev_id); + device_devreg_setup(sd->dev_id, FALSE); break; case HCI_DEV_UNREG: @@ -767,14 +771,14 @@ int main(int argc, char *argv[]) hcid_dbus_unregister(); + hcid_dbus_exit(); + plugin_cleanup(); stop_sdp_server(); agent_exit(); - hcid_dbus_exit(); - g_main_loop_unref(event_loop); if (config) diff --git a/src/manager.c b/src/manager.c index f9263ae8..b0ba429c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -326,8 +326,52 @@ dbus_bool_t manager_init(DBusConnection *conn, const char *path) NULL, NULL, NULL); } +static void manager_update_adapters(void) +{ + GSList *list; + char **array; + int i; + + array = g_new0(char *, g_slist_length(adapters) + 1); + for (i = 0, list = adapters; list; list = list->next, i++) { + struct btd_adapter *adapter = list->data; + array[i] = (char *) adapter_get_path(adapter); + } + + emit_array_property_changed(connection, "/", + MANAGER_INTERFACE, "Adapters", + DBUS_TYPE_OBJECT_PATH, &array); + + g_free(array); +} + +static void manager_remove_adapter(struct btd_adapter *adapter) +{ + uint16_t dev_id = adapter_get_dev_id(adapter); + const gchar *path = adapter_get_path(adapter); + + manager_update_adapters(); + + g_dbus_emit_signal(connection, "/", + MANAGER_INTERFACE, "AdapterRemoved", + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID); + + if (default_adapter_id == dev_id || default_adapter_id < 0) { + int new_default = hci_get_route(NULL); + + manager_set_default_adapter(new_default); + } + + adapters = g_slist_remove(adapters, adapter); + adapter_remove(adapter); +} + void manager_cleanup(DBusConnection *conn, const char *path) { + g_slist_foreach(adapters, (GFunc) manager_remove_adapter, NULL); + g_slist_free(adapters); + g_dbus_unregister_interface(conn, "/", MANAGER_INTERFACE); } @@ -403,25 +447,6 @@ GSList *manager_get_adapters(void) return adapters; } -static void manager_update_adapters(void) -{ - GSList *list; - char **array; - int i; - - array = g_new0(char *, g_slist_length(adapters) + 1); - for (i = 0, list = adapters; list; list = list->next, i++) { - struct btd_adapter *adapter = list->data; - array[i] = (char *) adapter_get_path(adapter); - } - - emit_array_property_changed(connection, "/", - MANAGER_INTERFACE, "Adapters", - DBUS_TYPE_OBJECT_PATH, &array); - - g_free(array); -} - static void manager_add_adapter(struct btd_adapter *adapter) { const gchar *path = adapter_get_path(adapter); @@ -442,30 +467,9 @@ static void manager_add_adapter(struct btd_adapter *adapter) manager_update_adapters(); } -static void manager_remove_adapter(struct btd_adapter *adapter) -{ - uint16_t dev_id = adapter_get_dev_id(adapter); - const gchar *path = adapter_get_path(adapter); - - manager_update_adapters(); - - g_dbus_emit_signal(connection, "/", - MANAGER_INTERFACE, "AdapterRemoved", - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - if (default_adapter_id == dev_id || default_adapter_id < 0) { - int new_default = hci_get_route(NULL); - - manager_set_default_adapter(new_default); - } - - adapters = g_slist_remove(adapters, adapter); -} - -int manager_register_adapter(int id) +int manager_register_adapter(int id, gboolean devup) { - struct btd_adapter *adapter = adapter_create(connection, id); + struct btd_adapter *adapter = adapter_create(connection, id, devup); if (!adapter) return -1; @@ -490,8 +494,6 @@ int manager_unregister_adapter(int id) manager_remove_adapter(adapter); - adapter_remove(adapter); - return 0; } diff --git a/src/manager.h b/src/manager.h index d0e30a89..eb087b95 100644 --- a/src/manager.h +++ b/src/manager.h @@ -32,7 +32,7 @@ struct btd_adapter *manager_find_adapter(const bdaddr_t *sba); struct btd_adapter *manager_find_adapter_by_path(const char *path); struct btd_adapter *manager_find_adapter_by_id(int id); GSList *manager_get_adapters(void); -int manager_register_adapter(int id); +int manager_register_adapter(int id, gboolean devup); int manager_unregister_adapter(int id); int manager_start_adapter(int id); int manager_stop_adapter(int id); -- cgit