/* * Copyright (c) 2018-2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include "hal/ccm.h" #include "hal/radio.h" #include "hal/ticker.h" #include "util/util.h" #include "util/memq.h" #include "util/mayfly.h" #include "util/dbuf.h" #include "ticker/ticker.h" #include "pdu.h" #include "lll.h" #include "lll/lll_vendor.h" #include "lll/lll_adv_types.h" #include "lll_adv.h" #include "lll/lll_adv_pdu.h" #include "lll_adv_sync.h" #include "lll_scan.h" #include "lll/lll_df_types.h" #include "lll_conn.h" #if !defined(CONFIG_BT_LL_SW_LLCP_LEGACY) #include "ull_tx_queue.h" #endif #include "ull_adv_types.h" #include "ull_scan_types.h" #include "ull_conn_types.h" #include "ull_internal.h" #include "ull_adv_internal.h" #include "ull_conn_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) #define LOG_MODULE_NAME bt_ctlr_ull_sched #include "common/log.h" #include "hal/debug.h" typedef struct ull_hdr *(*ull_hdr_get_func)(uint8_t ticker_id); #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select, uint32_t *ticks_to_offset_next, uint16_t conn_interval, uint8_t *offset_max, uint8_t *win_offset); #endif #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, ticker_op_match_func ticker_match_op_cb, ull_hdr_get_func ull_hdr_get_cb, uint32_t *ticks_anchor, uint32_t *ticks_to_expire_match, uint32_t *ticks_slot_match); static void ticker_op_cb(uint32_t status, void *param); #if defined(CONFIG_BT_CONN) static bool ticker_conn_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot, uint32_t ticks_to_expire, void *op_context); static struct ull_hdr *conn_ull_hdr_get_cb(uint8_t ticker_id); static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot, uint32_t ticks_anchor, uint32_t *win_offset_us); #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_CTLR_ADV_ISO) static bool ticker_adv_sync_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot, uint32_t ticks_to_expire, void *op_context); static struct ull_hdr *adv_sync_ull_hdr_get_cb(uint8_t ticker_id); int ull_sched_after_adv_sync_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, uint32_t *ticks_anchor) { uint32_t ticks_to_expire; uint32_t ticks_slot; uint8_t ticker_id; ticker_id = after_match_slot_get(user_id, ticks_slot_abs, ticker_adv_sync_match_op_cb, adv_sync_ull_hdr_get_cb, ticks_anchor, &ticks_to_expire, &ticks_slot); if (ticker_id != TICKER_NULL) { const struct ll_adv_sync_set *sync = (void *)adv_sync_ull_hdr_get_cb(ticker_id); uint32_t time_us; time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX); *ticks_anchor += ticks_to_expire; *ticks_anchor += HAL_TICKER_US_TO_TICKS(time_us); return 0; } return -ECHILD; } #endif /* CONFIG_BT_CTLR_ADV_ISO */ #if defined(CONFIG_BT_CONN) int ull_sched_after_cen_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, uint32_t *ticks_anchor, uint32_t *us_offset) { uint32_t ticks_to_expire; uint32_t ticks_slot; uint8_t ticker_id; ticker_id = after_match_slot_get(user_id, ticks_slot_abs, ticker_conn_match_op_cb, conn_ull_hdr_get_cb, ticks_anchor, &ticks_to_expire, &ticks_slot); if (ticker_id != TICKER_NULL) { *us_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire + ticks_slot) + (EVENT_JITTER_US << 3); return 0; } return -ECHILD; } #if defined(CONFIG_BT_CENTRAL) void ull_sched_mfy_after_cen_offset_get(void *param) { struct lll_prepare_param *p = param; struct lll_scan *lll = p->param; uint32_t ticks_slot_overhead; struct ll_conn *conn; conn = HDR_LLL2ULL(lll->conn); if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { ticks_slot_overhead = MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start); } else { ticks_slot_overhead = 0U; } after_cen_offset_get(lll->conn->interval, (ticks_slot_overhead + conn->ull.ticks_slot), p->ticks_at_expire, &lll->conn_win_offset_us); } #endif /* CONFIG_BT_CENTRAL */ void ull_sched_mfy_win_offset_use(void *param) { struct ll_conn *conn = param; uint32_t ticks_slot_overhead; /* * TODO: update when updating the connection update procedure */ #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) uint16_t win_offset; #endif if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { ticks_slot_overhead = MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start); } else { ticks_slot_overhead = 0U; } /* * TODO: update when updating the connection update procedure */ #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) after_cen_offset_get(conn->lll.interval, (ticks_slot_overhead + conn->ull.ticks_slot), conn->llcp.conn_upd.ticks_anchor, &conn->llcp_cu.win_offset_us); win_offset = conn->llcp_cu.win_offset_us / CONN_INT_UNIT_US; sys_put_le16(win_offset, (void *)conn->llcp.conn_upd.pdu_win_offset); /* move to offset calculated state */ conn->llcp_cu.state = LLCP_CUI_STATE_OFFS_RDY; #endif } #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) void ull_sched_mfy_free_win_offset_calc(void *param) { uint32_t ticks_to_offset_default = 0U; uint32_t *ticks_to_offset_next; /* * TODO: update when updating the connection update procedure */ #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) uint8_t offset_max = 6U; struct ll_conn *conn = param; #endif ticks_to_offset_next = &ticks_to_offset_default; /* * TODO: update when updating the connection update procedure */ #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) #if defined(CONFIG_BT_PERIPHERAL) if (conn->lll.role) { conn->llcp_conn_param.ticks_to_offset_next = conn->periph.ticks_to_offset; ticks_to_offset_next = &conn->llcp_conn_param.ticks_to_offset_next; } #endif /* CONFIG_BT_PERIPHERAL */ win_offset_calc(conn, 0, ticks_to_offset_next, conn->llcp_conn_param.interval_max, &offset_max, (void *)conn->llcp_conn_param.pdu_win_offset0); /* move to offset calculated state */ conn->llcp_conn_param.state = LLCP_CPR_STATE_OFFS_RDY; #endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ } void ull_sched_mfy_win_offset_select(void *param) { #define OFFSET_S_MAX 6 #define OFFSET_M_MAX 6 #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) uint16_t win_offset_m[OFFSET_M_MAX] = {0, }; uint8_t offset_m_max = OFFSET_M_MAX; struct ll_conn *conn = param; uint8_t offset_index_s = 0U; uint8_t has_offset_s = 0U; uint16_t win_offset_s; uint32_t ticks_to_offset; #endif /* * TODO: update when updating the connection update procedure */ #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) ticks_to_offset = HAL_TICKER_US_TO_TICKS(conn->llcp_conn_param.offset0 * CONN_INT_UNIT_US); win_offset_calc(conn, 1, &ticks_to_offset, conn->llcp_conn_param.interval_max, &offset_m_max, (void *)win_offset_m); while (offset_index_s < OFFSET_S_MAX) { uint8_t offset_index_m = 0U; win_offset_s = sys_get_le16((uint8_t *)&conn->llcp_conn_param.offset0 + (sizeof(uint16_t) * offset_index_s)); while (offset_index_m < offset_m_max) { if (win_offset_s != 0xffff) { if (win_offset_s == win_offset_m[offset_index_m]) { break; } has_offset_s = 1U; } offset_index_m++; } if (offset_index_m < offset_m_max) { break; } offset_index_s++; } if (offset_index_s < OFFSET_S_MAX) { conn->llcp_cu.win_offset_us = win_offset_s * CONN_INT_UNIT_US; sys_put_le16(win_offset_s, (void *)conn->llcp.conn_upd.pdu_win_offset); /* move to offset calculated state */ conn->llcp_cu.state = LLCP_CUI_STATE_OFFS_RDY; } else if (!has_offset_s) { conn->llcp_cu.win_offset_us = win_offset_m[0] * CONN_INT_UNIT_US; sys_put_le16(win_offset_m[0], (void *)conn->llcp.conn_upd.pdu_win_offset); /* move to offset calculated state */ conn->llcp_cu.state = LLCP_CUI_STATE_OFFS_RDY; } else { struct pdu_data *pdu_ctrl_tx; /* send reject_ind_ext */ pdu_ctrl_tx = CONTAINER_OF(conn->llcp.conn_upd.pdu_win_offset, struct pdu_data, llctrl.conn_update_ind.win_offset); pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL; pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, reject_ext_ind) + sizeof(struct pdu_data_llctrl_reject_ext_ind); pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND; pdu_ctrl_tx->llctrl.reject_ext_ind.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ; pdu_ctrl_tx->llctrl.reject_ext_ind.error_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL; /* move to conn param reject */ conn->llcp_cu.state = LLCP_CUI_STATE_REJECT; } #endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ #undef OFFSET_S_MAX #undef OFFSET_M_MAX } #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select, uint32_t *ticks_to_offset_next, uint16_t conn_interval, uint8_t *offset_max, uint8_t *win_offset) { uint32_t ticks_prepare_reduced = 0U; uint32_t ticks_to_expire_prev; uint32_t ticks_slot_abs_prev; uint32_t ticks_slot_abs = 0U; uint32_t ticks_anchor_prev; uint32_t ticks_to_expire; uint8_t ticker_id_other; uint8_t ticker_id_prev; uint32_t ticks_anchor; uint8_t offset_index; uint8_t ticker_id; uint16_t offset; #if defined(CONFIG_BT_CTLR_LOW_LAT) #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) if (conn_curr->ull.ticks_prepare_to_start & XON_BITMASK) { uint32_t ticks_prepare_to_start = MAX(conn_curr->ull.ticks_active_to_start, conn_curr->ull.ticks_preempt_to_start); ticks_slot_abs = conn_curr->ull.ticks_prepare_to_start & ~XON_BITMASK; ticks_prepare_reduced = ticks_slot_abs - ticks_prepare_to_start; } else #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ { uint32_t ticks_prepare_to_start = MAX(conn_curr->ull.ticks_active_to_start, conn_curr->ull.ticks_prepare_to_start); ticks_slot_abs = ticks_prepare_to_start; } #endif ticks_slot_abs += conn_curr->ull.ticks_slot; if (conn_curr->lll.role) { ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_TIES_US); } ticker_id = ticker_id_prev = ticker_id_other = TICKER_NULL; ticks_to_expire = ticks_to_expire_prev = ticks_anchor = ticks_anchor_prev = offset_index = offset = 0U; ticks_slot_abs_prev = 0U; do { uint32_t volatile ret_cb; struct ll_conn *conn; uint32_t ret; bool success; ret_cb = TICKER_STATUS_BUSY; ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_LOW, &ticker_id, &ticks_anchor, &ticks_to_expire, ticker_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); } } /* Using a local variable to address the Coverity rule: * Incorrect expression (ASSERT_SIDE_EFFECT) * Argument "ret_cb" of LL_ASSERT() has a side effect * because the variable is volatile. The containing function * might work differently in a non-debug build. */ success = (ret_cb == TICKER_STATUS_SUCCESS); LL_ASSERT(success); if (ticker_id == TICKER_NULL) { break; } /* ticks_anchor shall not change during this loop */ if ((ticker_id_prev != TICKER_NULL) && (ticks_anchor != ticks_anchor_prev)) { LL_ASSERT(0); } /* consider advertiser time as available. Any other time used by * tickers declared outside the controller is also available. */ #if defined(CONFIG_BT_BROADCASTER) if ((ticker_id < TICKER_ID_ADV_BASE) || (ticker_id > TICKER_ID_CONN_LAST)) #else /* !CONFIG_BT_BROADCASTER */ if ((ticker_id < TICKER_ID_SCAN_BASE) || (ticker_id > TICKER_ID_CONN_LAST)) #endif /* !CONFIG_BT_BROADCASTER */ { continue; } if (ticker_id < TICKER_ID_CONN_BASE) { /* non conn role found which could have preempted a * conn role, hence do not consider this free space * and any further as free slot for offset, */ ticker_id_other = ticker_id; continue; } /* TODO: handle scanner; for now we exit with as much we * where able to fill (offsets). */ if (ticker_id_other != TICKER_NULL) { break; } conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE); if ((conn != conn_curr) && (is_select || !conn->lll.role)) { uint32_t ticks_to_expire_normal = ticks_to_expire + ticks_prepare_reduced; uint32_t ticks_slot_margin = 0U; uint32_t ticks_slot_abs_curr = 0U; #if defined(CONFIG_BT_CTLR_LOW_LAT) #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) if (conn->ull.ticks_prepare_to_start & XON_BITMASK) { uint32_t ticks_prepare_to_start = MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_preempt_to_start); ticks_slot_abs_curr = conn->ull.ticks_prepare_to_start & ~XON_BITMASK; ticks_to_expire_normal -= ticks_slot_abs_curr - ticks_prepare_to_start; } else #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ { uint32_t ticks_prepare_to_start = MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start); ticks_slot_abs_curr = ticks_prepare_to_start; } #endif ticks_slot_abs_curr += conn->ull.ticks_slot + HAL_TICKER_US_TO_TICKS(CONN_INT_UNIT_US); if (conn->lll.role) { ticks_slot_margin = HAL_TICKER_US_TO_TICKS(EVENT_TIES_US); ticks_slot_abs_curr += ticks_slot_margin; } if (*ticks_to_offset_next < ticks_to_expire_normal) { if (ticks_to_expire_prev < *ticks_to_offset_next) { ticks_to_expire_prev = *ticks_to_offset_next; } while ((offset_index < *offset_max) && (ticker_ticks_diff_get( ticks_to_expire_normal, ticks_to_expire_prev) >= (ticks_slot_abs_prev + ticks_slot_abs + ticks_slot_margin))) { offset = (ticks_to_expire_prev + ticks_slot_abs_prev) / HAL_TICKER_US_TO_TICKS( CONN_INT_UNIT_US); if (offset >= conn_interval) { ticks_to_expire_prev = 0U; break; } sys_put_le16(offset, (win_offset + (sizeof(uint16_t) * offset_index))); offset_index++; ticks_to_expire_prev += HAL_TICKER_US_TO_TICKS( CONN_INT_UNIT_US); } *ticks_to_offset_next = ticks_to_expire_prev; if (offset >= conn_interval) { break; } } ticks_anchor_prev = ticks_anchor; ticker_id_prev = ticker_id; ticks_to_expire_prev = ticks_to_expire_normal; ticks_slot_abs_prev = ticks_slot_abs_curr; } } while (offset_index < *offset_max); if (ticker_id == TICKER_NULL) { if (ticks_to_expire_prev < *ticks_to_offset_next) { ticks_to_expire_prev = *ticks_to_offset_next; } while (offset_index < *offset_max) { offset = (ticks_to_expire_prev + ticks_slot_abs_prev) / HAL_TICKER_US_TO_TICKS(CONN_INT_UNIT_US); if (offset >= conn_interval) { ticks_to_expire_prev = 0U; break; } sys_put_le16(offset, (win_offset + (sizeof(uint16_t) * offset_index))); offset_index++; ticks_to_expire_prev += HAL_TICKER_US_TO_TICKS( CONN_INT_UNIT_US); } *ticks_to_offset_next = ticks_to_expire_prev; } *offset_max = offset_index; } #endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ #endif /* CONFIG_BT_CONN */ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, ticker_op_match_func ticker_match_op_cb, ull_hdr_get_func ull_hdr_get_cb, uint32_t *ticks_anchor, uint32_t *ticks_to_expire_match, uint32_t *ticks_slot_match) { uint32_t ticks_to_expire_prev; uint32_t ticks_slot_abs_prev; uint32_t ticks_to_expire; uint8_t ticker_id_prev; uint8_t ticker_id; ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_JITTER_US << 3); ticker_id = ticker_id_prev = TICKER_NULL; ticks_to_expire = ticks_to_expire_prev = 0U; ticks_slot_abs_prev = 0U; while (1) { uint32_t ticks_slot_abs_curr = 0U; uint32_t ticks_to_expire_normal; uint32_t volatile ret_cb; struct ull_hdr *hdr; uint32_t ret; bool success; ret_cb = TICKER_STATUS_BUSY; #if defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH) ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR, user_id, &ticker_id, ticks_anchor, &ticks_to_expire, NULL, /* lazy */ ticker_match_op_cb, NULL, /* match_op_context */ ticker_op_cb, (void *)&ret_cb); #else /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */ ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, user_id, &ticker_id, ticks_anchor, &ticks_to_expire, ticker_op_cb, (void *)&ret_cb); #endif /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */ if (ret == TICKER_STATUS_BUSY) { while (ret_cb == TICKER_STATUS_BUSY) { ticker_job_sched(TICKER_INSTANCE_ID_CTLR, user_id); } } /* Using a local variable to address the Coverity rule: * Incorrect expression (ASSERT_SIDE_EFFECT) * Argument "ret_cb" of LL_ASSERT() has a side effect * because the variable is volatile. The containing function * might work differently in a non-debug build. */ success = (ret_cb == TICKER_STATUS_SUCCESS); LL_ASSERT(success); if (ticker_id == TICKER_NULL) { break; } #if !defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH) if (!ticker_match_op_cb(ticker_id, 0, 0, NULL)) { continue; } #endif /* CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */ hdr = ull_hdr_get_cb(ticker_id); if (!hdr) { continue; } ticks_to_expire_normal = ticks_to_expire; #if defined(CONFIG_BT_CTLR_LOW_LAT) #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) if (hdr->ticks_prepare_to_start & XON_BITMASK) { const uint32_t ticks_prepare_to_start = MAX(hdr->ticks_active_to_start, hdr->ticks_preempt_to_start); ticks_slot_abs_curr = hdr->ticks_prepare_to_start & ~XON_BITMASK; ticks_to_expire_normal -= ticks_slot_abs_curr - ticks_prepare_to_start; } else #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ { const uint32_t ticks_prepare_to_start = MAX(hdr->ticks_active_to_start, hdr->ticks_prepare_to_start); ticks_slot_abs_curr = ticks_prepare_to_start; } #endif ticks_slot_abs_curr += hdr->ticks_slot; if ((ticker_id_prev != TICKER_NULL) && (ticker_ticks_diff_get(ticks_to_expire_normal, ticks_to_expire_prev) > (ticks_slot_abs_prev + ticks_slot_abs))) { break; } ticker_id_prev = ticker_id; ticks_to_expire_prev = ticks_to_expire_normal; ticks_slot_abs_prev = ticks_slot_abs_curr; } if (ticker_id_prev != TICKER_NULL) { *ticks_to_expire_match = ticks_to_expire_prev; *ticks_slot_match = ticks_slot_abs_prev; } return ticker_id_prev; } static void ticker_op_cb(uint32_t status, void *param) { *((uint32_t volatile *)param) = status; } #if defined(CONFIG_BT_CONN) static bool ticker_conn_match_op_cb(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); ARG_UNUSED(op_context); return (ticker_id >= TICKER_ID_CONN_BASE) && (ticker_id <= TICKER_ID_CONN_LAST); } static struct ull_hdr *conn_ull_hdr_get_cb(uint8_t ticker_id) { struct ll_conn *conn; conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE); if (!conn || conn->lll.role) { return NULL; } return &conn->ull; } static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot, uint32_t ticks_anchor, uint32_t *win_offset_us) { uint32_t ticks_anchor_offset = ticks_anchor; int err; err = ull_sched_after_cen_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot, &ticks_anchor_offset, win_offset_us); if (err) { return; } if ((ticks_anchor_offset - ticks_anchor) & BIT(HAL_TICKER_CNTR_MSBIT)) { *win_offset_us -= HAL_TICKER_TICKS_TO_US( ticker_ticks_diff_get(ticks_anchor, ticks_anchor_offset)); } else { *win_offset_us += HAL_TICKER_TICKS_TO_US( ticker_ticks_diff_get(ticks_anchor_offset, ticks_anchor)); } if ((*win_offset_us & BIT(31)) == 0) { uint32_t conn_interval_us = conn_interval * CONN_INT_UNIT_US; while (*win_offset_us > conn_interval_us) { *win_offset_us -= conn_interval_us; } } } #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_CTLR_ADV_ISO) static bool ticker_adv_sync_match_op_cb(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); ARG_UNUSED(op_context); return (ticker_id >= TICKER_ID_ADV_SYNC_BASE) && (ticker_id <= TICKER_ID_ADV_SYNC_LAST); } static struct ull_hdr *adv_sync_ull_hdr_get_cb(uint8_t ticker_id) { struct ll_adv_sync_set *sync; sync = ull_adv_sync_get(ticker_id - TICKER_ID_ADV_SYNC_BASE); if (!sync) { return NULL; } return &sync->ull; } #endif /* CONFIG_BT_CTLR_ADV_ISO */