From: Fabien Chevalier <fchevalier@silicom.fr>
To: Fabien Chevalier <fchevalier@silicom.fr>
Cc: Marcel Holtmann <marcel@holtmann.org>,
Johan Hedberg <johan.hedberg@nokia.com>,
BlueZ development <bluez-devel@lists.sourceforge.net>
Subject: Re: [PATCH] Allows sink.c to know why the stream setup failed
Date: Fri, 28 Sep 2007 15:02:07 +0200 [thread overview]
Message-ID: <46FCFB4F.7040700@silicom.fr> (raw)
In-Reply-To: <46FCE4A3.4060002@silicom.fr>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Thanks to Johan review, this is an updated version of the patch.
Fabien
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: avdtp-error-codes-up-the-call-stack.patch --]
[-- Type: text/x-patch; name="avdtp-error-codes-up-the-call-stack.patch", Size: 13720 bytes --]
--- audio/a2dp.c (.../trunk) (révision 71)
+++ audio/a2dp.c (.../branches/20070928_1202) (révision 71)
@@ -23,12 +23,13 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
+#include <errno.h>
#include <dbus/dbus.h>
#include <glib.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
@@ -109,25 +110,35 @@
avdtp_get_peers(session, NULL, &addr);
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;
for (l = setups; l != NULL; l = l->next) {
struct a2dp_stream_setup *setup = l->data;
@@ -321,51 +332,52 @@
*caps = g_slist_append(*caps, media_codec);
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;
}
debug("Discovery complete");
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);
}
}
static gboolean setconf_ind(struct avdtp *session,
struct avdtp_local_sep *sep,
struct avdtp_stream *stream,
@@ -487,13 +499,13 @@
debug("SBC Source: Set_Configuration_Cfm");
setup = find_setup_by_session(session);
if (err) {
if (setup)
- finalize_stream_setup(setup);
+ finalize_stream_setup(setup, err);
return;
}
avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
a2dp_sep->stream = stream;
@@ -507,13 +519,13 @@
ret = avdtp_open(session, stream);
if (ret < 0) {
error("Error on avdtp_open %s (%d)", strerror(-ret),
-ret);
setup->stream = NULL;
- finalize_stream_setup(setup);
+ finalize_stream_setup_errno(setup, ret);
}
}
static gboolean getconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
uint8_t *err, void *user_data)
{
@@ -554,12 +566,13 @@
static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
struct avdtp_stream *stream, struct avdtp_error *err,
void *user_data)
{
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");
else
debug("SBC Source: Open_Cfm");
@@ -573,25 +586,28 @@
stream_setup_free(setup);
return;
}
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)
{
if (avdtp_suspend(sep->session, sep->stream) == 0)
sep->suspending = TRUE;
@@ -643,16 +659,18 @@
if (!err)
avdtp_close(session, stream);
stream_setup_free(setup);
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,
struct avdtp_stream *stream, uint8_t *err,
void *user_data)
{
@@ -668,12 +686,13 @@
static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
struct avdtp_stream *stream, struct avdtp_error *err,
void *user_data)
{
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");
else
debug("SBC Source: Suspend_Cfm");
@@ -681,19 +700,20 @@
setup = find_setup_by_session(session);
if (!setup)
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);
}
}
static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
struct avdtp_stream *stream, uint8_t *err,
void *user_data)
@@ -711,12 +731,13 @@
static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
struct avdtp_stream *stream, struct avdtp_error *err,
void *user_data)
{
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");
else
debug("SBC Source: Close_Cfm");
@@ -728,25 +749,28 @@
stream_setup_free(setup);
return;
}
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,
struct avdtp_stream *stream, uint8_t *err,
void *user_data)
{
@@ -789,12 +813,13 @@
static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
struct avdtp_stream *stream, struct avdtp_error *err,
void *user_data)
{
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");
else
debug("SBC Source: ReConfigure_Cfm");
@@ -808,25 +833,28 @@
stream_setup_free(setup);
return;
}
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 = {
.set_configuration = setconf_cfm,
.get_configuration = getconf_cfm,
.open = open_cfm,
Index: audio/a2dp.h
===================================================================
--- audio/a2dp.h (.../trunk) (révision 71)
+++ audio/a2dp.h (.../branches/20070928_1202) (révision 71)
@@ -78,13 +78,14 @@
#endif
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);
unsigned int a2dp_source_request_stream(struct avdtp *session,
gboolean start, a2dp_stream_cb_t cb,
Index: audio/sink.c
===================================================================
--- audio/sink.c (.../trunk) (révision 71)
+++ audio/sink.c (.../branches/20070928_1202) (révision 71)
@@ -132,13 +132,13 @@
sink->state = new_state;
}
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;
pending = sink->connect;
sink->connect = NULL;
@@ -150,13 +150,13 @@
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");
+ debug("Stream setup failed : %s", avdtp_strerror(err));
}
pending_request_free(pending);
}
static DBusHandlerResult sink_connect(DBusConnection *conn,
Index: audio/avdtp.c
===================================================================
--- audio/avdtp.c (.../trunk) (révision 71)
+++ audio/avdtp.c (.../branches/20070928_1202) (révision 71)
@@ -74,17 +74,12 @@
#define REQ_TIMEOUT 4000
#define DISCONNECT_TIMEOUT 5000
#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
} avdtp_session_state_t;
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -359,20 +354,12 @@
guint dc_timer;
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;
static GIOChannel *avdtp_server = NULL;
static GSList *sessions = NULL;
@@ -496,13 +483,13 @@
remove_disconnect_timer(session);
session->dc_timer = g_timeout_add(DISCONNECT_TIMEOUT,
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) {
case AVDTP_ERROR_ERRNO:
err->err.posix_errno = id;
break;
@@ -695,16 +682,21 @@
break;
}
}
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;
session->user_data = NULL;
}
--- audio/avdtp.h (.../trunk) (révision 71)
+++ audio/avdtp.h (.../branches/20070928_1202) (révision 71)
@@ -18,17 +18,28 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+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
#define AVDTP_REPORTING 0x02
#define AVDTP_RECOVERY 0x03
#define AVDTP_CONTENT_PROTECTION 0x04
@@ -174,13 +185,13 @@
gboolean (*reconfigure) (struct avdtp *session,
struct avdtp_local_sep *lsep,
uint8_t *err, void *user_data);
};
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);
void avdtp_unref(struct avdtp *session);
struct avdtp *avdtp_ref(struct avdtp *session);
@@ -237,13 +248,15 @@
struct avdtp_remote_sep **rsep);
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);
int avdtp_init(void);
void avdtp_exit(void);
[-- Attachment #3: fchevalier.vcf --]
[-- Type: text/x-vcard, Size: 253 bytes --]
begin:vcard
fn:Fabien CHEVALIER
n:CHEVALIER;Fabien
org:SILICOM
adr:;;4 rue de Jouanet; RENNES ATALANTE;;35700;FRANCE
email;internet:fchevalier@silicom.fr
title:Software & Studies Engineer
tel;work:+33 (0) 2 99 84 17 17
version:2.1
end:vcard
next prev parent reply other threads:[~2007-09-28 13:02 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-28 11:25 [PATCH] Allows sink.c to know why the stream setup failed Fabien Chevalier
2007-09-28 13:02 ` Fabien Chevalier [this message]
2007-09-28 13:47 ` Johan Hedberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46FCFB4F.7040700@silicom.fr \
--to=fchevalier@silicom.fr \
--cc=bluez-devel@lists.sourceforge.net \
--cc=johan.hedberg@nokia.com \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox