From baef416d5d0d8282c5a826491a60bc7998f324f3 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 11 Aug 2020 11:12:34 +0530 Subject: [PATCH] Bluetooth: controller: Added Periodic Sync Terminate and Sync Lost Added implementation to perform Periodic Sync Terminate, generation of Sync Lost on terminate and on remote device termination of Periodic Advertising. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/hci/hci.c | 28 ++- subsys/bluetooth/controller/include/ll.h | 2 +- subsys/bluetooth/controller/ll_sw/lll_sync.h | 4 +- .../controller/ll_sw/nordic/lll/lll_sync.c | 28 +-- subsys/bluetooth/controller/ll_sw/ull.c | 12 +- subsys/bluetooth/controller/ll_sw/ull_conn.c | 10 +- .../controller/ll_sw/ull_conn_internal.h | 3 - .../bluetooth/controller/ll_sw/ull_internal.h | 6 + .../controller/ll_sw/ull_scan_types.h | 4 - subsys/bluetooth/controller/ll_sw/ull_sync.c | 174 +++++++++++++++--- .../controller/ll_sw/ull_sync_types.h | 7 +- 11 files changed, 221 insertions(+), 57 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 80943a5c561..d10105fea8b 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2088,7 +2088,8 @@ static void le_per_adv_create_sync_cancel(struct net_buf *buf, ccst->status = status; } -static void le_per_adv_terminate_sync(struct net_buf *buf, struct net_buf **evt) +static void le_per_adv_terminate_sync(struct net_buf *buf, struct net_buf **evt, + void **node_rx) { struct bt_hci_cp_le_per_adv_terminate_sync *cmd = (void *)buf->data; struct bt_hci_evt_cc_status *ccst; @@ -2097,7 +2098,7 @@ static void le_per_adv_terminate_sync(struct net_buf *buf, struct net_buf **evt) handle = sys_le16_to_cpu(cmd->handle); - status = ll_sync_terminate(handle); + status = ll_sync_terminate(handle, node_rx); ccst = hci_cmd_complete(evt, sizeof(*ccst)); ccst->status = status; @@ -2445,7 +2446,7 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, break; case BT_OCF(BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC): - le_per_adv_terminate_sync(cmd, evt); + le_per_adv_terminate_sync(cmd, evt, node_rx); break; /* FIXME: Enable when definition is added to hci.h */ @@ -3841,6 +3842,21 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data, sep->interval = sys_cpu_to_le16(se->interval); sep->clock_accuracy = se->sca; } + +static void le_per_adv_sync_lost(struct pdu_data *pdu_data, + struct node_rx_pdu *node_rx, + struct net_buf *buf) +{ + struct bt_hci_evt_le_per_adv_sync_lost *sep; + + if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) || + !(le_event_mask & BT_EVT_MASK_LE_PER_ADV_SYNC_LOST)) { + return; + } + + sep = meta_evt(buf, BT_HCI_EVT_LE_PER_ADV_SYNC_LOST, sizeof(*sep)); + sep->handle = sys_cpu_to_le16(node_rx->hdr.handle); +} #endif /* CONFIG_BT_CTLR_SCAN_PERIODIC */ #endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_OBSERVER */ @@ -3866,8 +3882,8 @@ static void le_adv_ext_terminate(struct pdu_data *pdu_data, sep->num_completed_ext_adv_evts = node_rx->hdr.rx_ftr.param_adv_term.num_events; } -#endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_BROADCASTER */ +#endif /* CONFIG_BT_CTLR_ADV_EXT */ #if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) static void le_scan_req_received(struct pdu_data *pdu_data, @@ -4201,6 +4217,9 @@ static void encode_control(struct node_rx_pdu *node_rx, case NODE_RX_TYPE_SYNC: le_per_adv_sync_established(pdu_data, node_rx, buf); break; + case NODE_RX_TYPE_SYNC_LOST: + le_per_adv_sync_lost(pdu_data, node_rx, buf); + break; #endif /* CONFIG_BT_CTLR_SCAN_PERIODIC */ #endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_OBSERVER */ @@ -4641,6 +4660,7 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #if defined(CONFIG_BT_CTLR_SCAN_PERIODIC) __fallthrough; case NODE_RX_TYPE_SYNC: + case NODE_RX_TYPE_SYNC_LOST: #endif /* CONFIG_BT_CTLR_SCAN_PERIODIC */ #if defined(CONFIG_BT_BROADCASTER) diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 05c1b0654f3..430669f01aa 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -102,7 +102,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, uint8_t *adv_addr, uint16_t skip, uint16_t sync_timeout, uint8_t sync_cte_type); uint8_t ll_sync_create_cancel(void **rx); -uint8_t ll_sync_terminate(uint16_t handle); +uint8_t ll_sync_terminate(uint16_t handle, void **rx); uint8_t ll_sync_recv_enable(uint16_t handle, uint8_t enable); #else /* !CONFIG_BT_CTLR_ADV_EXT */ uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window, diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync.h b/subsys/bluetooth/controller/ll_sw/lll_sync.h index 9057cbe9eb0..9b177738360 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync.h @@ -10,8 +10,8 @@ struct lll_sync { uint8_t access_addr[4]; uint8_t crc_init[3]; - uint16_t latency_prepare; - uint16_t latency_event; + uint16_t skip_prepare; + uint16_t skip_event; uint16_t event_counter; uint8_t data_chan_map[5]; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 6cb51b2d903..55245ace9a6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -78,8 +78,8 @@ void lll_sync_prepare(void *param) /* Instants elapsed */ elapsed = p->lazy + 1; - /* Save the (latency + 1) for use in event */ - lll->latency_prepare += elapsed; + /* Save the (skip + 1) for use in event */ + lll->skip_prepare += elapsed; /* Accumulate window widening */ lll->window_widening_prepare_us += lll->window_widening_periodic_us * @@ -115,17 +115,17 @@ static int prepare_cb(struct lll_prepare_param *p) lll = p->param; - /* Deduce the latency */ - lll->latency_event = lll->latency_prepare - 1; + /* Deduce the skip */ + lll->skip_event = lll->skip_prepare - 1; /* Calculate the current event counter value */ - event_counter = lll->event_counter + lll->latency_event; + event_counter = lll->event_counter + lll->skip_event; /* Update event counter to next value */ - lll->event_counter = lll->event_counter + lll->latency_prepare; + lll->event_counter = lll->event_counter + lll->skip_prepare; /* Reset accumulated latencies */ - lll->latency_prepare = 0; + lll->skip_prepare = 0; /* Current window widening */ lll->window_widening_event_us += lll->window_widening_prepare_us; @@ -242,6 +242,7 @@ static void isr_rx(void *param) struct event_done_extra *e; uint8_t rssi_ready; uint8_t trx_done; + uint8_t trx_cnt; uint8_t crc_ok; /* Read radio status and events */ @@ -257,25 +258,29 @@ static void isr_rx(void *param) lll_isr_rx_status_reset(); /* No Rx */ + trx_cnt = 0U; if (!trx_done) { /* TODO: Combine the early exit with above if-then-else block */ - goto isr_rx_exit; + goto isr_rx_done; } + /* Rx-ed */ + trx_cnt = 1U; + + /* Check CRC and generate Periodic Advertising Report */ if (crc_ok) { /* TODO: */ printk("CRC OK\n"); - } else { - printk("CRC BAD\n"); } +isr_rx_done: /* Calculate and place the drift information in done event */ e = ull_event_done_extra_get(); LL_ASSERT(e); e->type = EVENT_DONE_EXTRA_TYPE_SYNC; - e->trx_cnt = 1U; + e->trx_cnt = trx_cnt; e->crc_valid = crc_ok; #if defined(CONFIG_BT_CTLR_PHY) @@ -292,6 +297,5 @@ static void isr_rx(void *param) lll->window_widening_event_us = 0U; lll->window_size_event_us = 0U; -isr_rx_exit: lll_isr_cleanup(param); } diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index a6b6a46b0ac..87e0658f359 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -739,6 +739,7 @@ void ll_rx_dequeue(void) #if defined(CONFIG_BT_CTLR_SCAN_PERIODIC) /* fall through */ case NODE_RX_TYPE_SYNC: + case NODE_RX_TYPE_SYNC_LOST: #endif /* CONFIG_BT_CTLR_SCAN_PERIODIC */ #endif /* CONFIG_BT_OBSERVER */ @@ -967,14 +968,17 @@ void ll_rx_mem_release(void **node_rx) struct node_rx_sync *se = (void *)((struct node_rx_pdu *)rx_free)->pdu; - if (se->status) { - ull_sync_release(rx_free->rx_ftr.param); + if (!se->status) { + mem_release(rx_free, &mem_pdu_rx.free); break; } + } + /* Pass through */ - ll_rx_link_inc_quota(1); - mem_release(rx_free, &mem_pdu_rx.free); + case NODE_RX_TYPE_SYNC_LOST: + { + ull_sync_release(rx_free->rx_ftr.param); } break; #endif /* CONFIG_BT_CTLR_SCAN_PERIODIC */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index b3b8ac55411..f83670c5828 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1156,7 +1156,7 @@ void ull_conn_done(struct node_rx_event_done *done) conn->supervision_expire -= elapsed_event; /* break latency */ - lll->latency_event = 0; + lll->latency_event = 0U; /* Force both master and slave when close to * supervision timeout. @@ -1175,7 +1175,7 @@ void ull_conn_done(struct node_rx_event_done *done) force = conn->slave.force & 0x01; /* rotate force bits */ - conn->slave.force >>= 1; + conn->slave.force >>= 1U; if (force) { conn->slave.force |= BIT(31); } @@ -1242,7 +1242,7 @@ void ull_conn_done(struct node_rx_event_done *done) #if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT) /* generate RSSI event */ - if (lll->rssi_sample_count == 0) { + if (lll->rssi_sample_count == 0U) { struct node_rx_pdu *rx; struct pdu_data *pdu_data_rx; @@ -1271,13 +1271,13 @@ void ull_conn_done(struct node_rx_event_done *done) ((conn->llcp_type == LLCP_CONN_UPD) || (conn->llcp_type == LLCP_CHAN_MAP))) || (conn->llcp_cu.req != conn->llcp_cu.ack)) { - lll->latency_event = 0; + lll->latency_event = 0U; } /* check if latency needs update */ lazy = 0U; if ((force) || (latency_event != lll->latency_event)) { - lazy = lll->latency_event + 1; + lazy = lll->latency_event + 1U; } /* update conn ticker */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index 2f2eb2b54cb..d4a69019865 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -4,9 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/* Macro to convert time in us to connection interval units */ -#define RADIO_CONN_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y))) - struct ll_conn *ll_conn_acquire(void); void ll_conn_release(struct ll_conn *conn); uint16_t ll_conn_handle_get(struct ll_conn *conn); diff --git a/subsys/bluetooth/controller/ll_sw/ull_internal.h b/subsys/bluetooth/controller/ll_sw/ull_internal.h index cda8628ee20..e42fe932c3e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_internal.h @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Macro to convert time in us to connection interval units */ +#define RADIO_CONN_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y))) + +/* Macro to convert time in us to periodic advertising interval units */ +#define RADIO_SYNC_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y))) + static inline uint8_t ull_ref_get(struct ull_hdr *hdr) { return hdr->ref; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h index d67d189e2d4..2626b5bb090 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h @@ -23,10 +23,6 @@ struct ll_scan_set { uint8_t adv_addr[BDADDR_SIZE]; struct node_rx_hdr *node_rx_estab; - struct { - struct node_rx_hdr node_rx_lost; - uint8_t status; - }; struct ll_sync_set *sync; } per_scan; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index c0df6114038..4803f744c9d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -43,10 +43,13 @@ static int init_reset(void); static inline struct ll_sync_set *sync_acquire(void); static struct ll_sync_set *is_enabled_get(uint16_t handle); +static void timeout_cleanup(struct ll_sync_set *sync); static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, void *param); static void ticker_op_cb(uint32_t status, void *param); static void ticker_update_sync_op_cb(uint32_t status, void *param); +static void ticker_stop_op_cb(uint32_t status, void *param); +static void sync_lost(void *param); static struct ll_sync_set ll_sync_pool[CONFIG_BT_CTLR_SCAN_SYNC_SET]; static void *sync_free; @@ -104,8 +107,6 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } - sync->is_enabled = 0U; - scan->per_scan.filter_policy = options & BIT(0); if (!scan->per_scan.filter_policy) { scan->per_scan.sid = sid; @@ -113,16 +114,17 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, memcpy(scan->per_scan.adv_addr, adv_addr, BDADDR_SIZE); } - /* TODO: Support for skip */ - - /* TODO: Support for timeout */ + sync->skip = skip; + sync->timeout = sync_timeout; /* TODO: Support for CTE type */ /* Initialize sync context */ + sync->timeout_reload = 0U; + sync->timeout_expire = 0U; lll_sync = &sync->lll; - lll_sync->latency_prepare = 0U; - lll_sync->latency_event = 0U; + lll_sync->skip_prepare = 0U; + lll_sync->skip_event = 0U; lll_sync->data_chan_id = 0U; lll_sync->window_widening_prepare_us = 0U; lll_sync->window_widening_event_us = 0U; @@ -136,7 +138,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, /* established and sync_lost node_rx */ node_rx->link = link_sync_estab; scan->per_scan.node_rx_estab = node_rx; - scan->per_scan.node_rx_lost.link = link_sync_lost; + sync->node_rx_lost.link = link_sync_lost; /* Initialise ULL and LLL headers */ ull_hdr_init(&sync->ull); @@ -182,19 +184,19 @@ uint8_t ll_sync_create_cancel(void **rx) /* Check for race condition where in sync is established when sync * context was set to NULL. */ - if (sync->is_enabled) { + if (sync->timeout_reload) { return BT_HCI_ERR_CMD_DISALLOWED; } node_rx = (void *)scan->per_scan.node_rx_estab; link_sync_estab = node_rx->hdr.link; - link_sync_lost = scan->per_scan.node_rx_lost.link; + link_sync_lost = sync->node_rx_lost.link; ll_rx_link_release(link_sync_lost); ll_rx_link_release(link_sync_estab); ll_rx_release(node_rx); - node_rx = (void *)&scan->per_scan.node_rx_lost; + node_rx = (void *)&sync->node_rx_lost; node_rx->hdr.type = NODE_RX_TYPE_SYNC; node_rx->hdr.handle = 0xffff; node_rx->hdr.rx_ftr.param = sync; @@ -206,16 +208,47 @@ uint8_t ll_sync_create_cancel(void **rx) return 0; } -uint8_t ll_sync_terminate(uint16_t handle) +uint8_t ll_sync_terminate(uint16_t handle, void **rx) { + struct node_rx_pdu *node_rx; + memq_link_t *link_sync_lost; struct ll_sync_set *sync; + uint32_t volatile ret_cb; + uint32_t ret; + void *mark; sync = is_enabled_get(handle); if (!sync) { + return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER; + } + + mark = ull_disable_mark(sync); + LL_ASSERT(mark == sync); + + ret_cb = TICKER_STATUS_BUSY; + ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD, + TICKER_ID_SCAN_SYNC_BASE + handle, + ull_ticker_status_give, (void *)&ret_cb); + ret = ull_ticker_status_take(ret, &ret_cb); + if (ret) { + mark = ull_disable_mark(sync); + LL_ASSERT(mark == sync); + return BT_HCI_ERR_CMD_DISALLOWED; } - /* TODO: Stop periodic sync events */ + mark = ull_disable_unmark(sync); + LL_ASSERT(mark == sync); + + link_sync_lost = sync->node_rx_lost.link; + ll_rx_link_release(link_sync_lost); + + node_rx = (void *)&sync->node_rx_lost; + node_rx->hdr.type = NODE_RX_TYPE_SYNC_LOST; + node_rx->hdr.handle = handle; + node_rx->hdr.rx_ftr.param = sync; + + *rx = node_rx; return 0; } @@ -296,8 +329,6 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, sync = scan->per_scan.sync; scan->per_scan.sync = NULL; - sync->is_enabled = 1U; - lll = &sync->lll; memcpy(lll->data_chan_map, si->sca_chm, sizeof(lll->data_chan_map)); lll->data_chan_map[4] &= ~0xE0; @@ -316,6 +347,9 @@ 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 * 1250U; + sync->timeout_reload = RADIO_SYNC_EVENTS((sync->timeout * 10U * 1000U), + interval_us); + lll->window_widening_periodic_us = (((lll_clock_ppm_local_get() + lll_clock_ppm_get(sca)) * interval_us) + (1000000 - 1)) / 1000000U; @@ -393,17 +427,72 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, void ull_sync_done(struct node_rx_event_done *done) { struct lll_sync *lll = (void *)HDR_ULL2LLL(done->param); + struct ll_sync_set *sync = (void *)HDR_LLL2EVT(lll); uint32_t ticks_drift_minus; uint32_t ticks_drift_plus; - uint16_t lazy = 0U; - uint8_t force = 0U; + uint16_t elapsed_event; + uint16_t skip_event; + uint16_t lazy; + uint8_t force; - /* TODO: use skip value and decide on the laziness using latency_event. + /* Events elapsed used in timeout checks below */ + skip_event = lll->skip_event; + elapsed_event = skip_event + 1; + + /* Sync drift compensation and new skip calculation */ + ticks_drift_plus = 0U; + ticks_drift_minus = 0U; + if (done->extra.trx_cnt) { + /* Calculate drift in ticks unit */ + ull_drift_ticks_get(done, &ticks_drift_plus, + &ticks_drift_minus); - ull_drift_ticks_get(done, &ticks_drift_plus, &ticks_drift_minus); + /* Enforce skip */ + lll->skip_event = sync->skip; + } + + /* Reset supervision countdown */ + if (done->extra.crc_valid) { + sync->timeout_expire = 0U; + } + + /* if anchor point not sync-ed, start timeout countdown, and break + * skip if any. + */ + else { + if (!sync->timeout_expire) { + sync->timeout_expire = sync->timeout_reload; + } + } + + /* check timeout */ + force = 0U; + if (sync->timeout_expire) { + if (sync->timeout_expire > elapsed_event) { + sync->timeout_expire -= elapsed_event; + + /* break skip */ + lll->skip_event = 0U; + + if (skip_event) { + force = 1U; + } + } else { + timeout_cleanup(sync); + + return; + } + } + + /* check if skip needs update */ + lazy = 0U; + if ((force) || (skip_event != lll->skip_event)) { + lazy = lll->skip_event + 1U; + } + + /* Update Sync ticker instance */ if (ticks_drift_plus || ticks_drift_minus || lazy || force) { - struct ll_sync_set *sync = (void *)HDR_LLL2EVT(lll); uint16_t sync_handle = ull_sync_handle_get(sync); uint32_t ticker_status; @@ -447,13 +536,26 @@ static struct ll_sync_set *is_enabled_get(uint16_t handle) struct ll_sync_set *sync; sync = ull_sync_set_get(handle); - if (!sync || !sync->is_enabled) { + if (!sync || !sync->timeout_reload) { return NULL; } return sync; } +static void timeout_cleanup(struct ll_sync_set *sync) +{ + uint16_t sync_handle = ull_sync_handle_get(sync); + uint32_t ret; + + /* Stop Periodic Sync Ticker */ + ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, + TICKER_ID_SCAN_SYNC_BASE + sync_handle, + ticker_stop_op_cb, (void *)sync); + LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); +} + static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, void *param) { @@ -501,3 +603,33 @@ static void ticker_update_sync_op_cb(uint32_t status, void *param) param == ull_update_mark_get() || param == ull_disable_mark_get()); } + +static void ticker_stop_op_cb(uint32_t status, void *param) +{ + uint32_t retval; + static memq_link_t link; + static struct mayfly mfy = {0, 0, &link, NULL, sync_lost}; + + LL_ASSERT(status == TICKER_STATUS_SUCCESS); + + mfy.param = param; + + retval = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, + 0, &mfy); + LL_ASSERT(!retval); +} + +static void sync_lost(void *param) +{ + struct ll_sync_set *sync = param; + struct node_rx_pdu *rx; + + /* Generate Periodic advertising sync lost */ + rx = (void *)&sync->node_rx_lost; + rx->hdr.handle = ull_sync_handle_get(sync); + rx->hdr.type = NODE_RX_TYPE_SYNC_LOST; + + /* Enqueue the sync lost towards ULL context */ + ll_rx_put(rx->hdr.link, rx); + ll_rx_sched(); +} diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index 4793dd5efa3..0a1617bda27 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -13,7 +13,12 @@ struct ll_sync_set { struct ull_hdr ull; struct lll_sync lll; - uint8_t is_enabled:1; + uint16_t skip; + uint16_t timeout; + uint16_t timeout_reload; + uint16_t timeout_expire; + + struct node_rx_hdr node_rx_lost; }; struct node_rx_sync {