summaryrefslogtreecommitdiff
path: root/plugins/policy.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2013-07-05 13:38:42 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2013-07-12 15:05:50 +0300
commitf5fc3fffe54617c5c8cd5e8540d813fb80ff8823 (patch)
treec8d9be28a92d8cd24c56ab6bb99884e33bbf7491 /plugins/policy.c
parent3c29a14f84d4c685d9757b322b778cf055d4d010 (diff)
downloadbluez-f5fc3fffe54617c5c8cd5e8540d813fb80ff8823.tar.gz
audio/sink: Move stream retry logic to policy plugin
policy plugin is a better place to have such a logic as it is already handling other connection policies related to such profiles.
Diffstat (limited to 'plugins/policy.c')
-rw-r--r--plugins/policy.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/plugins/policy.c b/plugins/policy.c
index 667253d97..c5873734c 100644
--- a/plugins/policy.c
+++ b/plugins/policy.c
@@ -41,6 +41,7 @@
#define CONTROL_CONNECT_TIMEOUT 2
#define SOURCE_RETRY_TIMEOUT 2
+#define SINK_RETRY_TIMEOUT SOURCE_RETRY_TIMEOUT
static unsigned int service_id = 0;
static GSList *devices = NULL;
@@ -49,6 +50,7 @@ struct policy_data {
struct btd_device *dev;
guint source_timer;
+ guint sink_timer;
guint ct_timer;
guint tg_timer;
};
@@ -117,6 +119,9 @@ static void policy_remove(void *user_data)
if (data->source_timer > 0)
g_source_remove(data->source_timer);
+ if (data->sink_timer > 0)
+ g_source_remove(data->sink_timer);
+
if (data->ct_timer > 0)
g_source_remove(data->ct_timer);
@@ -142,9 +147,34 @@ static struct policy_data *policy_get_data(struct btd_device *dev)
return data;
}
-static void sink_cb(struct btd_device *dev, btd_service_state_t old_state,
+static gboolean policy_connect_sink(gpointer user_data)
+{
+ struct policy_data *data = user_data;
+ struct btd_service *service;
+
+ data->source_timer = 0;
+
+ service = btd_device_get_service(data->dev, A2DP_SINK_UUID);
+ if (service != NULL)
+ policy_connect(data, service);
+
+ return FALSE;
+}
+
+static void policy_set_sink_timer(struct policy_data *data)
+{
+ if (data->sink_timer > 0)
+ g_source_remove(data->sink_timer);
+
+ data->sink_timer = g_timeout_add_seconds(SINK_RETRY_TIMEOUT,
+ policy_connect_sink,
+ data);
+}
+
+static void sink_cb(struct btd_service *service, btd_service_state_t old_state,
btd_service_state_t new_state)
{
+ struct btd_device *dev = btd_service_get_device(service);
struct policy_data *data;
struct btd_service *controller;
@@ -157,6 +187,18 @@ static void sink_cb(struct btd_device *dev, btd_service_state_t old_state,
switch (new_state) {
case BTD_SERVICE_STATE_UNAVAILABLE:
case BTD_SERVICE_STATE_DISCONNECTED:
+ if (old_state == BTD_SERVICE_STATE_CONNECTING) {
+ int err = btd_service_get_error(service);
+
+ if (err == -EAGAIN) {
+ policy_set_sink_timer(data);
+ break;
+ } else if (data->sink_timer > 0) {
+ g_source_remove(data->sink_timer);
+ data->sink_timer = 0;
+ }
+ }
+
if (data->ct_timer > 0) {
g_source_remove(data->ct_timer);
data->ct_timer = 0;
@@ -167,6 +209,11 @@ static void sink_cb(struct btd_device *dev, btd_service_state_t old_state,
case BTD_SERVICE_STATE_CONNECTING:
break;
case BTD_SERVICE_STATE_CONNECTED:
+ if (data->sink_timer > 0) {
+ g_source_remove(data->sink_timer);
+ data->sink_timer = 0;
+ }
+
/* Check if service initiate the connection then proceed
* immediatelly otherwise set timer
*/
@@ -351,7 +398,7 @@ static void service_cb(struct btd_service *service,
struct btd_profile *profile = btd_service_get_profile(service);
if (g_str_equal(profile->remote_uuid, A2DP_SINK_UUID))
- sink_cb(dev, old_state, new_state);
+ sink_cb(service, old_state, new_state);
else if (g_str_equal(profile->remote_uuid, A2DP_SOURCE_UUID))
source_cb(service, old_state, new_state);
else if (g_str_equal(profile->remote_uuid, AVRCP_REMOTE_UUID))