This is an automated email from the ASF dual-hosted git repository.

rymek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit 868ecb0bdbec073aa6e4830f1cab9da323740193
Author: Mariusz Skamra <[email protected]>
AuthorDate: Thu Jan 25 13:28:54 2024 +0100

    apps/btshell: Add Audio Broadcast Sink to shell application
    
    this extends the btshell application with Audio Broadcast Sink
    functionality.
---
 apps/btshell/src/btshell.h                         |   2 +
 apps/btshell/src/cmd.c                             |  86 ++-
 apps/btshell/src/cmd.h                             |   7 +
 apps/btshell/src/cmd_leaudio.c                     | 705 ++++++++++++++++++++-
 apps/btshell/src/cmd_leaudio.h                     |  20 +
 apps/btshell/src/main.c                            |   6 +
 apps/btshell/syscfg.yml                            |   3 +
 nimble/host/audio/targets/btshell_native/pkg.yml   |   1 +
 .../host/audio/targets/btshell_native/syscfg.yml   |   5 +-
 9 files changed, 830 insertions(+), 5 deletions(-)

diff --git a/apps/btshell/src/btshell.h b/apps/btshell/src/btshell.h
index c2a2eb3e..3d94c212 100644
--- a/apps/btshell/src/btshell.h
+++ b/apps/btshell/src/btshell.h
@@ -222,6 +222,8 @@ int btshell_broadcast_start(uint8_t adv_instance);
 int btshell_broadcast_stop(uint8_t adv_instance);
 #endif
 
+void btshell_leaudio_init(void);
+
 int btshell_gap_event(struct ble_gap_event *event, void *arg);
 void btshell_sync_stats(uint16_t handle);
 uint8_t btshell_get_default_own_addr_type(void);
diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c
index 50aac794..a9758e14 100644
--- a/apps/btshell/src/cmd.c
+++ b/apps/btshell/src/cmd.c
@@ -87,14 +87,28 @@ static const struct parse_arg_kv_pair cmd_peer_addr_types[] 
= {
     { NULL }
 };
 
-static const struct parse_arg_kv_pair cmd_addr_type[] = {
+const struct parse_arg_kv_pair cmd_addr_type[] = {
     { "public",     BLE_ADDR_PUBLIC },
     { "random",     BLE_ADDR_RANDOM },
     { NULL }
 };
 
+const char *
+cmd_addr_type_str(uint8_t type)
+{
+    const struct parse_arg_kv_pair *kvs = cmd_addr_type;
+    int i;
 
-static int
+    for (i = 0; kvs[i].key != NULL; i++) {
+        if (type == kvs[i].val) {
+            return kvs[i].key;
+        }
+    }
+
+    return "unknown";
+}
+
+int
 parse_dev_addr(const char *prefix, const struct parse_arg_kv_pair *addr_types,
                ble_addr_t *addr)
 {
@@ -152,6 +166,12 @@ parse_dev_addr(const char *prefix, const struct 
parse_arg_kv_pair *addr_types,
     return 0;
 }
 
+int
+cmd_parse_addr(const char *prefix, ble_addr_t *addr)
+{
+    return parse_dev_addr(prefix, cmd_addr_type, addr);
+}
+
 /*****************************************************************************
  * $advertise                                                                *
  *****************************************************************************/
@@ -4924,7 +4944,67 @@ static const struct shell_cmd btshell_commands[] = {
         .help = &leaudio_broadcast_stop_help,
 #endif
     },
-#endif /* BLE_ISO_BROADCAST_SOURCE */
+#endif
+#if MYNEWT_VAL(BLE_AUDIO_BROADCAST_SINK)
+    {
+        .sc_cmd = "broadcast-sink-start",
+        .sc_cmd_func = cmd_leaudio_broadcast_sink_start,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_broadcast_sink_start_help,
+#endif
+    },
+    {
+        .sc_cmd = "broadcast-sink-stop",
+        .sc_cmd_func = cmd_leaudio_broadcast_sink_stop,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_broadcast_sink_stop_help,
+#endif
+    },
+    {
+        .sc_cmd = "broadcast-sink-metadata",
+        .sc_cmd_func = cmd_leaudio_broadcast_sink_metadata_update,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_broadcast_sink_metadata_update_help,
+#endif
+    },
+#endif /* BLE_AUDIO_BROADCAST_SINK */
+#if MYNEWT_VAL(BLE_AUDIO_SCAN_DELEGATOR)
+    {
+        .sc_cmd = "scan-delegator-add",
+        .sc_cmd_func = cmd_leaudio_scan_delegator_receive_state_add,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_scan_delegator_receive_state_add_help,
+#endif
+    },
+    {
+        .sc_cmd = "scan-delegator-remove",
+        .sc_cmd_func = cmd_leaudio_scan_delegator_receive_state_remove,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_scan_delegator_receive_state_remove_help,
+#endif
+    },
+    {
+        .sc_cmd = "scan-delegator-set",
+        .sc_cmd_func = cmd_leaudio_scan_delegator_receive_state_set,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_scan_delegator_receive_state_set_help,
+#endif
+    },
+    {
+        .sc_cmd = "scan-delegator-get",
+        .sc_cmd_func = cmd_leaudio_scan_delegator_receive_state_get,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_scan_delegator_receive_state_get_help,
+#endif
+    },
+    {
+        .sc_cmd = "scan-delegator-show",
+        .sc_cmd_func = cmd_leaudio_scan_delegator_receive_state_show,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &cmd_leaudio_scan_delegator_receive_state_show_help,
+#endif
+    },
+#endif /* BLE_AUDIO_SCAN_DELEGATOR */
 #if MYNEWT_VAL(BLE_ISO)
 #if MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE)
     {
diff --git a/apps/btshell/src/cmd.h b/apps/btshell/src/cmd.h
index 1477ea85..c5532f34 100644
--- a/apps/btshell/src/cmd.h
+++ b/apps/btshell/src/cmd.h
@@ -30,6 +30,13 @@ int parse_eddystone_url(char *full_url, uint8_t *out_scheme, 
char *out_body,
 int cmd_parse_conn_start_end(uint16_t *out_conn, uint16_t *out_start,
                              uint16_t *out_end);
 
+int parse_dev_addr(const char *prefix, const struct parse_arg_kv_pair 
*addr_types,
+                   ble_addr_t *addr);
+
+int cmd_parse_addr(const char *prefix, ble_addr_t *addr);
+
+const char *cmd_addr_type_str(uint8_t type);
+
 void cmd_init(void);
 
 #endif
diff --git a/apps/btshell/src/cmd_leaudio.c b/apps/btshell/src/cmd_leaudio.c
index 2f31246c..cea206b6 100644
--- a/apps/btshell/src/cmd_leaudio.c
+++ b/apps/btshell/src/cmd_leaudio.c
@@ -20,9 +20,13 @@
 #include "cmd_leaudio.h"
 #include "btshell.h"
 #include "console/console.h"
+#include "shell/shell.h"
+#include "bsp/bsp.h"
 #include "errno.h"
 
-#if (MYNEWT_VAL(BLE_AUDIO))
+#define STR_NULL        "null"
+
+#if (MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE))
 #include "audio/ble_audio_broadcast_source.h"
 int
 cmd_leaudio_base_add(int argc, char **argv)
@@ -382,4 +386,703 @@ cmd_leaudio_broadcast_stop(int argc, char **argv)
 
     return btshell_broadcast_stop(adv_instance);
 }
+#endif /* BLE_ISO_BROADCAST_SOURCE */
+
+#if (MYNEWT_VAL(BLE_AUDIO_BROADCAST_SINK))
+#include "audio/ble_audio_broadcast_sink.h"
+
+#define BROADCAST_SINK_PA_SYNC_TIMEOUT_DEFAULT  0x07D0
+
+static int
+broadcast_sink_pa_sync_params_get(struct ble_gap_periodic_sync_params *params)
+{
+    params->skip = 0;
+    params->sync_timeout = BROADCAST_SINK_PA_SYNC_TIMEOUT_DEFAULT;
+    params->reports_disabled = false;
+
+    return 0;
+}
+
+static void
+codec_specific_config_printf(const struct ble_audio_codec_id *unused, const 
uint8_t *data,
+                             uint8_t len)
+{
+    console_printf("data=%p len=%u\n", data, len);
+}
+
+static void
+base_bis_printf(const struct ble_audio_codec_id *codec_id, const struct 
ble_audio_base_bis *bis)
+{
+    console_printf("BISCodecConfig:\n\t");
+    codec_specific_config_printf(codec_id,bis->codec_spec_config, 
bis->codec_spec_config_len);
+}
+
+static void
+metadata_printf(const uint8_t *data, uint8_t len)
+{
+    console_printf("data=%p len=%u\n", data, len);
+}
+
+static void
+base_subgroup_printf(uint8_t subgroup_index, const struct 
ble_audio_base_subgroup *subgroup)
+{
+    console_printf("subgroup_index=%u\n", subgroup_index);
+    console_printf("Codec ID:\n\tformat=0x%02x company_id=0x%04x 
vendor_specific=0x%02x\n",
+                   subgroup->codec_id.format, subgroup->codec_id.company_id,
+                   subgroup->codec_id.vendor_specific);
+    console_printf("SubgroupCodecConfig:\n\t");
+    codec_specific_config_printf(&subgroup->codec_id,
+                                 subgroup->codec_spec_config,
+                                 subgroup->codec_spec_config_len);
+    console_printf("Metadata:\n\t");
+    metadata_printf(subgroup->metadata, subgroup->metadata_len);
+}
+
+static int
+broadcast_sink_disc_start(const struct ble_gap_ext_disc_params *params)
+{
+    uint8_t own_addr_type;
+    int rc;
+
+    /* Figure out address to use while scanning. */
+    rc = ble_hs_id_infer_auto(0, &own_addr_type);
+    if (rc != 0) {
+        console_printf("determining own address type failed (%d)", rc);
+        assert(0);
+    }
+
+    rc = ble_gap_ext_disc(own_addr_type, 0, 0, 0, 0, 0, params, NULL, NULL, 
NULL);
+    if (rc != 0) {
+        console_printf("ext disc failed (%d)", rc);
+    }
+
+    return rc;
+}
+
+static int
+broadcast_sink_disc_stop(void)
+{
+    int rc;
+
+    rc = ble_gap_disc_cancel();
+    if (rc != 0) {
+        console_printf("disc cancel failed (%d)", rc);
+    }
+
+    return rc;
+}
+
+static int
+broadcast_sink_action_fn(struct ble_audio_broadcast_sink_action *action, void 
*arg)
+{
+    switch (action->type) {
+    case BLE_AUDIO_BROADCAST_SINK_ACTION_PA_SYNC:
+        console_printf("PA Sync:\n");
+        return broadcast_sink_pa_sync_params_get(action->pa_sync.out_params);
+    case BLE_AUDIO_BROADCAST_SINK_ACTION_BIG_SYNC:
+        console_printf("BIG Sync:\nsource_id=0x%02x iso_interval=0x%04x"
+                       " presentation_delay=%u[us]\n",
+                       action->big_sync.source_id, 
action->big_sync.iso_interval,
+                       action->big_sync.presentation_delay);
+        break;
+    case BLE_AUDIO_BROADCAST_SINK_ACTION_BIS_SYNC:
+        console_printf("BIS Sync:\n\tsource_id=0x%02x bis_index=0x%02x\n",
+                       action->bis_sync.source_id, 
action->bis_sync.bis->index);
+        base_subgroup_printf(action->bis_sync.subgroup_index, 
action->bis_sync.subgroup);
+        base_bis_printf(&action->bis_sync.subgroup->codec_id, 
action->bis_sync.bis);
+        return 0;
+    case BLE_AUDIO_BROADCAST_SINK_ACTION_DISC_START:
+        return broadcast_sink_disc_start(action->disc_start.params_preferred);
+    case BLE_AUDIO_BROADCAST_SINK_ACTION_DISC_STOP:
+        return broadcast_sink_disc_stop();
+    default:
+        assert(false);
+        return ENOTSUP;
+    }
+
+    return 0;
+}
+
+
+static const struct shell_param cmd_leaudio_broadcast_sink_start_params[] = {
+    {"source_id", "usage: =<UINT8>"},
+    {"broadcast_code", "usage: =[string], default: NULL"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_broadcast_sink_start_help = {
+    .summary = "Start audio Broadcast Sink",
+    .usage = NULL,
+    .params = cmd_leaudio_broadcast_sink_start_params
+};
+#endif
+
+int
+cmd_leaudio_broadcast_sink_start(int argc, char **argv)
+{
+    struct ble_audio_broadcast_sink_add_params params = {0};
+    char *broadcast_code;
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    source_id = parse_arg_uint8("source_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'source_id' parameter\n");
+        return rc;
+    }
+
+    broadcast_code = parse_arg_extract("broadcast_code");
+    if (broadcast_code != NULL) {
+        strncpy((char *)params.broadcast_code, broadcast_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+        params.broadcast_code_is_valid = true;
+    }
+
+    rc = ble_audio_broadcast_sink_start(source_id, &params);
+    if (rc != 0) {
+        console_printf("start failed (%d)\n", rc);
+    }
+
+    return rc;
+}
+
+static const struct shell_param cmd_leaudio_broadcast_sink_stop_params[] = {
+    {"source_id", "usage: =<UINT8>"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_broadcast_sink_stop_help = {
+    .summary = "Stop audio Broadcast Sink",
+    .usage = NULL,
+    .params = cmd_leaudio_broadcast_sink_stop_params
+};
+#endif
+
+int
+cmd_leaudio_broadcast_sink_stop(int argc, char **argv)
+{
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    source_id = parse_arg_uint8("source_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'source_id' parameter\n");
+        return rc;
+    }
+
+    rc = ble_audio_broadcast_sink_stop(source_id);
+    if (rc != 0) {
+        console_printf("stop failed (%d)\n", rc);
+    }
+
+    return rc;
+}
+
+static const struct shell_param 
cmd_leaudio_broadcast_sink_metadata_update_params[] = {
+    {"source_id", "usage: =<UINT8>"},
+    {"subgroup_index", "usage: =<UINT8>"},
+    {"metadata", "usage: =[XX:XX...]"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_broadcast_sink_metadata_update_help = {
+    .summary = "Update Broadcast Sink metadata",
+    .usage = NULL,
+    .params = cmd_leaudio_broadcast_sink_metadata_update_params
+};
 #endif
+
+int
+cmd_leaudio_broadcast_sink_metadata_update(int argc, char **argv)
+{
+    struct ble_audio_broadcast_sink_metadata_update_params params = {0};
+    static bssnz_t uint8_t metadata[UINT8_MAX];
+    unsigned int metadata_len;
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    source_id = parse_arg_uint8("source_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'source_id' parameter\n");
+        return rc;
+    }
+
+    params.subgroup_index = parse_arg_uint8("subgroup_index", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'subgroup_index' parameter\n");
+        return rc;
+    }
+
+    rc = parse_arg_byte_stream("metadata", UINT8_MAX, metadata, &metadata_len);
+    if (rc == 0) {
+        params.metadata = metadata;
+        params.metadata_length = metadata_len;
+    } else if (rc != ENOENT) {
+        console_printf("invalid 'metadata' parameter\n");
+        return rc;
+    }
+
+    rc = ble_audio_broadcast_sink_metadata_update(source_id, &params);
+    if (rc != 0) {
+        console_printf("metadata update failed (%d)\n", rc);
+    }
+
+    return rc;
+}
+
+static int
+broadcast_sink_audio_event_handler(struct ble_audio_event *event, void *arg)
+{
+    switch (event->type) {
+    case BLE_AUDIO_EVENT_BROADCAST_SINK_PA_SYNC_STATE:
+        console_printf("source_id=0x%02x PA sync: %s\n",
+                       event->broadcast_sink_pa_sync_state.source_id,
+                       ble_audio_broadcast_sink_sync_state_str(
+                               event->broadcast_sink_pa_sync_state.state));
+        break;
+    case BLE_AUDIO_EVENT_BROADCAST_SINK_BIS_SYNC_STATE:
+        console_printf("source_id=0x%02x bis_index=0x%02x BIS sync: %s\n",
+                       event->broadcast_sink_bis_sync_state.source_id,
+                       event->broadcast_sink_bis_sync_state.bis_index,
+                       ble_audio_broadcast_sink_sync_state_str(
+                               event->broadcast_sink_bis_sync_state.state));
+        if (event->broadcast_sink_bis_sync_state.state ==
+            BLE_AUDIO_BROADCAST_SINK_SYNC_STATE_ESTABLISHED) {
+            console_printf("conn_handle=0x%04x\n",
+                           event->broadcast_sink_bis_sync_state.conn_handle);
+        }
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+#endif /* BLE_AUDIO_BROADCAST_SINK */
+
+#if MYNEWT_VAL(BLE_AUDIO_SCAN_DELEGATOR)
+#include "audio/ble_audio_scan_delegator.h"
+
+static void
+scan_delegator_source_desc_printf(const struct 
ble_audio_scan_delegator_source_desc *source_desc)
+{
+    console_printf("broadcast_id=0x%6x adv_sid=%d adv_addr_type=%s adv_addr=",
+                   source_desc->broadcast_id, source_desc->adv_sid,
+                   cmd_addr_type_str(source_desc->addr.type));
+    print_addr(source_desc->addr.val);
+    console_printf("\n");
+}
+
+static void
+scan_delegator_sync_opt_printf(const struct ble_audio_scan_delegator_sync_opt 
*sync_opt)
+{
+    console_printf("pa_sync=%d pa_interval=0x%04x num_subgroups=%d",
+                   sync_opt->pa_sync, sync_opt->pa_interval, 
sync_opt->num_subgroups);
+    for (uint8_t i = 0; i < sync_opt->num_subgroups; i++) {
+        console_printf("\n\tbis_sync=0x%04x metadata_length=%d metadata=",
+                       sync_opt->subgroups[i].bis_sync, 
sync_opt->subgroups[i].metadata_length);
+        print_bytes(sync_opt->subgroups[i].metadata, 
sync_opt->subgroups[i].metadata_length);
+    }
+    console_printf("\n");
+}
+
+static int
+scan_delegator_pick_source_id_to_swap(uint8_t *out_source_id_to_swap)
+{
+    /* TODO: Add some logic here */
+    *out_source_id_to_swap = 0;
+
+    return 0;
+}
+
+static int
+scan_delegator_action_fn(struct ble_audio_scan_delegator_action *action, void 
*arg)
+{
+    switch (action->type) {
+    case BLE_AUDIO_SCAN_DELEGATOR_ACTION_SOURCE_ADD:
+        console_printf("Source Add:\nsource_id=%u\n", 
action->source_add.source_id);
+        scan_delegator_source_desc_printf(&action->source_add.source_desc);
+        scan_delegator_sync_opt_printf(&action->source_add.sync_opt);
+        if (action->source_add.out_source_id_to_swap == NULL) {
+            return 0;
+        } else {
+            return 
scan_delegator_pick_source_id_to_swap(action->source_add.out_source_id_to_swap);
+        }
+    case BLE_AUDIO_SCAN_DELEGATOR_ACTION_SOURCE_MODIFY:
+        console_printf("Source Modify:\nsource_id=%u\n", 
action->source_modify.source_id);
+        scan_delegator_sync_opt_printf(&action->source_modify.sync_opt);
+        break;
+    case BLE_AUDIO_SCAN_DELEGATOR_ACTION_SOURCE_REMOVE:
+        console_printf("Source Remove:\nsource_id=%u\n", 
action->source_remove.source_id);
+        break;
+    default:
+        assert(false);
+        return ENOTSUP;
+    }
+
+    return 0;
+}
+
+static const struct shell_param 
cmd_leaudio_scan_delegator_receive_state_add_params[] = {
+    {"addr_type", "usage: =[public|random], default: public"},
+    {"addr", "usage: =[XX:XX:XX:XX:XX:XX]"},
+    {"broadcast_id", "usage: =[0-0xFFFFFF]"},
+    {"adv_sid", "usage: =[UINT8], default: 0"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_scan_delegator_receive_state_add_help 
= {
+    .summary = "Add receive state",
+    .usage = NULL,
+    .params = cmd_leaudio_scan_delegator_receive_state_add_params
+};
+#endif /* SHELL_CMD_HELP */
+
+int
+cmd_leaudio_scan_delegator_receive_state_add(int argc, char **argv)
+{
+    struct ble_audio_scan_delegator_receive_state_add_params params = {0};
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = cmd_parse_addr(NULL, &params.source_desc.addr);
+    if (rc != 0) {
+        console_printf("invalid 'adv_addr' parameter\n");
+        return rc;
+    }
+
+    params.source_desc.broadcast_id = parse_arg_uint32("broadcast_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'broadcast_id' parameter\n");
+        return rc;
+    }
+
+    params.source_desc.adv_sid = parse_arg_uint8_dflt("adv_sid", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'adv_sid' parameter\n");
+        return rc;
+    }
+
+    rc = ble_audio_scan_delegator_receive_state_add(&params, &source_id);
+    if (rc != 0) {
+        console_printf("Failed to add receive state (%d)\n", rc);
+    } else {
+        console_printf("New source_id=%u created\n", source_id);
+    }
+
+    return rc;
+}
+
+static const struct shell_param 
cmd_leaudio_scan_delegator_receive_state_remove_params[] = {
+    {"source_id", "usage: =<UINT8>"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help 
cmd_leaudio_scan_delegator_receive_state_remove_help = {
+    .summary = "Remove receive state",
+    .usage = NULL,
+    .params = cmd_leaudio_scan_delegator_receive_state_remove_params
+};
+#endif /* SHELL_CMD_HELP */
+
+int
+cmd_leaudio_scan_delegator_receive_state_remove(int argc, char **argv)
+{
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    source_id = parse_arg_uint8("source_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'source_id' parameter\n");
+        return rc;
+    }
+
+    rc = ble_audio_scan_delegator_receive_state_remove(source_id);
+    if (rc != 0) {
+        console_printf("remove failed (%d)\n", rc);
+    }
+
+    return rc;
+}
+
+const struct parse_arg_kv_pair cmd_pa_sync_type[] = {
+    { "not_synced",    BLE_AUDIO_SCAN_DELEGATOR_PA_SYNC_STATE_NOT_SYNCED },
+    { "sync_info_req", BLE_AUDIO_SCAN_DELEGATOR_PA_SYNC_STATE_SYNC_INFO_REQ },
+    { "synced",        BLE_AUDIO_SCAN_DELEGATOR_PA_SYNC_STATE_SYNCED },
+    { "failed",        BLE_AUDIO_SCAN_DELEGATOR_PA_SYNC_STATE_ERROR },
+    { "no_past",       BLE_AUDIO_SCAN_DELEGATOR_PA_SYNC_STATE_NO_PAST },
+    { NULL }
+};
+
+const struct parse_arg_kv_pair cmd_big_enc_type[] = {
+    { "not_encrypted", BLE_AUDIO_SCAN_DELEGATOR_BIG_ENC_NONE },
+    { "code_req",      BLE_AUDIO_SCAN_DELEGATOR_BIG_ENC_BROADCAST_CODE_MISSING 
},
+    { "decrypting",    BLE_AUDIO_SCAN_DELEGATOR_BIG_ENC_DECRYPTING },
+    { "bad_code",      BLE_AUDIO_SCAN_DELEGATOR_BIG_ENC_BROADCAST_CODE_INVALID 
},
+    { NULL }
+};
+
+static const struct shell_param 
cmd_leaudio_scan_delegator_receive_state_set_params[] = {
+    {"source_id", "usage: =<UINT8>"},
+    {"pa_sync_state", "usage: 
=[not_synced|sync_info_req|synced|failed|no_past],"
+     " default: not_synced"},
+    {"big_enc", "usage: =[not_encrypted|code_req|decrypting|bad_code],"
+     " default: not_encrypted"},
+    {"bad_code", "usage: =[string], default: NULL"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_scan_delegator_receive_state_set_help 
= {
+    .summary = "Set receive state",
+    .usage = NULL,
+    .params = cmd_leaudio_scan_delegator_receive_state_set_params
+};
+#endif /* SHELL_CMD_HELP */
+
+int
+cmd_leaudio_scan_delegator_receive_state_set(int argc, char **argv)
+{
+    struct ble_audio_scan_delegator_receive_state state = {0};
+    char *bad_code;
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    source_id = parse_arg_uint8("source_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'source_id' parameter\n");
+        return rc;
+    }
+
+    state.pa_sync_state = parse_arg_kv_dflt("pa_sync_state", cmd_pa_sync_type,
+                                            
BLE_AUDIO_SCAN_DELEGATOR_PA_SYNC_STATE_NOT_SYNCED, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'pa_sync_state' parameter\n");
+        return rc;
+    }
+
+    state.big_enc = parse_arg_kv_dflt("big_enc", cmd_big_enc_type,
+                                      BLE_AUDIO_SCAN_DELEGATOR_BIG_ENC_NONE, 
&rc);
+    if (rc != 0) {
+        console_printf("invalid 'big_enc' parameter\n");
+        return rc;
+    }
+
+    bad_code = parse_arg_extract("bad_code");
+    if (bad_code != NULL) {
+        strncpy((char *)state.bad_code, bad_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+    }
+
+    /* TODO: initialize state.subgroups  */
+    state.num_subgroups = 0;
+
+    rc = ble_audio_scan_delegator_receive_state_set(source_id, &state);
+    if (rc != 0) {
+        console_printf("set failed (%d)\n", rc);
+    }
+
+    return rc;
+}
+
+static const char *
+pa_sync_type_str(enum ble_audio_scan_delegator_pa_sync_state pa_sync_state)
+{
+    for (size_t i = 0; i < ARRAY_SIZE(cmd_pa_sync_type); i++) {
+        if (cmd_pa_sync_type[i].val == pa_sync_state) {
+            return cmd_pa_sync_type[i].key;
+        }
+    }
+
+    return STR_NULL;
+}
+
+static const char *
+big_enc_type_str(enum ble_audio_scan_delegator_big_enc big_enc)
+{
+    for (size_t i = 0; i < ARRAY_SIZE(cmd_big_enc_type); i++) {
+        if (cmd_big_enc_type[i].val == big_enc) {
+            return cmd_big_enc_type[i].key;
+        }
+    }
+
+    return STR_NULL;
+}
+
+static void
+scan_delegator_receive_state_printf(const struct 
ble_audio_scan_delegator_receive_state *state)
+{
+    console_printf("pa_sync_state=%s big_enc=%s num_subgroups=%d",
+                   pa_sync_type_str(state->pa_sync_state), 
big_enc_type_str(state->big_enc),
+                   state->num_subgroups);
+
+    if (state->big_enc == 
BLE_AUDIO_SCAN_DELEGATOR_BIG_ENC_BROADCAST_CODE_INVALID) {
+        console_printf("bad_code=");
+        print_bytes(state->bad_code, sizeof(state->bad_code));
+        console_printf("\n");
+    }
+
+    for (uint8_t i = 0; i < state->num_subgroups; i++) {
+        console_printf("\n\tbis_sync=0x%04x metadata_length=%d metadata=",
+                       state->subgroups[i].bis_sync, 
state->subgroups[i].metadata_length);
+        print_bytes(state->subgroups[i].metadata, 
state->subgroups[i].metadata_length);
+        console_printf("\n");
+    }
+}
+
+static const struct shell_param 
cmd_leaudio_scan_delegator_receive_state_get_params[] = {
+    {"source_id", "usage: =<UINT8>"},
+    {NULL, NULL}
+};
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_scan_delegator_receive_state_get_help 
= {
+    .summary = "Get receive state",
+    .usage = NULL,
+    .params = cmd_leaudio_scan_delegator_receive_state_get_params
+};
+#endif /* SHELL_CMD_HELP */
+
+int
+cmd_leaudio_scan_delegator_receive_state_get(int argc, char **argv)
+{
+    struct ble_audio_scan_delegator_receive_state state = {0};
+    uint8_t source_id;
+    int rc;
+
+    rc = parse_arg_init(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    source_id = parse_arg_uint8("source_id", &rc);
+    if (rc != 0) {
+        console_printf("invalid 'source_id' parameter\n");
+        return rc;
+    }
+
+    rc = ble_audio_scan_delegator_receive_state_get(source_id, &state);
+    if (rc != 0) {
+        console_printf("get failed (%d)\n", rc);
+    } else {
+        console_printf("source_id=%u\n", source_id);
+        scan_delegator_receive_state_printf(&state);
+    }
+
+    return rc;
+}
+
+static int
+scan_delegator_receive_state_foreach_fn(struct 
ble_audio_scan_delegator_receive_state_entry *entry,
+                                        void *arg)
+{
+    console_printf("source_id=%u\n", entry->source_id);
+    scan_delegator_source_desc_printf(&entry->source_desc);
+    scan_delegator_receive_state_printf(&entry->state);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+const struct shell_cmd_help cmd_leaudio_scan_delegator_receive_state_show_help 
= {
+    .summary = "List receive states",
+    .usage = NULL,
+    .params = NULL
+};
+#endif /* SHELL_CMD_HELP */
+
+int
+cmd_leaudio_scan_delegator_receive_state_show(int argc, char **argv)
+{
+    uint8_t num_entries = 0;
+
+    
ble_audio_scan_delegator_receive_state_foreach(scan_delegator_receive_state_foreach_fn,
+                                                   &num_entries);
+    if (num_entries == 0) {
+        console_printf("No receive state\n");
+    }
+
+    return 0;
+}
+
+static int
+scan_delegator_audio_event_handler(struct ble_audio_event *event, void *arg)
+{
+    switch (event->type) {
+    case BLE_AUDIO_EVENT_BROADCAST_ANNOUNCEMENT:
+        console_printf("Broadcast Announcement\n");
+        console_printf("broadcast_id=0x%6x adv_sid=%d addr_type=%s addr=",
+                       event->broadcast_announcement.broadcast_id,
+                       event->broadcast_announcement.ext_disc->sid,
+                       
cmd_addr_type_str(event->broadcast_announcement.ext_disc->addr.type));
+        print_addr(event->broadcast_announcement.ext_disc->addr.val);
+        console_printf("\n");
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+#endif /* BLE_AUDIO_SCAN_DELEGATOR */
+
+void
+btshell_leaudio_init(void)
+{
+    int rc = 0;
+
+#if (MYNEWT_VAL(BLE_AUDIO_SCAN_DELEGATOR))
+    static struct ble_audio_event_listener scan_delegator_listener;
+
+    rc = ble_audio_scan_delegator_action_fn_set(scan_delegator_action_fn, 
NULL);
+    assert(rc == 0);
+
+    rc = ble_audio_event_listener_register(&scan_delegator_listener,
+                                           scan_delegator_audio_event_handler, 
NULL);
+    assert(rc == 0);
+#endif /* BLE_AUDIO_SCAN_DELEGATOR */
+
+#if (MYNEWT_VAL(BLE_AUDIO_BROADCAST_SINK))
+    static struct ble_audio_event_listener broadcast_sink_listener;
+
+    rc = ble_audio_broadcast_sink_cb_set(broadcast_sink_action_fn, NULL);
+    assert(rc == 0);
+
+    rc = ble_audio_event_listener_register(&broadcast_sink_listener,
+                                           broadcast_sink_audio_event_handler, 
NULL);
+#endif /* BLE_AUDIO_BROADCAST_SINK */
+    assert(rc == 0);
+}
diff --git a/apps/btshell/src/cmd_leaudio.h b/apps/btshell/src/cmd_leaudio.h
index 84fc4586..477b33a2 100644
--- a/apps/btshell/src/cmd_leaudio.h
+++ b/apps/btshell/src/cmd_leaudio.h
@@ -43,4 +43,24 @@ int cmd_leaudio_broadcast_update(int argc, char **argv);
 int cmd_leaudio_broadcast_start(int argc, char **argv);
 int cmd_leaudio_broadcast_stop(int argc, char **argv);
 
+extern const struct shell_cmd_help cmd_leaudio_broadcast_sink_start_help;
+extern const struct shell_cmd_help cmd_leaudio_broadcast_sink_stop_help;
+extern const struct shell_cmd_help 
cmd_leaudio_broadcast_sink_metadata_update_help;
+
+int cmd_leaudio_broadcast_sink_start(int argc, char **argv);
+int cmd_leaudio_broadcast_sink_stop(int argc, char **argv);
+int cmd_leaudio_broadcast_sink_metadata_update(int argc, char **argv);
+
+extern const struct shell_cmd_help 
cmd_leaudio_scan_delegator_receive_state_add_help;
+extern const struct shell_cmd_help 
cmd_leaudio_scan_delegator_receive_state_remove_help;
+extern const struct shell_cmd_help 
cmd_leaudio_scan_delegator_receive_state_set_help;
+extern const struct shell_cmd_help 
cmd_leaudio_scan_delegator_receive_state_get_help;
+extern const struct shell_cmd_help 
cmd_leaudio_scan_delegator_receive_state_show_help;
+
+int cmd_leaudio_scan_delegator_receive_state_add(int argc, char **argv);
+int cmd_leaudio_scan_delegator_receive_state_remove(int argc, char **argv);
+int cmd_leaudio_scan_delegator_receive_state_set(int argc, char **argv);
+int cmd_leaudio_scan_delegator_receive_state_get(int argc, char **argv);
+int cmd_leaudio_scan_delegator_receive_state_show(int argc, char **argv);
+
 #endif /* H_CMD_LEAUDIO_ */
diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c
index 0ba90ff1..72929276 100644
--- a/apps/btshell/src/main.c
+++ b/apps/btshell/src/main.c
@@ -2078,6 +2078,10 @@ btshell_ext_scan(uint8_t own_addr_type, uint16_t 
duration, uint16_t period,
                  const struct ble_gap_ext_disc_params *coded_params,
                  void *cb_args)
 {
+    struct btshell_scan_opts *scan_opts = cb_args;
+
+    console_printf("silent %d.", scan_opts->silent);
+
 #if !MYNEWT_VAL(BLE_EXT_ADV)
     console_printf("BLE extended advertising not supported.");
     console_printf(" Configure nimble host to enable it\n");
@@ -3143,6 +3147,8 @@ mynewt_main(int argc, char **argv)
 
     btshell_init_ext_adv_restart();
 
+    btshell_leaudio_init();
+
     while (1) {
         os_eventq_run(os_eventq_dflt_get());
     }
diff --git a/apps/btshell/syscfg.yml b/apps/btshell/syscfg.yml
index 091a2df0..3bdfb34a 100644
--- a/apps/btshell/syscfg.yml
+++ b/apps/btshell/syscfg.yml
@@ -50,3 +50,6 @@ syscfg.vals:
 
 syscfg.vals.BLE_MESH:
     MSYS_1_BLOCK_COUNT: 16
+
+syscfg.vals.BLE_AUDIO_BROADCAST_SINK:
+    BLE_AUDIO_BROADCAST_SINK_MAX: 1
diff --git a/nimble/host/audio/targets/btshell_native/pkg.yml 
b/nimble/host/audio/targets/btshell_native/pkg.yml
index 67eb2d6f..7c129c62 100644
--- a/nimble/host/audio/targets/btshell_native/pkg.yml
+++ b/nimble/host/audio/targets/btshell_native/pkg.yml
@@ -24,3 +24,4 @@ pkg.description: Target for native btshell application with 
LE Audio
 pkg.author: "Apache Mynewt <[email protected]>"
 pkg.homepage: "http://mynewt.apache.org/";
 pkg.deps:
+  - nimble/host/audio
diff --git a/nimble/host/audio/targets/btshell_native/syscfg.yml 
b/nimble/host/audio/targets/btshell_native/syscfg.yml
index e9db0070..3c04c0c1 100644
--- a/nimble/host/audio/targets/btshell_native/syscfg.yml
+++ b/nimble/host/audio/targets/btshell_native/syscfg.yml
@@ -30,7 +30,7 @@ syscfg.vals:
 
     # Disable security manager (pairing and bonding).
     BLE_SM_LEGACY: 0
-    BLE_SM_SC: 0
+    BLE_SM_SC: 1
 
     # Default task settings
     OS_MAIN_STACK_SIZE: 512
@@ -64,6 +64,9 @@ syscfg.vals:
     BLE_ISO_MAX_BIGS: 1
     BLE_ISO_MAX_BISES: 2
 
+    BLE_AUDIO_BROADCAST_SINK: 1
+    BLE_AUDIO_SCAN_DELEGATOR: 1
+
     CONSOLE_UART: 1
     CONSOLE_UART_BAUD: 1000000
     CONSOLE_STICKY_PROMPT: 1

Reply via email to