Index: audio/sink.c =================================================================== --- audio/sink.c (.../tags/20071008_1310) (révision 113) +++ audio/sink.c (.../branches/20071008_1310) (révision 113) @@ -40,12 +40,14 @@ #include "avdtp.h" #include "device.h" #include "a2dp.h" #include "error.h" #include "sink.h" +#define STREAM_SETUP_RETRY_TIMER 2000 + struct pending_request { DBusConnection *conn; DBusMessage *msg; unsigned int id; }; @@ -130,35 +132,63 @@ break; } 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) { struct sink *sink = user_data; 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, DBusMessage *msg, void *data) { struct device *dev = data; Index: audio/avdtp.c =================================================================== --- audio/avdtp.c (.../tags/20071008_1310) (révision 113) +++ audio/avdtp.c (.../branches/20071008_1310) (révision 113) @@ -496,12 +496,29 @@ case AVDTP_ERROR_ERROR_CODE: err->err.error_code = id; break; } } +avdtp_error_type_t avdtp_error_type(struct avdtp_error *err) +{ + return err->type; +} + +int avdtp_error_error_code(struct avdtp_error *err) +{ + g_assert(err->type == AVDTP_ERROR_ERROR_CODE); + return err->err.error_code; +} + +int avdtp_error_posix_errno(struct avdtp_error *err) +{ + g_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) { GSList *l; for (l = session->streams; l != NULL; l = g_slist_next(l)) { Index: audio/avdtp.h =================================================================== --- audio/avdtp.h (.../tags/20071008_1310) (révision 113) +++ audio/avdtp.h (.../branches/20071008_1310) (révision 113) @@ -250,13 +250,15 @@ int avdtp_unregister_sep(struct avdtp_local_sep *sep); 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); int avdtp_init(void); void avdtp_exit(void);