diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2013-01-09 18:56:31 -0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2013-01-09 18:56:31 -0800 |
commit | ee0c0702f64095467c12d5eb6ba0e702a2ed9cd1 (patch) | |
tree | 07c15ac082b582f51c4ba4911a9886a9f07e90ce | |
parent | 6600b2585b7672b8cbba6d7cf7ba7e1d70baf642 (diff) | |
download | bluez-ee0c0702f64095467c12d5eb6ba0e702a2ed9cd1.tar.gz |
core: Add support for graceful shutdown of adapters
-rw-r--r-- | src/adapter.c | 49 | ||||
-rw-r--r-- | src/adapter.h | 4 | ||||
-rw-r--r-- | src/hcid.h | 2 | ||||
-rw-r--r-- | src/main.c | 19 |
4 files changed, 68 insertions, 6 deletions
diff --git a/src/adapter.c b/src/adapter.c index 77d820fd5..c1cde18c7 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -89,6 +89,8 @@ static DBusConnection *dbus_conn = NULL; static GList *adapter_list = NULL; +static unsigned int adapter_remaining = 0; +static bool powering_down = false; static GSList *adapters = NULL; static int default_adapter_id = -1; @@ -484,10 +486,18 @@ static void settings_changed(struct btd_adapter *adapter, uint32_t settings) g_dbus_emit_property_changed(dbus_conn, adapter->path, ADAPTER_INTERFACE, "Powered"); - if (adapter->current_settings & MGMT_SETTING_POWERED) + if (adapter->current_settings & MGMT_SETTING_POWERED) { adapter_start(adapter); - else + } else { adapter_stop(adapter); + + if (powering_down) { + adapter_remaining--; + + if (!adapter_remaining) + btd_exit(); + } + } } if (changed_mask & MGMT_SETTING_CONNECTABLE) @@ -1620,6 +1630,12 @@ static void property_set_powered(const GDBusPropertyTable *property, { struct btd_adapter *adapter = user_data; + if (powering_down) { + g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed", + "Powering down"); + return; + } + property_set_mode(adapter, MGMT_SETTING_POWERED, iter, id); } @@ -3575,8 +3591,6 @@ static void adapter_remove(struct btd_adapter *adapter) btd_adapter_gatt_server_stop(adapter); g_slist_free(adapter->pin_callbacks); - - set_mode(adapter, MGMT_OP_SET_POWERED, 0x00); } const char *adapter_get_path(struct btd_adapter *adapter) @@ -5107,6 +5121,9 @@ static int adapter_register(struct btd_adapter *adapter) { struct agent *agent; + if (powering_down) + return -EBUSY; + adapter->path = g_strdup_printf("/org/bluez/hci%d", adapter->dev_id); if (!g_dbus_register_interface(dbus_conn, @@ -5777,3 +5794,27 @@ void adapter_cleanup(void) dbus_conn = NULL; } + +void adapter_shutdown(void) +{ + GList *list; + + DBG(""); + + powering_down = true; + + for (list = g_list_first(adapter_list); list; + list = g_list_next(list)) { + struct btd_adapter *adapter = list->data; + + if (!(adapter->current_settings & MGMT_SETTING_POWERED)) + continue; + + set_mode(adapter, MGMT_OP_SET_POWERED, 0x00); + + adapter_remaining++; + } + + if (!adapter_remaining) + btd_exit(); +} diff --git a/src/adapter.h b/src/adapter.h index ec08886b5..5c53b4a46 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -76,8 +76,10 @@ struct smp_ltk_info { uint8_t val[16]; }; -void adapter_cleanup(void); int adapter_init(void); +void adapter_cleanup(void); +void adapter_shutdown(void); + struct btd_adapter *adapter_find(const bdaddr_t *sba); struct btd_adapter *adapter_find_by_id(int id); struct btd_adapter *adapter_get_default(void); diff --git a/src/hcid.h b/src/hcid.h index 9accebb49..ea67cc259 100644 --- a/src/hcid.h +++ b/src/hcid.h @@ -46,3 +46,5 @@ void plugin_cleanup(void); void rfkill_init(void); void rfkill_exit(void); + +void btd_exit(void); diff --git a/src/main.c b/src/main.c index 57f1fa926..bd1e9d912 100644 --- a/src/main.c +++ b/src/main.c @@ -61,6 +61,8 @@ #define DEFAULT_PAIRABLE_TIMEOUT 0 /* disabled */ #define DEFAULT_DISCOVERABLE_TIMEOUT 180 /* 3 minutes */ +#define SHUTDOWN_GRACE_SECONDS 10 + struct main_opts main_opts; static const char * const supported_options[] = { @@ -287,6 +289,17 @@ static void init_defaults(void) static GMainLoop *event_loop; +void btd_exit(void) +{ + g_main_loop_quit(event_loop); +} + +static gboolean quit_eventloop(gpointer user_data) +{ + btd_exit(); + return FALSE; +} + static gboolean signal_handler(GIOChannel *channel, GIOCondition cond, gpointer user_data) { @@ -309,7 +322,11 @@ static gboolean signal_handler(GIOChannel *channel, GIOCondition cond, case SIGTERM: if (__terminated == 0) { info("Terminating"); - g_main_loop_quit(event_loop); + g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS, + quit_eventloop, NULL); + + sd_notify(0, "STATUS=Powering down"); + adapter_shutdown(); } __terminated = 1; |