summaryrefslogtreecommitdiff
path: root/src/agent.c
diff options
context:
space:
mode:
authorSzymon Janc <szymon.janc@tieto.com>2014-04-28 16:27:15 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2014-04-29 11:24:17 +0300
commit123db1e883d4544376b24964ad9806a7e979457a (patch)
tree2c7c44dfa715dab9bf49765680de0e959bf14827 /src/agent.c
parent25cb97ada97dc32e2c8303f6d1ec09109341f268 (diff)
downloadbluez-123db1e883d4544376b24964ad9806a7e979457a.tar.gz
agent: Allow to stack default agents
There is no API for notifying agent that it is no longer default one. This can lead to situation when ie. console agent (bluetoothctl) is set as default leaving UI agent unfunctional after bluetoothctl exited. This patch adds stacking of default agents in case more then one agent requested being default.
Diffstat (limited to 'src/agent.c')
-rw-r--r--src/agent.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/agent.c b/src/agent.c
index 4a2f606dd..8c1211c33 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -46,6 +46,7 @@
#include "adapter.h"
#include "device.h"
#include "agent.h"
+#include "shared/queue.h"
#define IO_CAPABILITY_DISPLAYONLY 0x00
#define IO_CAPABILITY_DISPLAYYESNO 0x01
@@ -58,7 +59,7 @@
#define AGENT_INTERFACE "org.bluez.Agent1"
static GHashTable *agent_list;
-static struct agent *default_agent = NULL;
+struct queue *default_agents = NULL;
typedef enum {
AGENT_REQUEST_PASSKEY,
@@ -152,18 +153,38 @@ static void set_io_cap(struct btd_adapter *adapter, gpointer user_data)
adapter_set_io_capability(adapter, io_cap);
}
-static void set_default_agent(struct agent *agent)
+static bool add_default_agent(struct agent *agent)
{
- if (default_agent == agent)
+ if (queue_peek_head(default_agents) == agent)
+ return true;
+
+ queue_remove(default_agents, agent);
+
+ if (!queue_push_head(default_agents, agent))
+ return false;
+
+ DBG("Default agent set to %s %s", agent->owner, agent->path);
+
+ adapter_foreach(set_io_cap, agent);
+
+ return true;
+}
+
+static void remove_default_agent(struct agent *agent)
+{
+ if (queue_peek_head(default_agents) != agent) {
+ queue_remove(default_agents, agent);
return;
+ }
+
+ queue_remove(default_agents, agent);
+ agent = queue_peek_head(default_agents);
if (agent)
DBG("Default agent set to %s %s", agent->owner, agent->path);
else
DBG("Default agent cleared");
- default_agent = agent;
-
adapter_foreach(set_io_cap, agent);
}
@@ -178,8 +199,7 @@ static void agent_disconnect(DBusConnection *conn, void *user_data)
agent->watch = 0;
}
- if (agent == default_agent)
- set_default_agent(NULL);
+ remove_default_agent(agent);
g_hash_table_remove(agent_list, agent->owner);
}
@@ -247,8 +267,8 @@ struct agent *agent_get(const char *owner)
return agent_ref(agent);
}
- if (default_agent)
- return agent_ref(default_agent);
+ if (!queue_isempty(default_agents))
+ return agent_ref(queue_peek_head(default_agents));
return NULL;
}
@@ -889,6 +909,8 @@ static void agent_destroy(gpointer data)
agent_release(agent);
}
+ remove_default_agent(agent);
+
agent_unref(agent);
}
@@ -987,7 +1009,8 @@ static DBusMessage *request_default(DBusConnection *conn, DBusMessage *msg,
if (g_str_equal(path, agent->path) == FALSE)
return btd_error_does_not_exist(msg);
- set_default_agent(agent);
+ if (!add_default_agent(agent))
+ return btd_error_failed(msg, "Failed to set as default");
return dbus_message_new_method_return(msg);
}
@@ -1008,6 +1031,8 @@ void btd_agent_init(void)
agent_list = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, agent_destroy);
+ default_agents = queue_new();
+
g_dbus_register_interface(btd_get_dbus_connection(),
"/org/bluez", "org.bluez.AgentManager1",
methods, NULL, NULL, NULL, NULL);
@@ -1018,6 +1043,6 @@ void btd_agent_cleanup(void)
g_dbus_unregister_interface(btd_get_dbus_connection(),
"/org/bluez", "org.bluez.AgentManager1");
- set_default_agent(NULL);
g_hash_table_destroy(agent_list);
+ queue_destroy(default_agents, NULL);
}