summaryrefslogtreecommitdiffstats
path: root/audio/avdtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/avdtp.c')
-rw-r--r--audio/avdtp.c117
1 files changed, 72 insertions, 45 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c
index d03afbae..a50b82b3 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -387,6 +387,9 @@ static gboolean avdtp_parse_rej(struct avdtp *session,
struct avdtp_header *header, int size);
static int process_queue(struct avdtp *session);
static void connection_lost(struct avdtp *session, int err);
+static void avdtp_sep_set_state(struct avdtp *session,
+ struct avdtp_local_sep *sep,
+ avdtp_state_t state);
static const char *avdtp_statestr(avdtp_state_t state)
{
@@ -572,6 +575,60 @@ static gboolean stream_timeout(struct avdtp_stream *stream)
return FALSE;
}
+static gboolean transport_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct avdtp_stream *stream = data;
+ struct avdtp_local_sep *sep = stream->lsep;
+
+ if (stream->close_int && sep->cfm && sep->cfm->close)
+ sep->cfm->close(stream->session, sep, stream, NULL,
+ sep->user_data);
+
+ stream->io = 0;
+
+ avdtp_sep_set_state(stream->session, sep, AVDTP_STATE_IDLE);
+
+ return FALSE;
+}
+
+static void handle_transport_connect(struct avdtp *session, int sock,
+ uint16_t mtu)
+{
+ struct avdtp_stream *stream = session->pending_open;
+ struct avdtp_local_sep *sep = stream->lsep;
+ GIOChannel *channel;
+
+ session->pending_open = NULL;
+
+ if (stream->timer) {
+ g_source_remove(stream->timer);
+ stream->timer = 0;
+ }
+
+ if (sock < 0) {
+ if (!stream->open_acp && sep->cfm && sep->cfm->open) {
+ struct avdtp_error err;
+ avdtp_error_init(&err, AVDTP_ERROR_ERRNO, EIO);
+ sep->cfm->open(session, sep, NULL, &err,
+ sep->user_data);
+ }
+ return;
+ }
+
+ stream->sock = sock;
+ stream->mtu = mtu;
+
+ if (!stream->open_acp && sep->cfm && sep->cfm->open)
+ sep->cfm->open(session, sep, stream, NULL, sep->user_data);
+
+ channel = g_io_channel_unix_new(stream->sock);
+
+ stream->io = g_io_add_watch(channel, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) transport_cb, stream);
+ g_io_channel_unref(channel);
+}
+
static void avdtp_sep_set_state(struct avdtp *session,
struct avdtp_local_sep *sep,
avdtp_state_t state)
@@ -623,6 +680,8 @@ static void avdtp_sep_set_state(struct avdtp *session,
stream->idle_timer = 0;
}
session->streams = g_slist_remove(session->streams, stream);
+ if (session->pending_open == stream)
+ handle_transport_connect(session, -1, 0);
stream_free(stream);
if (session->ref == 1 && !session->streams)
set_disconnect_timer(session);
@@ -1311,50 +1370,6 @@ static gboolean avdtp_parse_cmd(struct avdtp *session,
}
}
-static gboolean transport_cb(GIOChannel *chan, GIOCondition cond,
- gpointer data)
-{
- struct avdtp_stream *stream = data;
- struct avdtp_local_sep *sep = stream->lsep;
-
- if (stream->close_int && sep->cfm && sep->cfm->close)
- sep->cfm->close(stream->session, sep, stream, NULL,
- sep->user_data);
-
- stream->io = 0;
-
- avdtp_sep_set_state(stream->session, sep, AVDTP_STATE_IDLE);
-
- return FALSE;
-}
-
-static void handle_transport_connect(struct avdtp *session, int sock,
- uint16_t mtu)
-{
- struct avdtp_stream *stream = session->pending_open;
- struct avdtp_local_sep *sep = stream->lsep;
- GIOChannel *channel;
-
- session->pending_open = NULL;
-
- if (stream->timer) {
- g_source_remove(stream->timer);
- stream->timer = 0;
- }
-
- stream->sock = sock;
- stream->mtu = mtu;
-
- if (!stream->open_acp && sep->cfm && sep->cfm->open)
- sep->cfm->open(session, sep, stream, NULL, sep->user_data);
-
- channel = g_io_channel_unix_new(stream->sock);
-
- stream->io = g_io_add_watch(channel, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) transport_cb, stream);
- g_io_channel_unref(channel);
-}
-
static void init_request(struct avdtp_header *header, int request_id)
{
static int transaction = 0;
@@ -1488,12 +1503,13 @@ static gboolean l2cap_connect_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
}
+ sk = g_io_channel_unix_get_fd(chan);
+
if (cond & (G_IO_ERR | G_IO_HUP)) {
err = EIO;
goto failed;
}
- sk = g_io_channel_unix_get_fd(chan);
len = sizeof(ret);
if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
err = errno;
@@ -1533,12 +1549,18 @@ static gboolean l2cap_connect_cb(GIOChannel *chan, GIOCondition cond,
}
else if (session->pending_open)
handle_transport_connect(session, sk, l2o.imtu);
+ else {
+ err = -EIO;
+ goto failed;
+ }
process_queue(session);
return FALSE;
failed:
+ close(sk);
+
if (session->pending_open) {
avdtp_sep_set_state(session, session->pending_open->lsep,
AVDTP_STATE_IDLE);
@@ -2897,3 +2919,8 @@ void avdtp_exit(void)
g_io_channel_unref(avdtp_server);
avdtp_server = NULL;
}
+
+gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
+{
+ return g_slist_find(session->streams, stream) ? TRUE : FALSE;
+}