diff --git a/plugins/policy.c b/plugins/policy.c
index 667253d..c587373 100644
--- a/plugins/policy.c
+++ b/plugins/policy.c
#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;
struct btd_device *dev;
guint source_timer;
+ guint sink_timer;
guint ct_timer;
guint tg_timer;
};
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);
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;
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;
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
*/
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))
diff --git a/profiles/audio/sink.c b/profiles/audio/sink.c
index 9226002..7211e68 100644
--- a/profiles/audio/sink.c
+++ b/profiles/audio/sink.c
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;
sink_state_t state;
sink->stream_state = new_state;
}
-static gboolean stream_setup_retry(gpointer user_data)
-{
- struct sink *sink = user_data;
-
- sink->retry_id = 0;
-
- if (sink->stream_state < AVDTP_STATE_OPEN) {
- DBG("Stream setup failed, after XCASE connect:connect");
- btd_service_connecting_complete(sink->service, -EIO);
- }
-
- if (sink->connect_id > 0) {
- a2dp_cancel(sink->connect_id);
- sink->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)
avdtp_unref(sink->session);
sink->session = NULL;
if (avdtp_error_category(err) == AVDTP_ERRNO
- && avdtp_error_posix_errno(err) != EHOSTDOWN) {
- DBG("connect:connect XCASE detected");
- sink->retry_id = g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
- stream_setup_retry,
- sink);
- } else {
- DBG("Stream setup failed : %s", avdtp_strerror(err));
+ && avdtp_error_posix_errno(err) != EHOSTDOWN)
+ btd_service_connecting_complete(sink->service, -EAGAIN);
+ else
btd_service_connecting_complete(sink->service, -EIO);
- }
}
static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
void *user_data)
{
struct sink *sink = user_data;
- int id;
+ int id, perr;
if (err) {
avdtp_unref(sink->session);
sink->session = NULL;
if (avdtp_error_category(err) == AVDTP_ERRNO
&& avdtp_error_posix_errno(err) != EHOSTDOWN) {
- DBG("connect:connect XCASE detected");
- sink->retry_id =
- g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
- stream_setup_retry,
- sink);
+ perr = -EAGAIN;
} else
- goto failed;
- return;
+ perr = -EIO;
+ goto failed;
}
DBG("Discovery complete");
id = a2dp_select_capabilities(sink->session, AVDTP_SEP_TYPE_SINK, NULL,
select_complete, sink);
- if (id == 0)
+ if (id == 0) {
+ perr = -EIO;
goto failed;
+ }
sink->connect_id = id;
return;
failed:
- btd_service_connecting_complete(sink->service, -EIO);
+ btd_service_connecting_complete(sink->service, perr);
avdtp_unref(sink->session);
sink->session = NULL;
}
sink->disconnect_id = 0;
}
- if (sink->retry_id)
- g_source_remove(sink->retry_id);
-
avdtp_remove_state_cb(sink->avdtp_callback_id);
btd_service_unref(sink->service);