Dear all:
I wanted to config the broadcast name and broadcast code of broadcst audio source dynamically through the ble link.
I added the nus service to the broadcast audio source project.
When the program was running, it outputed an error:
I tried to increase the MAIN STACK SIZE to 4096, but it didn't help.
The main.c is listed as follow:
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include "streamctrl.h"
#include <zephyr/bluetooth/audio/audio.h>
#include <zephyr/kernel.h>
#include <zephyr/zbus/zbus.h>
#include "nrf5340_audio_common.h"
#include "nrf5340_audio_dk.h"
#include "broadcast_source.h"
#include "led.h"
#include "button_assignments.h"
#include "macros_common.h"
#include "audio_system.h"
#include "bt_mgmt.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL);
// Tommy add start
#include <bluetooth/services/nus.h>
#define BT_UUID_NUS_VAL \
BT_UUID_128_ENCODE(0x6e400001, 0xb5a3, 0xf393, 0xe0a9, 0xe50e24dcca9e)
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static const struct bt_data sd[] = {
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data,
uint16_t len)
{
int ret;
char addr[BT_ADDR_LE_STR_LEN] = {0};
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, ARRAY_SIZE(addr));
LOG_INF("Received data from: %s", addr);
LOG_HEXDUMP_INF(data, len, "NUS:");
ret = bt_nus_send(NULL, data, len);
if (ret != 0) {
LOG_WRN("Failed to send data over BLE connection!, ret:%d", ret);
}
}
static struct bt_nus_cb nus_cb = {
.received = bt_receive_cb,
};
// Tommy add end
ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE);
ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub);
ZBUS_CHAN_DECLARE(button_chan);
ZBUS_CHAN_DECLARE(le_audio_chan);
ZBUS_CHAN_DECLARE(bt_mgmt_chan);
ZBUS_CHAN_DECLARE(sdu_ref_chan);
ZBUS_OBS_DECLARE(sdu_ref_msg_listen);
static struct k_thread button_msg_sub_thread_data;
static struct k_thread le_audio_msg_sub_thread_data;
static k_tid_t button_msg_sub_thread_id;
static k_tid_t le_audio_msg_sub_thread_id;
K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE);
K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE);
static enum stream_state strm_state = STATE_PAUSED;
/* Function for handling all stream state changes */
static void stream_state_set(enum stream_state stream_state_new)
{
strm_state = stream_state_new;
}
/**
* @brief Handle button activity.
*/
static void button_msg_sub_thread(void)
{
int ret;
const struct zbus_channel *chan;
while (1) {
ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER);
ERR_CHK(ret);
struct button_msg msg;
ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS);
ERR_CHK(ret);
LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin,
msg.button_action);
if (msg.button_action != BUTTON_PRESS) {
LOG_WRN("Unhandled button action");
return;
}
switch (msg.button_pin) {
case BUTTON_PLAY_PAUSE:
if (strm_state == STATE_STREAMING) {
ret = broadcast_source_stop();
if (ret) {
LOG_WRN("Failed to stop broadcaster: %d", ret);
}
} else if (strm_state == STATE_PAUSED) {
ret = broadcast_source_start(NULL);
if (ret) {
LOG_WRN("Failed to start broadcaster: %d", ret);
}
} else {
LOG_WRN("In invalid state: %d", strm_state);
}
break;
case BUTTON_4:
if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) {
if (strm_state != STATE_STREAMING) {
LOG_WRN("Not in streaming state");
break;
}
ret = audio_system_encode_test_tone_step();
if (ret) {
LOG_WRN("Failed to play test tone, ret: %d", ret);
}
break;
}
break;
default:
LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin);
}
STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data);
}
}
/**
* @brief Handle Bluetooth LE audio events.
*/
static void le_audio_msg_sub_thread(void)
{
int ret;
const struct zbus_channel *chan;
while (1) {
struct le_audio_msg msg;
ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER);
ERR_CHK(ret);
LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state);
switch (msg.event) {
case LE_AUDIO_EVT_STREAMING:
LOG_DBG("LE audio evt streaming");
audio_system_encoder_start();
if (strm_state == STATE_STREAMING) {
LOG_DBG("Got streaming event in streaming state");
break;
}
audio_system_start();
stream_state_set(STATE_STREAMING);
ret = led_blink(LED_APP_1_BLUE);
ERR_CHK(ret);
break;
case LE_AUDIO_EVT_NOT_STREAMING:
LOG_DBG("LE audio evt not_streaming");
audio_system_encoder_stop();
if (strm_state == STATE_PAUSED) {
LOG_DBG("Got not_streaming event in paused state");
break;
}
stream_state_set(STATE_PAUSED);
audio_system_stop();
ret = led_on(LED_APP_1_BLUE);
ERR_CHK(ret);
break;
default:
LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event);
break;
}
STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data);
}
}
/**
* @brief Create zbus subscriber threads.
*
* @return 0 for success, error otherwise.
*/
static int zbus_subscribers_create(void)
{
int ret;
button_msg_sub_thread_id = k_thread_create(
&button_msg_sub_thread_data, button_msg_sub_thread_stack,
CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL,
NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT);
ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB");
if (ret) {
LOG_ERR("Failed to create button_msg thread");
return ret;
}
le_audio_msg_sub_thread_id = k_thread_create(
&le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack,
CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL,
NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT);
ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB");
if (ret) {
LOG_ERR("Failed to create le_audio_msg thread");
return ret;
}
ret = zbus_chan_add_obs(&sdu_ref_chan, &sdu_ref_msg_listen, ZBUS_ADD_OBS_TIMEOUT_MS);
if (ret) {
LOG_ERR("Failed to add timestamp listener");
return ret;
}
return 0;
}
/**
* @brief Zbus listener to receive events from bt_mgmt.
*
* @param[in] chan Zbus channel.
*
* @note Will in most cases be called from BT_RX context,
* so there should not be too much processing done here.
*/
static void bt_mgmt_evt_handler(const struct zbus_channel *chan)
{
int ret;
const struct bt_mgmt_msg *msg;
msg = zbus_chan_const_msg(chan);
switch (msg->event) {
case BT_MGMT_EXT_ADV_WITH_PA_READY:
LOG_INF("Ext adv ready");
ret = broadcast_source_start(msg->ext_adv);
if (ret) {
LOG_ERR("Failed to start broadcaster: %d", ret);
}
// Tommy add start
// int ret;
// ret = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
// ARRAY_SIZE(sd));
// if (ret) {
// LOG_ERR("Advertising failed to start (ret %d)", ret);
// }
// Tommy add end
break;
default:
LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event);
break;
}
}
ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler);
/**
* @brief Link zbus producers and observers.
*
* @return 0 for success, error otherwise.
*/
static int zbus_link_producers_observers(void)
{
int ret;
if (!IS_ENABLED(CONFIG_ZBUS)) {
return -ENOTSUP;
}
ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS);
if (ret) {
LOG_ERR("Failed to add button sub");
return ret;
}
ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS);
if (ret) {
LOG_ERR("Failed to add le_audio sub");
return ret;
}
ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS);
if (ret) {
LOG_ERR("Failed to add bt_mgmt listener");
return ret;
}
return 0;
}
uint8_t stream_state_get(void)
{
return strm_state;
}
void streamctrl_send(void const *const data, size_t size, uint8_t num_ch)
{
int ret;
static int prev_ret;
struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch};
if (strm_state == STATE_STREAMING) {
ret = broadcast_source_send(enc_audio);
if (ret != 0 && ret != prev_ret) {
if (ret == -ECANCELED) {
LOG_WRN("Sending operation cancelled");
} else {
LOG_WRN("Problem with sending LE audio data, ret: %d", ret);
}
}
prev_ret = ret;
}
}
int main(void)
{
int ret;
static const struct bt_data *ext_adv;
static const struct bt_data *per_adv;
LOG_DBG("nRF5340 APP core started");
ret = nrf5340_audio_dk_init();
ERR_CHK(ret);
ret = nrf5340_audio_common_init();
ERR_CHK(ret);
size_t ext_adv_size = 0;
size_t per_adv_size = 0;
ret = zbus_subscribers_create();
ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads");
ret = zbus_link_producers_observers();
ERR_CHK_MSG(ret, "Failed to link zbus producers and observers");
ret = broadcast_source_enable();
ERR_CHK_MSG(ret, "Failed to enable broadcaster");
ret = audio_system_config_set(
bt_audio_codec_cfg_freq_to_freq_hz(CONFIG_BT_AUDIO_PREF_SAMPLE_RATE_VALUE),
CONFIG_BT_AUDIO_BITRATE_BROADCAST_SRC, VALUE_NOT_SET);
ERR_CHK_MSG(ret, "Failed to set sample- and bitrate");
broadcast_source_adv_get(&ext_adv, &ext_adv_size, &per_adv, &per_adv_size);
ret = bt_mgmt_adv_start(ext_adv, ext_adv_size, per_adv, per_adv_size, false);
ERR_CHK_MSG(ret, "Failed to start advertiser");
// Tommy add start
ret = bt_nus_init(&nus_cb);
if (ret) {
LOG_ERR("Failed to initialize UART service (ret: %d)", ret);
return 0;
}
ret = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
ARRAY_SIZE(sd));
if (ret) {
LOG_ERR("Advertising failed to start (ret %d)", ret);
return 0;
}
// Tommy add end
return 0;
}
The .config file is listed as follow:
The ncs version is v2.6.0-rc2
Did i miss anything?
Thanks in advance.
Tommy.
Best Regards.