shared/bap: Add initial code for BAP broadcast source
authorSilviu Florian Barbulescu <silviu.barbulescu@nxp.com>
Wed, 7 Jun 2023 08:22:59 +0000 (11:22 +0300)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 5 Jan 2024 13:34:03 +0000 (19:04 +0530)
This adds initial support for BAP broadcast source.

src/shared/bap.c
src/shared/bap.h

index 05d814c..4b31536 100644 (file)
@@ -121,6 +121,8 @@ struct bt_bap_db {
        struct bt_ascs *ascs;
        struct queue *sinks;
        struct queue *sources;
+       struct queue *broadcast_sources;
+       struct queue *broadcast_sinks;
 };
 
 struct bt_bap_req {
@@ -623,6 +625,18 @@ static struct bt_bap_endpoint *bap_endpoint_new(struct bt_bap_db *bdb,
        return ep;
 }
 
+static struct bt_bap_endpoint *bap_endpoint_new_broacast(struct bt_bap_db *bdb)
+{
+       struct bt_bap_endpoint *ep;
+
+       ep = new0(struct bt_bap_endpoint, 1);
+       ep->bdb = bdb;
+       ep->attr = NULL;
+       ep->dir = BT_BAP_BCAST_SOURCE;
+
+       return ep;
+}
+
 static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
                                                struct bt_bap_db *db,
                                                struct gatt_db_attribute *attr)
@@ -645,6 +659,30 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
        return ep;
 }
 
+static struct bt_bap_endpoint *bap_get_endpoint_bcast(struct queue *endpoints,
+                                               struct bt_bap_db *db)
+{
+       struct bt_bap_endpoint *ep;
+
+       if (!db)
+               return NULL;
+       /*
+        * We have support for only one stream so we will have
+        * only one endpoint.
+        * TO DO add support for more then one stream
+        */
+       if (queue_length(endpoints) > 0)
+               return queue_peek_head(endpoints);
+
+       ep = bap_endpoint_new_broacast(db);
+       if (!ep)
+               return NULL;
+
+       queue_push_tail(endpoints, ep);
+
+       return ep;
+}
+
 static bool bap_endpoint_match_id(const void *data, const void *match_data)
 {
        const struct bt_bap_endpoint *ep = data;
@@ -1261,6 +1299,37 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
        bt_bap_unref(bap);
 }
 
+static void stream_set_state_broadcast(struct bt_bap_stream *stream,
+                                       uint8_t state)
+{
+       struct bt_bap_endpoint *ep = stream->ep;
+       struct bt_bap *bap = stream->bap;
+       const struct queue_entry *entry;
+
+       ep->old_state = ep->state;
+       ep->state = state;
+
+       bt_bap_ref(bap);
+
+       for (entry = queue_get_entries(bap->state_cbs); entry;
+                                                       entry = entry->next) {
+               struct bt_bap_state *state = entry->data;
+
+               if (state->func)
+                       state->func(stream, stream->ep->old_state,
+                                       stream->ep->state, state->data);
+       }
+
+       /* Post notification updates */
+       switch (stream->ep->state) {
+       case BT_ASCS_ASE_STATE_IDLE:
+               bap_stream_detach(stream);
+               break;
+       }
+
+       bt_bap_unref(bap);
+}
+
 static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
 {
        struct bt_bap_endpoint *ep = stream->ep;
@@ -1397,6 +1466,11 @@ static void ep_config_cb(struct bt_bap_stream *stream, int err)
        if (err)
                return;
 
+       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BCAST) {
+               stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_CONFIG);
+               return;
+       }
+
        stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
 }
 
@@ -2222,6 +2296,8 @@ static struct bt_bap_db *bap_db_new(struct gatt_db *db)
        bdb->db = gatt_db_ref(db);
        bdb->sinks = queue_new();
        bdb->sources = queue_new();
+       bdb->broadcast_sources = queue_new();
+       bdb->broadcast_sinks = queue_new();
 
        if (!bap_db)
                bap_db = queue_new();
@@ -2397,6 +2473,16 @@ static void bap_add_source(struct bt_bap_pac *pac)
                                iov.iov_len, NULL);
 }
 
+static void bap_add_broadcast_source(struct bt_bap_pac *pac)
+{
+       queue_push_tail(pac->bdb->broadcast_sources, pac);
+}
+
+static void bap_add_broadcast_sink(struct bt_bap_pac *pac)
+{
+       queue_push_tail(pac->bdb->broadcast_sinks, pac);
+}
+
 static void notify_pac_added(void *data, void *user_data)
 {
        struct bt_bap_pac_changed *changed = data;
@@ -2421,7 +2507,7 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
                                        struct iovec *metadata)
 {
        struct bt_bap_db *bdb;
-       struct bt_bap_pac *pac;
+       struct bt_bap_pac *pac, *pac_brodcast_sink;
        struct bt_bap_codec codec;
 
        if (!db)
@@ -2447,6 +2533,13 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
        case BT_BAP_SOURCE:
                bap_add_source(pac);
                break;
+       case BT_BAP_BCAST_SOURCE:
+               // For broadcast add local pac and remote pac
+               bap_add_broadcast_source(pac);
+               pac_brodcast_sink = bap_pac_new(bdb, name, type, &codec, qos,
+                                       data, metadata);
+               bap_add_broadcast_sink(pac_brodcast_sink);
+               break;
        default:
                bap_pac_free(pac);
                return NULL;
@@ -2489,6 +2582,23 @@ uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac)
        }
 }
 
+uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream)
+{
+       if (!stream)
+               return 0x00;
+
+       switch (bt_bap_pac_get_type(stream->lpac)) {
+       case BT_BAP_SINK:
+       case BT_BAP_SOURCE:
+               return BT_BAP_STREAM_TYPE_UCAST;
+       case BT_BAP_BCAST_SOURCE:
+       case BT_BAP_BCAST_SINK:
+               return BT_BAP_STREAM_TYPE_BCAST;
+       }
+
+       return 0x00;
+}
+
 static void notify_pac_removed(void *data, void *user_data)
 {
        struct bt_bap_pac_changed *changed = data;
@@ -2547,6 +2657,9 @@ bool bt_bap_remove_pac(struct bt_bap_pac *pac)
        if (queue_remove_if(pac->bdb->sources, NULL, pac))
                goto found;
 
+       if (queue_remove_if(pac->bdb->broadcast_sources, NULL, pac))
+               goto found;
+
        return false;
 
 found:
@@ -3867,6 +3980,25 @@ clone:
        return true;
 }
 
+bool bt_bap_attach_broadcast(struct bt_bap *bap)
+{
+       struct bt_bap_endpoint *ep;
+
+       if (queue_find(sessions, NULL, bap))
+               return true;
+
+       if (!sessions)
+               sessions = queue_new();
+
+       queue_push_tail(sessions, bap);
+
+       ep = bap_get_endpoint_bcast(bap->remote_eps, bap->ldb);
+       if (ep)
+               ep->bap = bap;
+
+       return true;
+}
+
 static void stream_foreach_detach(void *data, void *user_data)
 {
        struct bt_bap_stream *stream = data;
@@ -4071,7 +4203,11 @@ void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type,
                                                        func, user_data);
        case BT_BAP_SOURCE:
                return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources,
-                                                       func, user_data);
+                                                          func, user_data);
+       case BT_BAP_BCAST_SOURCE:
+               return bap_foreach_pac(bap->ldb->broadcast_sources,
+                                       bap->ldb->broadcast_sinks,
+                                       func, user_data);
        }
 }
 
@@ -4184,42 +4320,51 @@ unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
        if (!bap_stream_valid(stream))
                return 0;
 
-       if (!stream->client) {
-               stream_config(stream, data, NULL);
-               return 0;
-       }
+       switch (bt_bap_stream_get_type(stream)) {
+       case BT_BAP_STREAM_TYPE_UCAST:
+               if (!stream->client) {
+                       stream_config(stream, data, NULL);
+                       return 0;
+               }
 
-       memset(&config, 0, sizeof(config));
+               memset(&config, 0, sizeof(config));
 
-       config.ase = stream->ep->id;
-       config.latency = qos->ucast.target_latency;
-       config.phy = qos->ucast.io_qos.phy;
-       config.codec = stream->rpac->codec;
+               config.ase = stream->ep->id;
+               config.latency = qos->ucast.target_latency;
+               config.phy = qos->ucast.io_qos.phy;
+               config.codec = stream->rpac->codec;
 
-       iov[0].iov_base = &config;
-       iov[0].iov_len = sizeof(config);
+               iov[0].iov_base = &config;
+               iov[0].iov_len = sizeof(config);
 
-       if (data) {
-               if (!bap_print_cc(data->iov_base, data->iov_len,
-                                       stream->bap->debug_func,
-                                       stream->bap->debug_data))
-                       return 0;
+               if (data) {
+                       if (!bap_print_cc(data->iov_base, data->iov_len,
+                                               stream->bap->debug_func,
+                                               stream->bap->debug_data))
+                               return 0;
 
-               config.cc_len = data->iov_len;
-               iov[1] = *data;
-               iovlen++;
-       }
+                       config.cc_len = data->iov_len;
+                       iov[1] = *data;
+                       iovlen++;
+               }
 
-       req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
+               req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen,
+                                       func, user_data);
 
