summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2013-01-09 18:56:31 -0800
committerMarcel Holtmann <marcel@holtmann.org>2013-01-09 18:56:31 -0800
commitee0c0702f64095467c12d5eb6ba0e702a2ed9cd1 (patch)
tree07c15ac082b582f51c4ba4911a9886a9f07e90ce
parent6600b2585b7672b8cbba6d7cf7ba7e1d70baf642 (diff)
downloadbluez-ee0c0702f64095467c12d5eb6ba0e702a2ed9cd1.tar.gz
core: Add support for graceful shutdown of adapters
-rw-r--r--src/adapter.c49
-rw-r--r--src/adapter.h4
-rw-r--r--src/hcid.h2
-rw-r--r--src/main.c19
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;