Re: [PATCH BlueZ v4 2/2] bap: Create transports for matching BISes

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

 



Hi Andrei,

On Tue, May 14, 2024 at 7:39 AM Andrei Istodorescu
<andrei.istodorescu@xxxxxxx> wrote:
>
> Rename bt_bap_add_bis to bt_bap_check_bis. This function is now an
> utilitary for checking if the information from a BIS is matching the
> capabilities in bt_bap. This utilitary is used when parsing the BASE
> data so that we can decide if we create a new setup/stream/transport for
> it, or advance to the next BIS.
> When checking in local PACS for a BIS match, return also the local PAC,
> along with the status of the operation. This information is required
> later when we create the stream.
>
> 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.
> ---
>  profiles/audio/bap.c | 323 ++++++++++++++++++++++++++++++-------------
>  src/shared/bap.c     | 227 ++++++++++++++++--------------
>  src/shared/bap.h     |   6 +-
>  3 files changed, 357 insertions(+), 199 deletions(-)
>
> diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
> index f09f2ea44109..eb321f33386a 100644
> --- a/profiles/audio/bap.c
> +++ b/profiles/audio/bap.c
> @@ -115,6 +115,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;
> @@ -131,7 +132,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;

Don't really like the idea of using nested structs like this, make it
confusing imo, besides can't you actually access the bap_data via
btd_device_get_user_data?

