summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-10-09 13:36:33 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-10-09 13:36:33 +0000
commitd328981381cec52309a57b991bad0b832b4b9373 (patch)
treee20e62df02339001bede8c3a2f2c0876b5f9b057
parentaf44f3cafbe4a2a2f2c4bb5879d803f766cf775a (diff)
Handle cross-connect case for AVDTP
-rw-r--r--audio/avdtp.c17
-rw-r--r--audio/avdtp.h4
-rw-r--r--audio/sink.c41
3 files changed, 56 insertions, 6 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c
index ee1bd06d..0fb64bb0 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -499,6 +499,23 @@ void avdtp_error_init(struct avdtp_error *err, uint8_t type, int id)
}
}
+avdtp_error_type_t avdtp_error_type(struct avdtp_error *err)
+{
+ return err->type;
+}
+
+int avdtp_error_error_code(struct avdtp_error *err)
+{
+ assert(err->type == AVDTP_ERROR_ERROR_CODE);
+ return err->err.error_code;
+}
+
+int avdtp_error_posix_errno(struct avdtp_error *err)
+{
+ assert(err->type == AVDTP_ERROR_ERRNO);
+ return err->err.posix_errno;
+}
+
static struct avdtp_stream *find_stream_by_rseid(struct avdtp *session,
uint8_t rseid)
{
diff --git a/audio/avdtp.h b/audio/avdtp.h
index 6af47e57..a14355b9 100644
--- a/audio/avdtp.h
+++ b/audio/avdtp.h
@@ -253,7 +253,9 @@ avdtp_state_t avdtp_sep_get_state(struct avdtp_local_sep *sep);
void avdtp_error_init(struct avdtp_error *err, uint8_t type, int id);
const char *avdtp_strerror(struct avdtp_error *err);
-int avdtp_error_code(struct avdtp_error *err);
+avdtp_error_type_t avdtp_error_type(struct avdtp_error *err);
+int avdtp_error_error_code(struct avdtp_error *err);
+int avdtp_error_posix_errno(struct avdtp_error *err);
void avdtp_get_peers(struct avdtp *session, bdaddr_t *src, bdaddr_t *dst);
diff --git a/audio/sink.c b/audio/sink.c
index 18bf7e37..0c5391f3 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -43,6 +43,8 @@
#include "error.h"
#include "sink.h"
+#define STREAM_SETUP_RETRY_TIMER 2000
+
struct pending_request {
DBusConnection *conn;
DBusMessage *msg;
@@ -133,6 +135,27 @@ static void stream_state_changed(struct avdtp_stream *stream,
sink->state = new_state;
}
+static gboolean stream_setup_retry(gpointer user_data)
+{
+ struct sink *sink = user_data;
+ struct pending_request *pending = sink->connect;
+
+ if (sink->state >= AVDTP_STATE_OPEN) {
+ DBusMessage *reply;
+ debug("Stream successfully created, after XCASE connect:connect");
+ reply = dbus_message_new_method_return(pending->msg);
+ send_message_and_unref(pending->conn, reply);
+ } else {
+ debug("Stream setup failed, after XCASE connect:connect");
+ err_failed(pending->conn, pending->msg, "Stream setup failed");
+ }
+
+ sink->connect = NULL;
+ pending_request_free(pending);
+
+ return FALSE;
+}
+
static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
struct avdtp_stream *stream,
void *user_data, struct avdtp_error *err)
@@ -141,21 +164,29 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
struct pending_request *pending;
pending = sink->connect;
- sink->connect = NULL;
if (stream) {
DBusMessage *reply;
+ sink->connect = NULL;
reply = dbus_message_new_method_return(pending->msg);
send_message_and_unref(pending->conn, reply);
+ pending_request_free(pending);
debug("Stream successfully created");
} else {
- err_failed(pending->conn, pending->msg, "Stream setup failed");
avdtp_unref(sink->session);
sink->session = NULL;
- debug("Stream setup failed : %s", avdtp_strerror(err));
+ if (avdtp_error_type(err) == AVDTP_ERROR_ERRNO
+ && avdtp_error_posix_errno(err) != EHOSTDOWN) {
+ debug("connect:connect XCASE detected");
+ g_timeout_add(STREAM_SETUP_RETRY_TIMER,
+ stream_setup_retry, sink);
+ } else {
+ sink->connect = NULL;
+ err_failed(pending->conn, pending->msg, "Stream setup failed");
+ pending_request_free(pending);
+ debug("Stream setup failed : %s", avdtp_strerror(err));
+ }
}
-
- pending_request_free(pending);
}
static DBusHandlerResult sink_connect(DBusConnection *conn,