-       if (!bap_queue_req(stream->bap, req)) {
-               bap_req_free(req);
-               return 0;
-       }
+               if (!bap_queue_req(stream->bap, req)) {
+                       bap_req_free(req);
+                       return 0;
+               }
 
-       stream->qos = *qos;
+               stream->qos = *qos;
 
-       return req->id;
+               return req->id;
+       case BT_BAP_STREAM_TYPE_BCAST:
+               stream->qos = *qos;
+               return 1;
+       }
+
+       return 0;
 }
 
 static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
@@ -4345,6 +4490,10 @@ bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
 
        stream->user_data = user_data;
 
+       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BCAST)
+               stream->lpac->ops->config(stream, stream->cc, &stream->qos,
+                                       ep_config_cb, stream->lpac->user_data);
+
        return true;
 }
 
@@ -4454,7 +4603,7 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
                                        bt_bap_stream_func_t func,
                                        void *user_data)
 {
-       int ret;
+       int ret = 0;
 
        /* Table 3.2: ASE state machine transition
         * Initiating device - client Only
@@ -4462,12 +4611,20 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
        if (!bap_stream_valid(stream) || !stream->client)
                return 0;
 
-       ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
-                                                               user_data);
-       if (!ret || !enable_links)
-               return ret;
+       switch (bt_bap_stream_get_type(stream)) {
+       case BT_BAP_STREAM_TYPE_UCAST:
+               ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata,
+                                                       func, user_data);
+               if (!ret || !enable_links)
+                       return ret;
 
-       queue_foreach(stream->links, bap_stream_enable_link, metadata);
+               queue_foreach(stream->links, bap_stream_enable_link, metadata);
+               break;
+       case BT_BAP_STREAM_TYPE_BCAST:
+               stream_set_state_broadcast(stream,
+                                       BT_BAP_STREAM_STATE_STREAMING);
+               return 1;
+       }
 
        return ret;
 }
@@ -4646,6 +4803,16 @@ unsigned int bt_bap_stream_release(struct bt_bap_stream *stream,
 
        bap = stream->bap;
 
+       /* If stream is broadcast, no BT_ASCS_RELEASE is required */
+       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BCAST) {
+               if (!bap_stream_valid(stream)) {
+                       stream_set_state_broadcast(stream,
+                                       BT_BAP_STREAM_STATE_IDLE);
+                       stream = NULL;
+               }
+               return 0;
+       }
+
        /* If stream does not belong to a client session, clean it up now */
        if (!bap_stream_valid(stream)) {
                stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
@@ -4681,8 +4848,13 @@ uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
 
        if (stream->ep->dir == BT_BAP_SOURCE)
                return pacs->source_loc_value;
-       else
+       else if (stream->ep->dir == BT_BAP_SINK)
                return pacs->sink_loc_value;
+       else
+               /* TO DO get the location values from metadata
+                * for brodcast source and sink
+                */
+               return stream->bap->ldb->pacs->source_loc_value;
 }
 
 struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
index 1a32bc8..8fc4186 100644 (file)
 
 #define BT_BAP_SINK                    0x01
 #define        BT_BAP_SOURCE                   0x02
+#define        BT_BAP_BCAST_SOURCE             0x03
+#define        BT_BAP_BCAST_SINK               0x04
+
+#define BT_BAP_STREAM_TYPE_UCAST       0x01
+#define        BT_BAP_STREAM_TYPE_BCAST        0x02
 
 #define BT_BAP_STREAM_STATE_IDLE       0x00
 #define BT_BAP_STREAM_STATE_CONFIG     0x01
@@ -160,6 +165,8 @@ uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac);
 
 uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac);
 
+uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream);
+
 struct bt_bap_stream *bt_bap_pac_get_stream(struct bt_bap_pac *pac);
 
 /* Session related function */
@@ -179,6 +186,7 @@ struct bt_bap *bt_bap_ref(struct bt_bap *bap);
 void bt_bap_unref(struct bt_bap *bap);
 
 bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client);
+bool bt_bap_attach_broadcast(struct bt_bap *bap);
 void bt_bap_detach(struct bt_bap *bap);
 
 bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb,