Hi Iulia, On Tue, Feb 25, 2025 at 3:44 AM Iulia Tanasescu <iulia.tanasescu@xxxxxxx> wrote: > > This adds support for registering BIS probe/remove calllbacks with > shared/bap. This is needed by the BAP Broadcast Assistant (BASS Client) > implementation, so that the BAP plugin can notify BISes discovered > after parsing the BASE to BASS, avoiding direct function calls > between plugins. > --- > src/shared/bap.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ > src/shared/bap.h | 12 +++++- > 2 files changed, 108 insertions(+), 1 deletion(-) > > diff --git a/src/shared/bap.c b/src/shared/bap.c > index 6ffeefa41..76df7f4e4 100644 > --- a/src/shared/bap.c > +++ b/src/shared/bap.c > @@ -80,6 +80,14 @@ struct bt_bap_state { > void *data; > }; > > +struct bt_bap_bis_cb { > + unsigned int id; > + bt_bap_bis_func_t probe; > + bt_bap_func_t remove; > + bt_bap_destroy_func_t destroy; > + void *data; > +}; > + > struct bt_bap_cb { > unsigned int id; > bt_bap_func_t attached; > @@ -180,6 +188,7 @@ struct bt_bap { > struct queue *pac_cbs; > struct queue *ready_cbs; > struct queue *state_cbs; > + struct queue *bis_cbs; > > bt_bap_debug_func_t debug_func; > bt_bap_destroy_func_t debug_destroy; > @@ -4190,6 +4199,16 @@ static void bap_state_free(void *data) > free(state); > } > > +static void bap_bis_cb_free(void *data) > +{ > + struct bt_bap_bis_cb *bis_cb = data; > + > + if (bis_cb->destroy) > + bis_cb->destroy(bis_cb->data); > + > + free(bis_cb); > +} > + > static void bap_ep_free(void *data) > { > struct bt_bap_endpoint *ep = data; > @@ -4228,6 +4247,7 @@ static void bap_free(void *data) > queue_destroy(bap->pac_cbs, pac_changed_free); > queue_destroy(bap->ready_cbs, bap_ready_free); > queue_destroy(bap->state_cbs, bap_state_free); > + queue_destroy(bap->bis_cbs, bap_bis_cb_free); > queue_destroy(bap->local_eps, free); > queue_destroy(bap->remote_eps, bap_ep_free); > > @@ -4310,6 +4330,7 @@ struct bt_bap *bt_bap_new(struct gatt_db *ldb, struct gatt_db *rdb) > bap->ready_cbs = queue_new(); > bap->streams = queue_new(); > bap->state_cbs = queue_new(); > + bap->bis_cbs = queue_new(); > bap->local_eps = queue_new(); > > if (!rdb) > @@ -5519,6 +5540,82 @@ bool bt_bap_state_unregister(struct bt_bap *bap, unsigned int id) > return false; > } > > +unsigned int bt_bap_bis_cb_register(struct bt_bap *bap, > + bt_bap_bis_func_t probe, > + bt_bap_func_t remove, > + void *user_data, > + bt_bap_destroy_func_t destroy) > +{ > + struct bt_bap_bis_cb *bis_cb; > + static unsigned int id; > + > + if (!bap) > + return 0; > + > + bis_cb = new0(struct bt_bap_bis_cb, 1); > + bis_cb->id = ++id ? id : ++id; > + bis_cb->probe = probe; > + bis_cb->remove = remove; > + bis_cb->destroy = destroy; > + bis_cb->data = user_data; > + > + queue_push_tail(bap->bis_cbs, bis_cb); > + > + return bis_cb->id; > +} > + > +static bool match_bis_cb_id(const void *data, const void *match_data) > +{ > + const struct bt_bap_bis_cb *bis_cb = data; > + unsigned int id = PTR_TO_UINT(match_data); > + > + return (bis_cb->id == id); > +} > + > +bool bt_bap_bis_cb_unregister(struct bt_bap *bap, unsigned int id) > +{ > + struct bt_bap_bis_cb *bis_cb; > + > + if (!bap) > + return false; > + > + bis_cb = queue_remove_if(bap->bis_cbs, match_bis_cb_id, > + UINT_TO_PTR(id)); > + if (!bis_cb) > + return false; > + > + bap_bis_cb_free(bis_cb); > + > + return false; > +} > + > +void bt_bap_bis_probe(struct bt_bap *bap, uint8_t bis, uint8_t sgrp, > + struct iovec *caps, struct iovec *meta, struct bt_bap_qos *qos) > +{ > + const struct queue_entry *entry; > + > + for (entry = queue_get_entries(bap->bis_cbs); entry; > + entry = entry->next) { > + struct bt_bap_bis_cb *cb = entry->data; > + > + if (cb->probe) > + cb->probe(bis, sgrp, caps, meta, qos, cb->data); It is probably a good idea to take a reference before the for loop to prevent bap instance from being destroyed by the callbacks if they drop the reference to 0, also you may need to move the entry = entry->next before the calling the cb since it may also call unregister. > + } > +} > + > +void bt_bap_bis_remove(struct bt_bap *bap) > +{ > + const struct queue_entry *entry; > + > + for (entry = queue_get_entries(bap->bis_cbs); entry; > + entry = entry->next) { > + struct bt_bap_bis_cb *cb = entry->data; > + > + if (cb->remove) > + cb->remove(bap, cb->data); > + } > +} > + > const char *bt_bap_stream_statestr(uint8_t state) > { > switch (state) { > diff --git a/src/shared/bap.h b/src/shared/bap.h > index 200dc8f13..adb531b4c 100644 > --- a/src/shared/bap.h > +++ b/src/shared/bap.h > @@ -4,7 +4,7 @@ > * BlueZ - Bluetooth protocol stack for Linux > * > * Copyright (C) 2022 Intel Corporation. All rights reserved. > - * Copyright 2023-2024 NXP > + * Copyright 2023-2025 NXP > * > */ > > @@ -269,3 +269,13 @@ bool bt_bap_parse_base(struct iovec *base, > bt_bap_bis_func_t handler, > void *user_data); > > +unsigned int bt_bap_bis_cb_register(struct bt_bap *bap, > + bt_bap_bis_func_t probe, > + bt_bap_func_t remove, > + void *user_data, > + bt_bap_destroy_func_t destroy); > +bool bt_bap_bis_cb_unregister(struct bt_bap *bap, unsigned int id); > + > +void bt_bap_bis_probe(struct bt_bap *bap, uint8_t bis, uint8_t sgrp, > + struct iovec *caps, struct iovec *meta, struct bt_bap_qos *qos); > +void bt_bap_bis_remove(struct bt_bap *bap); > -- > 2.43.0 > -- Luiz Augusto von Dentz