Bluetooth: Controller: Implement PAST support in ULL
Implement PAST support in ULL and fixed test after changed dependencies in ull_sync_internal.c Signed-off-by: Lucas Mathias Balling <lutb@demant.com>
This commit is contained in:
parent
c7ffce3eb2
commit
cb0e3a7646
23 changed files with 1204 additions and 207 deletions
|
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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):
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -7463,13 +7645,11 @@ 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
|
||||
*/
|
||||
|
@ -7477,10 +7657,14 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data,
|
|||
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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "lll_iso_tx.h"
|
||||
#include "isoal.h"
|
||||
#include "ull_iso_types.h"
|
||||
#include "ull_internal.h"
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
|
@ -134,12 +135,7 @@ isoal_status_t isoal_reset(void)
|
|||
*/
|
||||
uint32_t isoal_get_wrapped_time_us(uint32_t time_now_us, int32_t time_diff_us)
|
||||
{
|
||||
LL_ASSERT(time_now_us <= ISOAL_TIME_WRAPPING_POINT_US);
|
||||
|
||||
uint32_t result = ((uint64_t)time_now_us + ISOAL_TIME_SPAN_FULL_US + time_diff_us) %
|
||||
((uint64_t)ISOAL_TIME_SPAN_FULL_US);
|
||||
|
||||
return result;
|
||||
return ull_get_wrapped_time_us(time_now_us, time_diff_us);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -319,6 +319,7 @@ enum node_rx_type {
|
|||
NODE_RX_TYPE_DTM_IQ_SAMPLE_REPORT,
|
||||
NODE_RX_TYPE_IQ_SAMPLE_REPORT_ULL_RELEASE,
|
||||
NODE_RX_TYPE_IQ_SAMPLE_REPORT_LLL_RELEASE,
|
||||
NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED,
|
||||
/* Signals retention (ie non-release) of rx node */
|
||||
NODE_RX_TYPE_RETAIN,
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ extern uint8_t ull_filter_lll_fal_match(struct lll_filter const *const filter,
|
|||
uint8_t *devmatch_id);
|
||||
extern bool ull_filter_lll_lrpa_used(uint8_t rl_idx);
|
||||
extern bt_addr_t *ull_filter_lll_lrpa_get(uint8_t rl_idx);
|
||||
extern bt_addr_t *ull_filter_lll_id_addr_get(uint8_t rl_idx, uint8_t *id_addr_type);
|
||||
extern uint8_t *ull_filter_lll_irks_get(uint8_t *count);
|
||||
extern uint8_t ull_filter_lll_rl_idx(bool fal, uint8_t devmatch_id);
|
||||
extern uint8_t ull_filter_lll_rl_irk_idx(uint8_t irkmatch_id);
|
||||
|
|
|
@ -195,6 +195,11 @@ lll_adv_sync_data_latest_peek(const struct lll_adv_sync *const lll)
|
|||
return lll_adv_pdu_latest_peek(&lll->data);
|
||||
}
|
||||
|
||||
static inline struct pdu_adv *lll_adv_sync_data_curr_get(struct lll_adv_sync *lll)
|
||||
{
|
||||
return (void *)lll->data.pdu[lll->data.first];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
|
||||
static inline void *lll_adv_sync_extra_data_peek(struct lll_adv_sync *lll)
|
||||
{
|
||||
|
|
|
@ -506,6 +506,16 @@ static struct {
|
|||
static MEMQ_DECLARE(ull_rx);
|
||||
static MEMQ_DECLARE(ll_rx);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ISO) || \
|
||||
defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER) || \
|
||||
defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
#define ULL_TIME_WRAPPING_POINT_US (HAL_TICKER_TICKS_TO_US_64BIT(HAL_TICKER_CNTR_MASK))
|
||||
#define ULL_TIME_SPAN_FULL_US (ULL_TIME_WRAPPING_POINT_US + 1)
|
||||
#endif /* CONFIG_BT_CTLR_ISO ||
|
||||
* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER ||
|
||||
* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
static MFIFO_DEFINE(ll_pdu_rx_free, sizeof(void *), LL_PDU_RX_CNT);
|
||||
|
||||
|
@ -1267,6 +1277,10 @@ void ll_rx_dequeue(void)
|
|||
/* fall through */
|
||||
case NODE_RX_TYPE_SYNC:
|
||||
case NODE_RX_TYPE_SYNC_LOST:
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
/* fall through */
|
||||
case NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED:
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||
/* fall through */
|
||||
case NODE_RX_TYPE_SYNC_ISO:
|
||||
|
@ -1544,6 +1558,9 @@ void ll_rx_mem_release(void **node_rx)
|
|||
break;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
case NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED:
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
case NODE_RX_TYPE_SYNC:
|
||||
{
|
||||
struct node_rx_sync *se =
|
||||
|
@ -1558,21 +1575,15 @@ void ll_rx_mem_release(void **node_rx)
|
|||
(status == BT_HCI_ERR_UNSUPP_REMOTE_FEATURE) ||
|
||||
(status == BT_HCI_ERR_CONN_FAIL_TO_ESTAB)) {
|
||||
struct ll_sync_set *sync;
|
||||
struct ll_scan_set *scan;
|
||||
|
||||
/* pick the scan context before node_rx
|
||||
/* pick the sync context before node_rx
|
||||
* release.
|
||||
*/
|
||||
scan = (void *)rx_free->rx_ftr.param;
|
||||
sync = (void *)rx_free->rx_ftr.param;
|
||||
|
||||
ll_rx_release(rx_free);
|
||||
|
||||
/* pick the sync context before scan context
|
||||
* is cleanup of sync context association.
|
||||
*/
|
||||
sync = scan->periodic.sync;
|
||||
|
||||
ull_sync_setup_reset(scan);
|
||||
ull_sync_setup_reset(sync);
|
||||
|
||||
if (status != BT_HCI_ERR_SUCCESS) {
|
||||
memq_link_t *link_sync_lost;
|
||||
|
@ -2812,6 +2823,14 @@ static inline void rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx)
|
|||
ull_sync_established_report(link, (struct node_rx_pdu *)rx);
|
||||
}
|
||||
break;
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
case NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED:
|
||||
{
|
||||
(void)memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
|
||||
ll_rx_put_sched(link, rx);
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
#endif /* CONFIG_BT_OBSERVER */
|
||||
|
@ -3114,3 +3133,26 @@ void *ull_rxfifo_release(uint8_t s, uint8_t n, uint8_t f, uint8_t *l, uint8_t *m
|
|||
|
||||
return rx;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ISO) || \
|
||||
defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER) || \
|
||||
defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
/**
|
||||
* @brief Wraps given time within the range of 0 to ULL_TIME_WRAPPING_POINT_US
|
||||
* @param time_now Current time value
|
||||
* @param time_diff Time difference (signed)
|
||||
* @return Wrapped time after difference
|
||||
*/
|
||||
uint32_t ull_get_wrapped_time_us(uint32_t time_now_us, int32_t time_diff_us)
|
||||
{
|
||||
LL_ASSERT(time_now_us <= ULL_TIME_WRAPPING_POINT_US);
|
||||
|
||||
uint32_t result = ((uint64_t)time_now_us + ULL_TIME_SPAN_FULL_US + time_diff_us) %
|
||||
((uint64_t)ULL_TIME_SPAN_FULL_US);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ISO ||
|
||||
* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER ||
|
||||
* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER
|
||||
*/
|
||||
|
|
|
@ -43,6 +43,14 @@
|
|||
#include "ull_sched_internal.h"
|
||||
#include "ull_adv_internal.h"
|
||||
|
||||
#include "ull_conn_internal.h"
|
||||
|
||||
#include "isoal.h"
|
||||
#include "ull_iso_types.h"
|
||||
#include "lll_conn_iso.h"
|
||||
#include "ull_conn_iso_types.h"
|
||||
#include "ull_llcp.h"
|
||||
|
||||
#include "ll.h"
|
||||
|
||||
#include "hal/debug.h"
|
||||
|
@ -621,6 +629,51 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
/* @brief Link Layer interface function corresponding to HCI LE Periodic
|
||||
* Advertising Set Info Transfer command.
|
||||
*
|
||||
* @param[in] conn_handle Connection_Handle identifying the connected device
|
||||
* Range: 0x0000 to 0x0EFF.
|
||||
* @param[in] service_data Service_Data value provided by the Host for use by the
|
||||
* Host of the peer device.
|
||||
* @param[in] adv_handle Advertising_Handle identifying the advertising
|
||||
* set. Range: 0x00 to 0xEF.
|
||||
*
|
||||
* @return HCI error codes as documented in Bluetooth Core Specification v5.4.
|
||||
*/
|
||||
uint8_t ll_adv_sync_set_info_transfer(uint16_t conn_handle, uint16_t service_data,
|
||||
uint8_t adv_handle)
|
||||
{
|
||||
struct ll_adv_sync_set *sync;
|
||||
struct ll_adv_set *adv;
|
||||
struct ll_conn *conn;
|
||||
|
||||
conn = ll_connected_get(conn_handle);
|
||||
if (!conn) {
|
||||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
/* Verify that adv_handle is valid and periodic advertising is enabled */
|
||||
adv = ull_adv_is_created_get(adv_handle);
|
||||
if (!adv) {
|
||||
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
|
||||
}
|
||||
|
||||
if (!adv->lll.sync) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
sync = HDR_LLL2ULL(adv->lll.sync);
|
||||
if (!sync->is_enabled) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Call llcp to start LLCP_PERIODIC_SYNC_IND */
|
||||
return ull_cp_periodic_sync(conn, NULL, sync, service_data);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
|
||||
int ull_adv_sync_init(void)
|
||||
{
|
||||
int err;
|
||||
|
@ -945,8 +998,10 @@ void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
|
|||
{
|
||||
struct pdu_adv_com_ext_adv *com_hdr;
|
||||
struct pdu_adv_ext_hdr *ext_hdr;
|
||||
#if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
|
||||
struct pdu_adv_aux_ptr *aux_ptr;
|
||||
uint32_t cte_len_us;
|
||||
#endif
|
||||
uint8_t *dptr;
|
||||
uint8_t len;
|
||||
|
||||
|
@ -971,6 +1026,7 @@ void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
|
|||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
|
||||
ULL_ADV_PDU_HDR_FIELD_SYNC_INFO)));
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_DF_ADV_CTE_TX) &&
|
||||
(ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_CTE_INFO)) {
|
||||
(void)memcpy(dptr, cte_info, sizeof(*cte_info));
|
||||
|
@ -979,15 +1035,18 @@ void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
|
|||
} else {
|
||||
cte_len_us = 0U;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) &&
|
||||
(ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_ADI)) {
|
||||
dptr += sizeof(struct pdu_adv_adi);
|
||||
}
|
||||
#if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) &&
|
||||
(ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR)) {
|
||||
aux_ptr = (void *)dptr;
|
||||
dptr += sizeof(struct pdu_adv_aux_ptr);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
|
||||
if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_TX_POWER) {
|
||||
dptr += sizeof(uint8_t);
|
||||
}
|
||||
|
|
|
@ -722,7 +722,7 @@ void ull_central_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr,
|
|||
ll_rl_id_addr_get(rl_idx, &cc->peer_addr_type,
|
||||
&cc->peer_addr[0]);
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
cc->peer_addr_type += 2;
|
||||
MARK_AS_IDENTITY_ADDR(cc->peer_addr_type);
|
||||
|
||||
/* Store peer RPA */
|
||||
memcpy(&cc->peer_rpa[0], &peer_addr[0], BDADDR_SIZE);
|
||||
|
@ -749,6 +749,11 @@ void ull_central_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr,
|
|||
/* Set LLCP as connection-wise connected */
|
||||
ull_cp_state_set(conn, ULL_CP_CONNECTED);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
/* Set default PAST parameters */
|
||||
conn->past = ull_conn_default_past_param_get();
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
||||
lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
|
||||
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
||||
|
|
|
@ -57,7 +57,16 @@
|
|||
#include "ull_iso_internal.h"
|
||||
#include "ull_conn_iso_internal.h"
|
||||
#include "ull_peripheral_iso_internal.h"
|
||||
|
||||
#include "lll/lll_adv_types.h"
|
||||
#include "lll_adv.h"
|
||||
#include "ull_adv_types.h"
|
||||
#include "ull_adv_internal.h"
|
||||
#include "lll_sync.h"
|
||||
#include "lll_sync_iso.h"
|
||||
#include "ull_sync_types.h"
|
||||
#include "lll_scan.h"
|
||||
#include "ull_scan_types.h"
|
||||
#include "ull_sync_internal.h"
|
||||
|
||||
#include "ll.h"
|
||||
#include "ll_feat.h"
|
||||
|
@ -147,6 +156,10 @@ static uint8_t default_phy_tx;
|
|||
static uint8_t default_phy_rx;
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
static struct past_params default_past_params;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
static struct ll_conn conn_pool[CONFIG_BT_MAX_CONN];
|
||||
static void *conn_free;
|
||||
|
||||
|
@ -795,6 +808,22 @@ uint8_t ull_conn_default_phy_rx_get(void)
|
|||
}
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
void ull_conn_default_past_param_set(uint8_t mode, uint16_t skip, uint16_t timeout,
|
||||
uint8_t cte_type)
|
||||
{
|
||||
default_past_params.mode = mode;
|
||||
default_past_params.skip = skip;
|
||||
default_past_params.timeout = timeout;
|
||||
default_past_params.cte_type = cte_type;
|
||||
}
|
||||
|
||||
struct past_params ull_conn_default_past_param_get(void)
|
||||
{
|
||||
return default_past_params;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_CONN)
|
||||
bool ull_conn_peer_connected(uint8_t const own_id_addr_type,
|
||||
uint8_t const *const own_id_addr,
|
||||
|
@ -958,6 +987,10 @@ void ull_conn_done(struct node_rx_event_done *done)
|
|||
|
||||
ull_cp_tx_ntf(conn);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
ull_lp_past_conn_evt_done(conn, done);
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
/* Check authenticated payload expiry or MIC failure */
|
||||
switch (done->extra.mic_state) {
|
||||
|
@ -1625,6 +1658,10 @@ static int init_reset(void)
|
|||
#endif /* CONFIG_BT_CTLR_PHY_CODED */
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
memset(&default_past_params, 0, sizeof(struct past_params));
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2563,6 +2600,153 @@ void ull_conn_default_tx_time_set(uint16_t tx_time)
|
|||
}
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
static bool ticker_op_id_match_func(uint8_t ticker_id, uint32_t ticks_slot,
|
||||
uint32_t ticks_to_expire, void *op_context)
|
||||
{
|
||||
ARG_UNUSED(ticks_slot);
|
||||
ARG_UNUSED(ticks_to_expire);
|
||||
|
||||
uint8_t match_id = *(uint8_t *)op_context;
|
||||
|
||||
return ticker_id == match_id;
|
||||
}
|
||||
|
||||
static void ticker_get_offset_op_cb(uint32_t status, void *param)
|
||||
{
|
||||
*((uint32_t volatile *)param) = status;
|
||||
}
|
||||
|
||||
static uint32_t get_ticker_offset(uint8_t ticker_id, uint16_t *lazy)
|
||||
{
|
||||
uint32_t volatile ret_cb;
|
||||
uint32_t ticks_to_expire;
|
||||
uint32_t ticks_current;
|
||||
uint32_t sync_remainder_us;
|
||||
uint32_t remainder;
|
||||
uint32_t start_us;
|
||||
uint32_t ret;
|
||||
uint8_t id;
|
||||
|
||||
id = TICKER_NULL;
|
||||
ticks_to_expire = 0U;
|
||||
ticks_current = 0U;
|
||||
|
||||
ret_cb = TICKER_STATUS_BUSY;
|
||||
|
||||
ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_LOW,
|
||||
&id, &ticks_current, &ticks_to_expire, &remainder,
|
||||
lazy, ticker_op_id_match_func, &ticker_id,
|
||||
ticker_get_offset_op_cb, (void *)&ret_cb);
|
||||
|
||||
if (ret == TICKER_STATUS_BUSY) {
|
||||
while (ret_cb == TICKER_STATUS_BUSY) {
|
||||
ticker_job_sched(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
|
||||
|
||||
/* Reduced a tick for negative remainder and return positive remainder
|
||||
* value.
|
||||
*/
|
||||
hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
|
||||
sync_remainder_us = remainder;
|
||||
|
||||
/* Add a tick for negative remainder and return positive remainder
|
||||
* value.
|
||||
*/
|
||||
hal_ticker_add_jitter(&ticks_to_expire, &remainder);
|
||||
start_us = remainder;
|
||||
|
||||
return ull_get_wrapped_time_us(HAL_TICKER_TICKS_TO_US(ticks_to_expire),
|
||||
(sync_remainder_us - start_us));
|
||||
}
|
||||
|
||||
static void mfy_past_sender_offset_get(void *param)
|
||||
{
|
||||
uint16_t last_pa_event_counter;
|
||||
uint32_t ticker_offset_us;
|
||||
uint16_t pa_event_counter;
|
||||
uint8_t adv_sync_handle;
|
||||
uint16_t sync_handle;
|
||||
struct ll_conn *conn;
|
||||
uint16_t lazy;
|
||||
|
||||
conn = param;
|
||||
|
||||
/* Get handle to look for */
|
||||
ull_lp_past_offset_get_calc_params(conn, &adv_sync_handle, &sync_handle);
|
||||
|
||||
if (adv_sync_handle == BT_HCI_ADV_HANDLE_INVALID &&
|
||||
sync_handle == BT_HCI_SYNC_HANDLE_INVALID) {
|
||||
/* Procedure must have been aborted, do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
if (adv_sync_handle != BT_HCI_ADV_HANDLE_INVALID) {
|
||||
const struct ll_adv_sync_set *adv_sync = ull_adv_sync_get(adv_sync_handle);
|
||||
|
||||
LL_ASSERT(adv_sync);
|
||||
|
||||
ticker_offset_us = get_ticker_offset(TICKER_ID_ADV_SYNC_BASE + adv_sync_handle,
|
||||
&lazy);
|
||||
|
||||
pa_event_counter = adv_sync->lll.event_counter;
|
||||
last_pa_event_counter = pa_event_counter - 1;
|
||||
} else {
|
||||
const struct ll_sync_set *sync = ull_sync_is_enabled_get(sync_handle);
|
||||
uint32_t interval_us = sync->interval * PERIODIC_INT_UNIT_US;
|
||||
uint32_t window_widening_event_us;
|
||||
|
||||
LL_ASSERT(sync);
|
||||
|
||||
ticker_offset_us = get_ticker_offset(TICKER_ID_SCAN_SYNC_BASE + sync_handle,
|
||||
&lazy);
|
||||
|
||||
if (lazy && ticker_offset_us > interval_us) {
|
||||
|
||||
/* Figure out how many events we have actually skipped */
|
||||
lazy = lazy - (ticker_offset_us / interval_us);
|
||||
|
||||
/* Correct offset to point to next event */
|
||||
ticker_offset_us = ticker_offset_us % interval_us;
|
||||
}
|
||||
|
||||
/* Calculate window widening for next event */
|
||||
window_widening_event_us = sync->lll.window_widening_event_us +
|
||||
sync->lll.window_widening_periodic_us * (lazy + 1U);
|
||||
|
||||
/* Correct for window widening */
|
||||
ticker_offset_us += window_widening_event_us;
|
||||
|
||||
pa_event_counter = sync->lll.event_counter + lazy;
|
||||
|
||||
last_pa_event_counter = pa_event_counter - 1 - lazy;
|
||||
|
||||
/* Handle unsuccessful events */
|
||||
if (sync->timeout_expire) {
|
||||
last_pa_event_counter -= sync->timeout_reload - sync->timeout_expire;
|
||||
}
|
||||
}
|
||||
|
||||
ull_lp_past_offset_calc_reply(conn, ticker_offset_us, pa_event_counter,
|
||||
last_pa_event_counter);
|
||||
}
|
||||
|
||||
void ull_conn_past_sender_offset_request(struct ll_conn *conn)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, mfy_past_sender_offset_get};
|
||||
uint32_t ret;
|
||||
|
||||
mfy.param = conn;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
|
||||
&mfy);
|
||||
LL_ASSERT(!ret);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
|
||||
uint8_t ull_conn_lll_phy_active(struct ll_conn *conn, uint8_t phys)
|
||||
{
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
|
|
|
@ -17,6 +17,9 @@ uint16_t ull_conn_default_tx_octets_get(void);
|
|||
uint16_t ull_conn_default_tx_time_get(void);
|
||||
uint8_t ull_conn_default_phy_tx_get(void);
|
||||
uint8_t ull_conn_default_phy_rx_get(void);
|
||||
void ull_conn_default_past_param_set(uint8_t mode, uint16_t skip, uint16_t timeout,
|
||||
uint8_t cte_type);
|
||||
struct past_params ull_conn_default_past_param_get(void);
|
||||
bool ull_conn_peer_connected(uint8_t const own_id_addr_type,
|
||||
uint8_t const *const own_id_addr,
|
||||
uint8_t const peer_id_addr_type,
|
||||
|
@ -77,6 +80,10 @@ static inline void cpr_active_reset(void)
|
|||
}
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
void ull_conn_past_sender_offset_request(struct ll_conn *conn);
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
|
||||
uint16_t ull_conn_event_counter(struct ll_conn *conn);
|
||||
|
||||
void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc,
|
||||
|
|
|
@ -154,10 +154,23 @@ struct llcp_struct {
|
|||
|
||||
}; /* struct llcp_struct */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
struct past_params {
|
||||
uint8_t mode;
|
||||
uint8_t cte_type;
|
||||
uint16_t skip;
|
||||
uint16_t timeout;
|
||||
}; /* struct past_params */
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
struct ll_conn {
|
||||
struct ull_hdr ull;
|
||||
struct lll_conn lll;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
struct past_params past;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
struct ull_tx_q tx_q;
|
||||
struct llcp_struct llcp;
|
||||
|
||||
|
|
|
@ -859,6 +859,20 @@ bt_addr_t *ull_filter_lll_lrpa_get(uint8_t rl_idx)
|
|||
return rl[rl_idx].local_rpa;
|
||||
}
|
||||
|
||||
bt_addr_t *ull_filter_lll_id_addr_get(uint8_t rl_idx, uint8_t *id_addr_type)
|
||||
{
|
||||
struct lll_resolve_list *rl_entry;
|
||||
|
||||
if (rl_idx >= ARRAY_SIZE(rl)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rl_entry = &rl[rl_idx];
|
||||
*id_addr_type = rl_entry->id_addr_type;
|
||||
|
||||
return &rl_entry->id_addr;
|
||||
}
|
||||
|
||||
uint8_t *ull_filter_lll_irks_get(uint8_t *count)
|
||||
{
|
||||
*count = peer_irk_count;
|
||||
|
|
|
@ -45,6 +45,9 @@ extern bool ull_handle_cpr_anchor_point_move(struct ll_conn *conn, uint16_t *off
|
|||
/* Macro to convert time in us to periodic advertising interval units */
|
||||
#define RADIO_SYNC_EVENTS(x, y) ((uint16_t)DIV_ROUND_UP(x, y))
|
||||
|
||||
/* Macro to mark address type as identity address from RPA (0x02, 0x03) */
|
||||
#define MARK_AS_IDENTITY_ADDR(addr_type) ((addr_type) += 2U)
|
||||
|
||||
static inline uint8_t ull_ref_get(struct ull_hdr *hdr)
|
||||
{
|
||||
return hdr->ref;
|
||||
|
@ -170,3 +173,4 @@ void ull_rxfifo_alloc(uint8_t s, uint8_t n, uint8_t f, uint8_t *l, uint8_t *m,
|
|||
void *mem_free, void *link_free, uint8_t max);
|
||||
void *ull_rxfifo_release(uint8_t s, uint8_t n, uint8_t f, uint8_t *l, uint8_t *m,
|
||||
memq_link_t *link, struct node_rx_hdr *rx);
|
||||
uint32_t ull_get_wrapped_time_us(uint32_t time_now_us, int32_t time_diff_us);
|
||||
|
|
|
@ -1520,7 +1520,7 @@ void ull_lp_past_conn_evt_done(struct ll_conn *conn, struct node_rx_event_done *
|
|||
if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL && done->extra.trx_cnt) {
|
||||
uint32_t start_to_actual_us;
|
||||
|
||||
start_to_actual_us = isoal_get_wrapped_time_us(
|
||||
start_to_actual_us = ull_get_wrapped_time_us(
|
||||
done->extra.drift.start_to_address_actual_us,
|
||||
(-done->extra.drift.preamble_to_addr_us));
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr,
|
|||
/* Get identity address */
|
||||
ll_rl_id_addr_get(rl_idx, &peer_addr_type, peer_id_addr);
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
peer_addr_type += 2;
|
||||
MARK_AS_IDENTITY_ADDR(peer_addr_type);
|
||||
} else {
|
||||
#else /* CONFIG_BT_CTLR_PRIVACY */
|
||||
if (1) {
|
||||
|
@ -144,6 +144,11 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr,
|
|||
sizeof(conn->own_id_addr));
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_CONN */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
/* Set default PAST parameters */
|
||||
conn->past = ull_conn_default_past_param_get();
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
memcpy(&lll->crc_init[0], &pdu_adv->connect_ind.crc_init[0], 3);
|
||||
memcpy(&lll->access_addr[0], &pdu_adv->connect_ind.access_addr[0], 4);
|
||||
memcpy(&lll->data_chan_map[0], &pdu_adv->connect_ind.chan_map[0],
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/sys/slist.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "util/mem.h"
|
||||
|
@ -28,14 +29,27 @@
|
|||
#include "lll_scan_aux.h"
|
||||
#include "lll/lll_df_types.h"
|
||||
#include "lll_conn.h"
|
||||
#include "lll_conn_iso.h"
|
||||
#include "lll_sync.h"
|
||||
#include "lll_sync_iso.h"
|
||||
#include "lll/lll_adv_types.h"
|
||||
#include "lll_adv.h"
|
||||
#include "lll/lll_adv_pdu.h"
|
||||
|
||||
#include "ll_sw/ull_tx_queue.h"
|
||||
|
||||
#include "isoal.h"
|
||||
#include "ull_scan_types.h"
|
||||
#include "ull_conn_types.h"
|
||||
#include "ull_iso_types.h"
|
||||
#include "ull_conn_iso_types.h"
|
||||
#include "ull_sync_types.h"
|
||||
#include "ull_adv_types.h"
|
||||
#include "ull_adv_internal.h"
|
||||
|
||||
#include "ull_internal.h"
|
||||
#include "ull_scan_internal.h"
|
||||
#include "ull_conn_internal.h"
|
||||
#include "ull_sync_internal.h"
|
||||
#include "ull_sync_iso_internal.h"
|
||||
#include "ull_df_internal.h"
|
||||
|
@ -377,10 +391,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx)
|
|||
if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) {
|
||||
/* Check address and update internal state */
|
||||
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||
ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr,
|
||||
ull_sync_setup_addr_check(sync, scan, pdu->tx_addr, ptr,
|
||||
ftr->rl_idx);
|
||||
#else /* !CONFIG_BT_CTLR_PRIVACY */
|
||||
ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr, 0U);
|
||||
ull_sync_setup_addr_check(sync, scan, pdu->tx_addr, ptr, 0U);
|
||||
#endif /* !CONFIG_BT_CTLR_PRIVACY */
|
||||
|
||||
}
|
||||
|
@ -420,7 +434,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx)
|
|||
* Periodic Advertiser List or with the explicitly supplied.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && aux && sync && adi &&
|
||||
ull_sync_setup_sid_match(scan, PDU_ADV_ADI_SID_GET(adi))) {
|
||||
ull_sync_setup_sid_match(sync, scan, PDU_ADV_ADI_SID_GET(adi))) {
|
||||
ull_sync_setup(scan, aux, rx, si);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,15 +22,10 @@ struct ll_scan_set {
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
||||
struct {
|
||||
uint8_t sid;
|
||||
|
||||
uint8_t adv_addr_type:2;
|
||||
uint8_t filter_policy:1;
|
||||
uint8_t cancelled:1;
|
||||
uint8_t state:2;
|
||||
|
||||
uint8_t adv_addr[BDADDR_SIZE];
|
||||
|
||||
/* Non-Null when creating sync, reset in ISR context on
|
||||
* synchronisation state and checked in Thread context when
|
||||
* cancelling sync create, hence the volatile keyword.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <soc.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
@ -27,25 +28,41 @@
|
|||
#include "pdu.h"
|
||||
|
||||
#include "lll.h"
|
||||
#include "lll/lll_adv_types.h"
|
||||
#include "lll_adv.h"
|
||||
#include "lll/lll_adv_pdu.h"
|
||||
#include "lll_clock.h"
|
||||
#include "lll/lll_vendor.h"
|
||||
#include "lll_chan.h"
|
||||
#include "lll_scan.h"
|
||||
#include "lll/lll_df_types.h"
|
||||
#include "lll_conn.h"
|
||||
#include "lll_conn_iso.h"
|
||||
#include "lll_sync.h"
|
||||
#include "lll_sync_iso.h"
|
||||
|
||||
#include "isoal.h"
|
||||
|
||||
#include "ull_tx_queue.h"
|
||||
|
||||
#include "ull_filter.h"
|
||||
#include "ull_iso_types.h"
|
||||
#include "ull_scan_types.h"
|
||||
#include "ull_sync_types.h"
|
||||
#include "ull_conn_types.h"
|
||||
#include "ull_adv_types.h"
|
||||
#include "ull_conn_iso_types.h"
|
||||
|
||||
#include "ull_internal.h"
|
||||
#include "ull_adv_internal.h"
|
||||
#include "ull_scan_internal.h"
|
||||
#include "ull_sync_internal.h"
|
||||
#include "ull_conn_internal.h"
|
||||
#include "ull_conn_iso_internal.h"
|
||||
#include "ull_df_types.h"
|
||||
#include "ull_df_internal.h"
|
||||
|
||||
#include "ull_llcp.h"
|
||||
#include "ll.h"
|
||||
|
||||
#include <soc.h>
|
||||
|
@ -59,6 +76,8 @@
|
|||
*/
|
||||
MEM_FREE_MEMBER_ACCESS_BUILD_ASSERT(struct ll_sync_set, timeout_reload);
|
||||
|
||||
static struct ll_sync_set *ull_sync_create(uint8_t sid, uint16_t timeout, uint16_t skip,
|
||||
uint8_t cte_type, uint8_t rx_enable, uint8_t nodups);
|
||||
static int init_reset(void);
|
||||
static inline struct ll_sync_set *sync_acquire(void);
|
||||
static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_op_cb);
|
||||
|
@ -98,12 +117,10 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
|
|||
uint16_t sync_timeout, uint8_t sync_cte_type)
|
||||
{
|
||||
struct ll_scan_set *scan_coded;
|
||||
memq_link_t *link_sync_estab;
|
||||
memq_link_t *link_sync_lost;
|
||||
struct node_rx_pdu *node_rx;
|
||||
struct lll_sync *lll_sync;
|
||||
struct ll_scan_set *scan;
|
||||
struct ll_sync_set *sync;
|
||||
uint8_t rx_enable;
|
||||
uint8_t nodups;
|
||||
|
||||
scan = ull_scan_set_get(SCAN_HANDLE_1M);
|
||||
if (!scan || scan->periodic.sync) {
|
||||
|
@ -125,32 +142,11 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
|
|||
}
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */
|
||||
|
||||
link_sync_estab = ll_rx_link_alloc();
|
||||
if (!link_sync_estab) {
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
rx_enable = !(options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED);
|
||||
nodups = (options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_FILTER_DUPLICATE) ? 1U : 0U;
|
||||
|
||||
link_sync_lost = ll_rx_link_alloc();
|
||||
if (!link_sync_lost) {
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
|
||||
node_rx = ll_rx_alloc();
|
||||
if (!node_rx) {
|
||||
ll_rx_link_release(link_sync_lost);
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
|
||||
sync = sync_acquire();
|
||||
sync = ull_sync_create(sid, sync_timeout, skip, sync_cte_type, rx_enable, nodups);
|
||||
if (!sync) {
|
||||
ll_rx_release(node_rx);
|
||||
ll_rx_link_release(link_sync_lost);
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
|
||||
|
@ -166,55 +162,10 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
|
|||
}
|
||||
|
||||
if (!scan->periodic.filter_policy) {
|
||||
scan->periodic.sid = sid;
|
||||
scan->periodic.adv_addr_type = adv_addr_type;
|
||||
(void)memcpy(scan->periodic.adv_addr, adv_addr, BDADDR_SIZE);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
|
||||
scan_coded->periodic.sid = scan->periodic.sid;
|
||||
scan_coded->periodic.adv_addr_type =
|
||||
scan->periodic.adv_addr_type;
|
||||
(void)memcpy(scan_coded->periodic.adv_addr,
|
||||
scan->periodic.adv_addr, BDADDR_SIZE);
|
||||
}
|
||||
sync->peer_id_addr_type = adv_addr_type;
|
||||
(void)memcpy(sync->peer_id_addr, adv_addr, BDADDR_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize sync context */
|
||||
node_rx->hdr.link = link_sync_estab;
|
||||
sync->node_rx_lost.rx.hdr.link = link_sync_lost;
|
||||
|
||||
/* Make sure that the node_rx_sync_establ hasn't got anything assigned. It is used to
|
||||
* mark when sync establishment is in progress.
|
||||
*/
|
||||
LL_ASSERT(!sync->node_rx_sync_estab);
|
||||
sync->node_rx_sync_estab = node_rx;
|
||||
|
||||
/* Reporting initially enabled/disabled */
|
||||
sync->rx_enable =
|
||||
!(options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)
|
||||
sync->nodups = (options &
|
||||
BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_FILTER_DUPLICATE) ?
|
||||
1U : 0U;
|
||||
#endif
|
||||
sync->skip = skip;
|
||||
sync->is_stop = 0U;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||
sync->enc = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
|
||||
|
||||
/* NOTE: Use timeout not zero to represent sync context used for sync
|
||||
* create.
|
||||
*/
|
||||
sync->timeout = sync_timeout;
|
||||
|
||||
/* NOTE: Use timeout_reload not zero to represent sync established. */
|
||||
sync->timeout_reload = 0U;
|
||||
sync->timeout_expire = 0U;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)
|
||||
/* Remember the peer address when periodic advertiser list is not
|
||||
* used.
|
||||
* NOTE: Peer address will be filled/overwritten with correct identity
|
||||
|
@ -226,42 +177,11 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
|
|||
sizeof(sync->peer_id_addr));
|
||||
}
|
||||
|
||||
/* Remember the SID */
|
||||
sync->sid = sid;
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||
/* Reset Broadcast Isochronous Group Sync Establishment */
|
||||
sync->iso.sync_iso = NULL;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
|
||||
|
||||
/* Initialize sync LLL context */
|
||||
lll_sync = &sync->lll;
|
||||
lll_sync->lll_aux = NULL;
|
||||
lll_sync->is_rx_enabled = sync->rx_enable;
|
||||
lll_sync->skip_prepare = 0U;
|
||||
lll_sync->skip_event = 0U;
|
||||
lll_sync->window_widening_prepare_us = 0U;
|
||||
lll_sync->window_widening_event_us = 0U;
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING)
|
||||
lll_sync->cte_type = sync_cte_type;
|
||||
lll_sync->filter_policy = scan->periodic.filter_policy;
|
||||
/* Set filter policy in lll_sync */
|
||||
sync->lll.filter_policy = scan->periodic.filter_policy;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
|
||||
ull_df_sync_cfg_init(&lll_sync->df_cfg);
|
||||
LL_ASSERT(!lll_sync->node_cte_incomplete);
|
||||
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
|
||||
|
||||
/* Initialise ULL and LLL headers */
|
||||
ull_hdr_init(&sync->ull);
|
||||
lll_hdr_init(lll_sync, sync);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN)
|
||||
/* Initialise LLL abort count */
|
||||
lll_sync->abort_count = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */
|
||||
|
||||
/* Enable scanner to create sync */
|
||||
scan->periodic.sync = sync;
|
||||
|
||||
|
@ -279,6 +199,243 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
void ull_sync_setup_from_sync_transfer(struct ll_conn *conn, uint16_t service_data,
|
||||
struct ll_sync_set *sync, struct pdu_adv_sync_info *si,
|
||||
int16_t conn_evt_offset, uint16_t last_pa_event_counter,
|
||||
uint16_t sync_conn_event_count, uint8_t sender_sca)
|
||||
{
|
||||
struct node_rx_past_received *se_past;
|
||||
uint32_t ticks_slot_overhead;
|
||||
uint32_t ticks_slot_offset;
|
||||
uint32_t conn_interval_us;
|
||||
uint32_t sync_offset_us;
|
||||
uint32_t ready_delay_us;
|
||||
struct node_rx_pdu *rx;
|
||||
uint8_t *data_chan_map;
|
||||
struct lll_sync *lll;
|
||||
uint32_t interval_us;
|
||||
uint32_t slot_us;
|
||||
uint32_t ticks_anchor;
|
||||
uint8_t chm_last;
|
||||
uint32_t ret;
|
||||
uint16_t interval;
|
||||
uint16_t sync_handle;
|
||||
uint8_t sca;
|
||||
|
||||
lll = &sync->lll;
|
||||
|
||||
/* Copy channel map from sca_chm field in sync_info structure, and
|
||||
* clear the SCA bits.
|
||||
*/
|
||||
chm_last = lll->chm_first;
|
||||
lll->chm_last = chm_last;
|
||||
data_chan_map = lll->chm[chm_last].data_chan_map;
|
||||
(void)memcpy(data_chan_map, si->sca_chm,
|
||||
sizeof(lll->chm[chm_last].data_chan_map));
|
||||
data_chan_map[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
|
||||
~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
|
||||
lll->chm[chm_last].data_chan_count =
|
||||
util_ones_count_get(data_chan_map,
|
||||
sizeof(lll->chm[chm_last].data_chan_map));
|
||||
if (lll->chm[chm_last].data_chan_count < CHM_USED_COUNT_MIN) {
|
||||
/* Ignore sync setup, invalid available channel count */
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(lll->access_addr, si->aa, sizeof(lll->access_addr));
|
||||
lll->data_chan_id = lll_chan_id(lll->access_addr);
|
||||
memcpy(lll->crc_init, si->crc_init, sizeof(lll->crc_init));
|
||||
lll->event_counter = sys_le16_to_cpu(si->evt_cntr);
|
||||
|
||||
interval = sys_le16_to_cpu(si->interval);
|
||||
interval_us = interval * PERIODIC_INT_UNIT_US;
|
||||
|
||||
/* Convert fromm 10ms units to interval units */
|
||||
if (sync->timeout != 0 && interval_us != 0) {
|
||||
sync->timeout_reload = RADIO_SYNC_EVENTS((sync->timeout * 10U *
|
||||
USEC_PER_MSEC), interval_us);
|
||||
}
|
||||
|
||||
/* Adjust Skip value so that there is minimum of 6 events that can be
|
||||
* listened to before Sync_Timeout occurs.
|
||||
* The adjustment of the skip value is controller implementation
|
||||
* specific and not specified by the Bluetooth Core Specification v5.3.
|
||||
* The Controller `may` use the Skip value, and the implementation here
|
||||
* covers a case where Skip value could lead to less events being
|
||||
* listened to until Sync_Timeout. Listening to more consecutive events
|
||||
* before Sync_Timeout increases probability of retaining the Periodic
|
||||
* Synchronization.
|
||||
*/
|
||||
if (sync->timeout_reload > CONN_ESTAB_COUNTDOWN) {
|
||||
uint16_t skip_max = sync->timeout_reload - CONN_ESTAB_COUNTDOWN;
|
||||
|
||||
if (sync->skip > skip_max) {
|
||||
sync->skip = skip_max;
|
||||
}
|
||||
}
|
||||
|
||||
sync->sync_expire = CONN_ESTAB_COUNTDOWN;
|
||||
|
||||
/* Extract the SCA value from the sca_chm field of the sync_info
|
||||
* structure.
|
||||
*/
|
||||
sca = (si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &
|
||||
PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK) >>
|
||||
PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS;
|
||||
|
||||
lll->sca = sca;
|
||||
|
||||
lll->window_widening_periodic_us =
|
||||
DIV_ROUND_UP(((lll_clock_ppm_local_get() +
|
||||
lll_clock_ppm_get(sca)) *
|
||||
interval_us), USEC_PER_SEC);
|
||||
lll->window_widening_max_us = (interval_us >> 1) - EVENT_IFS_US;
|
||||
if (PDU_ADV_SYNC_INFO_OFFS_UNITS_GET(si)) {
|
||||
lll->window_size_event_us = OFFS_UNIT_300_US;
|
||||
} else {
|
||||
lll->window_size_event_us = OFFS_UNIT_30_US;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
|
||||
lll->node_cte_incomplete = NULL;
|
||||
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
|
||||
|
||||
/* Prepare Periodic Advertising Sync Transfer Received event (dispatched later) */
|
||||
sync_handle = ull_sync_handle_get(sync);
|
||||
rx = (void *)sync->node_rx_sync_estab;
|
||||
rx->hdr.type = NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED;
|
||||
rx->hdr.handle = sync_handle;
|
||||
rx->rx_ftr.param = sync;
|
||||
|
||||
/* Create node_rx and assign values */
|
||||
se_past = (void *)rx->pdu;
|
||||
se_past->rx_sync.status = BT_HCI_ERR_SUCCESS;
|
||||
se_past->rx_sync.interval = interval;
|
||||
se_past->rx_sync.phy = sync->lll.phy;
|
||||
se_past->rx_sync.sca = sca;
|
||||
se_past->conn_handle = ll_conn_handle_get(conn);
|
||||
se_past->service_data = service_data;
|
||||
|
||||
conn_interval_us = conn->lll.interval * CONN_INT_UNIT_US;
|
||||
|
||||
/* Calculate offset and schedule sync radio events */
|
||||
ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy, PHY_FLAGS_S8);
|
||||
|
||||
sync_offset_us = PDU_ADV_SYNC_INFO_OFFSET_GET(si) * lll->window_size_event_us;
|
||||
/* offs_adjust may be 1 only if sync setup by LL_PERIODIC_SYNC_IND */
|
||||
sync_offset_us += (PDU_ADV_SYNC_INFO_OFFS_ADJUST_GET(si) ? OFFS_ADJUST_US : 0U);
|
||||
sync_offset_us -= EVENT_TICKER_RES_MARGIN_US;
|
||||
sync_offset_us -= EVENT_JITTER_US;
|
||||
sync_offset_us -= ready_delay_us;
|
||||
|
||||
if (conn_evt_offset) {
|
||||
int64_t conn_offset_us = (int64_t)conn_evt_offset * conn_interval_us;
|
||||
|
||||
if ((int64_t)sync_offset_us + conn_offset_us < 0) {
|
||||
uint32_t total_offset_us = abs((int64_t)sync_offset_us + conn_offset_us);
|
||||
uint32_t sync_intervals = DIV_ROUND_UP(total_offset_us, interval_us);
|
||||
|
||||
lll->event_counter += sync_intervals;
|
||||
sync_offset_us = (sync_intervals * interval_us) - total_offset_us;
|
||||
} else {
|
||||
sync_offset_us += conn_offset_us;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate initial window widening - see Core Spec vol 6, part B, 5.1.13.1 */
|
||||
{
|
||||
uint16_t event_delta;
|
||||
uint32_t drift_us;
|
||||
uint64_t da;
|
||||
uint64_t db;
|
||||
uint64_t d;
|
||||
|
||||
const uint32_t local_sca_ppm = lll_clock_ppm_local_get();
|
||||
|
||||
event_delta = lll->event_counter - last_pa_event_counter;
|
||||
|
||||
da = (uint64_t)(local_sca_ppm + lll_clock_ppm_get(sca)) * interval_us;
|
||||
da = DIV_ROUND_UP(da * (uint64_t)event_delta, USEC_PER_SEC);
|
||||
|
||||
db = (uint64_t)(local_sca_ppm + lll_clock_ppm_get(sender_sca)) * conn_interval_us;
|
||||
db = DIV_ROUND_UP(db * (uint64_t)(ull_conn_event_counter(conn) -
|
||||
sync_conn_event_count), USEC_PER_SEC);
|
||||
|
||||
d = DIV_ROUND_UP((da + db) * (USEC_PER_SEC + local_sca_ppm +
|
||||
lll_clock_ppm_get(sca) +
|
||||
lll_clock_ppm_get(sender_sca)), USEC_PER_SEC);
|
||||
|
||||
/* Limit drift compenstion to the maximum window widening */
|
||||
drift_us = MIN((uint32_t)d, lll->window_widening_max_us);
|
||||
|
||||
/* Apply total drift to initial window size */
|
||||
lll->window_size_event_us += drift_us;
|
||||
|
||||
/* Adjust offset if less than the drift compensation */
|
||||
while (sync_offset_us < drift_us) {
|
||||
sync_offset_us += interval_us;
|
||||
lll->event_counter++;
|
||||
}
|
||||
|
||||
sync_offset_us -= drift_us;
|
||||
}
|
||||
|
||||
interval_us -= lll->window_widening_periodic_us;
|
||||
|
||||
/* Calculate event time reservation */
|
||||
slot_us = PDU_AC_MAX_US(PDU_AC_EXT_PAYLOAD_RX_SIZE, lll->phy);
|
||||
slot_us += ready_delay_us;
|
||||
|
||||
/* Add implementation defined radio event overheads */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX)) {
|
||||
slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
|
||||
}
|
||||
|
||||
/* TODO: active_to_start feature port */
|
||||
sync->ull.ticks_active_to_start = 0U;
|
||||
sync->ull.ticks_prepare_to_start =
|
||||
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
|
||||
sync->ull.ticks_preempt_to_start =
|
||||
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
|
||||
sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us);
|
||||
|
||||
ticks_slot_offset = MAX(sync->ull.ticks_active_to_start,
|
||||
sync->ull.ticks_prepare_to_start);
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
|
||||
ticks_slot_overhead = ticks_slot_offset;
|
||||
} else {
|
||||
ticks_slot_overhead = 0U;
|
||||
}
|
||||
ticks_slot_offset += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
|
||||
|
||||
sync->lll_sync_prepare = lll_sync_create_prepare;
|
||||
|
||||
ticks_anchor = conn->llcp.prep.ticks_at_expire;
|
||||
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) {
|
||||
/* Compensate for window widening */
|
||||
ticks_anchor += HAL_TICKER_US_TO_TICKS(conn->lll.periph.window_widening_event_us);
|
||||
}
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
|
||||
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
|
||||
(TICKER_ID_SCAN_SYNC_BASE + sync_handle),
|
||||
ticks_anchor,
|
||||
HAL_TICKER_US_TO_TICKS(sync_offset_us),
|
||||
HAL_TICKER_US_TO_TICKS(interval_us),
|
||||
HAL_TICKER_REMAINDER(interval_us),
|
||||
TICKER_NULL_LAZY,
|
||||
(sync->ull.ticks_slot + ticks_slot_overhead),
|
||||
ticker_cb, sync,
|
||||
ticker_start_op_cb, (void *)__LINE__);
|
||||
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
|
||||
(ret == TICKER_STATUS_BUSY));
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
|
||||
uint8_t ll_sync_create_cancel(void **rx)
|
||||
{
|
||||
struct ll_scan_set *scan_coded;
|
||||
|
@ -353,7 +510,7 @@ uint8_t ll_sync_create_cancel(void **rx)
|
|||
/* It is safe to remove association with scanner as cancelled flag is
|
||||
* set, sync is_stop flag was set and sync has not been established.
|
||||
*/
|
||||
ull_sync_setup_reset(scan);
|
||||
ull_sync_setup_reset(sync);
|
||||
|
||||
/* Mark the sync context as sync create cancelled */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)) {
|
||||
|
@ -431,6 +588,22 @@ uint8_t ll_sync_terminate(uint16_t handle)
|
|||
LL_ASSERT(!aux->parent);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
/* Clean up node_rx_sync_estab if still present */
|
||||
if (sync->node_rx_sync_estab) {
|
||||
memq_link_t *link_sync_estab;
|
||||
struct node_rx_pdu *node_rx;
|
||||
|
||||
node_rx = (void *)sync->node_rx_sync_estab;
|
||||
link_sync_estab = node_rx->hdr.link;
|
||||
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
ll_rx_release(node_rx);
|
||||
|
||||
sync->node_rx_sync_estab = NULL;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
link_sync_lost = sync->node_rx_lost.rx.hdr.link;
|
||||
ll_rx_link_release(link_sync_lost);
|
||||
|
||||
|
@ -474,6 +647,111 @@ uint8_t ll_sync_recv_enable(uint16_t handle, uint8_t enable)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
/* @brief Link Layer interface function corresponding to HCI LE Set Periodic
|
||||
* Advertising Sync Transfer command.
|
||||
*
|
||||
* @param[in] conn_handle Connection_Handle identifying the connected device
|
||||
* Range: 0x0000 to 0x0EFF.
|
||||
* @param[in] service_data Service_Data value provided by the Host for use by the
|
||||
* Host of the peer device.
|
||||
* @param[in] sync_handle Sync_Handle identifying the periodic advertising
|
||||
* train. Range: 0x0000 to 0x0EFF.
|
||||
*
|
||||
* @return HCI error codes as documented in Bluetooth Core Specification v5.4.
|
||||
*/
|
||||
uint8_t ll_sync_transfer(uint16_t conn_handle, uint16_t service_data, uint16_t sync_handle)
|
||||
{
|
||||
struct ll_sync_set *sync;
|
||||
struct ll_conn *conn;
|
||||
|
||||
conn = ll_connected_get(conn_handle);
|
||||
if (!conn) {
|
||||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
/* Verify that sync_handle is valid */
|
||||
sync = ull_sync_is_enabled_get(sync_handle);
|
||||
if (!sync) {
|
||||
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
|
||||
}
|
||||
|
||||
/* Call llcp to start LLCP_PERIODIC_SYNC_IND */
|
||||
return ull_cp_periodic_sync(conn, sync, NULL, service_data);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
/* @brief Link Layer interface function corresponding to HCI LE Set Periodic
|
||||
* Advertising Sync Transfer Parameters command.
|
||||
*
|
||||
* @param[in] conn_handle Connection_Handle identifying the connected device
|
||||
* Range: 0x0000 to 0x0EFF.
|
||||
* @param[in] mode Mode specifies the action to be taken when a periodic advertising
|
||||
* synchronization is received.
|
||||
* @param[in] skip Skip specifying the number of consectutive periodic advertising
|
||||
* packets that the receiver may skip after successfully reciving a
|
||||
* periodic advertising packet. Range: 0x0000 to 0x01F3.
|
||||
* @param[in] timeout Sync_timeout specifying the maximum permitted time between
|
||||
* successful receives. Range: 0x000A to 0x4000.
|
||||
* @param[in] cte_type CTE_Type specifying whether to only synchronize to periodic
|
||||
* advertising with certain types of Constant Tone Extension.
|
||||
*
|
||||
* @return HCI error codes as documented in Bluetooth Core Specification v5.4.
|
||||
*/
|
||||
uint8_t ll_past_param(uint16_t conn_handle, uint8_t mode, uint16_t skip, uint16_t timeout,
|
||||
uint8_t cte_type)
|
||||
{
|
||||
struct ll_conn *conn;
|
||||
|
||||
conn = ll_connected_get(conn_handle);
|
||||
if (!conn) {
|
||||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
if (mode == BT_HCI_LE_PAST_MODE_SYNC_FILTER_DUPLICATES &&
|
||||
!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)) {
|
||||
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
|
||||
}
|
||||
|
||||
/* Set PAST Param for connection instance */
|
||||
conn->past.mode = mode;
|
||||
conn->past.skip = skip;
|
||||
conn->past.timeout = timeout;
|
||||
conn->past.cte_type = cte_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @brief Link Layer interface function corresponding to HCI LE Set Default Periodic
|
||||
* Advertising Sync Transfer Parameters command.
|
||||
*
|
||||
* @param[in] mode Mode specifies the action to be taken when a periodic advertising
|
||||
* synchronization is received.
|
||||
* @param[in] skip Skip specifying the number of consectutive periodic advertising
|
||||
* packets that the receiver may skip after successfully reciving a
|
||||
* periodic advertising packet. Range: 0x0000 to 0x01F3.
|
||||
* @param[in] timeout Sync_timeout specifying the maximum permitted time between
|
||||
* successful receives. Range: 0x000A to 0x4000.
|
||||
* @param[in] cte_type CTE_Type specifying whether to only synchronize to periodic
|
||||
* advertising with certain types of Constant Tone Extension.
|
||||
*
|
||||
* @return HCI error codes as documented in Bluetooth Core Specification v5.4.
|
||||
*/
|
||||
uint8_t ll_default_past_param(uint8_t mode, uint16_t skip, uint16_t timeout, uint8_t cte_type)
|
||||
{
|
||||
if (mode == BT_HCI_LE_PAST_MODE_SYNC_FILTER_DUPLICATES &&
|
||||
!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)) {
|
||||
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
|
||||
}
|
||||
|
||||
/* Set default past param */
|
||||
ull_conn_default_past_param_set(mode, skip, timeout, cte_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
||||
int ull_sync_init(void)
|
||||
{
|
||||
int err;
|
||||
|
@ -594,8 +872,8 @@ void ull_sync_release(struct ll_sync_set *sync)
|
|||
mem_release(sync, &sync_free);
|
||||
}
|
||||
|
||||
void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
|
||||
uint8_t *addr, uint8_t rl_idx)
|
||||
void ull_sync_setup_addr_check(struct ll_sync_set *sync, struct ll_scan_set *scan,
|
||||
uint8_t addr_type, uint8_t *addr, uint8_t rl_idx)
|
||||
{
|
||||
/* Check if Periodic Advertiser list to be used */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADV_LIST) &&
|
||||
|
@ -605,8 +883,8 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
|
|||
/* Remember the address, to check with
|
||||
* SID in Sync Info
|
||||
*/
|
||||
scan->periodic.adv_addr_type = addr_type;
|
||||
(void)memcpy(scan->periodic.adv_addr, addr,
|
||||
sync->peer_id_addr_type = addr_type;
|
||||
(void)memcpy(sync->peer_id_addr, addr,
|
||||
BDADDR_SIZE);
|
||||
|
||||
/* Address matched */
|
||||
|
@ -615,22 +893,22 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
|
|||
/* Check in Resolving List */
|
||||
} else if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) &&
|
||||
ull_filter_ull_pal_listed(rl_idx, &addr_type,
|
||||
scan->periodic.adv_addr)) {
|
||||
sync->peer_id_addr)) {
|
||||
/* Remember the address, to check with the
|
||||
* SID in Sync Info
|
||||
*/
|
||||
scan->periodic.adv_addr_type = addr_type;
|
||||
sync->peer_id_addr_type = addr_type;
|
||||
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
scan->periodic.adv_addr_type += 2U;
|
||||
/* Mark it as identity address from RPA */
|
||||
sync->peer_addr_resolved = 1U;
|
||||
|
||||
/* Address matched */
|
||||
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
|
||||
}
|
||||
|
||||
/* Check with explicitly supplied address */
|
||||
} else if ((addr_type == scan->periodic.adv_addr_type) &&
|
||||
!memcmp(addr, scan->periodic.adv_addr, BDADDR_SIZE)) {
|
||||
} else if ((addr_type == sync->peer_id_addr_type) &&
|
||||
!memcmp(addr, sync->peer_id_addr, BDADDR_SIZE)) {
|
||||
/* Address matched */
|
||||
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
|
||||
|
||||
|
@ -638,10 +916,10 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
|
|||
} else if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) &&
|
||||
(rl_idx < ll_rl_size_get())) {
|
||||
ll_rl_id_addr_get(rl_idx, &addr_type, addr);
|
||||
if ((addr_type == scan->periodic.adv_addr_type) &&
|
||||
!memcmp(addr, scan->periodic.adv_addr, BDADDR_SIZE)) {
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
scan->periodic.adv_addr_type += 2U;
|
||||
if ((addr_type == sync->peer_id_addr_type) &&
|
||||
!memcmp(addr, sync->peer_id_addr, BDADDR_SIZE)) {
|
||||
/* Mark it as identity address from RPA */
|
||||
sync->peer_addr_resolved = 1U;
|
||||
|
||||
/* Identity address matched */
|
||||
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
|
||||
|
@ -649,15 +927,15 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
|
|||
}
|
||||
}
|
||||
|
||||
bool ull_sync_setup_sid_match(struct ll_scan_set *scan, uint8_t sid)
|
||||
bool ull_sync_setup_sid_match(struct ll_sync_set *sync, struct ll_scan_set *scan, uint8_t sid)
|
||||
{
|
||||
return (scan->periodic.state == LL_SYNC_STATE_ADDR_MATCH) &&
|
||||
((IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADV_LIST) &&
|
||||
scan->periodic.filter_policy &&
|
||||
ull_filter_ull_pal_match(scan->periodic.adv_addr_type,
|
||||
scan->periodic.adv_addr, sid)) ||
|
||||
ull_filter_ull_pal_match(sync->peer_id_addr_type,
|
||||
sync->peer_id_addr, sid)) ||
|
||||
(!scan->periodic.filter_policy &&
|
||||
(sid == scan->periodic.sid)));
|
||||
(sid == sync->sid)));
|
||||
}
|
||||
|
||||
void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
||||
|
@ -705,18 +983,6 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) || \
|
||||
defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)
|
||||
/* Remember the peer address.
|
||||
* NOTE: Peer identity address is copied here when privacy is enable.
|
||||
*/
|
||||
sync->peer_id_addr_type = scan->periodic.adv_addr_type & 0x01;
|
||||
(void)memcpy(sync->peer_id_addr, scan->periodic.adv_addr,
|
||||
sizeof(sync->peer_id_addr));
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC ||
|
||||
* CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT
|
||||
*/
|
||||
|
||||
memcpy(lll->access_addr, si->aa, sizeof(lll->access_addr));
|
||||
lll->data_chan_id = lll_chan_id(lll->access_addr);
|
||||
memcpy(lll->crc_init, si->crc_init, sizeof(lll->crc_init));
|
||||
|
@ -727,7 +993,12 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
|||
interval = sys_le16_to_cpu(si->interval);
|
||||
interval_us = interval * PERIODIC_INT_UNIT_US;
|
||||
|
||||
/* Convert from 10ms units to interval units */
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
/* Save Periodic Advertisement Interval */
|
||||
sync->interval = interval;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
|
||||
/* Convert fromm 10ms units to interval units */
|
||||
sync->timeout_reload = RADIO_SYNC_EVENTS((sync->timeout * 10U *
|
||||
USEC_PER_MSEC), interval_us);
|
||||
|
||||
|
@ -803,7 +1074,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
|||
rx = (void *)sync->node_rx_sync_estab;
|
||||
rx->hdr.type = NODE_RX_TYPE_SYNC;
|
||||
rx->hdr.handle = sync_handle;
|
||||
rx->rx_ftr.param = scan;
|
||||
rx->rx_ftr.param = sync;
|
||||
se = (void *)rx->pdu;
|
||||
se->interval = interval;
|
||||
se->phy = lll->phy;
|
||||
|
@ -813,7 +1084,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
|||
ftr = &node_rx->rx_ftr;
|
||||
pdu = (void *)((struct node_rx_pdu *)node_rx)->pdu;
|
||||
|
||||
ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy, 1);
|
||||
ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy, PHY_FLAGS_S8);
|
||||
|
||||
sync_offset_us = ftr->radio_end_us;
|
||||
sync_offset_us += PDU_ADV_SYNC_INFO_OFFSET_GET(si) *
|
||||
|
@ -885,9 +1156,13 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
|||
(ret == TICKER_STATUS_BUSY));
|
||||
}
|
||||
|
||||
void ull_sync_setup_reset(struct ll_scan_set *scan)
|
||||
void ull_sync_setup_reset(struct ll_sync_set *sync)
|
||||
{
|
||||
struct ll_scan_set *scan;
|
||||
|
||||
/* Remove the sync context from being associated with scan contexts */
|
||||
scan = ull_scan_set_get(SCAN_HANDLE_1M);
|
||||
|
||||
scan->periodic.sync = NULL;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST)
|
||||
|
@ -895,14 +1170,7 @@ void ull_sync_setup_reset(struct ll_scan_set *scan)
|
|||
#endif /* CONFIG_BT_CTLR_FILTER_ACCEPT_LIST */
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
|
||||
struct ll_scan_set *scan_1m;
|
||||
|
||||
scan_1m = ull_scan_set_get(SCAN_HANDLE_1M);
|
||||
if (scan == scan_1m) {
|
||||
scan = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
|
||||
} else {
|
||||
scan = scan_1m;
|
||||
}
|
||||
|
||||
scan->periodic.sync = NULL;
|
||||
|
||||
|
@ -965,8 +1233,7 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_pdu *rx)
|
|||
#endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
||||
/* Prepare and dispatch sync notification */
|
||||
rx_establ = sync->node_rx_sync_estab;
|
||||
rx_establ->hdr.type = NODE_RX_TYPE_SYNC;
|
||||
rx_establ = (void *)sync->node_rx_sync_estab;
|
||||
rx_establ->hdr.handle = ull_sync_handle_get(sync);
|
||||
se = (void *)rx_establ->pdu;
|
||||
/* Clear the node to mark the sync establish as being completed.
|
||||
|
@ -1297,6 +1564,110 @@ static inline struct ll_sync_set *sync_acquire(void)
|
|||
return mem_acquire(&sync_free);
|
||||
}
|
||||
|
||||
static struct ll_sync_set *ull_sync_create(uint8_t sid, uint16_t timeout, uint16_t skip,
|
||||
uint8_t cte_type, uint8_t rx_enable, uint8_t nodups)
|
||||
{
|
||||
memq_link_t *link_sync_estab;
|
||||
memq_link_t *link_sync_lost;
|
||||
struct node_rx_pdu *node_rx;
|
||||
struct lll_sync *lll;
|
||||
struct ll_sync_set *sync;
|
||||
|
||||
link_sync_estab = ll_rx_link_alloc();
|
||||
if (!link_sync_estab) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
link_sync_lost = ll_rx_link_alloc();
|
||||
if (!link_sync_lost) {
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_rx = ll_rx_alloc();
|
||||
if (!node_rx) {
|
||||
ll_rx_link_release(link_sync_lost);
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sync = sync_acquire();
|
||||
if (!sync) {
|
||||
ll_rx_release(node_rx);
|
||||
ll_rx_link_release(link_sync_lost);
|
||||
ll_rx_link_release(link_sync_estab);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sync->peer_addr_resolved = 0U;
|
||||
|
||||
/* Initialize sync context */
|
||||
node_rx->hdr.link = link_sync_estab;
|
||||
sync->node_rx_lost.rx.hdr.link = link_sync_lost;
|
||||
|
||||
/* Make sure that the node_rx_sync_establ hasn't got anything assigned. It is used to
|
||||
* mark when sync establishment is in progress.
|
||||
*/
|
||||
LL_ASSERT(!sync->node_rx_sync_estab);
|
||||
sync->node_rx_sync_estab = node_rx;
|
||||
|
||||
/* Reporting initially enabled/disabled */
|
||||
sync->rx_enable = rx_enable;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)
|
||||
sync->nodups = nodups;
|
||||
#endif
|
||||
sync->skip = skip;
|
||||
sync->is_stop = 0U;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||
sync->enc = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
|
||||
|
||||
/* NOTE: Use timeout not zero to represent sync context used for sync
|
||||
* create.
|
||||
*/
|
||||
sync->timeout = timeout;
|
||||
|
||||
/* NOTE: Use timeout_reload not zero to represent sync established. */
|
||||
sync->timeout_reload = 0U;
|
||||
sync->timeout_expire = 0U;
|
||||
|
||||
/* Remember the SID */
|
||||
sync->sid = sid;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||
/* Reset Broadcast Isochronous Group Sync Establishment */
|
||||
sync->iso.sync_iso = NULL;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
|
||||
|
||||
/* Initialize sync LLL context */
|
||||
lll = &sync->lll;
|
||||
lll->lll_aux = NULL;
|
||||
lll->is_rx_enabled = sync->rx_enable;
|
||||
lll->skip_prepare = 0U;
|
||||
lll->skip_event = 0U;
|
||||
lll->window_widening_prepare_us = 0U;
|
||||
lll->window_widening_event_us = 0U;
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING)
|
||||
lll->cte_type = cte_type;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
|
||||
ull_df_sync_cfg_init(&lll->df_cfg);
|
||||
LL_ASSERT(!lll->node_cte_incomplete);
|
||||
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
|
||||
|
||||
/* Initialise ULL and LLL headers */
|
||||
ull_hdr_init(&sync->ull);
|
||||
lll_hdr_init(lll, sync);
|
||||
|
||||
return sync;
|
||||
}
|
||||
|
||||
static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_op_cb)
|
||||
{
|
||||
uint16_t sync_handle = ull_sync_handle_get(sync);
|
||||
|
@ -1388,7 +1759,6 @@ static void sync_expire(void *param)
|
|||
|
||||
/* Generate Periodic advertising sync failed to establish */
|
||||
rx = (void *)sync->node_rx_sync_estab;
|
||||
rx->hdr.type = NODE_RX_TYPE_SYNC;
|
||||
rx->hdr.handle = LLL_HANDLE_INVALID;
|
||||
|
||||
/* Clear the node to mark the sync establish as being completed.
|
||||
|
@ -1535,3 +1905,61 @@ static struct pdu_cte_info *pdu_cte_info_get(struct pdu_adv *pdu)
|
|||
return (struct pdu_cte_info *)hdr->data;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING && !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER)
|
||||
void ull_sync_transfer_received(struct ll_conn *conn, uint16_t service_data,
|
||||
struct pdu_adv_sync_info *si, uint16_t conn_event_count,
|
||||
uint16_t last_pa_event_counter, uint8_t sid,
|
||||
uint8_t addr_type, uint8_t sca, uint8_t phy,
|
||||
uint8_t *adv_addr, uint16_t sync_conn_event_count,
|
||||
uint8_t addr_resolved)
|
||||
{
|
||||
struct ll_sync_set *sync;
|
||||
uint16_t conn_evt_current;
|
||||
uint8_t rx_enable;
|
||||
uint8_t nodups;
|
||||
|
||||
if (conn->past.mode == BT_HCI_LE_PAST_MODE_NO_SYNC) {
|
||||
/* Ignore LL_PERIODIC_SYNC_IND - see Bluetooth Core Specification v5.4
|
||||
* Vol 6, Part E, Section 7.8.91
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)
|
||||
/* Do not sync twice to the same peer and same SID */
|
||||
if (peer_sid_sync_exists(addr_type, adv_addr, sid)) {
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */
|
||||
|
||||
nodups = (conn->past.mode == BT_HCI_LE_PAST_MODE_SYNC_FILTER_DUPLICATES) ? 1U : 0U;
|
||||
rx_enable = (conn->past.mode == BT_HCI_LE_PAST_MODE_NO_REPORTS) ? 0U : 1U;
|
||||
|
||||
sync = ull_sync_create(sid, conn->past.timeout, conn->past.skip, conn->past.cte_type,
|
||||
rx_enable, nodups);
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING)
|
||||
/* Reset filter policy in lll_sync */
|
||||
sync->lll.filter_policy = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
||||
sync->peer_id_addr_type = addr_type;
|
||||
sync->peer_addr_resolved = addr_resolved;
|
||||
memcpy(sync->peer_id_addr, adv_addr, BDADDR_SIZE);
|
||||
sync->lll.phy = phy;
|
||||
|
||||
conn_evt_current = ull_conn_event_counter(conn);
|
||||
|
||||
/* LLCP should have ensured this holds */
|
||||
LL_ASSERT(sync_conn_event_count != conn_evt_current);
|
||||
|
||||
ull_sync_setup_from_sync_transfer(conn, service_data, sync, si,
|
||||
conn_event_count - conn_evt_current,
|
||||
last_pa_event_counter, sync_conn_event_count,
|
||||
sca);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */
|
||||
|
|
|
@ -9,15 +9,25 @@ int ull_sync_reset(void);
|
|||
uint16_t ull_sync_handle_get(struct ll_sync_set *sync);
|
||||
struct ll_sync_set *ull_sync_is_enabled_get(uint16_t handle);
|
||||
void ull_sync_release(struct ll_sync_set *sync);
|
||||
void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
|
||||
uint8_t *addr, uint8_t rl_idx);
|
||||
bool ull_sync_setup_sid_match(struct ll_scan_set *scan, uint8_t sid);
|
||||
void ull_sync_setup_addr_check(struct ll_sync_set *sync, struct ll_scan_set *scan,
|
||||
uint8_t addr_type, uint8_t *addr, uint8_t rl_idx);
|
||||
bool ull_sync_setup_sid_match(struct ll_sync_set *sync, struct ll_scan_set *scan, uint8_t sid);
|
||||
void ull_sync_create_from_sync_transfer(uint16_t conn_handle, uint16_t service_data,
|
||||
struct ll_sync_set *sync,
|
||||
struct pdu_adv_sync_info *si,
|
||||
uint32_t conn_offset_us);
|
||||
void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
|
||||
struct node_rx_pdu *node_rx, struct pdu_adv_sync_info *si);
|
||||
void ull_sync_setup_reset(struct ll_scan_set *scan);
|
||||
void ull_sync_setup_reset(struct ll_sync_set *sync);
|
||||
void ull_sync_established_report(memq_link_t *link, struct node_rx_pdu *rx);
|
||||
void ull_sync_done(struct node_rx_event_done *done);
|
||||
void ull_sync_chm_update(uint8_t sync_handle, uint8_t *acad, uint8_t acad_len);
|
||||
int ull_sync_slot_update(struct ll_sync_set *sync, uint32_t slot_plus_us,
|
||||
uint32_t slot_minus_us);
|
||||
struct ll_sync_set *ull_sync_is_valid_get(struct ll_sync_set *sync);
|
||||
void ull_sync_transfer_received(struct ll_conn *conn, uint16_t service_data,
|
||||
struct pdu_adv_sync_info *si, uint16_t conn_event_count,
|
||||
uint16_t last_pa_event_counter, uint8_t sid,
|
||||
uint8_t addr_type, uint8_t sca, uint8_t phy,
|
||||
uint8_t *adv_addr, uint16_t sync_conn_event_count,
|
||||
uint8_t addr_resolved);
|
||||
|
|
|
@ -31,18 +31,26 @@
|
|||
#include "lll/lll_df_types.h"
|
||||
#include "lll_sync.h"
|
||||
#include "lll_sync_iso.h"
|
||||
#include "lll_conn.h"
|
||||
#include "lll_conn_iso.h"
|
||||
|
||||
#include "isoal.h"
|
||||
|
||||
#include "ull_tx_queue.h"
|
||||
|
||||
#include "ull_scan_types.h"
|
||||
#include "ull_sync_types.h"
|
||||
#include "ull_iso_types.h"
|
||||
#include "ull_conn_types.h"
|
||||
#include "ull_conn_iso_types.h"
|
||||
|
||||
#include "ull_internal.h"
|
||||
#include "ull_scan_internal.h"
|
||||
#include "ull_sync_internal.h"
|
||||
#include "ull_iso_internal.h"
|
||||
#include "ull_sync_iso_internal.h"
|
||||
#include "ull_conn_internal.h"
|
||||
#include "ull_conn_iso_internal.h"
|
||||
|
||||
#include "ll.h"
|
||||
|
||||
|
|
|
@ -32,13 +32,9 @@ struct ll_sync_set {
|
|||
*/
|
||||
void (*lll_sync_prepare)(void *param);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) || \
|
||||
defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)
|
||||
uint8_t peer_id_addr[BDADDR_SIZE];
|
||||
uint8_t peer_id_addr_type:1;
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC ||
|
||||
* CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT
|
||||
*/
|
||||
uint8_t peer_addr_resolved:1;
|
||||
|
||||
uint8_t rx_enable:1;
|
||||
|
||||
|
@ -62,9 +58,7 @@ struct ll_sync_set {
|
|||
uint8_t num_bis : 5;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)
|
||||
uint8_t sid;
|
||||
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */
|
||||
|
||||
/* node rx type with memory aligned storage for sync lost reason.
|
||||
* HCI will reference the value using the pdu member of
|
||||
|
@ -94,8 +88,10 @@ struct ll_sync_set {
|
|||
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
|
||||
|
||||
uint16_t data_len;
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
|
||||
uint16_t interval;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
|
||||
};
|
||||
|
||||
struct node_rx_sync {
|
||||
uint8_t status;
|
||||
uint8_t phy;
|
||||
|
@ -103,6 +99,12 @@ struct node_rx_sync {
|
|||
uint8_t sca;
|
||||
};
|
||||
|
||||
struct node_rx_past_received {
|
||||
struct node_rx_sync rx_sync;
|
||||
uint16_t conn_handle;
|
||||
uint16_t service_data;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||
struct ll_sync_iso_set {
|
||||
struct ull_hdr ull;
|
||||
|
|
|
@ -23,8 +23,12 @@
|
|||
#include <lll_scan.h>
|
||||
#include <lll/lll_df_types.h>
|
||||
#include <lll_sync.h>
|
||||
#include <lll_conn.h>
|
||||
#include <ull_tx_queue.h>
|
||||
#include <ull_scan_types.h>
|
||||
#include <ull_scan_internal.h>
|
||||
#include <ull_conn_types.h>
|
||||
#include <ull_conn_internal.h>
|
||||
#include <ull_sync_types.h>
|
||||
#include <ull_sync_internal.h>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue