2020-04-21 11:12:41 +05:30
|
|
|
/*
|
|
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2020-08-03 16:28:58 +05:30
|
|
|
#include <sys/byteorder.h>
|
2020-04-21 11:12:41 +05:30
|
|
|
#include <sys/util.h>
|
|
|
|
|
|
|
|
#include "util/mem.h"
|
|
|
|
#include "util/memq.h"
|
|
|
|
#include "util/mayfly.h"
|
2021-04-01 11:44:33 +02:00
|
|
|
#include "util/util.h"
|
2021-10-30 23:40:52 +02:00
|
|
|
#include "util/dbuf.h"
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
#include "hal/ticker.h"
|
2021-11-15 09:41:12 +01:00
|
|
|
#include "hal/ccm.h"
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
#include "ticker/ticker.h"
|
|
|
|
|
|
|
|
#include "pdu.h"
|
|
|
|
|
|
|
|
#include "lll.h"
|
2021-02-24 16:42:02 +05:30
|
|
|
#include "lll/lll_vendor.h"
|
2020-04-21 11:12:41 +05:30
|
|
|
#include "lll_scan.h"
|
|
|
|
#include "lll_scan_aux.h"
|
2021-04-01 11:44:33 +02:00
|
|
|
#include "lll/lll_df_types.h"
|
2021-11-15 09:41:12 +01:00
|
|
|
#include "lll_conn.h"
|
2020-08-11 09:58:34 +05:30
|
|
|
#include "lll_sync.h"
|
2020-11-09 16:31:01 +01:00
|
|
|
#include "lll_sync_iso.h"
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
#include "ull_scan_types.h"
|
2020-08-11 09:48:29 +05:30
|
|
|
#include "ull_sync_types.h"
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
#include "ull_internal.h"
|
|
|
|
#include "ull_scan_internal.h"
|
2020-08-03 16:28:58 +05:30
|
|
|
#include "ull_sync_internal.h"
|
2021-02-18 13:02:24 +05:30
|
|
|
#include "ull_sync_iso_internal.h"
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
|
|
|
#define LOG_MODULE_NAME bt_ctlr_ull_scan_aux
|
|
|
|
#include "common/log.h"
|
|
|
|
#include <soc.h>
|
|
|
|
#include "hal/debug.h"
|
|
|
|
|
|
|
|
static int init_reset(void);
|
|
|
|
static inline struct ll_scan_aux_set *aux_acquire(void);
|
|
|
|
static inline void aux_release(struct ll_scan_aux_set *aux);
|
2020-04-28 14:12:04 +05:30
|
|
|
static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux);
|
2020-11-22 10:13:56 +05:30
|
|
|
static inline struct ll_sync_set *sync_create_get(struct ll_scan_set *scan);
|
2021-02-18 13:02:24 +05:30
|
|
|
static inline struct ll_sync_iso_set *
|
|
|
|
sync_iso_create_get(struct ll_sync_set *sync);
|
2021-04-06 12:10:00 +05:30
|
|
|
static void done_disabled_cb(void *param);
|
2021-11-30 06:46:22 +05:30
|
|
|
static void flush(void *param);
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
static void rx_release_put(struct node_rx_hdr *rx);
|
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
|
2021-09-15 11:48:21 +05:30
|
|
|
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
|
|
|
|
uint32_t remainder, uint16_t lazy, uint8_t force,
|
|
|
|
void *param);
|
2020-04-21 11:12:41 +05:30
|
|
|
static void ticker_op_cb(uint32_t status, void *param);
|
|
|
|
|
2021-12-08 22:31:24 +05:30
|
|
|
/* Auxiliary context pool used for reception of PDUs at aux offsets, common for
|
|
|
|
* both Extended Advertising and Periodic Advertising.
|
|
|
|
* Increasing the count allows simultaneous reception of interleaved chain PDUs
|
|
|
|
* from multiple advertisers.
|
|
|
|
*/
|
2020-04-21 11:12:41 +05:30
|
|
|
static struct ll_scan_aux_set ll_scan_aux_pool[CONFIG_BT_CTLR_SCAN_AUX_SET];
|
|
|
|
static void *scan_aux_free;
|
|
|
|
|
|
|
|
int ull_scan_aux_init(void)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = init_reset();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ull_scan_aux_reset(void)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = init_reset();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-05 18:13:25 +05:30
|
|
|
void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
|
2020-04-21 11:12:41 +05:30
|
|
|
{
|
2021-12-08 22:31:24 +05:30
|
|
|
struct node_rx_hdr *rx_incomplete;
|
2021-02-18 13:02:24 +05:30
|
|
|
struct ll_sync_iso_set *sync_iso;
|
2020-05-12 18:36:05 +05:30
|
|
|
struct pdu_adv_aux_ptr *aux_ptr;
|
2020-04-21 11:12:41 +05:30
|
|
|
struct pdu_adv_com_ext_adv *p;
|
|
|
|
uint32_t ticks_slot_overhead;
|
2021-07-30 06:57:47 +05:30
|
|
|
struct lll_scan_aux *lll_aux;
|
2020-08-11 09:58:34 +05:30
|
|
|
struct ll_scan_aux_set *aux;
|
2020-04-22 16:13:45 +05:30
|
|
|
uint32_t window_widening_us;
|
2020-08-11 09:58:34 +05:30
|
|
|
uint32_t ticks_slot_offset;
|
2021-05-16 14:00:29 +05:30
|
|
|
uint32_t ticks_aux_offset;
|
|
|
|
struct pdu_adv_ext_hdr *h;
|
2021-08-17 18:18:04 +02:00
|
|
|
struct lll_sync *sync_lll;
|
2020-08-03 16:28:58 +05:30
|
|
|
struct ll_scan_set *scan;
|
2020-08-11 09:58:34 +05:30
|
|
|
struct ll_sync_set *sync;
|
|
|
|
struct pdu_adv_adi *adi;
|
2020-04-21 11:12:41 +05:30
|
|
|
struct node_rx_ftr *ftr;
|
|
|
|
uint32_t ready_delay_us;
|
|
|
|
uint32_t aux_offset_us;
|
|
|
|
uint32_t ticker_status;
|
2021-07-30 06:57:47 +05:30
|
|
|
struct lll_scan *lll;
|
2020-08-11 09:58:34 +05:30
|
|
|
struct pdu_adv *pdu;
|
2021-12-01 21:01:23 +05:30
|
|
|
uint8_t hdr_buf_len;
|
2020-04-21 11:12:41 +05:30
|
|
|
uint8_t aux_handle;
|
2021-07-27 21:05:07 +05:30
|
|
|
bool is_scan_req;
|
2021-08-25 20:50:53 +05:30
|
|
|
uint8_t acad_len;
|
2021-12-01 21:01:23 +05:30
|
|
|
uint8_t data_len;
|
2021-08-25 20:50:53 +05:30
|
|
|
uint8_t hdr_len;
|
2020-04-21 11:12:41 +05:30
|
|
|
uint8_t *ptr;
|
2020-11-05 18:13:25 +05:30
|
|
|
uint8_t phy;
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-07-27 21:05:07 +05:30
|
|
|
is_scan_req = false;
|
2020-04-28 14:12:04 +05:30
|
|
|
ftr = &rx->rx_ftr;
|
2020-08-11 09:58:34 +05:30
|
|
|
|
2020-11-05 18:13:25 +05:30
|
|
|
switch (rx->type) {
|
|
|
|
case NODE_RX_TYPE_EXT_1M_REPORT:
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux = NULL;
|
2020-11-05 18:13:25 +05:30
|
|
|
aux = NULL;
|
2021-12-09 06:27:16 +05:30
|
|
|
sync_lll = NULL;
|
2021-02-18 13:02:24 +05:30
|
|
|
sync_iso = NULL;
|
2021-12-08 22:31:24 +05:30
|
|
|
rx_incomplete = NULL;
|
2021-07-30 06:57:47 +05:30
|
|
|
lll = ftr->param;
|
|
|
|
scan = HDR_LLL2ULL(lll);
|
2020-11-22 10:13:56 +05:30
|
|
|
sync = sync_create_get(scan);
|
2020-11-06 06:22:10 +05:30
|
|
|
phy = BT_HCI_LE_EXT_SCAN_PHY_1M;
|
2020-11-05 18:13:25 +05:30
|
|
|
break;
|
|
|
|
case NODE_RX_TYPE_EXT_CODED_REPORT:
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux = NULL;
|
2020-11-05 18:13:25 +05:30
|
|
|
aux = NULL;
|
2021-12-09 06:27:16 +05:30
|
|
|
sync_lll = NULL;
|
2021-02-18 13:02:24 +05:30
|
|
|
sync_iso = NULL;
|
2021-12-08 22:31:24 +05:30
|
|
|
rx_incomplete = NULL;
|
2021-07-30 06:57:47 +05:30
|
|
|
lll = ftr->param;
|
|
|
|
scan = HDR_LLL2ULL(lll);
|
2020-11-22 10:13:56 +05:30
|
|
|
sync = sync_create_get(scan);
|
2020-11-06 06:22:10 +05:30
|
|
|
phy = BT_HCI_LE_EXT_SCAN_PHY_CODED;
|
2020-11-05 18:13:25 +05:30
|
|
|
break;
|
|
|
|
case NODE_RX_TYPE_EXT_AUX_REPORT:
|
2021-02-18 13:02:24 +05:30
|
|
|
sync_iso = NULL;
|
2021-12-08 22:31:24 +05:30
|
|
|
rx_incomplete = NULL;
|
2021-05-18 15:45:45 +05:30
|
|
|
if (ull_scan_aux_is_valid_get(HDR_LLL2ULL(ftr->param))) {
|
2021-12-09 06:27:16 +05:30
|
|
|
sync_lll = NULL;
|
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
/* Node has valid aux context so its scan was scheduled
|
|
|
|
* from ULL.
|
|
|
|
*/
|
|
|
|
lll_aux = ftr->param;
|
|
|
|
aux = HDR_LLL2ULL(lll_aux);
|
2021-09-13 12:47:32 +05:30
|
|
|
|
|
|
|
/* aux parent will be NULL for periodic sync */
|
2021-08-25 09:59:53 +02:00
|
|
|
lll = aux->parent;
|
2021-12-09 06:27:16 +05:30
|
|
|
|
2021-12-09 06:18:07 +05:30
|
|
|
} else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) ||
|
|
|
|
ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) {
|
2021-12-09 06:27:16 +05:30
|
|
|
sync_lll = NULL;
|
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
/* Node that does not have valid aux context but has
|
|
|
|
* valid scan set was scheduled from LLL. We can
|
|
|
|
* retrieve aux context from lll_scan as it was stored
|
|
|
|
* there when superior PDU was handled.
|
2021-05-18 15:45:45 +05:30
|
|
|
*/
|
2021-07-30 06:57:47 +05:30
|
|
|
lll = ftr->param;
|
2021-07-30 17:18:13 +05:30
|
|
|
|
2021-07-30 06:57:47 +05:30
|
|
|
lll_aux = lll->lll_aux;
|
2021-07-30 17:18:13 +05:30
|
|
|
LL_ASSERT(lll_aux);
|
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
aux = HDR_LLL2ULL(lll_aux);
|
2021-08-25 09:59:53 +02:00
|
|
|
LL_ASSERT(lll == aux->parent);
|
2021-12-09 06:27:16 +05:30
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
} else {
|
2021-12-09 06:27:16 +05:30
|
|
|
lll = NULL;
|
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
/* If none of the above, node is part of sync scanning
|
|
|
|
*/
|
|
|
|
sync_lll = ftr->param;
|
2021-09-13 12:47:32 +05:30
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
lll_aux = sync_lll->lll_aux;
|
|
|
|
aux = HDR_LLL2ULL(lll_aux);
|
|
|
|
}
|
2021-05-18 15:45:45 +05:30
|
|
|
|
2021-12-09 06:18:07 +05:30
|
|
|
if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) {
|
2021-08-17 18:18:04 +02:00
|
|
|
scan = HDR_LLL2ULL(lll);
|
|
|
|
sync = (void *)scan;
|
|
|
|
scan = ull_scan_is_valid_get(scan);
|
|
|
|
if (scan) {
|
|
|
|
sync = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scan = NULL;
|
|
|
|
sync = HDR_LLL2ULL(sync_lll);
|
2021-05-18 15:45:45 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
phy = lll_aux->phy;
|
2021-12-09 06:18:07 +05:30
|
|
|
if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || scan) {
|
2020-11-22 10:13:56 +05:30
|
|
|
/* Here we are scanner context */
|
|
|
|
sync = sync_create_get(scan);
|
2021-08-03 05:59:29 +05:30
|
|
|
|
|
|
|
/* Generate report based on PHY scanned */
|
2020-11-05 18:13:25 +05:30
|
|
|
switch (phy) {
|
2020-12-04 16:20:16 +01:00
|
|
|
case PHY_1M:
|
2020-11-05 18:13:25 +05:30
|
|
|
rx->type = NODE_RX_TYPE_EXT_1M_REPORT;
|
|
|
|
break;
|
2020-12-04 16:20:16 +01:00
|
|
|
case PHY_2M:
|
2020-11-05 18:13:25 +05:30
|
|
|
rx->type = NODE_RX_TYPE_EXT_2M_REPORT;
|
|
|
|
break;
|
2020-12-04 16:20:16 +01:00
|
|
|
case PHY_CODED:
|
2020-11-05 18:13:25 +05:30
|
|
|
rx->type = NODE_RX_TYPE_EXT_CODED_REPORT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LL_ASSERT(0);
|
|
|
|
return;
|
|
|
|
}
|
2020-11-22 10:13:56 +05:30
|
|
|
|
2021-07-27 21:05:07 +05:30
|
|
|
/* Backup scan requested flag as it is in union with
|
|
|
|
* `extra` struct member which will be set to NULL
|
|
|
|
* in subsequent code.
|
|
|
|
*/
|
|
|
|
is_scan_req = !!ftr->scan_req;
|
|
|
|
|
2020-11-22 10:13:56 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
2020-11-05 18:13:25 +05:30
|
|
|
} else {
|
2020-11-22 10:13:56 +05:30
|
|
|
/* Here we are periodic sync context */
|
2020-11-05 18:13:25 +05:30
|
|
|
rx->type = NODE_RX_TYPE_SYNC_REPORT;
|
|
|
|
rx->handle = ull_sync_handle_get(sync);
|
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
sync_lll = &sync->lll;
|
|
|
|
|
2021-02-18 13:02:24 +05:30
|
|
|
/* Check if we need to create BIG sync */
|
|
|
|
sync_iso = sync_iso_create_get(sync);
|
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
/* lll_aux and aux are auxiliary channel context,
|
2020-11-22 10:13:56 +05:30
|
|
|
* reuse the existing aux context to scan the chain.
|
2021-05-18 15:45:45 +05:30
|
|
|
* hence lll_aux and aux are not released or set to NULL.
|
2020-11-22 10:13:56 +05:30
|
|
|
*/
|
2020-11-05 18:13:25 +05:30
|
|
|
sync = NULL;
|
|
|
|
}
|
|
|
|
break;
|
2020-11-22 10:13:56 +05:30
|
|
|
|
2020-11-05 18:13:25 +05:30
|
|
|
case NODE_RX_TYPE_SYNC_REPORT:
|
|
|
|
{
|
|
|
|
struct ll_sync_set *ull_sync;
|
|
|
|
|
|
|
|
/* set the sync handle corresponding to the LLL context
|
|
|
|
* passed in the node rx footer field.
|
|
|
|
*/
|
2021-08-17 18:18:04 +02:00
|
|
|
sync_lll = ftr->param;
|
|
|
|
ull_sync = HDR_LLL2ULL(sync_lll);
|
2020-11-05 18:13:25 +05:30
|
|
|
rx->handle = ull_sync_handle_get(ull_sync);
|
|
|
|
|
2021-02-18 13:02:24 +05:30
|
|
|
/* Check if we need to create BIG sync */
|
|
|
|
sync_iso = sync_iso_create_get(ull_sync);
|
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
/* FIXME: we will need lll_scan if chain was scheduled
|
|
|
|
* from LLL; should we store lll_scan_set in
|
2021-08-17 18:18:04 +02:00
|
|
|
* sync_lll instead?
|
2021-05-18 15:45:45 +05:30
|
|
|
*/
|
2021-07-30 06:57:47 +05:30
|
|
|
lll = NULL;
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux = NULL;
|
2020-11-05 18:13:25 +05:30
|
|
|
aux = NULL;
|
|
|
|
scan = NULL;
|
|
|
|
sync = NULL;
|
2021-08-17 18:18:04 +02:00
|
|
|
phy = sync_lll->phy;
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
/* backup extra node_rx supplied for generating
|
|
|
|
* incomplete report
|
|
|
|
*/
|
|
|
|
rx_incomplete = ftr->extra;
|
2020-11-22 10:13:56 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
|
2020-11-05 18:13:25 +05:30
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LL_ASSERT(0);
|
|
|
|
return;
|
|
|
|
}
|
2020-10-08 14:40:43 +05:30
|
|
|
|
2020-05-04 13:32:24 +05:30
|
|
|
rx->link = link;
|
|
|
|
ftr->extra = NULL;
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-12-01 21:01:23 +05:30
|
|
|
ftr->aux_sched = 0U;
|
2021-08-25 11:09:28 +02:00
|
|
|
|
2020-05-04 13:32:24 +05:30
|
|
|
pdu = (void *)((struct node_rx_pdu *)rx)->pdu;
|
2020-04-21 11:12:41 +05:30
|
|
|
p = (void *)&pdu->adv_ext_ind;
|
2021-12-10 06:34:55 +05:30
|
|
|
if (!pdu->len || !p->ext_hdr_len) {
|
|
|
|
if (pdu->len) {
|
|
|
|
data_len = pdu->len - PDU_AC_EXT_HEADER_SIZE_MIN;
|
|
|
|
} else {
|
|
|
|
data_len = 0U;
|
|
|
|
}
|
|
|
|
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) {
|
2021-12-01 21:01:23 +05:30
|
|
|
struct ll_sync_set *sync;
|
|
|
|
|
|
|
|
sync = HDR_LLL2ULL(sync_lll);
|
|
|
|
ftr->aux_data_len = sync->data_len + data_len;
|
|
|
|
sync->data_len = 0U;
|
|
|
|
} else if (aux) {
|
|
|
|
aux->data_len += data_len;
|
|
|
|
ftr->aux_data_len = aux->data_len;
|
|
|
|
} else {
|
|
|
|
ftr->aux_data_len = data_len;
|
|
|
|
}
|
|
|
|
|
2020-04-28 14:12:04 +05:30
|
|
|
goto ull_scan_aux_rx_flush;
|
2020-04-21 11:12:41 +05:30
|
|
|
}
|
|
|
|
|
2020-11-09 14:53:54 +01:00
|
|
|
h = (void *)p->ext_hdr_adv_data;
|
2021-08-27 11:46:55 +05:30
|
|
|
|
|
|
|
/* Regard PDU as invalid if a RFU field is set, we do not know the
|
|
|
|
* size of this future field, hence will cause incorrect calculation of
|
|
|
|
* offset to ACAD field.
|
|
|
|
*/
|
|
|
|
if (h->rfu) {
|
|
|
|
goto ull_scan_aux_rx_flush;
|
|
|
|
}
|
|
|
|
|
2020-11-09 15:22:49 +01:00
|
|
|
ptr = h->data;
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
if (h->adv_addr) {
|
2020-10-08 14:40:43 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
2021-09-06 11:59:23 +05:30
|
|
|
/* Check if Periodic Advertising Synchronization to be created
|
|
|
|
*/
|
2021-12-09 06:08:30 +05:30
|
|
|
if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) {
|
2021-09-14 11:57:39 +05:30
|
|
|
/* Check address and update internal state */
|
2021-09-06 11:59:23 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
2021-09-14 11:57:39 +05:30
|
|
|
ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr,
|
|
|
|
ftr->rl_idx);
|
2021-09-06 11:59:23 +05:30
|
|
|
#else /* !CONFIG_BT_CTLR_PRIVACY */
|
2021-09-14 11:57:39 +05:30
|
|
|
ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr, 0U);
|
2021-09-06 11:59:23 +05:30
|
|
|
#endif /* !CONFIG_BT_CTLR_PRIVACY */
|
2021-09-14 11:57:39 +05:30
|
|
|
|
2020-08-11 09:58:34 +05:30
|
|
|
}
|
2020-10-08 14:40:43 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
2020-08-11 09:58:34 +05:30
|
|
|
|
2020-04-21 11:12:41 +05:30
|
|
|
ptr += BDADDR_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (h->tgt_addr) {
|
|
|
|
ptr += BDADDR_SIZE;
|
|
|
|
}
|
|
|
|
|
2021-08-25 20:50:53 +05:30
|
|
|
if (h->cte_info) {
|
|
|
|
ptr += sizeof(struct pdu_cte_info);
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:58:34 +05:30
|
|
|
adi = NULL;
|
2020-04-21 11:12:41 +05:30
|
|
|
if (h->adi) {
|
|
|
|
adi = (void *)ptr;
|
|
|
|
ptr += sizeof(*adi);
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:58:34 +05:30
|
|
|
aux_ptr = NULL;
|
|
|
|
if (h->aux_ptr) {
|
|
|
|
aux_ptr = (void *)ptr;
|
|
|
|
ptr += sizeof(*aux_ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (h->sync_info) {
|
|
|
|
struct pdu_adv_sync_info *si;
|
|
|
|
|
|
|
|
si = (void *)ptr;
|
|
|
|
ptr += sizeof(*si);
|
|
|
|
|
2021-09-06 11:59:23 +05:30
|
|
|
/* Check if Periodic Advertising Synchronization to be created.
|
|
|
|
* Setup synchronization if address and SID match in the
|
|
|
|
* Periodic Advertiser List or with the explicitly supplied.
|
|
|
|
*/
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync && adi &&
|
|
|
|
ull_sync_setup_sid_match(scan, adi->sid)) {
|
2020-08-11 10:27:12 +05:30
|
|
|
ull_sync_setup(scan, aux, rx, si);
|
2020-08-11 09:58:34 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-25 20:50:53 +05:30
|
|
|
if (h->tx_pwr) {
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate ACAD Len */
|
|
|
|
hdr_len = ptr - (uint8_t *)p;
|
2021-12-01 21:01:23 +05:30
|
|
|
hdr_buf_len = PDU_AC_EXT_HEADER_SIZE_MIN + p->ext_hdr_len;
|
|
|
|
if (hdr_len > hdr_buf_len) {
|
|
|
|
/* FIXME: Handle invalid header length */
|
2021-08-25 20:50:53 +05:30
|
|
|
acad_len = 0U;
|
2021-12-01 21:01:23 +05:30
|
|
|
} else {
|
|
|
|
acad_len = hdr_buf_len - hdr_len;
|
|
|
|
hdr_len += acad_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate total data length */
|
|
|
|
if (hdr_len < pdu->len) {
|
|
|
|
data_len = pdu->len - hdr_len;
|
|
|
|
} else {
|
|
|
|
data_len = 0U;
|
2021-08-25 20:50:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/* Periodic Advertising Channel Map Indication and/or Broadcast ISO
|
|
|
|
* synchronization
|
|
|
|
*/
|
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) &&
|
|
|
|
(rx->type == NODE_RX_TYPE_SYNC_REPORT) &&
|
|
|
|
acad_len) {
|
|
|
|
/* Periodic Advertising Channel Map Indication */
|
|
|
|
ull_sync_chm_update(rx->handle, ptr, acad_len);
|
2021-02-18 13:02:24 +05:30
|
|
|
|
|
|
|
/* Broadcast ISO synchronize */
|
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_ISO) && sync_iso) {
|
|
|
|
ull_sync_iso_setup(sync_iso, rx, ptr, acad_len);
|
|
|
|
}
|
2021-08-25 20:50:53 +05:30
|
|
|
}
|
|
|
|
|
2021-09-13 12:47:32 +05:30
|
|
|
/* Do not ULL schedule auxiliary PDU reception if no aux pointer
|
2021-09-13 11:56:51 +05:30
|
|
|
* or aux pointer is zero or scannable advertising has erroneous aux
|
|
|
|
* pointer being present or PHY in the aux pointer is invalid.
|
|
|
|
*/
|
|
|
|
if (!aux_ptr || !aux_ptr->offs || is_scan_req ||
|
2021-08-10 22:04:58 +05:30
|
|
|
(aux_ptr->phy > EXT_ADV_AUX_PHY_LE_CODED)) {
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) {
|
2021-12-01 21:01:23 +05:30
|
|
|
struct ll_sync_set *sync;
|
|
|
|
|
|
|
|
sync = HDR_LLL2ULL(sync_lll);
|
|
|
|
ftr->aux_data_len = sync->data_len + data_len;
|
|
|
|
sync->data_len = 0U;
|
|
|
|
} else if (aux) {
|
|
|
|
aux->data_len += data_len;
|
|
|
|
ftr->aux_data_len = aux->data_len;
|
|
|
|
} else {
|
|
|
|
ftr->aux_data_len = data_len;
|
|
|
|
}
|
|
|
|
|
2021-08-25 20:50:53 +05:30
|
|
|
if (is_scan_req) {
|
|
|
|
LL_ASSERT(aux && aux->rx_last);
|
|
|
|
|
|
|
|
aux->rx_last->rx_ftr.extra = rx;
|
|
|
|
aux->rx_last = rx;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-28 14:12:04 +05:30
|
|
|
goto ull_scan_aux_rx_flush;
|
|
|
|
}
|
|
|
|
|
2020-05-04 13:32:24 +05:30
|
|
|
if (!aux) {
|
|
|
|
aux = aux_acquire();
|
|
|
|
if (!aux) {
|
2021-12-30 07:39:53 +05:30
|
|
|
/* As LLL scheduling has been used and will fail due to
|
|
|
|
* non-allocation of aux context, a sync report with
|
|
|
|
* aux_failed flag set will be generated. Let the
|
|
|
|
* current sync report be set as partial, and the
|
|
|
|
* sync report corresponding to ull_scan_aux_release
|
|
|
|
* have the incomplete data status.
|
|
|
|
*/
|
|
|
|
if (ftr->aux_lll_sched) {
|
|
|
|
ftr->aux_sched = 1U;
|
|
|
|
}
|
|
|
|
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) &&
|
|
|
|
sync_lll) {
|
2021-12-01 21:01:23 +05:30
|
|
|
struct ll_sync_set *sync;
|
|
|
|
|
|
|
|
sync = HDR_LLL2ULL(sync_lll);
|
|
|
|
ftr->aux_data_len = sync->data_len + data_len;
|
|
|
|
sync->data_len = 0U;
|
2021-12-08 22:31:24 +05:30
|
|
|
|
2021-12-01 21:01:23 +05:30
|
|
|
}
|
|
|
|
|
2020-05-04 13:32:24 +05:30
|
|
|
goto ull_scan_aux_rx_flush;
|
|
|
|
}
|
|
|
|
|
2021-08-25 10:13:29 +02:00
|
|
|
aux->rx_head = aux->rx_last = NULL;
|
2021-12-01 21:01:23 +05:30
|
|
|
aux->data_len = data_len;
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux = &aux->lll;
|
2021-09-13 12:47:32 +05:30
|
|
|
lll_aux->is_chain_sched = 0U;
|
2020-05-04 13:32:24 +05:30
|
|
|
|
|
|
|
ull_hdr_init(&aux->ull);
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_hdr_init(lll_aux, aux);
|
2021-08-25 09:59:53 +02:00
|
|
|
|
2021-08-25 10:13:29 +02:00
|
|
|
aux->parent = lll ? (void *)lll : (void *)sync_lll;
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
aux->rx_incomplete = rx_incomplete;
|
|
|
|
rx_incomplete = NULL;
|
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
|
2021-12-01 21:01:23 +05:30
|
|
|
} else {
|
|
|
|
aux->data_len += data_len;
|
2020-05-04 13:32:24 +05:30
|
|
|
}
|
|
|
|
|
2021-08-25 10:13:29 +02:00
|
|
|
/* In sync context we can dispatch rx immediately, in scan context we
|
|
|
|
* enqueue rx in aux context and will flush them after scan is complete.
|
|
|
|
*/
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) {
|
2021-12-01 21:01:23 +05:30
|
|
|
struct ll_sync_set *sync;
|
|
|
|
|
|
|
|
sync = HDR_LLL2ULL(sync_lll);
|
|
|
|
sync->data_len += data_len;
|
|
|
|
ftr->aux_data_len = sync->data_len;
|
2020-04-28 14:12:04 +05:30
|
|
|
} else {
|
2021-08-25 10:13:29 +02:00
|
|
|
if (aux->rx_last) {
|
|
|
|
aux->rx_last->rx_ftr.extra = rx;
|
|
|
|
} else {
|
|
|
|
aux->rx_head = rx;
|
|
|
|
}
|
|
|
|
aux->rx_last = rx;
|
2021-12-01 21:01:23 +05:30
|
|
|
|
|
|
|
ftr->aux_data_len = aux->data_len;
|
2020-04-28 14:12:04 +05:30
|
|
|
}
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-12-01 21:01:23 +05:30
|
|
|
/* Initialize the channel index and PHY for the Auxiliary PDU reception.
|
|
|
|
*/
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux->chan = aux_ptr->chan_idx;
|
|
|
|
lll_aux->phy = BIT(aux_ptr->phy);
|
2021-05-18 15:45:45 +05:30
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
/* See if this was already scheduled from LLL. If so, store aux context
|
|
|
|
* in global scan struct so we can pick it when scanned node is received
|
|
|
|
* with a valid context.
|
|
|
|
*/
|
2021-08-25 11:09:28 +02:00
|
|
|
if (ftr->aux_lll_sched) {
|
2021-12-08 22:31:24 +05:30
|
|
|
/* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being setup */
|
|
|
|
ftr->aux_sched = 1U;
|
|
|
|
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) {
|
2021-08-17 18:18:04 +02:00
|
|
|
sync_lll->lll_aux = lll_aux;
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
/* In sync context, dispatch immediately */
|
|
|
|
ll_rx_put(link, rx);
|
|
|
|
ll_rx_sched();
|
2021-08-26 14:52:44 +02:00
|
|
|
} else {
|
|
|
|
lll->lll_aux = lll_aux;
|
2021-08-17 18:18:04 +02:00
|
|
|
}
|
2021-09-13 12:47:32 +05:30
|
|
|
|
|
|
|
/* Reset auxiliary channel PDU scan state which otherwise is
|
|
|
|
* done in the prepare_cb when ULL scheduling is used.
|
|
|
|
*/
|
2021-07-30 17:18:13 +05:30
|
|
|
lll_aux->state = 0U;
|
2021-05-18 15:45:45 +05:30
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-30 17:18:13 +05:30
|
|
|
/* Switching to ULL scheduling to receive auxiliary PDUs */
|
2021-12-09 06:18:07 +05:30
|
|
|
if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) {
|
2021-08-17 18:18:04 +02:00
|
|
|
lll->lll_aux = NULL;
|
|
|
|
} else {
|
2021-11-30 06:46:22 +05:30
|
|
|
LL_ASSERT(sync_lll &&
|
|
|
|
(!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux));
|
|
|
|
sync_lll->lll_aux = lll_aux;
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
aux->rx_head = rx;
|
2021-08-17 18:18:04 +02:00
|
|
|
}
|
2021-07-30 17:18:13 +05:30
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
/* Determine the window size */
|
2020-04-21 11:12:41 +05:30
|
|
|
if (aux_ptr->offs_units) {
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux->window_size_us = OFFS_UNIT_300_US;
|
2020-04-22 16:13:45 +05:30
|
|
|
} else {
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux->window_size_us = OFFS_UNIT_30_US;
|
2020-04-22 16:13:45 +05:30
|
|
|
}
|
2021-05-18 15:45:45 +05:30
|
|
|
|
|
|
|
aux_offset_us = (uint32_t)aux_ptr->offs * lll_aux->window_size_us;
|
2020-04-22 16:13:45 +05:30
|
|
|
|
2021-06-29 12:38:16 +05:30
|
|
|
/* CA field contains the clock accuracy of the advertiser;
|
|
|
|
* 0 - 51 ppm to 500 ppm
|
|
|
|
* 1 - 0 ppm to 50 ppm
|
|
|
|
*/
|
2020-04-22 16:13:45 +05:30
|
|
|
if (aux_ptr->ca) {
|
2021-07-05 16:13:56 +05:30
|
|
|
window_widening_us = SCA_DRIFT_50_PPM_US(aux_offset_us);
|
2021-06-29 12:38:16 +05:30
|
|
|
} else {
|
2021-07-05 16:13:56 +05:30
|
|
|
window_widening_us = SCA_DRIFT_500_PPM_US(aux_offset_us);
|
2020-04-21 11:12:41 +05:30
|
|
|
}
|
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
lll_aux->window_size_us += (EVENT_TICKER_RES_MARGIN_US +
|
|
|
|
((EVENT_JITTER_US + window_widening_us) << 1));
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
ready_delay_us = lll_radio_rx_ready_delay_get(lll_aux->phy, 1);
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-05-18 15:45:45 +05:30
|
|
|
/* Calculate the aux offset from start of the scan window */
|
|
|
|
aux_offset_us += ftr->radio_end_us;
|
2021-08-18 11:16:18 +05:30
|
|
|
aux_offset_us -= PDU_AC_US(pdu->len, phy, ftr->phy_flags);
|
2020-04-21 11:12:41 +05:30
|
|
|
aux_offset_us -= EVENT_JITTER_US;
|
|
|
|
aux_offset_us -= ready_delay_us;
|
2020-04-22 16:13:45 +05:30
|
|
|
aux_offset_us -= window_widening_us;
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
/* TODO: active_to_start feature port */
|
2021-04-05 12:56:51 +05:30
|
|
|
aux->ull.ticks_active_to_start = 0;
|
|
|
|
aux->ull.ticks_prepare_to_start =
|
2020-04-21 11:12:41 +05:30
|
|
|
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
|
2021-04-05 12:56:51 +05:30
|
|
|
aux->ull.ticks_preempt_to_start =
|
2020-04-21 11:12:41 +05:30
|
|
|
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
|
2021-04-05 12:56:51 +05:30
|
|
|
aux->ull.ticks_slot =
|
2020-04-21 11:12:41 +05:30
|
|
|
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US +
|
2020-04-22 16:18:07 +05:30
|
|
|
ready_delay_us +
|
2021-08-07 15:56:22 +05:30
|
|
|
PDU_AC_MAX_US(PDU_AC_EXT_PAYLOAD_SIZE_MAX,
|
|
|
|
lll_aux->phy) +
|
2020-04-21 11:12:41 +05:30
|
|
|
EVENT_OVERHEAD_END_US);
|
|
|
|
|
2021-04-05 12:56:51 +05:30
|
|
|
ticks_slot_offset = MAX(aux->ull.ticks_active_to_start,
|
|
|
|
aux->ull.ticks_prepare_to_start);
|
2020-04-21 11:12:41 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
|
|
|
|
ticks_slot_overhead = ticks_slot_offset;
|
|
|
|
} else {
|
|
|
|
ticks_slot_overhead = 0U;
|
|
|
|
}
|
2021-05-18 10:41:03 +05:30
|
|
|
ticks_slot_offset += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-05-16 14:00:29 +05:30
|
|
|
ticks_aux_offset = HAL_TICKER_US_TO_TICKS(aux_offset_us);
|
|
|
|
|
|
|
|
/* Yield the primary scan window ticks in ticker */
|
|
|
|
if (scan) {
|
|
|
|
uint8_t handle;
|
|
|
|
|
|
|
|
handle = ull_scan_handle_get(scan);
|
|
|
|
|
|
|
|
ticker_status = ticker_yield_abs(TICKER_INSTANCE_ID_CTLR,
|
|
|
|
TICKER_USER_ID_ULL_HIGH,
|
|
|
|
(TICKER_ID_SCAN_BASE + handle),
|
|
|
|
(ftr->ticks_anchor +
|
|
|
|
ticks_aux_offset -
|
|
|
|
ticks_slot_offset),
|
|
|
|
NULL, NULL);
|
|
|
|
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
|
|
|
(ticker_status == TICKER_STATUS_BUSY));
|
|
|
|
}
|
2020-04-21 11:12:41 +05:30
|
|
|
|
|
|
|
aux_handle = aux_handle_get(aux);
|
|
|
|
|
|
|
|
ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR,
|
|
|
|
TICKER_USER_ID_ULL_HIGH,
|
|
|
|
TICKER_ID_SCAN_AUX_BASE + aux_handle,
|
|
|
|
ftr->ticks_anchor - ticks_slot_offset,
|
2021-05-16 14:00:29 +05:30
|
|
|
ticks_aux_offset,
|
2020-04-21 11:12:41 +05:30
|
|
|
TICKER_NULL_PERIOD,
|
|
|
|
TICKER_NULL_REMAINDER,
|
|
|
|
TICKER_NULL_LAZY,
|
2021-04-05 12:56:51 +05:30
|
|
|
(aux->ull.ticks_slot +
|
2020-04-21 11:12:41 +05:30
|
|
|
ticks_slot_overhead),
|
|
|
|
ticker_cb, aux, ticker_op_cb, aux);
|
|
|
|
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
|
|
|
(ticker_status == TICKER_STATUS_BUSY));
|
2020-04-28 14:12:04 +05:30
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
ull_scan_aux_rx_flush:
|
2020-10-08 14:40:43 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
2021-12-09 06:08:30 +05:30
|
|
|
if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) {
|
|
|
|
scan->periodic.state = LL_SYNC_STATE_IDLE;
|
2020-08-11 09:58:34 +05:30
|
|
|
}
|
2020-10-08 14:40:43 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
2020-08-11 09:58:34 +05:30
|
|
|
|
2020-04-28 14:12:04 +05:30
|
|
|
if (aux) {
|
2021-08-24 23:32:53 +02:00
|
|
|
struct ull_hdr *hdr;
|
|
|
|
|
2021-08-25 10:13:29 +02:00
|
|
|
/* Enqueue last rx in aux context if possible, otherwise send
|
|
|
|
* immediately since we are in sync context.
|
|
|
|
*/
|
2021-12-09 06:18:07 +05:30
|
|
|
if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || aux->rx_last) {
|
2021-08-25 10:13:29 +02:00
|
|
|
aux->rx_last->rx_ftr.extra = rx;
|
2021-12-13 21:30:08 +05:30
|
|
|
aux->rx_last = rx;
|
2021-08-25 10:13:29 +02:00
|
|
|
} else {
|
|
|
|
LL_ASSERT(sync_lll);
|
2021-12-01 21:01:23 +05:30
|
|
|
|
2021-08-25 10:13:29 +02:00
|
|
|
ll_rx_put(link, rx);
|
|
|
|
ll_rx_sched();
|
|
|
|
}
|
2021-08-25 01:53:08 +02:00
|
|
|
|
2021-08-24 23:32:53 +02:00
|
|
|
/* ref == 0
|
|
|
|
* All PDUs were scheduled from LLL and there is no pending done
|
|
|
|
* event, we can flush here.
|
|
|
|
*
|
|
|
|
* ref == 1
|
|
|
|
* There is pending done event so we need to flush from disabled
|
|
|
|
* callback. Flushing here would release aux context and thus
|
|
|
|
* ull_hdr before done event was processed.
|
|
|
|
*/
|
2021-09-13 22:27:31 +05:30
|
|
|
hdr = &aux->ull;
|
2021-08-24 23:32:53 +02:00
|
|
|
LL_ASSERT(ull_ref_get(hdr) < 2);
|
|
|
|
if (ull_ref_get(hdr) == 0) {
|
2021-08-25 01:53:08 +02:00
|
|
|
flush(aux);
|
2021-07-29 11:47:31 +05:30
|
|
|
} else {
|
|
|
|
LL_ASSERT(!hdr->disabled_cb);
|
2021-04-06 12:10:00 +05:30
|
|
|
|
2021-08-25 01:53:08 +02:00
|
|
|
hdr->disabled_param = aux;
|
2021-12-09 06:18:07 +05:30
|
|
|
hdr->disabled_cb = done_disabled_cb;
|
2021-07-29 11:47:31 +05:30
|
|
|
}
|
2020-05-04 13:32:24 +05:30
|
|
|
|
|
|
|
return;
|
2020-04-28 14:12:04 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
ll_rx_put(link, rx);
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
if (rx_incomplete) {
|
|
|
|
rx_release_put(rx_incomplete);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
|
2020-04-28 14:12:04 +05:30
|
|
|
ll_rx_sched();
|
2020-04-21 11:12:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
void ull_scan_aux_done(struct node_rx_event_done *done)
|
|
|
|
{
|
2021-04-05 12:56:51 +05:30
|
|
|
struct ll_scan_aux_set *aux;
|
2021-04-06 12:10:00 +05:30
|
|
|
struct ull_hdr *hdr;
|
|
|
|
|
2021-04-05 12:56:51 +05:30
|
|
|
/* Get reference to ULL context */
|
|
|
|
aux = CONTAINER_OF(done->param, struct ll_scan_aux_set, ull);
|
|
|
|
|
2021-12-09 06:18:07 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) &&
|
|
|
|
!ull_scan_aux_is_valid_get(aux)) {
|
2021-08-17 18:18:04 +02:00
|
|
|
struct ll_sync_set *sync;
|
|
|
|
|
|
|
|
sync = CONTAINER_OF(done->param, struct ll_sync_set, ull);
|
|
|
|
LL_ASSERT(ull_sync_is_valid_get(sync));
|
|
|
|
hdr = &sync->ull;
|
|
|
|
|
|
|
|
if (!sync->lll.lll_aux) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aux = HDR_LLL2ULL(sync->lll.lll_aux);
|
2021-08-26 14:52:44 +02:00
|
|
|
} else {
|
|
|
|
/* Setup the disabled callback to flush the auxiliary PDUs */
|
|
|
|
hdr = &aux->ull;
|
2021-08-17 18:18:04 +02:00
|
|
|
}
|
2020-04-21 11:12:41 +05:30
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
LL_ASSERT(!hdr->disabled_cb);
|
2021-04-06 12:10:00 +05:30
|
|
|
hdr->disabled_param = aux;
|
|
|
|
hdr->disabled_cb = done_disabled_cb;
|
2020-04-21 11:12:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ull_scan_aux_lll_handle_get(struct lll_scan_aux *lll)
|
|
|
|
{
|
2021-12-09 06:27:16 +05:30
|
|
|
struct ll_scan_aux_set *aux;
|
|
|
|
|
|
|
|
aux = HDR_LLL2ULL(lll);
|
|
|
|
|
|
|
|
return aux_handle_get(aux);
|
2020-04-21 11:12:41 +05:30
|
|
|
}
|
|
|
|
|
2021-08-26 14:52:44 +02:00
|
|
|
void *ull_scan_aux_lll_parent_get(struct lll_scan_aux *lll,
|
|
|
|
uint8_t *is_lll_scan)
|
|
|
|
{
|
2021-12-09 06:27:16 +05:30
|
|
|
struct ll_scan_aux_set *aux;
|
|
|
|
struct ll_scan_set *scan;
|
2021-08-26 14:52:44 +02:00
|
|
|
|
2021-12-09 06:27:16 +05:30
|
|
|
aux = HDR_LLL2ULL(lll);
|
|
|
|
scan = HDR_LLL2ULL(aux->parent);
|
2021-08-26 14:52:44 +02:00
|
|
|
|
|
|
|
if (is_lll_scan) {
|
2021-12-09 06:27:16 +05:30
|
|
|
*is_lll_scan = !!ull_scan_is_valid_get(scan);
|
2021-08-26 14:52:44 +02:00
|
|
|
}
|
|
|
|
|
2021-12-09 06:27:16 +05:30
|
|
|
return aux->parent;
|
2021-08-26 14:52:44 +02:00
|
|
|
}
|
|
|
|
|
2021-07-21 13:32:27 +02:00
|
|
|
struct ll_scan_aux_set *ull_scan_aux_is_valid_get(struct ll_scan_aux_set *aux)
|
|
|
|
{
|
|
|
|
if (((uint8_t *)aux < (uint8_t *)ll_scan_aux_pool) ||
|
|
|
|
((uint8_t *)aux > ((uint8_t *)ll_scan_aux_pool +
|
|
|
|
(sizeof(struct ll_scan_aux_set) *
|
|
|
|
(CONFIG_BT_CTLR_SCAN_AUX_SET - 1))))) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return aux;
|
|
|
|
}
|
|
|
|
|
2021-08-03 05:59:29 +05:30
|
|
|
void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx)
|
|
|
|
{
|
|
|
|
struct lll_scan_aux *lll_aux;
|
2021-08-17 18:18:04 +02:00
|
|
|
void *param_ull;
|
|
|
|
|
|
|
|
param_ull = HDR_LLL2ULL(rx->rx_ftr.param);
|
|
|
|
|
|
|
|
if (ull_scan_is_valid_get(param_ull)) {
|
|
|
|
struct lll_scan *lll;
|
|
|
|
|
2021-08-27 17:42:33 +02:00
|
|
|
/* Mark for buffer for release */
|
|
|
|
rx->type = NODE_RX_TYPE_RELEASE;
|
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
lll = rx->rx_ftr.param;
|
|
|
|
lll_aux = lll->lll_aux;
|
2021-12-09 06:18:07 +05:30
|
|
|
|
|
|
|
} else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) ||
|
|
|
|
ull_scan_aux_is_valid_get(param_ull)) {
|
2021-08-27 17:42:33 +02:00
|
|
|
/* Mark for buffer for release */
|
|
|
|
rx->type = NODE_RX_TYPE_RELEASE;
|
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
lll_aux = rx->rx_ftr.param;
|
2021-12-09 06:18:07 +05:30
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
} else if (ull_sync_is_valid_get(param_ull)) {
|
2021-12-01 21:01:23 +05:30
|
|
|
struct ll_sync_set *sync;
|
2021-08-17 18:18:04 +02:00
|
|
|
struct lll_sync *lll;
|
|
|
|
|
2021-12-01 21:01:23 +05:30
|
|
|
sync = param_ull;
|
2021-12-08 22:31:24 +05:30
|
|
|
|
|
|
|
/* reset data len total */
|
2021-12-01 21:01:23 +05:30
|
|
|
sync->data_len = 0U;
|
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
lll = rx->rx_ftr.param;
|
|
|
|
lll_aux = lll->lll_aux;
|
2021-08-27 17:42:33 +02:00
|
|
|
|
|
|
|
/* Change node type so HCI can dispatch report for truncated
|
|
|
|
* data properly.
|
|
|
|
*/
|
|
|
|
rx->type = NODE_RX_TYPE_SYNC_REPORT;
|
2021-12-01 21:01:23 +05:30
|
|
|
rx->handle = ull_sync_handle_get(sync);
|
2021-09-13 22:41:22 +05:30
|
|
|
|
|
|
|
/* Dequeue will try releasing list of node rx, set the extra
|
|
|
|
* pointer to NULL.
|
|
|
|
*/
|
|
|
|
rx->rx_ftr.extra = NULL;
|
2021-12-09 06:18:07 +05:30
|
|
|
|
2021-08-17 18:18:04 +02:00
|
|
|
} else {
|
|
|
|
LL_ASSERT(0);
|
|
|
|
lll_aux = NULL;
|
|
|
|
}
|
2021-08-03 05:59:29 +05:30
|
|
|
|
|
|
|
if (lll_aux) {
|
2021-08-17 18:18:04 +02:00
|
|
|
struct ll_scan_aux_set *aux;
|
2021-08-27 17:42:33 +02:00
|
|
|
struct ull_hdr *hdr;
|
2021-08-17 18:18:04 +02:00
|
|
|
|
2021-08-03 05:59:29 +05:30
|
|
|
aux = HDR_LLL2ULL(lll_aux);
|
2021-08-27 17:42:33 +02:00
|
|
|
hdr = &aux->ull;
|
2021-08-03 05:59:29 +05:30
|
|
|
|
2021-08-27 17:42:33 +02:00
|
|
|
LL_ASSERT(ull_ref_get(hdr) < 2);
|
2021-09-13 22:27:31 +05:30
|
|
|
|
2021-08-27 17:42:33 +02:00
|
|
|
/* Flush from here of from done event, if one is pending */
|
|
|
|
if (ull_ref_get(hdr) == 0) {
|
|
|
|
flush(aux);
|
|
|
|
} else {
|
|
|
|
LL_ASSERT(!hdr->disabled_cb);
|
|
|
|
|
|
|
|
hdr->disabled_param = aux;
|
2021-12-09 06:18:07 +05:30
|
|
|
hdr->disabled_cb = done_disabled_cb;
|
2021-08-27 17:42:33 +02:00
|
|
|
}
|
|
|
|
}
|
2021-08-03 05:59:29 +05:30
|
|
|
|
|
|
|
ll_rx_put(link, rx);
|
|
|
|
ll_rx_sched();
|
|
|
|
}
|
|
|
|
|
2021-11-30 06:46:22 +05:30
|
|
|
int ull_scan_aux_stop(struct ll_scan_aux_set *aux)
|
|
|
|
{
|
|
|
|
static memq_link_t link;
|
|
|
|
static struct mayfly mfy = {0, 0, &link, NULL, flush};
|
|
|
|
uint8_t aux_handle;
|
|
|
|
uint32_t ret;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Stop any ULL scheduling of auxiliary PDU scan */
|
|
|
|
aux_handle = aux_handle_get(aux);
|
|
|
|
err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_AUX_BASE + aux_handle,
|
|
|
|
aux, &aux->lll);
|
|
|
|
if (err && (err != -EALREADY)) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Abort LLL event if ULL scheduling not used or already in prepare */
|
|
|
|
if (err == -EALREADY) {
|
|
|
|
ret = ull_disable(&aux->lll);
|
|
|
|
if (ret) {
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release auxiliary context in ULL execution context */
|
|
|
|
mfy.param = aux;
|
|
|
|
ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH,
|
|
|
|
0, &mfy);
|
|
|
|
LL_ASSERT(!ret);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-21 11:12:41 +05:30
|
|
|
static int init_reset(void)
|
|
|
|
{
|
|
|
|
/* Initialize adv aux pool. */
|
|
|
|
mem_init(ll_scan_aux_pool, sizeof(struct ll_scan_aux_set),
|
|
|
|
sizeof(ll_scan_aux_pool) / sizeof(struct ll_scan_aux_set),
|
|
|
|
&scan_aux_free);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct ll_scan_aux_set *aux_acquire(void)
|
|
|
|
{
|
|
|
|
return mem_acquire(&scan_aux_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void aux_release(struct ll_scan_aux_set *aux)
|
|
|
|
{
|
|
|
|
mem_release(aux, &scan_aux_free);
|
|
|
|
}
|
|
|
|
|
2020-04-28 14:12:04 +05:30
|
|
|
static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux)
|
2020-04-21 11:12:41 +05:30
|
|
|
{
|
|
|
|
return mem_index_get(aux, ll_scan_aux_pool,
|
|
|
|
sizeof(struct ll_scan_aux_set));
|
|
|
|
}
|
|
|
|
|
2020-11-22 10:13:56 +05:30
|
|
|
static inline struct ll_sync_set *sync_create_get(struct ll_scan_set *scan)
|
|
|
|
{
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
2021-12-22 22:55:30 +05:30
|
|
|
return (!scan->periodic.cancelled) ? scan->periodic.sync : NULL;
|
2020-11-22 10:13:56 +05:30
|
|
|
#else /* !CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
return NULL;
|
|
|
|
#endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
}
|
|
|
|
|
2021-02-18 13:02:24 +05:30
|
|
|
static inline struct ll_sync_iso_set *
|
|
|
|
sync_iso_create_get(struct ll_sync_set *sync)
|
|
|
|
{
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
|
|
|
return sync->iso.sync_iso;
|
|
|
|
#else /* !CONFIG_BT_CTLR_SYNC_ISO */
|
|
|
|
return NULL;
|
|
|
|
#endif /* !CONFIG_BT_CTLR_SYNC_ISO */
|
|
|
|
}
|
|
|
|
|
2021-04-06 12:10:00 +05:30
|
|
|
static void done_disabled_cb(void *param)
|
|
|
|
{
|
2021-12-09 06:18:07 +05:30
|
|
|
flush(param);
|
2021-04-06 12:10:00 +05:30
|
|
|
}
|
|
|
|
|
2021-11-30 06:46:22 +05:30
|
|
|
static void flush(void *param)
|
2020-04-28 14:12:04 +05:30
|
|
|
{
|
2021-11-30 06:46:22 +05:30
|
|
|
struct ll_scan_aux_set *aux;
|
2021-12-08 22:31:24 +05:30
|
|
|
struct ll_scan_set *scan;
|
2021-08-25 01:53:08 +02:00
|
|
|
struct node_rx_hdr *rx;
|
2021-12-08 22:31:24 +05:30
|
|
|
struct lll_scan *lll;
|
|
|
|
bool sched = false;
|
2020-04-28 14:12:04 +05:30
|
|
|
|
2021-11-30 06:46:22 +05:30
|
|
|
aux = param;
|
2021-08-25 01:53:08 +02:00
|
|
|
rx = aux->rx_head;
|
2021-08-25 10:13:29 +02:00
|
|
|
if (rx) {
|
2021-12-08 22:31:24 +05:30
|
|
|
ll_rx_put(rx->link, rx);
|
|
|
|
sched = true;
|
|
|
|
}
|
2021-08-25 10:13:29 +02:00
|
|
|
|
2021-12-08 22:31:24 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
if (aux->rx_incomplete) {
|
|
|
|
rx_release_put(aux->rx_incomplete);
|
|
|
|
sched = true;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
2021-08-25 10:13:29 +02:00
|
|
|
|
2021-12-08 22:31:24 +05:30
|
|
|
if (sched) {
|
2021-08-25 10:13:29 +02:00
|
|
|
ll_rx_sched();
|
2021-12-08 22:31:24 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
lll = aux->parent;
|
|
|
|
scan = HDR_LLL2ULL(lll);
|
|
|
|
scan = ull_scan_is_valid_get(scan);
|
2021-12-09 06:18:07 +05:30
|
|
|
if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || scan) {
|
2021-12-08 22:31:24 +05:30
|
|
|
lll->lll_aux = NULL;
|
2021-08-17 18:18:04 +02:00
|
|
|
} else {
|
2021-12-08 22:31:24 +05:30
|
|
|
struct lll_sync *sync_lll;
|
|
|
|
|
|
|
|
sync_lll = aux->parent;
|
|
|
|
|
|
|
|
LL_ASSERT(sync_lll->lll_aux);
|
|
|
|
sync_lll->lll_aux = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
aux_release(aux);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
static void rx_release_put(struct node_rx_hdr *rx)
|
|
|
|
{
|
|
|
|
rx->type = NODE_RX_TYPE_RELEASE;
|
|
|
|
|
|
|
|
ll_rx_put(rx->link, rx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aux_sync_partial(void *param)
|
|
|
|
{
|
|
|
|
struct ll_scan_aux_set *aux;
|
|
|
|
struct node_rx_hdr *rx;
|
|
|
|
|
|
|
|
aux = param;
|
|
|
|
rx = aux->rx_head;
|
|
|
|
aux->rx_head = NULL;
|
|
|
|
|
|
|
|
rx->rx_ftr.aux_sched = 1U;
|
|
|
|
|
|
|
|
ll_rx_put(rx->link, rx);
|
|
|
|
ll_rx_sched();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aux_sync_incomplete(void *param)
|
|
|
|
{
|
|
|
|
struct ll_scan_aux_set *aux;
|
|
|
|
|
|
|
|
aux = param;
|
|
|
|
if (!aux->rx_head) {
|
|
|
|
struct ll_sync_set *sync;
|
|
|
|
struct node_rx_hdr *rx;
|
2021-08-25 10:13:29 +02:00
|
|
|
struct lll_sync *lll;
|
2021-08-17 18:18:04 +02:00
|
|
|
|
2021-12-08 22:31:24 +05:30
|
|
|
/* get reference to sync context */
|
2021-08-25 10:13:29 +02:00
|
|
|
lll = aux->parent;
|
2021-12-08 22:31:24 +05:30
|
|
|
sync = HDR_LLL2ULL(lll);
|
|
|
|
|
|
|
|
/* reset data len total */
|
|
|
|
sync->data_len = 0U;
|
|
|
|
|
|
|
|
/* pick extra node rx stored in aux context */
|
|
|
|
rx = aux->rx_incomplete;
|
|
|
|
LL_ASSERT(rx);
|
|
|
|
aux->rx_incomplete = NULL;
|
|
|
|
|
|
|
|
/* prepare sync report with failure */
|
|
|
|
rx->type = NODE_RX_TYPE_SYNC_REPORT;
|
|
|
|
rx->handle = ull_sync_handle_get(sync);
|
|
|
|
|
|
|
|
/* flag chain reception failure */
|
|
|
|
rx->rx_ftr.aux_failed = 1U;
|
|
|
|
|
|
|
|
/* Dequeue will try releasing list of node rx,
|
|
|
|
* set the extra pointer to NULL.
|
|
|
|
*/
|
|
|
|
rx->rx_ftr.extra = NULL;
|
|
|
|
|
|
|
|
/* add to rx list, will be flushed */
|
|
|
|
aux->rx_head = rx;
|
2021-08-17 18:18:04 +02:00
|
|
|
}
|
2021-07-27 21:05:07 +05:30
|
|
|
|
2021-12-08 22:31:24 +05:30
|
|
|
flush(aux);
|
2020-04-28 14:12:04 +05:30
|
|
|
}
|
2021-12-08 22:31:24 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
2020-04-28 14:12:04 +05:30
|
|
|
|
2021-09-15 11:48:21 +05:30
|
|
|
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
|
|
|
|
uint32_t remainder, uint16_t lazy, uint8_t force,
|
|
|
|
void *param)
|
2020-04-21 11:12:41 +05:30
|
|
|
{
|
|
|
|
static memq_link_t link;
|
|
|
|
static struct mayfly mfy = {0, 0, &link, NULL, lll_scan_aux_prepare};
|
|
|
|
struct ll_scan_aux_set *aux = param;
|
|
|
|
static struct lll_prepare_param p;
|
|
|
|
uint32_t ret;
|
|
|
|
uint8_t ref;
|
|
|
|
|
|
|
|
DEBUG_RADIO_PREPARE_O(1);
|
|
|
|
|
|
|
|
/* Increment prepare reference count */
|
|
|
|
ref = ull_ref_inc(&aux->ull);
|
|
|
|
LL_ASSERT(ref);
|
|
|
|
|
|
|
|
/* Append timing parameters */
|
|
|
|
p.ticks_at_expire = ticks_at_expire;
|
|
|
|
p.remainder = 0; /* FIXME: remainder; */
|
|
|
|
p.lazy = lazy;
|
2021-03-03 15:41:55 +01:00
|
|
|
p.force = force;
|
2020-04-21 11:12:41 +05:30
|
|
|
p.param = &aux->lll;
|
|
|
|
mfy.param = &p;
|
|
|
|
|
|
|
|
/* Kick LLL prepare */
|
|
|
|
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
|
|
|
|
0, &mfy);
|
|
|
|
LL_ASSERT(!ret);
|
|
|
|
|
|
|
|
DEBUG_RADIO_PREPARE_O(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ticker_op_cb(uint32_t status, void *param)
|
|
|
|
{
|
|
|
|
static memq_link_t link;
|
2021-12-08 22:31:24 +05:30
|
|
|
static struct mayfly mfy = {0, 0, &link, NULL, NULL};
|
|
|
|
struct ll_sync_set *sync;
|
2020-04-21 11:12:41 +05:30
|
|
|
uint32_t ret;
|
|
|
|
|
2021-12-08 22:31:24 +05:30
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC)) {
|
|
|
|
struct ll_scan_aux_set *aux;
|
|
|
|
struct lll_sync *sync_lll;
|
|
|
|
|
|
|
|
aux = param;
|
|
|
|
sync_lll = aux->parent;
|
|
|
|
sync = HDR_LLL2ULL(sync_lll);
|
|
|
|
sync = ull_sync_is_valid_get(sync);
|
|
|
|
} else {
|
|
|
|
sync = NULL;
|
|
|
|
}
|
|
|
|
|
2020-04-21 11:12:41 +05:30
|
|
|
if (status == TICKER_STATUS_SUCCESS) {
|
2021-12-08 22:31:24 +05:30
|
|
|
if (0) {
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
} else if (sync) {
|
|
|
|
mfy.fp = aux_sync_partial;
|
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (0) {
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
|
|
|
|
} else if (sync) {
|
|
|
|
mfy.fp = aux_sync_incomplete;
|
|
|
|
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
mfy.fp = flush;
|
|
|
|
}
|
2020-04-21 11:12:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
mfy.param = param;
|
|
|
|
|
2020-04-28 14:12:04 +05:30
|
|
|
ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH,
|
2020-04-21 11:12:41 +05:30
|
|
|
0, &mfy);
|
|
|
|
LL_ASSERT(!ret);
|
|
|
|
}
|