Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth: Controller: Implement PAST Support #78894

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions subsys/bluetooth/audio/bap_scan_delegator.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn,
*/
if (pa_sync != BT_BAP_BASS_PA_REQ_NO_SYNC &&
state->pa_sync_state != BT_BAP_PA_STATE_SYNCED) {
const uint8_t pa_sync_state = state->pa_sync_state;
const int err = pa_sync_request(conn, state, pa_sync,
pa_interval);

Expand All @@ -834,6 +835,12 @@ static int scan_delegator_mod_src(struct bt_conn *conn,
err);

return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED);
} else if (pa_sync_state != state->pa_sync_state) {
/* Temporary work around if the state is changed when pa_sync_request is
* called. See https://github.com/zephyrproject-rtos/zephyr/issues/79308 for
* more information about this issue.
*/
state_changed = true;
}
} else if (pa_sync == BT_BAP_BASS_PA_REQ_NO_SYNC &&
(state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ ||
Expand Down
8 changes: 7 additions & 1 deletion subsys/bluetooth/controller/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,13 @@ if(CONFIG_BT_CONN)
ll_sw/ull_llcp_chmu.c
ll_sw/ull_llcp_remote.c
)
zephyr_library_sources_ifdef(
if (CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER OR
CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
zephyr_library_sources(
ll_sw/ull_llcp_past.c
)
endif()
zephyr_library_sources_ifdef(
CONFIG_BT_PERIPHERAL
ll_sw/ull_peripheral.c
)
Expand Down
4 changes: 3 additions & 1 deletion subsys/bluetooth/controller/Kconfig.ll_sw_split
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ config BT_LLL_VENDOR_NORDIC
select BT_CTLR_CHAN_SEL_2_SUPPORT
select BT_CTLR_MIN_USED_CHAN_SUPPORT
select BT_CTLR_SCA_UPDATE_SUPPORT
select BT_CTLR_SYNC_TRANSFER_RECEIVER_SUPPORT
select BT_CTLR_SYNC_TRANSFER_SENDER_SUPPORT
select BT_CTLR_DTM_HCI_SUPPORT
select BT_CTLR_CONN_RSSI_SUPPORT

Expand All @@ -61,7 +63,7 @@ config BT_LLL_VENDOR_NORDIC
(BT_OBSERVER && BT_CTLR_ADV_EXT)
select BT_TICKER_START_REMAINDER if BT_CTLR_CENTRAL_ISO
select BT_TICKER_REMAINDER_GET if BT_BROADCASTER && BT_CTLR_ADV_EXT
select BT_TICKER_LAZY_GET if BT_CTLR_ADV_PERIODIC || BT_CTLR_CENTRAL_ISO
select BT_TICKER_LAZY_GET if BT_CTLR_ADV_PERIODIC || BT_CTLR_CENTRAL_ISO || BT_CTLR_SYNC_TRANSFER_SENDER

select BT_TICKER_PREFER_START_BEFORE_STOP if BT_TICKER_SLOT_AGNOSTIC

Expand Down
222 changes: 208 additions & 14 deletions subsys/bluetooth/controller/hci/hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,19 @@ static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)

#endif /* CONFIG_BT_CTLR_DF */

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
/* LE Periodic Advertising Sync Transfer */
rp->commands[40] |= BIT(6);
/* LE Periodic Advertising Set Info Transfer */
rp->commands[40] |= BIT(7);
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
/* LE Set Periodic Advertising Sync Transfer Parameters */
rp->commands[41] |= BIT(0);
/* LE Set Default Periodic Advertising Sync Transfer Parameters */
rp->commands[41] |= BIT(1);
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */

#if defined(CONFIG_BT_HCI_RAW) && defined(CONFIG_BT_TINYCRYPT_ECC)
bt_hci_ecc_supported_commands(rp->commands);
#endif /* CONFIG_BT_HCI_RAW && CONFIG_BT_TINYCRYPT_ECC */
Expand Down Expand Up @@ -4081,6 +4094,110 @@ static void le_read_pal_size(struct net_buf *buf, struct net_buf **evt)
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#endif /* CONFIG_BT_OBSERVER */

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
static void le_per_adv_sync_transfer(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_per_adv_sync_transfer *cmd = (void *)buf->data;
struct bt_hci_rp_le_per_adv_sync_transfer *rp;
uint16_t conn_handle, conn_handle_le16;
uint16_t service_data;
uint16_t sync_handle;
uint8_t status;

conn_handle_le16 = cmd->conn_handle;

conn_handle = sys_le16_to_cpu(cmd->conn_handle);
service_data = sys_le16_to_cpu(cmd->service_data);
sync_handle = sys_le16_to_cpu(cmd->sync_handle);

status = ll_sync_transfer(conn_handle, service_data, sync_handle);

rp = hci_cmd_complete(evt, sizeof(*rp));
rp->conn_handle = conn_handle_le16;
rp->status = status;
}

static void le_per_adv_set_info_transfer(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_per_adv_set_info_transfer *cmd = (void *)buf->data;
struct bt_hci_rp_le_per_adv_set_info_transfer *rp;
uint16_t conn_handle, conn_handle_le16;
uint16_t service_data;
uint8_t adv_handle;
uint8_t status;

conn_handle_le16 = cmd->conn_handle;

conn_handle = sys_le16_to_cpu(cmd->conn_handle);
service_data = sys_le16_to_cpu(cmd->service_data);
adv_handle = cmd->adv_handle;

status = ll_adv_sync_set_info_transfer(conn_handle, service_data, adv_handle);

rp = hci_cmd_complete(evt, sizeof(*rp));
rp->conn_handle = conn_handle_le16;
rp->status = status;
}
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
static void le_past_param(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_past_param *cmd = (void *)buf->data;
struct bt_hci_rp_le_past_param *rp;
uint16_t conn_handle_le16;
uint16_t conn_handle;
uint16_t timeout;
uint8_t cte_type;
uint8_t status;
uint16_t skip;
uint8_t mode;

if (adv_cmds_ext_check(evt)) {
return;
}

conn_handle_le16 = cmd->conn_handle;

conn_handle = sys_le16_to_cpu(cmd->conn_handle);
mode = cmd->mode;
skip = sys_le16_to_cpu(cmd->skip);
timeout = sys_le16_to_cpu(cmd->timeout);
cte_type = cmd->cte_type;

status = ll_past_param(conn_handle, mode, skip, timeout, cte_type);

rp = hci_cmd_complete(evt, sizeof(*rp));
rp->conn_handle = conn_handle_le16;
rp->status = status;
}

static void le_default_past_param(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_default_past_param *cmd = (void *)buf->data;
struct bt_hci_rp_le_default_past_param *rp;
uint16_t timeout;
uint8_t cte_type;
uint8_t status;
uint16_t skip;
uint8_t mode;

if (adv_cmds_ext_check(evt)) {
return;
}

mode = cmd->mode;
skip = sys_le16_to_cpu(cmd->skip);
timeout = sys_le16_to_cpu(cmd->timeout);
cte_type = cmd->cte_type;

status = ll_default_past_param(mode, skip, timeout, cte_type);

rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
}
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */

#if defined(CONFIG_BT_CENTRAL)
static void le_ext_create_connection(struct net_buf *buf, struct net_buf **evt)
{
Expand Down Expand Up @@ -4297,6 +4414,51 @@ static void le_cis_established(struct pdu_data *pdu_data,
}
#endif /* CONFIG_BT_CTLR_CONN_ISO */

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
static void le_per_adv_sync_transfer_received(struct pdu_data *pdu_data_rx,
struct node_rx_pdu *node_rx, struct net_buf *buf)
{
struct bt_hci_evt_le_past_received *sep;
struct node_rx_past_received *se;
struct ll_sync_set *sync;
void *node;

if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
!(le_event_mask & BT_EVT_MASK_LE_PAST_RECEIVED)) {
return;
}

sep = meta_evt(buf, BT_HCI_EVT_LE_PAST_RECEIVED, sizeof(*sep));

/* Check for pdu field being aligned before accessing PAST received
* event.
*/
node = pdu_data_rx;
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_past_received));

se = node;
sep->status = se->rx_sync.status;

sync = node_rx->rx_ftr.param;

/* Resolved address, if private, has been populated in ULL */
sep->addr.type = sync->peer_id_addr_type;
if (sync->peer_addr_resolved) {
/* Mark it as identity address from RPA (0x02, 0x03) */
MARK_AS_IDENTITY_ADDR(sep->addr.type);
}
(void)memcpy(sep->addr.a.val, sync->peer_id_addr, BDADDR_SIZE);

sep->adv_sid = sync->sid;
sep->phy = find_lsb_set(se->rx_sync.phy);
sep->interval = sys_cpu_to_le16(se->rx_sync.interval);
sep->clock_accuracy = se->rx_sync.sca;
sep->conn_handle = sys_cpu_to_le16(se->conn_handle);
sep->service_data = sys_cpu_to_le16(se->service_data);
sep->sync_handle = sys_cpu_to_le16(node_rx->hdr.handle);
}
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */

static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
struct net_buf **evt, void **node_rx)
{
Expand Down Expand Up @@ -4671,6 +4833,26 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#endif /* CONFIG_BT_OBSERVER */

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
case BT_OCF(BT_HCI_OP_LE_PER_ADV_SYNC_TRANSFER):
le_per_adv_sync_transfer(cmd, evt);
break;

case BT_OCF(BT_HCI_OP_LE_PER_ADV_SET_INFO_TRANSFER):
le_per_adv_set_info_transfer(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
case BT_OCF(BT_HCI_OP_LE_PAST_PARAM):
le_past_param(cmd, evt);
break;

case BT_OCF(BT_HCI_OP_LE_DEFAULT_PAST_PARAM):
le_default_past_param(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */

#if defined(CONFIG_BT_CONN)
#if defined(CONFIG_BT_CENTRAL)
case BT_OCF(BT_HCI_OP_LE_EXT_CREATE_CONN):
Expand Down Expand Up @@ -6306,7 +6488,7 @@ static inline void le_dir_adv_report(struct pdu_adv *adv, struct net_buf *buf,
ll_rl_id_addr_get(rl_idx, &dir_info->addr.type,
&dir_info->addr.a.val[0]);
/* Mark it as identity address from RPA (0x02, 0x03) */
dir_info->addr.type += 2U;
MARK_AS_IDENTITY_ADDR(dir_info->addr.type);
} else {
#else
if (1) {
Expand Down Expand Up @@ -6466,7 +6648,7 @@ static void le_advertising_report(struct pdu_data *pdu_data,
ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
&adv_info->addr.a.val[0]);
/* Mark it as identity address from RPA (0x02, 0x03) */
adv_info->addr.type += 2U;
MARK_AS_IDENTITY_ADDR(adv_info->addr.type);
} else {
#else
if (1) {
Expand Down Expand Up @@ -6571,7 +6753,7 @@ static void le_ext_adv_legacy_report(struct pdu_data *pdu_data,
ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
&adv_info->addr.a.val[0]);
/* Mark it as identity address from RPA (0x02, 0x03) */
adv_info->addr.type += 2U;
MARK_AS_IDENTITY_ADDR(adv_info->addr.type);
} else
#endif /* CONFIG_BT_CTLR_PRIVACY */
{
Expand Down Expand Up @@ -6763,7 +6945,7 @@ static void ext_adv_info_fill(uint8_t evt_type, uint8_t phy, uint8_t sec_phy,
ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
adv_info->addr.a.val);
/* Mark it as identity address from RPA (0x02, 0x03) */
adv_info->addr.type += 2U;
MARK_AS_IDENTITY_ADDR(adv_info->addr.type);
#else /* !CONFIG_BT_CTLR_PRIVACY */
ARG_UNUSED(rl_idx);
#endif /* !CONFIG_BT_CTLR_PRIVACY */
Expand Down Expand Up @@ -7438,7 +7620,7 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data,
struct net_buf *buf)
{
struct bt_hci_evt_le_per_adv_sync_established *sep;
struct ll_scan_set *scan;
struct ll_sync_set *sync;
struct node_rx_sync *se;
void *node;

Expand All @@ -7463,24 +7645,26 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data,
return;
}

scan = node_rx->rx_ftr.param;
sync = node_rx->rx_ftr.param;

#if (CONFIG_BT_CTLR_DUP_FILTER_LEN > 0) && \
defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)
dup_periodic_adv_reset(scan->periodic.adv_addr_type,
scan->periodic.adv_addr,
scan->periodic.sid);
dup_periodic_adv_reset(sync->peer_id_addr_type, sync->peer_id_addr, sync->sid);
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 &&
* CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT
*/

sep->handle = sys_cpu_to_le16(node_rx->hdr.handle);

/* Resolved address, if private, has been populated in ULL */
sep->adv_addr.type = scan->periodic.adv_addr_type;
(void)memcpy(sep->adv_addr.a.val, scan->periodic.adv_addr, BDADDR_SIZE);
sep->adv_addr.type = sync->peer_id_addr_type;
if (sync->peer_addr_resolved) {
/* Mark it as identity address from RPA (0x02, 0x03) */
MARK_AS_IDENTITY_ADDR(sep->adv_addr.type);
}
(void)memcpy(sep->adv_addr.a.val, sync->peer_id_addr, BDADDR_SIZE);

sep->sid = scan->periodic.sid;
sep->sid = sync->sid;
sep->phy = find_lsb_set(se->phy);
sep->interval = sys_cpu_to_le16(se->interval);
sep->clock_accuracy = se->sca;
Expand Down Expand Up @@ -8077,7 +8261,7 @@ static void le_scan_req_received(struct pdu_data *pdu_data,
ll_rl_id_addr_get(rl_idx, &sep->addr.type,
&sep->addr.a.val[0]);
/* Mark it as identity address from RPA (0x02, 0x03) */
sep->addr.type += 2U;
MARK_AS_IDENTITY_ADDR(sep->addr.type);
} else {
#else
if (1) {
Expand Down Expand Up @@ -8117,7 +8301,7 @@ static void le_vs_scan_req_received(struct pdu_data *pdu,
ll_rl_id_addr_get(rl_idx, &sep->addr.type,
&sep->addr.a.val[0]);
/* Mark it as identity address from RPA (0x02, 0x03) */
sep->addr.type += 2U;
MARK_AS_IDENTITY_ADDR(sep->addr.type);
} else {
#else
if (1) {
Expand Down Expand Up @@ -8465,6 +8649,12 @@ static void encode_control(struct node_rx_pdu *node_rx,
le_per_adv_sync_lost(pdu_data, node_rx, buf);
break;

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
case NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED:
le_per_adv_sync_transfer_received(pdu_data, node_rx, buf);
return;
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */

#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT:
#if defined(CONFIG_BT_CTLR_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES)
Expand Down Expand Up @@ -9009,6 +9199,10 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
case NODE_RX_TYPE_SYNC_REPORT:
case NODE_RX_TYPE_SYNC_LOST:

#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
case NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED:
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */

#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT:
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
Expand Down
6 changes: 6 additions & 0 deletions subsys/bluetooth/controller/include/ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
uint8_t ll_sync_create_cancel(void **rx);
uint8_t ll_sync_terminate(uint16_t handle);
uint8_t ll_sync_recv_enable(uint16_t handle, uint8_t enable);
uint8_t ll_sync_transfer(uint16_t conn_handle, uint16_t service_data, uint16_t sync_handle);
uint8_t ll_adv_sync_set_info_transfer(uint16_t conn_handle, uint16_t service_data,
uint8_t adv_handle);
uint8_t ll_past_param(uint16_t conn_handle, uint8_t mode, uint16_t skip, uint16_t timeout,
uint8_t cte_type);
uint8_t ll_default_past_param(uint8_t mode, uint16_t skip, uint16_t timeout, uint8_t cte_type);
uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t *bcode, uint8_t mse,
uint16_t sync_timeout, uint8_t num_bis,
Expand Down
Loading
Loading