diff --git a/src/adapter.c b/src/adapter.c
index 77d820f..c1cde18 100644
--- a/src/adapter.c
+++ b/src/adapter.c
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;
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)
{
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);
}
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)
{
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,
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 ec08886..5c53b4a 100644
--- a/src/adapter.h
+++ b/src/adapter.h
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 9accebb..ea67cc2 100644
--- a/src/hcid.h
+++ b/src/hcid.h
void rfkill_init(void);
void rfkill_exit(void);
+
+void btd_exit(void);
diff --git a/src/main.c b/src/main.c
index 57f1fa9..bd1e9d9 100644
--- a/src/main.c
+++ b/src/main.c
#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[] = {
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)
{
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;