diff mbox series

[BlueZ,2/3] vcp: fix memory & connection management

Message ID 20250110145019.2380299-3-michal.dzik@streamunlimited.com (mailing list archive)
State New
Headers show
Series connect VCP profile to MediaTransport volume | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success

Commit Message

Michal Dzik Jan. 10, 2025, 2:50 p.m. UTC
Those changes are mandatory to be able to connect to the same VCP
renderer more than once without need to restart bluez.
- use vcp_disconnect() to close client connection and reset vcs members
- call bt_vcp_detach() the same way as bt_vcp_attach - from btd_profile
  callback
- vcs members are cleared during disconnect, because they are expected
  to be null when connecting
---
 profiles/audio/vcp.c |  9 +++++++++
 src/shared/vcp.c     | 23 +++++++++++++++++++----
 2 files changed, 28 insertions(+), 4 deletions(-)

Comments

Luiz Augusto von Dentz Jan. 10, 2025, 3:16 p.m. UTC | #1
Hi Michal,

On Fri, Jan 10, 2025 at 9:54 AM Michal Dzik
<michal.dzik@streamunlimited.com> wrote:
>
> Those changes are mandatory to be able to connect to the same VCP
> renderer more than once without need to restart bluez.
> - use vcp_disconnect() to close client connection and reset vcs members
> - call bt_vcp_detach() the same way as bt_vcp_attach - from btd_profile
>   callback
> - vcs members are cleared during disconnect, because they are expected
>   to be null when connecting
> ---
>  profiles/audio/vcp.c |  9 +++++++++
>  src/shared/vcp.c     | 23 +++++++++++++++++++----
>  2 files changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/profiles/audio/vcp.c b/profiles/audio/vcp.c
> index 83e568f22..0203673bf 100644
> --- a/profiles/audio/vcp.c
> +++ b/profiles/audio/vcp.c
> @@ -72,7 +72,16 @@ static void vcp_debug(const char *str, void *user_data)
>
>  static int vcp_disconnect(struct btd_service *service)
>  {
> +       struct vcp_data *data = btd_service_get_user_data(service);
>         DBG("");
> +
> +       if (!data) {
> +               error("VCP service not handled by profile");
> +               return -EINVAL;
> +       }
> +       bt_vcp_detach(data->vcp);
> +
> +       btd_service_disconnecting_complete(service, 0);
>         return 0;
>  }
>
> diff --git a/src/shared/vcp.c b/src/shared/vcp.c
> index 489cd2b97..c92eb00d4 100644
> --- a/src/shared/vcp.c
> +++ b/src/shared/vcp.c
> @@ -389,13 +389,24 @@ static void vcp_detached(void *data, void *user_data)
>
>  void bt_vcp_detach(struct bt_vcp *vcp)
>  {
> +       struct bt_vcs *vcs;
>         if (!queue_remove(sessions, vcp))
>                 return;
>
> -       bt_gatt_client_unref(vcp->client);
> -       vcp->client = NULL;
> +       if (vcp->client) {
> +               bt_gatt_client_unref(vcp->client);
> +               vcp->client = NULL;
> +       }
>
> -       queue_foreach(vcp_cbs, vcp_detached, vcp);
> +       if (vcp->rdb) {
> +               vcs = vcp_get_vcs(vcp);
> +               vcs->service = NULL;
> +               vcs->vs = NULL;
> +               vcs->vs_ccc = NULL;
> +               vcs->vol_cp = NULL;
> +               vcs->vf = NULL;
> +               vcs->vf_ccc = NULL;

You shouldn't need to clean up the found attributes, these are stored
in the gatt_db and are persisted on reconnection.

> +       }
>  }
>
>  static void vcp_db_free(void *data)
> @@ -489,6 +500,7 @@ static void vcp_debug(struct bt_vcp *vcp, const char *format, ...)
>
>  static void vcp_disconnected(int err, void *user_data)
>  {
> +       // called only when this device is acting a a server

Use C style comments (/*) rather than C++.

>         struct bt_vcp *vcp = user_data;
>
>         DBG(vcp, "vcp %p disconnected err %d", vcp, err);
> @@ -508,12 +520,15 @@ static struct bt_vcp *vcp_get_session(struct bt_att *att, struct gatt_db *db)
>                         return vcp;
>         }
>
> +       // called only when this device is acting a a server
>         vcp = bt_vcp_new(db, NULL);
>         vcp->att = att;
>
>         bt_att_register_disconnect(att, vcp_disconnected, vcp, NULL);
>
> -       bt_vcp_attach(vcp, NULL);
> +       if (!sessions)
> +               sessions = queue_new();
> +       queue_push_tail(sessions, vcp);
>
>         return vcp;
>
> --
> 2.34.1
>
>
diff mbox series

Patch

diff --git a/profiles/audio/vcp.c b/profiles/audio/vcp.c
index 83e568f22..0203673bf 100644
--- a/profiles/audio/vcp.c
+++ b/profiles/audio/vcp.c
@@ -72,7 +72,16 @@  static void vcp_debug(const char *str, void *user_data)
 
 static int vcp_disconnect(struct btd_service *service)
 {
+	struct vcp_data *data = btd_service_get_user_data(service);
 	DBG("");
+
+	if (!data) {
+		error("VCP service not handled by profile");
+		return -EINVAL;
+	}
+	bt_vcp_detach(data->vcp);
+
+	btd_service_disconnecting_complete(service, 0);
 	return 0;
 }
 
diff --git a/src/shared/vcp.c b/src/shared/vcp.c
index 489cd2b97..c92eb00d4 100644
--- a/src/shared/vcp.c
+++ b/src/shared/vcp.c
@@ -389,13 +389,24 @@  static void vcp_detached(void *data, void *user_data)
 
 void bt_vcp_detach(struct bt_vcp *vcp)
 {
+	struct bt_vcs *vcs;
 	if (!queue_remove(sessions, vcp))
 		return;
 
-	bt_gatt_client_unref(vcp->client);
-	vcp->client = NULL;
+	if (vcp->client) {
+		bt_gatt_client_unref(vcp->client);
+		vcp->client = NULL;
+	}
 
-	queue_foreach(vcp_cbs, vcp_detached, vcp);
+	if (vcp->rdb) {
+		vcs = vcp_get_vcs(vcp);
+		vcs->service = NULL;
+		vcs->vs = NULL;
+		vcs->vs_ccc = NULL;
+		vcs->vol_cp = NULL;
+		vcs->vf = NULL;
+		vcs->vf_ccc = NULL;
+	}
 }
 
 static void vcp_db_free(void *data)
@@ -489,6 +500,7 @@  static void vcp_debug(struct bt_vcp *vcp, const char *format, ...)
 
 static void vcp_disconnected(int err, void *user_data)
 {
+	// called only when this device is acting a a server
 	struct bt_vcp *vcp = user_data;
 
 	DBG(vcp, "vcp %p disconnected err %d", vcp, err);
@@ -508,12 +520,15 @@  static struct bt_vcp *vcp_get_session(struct bt_att *att, struct gatt_db *db)
 			return vcp;
 	}
 
+	// called only when this device is acting a a server
 	vcp = bt_vcp_new(db, NULL);
 	vcp->att = att;
 
 	bt_att_register_disconnect(att, vcp_disconnected, vcp, NULL);
 
-	bt_vcp_attach(vcp, NULL);
+	if (!sessions)
+		sessions = queue_new();
+	queue_push_tail(sessions, vcp);
 
 	return vcp;