[PATCH] Handle unanswered AVDTP request on disconnect

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux