mbox series

[BlueZ,0/5] Create transports for matching BISes

Message ID 20240419180752.96699-1-andrei.istodorescu@nxp.com
Headers show
Series Create transports for matching BISes | expand

Message

Andrei Istodorescu April 19, 2024, 6:07 p.m. UTC
This patch refactors the flow for the BAP Broadcast Sink.
After observing the BASE information, streams and transports will be
generated for each BIS that matches local PAC capabilities.
Because endpoints are not available any more, local PAC (which contain
local registered capabilities) has a new list of setups. Each setup is 
generated based on the matching BIS observed.
Then, the setup is used to configure a stream which then generates a
MediaTransport.
The transport is in the TRANSPORT_STATE_IDLE state until someone
acquires it. The "Acquire" procedure results in creating the IO using
BIG Create Sync. The successful reply of it causes the transport to be
advanced in TRANSPORT_STATE_ACTIVE state.

bluetoothctl log with two transports being created and acquired:
endpoint.register 00001851-0000-1000-8000-00805f9b34fb 0x06
[/local/endpoint/ep0] Auto Accept (yes/no): y
[/local/endpoint/ep0] Max Transports (auto/value): a
[/local/endpoint/ep0] Locations: 3
[/local/endpoint/ep0] Supported Context (value): 3
Capabilities:
  03 01 ff 00 02 02 03 02 03 03 05 04 1a 00 f0 00  ................
Metadata:
[bluetooth]# Endpoint /local/endpoint/ep0 registered

scan le

[bluetooth]# SetDiscoveryFilter success
[bluetooth]# hci7 type 6 discovering on
[bluetooth]# Discovery started
[bluetooth]# [CHG] Controller 00:60:37:A6:AE:22 Discovering: yes
[bluetooth]# [NEW] Device 07:34:BB:4B:6F:C3 07-34-BB-4B-6F-C3
[bluetooth]# hci7 07:34:BB:4B:6F:C3 type LE Random connected eir_len 0
[bluetooth]# [NEW] Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis1/
fd0 
[bluetooth]# Endpoint: SetConfiguration
[bluetooth]# 	Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis1/fd0
[bluetooth]# 	Properties.Device: /org/bluez/hci7/dev_07_34_BB_4B_6F_C3
[bluetooth]# Auto Accepting...
[bluetooth]# [NEW] Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis2/
fd1 
[bluetooth]# Endpoint: SetConfiguration
[bluetooth]# 	Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis2/fd1
[bluetooth]# 	Properties.Device: /org/bluez/hci7/dev_07_34_BB_4B_6F_C3
[bluetooth]# Auto Accepting...
[CHG] Device 07:34:BB:4B:6F:C3 Connected: yes

[07-34-BB-4B-6F-C3]# transport.acquire /org/bluez/hci7/
dev_07_34_BB_4B_6F_C3/bis1/fd0 
auto acquiring...
Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis1/fd0 acquiring
[07-34-BB-4B-6F-C3]# hci7 07:34:BB:4B:6F:C3 type LE Random connected 
eir_len 0
[07-34-BB-4B-6F-C3]# hci7 07:34:BB:4B:6F:C3 type LE Random connected 
eir_len 0
[07-34-BB-4B-6F-C3]# Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/
bis1/fd0 acquiring complete
[07-34-BB-4B-6F-C3]# Acquire successful: fd 8 MTU 40:0
[07-34-BB-4B-6F-C3]# [CHG] Transport /org/bluez/hci7/
dev_07_34_BB_4B_6F_C3/bis1/fd0 State: active
hci7 type 6 discovering offm[seq 0] recv: 0 bytes #            1
hci7 type 6 discovering on9m[seq 146] recv: 0 bytes #              7
hci7 type 6 discovering offm[seq 149] recv: 0 bytes #             50
hci7 type 6 discovering on
[seq 2446] recv: 0 bytes #transport.release /org/bluez/hci7/
dev_07_34_BB_4B_6F_C3/bis1/fd0 
[07-34-BB-4B-6F-C3]# [CHG] Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3
/bis1/fd0 State: idle
[07-34-BB-4B-6F-C3]# Release successful

[07-34-BB-4B-6F-C3]# transport.acquire /org/bluez/hci7/
dev_07_34_BB_4B_6F_C3/bis2/fd1 
auto acquiring...
Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis2/fd1 acquiring
[07-34-BB-4B-6F-C3]# hci7 07:34:BB:4B:6F:C3 type LE Random connected 
eir_len 0
[07-34-BB-4B-6F-C3]# hci7 07:34:BB:4B:6F:C3 type LE Random connected 
eir_len 0
[07-34-BB-4B-6F-C3]# Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3/bis2
/fd1 acquiring complete
[07-34-BB-4B-6F-C3]# Acquire successful: fd 9 MTU 40:0
[07-34-BB-4B-6F-C3]# [CHG] Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3
/bis2/fd1 State: active
hci7 type 6 discovering off
hci7 type 6 discovering on
[seq 1330] recv: 0 bytes #transport.release /org/bluez/hci7/
dev_07_34_BB_4B_6F_C3/bis2/fd1 
[07-34-BB-4B-6F-C3]#   1;39m[seq 1331] recv: 0 bytes #Transport fd
disconnected
[07-34-BB-4B-6F-C3]# [CHG] Transport /org/bluez/hci7/dev_07_34_BB_4B_6F_C3
/bis2/fd1 State: idle
[07-34-BB-4B-6F-C3]# Release successful

Andrei Istodorescu (5):
  shared/bap: Allow NULL bap endpoint in streams
  shared/bap: Get broadcast channel location from stream capabilities
  shared/bap: Update stream management to avoid PACs
  shared/bap: In case of a BIS-PAC match return also the local pac
  bap: Create streams and transports for each matching BIS

 profiles/audio/bap.c | 184 ++++++++++++++++++++--------
 src/shared/bap.c     | 280 +++++++++++++++++++++----------------------
 src/shared/bap.h     |   6 +-
 3 files changed, 279 insertions(+), 191 deletions(-)

Comments

Luiz Augusto von Dentz April 19, 2024, 7:28 p.m. UTC | #1
Hi Andrei,

On Fri, Apr 19, 2024 at 2:08 PM Andrei Istodorescu
<andrei.istodorescu@nxp.com> wrote:
>
> Rename bt_bap_add_bis to bt_bap_check_bis as its scope has changed.

The scope being changed doesn't mean we need to change its name,
except if you add an explanation on why check is a better term than
add here, or perhaps we want to add something like
bt_bap_stream_new_bis? Which shall return the bt_bap_stream already
configured from BIS.

> Use the BIS index received in the BASE to synchronize to the BIG.
> Allow bt_bap_endpoint to be NULL.
> Remove the Broadcast Sink code from set_configuration.
> Update BASE parsing so that it creates streams and transports, without a
> remote PAC and endpoint.
> Update bap_find_setup_by_stream to find the setup in case the stream does
> not contain an endpoint.
> Update BAP Broadcast Sink state machine:
> * BIS matched over the air -> create stream and transport and set the
>   stream state to BT_BAP_STREAM_STATE_CONFIG
> * transport acquire sets stream state to BT_BAP_STREAM_STATE_ENABLING
>   and do BIG Create Sync

If we were to follow the BAP spec to the letter then there is no
Enabling state, nor Enable procedure:

https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/16212-BAP-html5/out/en/index-en.html#UUID-4a295bf2-6e50-be11-e827-c23e63569087_figure-idm4631863059107233170457600297

Broadcast streams can only be on Idle, Configured or Streaming states,
so I suggest we follow that as closely as possible.

