See attachment. One way to reproduce the issue is to turn off the remote device abruptly (so that it doesn't make a proper disconnection, for example with a carkit unplug the power), and then try to start the stream (Audio API: BT_REQUEST <- BT_START_STREAM), followed by making a disconnection. Then there will be no BT RESPONSE on the Audio API. /Daniel
From 027a0de811ad24613d9bb0060b3c283acc4be604 Mon Sep 17 00:00:00 2001 From: Daniel Orstadius <daniel.orstadius@xxxxxxxxx> Date: Tue, 9 Feb 2010 18:23:50 +0200 Subject: [PATCH] Handle unanswered AVDTP request on disconnect If the connection is lost when there is an AVDTP request the remote has not replied to and which has not timed out, then at least in some cases the callback for the request is not called leading to no Error response being sent on the Audio API. This patch checks if there is an outstanding request when the stream state goes to idle and in that case triggers the corresponding callback with an error. --- audio/avdtp.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 1 deletions(-) diff --git a/audio/avdtp.c b/audio/avdtp.c index e5622e4..33ad277 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -898,6 +898,62 @@ static void cleanup_queue(struct avdtp *session, struct avdtp_stream *stream) } } +static void handle_unanswered_req(struct avdtp *session, struct avdtp_stream *stream) +{ + struct pending_req *req; + struct avdtp_local_sep *lsep; + struct avdtp_error err; + + error("avdtp: entering handle_unanswered_req"); + + req = session->req; + session->req = NULL; + + avdtp_error_init(&err, AVDTP_ERROR_ERRNO, EIO); + + lsep = stream->lsep; + + switch (req->signal_id) { + case AVDTP_RECONFIGURE: + error("No reply to Reconfigure request"); + if (lsep && lsep->cfm && lsep->cfm->reconfigure) + lsep->cfm->reconfigure(session, lsep, stream, &err, + lsep->user_data); + break; + case AVDTP_OPEN: + error("No reply to Open request"); + if (lsep && lsep->cfm && lsep->cfm->open) + lsep->cfm->open(session, lsep, stream, &err, + lsep->user_data); + break; + case AVDTP_START: + error("No reply to Start request"); + if (lsep && lsep->cfm && lsep->cfm->start) + lsep->cfm->start(session, lsep, stream, &err, + lsep->user_data); + break; + case AVDTP_SUSPEND: + error("No reply to Suspend request"); + if (lsep && lsep->cfm && lsep->cfm->suspend) + lsep->cfm->suspend(session, lsep, stream, &err, + lsep->user_data); + break; + case AVDTP_CLOSE: + error("No reply to Close request"); + if (lsep && lsep->cfm && lsep->cfm->close) + lsep->cfm->close(session, lsep, stream, &err, + lsep->user_data); + break; + case AVDTP_SET_CONFIGURATION: + error("No reply to SetConfiguration request"); + if (lsep && lsep->cfm && lsep->cfm->set_configuration) + lsep->cfm->set_configuration(session, lsep, stream, + &err, lsep->user_data); + } + + pending_req_free(req); +} + static void avdtp_sep_set_state(struct avdtp *session, struct avdtp_local_sep *sep, avdtp_state_t state) @@ -959,7 +1015,7 @@ static void avdtp_sep_set_state(struct avdtp *session, if (session->pending_open == stream) handle_transport_connect(session, NULL, 0, 0); if (session->req && session->req->stream == stream) - session->req->stream = NULL; + handle_unanswered_req(session, stream); /* Remove pending commands for this stream from the queue */ cleanup_queue(session, stream); stream_free(stream); -- 1.6.0.4