diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-11 13:02:10 +0000 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-11 13:02:10 +0000 |
commit | 37b86c3b3bf4641c7f41c701f531ffbfc5ebe720 (patch) | |
tree | 697038f5edc0efd4fd24c947ffcf619f35d26535 /audio/avdtp.c | |
parent | 36a07968fcc69442e3248caa46e74de18bacea75 (diff) |
Implement support for receiving the Close command
Diffstat (limited to 'audio/avdtp.c')
-rw-r--r-- | audio/avdtp.c | 60 |
1 files changed, 57 insertions, 3 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c index cf6060e4..2d71e272 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -171,6 +171,10 @@ struct abort_resp { struct avdtp_header header; } __attribute__ ((packed)); +struct close_resp { + struct avdtp_header header; +} __attribute__ ((packed)); + struct stream_pause_resp { struct avdtp_header header; uint8_t rfa0:2; @@ -309,6 +313,9 @@ static gboolean avdtp_send(struct avdtp *session, void *data, int len) { int ret; + if (session->sock < 0) + return FALSE; + ret = send(session->sock, data, len, 0); if (ret < 0) @@ -332,7 +339,6 @@ static void pending_req_free(struct pending_req *req) g_free(req); } -#if 0 static gboolean stream_close_timeout(gpointer user_data) { struct avdtp_stream *stream = user_data; @@ -341,7 +347,6 @@ static gboolean stream_close_timeout(gpointer user_data) return FALSE; } -#endif static gboolean disconnect_timeout(gpointer user_data) { @@ -389,6 +394,8 @@ static void stream_free(struct avdtp_stream *stream) stream->lsep->info.inuse = 0; stream->lsep->stream = NULL; stream->rsep->stream = NULL; + if (stream->close_timer) + g_source_remove(stream->close_timer); if (stream->caps) { g_slist_foreach(stream->caps, (GFunc) g_free, NULL); g_slist_free(stream->caps); @@ -717,7 +724,54 @@ static gboolean avdtp_start_cmd(struct avdtp *session, struct seid_req *req, static gboolean avdtp_close_cmd(struct avdtp *session, struct seid_req *req, int size) { - return avdtp_unknown_cmd(session, (void *) req, size); + struct avdtp_local_sep *sep; + struct avdtp_stream *stream; + struct close_resp *rsp = (struct close_resp *) session->buf; + struct seid_rej rej; + uint8_t err; + gboolean ret; + + if (size < sizeof(struct seid_req)) { + error("Too short abort request"); + return FALSE; + } + + sep = find_local_sep_by_seid(req->acp_seid); + if (!sep || !sep->stream) { + err = AVDTP_BAD_ACP_SEID; + goto failed; + } + + if (sep->state != AVDTP_STATE_OPEN && + sep->state != AVDTP_STATE_STREAMING) { + err = AVDTP_BAD_STATE; + goto failed; + } + + stream = sep->stream; + + if (sep->ind && sep->ind->close) { + if (!sep->ind->close(sep, stream, &err)) + goto failed; + } + + avdtp_sep_set_state(session, sep, AVDTP_STATE_CLOSING); + + init_response(&rsp->header, &req->header, TRUE); + + ret = avdtp_send(session, rsp, sizeof(struct close_resp)); + if (ret == TRUE) { + stream->close_timer = g_timeout_add(REQ_TIMEOUT, + stream_close_timeout, + stream); + } + + return ret; + +failed: + init_response(&rej.header, &req->header, FALSE); + rej.error = err; + return avdtp_send(session, &rej, sizeof(rej)); } static gboolean avdtp_suspend_cmd(struct avdtp *session, struct seid_req *req, |