diff mbox series

[BlueZ] a2dp: Handle remote SEP disappearing

Message ID 20210121010955.1193543-1-luiz.dentz@gmail.com (mailing list archive)
State Accepted
Delegated to: Luiz Von Dentz
Headers show
Series [BlueZ] a2dp: Handle remote SEP disappearing | expand

Commit Message

Luiz Augusto von Dentz Jan. 21, 2021, 1:09 a.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Some devices (Sony WH-1000XM4) seems to dinamically change its endpoints
depending on the configuration which may leave behind endpoints loaded
from cache that are no longer valid.

gh-issue: https://github.com/bluez/bluez/issues/85
---
 profiles/audio/a2dp.c  | 12 +++++++++
 profiles/audio/avdtp.c | 55 +++++++++++++++++++++++++++++++++++-------
 profiles/audio/avdtp.h |  5 ++++
 3 files changed, 63 insertions(+), 9 deletions(-)

Comments

bluez.test.bot@gmail.com Jan. 21, 2021, 1:59 a.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=418663

---Test result---

##############################
Test: CheckPatch - PASS

##############################
Test: CheckGitLint - PASS

##############################
Test: CheckBuild - PASS

##############################
Test: MakeCheck - PASS



---
Regards,
Linux Bluetooth
Luiz Augusto von Dentz Jan. 22, 2021, 10:01 p.m. UTC | #2
Hi,

On Wed, Jan 20, 2021 at 5:59 PM <bluez.test.bot@gmail.com> wrote:
>
> This is automated email and please do not reply to this email!
>
> Dear submitter,
>
> Thank you for submitting the patches to the linux bluetooth mailing list.
> This is a CI test results with your patch series:
> PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=418663
>
> ---Test result---
>
> ##############################
> Test: CheckPatch - PASS
>
> ##############################
> Test: CheckGitLint - PASS
>
> ##############################
> Test: CheckBuild - PASS
>
> ##############################
> Test: MakeCheck - PASS
>
>
>
> ---
> Regards,
> Linux Bluetooth

Pushed.
diff mbox series

Patch

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index a333276e0..624d0d42d 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1488,6 +1488,8 @@  static void remote_sep_free(void *data)
 {
 	struct a2dp_remote_sep *sep = data;
 
+	avdtp_remote_sep_set_destroy(sep->sep, NULL, NULL);
+
 	free(sep->path);
 	free(sep);
 }
@@ -1874,6 +1876,14 @@  static const GDBusPropertyTable sep_properties[] = {
 	{ }
 };
 
+static void remote_sep_destroy(void *user_data)
+{
+	struct a2dp_remote_sep *sep = user_data;
+
+	if (queue_remove(sep->chan->seps, sep))
+		remove_remote_sep(sep);
+}
+
 static void register_remote_sep(void *data, void *user_data)
 {
 	struct avdtp_remote_sep *rsep = data;
@@ -1910,6 +1920,8 @@  static void register_remote_sep(void *data, void *user_data)
 
 	DBG("Found remote SEP: %s", sep->path);
 
+	avdtp_remote_sep_set_destroy(rsep, sep, remote_sep_destroy);
+
 done:
 	queue_push_tail(chan->seps, sep);
 }
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 1093a3543..b8ef5f682 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -308,8 +308,11 @@  struct avdtp_remote_sep {
 	uint8_t media_type;
 	struct avdtp_service_capability *codec;
 	gboolean delay_reporting;
+	bool discovered;
 	GSList *caps; /* of type struct avdtp_service_capability */
 	struct avdtp_stream *stream;
+	avdtp_remote_sep_destroy_t destroy;
+	void *user_data;
 };
 
 struct avdtp_local_sep {
@@ -1038,6 +1041,32 @@  static void avdtp_sep_set_state(struct avdtp *session,
 		stream_free(stream);
 }
 
+static void sep_free(gpointer data)
+{
+	struct avdtp_remote_sep *sep = data;
+
+	if (sep->destroy)
+		sep->destroy(sep->user_data);
+
+	g_slist_free_full(sep->caps, g_free);
+	g_free(sep);
+}
+
+static void remove_disappeared(void *data, void *user_data)
+{
+	struct avdtp_remote_sep *sep = data;
+	struct avdtp *session = user_data;
+
+	if (sep->discovered)
+		return;
+
+	DBG("seid %d disappeared", sep->seid);
+
+	session->seps = g_slist_remove(session->seps, sep);
+
+	sep_free(sep);
+}
+
 static void finalize_discovery(struct avdtp *session, int err)
 {
 	struct discover_callback *discover = session->discover;
@@ -1051,6 +1080,9 @@  static void finalize_discovery(struct avdtp *session, int err)
 	if (discover->id > 0)
 		g_source_remove(discover->id);
 
+	if (!err)
+		g_slist_foreach(session->seps, remove_disappeared, session);
+
 	if (discover->cb)
 		discover->cb(session, session->seps, err ? &avdtp_err : NULL,
 							discover->user_data);
@@ -1070,14 +1102,6 @@  static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
 	avdtp_sep_set_state(session, sep, AVDTP_STATE_IDLE);
 }
 
-static void sep_free(gpointer data)
-{
-	struct avdtp_remote_sep *sep = data;
-
-	g_slist_free_full(sep->caps, g_free);
-	g_free(sep);
-}
-
 static void remove_disconnect_timer(struct avdtp *session)
 {
 	if (!session->dc_timer)
@@ -2707,8 +2731,10 @@  static gboolean avdtp_discover_resp(struct avdtp *session,
 		sep = find_remote_sep(session->seps, resp->seps[i].seid);
 		if (sep && sep->type == resp->seps[i].type &&
 				sep->media_type == resp->seps[i].media_type &&
-				sep->codec)
+				sep->codec) {
+			sep->discovered = true;
 			continue;
+		}
 
 		if (resp->seps[i].inuse && !stream)
 			continue;
@@ -2720,6 +2746,7 @@  static gboolean avdtp_discover_resp(struct avdtp *session,
 		sep->seid = resp->seps[i].seid;
 		sep->type = resp->seps[i].type;
 		sep->media_type = resp->seps[i].media_type;
+		sep->discovered = true;
 
 		memset(&req, 0, sizeof(req));
 		req.acp_seid = sep->seid;
@@ -3325,6 +3352,16 @@  struct avdtp_remote_sep *avdtp_register_remote_sep(struct avdtp *session,
 	return sep;
 }
 
+void avdtp_remote_sep_set_destroy(struct avdtp_remote_sep *sep, void *user_data,
+					avdtp_remote_sep_destroy_t destroy)
+{
+	if (!sep)
+		return;
+
+	sep->user_data = user_data;
+	sep->destroy = destroy;
+}
+
 static gboolean process_discover(gpointer data)
 {
 	struct avdtp *session = data;
diff --git a/profiles/audio/avdtp.h b/profiles/audio/avdtp.h
index 7a1c109c2..b29d0621a 100644
--- a/profiles/audio/avdtp.h
+++ b/profiles/audio/avdtp.h
@@ -216,6 +216,11 @@  struct avdtp_remote_sep *avdtp_register_remote_sep(struct avdtp *session,
 							GSList *caps,
 							bool delay_reporting);
 
+typedef void (*avdtp_remote_sep_destroy_t)(void *user_data);
+
+void avdtp_remote_sep_set_destroy(struct avdtp_remote_sep *sep, void *user_data,
+					avdtp_remote_sep_destroy_t destroy);
+
 uint8_t avdtp_get_seid(struct avdtp_remote_sep *sep);
 
 uint8_t avdtp_get_type(struct avdtp_remote_sep *sep);