bluetooth: tester: Add support for BASS
Support for BAP/BASS and BASS test cases. Signed-off-by: Magdalena Kasenberg <magdalena.kasenberg@codecoup.pl>
This commit is contained in:
parent
5879803d15
commit
17b39baa61
8 changed files with 858 additions and 79 deletions
|
@ -31,6 +31,7 @@ CONFIG_BT_BAP_BROADCAST_SOURCE=y
|
||||||
CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2
|
CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2
|
||||||
CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=2
|
CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=2
|
||||||
CONFIG_BT_ISO_TX_BUF_COUNT=4
|
CONFIG_BT_ISO_TX_BUF_COUNT=4
|
||||||
|
CONFIG_BT_BAP_BROADCAST_ASSISTANT=y
|
||||||
|
|
||||||
# Broadcast Sink
|
# Broadcast Sink
|
||||||
CONFIG_BT_BAP_SCAN_DELEGATOR=y
|
CONFIG_BT_BAP_SCAN_DELEGATOR=y
|
||||||
|
@ -38,6 +39,14 @@ CONFIG_BT_BAP_BROADCAST_SINK=y
|
||||||
CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=2
|
CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=2
|
||||||
CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=2
|
CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=2
|
||||||
|
|
||||||
|
# BASS
|
||||||
|
CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y
|
||||||
|
CONFIG_BT_BAP_SCAN_DELEGATOR_MAX_METADATA_LEN=255
|
||||||
|
CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER=y
|
||||||
|
# BASS notifications need higher MTU
|
||||||
|
CONFIG_BT_L2CAP_TX_MTU=255
|
||||||
|
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||||
|
|
||||||
# ASCS
|
# ASCS
|
||||||
CONFIG_BT_ASCS_ASE_SNK_COUNT=2
|
CONFIG_BT_ASCS_ASE_SNK_COUNT=2
|
||||||
CONFIG_BT_ASCS_ASE_SRC_COUNT=2
|
CONFIG_BT_ASCS_ASE_SRC_COUNT=2
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* btp_bap.h - Bluetooth tester headers */
|
/* btp_ascs.h - Bluetooth tester headers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 Codecoup
|
* Copyright (c) 2023 Codecoup
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/audio/audio.h>
|
||||||
|
|
||||||
/* BAP commands */
|
/* BAP commands */
|
||||||
#define BTP_BAP_READ_SUPPORTED_COMMANDS 0x01
|
#define BTP_BAP_READ_SUPPORTED_COMMANDS 0x01
|
||||||
struct btp_bap_read_supported_commands_rp {
|
struct btp_bap_read_supported_commands_rp {
|
||||||
|
@ -50,32 +52,32 @@ struct btp_bap_broadcast_source_setup_cmd {
|
||||||
} __packed;
|
} __packed;
|
||||||
struct btp_bap_broadcast_source_setup_rp {
|
struct btp_bap_broadcast_source_setup_rp {
|
||||||
uint32_t gap_settings;
|
uint32_t gap_settings;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_SOURCE_RELEASE 0x05
|
#define BTP_BAP_BROADCAST_SOURCE_RELEASE 0x05
|
||||||
struct btp_bap_broadcast_source_release_cmd {
|
struct btp_bap_broadcast_source_release_cmd {
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_ADV_START 0x06
|
#define BTP_BAP_BROADCAST_ADV_START 0x06
|
||||||
struct btp_bap_broadcast_adv_start_cmd {
|
struct btp_bap_broadcast_adv_start_cmd {
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_ADV_STOP 0x07
|
#define BTP_BAP_BROADCAST_ADV_STOP 0x07
|
||||||
struct btp_bap_broadcast_adv_stop_cmd {
|
struct btp_bap_broadcast_adv_stop_cmd {
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_SOURCE_START 0x08
|
#define BTP_BAP_BROADCAST_SOURCE_START 0x08
|
||||||
struct btp_bap_broadcast_source_start_cmd {
|
struct btp_bap_broadcast_source_start_cmd {
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_SOURCE_STOP 0x09
|
#define BTP_BAP_BROADCAST_SOURCE_STOP 0x09
|
||||||
struct btp_bap_broadcast_source_stop_cmd {
|
struct btp_bap_broadcast_source_stop_cmd {
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_SINK_SETUP 0x0a
|
#define BTP_BAP_BROADCAST_SINK_SETUP 0x0a
|
||||||
|
@ -97,16 +99,81 @@ struct btp_bap_broadcast_scan_stop_cmd {
|
||||||
#define BTP_BAP_BROADCAST_SINK_SYNC 0x0e
|
#define BTP_BAP_BROADCAST_SINK_SYNC 0x0e
|
||||||
struct btp_bap_broadcast_sink_sync_cmd {
|
struct btp_bap_broadcast_sink_sync_cmd {
|
||||||
bt_addr_le_t address;
|
bt_addr_le_t address;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
uint8_t advertiser_sid;
|
uint8_t advertiser_sid;
|
||||||
uint16_t skip;
|
uint16_t skip;
|
||||||
uint16_t sync_timeout;
|
uint16_t sync_timeout;
|
||||||
|
uint8_t past_avail;
|
||||||
|
uint8_t src_id;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_BROADCAST_SINK_STOP 0x0f
|
#define BTP_BAP_BROADCAST_SINK_STOP 0x0f
|
||||||
struct btp_bap_broadcast_sink_stop_cmd {
|
struct btp_bap_broadcast_sink_stop_cmd {
|
||||||
bt_addr_le_t address;
|
bt_addr_le_t address;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_BROADCAST_SINK_BIS_SYNC 0x10
|
||||||
|
struct btp_bap_broadcast_sink_bis_sync_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
|
uint32_t requested_bis_sync;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_DISCOVER_SCAN_DELEGATORS 0x11
|
||||||
|
struct btp_bap_discover_scan_delegators_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_BROADCAST_ASSISTANT_SCAN_START 0x12
|
||||||
|
struct btp_bap_broadcast_assistant_scan_start_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_BROADCAST_ASSISTANT_SCAN_STOP 0x13
|
||||||
|
struct btp_bap_broadcast_assistant_scan_stop_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_ADD_BROADCAST_SRC 0x14
|
||||||
|
struct btp_bap_add_broadcast_src_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
bt_addr_le_t broadcaster_address;
|
||||||
|
uint8_t advertiser_sid;
|
||||||
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
|
uint8_t padv_sync;
|
||||||
|
uint16_t padv_interval;
|
||||||
|
uint8_t num_subgroups;
|
||||||
|
uint8_t subgroups[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_REMOVE_BROADCAST_SRC 0x15
|
||||||
|
struct btp_bap_remove_broadcast_src_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t src_id;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_MODIFY_BROADCAST_SRC 0x16
|
||||||
|
struct btp_bap_modify_broadcast_src_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t src_id;
|
||||||
|
uint8_t padv_sync;
|
||||||
|
uint16_t padv_interval;
|
||||||
|
uint8_t num_subgroups;
|
||||||
|
uint8_t subgroups[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_SET_BROADCAST_CODE 0x17
|
||||||
|
struct btp_bap_set_broadcast_code_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t src_id;
|
||||||
|
uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_SEND_PAST 0x18
|
||||||
|
struct btp_bap_send_past_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t src_id;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* BAP events */
|
/* BAP events */
|
||||||
|
@ -145,7 +212,7 @@ struct btp_bap_stream_received_ev {
|
||||||
#define BTP_BAP_EV_BAA_FOUND 0x84
|
#define BTP_BAP_EV_BAA_FOUND 0x84
|
||||||
struct btp_bap_baa_found_ev {
|
struct btp_bap_baa_found_ev {
|
||||||
bt_addr_le_t address;
|
bt_addr_le_t address;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
uint8_t advertiser_sid;
|
uint8_t advertiser_sid;
|
||||||
uint16_t padv_interval;
|
uint16_t padv_interval;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
@ -153,7 +220,7 @@ struct btp_bap_baa_found_ev {
|
||||||
#define BTP_BAP_EV_BIS_FOUND 0x85
|
#define BTP_BAP_EV_BIS_FOUND 0x85
|
||||||
struct btp_bap_bis_found_ev {
|
struct btp_bap_bis_found_ev {
|
||||||
bt_addr_le_t address;
|
bt_addr_le_t address;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
uint8_t presentation_delay[3];
|
uint8_t presentation_delay[3];
|
||||||
uint8_t subgroup_id;
|
uint8_t subgroup_id;
|
||||||
uint8_t bis_id;
|
uint8_t bis_id;
|
||||||
|
@ -167,15 +234,43 @@ struct btp_bap_bis_found_ev {
|
||||||
#define BTP_BAP_EV_BIS_SYNCED 0x86
|
#define BTP_BAP_EV_BIS_SYNCED 0x86
|
||||||
struct btp_bap_bis_syned_ev {
|
struct btp_bap_bis_syned_ev {
|
||||||
bt_addr_le_t address;
|
bt_addr_le_t address;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
uint8_t bis_id;
|
uint8_t bis_id;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_BAP_EV_BIS_STREAM_RECEIVED 0x87
|
#define BTP_BAP_EV_BIS_STREAM_RECEIVED 0x87
|
||||||
struct btp_bap_bis_stream_received_ev {
|
struct btp_bap_bis_stream_received_ev {
|
||||||
bt_addr_le_t address;
|
bt_addr_le_t address;
|
||||||
uint8_t broadcast_id[3];
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
uint8_t bis_id;
|
uint8_t bis_id;
|
||||||
uint8_t data_len;
|
uint8_t data_len;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_EV_SCAN_DELEGATOR_FOUND 0x88
|
||||||
|
struct btp_bap_scan_delegator_found_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_EV_BROADCAST_RECEIVE_STATE 0x89
|
||||||
|
struct btp_bap_broadcast_receive_state_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t src_id;
|
||||||
|
bt_addr_le_t broadcaster_address;
|
||||||
|
uint8_t advertiser_sid;
|
||||||
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
|
uint8_t pa_sync_state;
|
||||||
|
uint8_t big_encryption;
|
||||||
|
uint8_t num_subgroups;
|
||||||
|
uint8_t subgroups[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_BAP_EV_PA_SYNC_REQ 0x8a
|
||||||
|
struct btp_bap_pa_sync_req_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t src_id;
|
||||||
|
uint8_t advertiser_sid;
|
||||||
|
uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE];
|
||||||
|
uint8_t past_avail;
|
||||||
|
uint16_t pa_interval;
|
||||||
|
} __packed;
|
||||||
|
|
|
@ -456,5 +456,6 @@ int tester_gap_padv_configure(const struct bt_le_per_adv_param *param);
|
||||||
int tester_gap_padv_set_data(struct bt_data *per_ad, uint8_t ad_len);
|
int tester_gap_padv_set_data(struct bt_data *per_ad, uint8_t ad_len);
|
||||||
int tester_gap_padv_start(void);
|
int tester_gap_padv_start(void);
|
||||||
int tester_gap_padv_stop(void);
|
int tester_gap_padv_stop(void);
|
||||||
int tester_padv_create_sync(struct bt_le_per_adv_sync_param *create_params);
|
int tester_gap_padv_create_sync(struct bt_le_per_adv_sync_param *create_params);
|
||||||
|
int tester_gap_padv_stop_sync(void);
|
||||||
#endif /* defined(CONFIG_BT_EXT_ADV) */
|
#endif /* defined(CONFIG_BT_EXT_ADV) */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* btp_bap.h - Bluetooth tester headers */
|
/* btp_pacs.h - Bluetooth tester headers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 Codecoup
|
* Copyright (c) 2023 Codecoup
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <zephyr/bluetooth/audio/audio.h>
|
#include <zephyr/bluetooth/audio/audio.h>
|
||||||
#include <zephyr/bluetooth/audio/pacs.h>
|
#include <zephyr/bluetooth/audio/pacs.h>
|
||||||
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
|
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
|
||||||
|
#include <hci_core.h>
|
||||||
|
|
||||||
#include "bap_endpoint.h"
|
#include "bap_endpoint.h"
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
@ -118,7 +119,15 @@ static struct bt_bap_stream *sink_streams[MAX_STREAMS_COUNT];
|
||||||
/* A mask for the maximum BIS we can sync to. +1 since the BIS indexes start from 1. */
|
/* A mask for the maximum BIS we can sync to. +1 since the BIS indexes start from 1. */
|
||||||
static const uint32_t bis_index_mask = BIT_MASK(MAX_STREAMS_COUNT + 1);
|
static const uint32_t bis_index_mask = BIT_MASK(MAX_STREAMS_COUNT + 1);
|
||||||
static uint32_t bis_index_bitfield;
|
static uint32_t bis_index_bitfield;
|
||||||
|
static uint32_t requested_bis_sync;
|
||||||
#define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1)
|
#define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1)
|
||||||
|
#define SYNC_RETRY_COUNT 6 /* similar to retries for connections */
|
||||||
|
#define PA_SYNC_SKIP 5
|
||||||
|
/* Sample assumes that we only have a single Scan Delegator receive state */
|
||||||
|
static const struct bt_bap_scan_delegator_recv_state *sink_recv_state;
|
||||||
|
static const struct bt_bap_scan_delegator_recv_state *broadcast_recv_state;
|
||||||
|
static uint8_t sink_broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE];
|
||||||
|
static struct bt_bap_scan_delegator_subgroup delegator_subgroups[BROADCAST_SNK_SUBGROUP_CNT];
|
||||||
|
|
||||||
static bool print_cb(struct bt_data *data, void *user_data)
|
static bool print_cb(struct bt_data *data, void *user_data)
|
||||||
{
|
{
|
||||||
|
@ -237,10 +246,8 @@ static void btp_send_ascs_operation_completed_ev(struct bt_conn *conn, uint8_t a
|
||||||
uint8_t opcode, uint8_t status)
|
uint8_t opcode, uint8_t status)
|
||||||
{
|
{
|
||||||
struct btp_ascs_operation_completed_ev ev;
|
struct btp_ascs_operation_completed_ev ev;
|
||||||
struct bt_conn_info info;
|
|
||||||
|
|
||||||
(void)bt_conn_get_info(conn, &info);
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
bt_addr_le_copy(&ev.address, info.le.dst);
|
|
||||||
ev.ase_id = ase_id;
|
ev.ase_id = ase_id;
|
||||||
ev.opcode = opcode;
|
ev.opcode = opcode;
|
||||||
ev.status = status;
|
ev.status = status;
|
||||||
|
@ -252,10 +259,8 @@ static void btp_send_ascs_operation_completed_ev(struct bt_conn *conn, uint8_t a
|
||||||
static void btp_send_ascs_ase_state_changed_ev(struct bt_conn *conn, uint8_t ase_id, uint8_t state)
|
static void btp_send_ascs_ase_state_changed_ev(struct bt_conn *conn, uint8_t ase_id, uint8_t state)
|
||||||
{
|
{
|
||||||
struct btp_ascs_ase_state_changed_ev ev;
|
struct btp_ascs_ase_state_changed_ev ev;
|
||||||
struct bt_conn_info info;
|
|
||||||
|
|
||||||
(void)bt_conn_get_info(conn, &info);
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
bt_addr_le_copy(&ev.address, info.le.dst);
|
|
||||||
ev.ase_id = ase_id;
|
ev.ase_id = ase_id;
|
||||||
ev.state = state;
|
ev.state = state;
|
||||||
|
|
||||||
|
@ -487,18 +492,15 @@ static void btp_send_stream_received_ev(struct bt_conn *conn, struct bt_bap_ep *
|
||||||
uint8_t data_len, uint8_t *data)
|
uint8_t data_len, uint8_t *data)
|
||||||
{
|
{
|
||||||
struct btp_bap_stream_received_ev *ev;
|
struct btp_bap_stream_received_ev *ev;
|
||||||
struct bt_conn_info info;
|
|
||||||
|
|
||||||
LOG_DBG("Stream received, ep %d, dir %d, len %d", ep->status.id, ep->dir,
|
LOG_DBG("Stream received, ep %d, dir %d, len %d", ep->status.id, ep->dir,
|
||||||
data_len);
|
data_len);
|
||||||
|
|
||||||
(void)bt_conn_get_info(conn, &info);
|
|
||||||
|
|
||||||
net_buf_simple_init(rx_ev_buf, 0);
|
net_buf_simple_init(rx_ev_buf, 0);
|
||||||
|
|
||||||
ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev));
|
ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev));
|
||||||
|
|
||||||
bt_addr_le_copy(&ev->address, info.le.dst);
|
bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
ev->ase_id = ep->status.id;
|
ev->ase_id = ep->status.id;
|
||||||
ev->data_len = data_len;
|
ev->data_len = data_len;
|
||||||
|
@ -680,6 +682,7 @@ static void stream_started(struct bt_bap_stream *stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_stream->broadcast) {
|
if (a_stream->broadcast) {
|
||||||
|
a_stream->bis_synced = true;
|
||||||
btp_send_bis_syced_ev(&broadcaster_addr, broadcaster_broadcast_id,
|
btp_send_bis_syced_ev(&broadcaster_addr, broadcaster_broadcast_id,
|
||||||
a_stream->bis_id);
|
a_stream->bis_id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -701,6 +704,8 @@ static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
|
||||||
if (!a_stream->broadcast) {
|
if (!a_stream->broadcast) {
|
||||||
btp_send_ascs_operation_completed_ev(stream->conn, a_stream->ase_id,
|
btp_send_ascs_operation_completed_ev(stream->conn, a_stream->ase_id,
|
||||||
BT_ASCS_STOP_OP, BTP_STATUS_SUCCESS);
|
BT_ASCS_STOP_OP, BTP_STATUS_SUCCESS);
|
||||||
|
} else {
|
||||||
|
a_stream->bis_synced = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,10 +752,8 @@ static struct bt_bap_stream_ops stream_ops = {
|
||||||
static void btp_send_discovery_completed_ev(struct bt_conn *conn, uint8_t status)
|
static void btp_send_discovery_completed_ev(struct bt_conn *conn, uint8_t status)
|
||||||
{
|
{
|
||||||
struct btp_bap_discovery_completed_ev ev;
|
struct btp_bap_discovery_completed_ev ev;
|
||||||
struct bt_conn_info info;
|
|
||||||
|
|
||||||
(void) bt_conn_get_info(conn, &info);
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
bt_addr_le_copy(&ev.address, info.le.dst);
|
|
||||||
ev.status = status;
|
ev.status = status;
|
||||||
|
|
||||||
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_DISCOVERY_COMPLETED, &ev, sizeof(ev));
|
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_DISCOVERY_COMPLETED, &ev, sizeof(ev));
|
||||||
|
@ -807,11 +810,9 @@ static void btp_send_pac_codec_found_ev(struct bt_conn *conn,
|
||||||
enum bt_audio_dir dir)
|
enum bt_audio_dir dir)
|
||||||
{
|
{
|
||||||
struct btp_bap_codec_cap_found_ev ev;
|
struct btp_bap_codec_cap_found_ev ev;
|
||||||
struct bt_conn_info info;
|
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
|
|
||||||
(void)bt_conn_get_info(conn, &info);
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
bt_addr_le_copy(&ev.address, info.le.dst);
|
|
||||||
|
|
||||||
ev.dir = dir;
|
ev.dir = dir;
|
||||||
ev.coding_format = codec_cap->id;
|
ev.coding_format = codec_cap->id;
|
||||||
|
@ -838,10 +839,8 @@ static void btp_send_pac_codec_found_ev(struct bt_conn *conn,
|
||||||
static void btp_send_ase_found_ev(struct bt_conn *conn, struct bt_bap_ep *ep)
|
static void btp_send_ase_found_ev(struct bt_conn *conn, struct bt_bap_ep *ep)
|
||||||
{
|
{
|
||||||
struct btp_ascs_ase_found_ev ev;
|
struct btp_ascs_ase_found_ev ev;
|
||||||
struct bt_conn_info info;
|
|
||||||
|
|
||||||
(void)bt_conn_get_info(conn, &info);
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
bt_addr_le_copy(&ev.address, info.le.dst);
|
|
||||||
|
|
||||||
ev.ase_id = ep->status.id;
|
ev.ase_id = ep->status.id;
|
||||||
ev.dir = ep->dir;
|
ev.dir = ep->dir;
|
||||||
|
@ -1418,6 +1417,8 @@ static uint8_t broadcast_source_stop(const void *cmd, uint16_t cmd_len,
|
||||||
static int broadcast_sink_reset(void)
|
static int broadcast_sink_reset(void)
|
||||||
{
|
{
|
||||||
bis_index_bitfield = 0U;
|
bis_index_bitfield = 0U;
|
||||||
|
sink_recv_state = NULL;
|
||||||
|
(void)memset(sink_broadcast_code, 0, sizeof(sink_broadcast_code));
|
||||||
(void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr));
|
(void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr));
|
||||||
(void)memset(broadcaster, 0, sizeof(*broadcaster));
|
(void)memset(broadcaster, 0, sizeof(*broadcaster));
|
||||||
broadcaster_broadcast_id = INVALID_BROADCAST_ID;
|
broadcaster_broadcast_id = INVALID_BROADCAST_ID;
|
||||||
|
@ -1433,18 +1434,20 @@ static void btp_send_baa_found_ev(const bt_addr_le_t *address, uint32_t broadcas
|
||||||
bt_addr_le_copy(&ev.address, address);
|
bt_addr_le_copy(&ev.address, address);
|
||||||
sys_put_le24(broadcast_id, ev.broadcast_id);
|
sys_put_le24(broadcast_id, ev.broadcast_id);
|
||||||
ev.advertiser_sid = sid;
|
ev.advertiser_sid = sid;
|
||||||
ev.padv_interval = interval;
|
ev.padv_interval = sys_cpu_to_le16(interval);
|
||||||
|
|
||||||
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BAA_FOUND, &ev, sizeof(ev));
|
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BAA_FOUND, &ev, sizeof(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
|
static bool baa_check(struct bt_data *data, void *user_data)
|
||||||
{
|
{
|
||||||
const struct bt_le_scan_recv_info *info = user_data;
|
const struct bt_le_scan_recv_info *info = user_data;
|
||||||
char le_addr[BT_ADDR_LE_STR_LEN];
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||||
struct bt_uuid_16 adv_uuid;
|
struct bt_uuid_16 adv_uuid;
|
||||||
uint32_t broadcast_id;
|
uint32_t broadcast_id;
|
||||||
|
|
||||||
|
/* Parse the scanned Broadcast Audio Announcement */
|
||||||
|
|
||||||
if (data->type != BT_DATA_SVC_DATA16) {
|
if (data->type != BT_DATA_SVC_DATA16) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1465,8 +1468,8 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
|
||||||
|
|
||||||
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||||
|
|
||||||
LOG_DBG("Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X", broadcast_id,
|
LOG_DBG("Found BAA with ID 0x%06X, addr %s, sid 0x%02X, interval 0x%04X",
|
||||||
le_addr, info->sid);
|
broadcast_id, le_addr, info->sid, info->interval);
|
||||||
|
|
||||||
btp_send_baa_found_ev(info->addr, broadcast_id, info->sid, info->interval);
|
btp_send_baa_found_ev(info->addr, broadcast_id, info->sid, info->interval);
|
||||||
|
|
||||||
|
@ -1478,7 +1481,7 @@ static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct
|
||||||
{
|
{
|
||||||
/* If 0 there is no periodic advertising. */
|
/* If 0 there is no periodic advertising. */
|
||||||
if (info->interval != 0U) {
|
if (info->interval != 0U) {
|
||||||
bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info);
|
bt_data_parse(ad, baa_check, (void *)info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,8 +1529,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("Received BASE with %u subgroups from broadcast sink %p", base->subgroup_count,
|
LOG_DBG("Received BASE: broadcast sink %p subgroups %u", sink, base->subgroup_count);
|
||||||
sink);
|
|
||||||
|
|
||||||
for (size_t i = 0U; i < base->subgroup_count; i++) {
|
for (size_t i = 0U; i < base->subgroup_count; i++) {
|
||||||
for (size_t j = 0U; j < base->subgroups[i].bis_count; j++) {
|
for (size_t j = 0U; j < base->subgroups[i].bis_count; j++) {
|
||||||
|
@ -1546,15 +1548,29 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap
|
||||||
}
|
}
|
||||||
|
|
||||||
bis_index_bitfield = base_bis_index_bitfield & bis_index_mask;
|
bis_index_bitfield = base_bis_index_bitfield & bis_index_mask;
|
||||||
|
LOG_DBG("bis_index_bitfield 0x%08x", bis_index_bitfield);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted)
|
static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
uint32_t index_bitfield;
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("PA found, encrypted %d, requested_bis_sync %d", encrypted, requested_bis_sync);
|
||||||
|
|
||||||
err = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfield, sink_streams, NULL);
|
if (encrypted) {
|
||||||
|
/* Wait for Set Broadcast Code and start sync at broadcast_code_cb */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requested_bis_sync) {
|
||||||
|
/* No sync with any BIS was requested yet */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_bitfield = bis_index_bitfield & requested_bis_sync;
|
||||||
|
err = bt_bap_broadcast_sink_sync(broadcast_sink, index_bitfield, sink_streams,
|
||||||
|
sink_broadcast_code);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
LOG_DBG("Unable to sync to broadcast source: %d", err);
|
LOG_DBG("Unable to sync to broadcast source: %d", err);
|
||||||
}
|
}
|
||||||
|
@ -1565,21 +1581,36 @@ static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = {
|
||||||
.syncable = syncable_cb,
|
.syncable = syncable_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void pa_timer_handler(struct k_work *work)
|
||||||
|
{
|
||||||
|
if (broadcast_recv_state != NULL) {
|
||||||
|
enum bt_bap_pa_state pa_state;
|
||||||
|
|
||||||
|
if (broadcast_recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) {
|
||||||
|
pa_state = BT_BAP_PA_STATE_NO_PAST;
|
||||||
|
} else {
|
||||||
|
pa_state = BT_BAP_PA_STATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_bap_scan_delegator_set_pa_state(broadcast_recv_state->src_id,
|
||||||
|
pa_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("PA timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
static K_WORK_DELAYABLE_DEFINE(pa_timer, pa_timer_handler);
|
||||||
|
|
||||||
static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync,
|
static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync,
|
||||||
struct bt_le_per_adv_sync_synced_info *info)
|
struct bt_le_per_adv_sync_synced_info *info)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct bt_le_per_adv_sync *pa_sync;
|
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("Sync info: service_data 0x%04X", info->service_data);
|
||||||
|
|
||||||
pa_sync = tester_gap_padv_get();
|
k_work_cancel_delayable(&pa_timer);
|
||||||
|
|
||||||
if (sync != pa_sync) {
|
err = bt_bap_broadcast_sink_create(sync, broadcaster_broadcast_id, &broadcast_sink);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = bt_bap_broadcast_sink_create(pa_sync, broadcaster_broadcast_id, &broadcast_sink);
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
LOG_DBG("Failed to create broadcast sink: ID 0x%06X, err %d",
|
LOG_DBG("Failed to create broadcast sink: ID 0x%06X, err %d",
|
||||||
broadcaster_broadcast_id, err);
|
broadcaster_broadcast_id, err);
|
||||||
|
@ -1590,6 +1621,203 @@ static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = {
|
||||||
.synced = bap_pa_sync_synced_cb,
|
.synced = bap_pa_sync_synced_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void btp_send_pas_sync_req_ev(struct bt_conn *conn, uint8_t src_id,
|
||||||
|
uint8_t advertiser_sid, uint32_t broadcast_id,
|
||||||
|
bool past_avail, uint16_t pa_interval)
|
||||||
|
{
|
||||||
|
struct btp_bap_pa_sync_req_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
ev.src_id = src_id;
|
||||||
|
ev.advertiser_sid = advertiser_sid;
|
||||||
|
sys_put_le24(broadcast_id, ev.broadcast_id);
|
||||||
|
ev.past_avail = past_avail;
|
||||||
|
ev.pa_interval = sys_cpu_to_le16(pa_interval);
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_PA_SYNC_REQ, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btp_send_scan_delegator_found_ev(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
struct btp_bap_scan_delegator_found_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_SCAN_DELEGATOR_FOUND, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btp_send_broadcast_receive_state_ev(struct bt_conn *conn,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *state)
|
||||||
|
{
|
||||||
|
struct btp_bap_broadcast_receive_state_ev *ev;
|
||||||
|
size_t len;
|
||||||
|
uint8_t *ptr;
|
||||||
|
|
||||||
|
tester_rsp_buffer_lock();
|
||||||
|
tester_rsp_buffer_allocate(sizeof(*ev) + BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS *
|
||||||
|
sizeof(struct bt_bap_scan_delegator_subgroup), (uint8_t **)&ev);
|
||||||
|
|
||||||
|
if (conn) {
|
||||||
|
bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn));
|
||||||
|
} else {
|
||||||
|
(void)memset(&ev->address, 0, sizeof(ev->address));
|
||||||
|
}
|
||||||
|
|
||||||
|
ev->src_id = state->src_id;
|
||||||
|
bt_addr_le_copy(&ev->broadcaster_address, &state->addr);
|
||||||
|
ev->advertiser_sid = state->adv_sid;
|
||||||
|
sys_put_le24(state->broadcast_id, ev->broadcast_id);
|
||||||
|
ev->pa_sync_state = state->pa_sync_state;
|
||||||
|
ev->big_encryption = state->encrypt_state;
|
||||||
|
ev->num_subgroups = state->num_subgroups;
|
||||||
|
|
||||||
|
ptr = ev->subgroups;
|
||||||
|
for (uint8_t i = 0; i < ev->num_subgroups; i++) {
|
||||||
|
const struct bt_bap_scan_delegator_subgroup *subgroup = &state->subgroups[i];
|
||||||
|
|
||||||
|
sys_put_le32(subgroup->bis_sync >> 1, ptr);
|
||||||
|
ptr += sizeof(subgroup->bis_sync);
|
||||||
|
*ptr = subgroup->metadata_len;
|
||||||
|
ptr += sizeof(subgroup->metadata_len);
|
||||||
|
memcpy(ptr, subgroup->metadata, subgroup->metadata_len);
|
||||||
|
ptr += subgroup->metadata_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(*ev) + ptr - ev->subgroups;
|
||||||
|
tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BROADCAST_RECEIVE_STATE, ev, len);
|
||||||
|
|
||||||
|
tester_rsp_buffer_free();
|
||||||
|
tester_rsp_buffer_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pa_sync_past(struct bt_conn *conn, uint16_t sync_timeout)
|
||||||
|
{
|
||||||
|
struct bt_le_per_adv_sync_transfer_param param = { 0 };
|
||||||
|
int err;
|
||||||
|
|
||||||
|
param.skip = PA_SYNC_SKIP;
|
||||||
|
param.timeout = sync_timeout;
|
||||||
|
|
||||||
|
err = bt_le_per_adv_sync_transfer_subscribe(conn, ¶m);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Could not do PAST subscribe: %d", err);
|
||||||
|
} else {
|
||||||
|
LOG_DBG("Syncing with PAST: %d", err);
|
||||||
|
(void)k_work_reschedule(&pa_timer, K_MSEC(param.timeout * 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pa_sync_req_cb(struct bt_conn *conn,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *recv_state,
|
||||||
|
bool past_avail, uint16_t pa_interval)
|
||||||
|
{
|
||||||
|
LOG_DBG("sync state %d ", recv_state->pa_sync_state);
|
||||||
|
|
||||||
|
sink_recv_state = recv_state;
|
||||||
|
broadcast_recv_state = recv_state;
|
||||||
|
|
||||||
|
btp_send_pas_sync_req_ev(conn, recv_state->src_id, recv_state->adv_sid,
|
||||||
|
recv_state->broadcast_id, past_avail, pa_interval);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pa_sync_term_req_cb(struct bt_conn *conn,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *recv_state)
|
||||||
|
{
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
sink_recv_state = recv_state;
|
||||||
|
|
||||||
|
tester_gap_padv_stop_sync();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void broadcast_code_cb(struct bt_conn *conn,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *recv_state,
|
||||||
|
const uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE])
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
uint32_t index_bitfield;
|
||||||
|
|
||||||
|
LOG_DBG("Broadcast code received for %p", recv_state);
|
||||||
|
|
||||||
|
sink_recv_state = recv_state;
|
||||||
|
|
||||||
|
(void)memcpy(sink_broadcast_code, broadcast_code, BT_AUDIO_BROADCAST_CODE_SIZE);
|
||||||
|
|
||||||
|
if (!requested_bis_sync) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_bitfield = bis_index_bitfield & requested_bis_sync;
|
||||||
|
err = bt_bap_broadcast_sink_sync(broadcast_sink, index_bitfield, sink_streams,
|
||||||
|
sink_broadcast_code);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Unable to sync to broadcast source: %d", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bis_sync_req_cb(struct bt_conn *conn,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *recv_state,
|
||||||
|
const uint32_t bis_sync_req[BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS])
|
||||||
|
{
|
||||||
|
bool bis_synced = false;
|
||||||
|
|
||||||
|
LOG_DBG("BIS sync request received for %p: 0x%08x", recv_state, bis_sync_req[0]);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_STREAMS_COUNT; i++) {
|
||||||
|
if (broadcaster->streams[i].bis_synced) {
|
||||||
|
bis_synced = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only care about a single subgroup in this sample */
|
||||||
|
if (bis_synced) {
|
||||||
|
/* If the BIS sync request is received while we are already
|
||||||
|
* synced, it means that the requested BIS sync has changed.
|
||||||
|
*/
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* The stream stopped callback will be called as part of this,
|
||||||
|
* and we do not need to wait for any events from the
|
||||||
|
* controller. Thus, when this returns, the `bis_synced`
|
||||||
|
* is back to false.
|
||||||
|
*/
|
||||||
|
err = bt_bap_broadcast_sink_stop(broadcast_sink);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Failed to stop Broadcast Sink: %d", err);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requested_bis_sync = bis_sync_req[0];
|
||||||
|
broadcaster_broadcast_id = recv_state->broadcast_id;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_state_updated_cb(struct bt_conn *conn,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *recv_state)
|
||||||
|
{
|
||||||
|
LOG_DBG("Receive state with ID %u updated", recv_state->src_id);
|
||||||
|
|
||||||
|
btp_send_broadcast_receive_state_ev(conn, recv_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_bap_scan_delegator_cb scan_delegator_cbs = {
|
||||||
|
.recv_state_updated = recv_state_updated_cb,
|
||||||
|
.pa_sync_req = pa_sync_req_cb,
|
||||||
|
.pa_sync_term_req = pa_sync_term_req_cb,
|
||||||
|
.broadcast_code = broadcast_code_cb,
|
||||||
|
.bis_sync_req = bis_sync_req_cb,
|
||||||
|
};
|
||||||
|
|
||||||
static uint8_t broadcast_sink_setup(const void *cmd, uint16_t cmd_len,
|
static uint8_t broadcast_sink_setup(const void *cmd, uint16_t cmd_len,
|
||||||
void *rsp, uint16_t *rsp_len)
|
void *rsp, uint16_t *rsp_len)
|
||||||
{
|
{
|
||||||
|
@ -1608,8 +1836,14 @@ static uint8_t broadcast_sink_setup(const void *cmd, uint16_t cmd_len,
|
||||||
sink_streams[i]->ops = &stream_ops;
|
sink_streams[i]->ops = &stream_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For Scan Delegator role */
|
||||||
|
bt_bap_scan_delegator_register_cb(&scan_delegator_cbs);
|
||||||
|
|
||||||
|
/* For Broadcast Sink role */
|
||||||
bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs);
|
bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs);
|
||||||
bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb);
|
bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb);
|
||||||
|
|
||||||
|
/* For Broadcast Sink or Broadcast Assistant role */
|
||||||
bt_le_scan_cb_register(&bap_scan_cb);
|
bt_le_scan_cb_register(&bap_scan_cb);
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
return BTP_STATUS_SUCCESS;
|
||||||
|
@ -1668,35 +1902,36 @@ static uint8_t broadcast_sink_sync(const void *cmd, uint16_t cmd_len,
|
||||||
void *rsp, uint16_t *rsp_len)
|
void *rsp, uint16_t *rsp_len)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct bt_conn *conn;
|
||||||
const struct btp_bap_broadcast_sink_sync_cmd *cp = cmd;
|
const struct btp_bap_broadcast_sink_sync_cmd *cp = cmd;
|
||||||
struct bt_le_per_adv_sync_param create_params = {0};
|
struct bt_le_per_adv_sync_param create_params = {0};
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
/* Sink Sync steps:
|
|
||||||
* 1. bt_le_per_adv_sync_create()
|
|
||||||
* 2. bap_pa_sync_synced_cb()
|
|
||||||
* 3. bt_bap_broadcast_sink_create()
|
|
||||||
* 4. - base_recv_cb()
|
|
||||||
* - syncable_cb()
|
|
||||||
* - broadcast_code_cb() <- only with scan delegator
|
|
||||||
* - bis_sync_req_cb() <- only for scan delegator
|
|
||||||
* 5. bt_bap_broadcast_sink_sync()
|
|
||||||
* 6. stream_started()
|
|
||||||
* 7. stream_recv_cb()
|
|
||||||
* 8. bap_pa_sync_terminated_cb()
|
|
||||||
* 9. stream_stopped_cb()
|
|
||||||
*/
|
|
||||||
|
|
||||||
broadcaster_broadcast_id = sys_get_le24(cp->broadcast_id);
|
broadcaster_broadcast_id = sys_get_le24(cp->broadcast_id);
|
||||||
bt_addr_le_copy(&broadcaster_addr, &cp->address);
|
bt_addr_le_copy(&broadcaster_addr, &cp->address);
|
||||||
bt_addr_le_copy(&create_params.addr, &cp->address);
|
|
||||||
create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE;
|
|
||||||
create_params.sid = cp->advertiser_sid;
|
|
||||||
create_params.skip = cp->skip;
|
|
||||||
create_params.timeout = cp->sync_timeout;
|
|
||||||
|
|
||||||
err = tester_padv_create_sync(&create_params);
|
if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER) && cp->past_avail) {
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_scan_delegator_set_pa_state(cp->src_id, BT_BAP_PA_STATE_INFO_REQ);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Failed to set INFO_REQ state: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pa_sync_past(conn, cp->sync_timeout);
|
||||||
|
} else {
|
||||||
|
bt_addr_le_copy(&create_params.addr, &cp->address);
|
||||||
|
create_params.options = 0;
|
||||||
|
create_params.sid = cp->advertiser_sid;
|
||||||
|
create_params.skip = cp->skip;
|
||||||
|
create_params.timeout = cp->sync_timeout;
|
||||||
|
err = tester_gap_padv_create_sync(&create_params);
|
||||||
|
}
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return BTP_STATUS_FAILED;
|
return BTP_STATUS_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -1711,6 +1946,8 @@ static uint8_t broadcast_sink_stop(const void *cmd, uint16_t cmd_len,
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
|
requested_bis_sync = 0;
|
||||||
|
|
||||||
err = bt_bap_broadcast_sink_stop(broadcast_sink);
|
err = bt_bap_broadcast_sink_stop(broadcast_sink);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
LOG_DBG("Unable to sync to broadcast source: %d", err);
|
LOG_DBG("Unable to sync to broadcast source: %d", err);
|
||||||
|
@ -1718,6 +1955,368 @@ static uint8_t broadcast_sink_stop(const void *cmd, uint16_t cmd_len,
|
||||||
return BTP_STATUS_FAILED;
|
return BTP_STATUS_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = tester_gap_padv_stop_sync();
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Failed to stop PA sync, %d", err);
|
||||||
|
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_sink_bis_sync(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
const struct btp_bap_broadcast_sink_bis_sync_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
if (cp->requested_bis_sync == BT_BAP_BIS_SYNC_NO_PREF) {
|
||||||
|
requested_bis_sync = sys_le32_to_cpu(cp->requested_bis_sync);
|
||||||
|
} else {
|
||||||
|
/* For semantic purposes Zephyr API uses BIS Index bitfield
|
||||||
|
* where BIT(1) means BIS Index 1
|
||||||
|
*/
|
||||||
|
requested_bis_sync = sys_le32_to_cpu(cp->requested_bis_sync) << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_sink_sync(broadcast_sink, requested_bis_sync, sink_streams,
|
||||||
|
sink_broadcast_code);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Unable to sync to BISes, req_bis_sync %d, err %d", requested_bis_sync,
|
||||||
|
err);
|
||||||
|
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_discover_cb(struct bt_conn *conn, int err,
|
||||||
|
uint8_t recv_state_count)
|
||||||
|
{
|
||||||
|
LOG_DBG("err %d", err);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("BASS discover failed (%d)", err);
|
||||||
|
} else {
|
||||||
|
LOG_DBG("BASS discover done with %u recv states", recv_state_count);
|
||||||
|
|
||||||
|
btp_send_scan_delegator_found_ev(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_scan_cb(const struct bt_le_scan_recv_info *info,
|
||||||
|
uint32_t broadcast_id)
|
||||||
|
{
|
||||||
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||||
|
LOG_DBG("[DEVICE]: %s, broadcast_id 0x%06X, interval (ms) %u), SID 0x%x, RSSI %i", le_addr,
|
||||||
|
broadcast_id, BT_GAP_PER_ADV_INTERVAL_TO_MS(info->interval), info->sid, info->rssi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_recv_state_cb(struct bt_conn *conn, int err,
|
||||||
|
const struct bt_bap_scan_delegator_recv_state *state)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
|
||||||
|
if (err != 0 || state == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btp_send_broadcast_receive_state_ev(conn, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, int err,
|
||||||
|
uint8_t src_id)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_scan_start_cb(struct bt_conn *conn, int err)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_scan_stop_cb(struct bt_conn *conn, int err)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_add_src_cb(struct bt_conn *conn, int err)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_mod_src_cb(struct bt_conn *conn, int err)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_broadcast_code_cb(struct bt_conn *conn, int err)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bap_broadcast_assistant_rem_src_cb(struct bt_conn *conn, int err)
|
||||||
|
{
|
||||||
|
LOG_DBG("err: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_bap_broadcast_assistant_cb broadcast_assistant_cb = {
|
||||||
|
.discover = bap_broadcast_assistant_discover_cb,
|
||||||
|
.scan = bap_broadcast_assistant_scan_cb,
|
||||||
|
.recv_state = bap_broadcast_assistant_recv_state_cb,
|
||||||
|
.recv_state_removed = bap_broadcast_assistant_recv_state_removed_cb,
|
||||||
|
.scan_start = bap_broadcast_assistant_scan_start_cb,
|
||||||
|
.scan_stop = bap_broadcast_assistant_scan_stop_cb,
|
||||||
|
.add_src = bap_broadcast_assistant_add_src_cb,
|
||||||
|
.mod_src = bap_broadcast_assistant_mod_src_cb,
|
||||||
|
.broadcast_code = bap_broadcast_assistant_broadcast_code_cb,
|
||||||
|
.rem_src = bap_broadcast_assistant_rem_src_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t broadcast_discover_scan_delegators(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_discover_scan_delegators_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_discover(conn);
|
||||||
|
if (err != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_scan_start(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_broadcast_assistant_scan_start_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_scan_start(conn, true);
|
||||||
|
if (err != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_scan_stop(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_broadcast_assistant_scan_stop_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_scan_stop(conn);
|
||||||
|
if (err != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_add_src(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
const uint8_t *ptr;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_add_broadcast_src_cmd *cp = cmd;
|
||||||
|
struct bt_bap_broadcast_assistant_add_src_param param = { 0 };
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(delegator_subgroups, 0, sizeof(delegator_subgroups));
|
||||||
|
bt_addr_le_copy(¶m.addr, &cp->broadcaster_address);
|
||||||
|
param.adv_sid = cp->advertiser_sid;
|
||||||
|
param.pa_sync = cp->padv_sync > 0 ? true : false;
|
||||||
|
param.broadcast_id = sys_get_le24(cp->broadcast_id);
|
||||||
|
param.pa_interval = sys_le16_to_cpu(cp->padv_interval);
|
||||||
|
param.num_subgroups = MIN(cp->num_subgroups, BROADCAST_SNK_SUBGROUP_CNT);
|
||||||
|
param.subgroups = delegator_subgroups;
|
||||||
|
|
||||||
|
ptr = cp->subgroups;
|
||||||
|
for (uint8_t i = 0; i < param.num_subgroups; i++) {
|
||||||
|
struct bt_bap_scan_delegator_subgroup *subgroup = &delegator_subgroups[i];
|
||||||
|
|
||||||
|
subgroup->bis_sync = sys_get_le32(ptr);
|
||||||
|
ptr += sizeof(subgroup->bis_sync);
|
||||||
|
subgroup->metadata_len = *ptr;
|
||||||
|
ptr += sizeof(subgroup->metadata_len);
|
||||||
|
memcpy(subgroup->metadata, ptr, subgroup->metadata_len);
|
||||||
|
ptr += subgroup->metadata_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_add_src(conn, ¶m);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("err %d", err);
|
||||||
|
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_remove_src(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_remove_broadcast_src_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_rem_src(conn, cp->src_id);
|
||||||
|
if (err != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_modify_src(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
const uint8_t *ptr;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_modify_broadcast_src_cmd *cp = cmd;
|
||||||
|
struct bt_bap_broadcast_assistant_mod_src_param param = { 0 };
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(delegator_subgroups, 0, sizeof(delegator_subgroups));
|
||||||
|
param.src_id = cp->src_id;
|
||||||
|
param.pa_sync = cp->padv_sync > 0 ? true : false;
|
||||||
|
param.pa_interval = sys_le16_to_cpu(cp->padv_interval);
|
||||||
|
param.num_subgroups = MIN(cp->num_subgroups, BROADCAST_SNK_SUBGROUP_CNT);
|
||||||
|
param.subgroups = delegator_subgroups;
|
||||||
|
|
||||||
|
ptr = cp->subgroups;
|
||||||
|
for (uint8_t i = 0; i < param.num_subgroups; i++) {
|
||||||
|
struct bt_bap_scan_delegator_subgroup *subgroup = &delegator_subgroups[i];
|
||||||
|
|
||||||
|
subgroup->bis_sync = sys_get_le32(ptr);
|
||||||
|
ptr += sizeof(subgroup->bis_sync);
|
||||||
|
subgroup->metadata_len = *ptr;
|
||||||
|
ptr += sizeof(subgroup->metadata_len);
|
||||||
|
memcpy(subgroup->metadata, ptr, subgroup->metadata_len);
|
||||||
|
ptr += subgroup->metadata_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_mod_src(conn, ¶m);
|
||||||
|
if (err != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_set_broadcast_code(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
const struct btp_bap_set_broadcast_code_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_bap_broadcast_assistant_set_broadcast_code(conn, cp->src_id, cp->broadcast_code);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("err %d", err);
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t broadcast_assistant_send_past(const void *cmd, uint16_t cmd_len,
|
||||||
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
uint16_t service_data;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
struct bt_le_per_adv_sync *pa_sync;
|
||||||
|
const struct btp_bap_send_past_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
pa_sync = tester_gap_padv_get();
|
||||||
|
if (!pa_sync) {
|
||||||
|
LOG_DBG("Could not send PAST to Scan Delegator");
|
||||||
|
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("Sending PAST");
|
||||||
|
|
||||||
|
/* If octet 0 is set to 0, it means AdvA in PAST matches AdvA in ADV_EXT_IND.
|
||||||
|
* Octet 1 shall be set to Source_ID.
|
||||||
|
*/
|
||||||
|
service_data = cp->src_id << 8;
|
||||||
|
|
||||||
|
err = bt_le_per_adv_sync_transfer(pa_sync, conn, service_data);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Could not transfer periodic adv sync: %d", err);
|
||||||
|
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
return BTP_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2698,6 +3297,51 @@ static const struct btp_handler bap_handlers[] = {
|
||||||
.expect_len = sizeof(struct btp_bap_broadcast_sink_stop_cmd),
|
.expect_len = sizeof(struct btp_bap_broadcast_sink_stop_cmd),
|
||||||
.func = broadcast_sink_stop,
|
.func = broadcast_sink_stop,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_BROADCAST_SINK_BIS_SYNC,
|
||||||
|
.expect_len = sizeof(struct btp_bap_broadcast_sink_bis_sync_cmd),
|
||||||
|
.func = broadcast_sink_bis_sync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_DISCOVER_SCAN_DELEGATORS,
|
||||||
|
.expect_len = sizeof(struct btp_bap_discover_scan_delegators_cmd),
|
||||||
|
.func = broadcast_discover_scan_delegators,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_BROADCAST_ASSISTANT_SCAN_START,
|
||||||
|
.expect_len = sizeof(struct btp_bap_broadcast_assistant_scan_start_cmd),
|
||||||
|
.func = broadcast_assistant_scan_start,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_BROADCAST_ASSISTANT_SCAN_STOP,
|
||||||
|
.expect_len = sizeof(struct btp_bap_broadcast_assistant_scan_stop_cmd),
|
||||||
|
.func = broadcast_assistant_scan_stop,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_ADD_BROADCAST_SRC,
|
||||||
|
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
|
||||||
|
.func = broadcast_assistant_add_src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_REMOVE_BROADCAST_SRC,
|
||||||
|
.expect_len = sizeof(struct btp_bap_remove_broadcast_src_cmd),
|
||||||
|
.func = broadcast_assistant_remove_src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_MODIFY_BROADCAST_SRC,
|
||||||
|
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
|
||||||
|
.func = broadcast_assistant_modify_src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_SET_BROADCAST_CODE,
|
||||||
|
.expect_len = sizeof(struct btp_bap_set_broadcast_code_cmd),
|
||||||
|
.func = broadcast_assistant_set_broadcast_code,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_BAP_SEND_PAST,
|
||||||
|
.expect_len = sizeof(struct btp_bap_send_past_cmd),
|
||||||
|
.func = broadcast_assistant_send_past,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t tester_init_pacs(void)
|
uint8_t tester_init_pacs(void)
|
||||||
|
@ -2767,6 +3411,9 @@ uint8_t tester_init_bap(void)
|
||||||
return BTP_STATUS_FAILED;
|
return BTP_STATUS_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For Broadcast Assistant role */
|
||||||
|
bt_bap_broadcast_assistant_register_cb(&broadcast_assistant_cb);
|
||||||
|
|
||||||
k_work_queue_init(&iso_data_work_q);
|
k_work_queue_init(&iso_data_work_q);
|
||||||
k_work_queue_start(&iso_data_work_q, iso_data_thread_stack_area,
|
k_work_queue_start(&iso_data_work_q, iso_data_thread_stack_area,
|
||||||
K_THREAD_STACK_SIZEOF(iso_data_thread_stack_area),
|
K_THREAD_STACK_SIZEOF(iso_data_thread_stack_area),
|
||||||
|
|
|
@ -156,7 +156,8 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len,
|
||||||
status = tester_init_ias();
|
status = tester_init_ias();
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_IAS */
|
#endif /* CONFIG_BT_IAS */
|
||||||
#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER)
|
#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER) || \
|
||||||
|
defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||||
case BTP_SERVICE_ID_PACS:
|
case BTP_SERVICE_ID_PACS:
|
||||||
status = tester_init_pacs();
|
status = tester_init_pacs();
|
||||||
break;
|
break;
|
||||||
|
@ -166,7 +167,9 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len,
|
||||||
case BTP_SERVICE_ID_BAP:
|
case BTP_SERVICE_ID_BAP:
|
||||||
status = tester_init_bap();
|
status = tester_init_bap();
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */
|
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT || CONFIG_BT_BAP_UNICAST_SERVER || \
|
||||||
|
* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_BROADCAST_SINK
|
||||||
|
*/
|
||||||
#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR)
|
#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR)
|
||||||
case BTP_SERVICE_ID_MICP:
|
case BTP_SERVICE_ID_MICP:
|
||||||
status = tester_init_micp();
|
status = tester_init_micp();
|
||||||
|
@ -265,7 +268,8 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len,
|
||||||
status = tester_unregister_ias();
|
status = tester_unregister_ias();
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_IAS */
|
#endif /* CONFIG_BT_IAS */
|
||||||
#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER)
|
#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER) || \
|
||||||
|
defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||||
case BTP_SERVICE_ID_PACS:
|
case BTP_SERVICE_ID_PACS:
|
||||||
status = tester_unregister_pacs();
|
status = tester_unregister_pacs();
|
||||||
break;
|
break;
|
||||||
|
@ -275,10 +279,17 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len,
|
||||||
case BTP_SERVICE_ID_BAP:
|
case BTP_SERVICE_ID_BAP:
|
||||||
status = tester_unregister_bap();
|
status = tester_unregister_bap();
|
||||||
break;
|
break;
|
||||||
case BTP_SERVICE_ID_MICP:
|
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT || CONFIG_BT_BAP_UNICAST_SERVER || \
|
||||||
|
* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_BROADCAST_SINK
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR)
|
||||||
|
case BTP_SERVICE_ID_MICP:
|
||||||
status = tester_unregister_micp();
|
status = tester_unregister_micp();
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */
|
case BTP_SERVICE_ID_MICS:
|
||||||
|
status = tester_unregister_mics();
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_BT_MICP_MIC_DEV or CONFIG_BT_MICP_MIC_CTLR */
|
||||||
#if defined(CONFIG_BT_HAS)
|
#if defined(CONFIG_BT_HAS)
|
||||||
case BTP_SERVICE_ID_HAS:
|
case BTP_SERVICE_ID_HAS:
|
||||||
status = tester_unregister_has();
|
status = tester_unregister_has();
|
||||||
|
|
|
@ -1539,7 +1539,7 @@ static uint8_t padv_set_data(const void *cmd, uint16_t cmd_len,
|
||||||
return BTP_STATUS_SUCCESS;
|
return BTP_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tester_padv_create_sync(struct bt_le_per_adv_sync_param *create_params)
|
int tester_gap_padv_create_sync(struct bt_le_per_adv_sync_param *create_params)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -1556,6 +1556,22 @@ int tester_padv_create_sync(struct bt_le_per_adv_sync_param *create_params)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tester_gap_padv_stop_sync(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (pa_sync == NULL) {
|
||||||
|
return -EALREADY;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_le_per_adv_sync_delete(pa_sync);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_DBG("Unable to stop sync to PA: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t padv_create_sync(const void *cmd, uint16_t cmd_len,
|
static uint8_t padv_create_sync(const void *cmd, uint16_t cmd_len,
|
||||||
void *rsp, uint16_t *rsp_len)
|
void *rsp, uint16_t *rsp_len)
|
||||||
{
|
{
|
||||||
|
@ -1569,7 +1585,7 @@ static uint8_t padv_create_sync(const void *cmd, uint16_t cmd_len,
|
||||||
create_params.skip = cp->skip;
|
create_params.skip = cp->skip;
|
||||||
create_params.timeout = cp->sync_timeout;
|
create_params.timeout = cp->sync_timeout;
|
||||||
|
|
||||||
err = tester_padv_create_sync(&create_params);
|
err = tester_gap_padv_create_sync(&create_params);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return BTP_STATUS_FAILED;
|
return BTP_STATUS_FAILED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue