diff --git a/include/zephyr/bluetooth/audio/capabilities.h b/include/zephyr/bluetooth/audio/capabilities.h index a81ac7529295c..4069d4347a142 100644 --- a/include/zephyr/bluetooth/audio/capabilities.h +++ b/include/zephyr/bluetooth/audio/capabilities.h @@ -19,225 +19,12 @@ extern "C" { /* Get list of capabilities by type */ sys_slist_t *bt_audio_capability_get(enum bt_audio_dir dir); - -/** @brief Audio Capability type */ -enum bt_audio_capability_framing { - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED = 0x00, - BT_AUDIO_CAPABILITY_UNFRAMED_NOT_SUPPORTED = 0x01, -}; - -/** - * @brief Helper to declare elements of @ref bt_audio_capability_pref - * - * @param _framing Framing Support - * @param _phy Preferred Target PHY - * @param _rtn Preferred Retransmission number - * @param _latency Preferred Maximum Transport Latency (msec) - * @param _pd_min Minimum Presentation Delay (usec) - * @param _pd_max Maximum Presentation Delay (usec) - * @param _pref_pd_min Preferred Minimum Presentation Delay (usec) - * @param _pref_pd_max Preferred Maximum Presentation Delay (usec) - */ -#define BT_AUDIO_CAPABILITY_PREF(_framing, _phy, _rtn, _latency, _pd_min, \ - _pd_max, _pref_pd_min, _pref_pd_max) \ - { \ - .framing = _framing, \ - .phy = _phy, \ - .rtn = _rtn, \ - .latency = _latency, \ - .pd_min = _pd_min, \ - .pd_max = _pd_max, \ - .pref_pd_min = _pref_pd_min, \ - .pref_pd_max = _pref_pd_max, \ - } - -/** @brief Audio Capability Preference structure. */ -struct bt_audio_capability_pref { - /** @brief Framing support value - * - * Unlike the other fields, this is not a preference but whether - * the capability supports unframed ISOAL PDUs. - * - * Possible values: BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED and - * BT_AUDIO_CAPABILITY_UNFRAMED_NOT_SUPPORTED. - */ - uint8_t framing; - - /** Preferred PHY */ - uint8_t phy; - - /** Preferred Retransmission Number */ - uint8_t rtn; - - /** Preferred Transport Latency in ms */ - uint16_t latency; - - /** @brief Minimum Presentation Delay in us - * - * Unlike the other fields, this is not a preference but a minimum - * requirement. - */ - uint32_t pd_min; - - /** @brief Maximum Presentation Delay in us - * - * Unlike the other fields, this is not a preference but a maximum - * requirement. - */ - uint32_t pd_max; - - /** @brief Preferred minimum Presentation Delay in us*/ - uint32_t pref_pd_min; - - /** @brief Preferred maximum Presentation Delay in us */ - uint32_t pref_pd_max; -}; - -struct bt_audio_capability; /* Handle circular dependency */ - -/** @brief Capability operations structure. - * - * These are only used for unicast streams and broadcast sink streams. - */ -struct bt_audio_capability_ops { - /** @brief Capability config callback - * - * Config callback is called whenever a new Audio Stream needs to be - * allocated. - * - * @param conn Connection object - * @param ep Remote Audio Endpoint being configured - * @param dir Direction of the endpoint. - * @param cap Local Audio Capability being configured - * @param codec Codec configuration - * - * @return Allocated Audio Stream object or NULL in case of error. - */ - struct bt_audio_stream *(*config)(struct bt_conn *conn, - struct bt_audio_ep *ep, - enum bt_audio_dir dir, - struct bt_audio_capability *cap, - struct bt_codec *codec); - - /** @brief Capability reconfig callback - * - * Reconfig callback is called whenever an Audio Stream needs to be - * reconfigured with different codec configuration. - * - * @param stream Stream object being reconfigured. - * @param cap Local Audio Capability being reconfigured - * @param codec Codec configuration - * - * @return 0 in case of success or negative value in case of error. - */ - int (*reconfig)(struct bt_audio_stream *stream, - struct bt_audio_capability *cap, - struct bt_codec *codec); - - /** @brief Capability QoS callback - * - * QoS callback is called whenever an Audio Stream Quality of - * Service needs to be configured. - * - * @param stream Stream object being reconfigured. - * @param QoS Quality of Service configuration - * - * @return 0 in case of success or negative value in case of error. - */ - int (*qos)(struct bt_audio_stream *stream, struct bt_codec_qos *qos); - - /** @brief Capability Enable callback - * - * Enable callback is called whenever an Audio Stream is about to be - * enabled. - * - * @param stream Stream object being enabled. - * @param meta_count Number of metadata entries - * @param meta Metadata entries - * - * @return 0 in case of success or negative value in case of error. - */ - int (*enable)(struct bt_audio_stream *stream, - struct bt_codec_data *meta, - size_t meta_count); - - /** @brief Capability Start callback - * - * Start callback is called whenever an Audio Stream is about to - * start streaming. - * - * @param stream Stream object. - * - * @return 0 in case of success or negative value in case of error. - */ - int (*start)(struct bt_audio_stream *stream); - - /** @brief Capability Metadata callback - * - * Metadata callback is called whenever an Audio Stream needs to - * update its metadata. - * - * @param stream Stream object. - * @param meta_count Number of metadata entries - * @param meta Metadata entries - * - * @return 0 in case of success or negative value in case of error. - */ - int (*metadata)(struct bt_audio_stream *stream, - struct bt_codec_data *meta, - size_t meta_count); - - /** @brief Capability Disable callback - * - * Disable callback is called whenever an Audio Stream is about to be - * disabled. - * - * @param stream Stream object being disabled. - * - * @return 0 in case of success or negative value in case of error. - */ - int (*disable)(struct bt_audio_stream *stream); - - /** @brief Capability Stop callback - * - * Stop callback is called whenever an Audio Stream is about to - * stop streaming. - * - * @param stream Stream object. - * - * @return 0 in case of success or negative value in case of error. - */ - int (*stop)(struct bt_audio_stream *stream); - - /** @brief Capability release callback - * - * Release callback is called whenever a new Audio Stream needs to be - * deallocated. - * - * @param stream Stream object. - * - * @return 0 in case of success or negative value in case of error. - */ - int (*release)(struct bt_audio_stream *stream); -}; - -/** @brief Audio Capability structure. - * - * Audio Capability represents a Local Codec including its preferrable - * Quality of service. - * - */ +/** @brief Audio Capability structure. */ struct bt_audio_capability { /** Capability direction */ enum bt_audio_dir dir; /** Capability codec reference */ struct bt_codec *codec; -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) - /** Capability preferences */ - struct bt_audio_capability_pref pref; - /** Capability operations reference */ - struct bt_audio_capability_ops *ops; -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */ /* Internally used list node */ sys_snode_t _node; diff --git a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c index c777c05410727..5746e440e0f55 100644 --- a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c +++ b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c @@ -35,6 +35,9 @@ static struct bt_audio_source { } source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; static size_t configured_source_stream_count; +static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, + 10, 20000, 40000, 20000, 40000); + static uint32_t get_and_incr_seq_num(const struct bt_audio_stream *stream) { for (size_t i = 0U; i < configured_source_stream_count; i++) { @@ -98,7 +101,7 @@ static void print_codec(const struct bt_codec *codec) } } -static void print_qos(struct bt_codec_qos *qos) +static void print_qos(const struct bt_codec_qos *qos) { printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " "rtn %u latency %u pd %u\n", @@ -170,37 +173,49 @@ static void audio_timer_timeout(struct k_work *work) } } -static struct bt_audio_stream *lc3_config(struct bt_conn *conn, struct bt_audio_ep *ep, - enum bt_audio_dir dir, struct bt_audio_capability *cap, - struct bt_codec *codec) +static struct bt_audio_stream *stream_alloc(void) { - printk("ASE Codec Config: conn %p ep %p dir %u, cap %p\n", - conn, ep, dir, cap); - - print_codec(codec); - for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { struct bt_audio_stream *stream = &streams[i]; if (!stream->conn) { - printk("ASE Codec Config stream %p\n", stream); - if (dir == BT_AUDIO_DIR_SOURCE) { - source_streams[configured_source_stream_count++].stream = stream; - } - return stream; } } - printk("No streams available\n"); - return NULL; } -static int lc3_reconfig(struct bt_audio_stream *stream, struct bt_audio_capability *cap, - struct bt_codec *codec) +static int lc3_config(struct bt_conn *conn, const struct bt_audio_ep *ep, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_audio_stream **stream, + struct bt_codec_qos_pref *const pref) +{ + printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); + + print_codec(codec); + + *stream = stream_alloc(); + if (*stream == NULL) { + printk("No streams available\n"); + + return -ENOMEM; + } + + printk("ASE Codec Config stream %p\n", *stream); + + if (dir == BT_AUDIO_DIR_SOURCE) { + source_streams[configured_source_stream_count++].stream = *stream; + } + + *pref = qos_pref; + + return 0; +} + +static int lc3_reconfig(struct bt_audio_stream *stream, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_codec_qos_pref *const pref) { - printk("ASE Codec Reconfig: stream %p cap %p\n", stream, cap); + printk("ASE Codec Reconfig: stream %p\n", stream); print_codec(codec); @@ -208,7 +223,7 @@ static int lc3_reconfig(struct bt_audio_stream *stream, struct bt_audio_capabili return -ENOEXEC; } -static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) +static int lc3_qos(struct bt_audio_stream *stream, const struct bt_codec_qos *qos) { printk("QoS: stream %p qos %p\n", stream, qos); @@ -217,7 +232,7 @@ static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) return 0; } -static int lc3_enable(struct bt_audio_stream *stream, struct bt_codec_data *meta, +static int lc3_enable(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { printk("Enable: stream %p meta_count %u\n", stream, meta_count); @@ -291,7 +306,7 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_audio_stream *stream, struct bt_codec_data *meta, +static int lc3_metadata(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { printk("Metadata: stream %p meta_count %u\n", stream, meta_count); @@ -328,7 +343,7 @@ static int lc3_release(struct bt_audio_stream *stream) return 0; } -static struct bt_audio_capability_ops lc3_ops = { +static const struct bt_audio_unicast_server_cb unicast_server_cb = { .config = lc3_config, .reconfig = lc3_reconfig, .qos = lc3_qos, @@ -399,28 +414,20 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { static struct bt_audio_capability caps[] = { { .dir = BT_AUDIO_DIR_SINK, - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0x02, 10, 20000, 40000, - 20000, 40000), .codec = &lc3_codec, - .ops = &lc3_ops, }, #if defined(CONFIG_BT_ASCS_ASE_SRC) { .dir = BT_AUDIO_DIR_SOURCE, - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0x02, 10, 20000, 40000, - 20000, 40000), .codec = &lc3_codec, - .ops = &lc3_ops, } #endif /* CONFIG_BT_ASCS_ASE_SRC */ }; int bap_unicast_sr_init(void) { + bt_audio_unicast_server_register_cb(&unicast_server_cb); + for (size_t i = 0; i < ARRAY_SIZE(caps); i++) { bt_audio_capability_register(&caps[i]); } diff --git a/samples/bluetooth/unicast_audio_server/src/main.c b/samples/bluetooth/unicast_audio_server/src/main.c index 76efb338dc8df..8b0ad61113e8f 100644 --- a/samples/bluetooth/unicast_audio_server/src/main.c +++ b/samples/bluetooth/unicast_audio_server/src/main.c @@ -47,6 +47,9 @@ static struct bt_audio_source { } source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; static size_t configured_source_stream_count; +static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, + 10, 40000, 40000, 40000, 40000); + static K_SEM_DEFINE(sem_disconnected, 0, 1); static uint8_t unicast_server_addata[] = { @@ -144,7 +147,7 @@ static void print_codec(const struct bt_codec *codec) } } -static void print_qos(struct bt_codec_qos *qos) +static void print_qos(const struct bt_codec_qos *qos) { printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " "rtn %u latency %u pd %u\n", @@ -214,45 +217,54 @@ static void audio_timer_timeout(struct k_work *work) k_work_schedule(&audio_send_work, K_MSEC(1000U)); } -static struct bt_audio_stream *lc3_config(struct bt_conn *conn, - struct bt_audio_ep *ep, - enum bt_audio_dir dir, - struct bt_audio_capability *cap, - struct bt_codec *codec) +static struct bt_audio_stream *stream_alloc(void) { - printk("ASE Codec Config: conn %p ep %p dir %u, cap %p\n", - conn, ep, dir, cap); - - print_codec(codec); - for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { struct bt_audio_stream *stream = &streams[i]; if (!stream->conn) { - printk("ASE Codec Config stream %p\n", stream); - if (dir == BT_AUDIO_DIR_SOURCE) { - source_streams[configured_source_stream_count++].stream = stream; - } - return stream; } } - printk("No streams available\n"); + return NULL; +} + +static int lc3_config(struct bt_conn *conn, const struct bt_audio_ep *ep, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_audio_stream **stream, + struct bt_codec_qos_pref *const pref) +{ + printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); + + print_codec(codec); + + *stream = stream_alloc(); + if (*stream == NULL) { + printk("No streams available\n"); + + return -ENOMEM; + } + + printk("ASE Codec Config stream %p\n", *stream); + + if (dir == BT_AUDIO_DIR_SOURCE) { + source_streams[configured_source_stream_count++].stream = *stream; + } + + *pref = qos_pref; #if defined(CONFIG_LIBLC3) /* Nothing to free as static memory is used */ lc3_decoder = NULL; #endif - return NULL; + return 0; } -static int lc3_reconfig(struct bt_audio_stream *stream, - struct bt_audio_capability *cap, - struct bt_codec *codec) +static int lc3_reconfig(struct bt_audio_stream *stream, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_codec_qos_pref *const pref) { - printk("ASE Codec Reconfig: stream %p cap %p\n", stream, cap); + printk("ASE Codec Reconfig: stream %p\n", stream); print_codec(codec); @@ -265,7 +277,7 @@ static int lc3_reconfig(struct bt_audio_stream *stream, return -ENOEXEC; } -static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) +static int lc3_qos(struct bt_audio_stream *stream, const struct bt_codec_qos *qos) { printk("QoS: stream %p qos %p\n", stream, qos); @@ -281,8 +293,7 @@ static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) return 0; } -static int lc3_enable(struct bt_audio_stream *stream, - struct bt_codec_data *meta, +static int lc3_enable(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { printk("Enable: stream %p meta_count %u\n", stream, meta_count); @@ -383,8 +394,7 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_audio_stream *stream, - struct bt_codec_data *meta, +static int lc3_metadata(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { printk("Metadata: stream %p meta_count %u\n", stream, meta_count); @@ -421,7 +431,7 @@ static int lc3_release(struct bt_audio_stream *stream) return 0; } -static struct bt_audio_capability_ops lc3_ops = { +static const struct bt_audio_unicast_server_cb unicast_server_cb = { .config = lc3_config, .reconfig = lc3_reconfig, .qos = lc3_qos, @@ -556,21 +566,11 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { static struct bt_audio_capability caps[] = { { .dir = BT_AUDIO_DIR_SINK, - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, - 40000, 40000), .codec = &lc3_codec, - .ops = &lc3_ops, }, { .dir = BT_AUDIO_DIR_SOURCE, - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, - 40000, 40000), .codec = &lc3_codec, - .ops = &lc3_ops, } }; @@ -641,6 +641,8 @@ void main(void) printk("Bluetooth initialized\n"); + bt_audio_unicast_server_register_cb(&unicast_server_cb); + for (size_t i = 0; i < ARRAY_SIZE(caps); i++) { bt_audio_capability_register(&caps[i]); } diff --git a/subsys/bluetooth/audio/capabilities.c b/subsys/bluetooth/audio/capabilities.c index 6c8208f6a77d4..6d6f4a97577fc 100644 --- a/subsys/bluetooth/audio/capabilities.c +++ b/subsys/bluetooth/audio/capabilities.c @@ -31,218 +31,6 @@ static sys_slist_t srcs; IF_ENABLED(CONFIG_BT_PAC_SNK, (static enum bt_audio_context sink_available_contexts;)) IF_ENABLED(CONFIG_BT_PAC_SRC, (static enum bt_audio_context source_available_contexts;)); -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS) -/* TODO: The unicast server callbacks uses `const` for many of the pointers, - * wheras the capabilities callbacks do no. The latter should be updated to use - * `const` where possible. - */ -static int unicast_server_config_cb(struct bt_conn *conn, - const struct bt_audio_ep *ep, - enum bt_audio_dir dir, - const struct bt_codec *codec, - struct bt_audio_stream **stream, - struct bt_codec_qos_pref *const pref) -{ - struct bt_audio_capability *cap; - sys_slist_t *lst; - - if (dir == BT_AUDIO_DIR_SINK) { - lst = &snks; - } else if (dir == BT_AUDIO_DIR_SOURCE) { - lst = &srcs; - } else { - BT_ERR("Invalid endpoint dir: %u", dir); - return -EINVAL; - } - - SYS_SLIST_FOR_EACH_CONTAINER(lst, cap, _node) { - /* Skip if capabilities don't match */ - if (codec->id != cap->codec->id) { - continue; - } - - if (cap->ops == NULL || cap->ops->config == NULL) { - return -EACCES; - } - - *stream = cap->ops->config(conn, (struct bt_audio_ep *)ep, - dir, cap, (struct bt_codec *)codec); - - if (*stream == NULL) { - return -ENOMEM; - } - - pref->unframed_supported = - cap->pref.framing == BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED; - pref->phy = cap->pref.phy; - pref->rtn = cap->pref.rtn; - pref->latency = cap->pref.latency; - pref->pd_min = cap->pref.pd_min; - pref->pd_max = cap->pref.pd_max; - pref->pref_pd_min = cap->pref.pref_pd_min; - pref->pref_pd_max = cap->pref.pref_pd_max; - - (*stream)->user_data = cap; - - return 0; - } - - BT_ERR("No capability for dir %u and codec ID %u", dir, codec->id); - - return -EOPNOTSUPP; -} - -static int unicast_server_reconfig_cb(struct bt_audio_stream *stream, - enum bt_audio_dir dir, - const struct bt_codec *codec, - struct bt_codec_qos_pref *const pref) -{ - struct bt_audio_capability *cap; - sys_slist_t *lst; - - if (dir == BT_AUDIO_DIR_SINK) { - lst = &snks; - } else if (dir == BT_AUDIO_DIR_SOURCE) { - lst = &srcs; - } else { - BT_ERR("Invalid endpoint dir: %u", dir); - return -EINVAL; - } - - SYS_SLIST_FOR_EACH_CONTAINER(lst, cap, _node) { - int err; - - if (codec->id != cap->codec->id) { - continue; - } - - if (cap->ops == NULL || cap->ops->reconfig == NULL) { - return -EACCES; - } - - pref->unframed_supported = - cap->pref.framing == BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED; - pref->phy = cap->pref.phy; - pref->rtn = cap->pref.rtn; - pref->latency = cap->pref.latency; - pref->pd_min = cap->pref.pd_min; - pref->pd_max = cap->pref.pd_max; - pref->pref_pd_min = cap->pref.pref_pd_min; - pref->pref_pd_max = cap->pref.pref_pd_max; - - err = cap->ops->reconfig(stream, cap, - (struct bt_codec *)codec); - if (err != 0) { - return err; - } - - stream->user_data = cap; - - return 0; - } - - BT_ERR("No capability for dir %u and codec ID %u", dir, codec->id); - - return -EOPNOTSUPP; -} - -static int unicast_server_qos_cb(struct bt_audio_stream *stream, - const struct bt_codec_qos *qos) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->qos == NULL) { - return -EACCES; - } - - return cap->ops->qos(stream, (struct bt_codec_qos *)qos); -} - -static int unicast_server_enable_cb(struct bt_audio_stream *stream, - const struct bt_codec_data *meta, - size_t meta_count) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->enable == NULL) { - return -EACCES; - } - - return cap->ops->enable(stream, (struct bt_codec_data *)meta, - meta_count); -} - -static int unicast_server_start_cb(struct bt_audio_stream *stream) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->start == NULL) { - return -EACCES; - } - - return cap->ops->start(stream); -} - -static int unicast_server_metadata_cb(struct bt_audio_stream *stream, - const struct bt_codec_data *meta, - size_t meta_count) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->metadata == NULL) { - return -EACCES; - } - - return cap->ops->metadata(stream, (struct bt_codec_data *)meta, - meta_count); -} - -static int unicast_server_disable_cb(struct bt_audio_stream *stream) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->disable == NULL) { - return -EACCES; - } - - return cap->ops->disable(stream); -} - -static int unicast_server_stop_cb(struct bt_audio_stream *stream) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->stop == NULL) { - return -EACCES; - } - - return cap->ops->stop(stream); -} - -static int unicast_server_release_cb(struct bt_audio_stream *stream) -{ - struct bt_audio_capability *cap = stream->user_data; - - if (cap->ops == NULL || cap->ops->release == NULL) { - return -EACCES; - } - - return cap->ops->release(stream); -} - -static struct bt_audio_unicast_server_cb unicast_server_cb = { - .config = unicast_server_config_cb, - .reconfig = unicast_server_reconfig_cb, - .qos = unicast_server_qos_cb, - .enable = unicast_server_enable_cb, - .start = unicast_server_start_cb, - .metadata = unicast_server_metadata_cb, - .disable = unicast_server_disable_cb, - .stop = unicast_server_stop_cb, - .release = unicast_server_release_cb -}; -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */ - static int publish_capability_cb(struct bt_conn *conn, uint8_t dir, uint8_t index, struct bt_codec *codec) { @@ -377,28 +165,6 @@ int bt_audio_capability_register(struct bt_audio_capability *cap) pacs_cb_registered = true; } -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS) - /* Using the capabilities instead of the unicast server directly will - * require the capabilities to register the callbacks, which not only - * will forward the unicast server callbacks, but also ensure that the - * unicast server callbacks are not registered elsewhere - */ - static bool unicast_server_cb_registered; - - if (!unicast_server_cb_registered) { - int err; - - err = bt_audio_unicast_server_register_cb(&unicast_server_cb); - if (err != 0) { - BT_DBG("Failed to register unicast server callbacks: %d", - err); - return err; - } - - unicast_server_cb_registered = true; - } -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */ - sys_slist_append(lst, &cap->_node); #if defined(CONFIG_BT_PACS) @@ -428,22 +194,6 @@ int bt_audio_capability_unregister(struct bt_audio_capability *cap) return -ENOENT; } -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS) - /* If we are removing the last audio capability as the unicast - * server, we unregister the callbacks. - */ - if (sys_slist_is_empty(&snks) && sys_slist_is_empty(&srcs)) { - int err; - - err = bt_audio_unicast_server_unregister_cb(&unicast_server_cb); - if (err != 0) { - BT_DBG("Failed to register unicast server callbacks: %d", - err); - return err; - } - } -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */ - #if defined(CONFIG_BT_PACS) bt_pacs_remove_capability(cap->dir); #endif /* CONFIG_BT_PACS */ diff --git a/subsys/bluetooth/shell/audio.c b/subsys/bluetooth/shell/audio.c index 4cb3f275a9305..3b59f39f83ceb 100644 --- a/subsys/bluetooth/shell/audio.c +++ b/subsys/bluetooth/shell/audio.c @@ -39,6 +39,9 @@ static struct bt_audio_stream streams[UNICAST_SERVER_STREAM_COUNT + UNICAST_CLIENT_STREAM_COUNT]; +static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0u, 60u, + 20000u, 40000u, 20000u, 40000u); + #if defined(CONFIG_BT_AUDIO_UNICAST_CLIENT) static struct bt_audio_unicast_group *default_unicast_group; static struct bt_codec *rcodecs[2][CONFIG_BT_AUDIO_UNICAST_CLIENT_PAC_COUNT]; @@ -249,8 +252,7 @@ static void set_stream(struct bt_audio_stream *stream) } } -#if defined(CONFIG_BT_AUDIO_UNICAST) -static void print_qos(struct bt_codec_qos *qos) +static void print_qos(const struct bt_codec_qos *qos) { shell_print(ctx_shell, "QoS: interval %u framing 0x%02x " "phy 0x%02x sdu %u rtn %u latency %u pd %u", @@ -280,41 +282,47 @@ static int cmd_select_unicast(const struct shell *sh, size_t argc, char *argv[]) return 0; } -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) -static struct bt_audio_stream *lc3_config(struct bt_conn *conn, - struct bt_audio_ep *ep, - enum bt_audio_dir dir, - struct bt_audio_capability *cap, - struct bt_codec *codec) +static struct bt_audio_stream *stream_alloc(void) { - int i; + for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { + struct bt_audio_stream *stream = &streams[i]; + + if (!stream->conn) { + return stream; + } + } + + return NULL; +} - shell_print(ctx_shell, "ASE Codec Config: conn %p ep %p dir %u, cap %p", - conn, ep, dir, cap); +static int lc3_config(struct bt_conn *conn, const struct bt_audio_ep *ep, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_audio_stream **stream, + struct bt_codec_qos_pref *const pref) +{ + shell_print(ctx_shell, "ASE Codec Config: conn %p ep %p dir %u", conn, ep, dir); print_codec(codec); - for (i = 0; i < ARRAY_SIZE(streams); i++) { - struct bt_audio_stream *stream = &streams[i]; + *stream = stream_alloc(); + if (*stream == NULL) { + shell_print(ctx_shell, "No streams available"); - if (stream->conn == NULL) { - shell_print(ctx_shell, "ASE Codec Config stream %p", - stream); - set_stream(stream); - return stream; - } + return -ENOMEM; } - shell_print(ctx_shell, "No streams available"); + shell_print(ctx_shell, "ASE Codec Config stream %p", *stream); - return NULL; + set_stream(*stream); + + *pref = qos_pref; + + return 0; } -static int lc3_reconfig(struct bt_audio_stream *stream, - struct bt_audio_capability *cap, - struct bt_codec *codec) +static int lc3_reconfig(struct bt_audio_stream *stream, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_codec_qos_pref *const pref) { - shell_print(ctx_shell, "ASE Codec Reconfig: stream %p cap %p", stream, cap); + shell_print(ctx_shell, "ASE Codec Reconfig: stream %p", stream); print_codec(codec); @@ -322,10 +330,12 @@ static int lc3_reconfig(struct bt_audio_stream *stream, set_stream(stream); } + *pref = qos_pref; + return 0; } -static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) +static int lc3_qos(struct bt_audio_stream *stream, const struct bt_codec_qos *qos) { shell_print(ctx_shell, "QoS: stream %p %p", stream, qos); @@ -334,8 +344,7 @@ static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) return 0; } -static int lc3_enable(struct bt_audio_stream *stream, - struct bt_codec_data *meta, +static int lc3_enable(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { shell_print(ctx_shell, "Enable: stream %p meta_count %zu", stream, @@ -397,8 +406,7 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_audio_stream *stream, - struct bt_codec_data *meta, +static int lc3_metadata(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { shell_print(ctx_shell, "Metadata: stream %p meta_count %zu", stream, @@ -450,7 +458,7 @@ static struct bt_codec lc3_codec = BT_CODEC_LC3(BT_CODEC_LC3_FREQ_ANY, (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); -static struct bt_audio_capability_ops lc3_ops = { +static const struct bt_audio_unicast_server_cb unicast_server_cb = { .config = lc3_config, .reconfig = lc3_reconfig, .qos = lc3_qos, @@ -461,35 +469,19 @@ static struct bt_audio_capability_ops lc3_ops = { .stop = lc3_stop, .release = lc3_release, }; -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */ -#endif /* CONFIG_BT_AUDIO_UNICAST */ -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) || defined(CONFIG_BT_AUDIO_BROADCAST_SINK) static struct bt_audio_capability caps[] = { #if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) { .dir = BT_AUDIO_DIR_SOURCE, - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0u, 60u, 20000u, 40000u, - 20000u, 40000u), .codec = &lc3_codec, - .ops = &lc3_ops, }, #endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */ { .dir = BT_AUDIO_DIR_SINK, .codec = &lc3_codec, -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0u, 60u, 20000u, 40000u, - 20000u, 40000u), - .ops = &lc3_ops, -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */ }, }; -#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER || CONFIG_BT_AUDIO_BROADCAST_SINK */ #if defined(CONFIG_BT_AUDIO_UNICAST_CLIENT) static uint8_t stream_dir(const struct bt_audio_stream *stream) @@ -1476,11 +1468,16 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[]) return err; } -#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) || defined(CONFIG_BT_AUDIO_BROADCAST_SINK) - for (i = 0; i < ARRAY_SIZE(caps); i++) { - bt_audio_capability_register(&caps[i]); + if (IS_ENABLED(CONFIG_BT_AUDIO_UNICAST_SERVER)) { + bt_audio_unicast_server_register_cb(&unicast_server_cb); + } + + if (IS_ENABLED(CONFIG_BT_AUDIO_UNICAST_SERVER) || + IS_ENABLED(CONFIG_BT_AUDIO_BROADCAST_SINK)) { + for (i = 0; i < ARRAY_SIZE(caps); i++) { + bt_audio_capability_register(&caps[i]); + } } -#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SOURCE */ if (IS_ENABLED(CONFIG_BT_AUDIO_CAPABILITY)) { if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) { @@ -1628,10 +1625,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(audio_cmds, " [codec] [preset]", cmd_connect, 3, 2), #endif /* CONFIG_BT_AUDIO_UNICAST_CLIENT */ -#if defined(CONFIG_BT_AUDIO_UNICAST) - SHELL_CMD_ARG(select_unicast, NULL, "", - cmd_select_unicast, 2, 0), -#endif /* CONFIG_BT_AUDIO_UNICAST */ + SHELL_COND_CMD_ARG(CONFIG_BT_AUDIO_UNICAST, select_unicast, NULL, + "", cmd_select_unicast, 2, 0), SHELL_CMD_ARG(send, NULL, "Send to Audio Stream [data]", cmd_send, 1, 1), SHELL_COND_CMD_ARG(CONFIG_BT_AUDIO_CAPABILITY, set_location, NULL, diff --git a/tests/bluetooth/bsim_bt/bsim_test_audio/src/unicast_server_test.c b/tests/bluetooth/bsim_bt/bsim_test_audio/src/unicast_server_test.c index 34fee5ec19c8e..96d5d17d4f94a 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_audio/src/unicast_server_test.c +++ b/tests/bluetooth/bsim_bt/bsim_test_audio/src/unicast_server_test.c @@ -22,6 +22,9 @@ static struct bt_codec lc3_codec = static struct bt_audio_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT]; +static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, + 10, 40000, 40000, 40000, 40000); + /* TODO: Expand with BAP data */ static const struct bt_data unicast_server_ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), @@ -31,37 +34,47 @@ static const struct bt_data unicast_server_ad[] = { CREATE_FLAG(flag_connected); CREATE_FLAG(flag_stream_configured); -static struct bt_audio_stream *lc3_config(struct bt_conn *conn, - struct bt_audio_ep *ep, - enum bt_audio_dir dir, - struct bt_audio_capability *cap, - struct bt_codec *codec) +static struct bt_audio_stream *stream_alloc(void) { - printk("ASE Codec Config: conn %p ep %p dir %u, cap %p\n", - conn, ep, dir, cap); - - print_codec(codec); - for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { struct bt_audio_stream *stream = &streams[i]; - if (stream->conn == NULL) { - printk("ASE Codec Config stream %p\n", stream); - SET_FLAG(flag_stream_configured); + if (!stream->conn) { return stream; } } - FAIL("No streams available\n"); - return NULL; } -static int lc3_reconfig(struct bt_audio_stream *stream, - struct bt_audio_capability *cap, - struct bt_codec *codec) +static int lc3_config(struct bt_conn *conn, const struct bt_audio_ep *ep, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_audio_stream **stream, + struct bt_codec_qos_pref *const pref) { - printk("ASE Codec Reconfig: stream %p cap %p\n", stream, cap); + printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); + + print_codec(codec); + + *stream = stream_alloc(); + if (*stream == NULL) { + printk("No streams available\n"); + + return -ENOMEM; + } + + printk("ASE Codec Config stream %p\n", *stream); + + SET_FLAG(flag_stream_configured); + + *pref = qos_pref; + + return 0; +} + +static int lc3_reconfig(struct bt_audio_stream *stream, enum bt_audio_dir dir, + const struct bt_codec *codec, struct bt_codec_qos_pref *const pref) +{ + printk("ASE Codec Reconfig: stream %p\n", stream); print_codec(codec); @@ -69,7 +82,7 @@ static int lc3_reconfig(struct bt_audio_stream *stream, return -ENOEXEC; } -static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) +static int lc3_qos(struct bt_audio_stream *stream, const struct bt_codec_qos *qos) { printk("QoS: stream %p qos %p\n", stream, qos); @@ -78,8 +91,7 @@ static int lc3_qos(struct bt_audio_stream *stream, struct bt_codec_qos *qos) return 0; } -static int lc3_enable(struct bt_audio_stream *stream, - struct bt_codec_data *meta, +static int lc3_enable(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { printk("Enable: stream %p meta_count %zu\n", stream, meta_count); @@ -137,8 +149,7 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_audio_stream *stream, - struct bt_codec_data *meta, +static int lc3_metadata(struct bt_audio_stream *stream, const struct bt_codec_data *meta, size_t meta_count) { printk("Metadata: stream %p meta_count %zu\n", stream, meta_count); @@ -176,7 +187,7 @@ static int lc3_release(struct bt_audio_stream *stream) return 0; } -static struct bt_audio_capability_ops lc3_ops = { +static const struct bt_audio_unicast_server_cb unicast_server_cb = { .config = lc3_config, .reconfig = lc3_reconfig, .qos = lc3_qos, @@ -223,11 +234,7 @@ static void init(void) { static struct bt_audio_capability caps = { .dir = BT_AUDIO_DIR_SINK, - .pref = BT_AUDIO_CAPABILITY_PREF( - BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED, - BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000), .codec = &lc3_codec, - .ops = &lc3_ops, }; int err; @@ -239,6 +246,8 @@ static void init(void) printk("Bluetooth initialized\n"); + bt_audio_unicast_server_register_cb(&unicast_server_cb); + err = bt_audio_capability_register(&caps); if (err != 0) { FAIL("Failed to register capabilities: %d", err);