#include "src/profile.h"
#define CONTROL_CONNECT_TIMEOUT 2
+#define SOURCE_RETRY_TIMEOUT 2
static unsigned int service_id = 0;
static GSList *devices = NULL;
struct policy_data {
struct btd_device *dev;
+ guint source_timer;
guint ct_timer;
guint tg_timer;
};
{
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);
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;
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;
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
*/
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))
#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;
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)
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,
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;
}
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);