> * BIG Sync Established received sets stream state to
>   BT_BAP_STREAM_STATE_STREAMING
> ---
>  profiles/audio/bap.c | 184 +++++++++++++++++++++++++++++----------
>  src/shared/bap.c     | 199 ++++++++++++++++++++++---------------------
>  src/shared/bap.h     |   6 +-
>  3 files changed, 244 insertions(+), 145 deletions(-)
>
> diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
> index ff6d6d881346..b59ef405ab74 100644
> --- a/profiles/audio/bap.c
> +++ b/profiles/audio/bap.c
> @@ -109,6 +109,7 @@ struct bap_data {
>         struct queue *srcs;
>         struct queue *snks;
>         struct queue *bcast;
> +       struct queue *bcast_snks;
>         struct queue *streams;
>         GIOChannel *listen_io;
>         int selecting;
> @@ -125,7 +126,10 @@ struct bap_bcast_pa_req {
>         bool in_progress;
>         union {
>                 struct btd_service *service;
> -               struct bap_setup *setup;
> +               struct bap_accept {
> +                       struct bap_setup *setup;
> +                       struct bap_data *bap_data;
> +               } accept_data;
>         } data;
>  };
>
> @@ -197,6 +201,8 @@ static void ep_unregister(void *data)
>                                                 MEDIA_ENDPOINT_INTERFACE);
>  }
>
> +static void setup_free(void *data);
> +
>  static void bap_data_free(struct bap_data *data)
>  {
>         if (data->listen_io) {
> @@ -213,6 +219,7 @@ static void bap_data_free(struct bap_data *data)
>         queue_destroy(data->srcs, ep_unregister);
>         queue_destroy(data->bcast, ep_unregister);
>         queue_destroy(data->streams, NULL);
> +       queue_destroy(data->bcast_snks, setup_free);
>         bt_bap_ready_unregister(data->bap, data->ready_id);
>         bt_bap_state_unregister(data->bap, data->state_id);
>         bt_bap_pac_unregister(data->bap, data->pac_id);
> @@ -850,7 +857,11 @@ static struct bap_setup *setup_new(struct bap_ep *ep)
>         setup = new0(struct bap_setup, 1);
>         setup->ep = ep;
>
> -       if (queue_find(ep->data->bcast, NULL, ep)) {
> +       /* Broadcast Source has endpoints in bcast list, Broadcast Sink
> +        * does not have endpoints
> +        */
> +       if (((ep != NULL) && queue_find(ep->data->bcast, NULL, ep)) ||
> +                       (ep == NULL)) {
>                 /* Mark BIG and BIS to be auto assigned */
>                 setup->qos.bcast.big = BT_ISO_QOS_BIG_UNSET;
>                 setup->qos.bcast.bis = BT_ISO_QOS_BIS_UNSET;
> @@ -866,12 +877,14 @@ static struct bap_setup *setup_new(struct bap_ep *ep)
>                 setup->qos_parser = setup_parse_ucast_qos;
>         }
>
> -       if (!ep->setups)
> -               ep->setups = queue_new();
> +       if (ep) {
> +               if (!ep->setups)
> +                       ep->setups = queue_new();
>
> -       queue_push_tail(ep->setups, setup);
> +               queue_push_tail(ep->setups, setup);
>
> -       DBG("ep %p setup %p", ep, setup);
> +               DBG("ep %p setup %p", ep, setup);
> +       }
>
>         return setup;
>  }
> @@ -942,17 +955,6 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
>                 return btd_error_invalid_args(msg);
>         }
>
> -       /* For BAP Broadcast Sink, the capabilities and metadata are coming
> -        * from the source's BIS, which are present in the remote PAC
> -        */
> -       if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SINK) {
> -               util_iov_free(setup->caps, 1);
> -               setup->caps = util_iov_dup(bt_bap_pac_get_data(ep->rpac), 1);
> -               util_iov_free(setup->metadata, 1);
> -               setup->metadata = util_iov_dup(
> -                               bt_bap_pac_get_metadata(ep->rpac), 1);
> -       }
> -
>         setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac, ep->rpac,
>                                                 &setup->qos, setup->caps);
>         bt_bap_stream_set_user_data(setup->stream, ep->path);
> @@ -988,20 +990,24 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
>  static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
>  {
>         struct bap_bcast_pa_req *req = user_data;
> -       struct bap_setup *setup = req->data.setup;
> +       struct bap_setup *setup = req->data.accept_data.setup;
>         int fd;
>
>         DBG("BIG Sync completed");
>
>         queue_remove(bcast_pa_requests, req);
>
> +       g_io_channel_unref(setup->io);
> +       g_io_channel_shutdown(setup->io, TRUE, NULL);
> +       setup->io = NULL;
> +
>         /* This device is no longer needed */
> -       btd_service_connecting_complete(setup->ep->data->service, 0);
> +       btd_service_connecting_complete(req->data.accept_data.bap_data->service,
> +                       0);
>
>         fd = g_io_channel_unix_get_fd(io);
>
>         if (bt_bap_stream_set_io(setup->stream, fd)) {
> -               bt_bap_stream_enable(setup->stream, true, NULL, NULL, NULL);
>                 g_io_channel_set_close_on_unref(io, FALSE);
>                 return;
>         }
> @@ -1014,8 +1020,54 @@ static void print_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
>         util_hexdump(' ', v, l, user_data, NULL);
>  }
>
> -static bool parse_base(struct bt_bap *bap, struct bt_iso_base *base,
> -               util_debug_func_t func)
> +static void create_stream_for_bis(struct bap_data *bap_data,
> +               struct bt_bap_pac *lpac, struct bt_iso_qos *qos,
> +               struct iovec *caps, struct iovec *meta, char *path)
> +{
> +       struct bap_setup *setup;
> +
> +       setup = setup_new(NULL);
> +
> +       /* Create BAP QoS structure */
> +       setup->qos.bcast.big = qos->bcast.big;
> +       setup->qos.bcast.bis = qos->bcast.bis;
> +       setup->qos.bcast.sync_factor = qos->bcast.sync_factor;
> +       setup->qos.bcast.packing = qos->bcast.packing;
> +       setup->qos.bcast.framing = qos->bcast.framing;
> +       setup->qos.bcast.encryption = qos->bcast.encryption;
> +       if (setup->qos.bcast.encryption)
> +               util_iov_append(setup->qos.bcast.bcode,
> +                               qos->bcast.bcode,
> +                               sizeof(qos->bcast.bcode));
> +       setup->qos.bcast.options = qos->bcast.options;
> +       setup->qos.bcast.skip = qos->bcast.skip;
> +       setup->qos.bcast.sync_timeout = qos->bcast.sync_timeout;
> +       setup->qos.bcast.sync_cte_type =
> +                       qos->bcast.sync_cte_type;
> +       setup->qos.bcast.mse = qos->bcast.mse;
> +       setup->qos.bcast.timeout = qos->bcast.timeout;
> +       setup->qos.bcast.io_qos.interval =
> +                       qos->bcast.in.interval;
> +       setup->qos.bcast.io_qos.latency = qos->bcast.in.latency;
> +       setup->qos.bcast.io_qos.phy = qos->bcast.in.phy;
> +       setup->qos.bcast.io_qos.rtn = qos->bcast.in.rtn;
> +       setup->qos.bcast.io_qos.sdu = qos->bcast.in.sdu;
> +
> +       queue_push_tail(bap_data->bcast_snks, setup);
> +
> +       /* Create and configure stream */
> +       setup->stream = bt_bap_stream_new(bap_data->bap,
> +                       lpac, NULL, &setup->qos, caps);
> +
> +       bt_bap_stream_set_user_data(setup->stream, path);
> +       bt_bap_stream_config(setup->stream, &setup->qos,
> +                       caps, NULL, NULL);
> +       bt_bap_stream_metadata(setup->stream, meta,
> +                       NULL, NULL);
> +}
> +
> +static bool parse_base(struct bap_data *bap_data, struct bt_iso_base *base,
> +               struct bt_iso_qos *qos, util_debug_func_t func)
>  {
>         struct iovec iov = {
>                 .iov_base = base->base,
> @@ -1087,11 +1139,20 @@ static bool parse_base(struct bt_bap *bap, struct bt_iso_base *base,
>                 for (; num_bis; num_bis--) {
>                         uint8_t bis_index;
>                         struct iovec *l3_caps;
> +                       struct iovec *merged_caps;
> +                       struct bt_bap_pac *matched_lpac;
> +                       char *path;
> +                       int err;
>
>                         if (!util_iov_pull_u8(&iov, &bis_index))
>                                 goto fail;
>
>                         util_debug(func, NULL, "BIS #%d", bis_index);
> +                       err = asprintf(&path, "%s/bis%d",
> +                                       device_get_path(bap_data->device),
> +                                       bis_index);
> +                       if (err < 0)
> +                               continue;
>
>                         /* Read Codec Specific Configuration */
>                         l3_caps = new0(struct iovec, 1);
> @@ -1110,9 +1171,16 @@ static bool parse_base(struct bt_bap *bap, struct bt_iso_base *base,
>                                         l3_caps->iov_len, NULL, print_ltv,
>                                         func);
>
> -                       /* Try to create a PAC using this BIS information */
> -                       bt_bap_add_bis(bap, bis_index, &codec, l2_caps, l3_caps,
> -                                       meta);
> +                       /* Check if this BIS matches any local PAC */
> +                       bt_bap_verify_bis(bap_data->bap, bis_index, &codec,
> +                                       l2_caps, l3_caps, &matched_lpac,
> +                                       &merged_caps);
> +
> +                       if (matched_lpac == NULL || merged_caps == NULL)
> +                               continue;
> +
> +                       create_stream_for_bis(bap_data, matched_lpac, qos,
> +                                       merged_caps, meta, path);
>                 }
>
>         }
> @@ -1155,7 +1223,9 @@ static void iso_pa_sync_confirm_cb(GIOChannel *io, void *user_data)
>         /* Analyze received BASE data and create remote media endpoints for each
>          * BIS matching our capabilities
>          */
> -       parse_base(data->bap, &base, bap_debug);
> +       parse_base(data, &base, &qos, bap_debug);
> +
> +       service_set_connecting(pa_req->data.service);
>  }
>
>  static bool match_data_bap_data(const void *data, const void *match_data)
> @@ -1558,6 +1628,7 @@ static struct bap_setup *bap_find_setup_by_stream(struct bap_data *data,
>                                         struct bt_bap_stream *stream)
>  {
>         struct bap_ep *ep = NULL;
> +       struct queue *queue = NULL;
>
>         switch (bt_bap_stream_get_type(stream)) {
>         case BT_BAP_STREAM_TYPE_UCAST:
> @@ -1572,9 +1643,11 @@ static struct bap_setup *bap_find_setup_by_stream(struct bap_data *data,
>         }
>
>         if (ep)
> -               return queue_find(ep->setups, match_setup_stream, stream);
> +               queue = ep->setups;
> +       else
> +               queue = data->bcast_snks;
>
> -       return NULL;
> +       return queue_find(queue, match_setup_stream, stream);
>  }
>
>  static void iso_connect_bcast_cb(GIOChannel *chan, GError *err,
> @@ -2097,7 +2170,8 @@ static void setup_accept_io_broadcast(struct bap_data *data,
>          */
>         pa_req->type = BAP_PA_BIG_SYNC_REQ;
>         pa_req->in_progress = FALSE;
> -       pa_req->data.setup = setup;
> +       pa_req->data.accept_data.setup = setup;
> +       pa_req->data.accept_data.bap_data = data;
>         queue_push_tail(bcast_pa_requests, pa_req);
>  }
>
> @@ -2157,7 +2231,7 @@ static void setup_create_bcast_io(struct bap_data *data,
>         memcpy(&iso_qos.bcast.out, &setup->qos.bcast.io_qos,
>                                 sizeof(struct bt_iso_io_qos));
>
> -       if (bt_bap_pac_get_type(setup->ep->lpac) == BT_BAP_BCAST_SOURCE)
> +       if (bt_bap_stream_get_dir(stream) == BT_BAP_BCAST_SINK)
>                 setup_connect_io_broadcast(data, setup, stream, &iso_qos,
>                         defer);
>         else
> @@ -2399,12 +2473,7 @@ static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
>                 if (!setup || setup->id)
>                         break;
>                 if (bt_bap_stream_io_dir(stream) ==
> -                               BT_BAP_BCAST_SOURCE)
> -                       /* If the stream is attached to a
> -                        * broadcast sink endpoint.
> -                        */
> -                       setup_create_io(data, setup, stream, defer);
> -               else {
> +                               BT_BAP_BCAST_SINK) {
>                         /* If the stream attached to a broadcast
>                          * source endpoint generate the base.
>                          */
> @@ -2455,6 +2524,14 @@ static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
>                         }
>                 }
>                 break;
> +       case BT_BAP_STREAM_STATE_ENABLING:
> +               if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE)
> +                       setup_create_io(data, setup, stream, defer);
> +               break;
> +       case BT_BAP_STREAM_STATE_RELEASING:
> +               if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE)
> +                       setup_io_close(setup, NULL);
> +               break;
>         }
>  }
>
> @@ -2794,6 +2871,7 @@ static int short_lived_pa_sync(struct bap_bcast_pa_req *req)
>                 error("BAP unable to attach");
>                 return -EINVAL;
>         }
> +       data->bcast_snks = queue_new();
>
>         bap_data_add(data);
>
> @@ -2833,29 +2911,41 @@ static void iso_do_big_sync(GIOChannel *io, void *user_data)
>  {
>         GError *err = NULL;
>         struct bap_bcast_pa_req *req = user_data;
> -       struct bap_setup *setup = req->data.setup;
> -       struct bap_data *data = setup->ep->data;
> +       struct bap_setup *setup = req->data.accept_data.setup;
> +       struct bap_data *data = req->data.accept_data.bap_data;
>         struct sockaddr_iso_bc iso_bc_addr;
>         struct bt_iso_qos qos;
> +       char *path;
> +       int bis_index = 1;
> +       char device_name[40] = {0};
> +       int s_err;
>
> -       DBG("PA Sync done, do BIG Sync");
> +       DBG("PA Sync done");
>         g_io_channel_unref(setup->io);
> -       setup->io = NULL;
> -
> +       g_io_channel_shutdown(setup->io, TRUE, NULL);
>         setup->io = io;
>         g_io_channel_ref(setup->io);
>
>         /* TODO
>          * We can only synchronize with a single BIS to a BIG.
>          * In order to have multiple BISes targeting this BIG we need to have
> -        * all the BISes before doing this request. This request is triggered
> -        * by an endpoint "SetConfiguration" command. For multiple BISes
> -        * we need another way to specify which BISes user is requesting
> +        * all the BISes before doing bt_io_bcast_accept.
> +        * This request comes from a transport "Acquire" call.
> +        * For multiple BISes in the same BIG we need to either wait for all
> +        * transports in the same BIG to be acquired or tell when to do the
> +        * bt_io_bcast_accept by other means
>          */
> +       path = bt_bap_stream_get_user_data(setup->stream);
> +       s_err = sscanf(path, "%s/bis%d", device_name, &bis_index);
> +       if (s_err == -1)
> +               DBG("sscanf error");
> +
> +       DBG("Do BIG Sync with BIS %d", bis_index);
> +
>         iso_bc_addr.bc_bdaddr_type = btd_device_get_bdaddr_type(data->device);
>         memcpy(&iso_bc_addr.bc_bdaddr, device_get_address(data->device),
>                         sizeof(bdaddr_t));
> -       iso_bc_addr.bc_bis[0] = 1;
> +       iso_bc_addr.bc_bis[0] = bis_index;
>         iso_bc_addr.bc_num_bis = 1;
>
>         /* Set the user requested QOS */
> @@ -2898,8 +2988,8 @@ static void iso_do_big_sync(GIOChannel *io, void *user_data)
>  static void pa_and_big_sync(struct bap_bcast_pa_req *req)
>  {
>         GError *err = NULL;
> -       struct bap_setup *setup = req->data.setup;
> -       struct bap_data *data = setup->ep->data;
> +       struct bap_setup *setup = req->data.accept_data.setup;
> +       struct bap_data *data = req->data.accept_data.bap_data;
>
>         req->in_progress = TRUE;
>
> diff --git a/src/shared/bap.c b/src/shared/bap.c
> index 8c4868f4bf9f..e69f6cec99bf 100644
> --- a/src/shared/bap.c
> +++ b/src/shared/bap.c
> @@ -226,6 +226,7 @@ struct bt_bap_stream_io {
>  struct bt_bap_stream_ops {
>         uint8_t type;
>         void (*set_state)(struct bt_bap_stream *stream, uint8_t state);
> +       unsigned int (*get_state)(struct bt_bap_stream *stream);
>         unsigned int (*config)(struct bt_bap_stream *stream,
>                                 struct bt_bap_qos *qos, struct iovec *data,
>                                 bt_bap_stream_func_t func, void *user_data);
> @@ -245,6 +246,8 @@ struct bt_bap_stream_ops {
>         unsigned int (*metadata)(struct bt_bap_stream *stream,
>                                 struct iovec *data, bt_bap_stream_func_t func,
>                                 void *user_data);
> +       unsigned int (*get_dir)(struct bt_bap_stream *stream);
> +       unsigned int (*get_loc)(struct bt_bap_stream *stream);
>         unsigned int (*release)(struct bt_bap_stream *stream,
>                                 bt_bap_stream_func_t func, void *user_data);
>  };
> @@ -1578,6 +1581,11 @@ done:
>         bap_stream_state_changed(stream);
>  }
>
> +static unsigned int bap_ucast_get_state(struct bt_bap_stream *stream)
> +{
> +       return stream->ep->state;
> +}
> +
>  static unsigned int bap_ucast_config(struct bt_bap_stream *stream,
>                                         struct bt_bap_qos *qos,
>                                         struct iovec *data,
> @@ -1923,6 +1931,27 @@ static bool bap_stream_valid(struct bt_bap_stream *stream)
>         return queue_find(stream->bap->streams, NULL, stream);
>  }
>
> +static unsigned int bap_ucast_get_dir(struct bt_bap_stream *stream)
> +{
> +       return stream->ep->dir;
> +}
> +
> +static unsigned int bap_ucast_get_location(struct bt_bap_stream *stream)
> +{
> +       struct bt_pacs *pacs;
> +
> +       if (!stream)
> +               return 0x00000000;
> +
> +       pacs = stream->client ? stream->bap->rdb->pacs : stream->bap->ldb->pacs;
> +
> +       if (stream->ep->dir == BT_BAP_SOURCE)
> +               return pacs->source_loc_value;
> +       else if (stream->ep->dir == BT_BAP_SINK)
> +               return pacs->sink_loc_value;
> +       return 0x00000000;
> +}
> +
>  static unsigned int bap_ucast_release(struct bt_bap_stream *stream,
>                                         bt_bap_stream_func_t func,
>                                         void *user_data)
> @@ -2000,6 +2029,11 @@ static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
>         }
>  }
>
> +static unsigned int bap_bcast_get_state(struct bt_bap_stream *stream)
> +{
> +       return stream->state;
> +}
> +
>  static unsigned int bap_bcast_enable(struct bt_bap_stream *stream,
>                                         bool enable_links, struct iovec *data,
>                                         bt_bap_stream_func_t func,
> @@ -2043,6 +2077,41 @@ static unsigned int bap_bcast_metadata(struct bt_bap_stream *stream,
>         return 1;
>  }
>
> +static unsigned int bap_bcast_get_dir(struct bt_bap_stream *stream)
> +{
> +       if (bt_bap_pac_get_type(stream->lpac) == BT_BAP_BCAST_SINK)
> +               return BT_BAP_BCAST_SOURCE;
> +       else
> +               return BT_BAP_BCAST_SINK;
> +}
> +
> +static void bap_sink_get_allocation(size_t i, uint8_t l, uint8_t t,
> +               uint8_t *v, void *user_data)
> +{
> +       uint32_t location32;
> +
> +       if (!v)
> +               return;
> +
> +       memcpy(&location32, v, l);
> +       *((uint32_t *)user_data) = le32_to_cpu(location32);
> +}
> +
> +static unsigned int bap_bcast_get_location(struct bt_bap_stream *stream)
> +{
> +       uint8_t type = BAP_CHANNEL_ALLOCATION_LTV_TYPE;
> +       uint32_t allocation = 0;
> +       struct iovec *caps;
> +
> +       caps = bt_bap_stream_get_config(stream);
> +
> +       /* Get stream allocation from capabilities */
> +       util_ltv_foreach(caps->iov_base, caps->iov_len, &type,
> +                       bap_sink_get_allocation, &allocation);
> +
> +       return allocation;
> +}
> +
>  static unsigned int bap_bcast_release(struct bt_bap_stream *stream,
>                                         bt_bap_stream_func_t func,
>                                         void *user_data)
> @@ -2052,11 +2121,12 @@ static unsigned int bap_bcast_release(struct bt_bap_stream *stream,
>         return 1;
>  }
>
> -#define STREAM_OPS(_type, _set_state, _config, _qos, _enable, _start, \
> -                       _disable, _stop, _metadata, _release) \
> +#define STREAM_OPS(_type, _set_state, _get_state, _config, _qos, _enable, \
> +       _start, _disable, _stop, _metadata, _get_dir, _get_loc, _release) \
>  { \
>         .type = _type, \
>         .set_state = _set_state, \
> +       .get_state = _get_state, \
>         .config = _config, \
>         .qos = _qos, \
>         .enable = _enable, \
> @@ -2064,26 +2134,40 @@ static unsigned int bap_bcast_release(struct bt_bap_stream *stream,
>         .disable = _disable, \
>         .stop = _stop, \
>         .metadata = _metadata, \
> +       .get_dir = _get_dir,\
> +       .get_loc = _get_loc, \
>         .release = _release, \
>  }
>
>  static const struct bt_bap_stream_ops stream_ops[] = {
>         STREAM_OPS(BT_BAP_SINK, bap_ucast_set_state,
> +                       bap_ucast_get_state,
>                         bap_ucast_config, bap_ucast_qos, bap_ucast_enable,
>                         bap_ucast_start, bap_ucast_disable, bap_ucast_stop,
> -                       bap_ucast_metadata, bap_ucast_release),
> +                       bap_ucast_metadata, bap_ucast_get_dir,
> +                       bap_ucast_get_location,
> +                       bap_ucast_release),
>         STREAM_OPS(BT_BAP_SOURCE, bap_ucast_set_state,
> +                       bap_ucast_get_state,
>                         bap_ucast_config, bap_ucast_qos, bap_ucast_enable,
>                         bap_ucast_start, bap_ucast_disable, bap_ucast_stop,
> -                       bap_ucast_metadata, bap_ucast_release),
> +                       bap_ucast_metadata, bap_ucast_get_dir,
> +                       bap_ucast_get_location,
> +                       bap_ucast_release),
>         STREAM_OPS(BT_BAP_BCAST_SINK, bap_bcast_set_state,
> +                       bap_bcast_get_state,
>                         bap_bcast_config, NULL, bap_bcast_enable,
>                         bap_bcast_start, bap_bcast_disable, NULL,
> -                       bap_bcast_metadata, bap_bcast_release),
> +                       bap_bcast_metadata, bap_bcast_get_dir,
> +                       bap_bcast_get_location,
> +                       bap_bcast_release),
>         STREAM_OPS(BT_BAP_BCAST_SOURCE, bap_bcast_set_state,
> +                       bap_bcast_get_state,
>                         bap_bcast_config, NULL, bap_bcast_enable,
>                         bap_bcast_start, bap_bcast_disable, NULL,
> -                       bap_bcast_metadata, bap_bcast_release),
> +                       bap_bcast_metadata, bap_bcast_get_dir,
> +                       bap_bcast_get_location,
> +                       bap_bcast_release),
>  };
>
>  static const struct bt_bap_stream_ops *
> @@ -5383,11 +5467,7 @@ uint8_t bt_bap_stream_get_state(struct bt_bap_stream *stream)
>         if (!stream)
>                 return BT_BAP_STREAM_STATE_IDLE;
>
> -       if (stream->lpac->type != BT_BAP_BCAST_SOURCE &&
> -                       stream->lpac->type != BT_BAP_BCAST_SINK)
> -               return stream->ep->state;
> -       else
> -               return stream->state;
> +       return stream->ops->get_state(stream);
>  }
>
>  bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
> @@ -5571,53 +5651,15 @@ uint8_t bt_bap_stream_get_dir(struct bt_bap_stream *stream)
>         if (!stream)
>                 return 0x00;
>
> -       if (stream->ep)
> -               return stream->ep->dir;
> -
> -       if (bt_bap_pac_get_type(stream->lpac) == BT_BAP_BCAST_SINK)
> -               return BT_BAP_BCAST_SOURCE;
> -       else
> -               return BT_BAP_BCAST_SINK;
> -}
> -
> -static void bap_sink_get_allocation(size_t i, uint8_t l, uint8_t t,
> -               uint8_t *v, void *user_data)
> -{
> -       uint32_t location32;
> -
> -       if (!v)
> -               return;
> -
> -       memcpy(&location32, v, l);
> -       *((uint32_t *)user_data) = le32_to_cpu(location32);
> +       return stream->ops->get_dir(stream);
>  }
>
>  uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
>  {
> -       struct bt_pacs *pacs;
> -       uint8_t type = BAP_CHANNEL_ALLOCATION_LTV_TYPE;
> -       uint32_t allocation = 0;
> -       struct iovec *caps;
> -
>         if (!stream)
>                 return 0x00000000;
>
> -       pacs = stream->client ? stream->bap->rdb->pacs : stream->bap->ldb->pacs;
> -
> -       if (stream->ep) {
> -               if (stream->ep->dir == BT_BAP_SOURCE)
> -                       return pacs->source_loc_value;
> -               else if (stream->ep->dir == BT_BAP_SINK)
> -                       return pacs->sink_loc_value;
> -       }
> -
> -       caps = bt_bap_stream_get_config(stream);
> -
> -       /* Get stream allocation from capabilities */
> -       util_ltv_foreach(caps->iov_base, caps->iov_len, &type,
> -                       bap_sink_get_allocation, &allocation);
> -
> -       return allocation;
> +       return stream->ops->get_loc(stream);
>  }
>
>  struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
> @@ -6459,17 +6501,13 @@ static struct bt_ltv_match bap_check_bis(struct bt_bap_db *ldb,
>         return compare_data;
>  }
>
> -void bt_bap_add_bis(struct bt_bap *bap, uint8_t bis_index,
> +void bt_bap_verify_bis(struct bt_bap *bap, uint8_t bis_index,
>                 struct bt_bap_codec *codec,
>                 struct iovec *l2_caps,
>                 struct iovec *l3_caps,
> -               struct iovec *meta)
> +               struct bt_bap_pac **lpac,
> +               struct iovec **caps)
>  {
> -       struct bt_bap_pac *pac_source_bis;
> -       struct bt_bap_endpoint *ep;
> -       int err = 0;
> -       struct bt_bap_pac_qos bis_qos = {0};
> -       uint8_t type = 0;
>         struct bt_ltv_extract merge_data = {0};
>         struct bt_ltv_match match_data = {0};
>
> @@ -6488,43 +6526,14 @@ void bt_bap_add_bis(struct bt_bap *bap, uint8_t bis_index,
>          * Specific Capabilities and if the BIS matches create a PAC with it
>          */
>         match_data = bap_check_bis(bap->ldb, merge_data.result);
> -       if (match_data.found == false)
> -               goto cleanup;
> -
> -       DBG(bap, "Matching BIS %i", bis_index);
> -
> -       /* Create a QoS structure based on the received BIS information to
> -        * specify the desired channel for this BIS/PAC
> -        */
> -       type = BAP_CHANNEL_ALLOCATION_LTV_TYPE;
> -       util_ltv_foreach(merge_data.result->iov_base,
> -                       merge_data.result->iov_len, &type,
> -                       bap_sink_get_allocation, &bis_qos.location);
> -
> -       /* Create a remote PAC */
> -       pac_source_bis = bap_pac_new(bap->rdb, NULL,
> -                               BT_BAP_BCAST_SOURCE, codec, &bis_qos,
> -                               merge_data.result, meta);
> -
> -       err = asprintf(&pac_source_bis->name, "%d", bis_index);
> -
> -       if (err < 0) {
> -               DBG(bap, "error in asprintf");
> -               goto cleanup;
> +       if (match_data.found == true) {
> +               *caps = merge_data.result;
> +               *lpac = match_data.data;
> +               DBG(bap, "Matching BIS %i", bis_index);
> +       } else {
> +               util_iov_free(merge_data.result, 1);
> +               *caps = NULL;
> +               *lpac = NULL;
>         }
>
> -       /* Add remote source endpoint */
> -       if (!bap->rdb->broadcast_sources)
> -               bap->rdb->broadcast_sources = queue_new();
> -       queue_push_tail(bap->rdb->broadcast_sources, pac_source_bis);
> -
> -       queue_foreach(bap->pac_cbs, notify_pac_added, pac_source_bis);
> -       /* Push remote endpoint with direction sink */
> -       ep = bap_endpoint_new_broadcast(bap->rdb, BT_BAP_BCAST_SINK);
> -
> -       if (ep)
> -               queue_push_tail(bap->remote_eps, ep);
> -
> -cleanup:
> -       util_iov_free(merge_data.result, 1);
>  }
> diff --git a/src/shared/bap.h b/src/shared/bap.h
> index 62e2104850c7..35524df0b451 100644
> --- a/src/shared/bap.h
> +++ b/src/shared/bap.h
> @@ -251,9 +251,9 @@ bool bt_bap_pac_bcast_is_local(struct bt_bap *bap, struct bt_bap_pac *pac);
>
>  struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream);
>
> -void bt_bap_add_bis(struct bt_bap *bap, uint8_t bis_index,
> +void bt_bap_verify_bis(struct bt_bap *bap, uint8_t bis_index,
>                 struct bt_bap_codec *codec,
>                 struct iovec *l2_caps,
>                 struct iovec *l3_caps,
> -               struct iovec *meta);
> -
> +               struct bt_bap_pac **lpac,
> +               struct iovec **caps);
> --
> 2.40.1
>
patchwork-bot+bluetooth@kernel.org April 23, 2024, 5:40 p.m. UTC | #2
Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Fri, 19 Apr 2024 21:07:47 +0300 you wrote:
> This patch refactors the flow for the BAP Broadcast Sink.
> After observing the BASE information, streams and transports will be
> generated for each BIS that matches local PAC capabilities.
> Because endpoints are not available any more, local PAC (which contain
> local registered capabilities) has a new list of setups. Each setup is
> generated based on the matching BIS observed.
> Then, the setup is used to configure a stream which then generates a
> MediaTransport.
> The transport is in the TRANSPORT_STATE_IDLE state until someone
> acquires it. The "Acquire" procedure results in creating the IO using
> BIG Create Sync. The successful reply of it causes the transport to be
> advanced in TRANSPORT_STATE_ACTIVE state.
> 
> [...]

Here is the summary with links:
  - [BlueZ,1/5] shared/bap: Allow NULL bap endpoint in streams
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=5b4d9abfdeee
  - [BlueZ,2/5] shared/bap: Get broadcast channel location from stream capabilities
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=30b741baa569
  - [BlueZ,3/5] shared/bap: Update stream management to avoid PACs
    (no matching commit)
  - [BlueZ,4/5] shared/bap: In case of a BIS-PAC match return also the local pac
    (no matching commit)
  - [BlueZ,5/5] bap: Create streams and transports for each matching BIS
    (no matching commit)

You are awesome, thank you!