Bluetooth: controller: Add terminate event for external advertising

Add terminate event for duration timeout, max number of events and
connection.

Signed-off-by: Dag Bjarvin <Dag.Bjarvin@nordicsemi.no>
This commit is contained in:
Dag Bjarvin 2020-06-18 14:13:41 +02:00 committed by Carles Cufí
commit 12fdddb80d
12 changed files with 293 additions and 50 deletions

View file

@ -1039,7 +1039,7 @@ static void le_set_adv_enable(struct net_buf *buf, struct net_buf **evt)
#if defined(CONFIG_BT_HCI_MESH_EXT) #if defined(CONFIG_BT_HCI_MESH_EXT)
status = ll_adv_enable(0, cmd->enable, 0, 0, 0, 0, 0); status = ll_adv_enable(0, cmd->enable, 0, 0, 0, 0, 0);
#else /* !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_HCI_MESH_EXT */
status = ll_adv_enable(0, cmd->enable); status = ll_adv_enable(0, cmd->enable, 0, 0);
#endif /* !CONFIG_BT_HCI_MESH_EXT */ #endif /* !CONFIG_BT_HCI_MESH_EXT */
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
status = ll_adv_enable(cmd->enable); status = ll_adv_enable(cmd->enable);
@ -1754,7 +1754,8 @@ static void le_set_ext_adv_enable(struct net_buf *buf, struct net_buf **evt)
#if defined(CONFIG_BT_HCI_MESH_EXT) #if defined(CONFIG_BT_HCI_MESH_EXT)
status = ll_adv_enable(s->handle, cmd->enable, 0, 0, 0, 0, 0); status = ll_adv_enable(s->handle, cmd->enable, 0, 0, 0, 0, 0);
#else /* !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_HCI_MESH_EXT */
status = ll_adv_enable(s->handle, cmd->enable); status = ll_adv_enable(s->handle, cmd->enable,
s->duration, s->max_ext_adv_evts);
#endif /* !CONFIG_BT_HCI_MESH_EXT */ #endif /* !CONFIG_BT_HCI_MESH_EXT */
if (status) { if (status) {
/* TODO: how to handle succeeded ones before this /* TODO: how to handle succeeded ones before this
@ -3590,6 +3591,26 @@ static void le_adv_ext_coded_report(struct pdu_data *pdu_data,
{ {
le_adv_ext_report(pdu_data, node_rx, buf, BIT(2)); le_adv_ext_report(pdu_data, node_rx, buf, BIT(2));
} }
static void le_adv_ext_terminate(struct pdu_data *pdu_data,
struct node_rx_pdu *node_rx,
struct net_buf *buf)
{
struct bt_hci_evt_le_adv_set_terminated *sep;
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
!(le_event_mask & BT_EVT_MASK_LE_ADV_SET_TERMINATED)) {
return;
}
sep = meta_evt(buf, BT_HCI_EVT_LE_ADV_SET_TERMINATED, sizeof(*sep));
sep->status = ((uint32_t)node_rx->hdr.rx_ftr.extra >> 8) & 0xff;
sep->adv_handle = (node_rx->hdr.handle & 0xff);
sep->conn_handle =
sys_cpu_to_le16(*(uint16_t *)node_rx->hdr.rx_ftr.param);
sep->num_completed_ext_adv_evts =
(uint8_t)((uint32_t)node_rx->hdr.rx_ftr.extra & 0xff);
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_OBSERVER */ #endif /* CONFIG_BT_OBSERVER */
@ -3901,6 +3922,10 @@ static void encode_control(struct node_rx_pdu *node_rx,
case NODE_RX_TYPE_EXT_CODED_REPORT: case NODE_RX_TYPE_EXT_CODED_REPORT:
le_adv_ext_coded_report(pdu_data, node_rx, buf); le_adv_ext_coded_report(pdu_data, node_rx, buf);
break; break;
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
le_adv_ext_terminate(pdu_data, node_rx, buf);
break;
#endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_OBSERVER */ #endif /* CONFIG_BT_OBSERVER */
@ -4297,7 +4322,7 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
case NODE_RX_TYPE_REPORT: case NODE_RX_TYPE_REPORT:
#if defined(CONFIG_BT_CTLR_ADV_EXT) #if defined(CONFIG_BT_CTLR_ADV_EXT)
/* fallthrough */ /* fallthrough */
case NODE_RX_TYPE_EXT_1M_REPORT: case NODE_RX_TYPE_EXT_1M_REPORT:
case NODE_RX_TYPE_EXT_2M_REPORT: case NODE_RX_TYPE_EXT_2M_REPORT:
case NODE_RX_TYPE_EXT_CODED_REPORT: case NODE_RX_TYPE_EXT_CODED_REPORT:
@ -4328,6 +4353,11 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
case NODE_RX_TYPE_MESH_REPORT: case NODE_RX_TYPE_MESH_REPORT:
#endif /* CONFIG_BT_HCI_MESH_EXT */ #endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* fallthrough */
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CONN)
case NODE_RX_TYPE_CONNECTION: case NODE_RX_TYPE_CONNECTION:
return HCI_CLASS_EVT_REQUIRED; return HCI_CLASS_EVT_REQUIRED;

View file

@ -53,7 +53,8 @@ uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
uint8_t at_anchor, uint32_t ticks_anchor, uint8_t retry, uint8_t at_anchor, uint32_t ticks_anchor, uint8_t retry,
uint8_t scan_window, uint8_t scan_delay); uint8_t scan_window, uint8_t scan_delay);
#else /* !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_HCI_MESH_EXT */
uint8_t ll_adv_enable(uint8_t handle, uint8_t enable); uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
uint16_t duration, uint8_t max_ext_adv_evts);
#endif /* !CONFIG_BT_HCI_MESH_EXT */ #endif /* !CONFIG_BT_HCI_MESH_EXT */
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
uint8_t ll_adv_enable(uint8_t enable); uint8_t ll_adv_enable(uint8_t enable);

View file

@ -163,53 +163,54 @@ enum node_rx_type {
NODE_RX_TYPE_EXT_1M_REPORT = 0x05, NODE_RX_TYPE_EXT_1M_REPORT = 0x05,
NODE_RX_TYPE_EXT_2M_REPORT = 0x06, NODE_RX_TYPE_EXT_2M_REPORT = 0x06,
NODE_RX_TYPE_EXT_CODED_REPORT = 0x07, NODE_RX_TYPE_EXT_CODED_REPORT = 0x07,
NODE_RX_TYPE_EXT_ADV_TERMINATE = 0x08,
#endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) #if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
NODE_RX_TYPE_SCAN_REQ = 0x08, NODE_RX_TYPE_SCAN_REQ = 0x09,
#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */ #endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
#if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CONN)
NODE_RX_TYPE_CONNECTION = 0x09, NODE_RX_TYPE_CONNECTION = 0x0a,
NODE_RX_TYPE_TERMINATE = 0x0a, NODE_RX_TYPE_TERMINATE = 0x0b,
NODE_RX_TYPE_CONN_UPDATE = 0x0b, NODE_RX_TYPE_CONN_UPDATE = 0x0c,
NODE_RX_TYPE_ENC_REFRESH = 0x0c, NODE_RX_TYPE_ENC_REFRESH = 0x0d,
#if defined(CONFIG_BT_CTLR_LE_PING) #if defined(CONFIG_BT_CTLR_LE_PING)
NODE_RX_TYPE_APTO = 0x0d, NODE_RX_TYPE_APTO = 0x0e,
#endif /* CONFIG_BT_CTLR_LE_PING */ #endif /* CONFIG_BT_CTLR_LE_PING */
NODE_RX_TYPE_CHAN_SEL_ALGO = 0x0e, NODE_RX_TYPE_CHAN_SEL_ALGO = 0x0f,
#if defined(CONFIG_BT_CTLR_PHY) #if defined(CONFIG_BT_CTLR_PHY)
NODE_RX_TYPE_PHY_UPDATE = 0x0f, NODE_RX_TYPE_PHY_UPDATE = 0x10,
#endif /* CONFIG_BT_CTLR_PHY */ #endif /* CONFIG_BT_CTLR_PHY */
#if defined(CONFIG_BT_CTLR_CONN_RSSI) #if defined(CONFIG_BT_CTLR_CONN_RSSI)
NODE_RX_TYPE_RSSI = 0x10, NODE_RX_TYPE_RSSI = 0x11,
#endif /* CONFIG_BT_CTLR_CONN_RSSI */ #endif /* CONFIG_BT_CTLR_CONN_RSSI */
#endif /* CONFIG_BT_CONN */ #endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_CTLR_PROFILE_ISR) #if defined(CONFIG_BT_CTLR_PROFILE_ISR)
NODE_RX_TYPE_PROFILE = 0x11, NODE_RX_TYPE_PROFILE = 0x12,
#endif /* CONFIG_BT_CTLR_PROFILE_ISR */ #endif /* CONFIG_BT_CTLR_PROFILE_ISR */
#if defined(CONFIG_BT_CTLR_ADV_INDICATION) #if defined(CONFIG_BT_CTLR_ADV_INDICATION)
NODE_RX_TYPE_ADV_INDICATION = 0x12, NODE_RX_TYPE_ADV_INDICATION = 0x13,
#endif /* CONFIG_BT_CTLR_ADV_INDICATION */ #endif /* CONFIG_BT_CTLR_ADV_INDICATION */
#if defined(CONFIG_BT_CTLR_SCAN_INDICATION) #if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
NODE_RX_TYPE_SCAN_INDICATION = 0x13, NODE_RX_TYPE_SCAN_INDICATION = 0x14,
#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */ #endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
#if defined(CONFIG_BT_HCI_MESH_EXT) #if defined(CONFIG_BT_HCI_MESH_EXT)
NODE_RX_TYPE_MESH_ADV_CPLT = 0x14, NODE_RX_TYPE_MESH_ADV_CPLT = 0x15,
NODE_RX_TYPE_MESH_REPORT = 0x15, NODE_RX_TYPE_MESH_REPORT = 0x16,
#endif /* CONFIG_BT_HCI_MESH_EXT */ #endif /* CONFIG_BT_HCI_MESH_EXT */
/* Following proprietary defines must be at end of enum range */ /* Following proprietary defines must be at end of enum range */
#if defined(CONFIG_BT_CTLR_USER_EXT) #if defined(CONFIG_BT_CTLR_USER_EXT)
NODE_RX_TYPE_USER_START = 0x16, NODE_RX_TYPE_USER_START = 0x17,
NODE_RX_TYPE_USER_END = NODE_RX_TYPE_USER_START + NODE_RX_TYPE_USER_END = NODE_RX_TYPE_USER_START +
CONFIG_BT_CTLR_USER_EVT_RANGE, CONFIG_BT_CTLR_USER_EVT_RANGE,
#endif /* CONFIG_BT_CTLR_USER_EXT */ #endif /* CONFIG_BT_CTLR_USER_EXT */
@ -265,6 +266,10 @@ enum {
EVENT_DONE_EXTRA_TYPE_NONE, EVENT_DONE_EXTRA_TYPE_NONE,
EVENT_DONE_EXTRA_TYPE_CONN, EVENT_DONE_EXTRA_TYPE_CONN,
#if defined(CONFIG_BT_CTLR_ADV_EXT)
EVENT_DONE_EXTRA_TYPE_ADV,
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_OBSERVER) #if defined(CONFIG_BT_OBSERVER)
#if defined(CONFIG_BT_CTLR_ADV_EXT) #if defined(CONFIG_BT_CTLR_ADV_EXT)
EVENT_DONE_EXTRA_TYPE_SCAN_AUX, EVENT_DONE_EXTRA_TYPE_SCAN_AUX,

View file

@ -448,6 +448,9 @@ static void isr_done(void *param)
{ {
struct node_rx_hdr *node_rx; struct node_rx_hdr *node_rx;
struct lll_adv *lll = param; struct lll_adv *lll = param;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct event_done_extra *e;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
/* Clear radio status and events */ /* Clear radio status and events */
lll_isr_status_reset(); lll_isr_status_reset();
@ -554,6 +557,12 @@ static void isr_done(void *param)
ARG_UNUSED(node_rx); ARG_UNUSED(node_rx);
#endif /* !CONFIG_BT_CTLR_ADV_INDICATION */ #endif /* !CONFIG_BT_CTLR_ADV_INDICATION */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
e = ull_event_done_extra_get();
LL_ASSERT(e);
e->type = EVENT_DONE_EXTRA_TYPE_ADV;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
lll_isr_cleanup(param); lll_isr_cleanup(param);
} }

View file

@ -90,6 +90,10 @@ struct lll_adv {
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
int8_t tx_pwr_lvl; int8_t tx_pwr_lvl;
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct node_rx_hdr *node_rx_adv_term;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
}; };
int lll_adv_init(void); int lll_adv_init(void);

View file

@ -222,8 +222,21 @@ static MFIFO_DEFINE(pdu_rx_free, sizeof(void *), PDU_RX_CNT);
#define BT_CTLR_MAX_CONN 0 #define BT_CTLR_MAX_CONN 0
#endif #endif
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#if defined(CONFIG_BT_CTLR_ADV_SET)
#define BT_CTLR_ADV_SET CONFIG_BT_CTLR_ADV_SET
#else /* CONFIG_BT_CTLR_ADV_SET */
#define BT_CTLR_ADV_SET 1
#endif /* CONFIG_BT_CTLR_ADV_SET */
#else /* CONFIG_BT_CTLR_ADV_EXT */
#define BT_CTLR_ADV_SET 0
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#define PDU_RX_POOL_SIZE (PDU_RX_NODE_POOL_ELEMENT_SIZE * \ #define PDU_RX_POOL_SIZE (PDU_RX_NODE_POOL_ELEMENT_SIZE * \
(RX_CNT + BT_CTLR_MAX_CONNECTABLE)) (RX_CNT + BT_CTLR_MAX_CONNECTABLE + \
BT_CTLR_ADV_SET))
static struct { static struct {
void *free; void *free;
@ -231,7 +244,8 @@ static struct {
} mem_pdu_rx; } mem_pdu_rx;
#define LINK_RX_POOL_SIZE (sizeof(memq_link_t) * (RX_CNT + 2 + \ #define LINK_RX_POOL_SIZE (sizeof(memq_link_t) * (RX_CNT + 2 + \
BT_CTLR_MAX_CONN)) BT_CTLR_MAX_CONN + \
BT_CTLR_ADV_SET))
static struct { static struct {
uint8_t quota_pdu; /* Number of un-utilized buffers */ uint8_t quota_pdu; /* Number of un-utilized buffers */
@ -266,6 +280,10 @@ static inline void rx_demux_event_done(memq_link_t *link,
static inline void ll_rx_link_inc_quota(int8_t delta); static inline void ll_rx_link_inc_quota(int8_t delta);
static void disabled_cb(void *param); static void disabled_cb(void *param);
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
static void term_evt_disable(struct ull_hdr *ull_hdr);
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CONN)
static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last); static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last);
#endif /* CONFIG_BT_CONN */ #endif /* CONFIG_BT_CONN */
@ -646,9 +664,9 @@ void ll_rx_dequeue(void)
* enabled status bitmask * enabled status bitmask
*/ */
bm = (IS_ENABLED(CONFIG_BT_OBSERVER) && bm = (IS_ENABLED(CONFIG_BT_OBSERVER) &&
ull_scan_is_enabled(0) << 1) | ull_scan_is_enabled(0) << 1) |
(IS_ENABLED(CONFIG_BT_BROADCASTER) && (IS_ENABLED(CONFIG_BT_BROADCASTER) &&
ull_adv_is_enabled(0)); ull_adv_is_enabled(0));
if (!bm) { if (!bm) {
ull_filter_adv_scan_state_cb(0); ull_filter_adv_scan_state_cb(0);
@ -665,6 +683,11 @@ void ll_rx_dequeue(void)
case NODE_RX_TYPE_REPORT: case NODE_RX_TYPE_REPORT:
#endif /* CONFIG_BT_OBSERVER */ #endif /* CONFIG_BT_OBSERVER */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* fallthrough */
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) #if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
case NODE_RX_TYPE_SCAN_REQ: case NODE_RX_TYPE_SCAN_REQ:
#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */ #endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
@ -824,6 +847,7 @@ void ll_rx_mem_release(void **node_rx)
case NODE_RX_TYPE_EXT_1M_REPORT: case NODE_RX_TYPE_EXT_1M_REPORT:
case NODE_RX_TYPE_EXT_2M_REPORT: case NODE_RX_TYPE_EXT_2M_REPORT:
case NODE_RX_TYPE_EXT_CODED_REPORT: case NODE_RX_TYPE_EXT_CODED_REPORT:
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
#endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) #if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
@ -1722,6 +1746,28 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx)
return 0; return 0;
} }
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
static void term_evt_disable(struct ull_hdr *ull_hdr)
{
struct lll_adv *lll;
struct ll_adv_set *adv;
uint8_t handle;
uint32_t ret;
lll = (struct lll_adv *)HDR_ULL2LLL(ull_hdr);
adv = (void *)HDR_LLL2EVT(lll);
handle = ull_adv_handle_get(adv);
LL_ASSERT(handle < BT_CTLR_ADV_SET);
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
TICKER_ID_ADV_BASE + handle, NULL, adv);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS)
|| (ret == TICKER_STATUS_BUSY));
}
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
static inline void rx_demux_event_done(memq_link_t *link, static inline void rx_demux_event_done(memq_link_t *link,
struct node_rx_hdr *rx) struct node_rx_hdr *rx)
{ {
@ -1741,6 +1787,52 @@ static inline void rx_demux_event_done(memq_link_t *link,
break; break;
#endif /* CONFIG_BT_CONN */ #endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
case EVENT_DONE_EXTRA_TYPE_ADV:
{
struct lll_adv *lll;
struct ll_adv_set *adv;
bool send_term_evt = false;
lll = (struct lll_adv *)HDR_ULL2LLL(ull_hdr);
adv = (void *)HDR_LLL2EVT(lll);
if ((adv->max_events > 0) &&
(adv->event_counter >= adv->max_events)) {
adv->max_events = 0;
send_term_evt = true;
lll->node_rx_adv_term->rx_ftr.extra = (void *)
((uint32_t)adv->event_counter & 0xff);
}
if (adv->remain_duration == 1) {
adv->remain_duration = 0;
send_term_evt = true;
lll->node_rx_adv_term->rx_ftr.extra = (void *)
(((uint32_t)adv->event_counter & 0xff)
| (BT_HCI_ERR_ADV_TIMEOUT << 8));
}
if (send_term_evt) {
lll->node_rx_adv_term->type =
NODE_RX_TYPE_EXT_ADV_TERMINATE;
lll->node_rx_adv_term->rx_ftr.param = (void *)
(uint32_t)(lll->node_rx_adv_term->handle);
rx = lll->node_rx_adv_term;
link = rx->link;
ll_rx_put(link, rx);
ll_rx_sched();
term_evt_disable(ull_hdr);
}
break;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_OBSERVER) #if defined(CONFIG_BT_OBSERVER)
#if defined(CONFIG_BT_CTLR_ADV_EXT) #if defined(CONFIG_BT_CTLR_ADV_EXT)
/* fallthrough checkpatch workaround! */ /* fallthrough checkpatch workaround! */

View file

@ -55,13 +55,13 @@ inline uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
static int init_reset(void); static int init_reset(void);
static inline struct ll_adv_set *is_disabled_get(uint8_t handle); static inline struct ll_adv_set *is_disabled_get(uint8_t handle);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
void *param); uint16_t lazy, void *param);
static void ticker_op_update_cb(uint32_t status, void *params); static void ticker_op_update_cb(uint32_t status, void *params);
#if defined(CONFIG_BT_PERIPHERAL) #if defined(CONFIG_BT_PERIPHERAL)
static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder,
void *param); uint16_t lazy, void *param);
static void ticker_op_stop_cb(uint32_t status, void *params); static void ticker_op_stop_cb(uint32_t status, void *params);
static void disabled_cb(void *param); static void disabled_cb(void *param);
static void conn_release(struct ll_adv_set *adv); static void conn_release(struct ll_adv_set *adv);
@ -477,7 +477,8 @@ uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
uint8_t scan_window, uint8_t scan_delay) uint8_t scan_window, uint8_t scan_delay)
{ {
#else /* !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_HCI_MESH_EXT */
uint8_t ll_adv_enable(uint8_t handle, uint8_t enable) uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
uint16_t duration, uint8_t max_ext_adv_evts)
{ {
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC) #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
struct ll_adv_sync_set *sync = NULL; struct ll_adv_sync_set *sync = NULL;
@ -815,10 +816,45 @@ uint8_t ll_adv_enable(uint8_t enable)
return BT_HCI_ERR_HW_FAILURE; return BT_HCI_ERR_HW_FAILURE;
} }
} }
#if defined(CONFIG_BT_CTLR_ADV_EXT)
if (adv->is_created & ULL_ADV_CREATED_BITMASK_EXTENDED) {
struct node_rx_pdu *node_rx_adv_term;
void *link_adv_term;
/* The alloc here used for connection complete event */
link_adv_term = ll_rx_link_alloc();
if (!link_adv_term) {
/* TODO: figure out right return value */
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
node_rx_adv_term = ll_rx_alloc();
if (!node_rx_adv_term) {
ll_rx_link_release(link_adv_term);
/* TODO: figure out right return value */
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
node_rx_adv_term->hdr.link =
(memq_link_t *)link_adv_term;
adv->lll.node_rx_adv_term =
(struct node_rx_hdr *)node_rx_adv_term;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_PERIPHERAL */ #endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CTLR_ADV_EXT) #if defined(CONFIG_BT_CTLR_ADV_EXT)
const uint8_t phy = lll->phy_p; const uint8_t phy = lll->phy_p;
struct ull_hdr *ull;
ull = &adv->ull;
adv->max_events = max_ext_adv_evts;
adv->event_counter = 0;
/* duration unit is 10 ms, convert to units of 625 us */
adv->remain_duration = duration*16;
#else #else
/* Legacy ADV only supports LE_1M PHY */ /* Legacy ADV only supports LE_1M PHY */
const uint8_t phy = 1; const uint8_t phy = 1;
@ -1117,6 +1153,8 @@ uint8_t ll_adv_enable(uint8_t enable)
#endif /* !CONFIG_BT_HCI_MESH_EXT */ #endif /* !CONFIG_BT_HCI_MESH_EXT */
#endif /* CONFIG_BT_CTLR_PRIVACY */ #endif /* CONFIG_BT_CTLR_PRIVACY */
adv->next_random_delay = 0;
return 0; return 0;
failure_cleanup: failure_cleanup:
@ -1371,6 +1409,12 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t laz
struct lll_adv *lll; struct lll_adv *lll;
uint32_t ret; uint32_t ret;
uint8_t ref; uint8_t ref;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct ull_hdr *ull;
uint32_t time_this_evt;
uint32_t time_this_and_next_evt;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
uint32_t curr_random_delay = 0;
DEBUG_RADIO_PREPARE_A(1); DEBUG_RADIO_PREPARE_A(1);
@ -1400,29 +1444,60 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t laz
if (!lll->is_hdcd) if (!lll->is_hdcd)
#endif /* CONFIG_BT_PERIPHERAL */ #endif /* CONFIG_BT_PERIPHERAL */
{ {
uint32_t random_delay;
uint32_t ret; uint32_t ret;
lll_rand_isr_get(&random_delay, sizeof(random_delay)); curr_random_delay = adv->next_random_delay;
random_delay %= ULL_ADV_RANDOM_DELAY; /* initialized to 0, so the first time, we generate a value */
random_delay += 1; if (curr_random_delay == 0) {
lll_rand_isr_get(&curr_random_delay,
sizeof(curr_random_delay));
curr_random_delay %= ULL_ADV_RANDOM_DELAY;
curr_random_delay += 1;
}
lll_rand_isr_get(&adv->next_random_delay,
sizeof(adv->next_random_delay));
adv->next_random_delay %= ULL_ADV_RANDOM_DELAY;
adv->next_random_delay += 1;
ret = ticker_update(TICKER_INSTANCE_ID_CTLR, ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_HIGH,
(TICKER_ID_ADV_BASE + (TICKER_ID_ADV_BASE +
ull_adv_handle_get(adv)), ull_adv_handle_get(adv)),
random_delay, curr_random_delay,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
ticker_op_update_cb, adv); ticker_op_update_cb, adv);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_BUSY)); (ret == TICKER_STATUS_BUSY));
} }
#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) #if defined(CONFIG_BT_CTLR_ADV_EXT)
ull = &adv->ull;
adv->event_counter += (lazy + 1);
time_this_evt =
(HAL_TICKER_TICKS_TO_US(curr_random_delay) / 625U)
+ adv->interval;
time_this_and_next_evt = (HAL_TICKER_TICKS_TO_US
(curr_random_delay + adv->next_random_delay) / 625U)
+ 2*adv->interval;
if (adv->remain_duration) {
if (adv->remain_duration >= time_this_and_next_evt) {
adv->remain_duration -= time_this_evt;
} else {
/* 1 means terminate adv set after this event*/
adv->remain_duration = 1;
}
}
#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
if (adv->lll.aux) { if (adv->lll.aux) {
ull_adv_aux_offset_get(adv); ull_adv_aux_offset_get(adv);
} }
#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */ #endif /* CONFIG_BT_CTLR_ADV_AUX_SET > 0 */
#endif /* CONFIG_BT_CTLR_ADV_EXT */
DEBUG_RADIO_PREPARE_A(1); DEBUG_RADIO_PREPARE_A(1);
} }
@ -1434,8 +1509,8 @@ static void ticker_op_update_cb(uint32_t status, void *param)
} }
#if defined(CONFIG_BT_PERIPHERAL) #if defined(CONFIG_BT_PERIPHERAL)
static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder,
void *param) uint16_t lazy, void *param)
{ {
struct ll_adv_set *adv = param; struct ll_adv_set *adv = param;
uint8_t handle; uint8_t handle;

View file

@ -19,10 +19,15 @@ struct ll_adv_set {
uint8_t rnd_addr[BDADDR_SIZE]; uint8_t rnd_addr[BDADDR_SIZE];
uint8_t sid:4; uint8_t sid:4;
uint8_t is_created:2; uint8_t is_created:2;
uint16_t max_events;
uint16_t event_counter;
uint32_t remain_duration;
#else /* !CONFIG_BT_CTLR_ADV_EXT */ #else /* !CONFIG_BT_CTLR_ADV_EXT */
uint16_t interval; uint16_t interval;
#endif /* !CONFIG_BT_CTLR_ADV_EXT */ #endif /* !CONFIG_BT_CTLR_ADV_EXT */
uint32_t next_random_delay;
uint8_t is_enabled:1; uint8_t is_enabled:1;
#if defined(CONFIG_BT_CTLR_PRIVACY) #if defined(CONFIG_BT_CTLR_PRIVACY)

View file

@ -214,6 +214,27 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
} }
} }
#if defined(CONFIG_BT_CTLR_ADV_EXT)
if (adv->is_created & ULL_ADV_CREATED_BITMASK_EXTENDED) {
struct ull_hdr *ull;
ull = &adv->ull;
ll_rx_put(link, rx);
/* use reserved link and node_rx to prepare
* advertising terminate event
*/
rx = adv->lll.node_rx_adv_term;
link = rx->link;
rx->handle = ull_adv_handle_get(adv);
rx->type = NODE_RX_TYPE_EXT_ADV_TERMINATE;
rx->rx_ftr.param = (void *)((uint32_t)lll->handle);
rx->rx_ftr.extra = (void *)(((uint32_t)rx->rx_ftr.extra & 0xff)
| (BT_HCI_ERR_SUCCESS << 8));
}
#endif
ll_rx_put(link, rx); ll_rx_put(link, rx);
ll_rx_sched(); ll_rx_sched();
@ -348,8 +369,8 @@ void ull_slave_done(struct node_rx_event_done *done, uint32_t *ticks_drift_plus,
} }
} }
void ull_slave_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, void ull_slave_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
void *param) uint16_t lazy, void *param)
{ {
static memq_link_t link; static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, lll_slave_prepare}; static struct mayfly mfy = {0, 0, &link, NULL, lll_slave_prepare};

View file

@ -1116,7 +1116,7 @@ static int cmd_adv_start(const struct shell *shell, size_t argc, char *argv[])
timeout = strtoul(argv[argn], NULL, 16); timeout = strtoul(argv[argn], NULL, 16);
} }
if (!strcmp(arg, "num_events")) { if (!strcmp(arg, "num-events")) {
if (++argn == argc) { if (++argn == argc) {
goto fail_show_help; goto fail_show_help;
} }
@ -2470,8 +2470,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
SHELL_CMD_ARG(adv-data, NULL, "<data> [scan-response <data>] " SHELL_CMD_ARG(adv-data, NULL, "<data> [scan-response <data>] "
"<type: discov, name, hex>", cmd_adv_data, "<type: discov, name, hex>", cmd_adv_data,
1, 16), 1, 16),
SHELL_CMD_ARG(adv-start, NULL, "[timeout] [num_events]", cmd_adv_start, SHELL_CMD_ARG(adv-start, NULL,
1, 4), "[timeout <timeout>] [num-events <num events>]",
cmd_adv_start, 1, 4),
SHELL_CMD_ARG(adv-stop, NULL, "", cmd_adv_stop, 1, 0), SHELL_CMD_ARG(adv-stop, NULL, "", cmd_adv_stop, 1, 0),
SHELL_CMD_ARG(adv-delete, NULL, "", cmd_adv_delete, 1, 0), SHELL_CMD_ARG(adv-delete, NULL, "", cmd_adv_delete, 1, 0),
SHELL_CMD_ARG(adv-select, NULL, "[adv]", cmd_adv_select, 1, 1), SHELL_CMD_ARG(adv-select, NULL, "[adv]", cmd_adv_select, 1, 1),

View file

@ -270,7 +270,7 @@ disable:
#if defined(CONFIG_BT_HCI_MESH_EXT) #if defined(CONFIG_BT_HCI_MESH_EXT)
err = ll_adv_enable(handle, enable, 0, 0, 0, 0, 0); err = ll_adv_enable(handle, enable, 0, 0, 0, 0, 0);
#else /* !CONFIG_BT_HCI_MESH_EXT */ #else /* !CONFIG_BT_HCI_MESH_EXT */
err = ll_adv_enable(handle, enable); err = ll_adv_enable(handle, enable, 0, 0);
#endif /* !CONFIG_BT_HCI_MESH_EXT */ #endif /* !CONFIG_BT_HCI_MESH_EXT */
if (err) { if (err) {
goto exit; goto exit;

View file

@ -128,7 +128,7 @@ static void test_advx_main(void)
} }
printk("enabling..."); printk("enabling...");
err = ll_adv_enable(handle, 1); err = ll_adv_enable(handle, 1, 0, 0);
if (err) { if (err) {
goto exit; goto exit;
} }
@ -137,7 +137,7 @@ static void test_advx_main(void)
k_sleep(K_MSEC(400)); k_sleep(K_MSEC(400));
printk("Disabling..."); printk("Disabling...");
err = ll_adv_enable(handle, 0); err = ll_adv_enable(handle, 0, 0, 0);
if (err) { if (err) {
goto exit; goto exit;
} }
@ -153,7 +153,7 @@ static void test_advx_main(void)
} }
printk("enabling..."); printk("enabling...");
err = ll_adv_enable(handle, 1); err = ll_adv_enable(handle, 1, 0, 0);
if (err) { if (err) {
goto exit; goto exit;
} }
@ -182,7 +182,7 @@ static void test_advx_main(void)
k_sleep(K_MSEC(400)); k_sleep(K_MSEC(400));
printk("Disabling..."); printk("Disabling...");
err = ll_adv_enable(handle, 0); err = ll_adv_enable(handle, 0, 0, 0);
if (err) { if (err) {
goto exit; goto exit;
} }
@ -203,7 +203,7 @@ static void test_advx_main(void)
} }
printk("enabling extended..."); printk("enabling extended...");
err = ll_adv_enable(handle, 1); err = ll_adv_enable(handle, 1, 0, 0);
if (err) { if (err) {
goto exit; goto exit;
} }
@ -235,7 +235,7 @@ static void test_advx_main(void)
k_sleep(K_MSEC(400)); k_sleep(K_MSEC(400));
printk("Disabling..."); printk("Disabling...");
err = ll_adv_enable(handle, 0); err = ll_adv_enable(handle, 0, 0, 0);
if (err) { if (err) {
goto exit; goto exit;
} }