diff options
-rw-r--r-- | audio/a2dp.c | 102 | ||||
-rw-r--r-- | audio/a2dp.h | 3 | ||||
-rw-r--r-- | audio/avdtp.c | 22 | ||||
-rw-r--r-- | audio/avdtp.h | 17 | ||||
-rw-r--r-- | audio/sink.c | 4 |
5 files changed, 91 insertions, 57 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c index 5dd85a5e..cb43dce2 100644 --- a/audio/a2dp.c +++ b/audio/a2dp.c @@ -26,6 +26,7 @@ #endif #include <stdlib.h> +#include <errno.h> #include <dbus/dbus.h> #include <glib.h> @@ -112,19 +113,29 @@ static struct device *a2dp_get_dev(struct avdtp *session) return manager_device_connected(&addr, A2DP_SOURCE_UUID); } -static void setup_callback(struct a2dp_stream_cb *cb, - struct a2dp_stream_setup *s) +static gboolean finalize_stream_setup(struct a2dp_stream_setup *s, struct avdtp_error *err) { - cb->cb(s->session, s->sep, s->stream, cb->user_data); -} + GSList *l; + + for (l = s->cb; l != NULL; l = l->next) { + struct a2dp_stream_cb *cb = l->data; + + cb->cb(s->session, s->sep, s->stream, cb->user_data, err); + } -static gboolean finalize_stream_setup(struct a2dp_stream_setup *s) -{ - g_slist_foreach(s->cb, (GFunc) setup_callback, s); stream_setup_free(s); return FALSE; } +static gboolean finalize_stream_setup_errno(struct a2dp_stream_setup *s, int err) +{ + struct avdtp_error avdtp_err; + + avdtp_error_init(&avdtp_err, AVDTP_ERROR_ERRNO, -err); + + return finalize_stream_setup(s, err ? &avdtp_err : NULL); +} + static struct a2dp_stream_setup *find_setup_by_session(struct avdtp *session) { GSList *l; @@ -324,22 +335,23 @@ static gboolean a2dp_select_capabilities(struct avdtp *session, return TRUE; } -static void discovery_complete(struct avdtp *session, GSList *seps, int err, +static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp_error *err, void *user_data) { struct avdtp_local_sep *lsep; struct avdtp_remote_sep *rsep; struct a2dp_stream_setup *setup; GSList *caps = NULL; + int posix_err; setup = find_setup_by_session(session); if (!setup) return; - if (err < 0 || setup->canceled) { + if (err || setup->canceled) { setup->stream = NULL; - finalize_stream_setup(setup); + finalize_stream_setup(setup, err); return; } @@ -348,21 +360,21 @@ static void discovery_complete(struct avdtp *session, GSList *seps, int err, if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO, A2DP_CODEC_SBC, &lsep, &rsep) < 0) { error("No matching ACP and INT SEPs found"); - finalize_stream_setup(setup); + finalize_stream_setup_errno(setup, -EINVAL); return; } if (!a2dp_select_capabilities(session, rsep, &caps)) { error("Unable to select remote SEP capabilities"); - finalize_stream_setup(setup); + finalize_stream_setup_errno(setup, -EINVAL); return; } - err = avdtp_set_configuration(session, rsep, lsep, caps, + posix_err = avdtp_set_configuration(session, rsep, lsep, caps, &setup->stream); - if (err < 0) { - error("avdtp_set_configuration: %s", strerror(-err)); - finalize_stream_setup(setup); + if (posix_err < 0) { + error("avdtp_set_configuration: %s", strerror(-posix_err)); + finalize_stream_setup_errno(setup, posix_err); } } @@ -490,7 +502,7 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, if (err) { if (setup) - finalize_stream_setup(setup); + finalize_stream_setup(setup, err); return; } @@ -510,7 +522,7 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, error("Error on avdtp_open %s (%d)", strerror(-ret), -ret); setup->stream = NULL; - finalize_stream_setup(setup); + finalize_stream_setup_errno(setup, ret); } } @@ -557,6 +569,7 @@ static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep, { struct a2dp_sep *a2dp_sep = user_data; struct a2dp_stream_setup *setup; + int posix_err; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("SBC Sink: Open_Cfm"); @@ -576,19 +589,22 @@ static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep, if (err) { setup->stream = NULL; - goto finalize; + finalize_stream_setup(setup, err); + return; } if (setup->start) { - if (avdtp_start(session, stream) == 0) + posix_err = avdtp_start(session, stream); + if (posix_err == 0) return; error("avdtp_start failed"); - setup->stream = NULL; + setup->stream = NULL; } + else + posix_err = 0; -finalize: - finalize_stream_setup(setup); + finalize_stream_setup_errno(setup, -posix_err); } static gboolean suspend_timeout(struct a2dp_sep *sep) @@ -646,10 +662,12 @@ static void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep, return; } - if (err) + if (err) { setup->stream = NULL; - - finalize_stream_setup(setup); + finalize_stream_setup(setup, err); + } + else + finalize_stream_setup_errno(setup, 0); } static gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep, @@ -671,6 +689,7 @@ static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep, { struct a2dp_sep *a2dp_sep = user_data; struct a2dp_stream_setup *setup; + int posix_err; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("SBC Sink: Suspend_Cfm"); @@ -684,13 +703,14 @@ static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep, return; if (err) { - finalize_stream_setup(setup); + finalize_stream_setup(setup, err); return; } if (setup->start) { - if (avdtp_start(session, stream) < 0) - finalize_stream_setup(setup); + posix_err = avdtp_start(session, stream); + if (posix_err < 0) + finalize_stream_setup_errno(setup, posix_err); } } @@ -714,6 +734,7 @@ static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep, { struct a2dp_sep *a2dp_sep = user_data; struct a2dp_stream_setup *setup; + int posix_err; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("SBC Sink: Close_Cfm"); @@ -731,19 +752,22 @@ static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep, if (err) { setup->stream = NULL; - goto finalize; + finalize_stream_setup(setup, err); + return; } if (setup->start) { - if (avdtp_discover(session, discovery_complete, setup) == 0) + posix_err = avdtp_discover(session, discovery_complete, setup); + if (posix_err == 0) return; error("avdtp_discover failed"); setup->stream = NULL; } + else + posix_err = 0; -finalize: - finalize_stream_setup(setup); + finalize_stream_setup_errno(setup, -posix_err); } static gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep, @@ -792,6 +816,7 @@ static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, { struct a2dp_sep *a2dp_sep = user_data; struct a2dp_stream_setup *setup; + int posix_err; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("SBC Sink: ReConfigure_Cfm"); @@ -811,19 +836,22 @@ static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, if (err) { setup->stream = NULL; - goto finalize; + finalize_stream_setup(setup, err); + return; } if (setup->start) { - if (avdtp_start(session, stream) == 0) + posix_err = avdtp_start(session, stream); + if (posix_err == 0) return; error("avdtp_start failed"); setup->stream = NULL; } + else + posix_err = 0; -finalize: - finalize_stream_setup(setup); + finalize_stream_setup_errno(setup, -posix_err); } static struct avdtp_sep_cfm cfm = { diff --git a/audio/a2dp.h b/audio/a2dp.h index e0d1c2f6..dffdf259 100644 --- a/audio/a2dp.h +++ b/audio/a2dp.h @@ -81,7 +81,8 @@ struct a2dp_sep; typedef void (*a2dp_stream_cb_t) (struct avdtp *session, struct a2dp_sep *sep, struct avdtp_stream *stream, - void *user_data); + void *user_data, + struct avdtp_error *err); int a2dp_init(DBusConnection *conn, int sources, int sinks); void a2dp_exit(void); diff --git a/audio/avdtp.c b/audio/avdtp.c index 7907763a..ee1bd06d 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -77,11 +77,6 @@ #define STREAM_TIMEOUT 20000 typedef enum { - AVDTP_ERROR_ERRNO, - AVDTP_ERROR_ERROR_CODE -} avdtp_error_type_t; - -typedef enum { AVDTP_SESSION_STATE_DISCONNECTED, AVDTP_SESSION_STATE_CONNECTING, AVDTP_SESSION_STATE_CONNECTED @@ -362,14 +357,6 @@ struct avdtp { DBusPendingCall *pending_auth; }; -struct avdtp_error { - avdtp_error_type_t type; - union { - uint8_t error_code; - int posix_errno; - } err; -}; - static uint8_t free_seid = 1; static GSList *local_seps = NULL; @@ -499,7 +486,7 @@ static void set_disconnect_timer(struct avdtp *session) disconnect_timeout, session); } -static void avdtp_error_init(struct avdtp_error *err, uint8_t type, int id) +void avdtp_error_init(struct avdtp_error *err, uint8_t type, int id) { err->type = type; switch (type) { @@ -698,10 +685,15 @@ static void avdtp_sep_set_state(struct avdtp *session, static void finalize_discovery(struct avdtp *session, int err) { + struct avdtp_error avdtp_err; + + avdtp_error_init(&avdtp_err, AVDTP_ERROR_ERRNO, -err); + if (!session->discov_cb) return; - session->discov_cb(session, session->seps, err, + session->discov_cb(session, session->seps, + err ? &avdtp_err : NULL, session->user_data); session->discov_cb = NULL; diff --git a/audio/avdtp.h b/audio/avdtp.h index e81bf496..6af47e57 100644 --- a/audio/avdtp.h +++ b/audio/avdtp.h @@ -21,11 +21,22 @@ * */ +typedef enum { + AVDTP_ERROR_ERRNO, + AVDTP_ERROR_ERROR_CODE +} avdtp_error_type_t; + struct avdtp; struct avdtp_stream; struct avdtp_local_sep; struct avdtp_remote_sep; -struct avdtp_error; +struct avdtp_error { + avdtp_error_type_t type; + union { + uint8_t error_code; + int posix_errno; + } err; +}; /* SEP capability categories */ #define AVDTP_MEDIA_TRANSPORT 0x01 @@ -177,7 +188,7 @@ struct avdtp_sep_ind { }; typedef void (*avdtp_discover_cb_t) (struct avdtp *session, GSList *seps, - int err, void *user_data); + struct avdtp_error *err, void *user_data); struct avdtp *avdtp_get(bdaddr_t *src, bdaddr_t *dst); @@ -240,7 +251,9 @@ 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); void avdtp_get_peers(struct avdtp *session, bdaddr_t *src, bdaddr_t *dst); diff --git a/audio/sink.c b/audio/sink.c index ea95bcf7..e249af18 100644 --- a/audio/sink.c +++ b/audio/sink.c @@ -135,7 +135,7 @@ static void stream_state_changed(struct avdtp_stream *stream, static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep, struct avdtp_stream *stream, - void *user_data) + void *user_data, struct avdtp_error *err) { struct sink *sink = user_data; struct pending_request *pending; @@ -153,7 +153,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep, err_failed(pending->conn, pending->msg, "Stream setup failed"); avdtp_unref(sink->session); sink->session = NULL; - debug("Stream setup failed"); + debug("Stream setup failed : %s", avdtp_strerror(err)); } pending_request_free(pending); |