>         } data;
>  };
>
> @@ -202,6 +206,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) {
> @@ -218,6 +224,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);
> @@ -855,7 +862,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;
> @@ -871,12 +882,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;
>  }
> @@ -947,17 +960,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);
> @@ -993,20 +995,27 @@ 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(setup->ep->data->adapter->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);
>
> +       queue_remove(req->data.accept_data.bap_data->adapter->bcast_pa_requests,
> +                               req);
> +       free(req);
> +
>         if (bt_bap_stream_set_io(setup->stream, fd)) {
> -               bt_bap_stream_enable(setup->stream, true, NULL, NULL, NULL);
> +               bt_bap_stream_start(setup->stream, NULL, NULL);
>                 g_io_channel_set_close_on_unref(io, FALSE);
>                 return;
>         }
> @@ -1019,8 +1028,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,
> @@ -1099,6 +1154,10 @@ 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)) {
>                                 ret = false;
> @@ -1106,6 +1165,11 @@ static bool parse_base(struct bt_bap *bap, struct bt_iso_base *base,
>                         }
>
>                         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);
> @@ -1128,9 +1192,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);
>                 }
>
>  group_fail:
> @@ -1175,12 +1246,16 @@ static void iso_pa_sync_confirm_cb(GIOChannel *io, void *user_data)
>         g_io_channel_unref(data->listen_io);
>         g_io_channel_shutdown(io, TRUE, NULL);
>         data->listen_io = NULL;
> -       queue_remove(data->adapter->bcast_pa_requests, req);
> -       free(req);
> +
>         /* 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(req->data.service);
> +
> +       queue_remove(data->adapter->bcast_pa_requests, req);
> +       free(req);
>  }
>
>  static bool match_data_bap_data(const void *data, const void *match_data)
> @@ -1583,6 +1658,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:
> @@ -1597,9 +1673,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,
> @@ -2141,7 +2219,8 @@ static void setup_accept_io_broadcast(struct bap_data *data,
>          */
>         req->type = BAP_PA_BIG_SYNC_REQ;
>         req->in_progress = FALSE;
> -       req->data.setup = setup;
> +       req->data.accept_data.setup = setup;
> +       req->data.accept_data.bap_data = data;
>         queue_push_tail(adapter->bcast_pa_requests, req);
>  }
>
> @@ -2201,7 +2280,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
> @@ -2413,7 +2492,7 @@ static uint8_t get_streams_nb_by_state(struct bap_setup *setup)
>         return stream_cnt;
>  }
>
> -static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
> +static void bap_state_bcast_src(struct bt_bap_stream *stream, uint8_t old_state,
>                                 uint8_t new_state, void *user_data)
>  {
>         struct bap_data *data = user_data;
> @@ -2442,66 +2521,96 @@ static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
>         case BT_BAP_STREAM_STATE_CONFIG:
>                 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 {
> -                       /* If the stream attached to a broadcast
> -                        * source endpoint generate the base.
> -                        */
> -                       if (setup->base == NULL) {
> -                               setup->base = bt_bap_stream_get_base(
> -                                               setup->stream);
> -                               /* Set the generated BASE on all setups
> -                                * from the same BIG.
> -                                */
> -                               queue_foreach(setup->ep->setups,
> -                                       iterate_setup_update_base, setup);
> -                       }
> -                       /* The kernel has 2 requirements when handling
> -                        * multiple BIS connections for the same BIG:
> -                        * 1 - setup_create_io for all but the last BIS
> -                        * must be with defer true so we can inform the
> -                        * kernel when to start the BIG.
> -                        * 2 - The order in which the setup_create_io
> -                        * are called must be in the order of BIS
> -                        * indexes in BASE from first to last.
> -                        * To address this requirement we will call
> -                        * setup_create_io on all BISes only when all
> -                        * transport acquire have been received and will
> -                        * send it in the order of the BIS index
> -                        * from BASE.
> +               /* If the stream attached to a broadcast
> +                * source endpoint generate the base.
> +                */
> +               if (setup->base == NULL) {
> +                       setup->base = bt_bap_stream_get_base(
> +                                       setup->stream);
> +                       /* Set the generated BASE on all setups
> +                        * from the same BIG.
>                          */
> -                       nb_bises = get_streams_nb_by_state(setup);
> -
> -                       if (nb_bises == 1) {
> -                               setup_create_io(data, setup,
> -                               stream, defer);
> -                               if (!setup->io) {
> -                                       error("Unable to create io");
> -                                       if (old_state !=
> -                                               BT_BAP_STREAM_STATE_RELEASING)
> -                                               bt_bap_stream_release(stream,
> -                                                               NULL, NULL);
> -                               }
> -                               break;
> -                       } else if (nb_bises == 0)
> -                               break;
> +                       queue_foreach(setup->ep->setups,
> +                               iterate_setup_update_base, setup);
> +               }
> +               /* The kernel has 2 requirements when handling
> +                * multiple BIS connections for the same BIG:
> +                * 1 - setup_create_io for all but the last BIS
> +                * must be with defer true so we can inform the
> +                * kernel when to start the BIG.
> +                * 2 - The order in which the setup_create_io
> +                * are called must be in the order of BIS
> +                * indexes in BASE from first to last.
> +                * To address this requirement we will call
> +                * setup_create_io on all BISes only when all
> +                * transport acquire have been received and will
> +                * send it in the order of the BIS index
> +                * from BASE.
> +                */
> +               nb_bises = get_streams_nb_by_state(setup);
>
> -                       if (!create_io_bises(setup, nb_bises, data)) {
> +               if (nb_bises == 1) {
> +                       setup_create_io(data, setup,
> +                       stream, defer);
> +                       if (!setup->io) {
> +                               error("Unable to create io");
>                                 if (old_state !=
>                                         BT_BAP_STREAM_STATE_RELEASING)
>                                         bt_bap_stream_release(stream,
> -                                               NULL, NULL);
> +                                                       NULL, NULL);
>                         }
> +                       break;
> +               } else if (nb_bises == 0)
> +                       break;
> +
> +               if (!create_io_bises(setup, nb_bises, data)) {
> +                       if (old_state !=
> +                               BT_BAP_STREAM_STATE_RELEASING)
> +                               bt_bap_stream_release(stream,
> +                                       NULL, NULL);
>                 }
>                 break;
>         }
>  }
>
> +static void bap_state_bcast_sink(struct bt_bap_stream *stream,
> +                               uint8_t old_state, uint8_t new_state,
> +                               void *user_data)
> +{
> +       struct bap_data *data = user_data;
> +       struct bap_setup *setup;
> +       bool defer = false;
> +
> +       DBG("stream %p: %s(%u) -> %s(%u)", stream,
> +                       bt_bap_stream_statestr(old_state), old_state,
> +                       bt_bap_stream_statestr(new_state), new_state);
> +
> +       if (new_state == old_state && new_state != BT_BAP_STREAM_STATE_CONFIG)
> +               return;
> +
> +       setup = bap_find_setup_by_stream(data, stream);
> +
> +       switch (new_state) {
> +       case BT_BAP_STREAM_STATE_IDLE:
> +               /* Release stream if idle */
> +               if (setup)
> +                       setup_free(setup);
> +               else
> +                       queue_remove(data->streams, stream);
> +               break;
> +       case BT_BAP_STREAM_STATE_CONFIG:
> +               if (!setup)
> +                       break;
> +               if (old_state ==
> +                               BT_BAP_STREAM_STATE_CONFIG)
> +                       setup_create_io(data, setup, stream, defer);
> +               if (old_state ==
> +                               BT_BAP_STREAM_STATE_STREAMING)
> +                       setup_io_close(setup, NULL);
> +               break;
> +       }
> +}
> +
>  static void pac_added(struct bt_bap_pac *pac, void *user_data)
>  {
>         struct btd_service *service = user_data;
> @@ -2847,29 +2956,50 @@ 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;
> +       int s_err;
> +       const char *strbis = NULL;
>
> -       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);
> +
> +       strbis = strstr(path, "/bis");
> +       if (strbis == NULL) {
> +               DBG("bis index cannot be found");
> +               return;
> +       }
> +
> +       s_err = sscanf(strbis, "/bis%d", &bis_index);
> +       if (s_err == -1) {
> +               DBG("sscanf error");
> +               return;
> +       }
> +
> +       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 */
> @@ -2913,8 +3043,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;
>
> @@ -2967,6 +3097,7 @@ static int bap_bcast_probe(struct btd_service *service)
>                 free(data);
>                 return -EINVAL;
>         }
> +       data->bcast_snks = queue_new();
>
>         if (!bt_bap_attach(data->bap, NULL)) {
>                 error("BAP unable to attach");
> @@ -2977,7 +3108,7 @@ static int bap_bcast_probe(struct btd_service *service)
>
>         data->ready_id = bt_bap_ready_register(data->bap, bap_ready, service,
>                                                                 NULL);
> -       data->state_id = bt_bap_state_register(data->bap, bap_state_bcast,
> +       data->state_id = bt_bap_state_register(data->bap, bap_state_bcast_sink,
>                                         bap_connecting_bcast, data, NULL);
>         data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
>                                 pac_removed_broadcast, data, NULL);
> @@ -3160,7 +3291,7 @@ static int bap_adapter_probe(struct btd_profile *p, struct btd_adapter *adapter)
>                 return -EINVAL;
>         }
>
> -       data->state_id = bt_bap_state_register(data->bap, bap_state_bcast,
> +       data->state_id = bt_bap_state_register(data->bap, bap_state_bcast_src,
>                                         bap_connecting_bcast, data, NULL);
>         data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
>                                         pac_removed_broadcast, data, NULL);

