OSDN Git Service

audio/source: Move stream retry logic to policy plugin
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 5 Jul 2013 10:29:28 +0000 (13:29 +0300)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 12 Jul 2013 12:05:49 +0000 (15:05 +0300)
policy plugin is a better place to have such a logic as it is already
handling other connection policies related to such profiles.

plugins/policy.c
profiles/audio/source.c

index b0679f8..667253d 100644 (file)
@@ -40,6 +40,7 @@
 #include "src/profile.h"
 
 #define CONTROL_CONNECT_TIMEOUT 2
+#define SOURCE_RETRY_TIMEOUT 2
 
 static unsigned int service_id = 0;
 static GSList *devices = NULL;
@@ -47,6 +48,7 @@ static GSList *devices = NULL;
 struct policy_data {
        struct btd_device *dev;
 
+       guint source_timer;
        guint ct_timer;
        guint tg_timer;
 };
@@ -112,6 +114,9 @@ static void policy_remove(void *user_data)
 {
        struct policy_data *data = user_data;
 
+       if (data->source_timer > 0)
+               g_source_remove(data->source_timer);
+
        if (data->ct_timer > 0)
                g_source_remove(data->ct_timer);
 
@@ -200,9 +205,35 @@ static void policy_set_tg_timer(struct policy_data *data)
                                                        data);
 }
 
-static void source_cb(struct btd_device *dev, btd_service_state_t old_state,
+static gboolean policy_connect_source(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_SOURCE_UUID);
+       if (service != NULL)
+               policy_connect(data, service);
+
+       return FALSE;
+}
+
+static void policy_set_source_timer(struct policy_data *data)
+{
+       if (data->source_timer > 0)
+               g_source_remove(data->source_timer);
+
+       data->source_timer = g_timeout_add_seconds(SOURCE_RETRY_TIMEOUT,
+                                                       policy_connect_source,
+                                                       data);
+}
+
+static void source_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 *target;
 
@@ -215,6 +246,18 @@ static void source_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_source_timer(data);
+                               break;
+                       } else if (data->source_timer > 0) {
+                               g_source_remove(data->source_timer);
+                               data->source_timer = 0;
+                       }
+               }
+
                if (data->tg_timer > 0) {
                        g_source_remove(data->tg_timer);
                        data->tg_timer = 0;
@@ -225,6 +268,11 @@ static void source_cb(struct btd_device *dev, btd_service_state_t old_state,
        case BTD_SERVICE_STATE_CONNECTING:
                break;
        case BTD_SERVICE_STATE_CONNECTED:
+               if (data->source_timer > 0) {
+                       g_source_remove(data->source_timer);
+                       data->source_timer = 0;
+               }
+
                /* Check if service initiate the connection then proceed
                 * immediatelly otherwise set timer
                 */
@@ -305,7 +353,7 @@ static void service_cb(struct btd_service *service,
        if (g_str_equal(profile->remote_uuid, A2DP_SINK_UUID))
                sink_cb(dev, old_state, new_state);
        else if (g_str_equal(profile->remote_uuid, A2DP_SOURCE_UUID))
-               source_cb(dev, old_state, new_state);
+               source_cb(service, old_state, new_state);
        else if (g_str_equal(profile->remote_uuid, AVRCP_REMOTE_UUID))
                controller_cb(service, old_state, new_state);
        else if (g_str_equal(profile->remote_uuid, AVRCP_TARGET_UUID))
index 3cb3dbb..0793af3 100644 (file)
 #include "source.h"
 #include "dbus-common.h"
 
-#define STREAM_SETUP_RETRY_TIMER 2
-
 struct source {
        struct btd_service *service;
        struct avdtp *session;
        struct avdtp_stream *stream;
        unsigned int cb_id;
-       guint retry_id;
        avdtp_session_state_t session_state;
        avdtp_state_t stream_state;
        source_state_t state;
@@ -179,25 +176,6 @@ static void stream_state_changed(struct avdtp_stream *stream,
        source->stream_state = new_state;
 }
 
-static gboolean stream_setup_retry(gpointer user_data)
-{
-       struct source *source = user_data;
-
-       source->retry_id = 0;
-
-       if (source->stream_state < AVDTP_STATE_OPEN) {
-               DBG("Stream setup failed, after XCASE connect:connect");
-               btd_service_connecting_complete(source->service, -EIO);
-       }
-
-       if (source->connect_id > 0) {
-               a2dp_cancel(source->connect_id);
-               source->connect_id = 0;
-       }
-
-       return FALSE;
-}
-
 static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
                                        struct avdtp_stream *stream,
                                        struct avdtp_error *err, void *user_data)
@@ -212,15 +190,10 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
        avdtp_unref(source->session);
        source->session = NULL;
        if (avdtp_error_category(err) == AVDTP_ERRNO
-                       && avdtp_error_posix_errno(err) != EHOSTDOWN) {
-               DBG("connect:connect XCASE detected");
-               source->retry_id = g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
-                                                       stream_setup_retry,
-                                                       source);
-       } else {
-               DBG("Stream setup failed : %s", avdtp_strerror(err));
+                               && avdtp_error_posix_errno(err) != EHOSTDOWN)
+               btd_service_connecting_complete(source->service, -EAGAIN);
+       else
                btd_service_connecting_complete(source->service, -EIO);
-       }
 }
 
 static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
@@ -252,35 +225,33 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp
                                void *user_data)
 {
        struct source *source = user_data;
-       int id;
+       int id, perr;
 
        if (err) {
                avdtp_unref(source->session);
                source->session = NULL;
                if (avdtp_error_category(err) == AVDTP_ERRNO
                                && avdtp_error_posix_errno(err) != EHOSTDOWN) {
-                       DBG("connect:connect XCASE detected");
-                       source->retry_id =
-                               g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
-                                                       stream_setup_retry,
-                                                       source);
+                       perr = -EAGAIN;
                } else
-                       goto failed;
-               return;
+                       perr = -EIO;
+               goto failed;
        }
 
        DBG("Discovery complete");
 
        id = a2dp_select_capabilities(source->session, AVDTP_SEP_TYPE_SOURCE, NULL,
                                                select_complete, source);
-       if (id == 0)
+       if (id == 0) {
+               perr = -EIO;
                goto failed;
+       }
 
        source->connect_id = id;
        return;
 
 failed:
-       btd_service_connecting_complete(source->service, -EIO);
+       btd_service_connecting_complete(source->service, perr);
        avdtp_unref(source->session);
        source->session = NULL;
 }
@@ -356,9 +327,6 @@ static void source_free(struct btd_service *service)
                source->disconnect_id = 0;
        }
 
-       if (source->retry_id)
-               g_source_remove(source->retry_id);
-
        avdtp_remove_state_cb(source->avdtp_callback_id);
        btd_service_unref(source->service);