Let's split the changes to src/shared/, that always should be
self-contained as much as possible since it has a different license
and is subject to unit tests.

> diff --git a/src/shared/bap.c b/src/shared/bap.c
> index 919ecbb6a016..fe91cd67f491 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,
> @@ -2019,6 +2053,17 @@ static unsigned int bap_bcast_start(struct bt_bap_stream *stream,
>         return 1;
>  }
>
> +static unsigned int bap_bcast_sink_disable(struct bt_bap_stream *stream,
> +                                       bool disable_links,
> +                                       bt_bap_stream_func_t func,
> +                                       void *user_data)
> +{
> +       bap_stream_io_detach(stream);
> +       stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
> +
> +       return 1;
> +}
> +
>  static unsigned int bap_bcast_disable(struct bt_bap_stream *stream,
>                                         bool disable_links,
>                                         bt_bap_stream_func_t func,
> @@ -2040,6 +2085,43 @@ static unsigned int bap_bcast_metadata(struct bt_bap_stream *stream,
>         return 1;
>  }
>
> +static unsigned int bap_bcast_src_get_dir(struct bt_bap_stream *stream)
> +{
> +       return BT_BAP_BCAST_SINK;
> +}
> +
> +static unsigned int bap_bcast_sink_get_dir(struct bt_bap_stream *stream)
> +{
> +       return BT_BAP_BCAST_SOURCE;
> +}
> +
> +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)
> @@ -2049,11 +2131,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, \
> @@ -2061,26 +2144,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_start, bap_bcast_sink_disable, NULL,
> +                       bap_bcast_metadata, bap_bcast_sink_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_src_get_dir,
> +                       bap_bcast_get_location,
> +                       bap_bcast_release),
>  };
>
>  static const struct bt_bap_stream_ops *
> @@ -5380,11 +5477,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)
> @@ -5568,53 +5661,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)
> @@ -6398,9 +6453,11 @@ static void check_local_pac(void *data, void *user_data)
>
>                 /* We have a match if all selected LTVs have a match */
>                 if ((bis_compare_data.data32 &
> -                       CODEC_SPECIFIC_CONFIGURATION_MASK) ==
> -                       CODEC_SPECIFIC_CONFIGURATION_MASK)
> +                               CODEC_SPECIFIC_CONFIGURATION_MASK) ==
> +                               CODEC_SPECIFIC_CONFIGURATION_MASK) {
>                         compare_data->found = true;
> +                       compare_data->data = data;
> +               }
>         }
>  }
>
> @@ -6425,7 +6482,8 @@ static void bap_sink_match_allocation(size_t i, uint8_t l, uint8_t t,
>                 data->found = false;
>  }
>
> -static bool bap_check_bis(struct bt_bap_db *ldb, struct iovec *bis_data)
> +static struct bt_ltv_match bap_check_bis(struct bt_bap_db *ldb,
> +       struct iovec *bis_data)
>  {
>         struct bt_ltv_match compare_data = {};
>
> @@ -6451,21 +6509,18 @@ static bool bap_check_bis(struct bt_bap_db *ldb, struct iovec *bis_data)
>                                 &compare_data);
>         }
>
> -       return compare_data.found;
> +       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;
>
>         merge_data.src = l3_caps;
>         merge_data.result = new0(struct iovec, 1);
> @@ -6481,43 +6536,15 @@ void bt_bap_add_bis(struct bt_bap *bap, uint8_t bis_index,
>         /* Check each BIS Codec Specific Configuration LTVs against our Codec
>          * Specific Capabilities and if the BIS matches create a PAC with it
>          */
> -       if (bap_check_bis(bap->ldb, merge_data.result) == 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;
> +       match_data = bap_check_bis(bap->ldb, merge_data.result);
> +       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
>


-- 
Luiz Augusto von Dentz





[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