Bluetooth: controller: Preliminary work in progress mesh ext.

Preliminary work done towards Mesh extensions on the old LL
architecture implementation.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2019-01-09 21:25:14 +05:30 committed by Carles Cufí
commit 254a97af93
14 changed files with 904 additions and 26 deletions

View file

@ -1,6 +1,7 @@
/* hci_vs.h - Bluetooth Host Control Interface Vendor Specific definitions */
/*
* Copyright (c) 2017-2018 Nordic Semiconductor ASA
* Copyright (c) 2015-2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
@ -163,6 +164,142 @@ struct bt_hci_evt_vs_scan_req_rx {
#define BT_EVT_MASK_VS_TRACE_INFO BT_EVT_BIT(2)
#define BT_EVT_MASK_VS_SCAN_REQ_RX BT_EVT_BIT(3)
/* Mesh HCI commands */
#define BT_HCI_MESH_REVISION 0x01
#define BT_HCI_OP_VS_MESH BT_OP(BT_OGF_VS, 0x0042)
#define BT_HCI_MESH_EVT_PREFIX 0xF0
struct bt_hci_cp_mesh {
u8_t opcode;
} __packed;
#define BT_HCI_OC_MESH_GET_OPTS 0x00
struct bt_hci_rp_mesh_get_opts {
u8_t status;
u8_t opcode;
u8_t revision;
u8_t ch_map;
s8_t min_tx_power;
s8_t max_tx_power;
u8_t max_scan_filter;
u8_t max_filter_pattern;
u8_t max_adv_slot;
u8_t max_tx_window;
u8_t evt_prefix_len;
u8_t evt_prefix;
} __packed;
#define BT_HCI_MESH_PATTERN_LEN_MAX 0x0f
#define BT_HCI_OC_MESH_SET_SCAN_FILTER 0x01
struct bt_hci_mesh_pattern {
u8_t pattern_len;
u8_t pattern[0];
} __packed;
struct bt_hci_cp_mesh_set_scan_filter {
u8_t scan_filter;
u8_t filter_dup;
u8_t num_patterns;
struct bt_hci_mesh_pattern patterns[0];
} __packed;
struct bt_hci_rp_mesh_set_scan_filter {
u8_t status;
u8_t opcode;
u8_t scan_filter;
} __packed;
#define BT_HCI_OC_MESH_ADVERTISE 0x02
struct bt_hci_cp_mesh_advertise {
u8_t adv_slot;
u8_t own_addr_type;
bt_addr_t random_addr;
u8_t ch_map;
s8_t tx_power;
u8_t min_tx_delay;
u8_t max_tx_delay;
u8_t retx_count;
u8_t retx_interval;
u8_t scan_delay;
u16_t scan_duration;
u8_t scan_filter;
u8_t data_len;
u8_t data[31];
} __packed;
struct bt_hci_rp_mesh_advertise {
u8_t status;
u8_t opcode;
u8_t adv_slot;
} __packed;
#define BT_HCI_OC_MESH_ADVERTISE_TIMED 0x03
struct bt_hci_cp_mesh_advertise_timed {
u8_t adv_slot;
u8_t own_addr_type;
bt_addr_t random_addr;
u8_t ch_map;
s8_t tx_power;
u8_t retx_count;
u8_t retx_interval;
u32_t instant;
u16_t tx_delay;
u16_t tx_window;
u8_t data_len;
u8_t data[31];
} __packed;
struct bt_hci_rp_mesh_advertise_timed {
u8_t status;
u8_t opcode;
u8_t adv_slot;
} __packed;
#define BT_HCI_OC_MESH_ADVERTISE_CANCEL 0x04
struct bt_hci_cp_mesh_advertise_cancel {
u8_t adv_slot;
} __packed;
struct bt_hci_rp_mesh_advertise_cancel {
u8_t status;
u8_t opcode;
u8_t adv_slot;
} __packed;
#define BT_HCI_OC_MESH_SET_SCANNING 0x05
struct bt_hci_cp_mesh_set_scanning {
u8_t enable;
u8_t ch_map;
u8_t scan_filter;
} __packed;
struct bt_hci_rp_mesh_set_scanning {
u8_t status;
u8_t opcode;
} __packed;
/* Events */
struct bt_hci_evt_mesh {
u8_t prefix;
u8_t subevent;
} __packed;
#define BT_HCI_EVT_MESH_ADV_COMPLETE 0x00
struct bt_hci_evt_mesh_adv_complete {
u8_t adv_slot;
} __packed;
#define BT_HCI_EVT_MESH_SCANNING_REPORT 0x01
struct bt_hci_evt_mesh_scan_report {
bt_addr_le_t addr;
u8_t chan;
s8_t rssi;
u32_t instant;
u8_t data_len;
u8_t data[0];
} __packed;
struct bt_hci_evt_mesh_scanning_report {
u8_t num_reports;
struct bt_hci_evt_mesh_scan_report reports[0];
} __packed;
#ifdef __cplusplus
}
#endif

View file

@ -35,6 +35,12 @@ config BT_HCI_VS_EXT_DETECT
sending vendor commands to controller which may interpret them in
completely different ways.
config BT_HCI_MESH_EXT
bool "Mesh HCI Command support"
depends on BT_BROADCASTER && BT_OBSERVER && !BT_LL_SW_SPLIT
help
Enable support for the Bluetooth Mesh HCI Commands.
config BT_RPA
# Virtual/hidden option
bool

View file

@ -41,16 +41,16 @@ if(CONFIG_BT_LL_SW)
CONFIG_BT_CTLR_ADV_EXT
ll_sw/ll_adv_aux.c
)
zephyr_library_sources_ifdef(
CONFIG_BT_HCI_MESH_EXT
ll_sw/ll_mesh.c
)
zephyr_library_sources_ifdef(
CONFIG_BT_CTLR_DTM
ll_sw/ll_test.c
)
endif()
zephyr_library_sources_ifdef(
CONFIG_BT_CTLR_FILTER
ll_sw/ll_filter.c
)
zephyr_library_sources_ifdef(
CONFIG_SOC_COMPATIBLE_NRF

View file

@ -71,6 +71,26 @@ config BT_CTLR_DUP_FILTER_LEN
Set the number of unique BLE addresses that can be filtered as
duplicates while scanning.
config BT_CTLR_MESH_SCAN_FILTERS
prompt "Number of Mesh scan filters"
int
depends on BT_HCI_MESH_EXT
default 1
range 1 15
help
Set the number of unique Mesh Scan Filters available as part of
the Intel Mesh Vendor Specific Extensions.
config BT_CTLR_MESH_SF_PATTERNS
prompt "Number of Mesh scan filter patterns"
int
depends on BT_HCI_MESH_EXT
default 15
range 1 15
help
Set the number of unique Mesh Scan Filter patterns available per
Scan Filter as part of the Intel Mesh Vendor Specific Extensions.
config BT_CTLR_RX_BUFFERS
int "Number of Rx buffers"
default 6 if BT_HCI_RAW

View file

@ -34,6 +34,10 @@
#include "ll_feat.h"
#include "hci_internal.h"
#if defined(CONFIG_BT_HCI_MESH_EXT)
#include "ll_sw/ll_mesh.h"
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_DTM_HCI)
#include "ll_sw/ll_test.h"
#endif /* CONFIG_BT_CTLR_DTM_HCI */
@ -60,6 +64,18 @@ static s32_t dup_count;
static u32_t dup_curr;
#endif
#if defined(CONFIG_BT_HCI_MESH_EXT)
struct scan_filter {
u8_t count;
u8_t lengths[CONFIG_BT_CTLR_MESH_SF_PATTERNS];
u8_t patterns[CONFIG_BT_CTLR_MESH_SF_PATTERNS]
[BT_HCI_MESH_PATTERN_LEN_MAX];
};
static struct scan_filter scan_filters[CONFIG_BT_CTLR_MESH_SCAN_FILTERS];
static u8_t sf_curr;
#endif
#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
s32_t hci_hbuf_total;
u32_t hci_hbuf_sent;
@ -139,6 +155,20 @@ static void *meta_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
return net_buf_add(buf, melen);
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
static void *mesh_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
{
struct bt_hci_evt_mesh *me;
evt_create(buf, BT_HCI_EVT_VENDOR, sizeof(*me) + melen);
me = net_buf_add(buf, sizeof(*me));
me->prefix = BT_HCI_MESH_EVT_PREFIX;
me->subevent = subevt;
return net_buf_add(buf, melen);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CONN)
static void disconnect(struct net_buf *buf, struct net_buf **evt)
{
@ -210,6 +240,15 @@ static void reset(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_evt_cc_status *ccst;
#if defined(CONFIG_BT_HCI_MESH_EXT)
int i;
for (i = 0; i < ARRAY_SIZE(scan_filters); i++) {
scan_filters[i].count = 0;
}
sf_curr = 0xFF;
#endif
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
dup_count = -1;
#endif
@ -950,11 +989,15 @@ static void le_set_adv_enable(struct net_buf *buf, struct net_buf **evt)
struct bt_hci_evt_cc_status *ccst;
u8_t status;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT) || 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);
#else /* !CONFIG_BT_HCI_MESH_EXT */
status = ll_adv_enable(0, cmd->enable);
#else /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_HCI_MESH_EXT */
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
status = ll_adv_enable(cmd->enable);
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = status;
@ -1923,6 +1966,160 @@ static void vs_read_key_hierarchy_roots(struct net_buf *buf,
}
#endif /* CONFIG_BT_HCI_VS_EXT */
#if defined(CONFIG_BT_HCI_MESH_EXT)
static void mesh_get_opts(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_mesh_get_opts *rp;
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
rp->opcode = BT_HCI_OC_MESH_GET_OPTS;
rp->revision = BT_HCI_MESH_REVISION;
rp->ch_map = 0x7;
/*@todo: nRF51 only */
rp->min_tx_power = -30;
/*@todo: nRF51 only */
rp->max_tx_power = 4;
rp->max_scan_filter = CONFIG_BT_CTLR_MESH_SCAN_FILTERS;
rp->max_filter_pattern = CONFIG_BT_CTLR_MESH_SF_PATTERNS;
rp->max_adv_slot = 1;
rp->evt_prefix_len = 0x01;
rp->evt_prefix = BT_HCI_MESH_EVT_PREFIX;
}
static void mesh_set_scan_filter(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_mesh_set_scan_filter *cmd = (void *)buf->data;
struct bt_hci_rp_mesh_set_scan_filter *rp;
u8_t filter = cmd->scan_filter - 1;
struct scan_filter *f;
u8_t status = 0x00;
u8_t i;
if (filter > ARRAY_SIZE(scan_filters) ||
cmd->num_patterns > CONFIG_BT_CTLR_MESH_SF_PATTERNS) {
status = BT_HCI_ERR_INVALID_PARAM;
goto exit;
}
if (filter == sf_curr) {
status = BT_HCI_ERR_CMD_DISALLOWED;
goto exit;
}
/* duplicate filtering not supported yet */
if (cmd->filter_dup) {
status = BT_HCI_ERR_INVALID_PARAM;
goto exit;
}
f = &scan_filters[filter];
for (i = 0; i < cmd->num_patterns; i++) {
if (!cmd->patterns[i].pattern_len ||
cmd->patterns[i].pattern_len >
BT_HCI_MESH_PATTERN_LEN_MAX) {
status = BT_HCI_ERR_INVALID_PARAM;
goto exit;
}
f->lengths[i] = cmd->patterns[i].pattern_len;
memcpy(f->patterns[i], cmd->patterns[i].pattern, f->lengths[i]);
}
f->count = cmd->num_patterns;
exit:
rp = cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->opcode = BT_HCI_OC_MESH_SET_SCAN_FILTER;
rp->scan_filter = filter + 1;
}
static void mesh_advertise(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_mesh_advertise *cmd = (void *)buf->data;
struct bt_hci_rp_mesh_advertise *rp;
u8_t adv_slot = cmd->adv_slot;
u8_t status;
status = ll_mesh_advertise(adv_slot,
cmd->own_addr_type, cmd->random_addr.val,
cmd->ch_map, cmd->tx_power,
cmd->min_tx_delay, cmd->max_tx_delay,
cmd->retx_count, cmd->retx_interval,
cmd->scan_duration, cmd->scan_delay,
cmd->scan_filter, cmd->data_len, cmd->data);
if (!status) {
/* Yields 0xFF if no scan filter selected */
sf_curr = cmd->scan_filter - 1;
}
rp = cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->opcode = BT_HCI_OC_MESH_ADVERTISE;
rp->adv_slot = adv_slot;
}
static void mesh_advertise_cancel(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_mesh_advertise_cancel *cmd = (void *)buf->data;
struct bt_hci_rp_mesh_advertise_cancel *rp;
u8_t adv_slot = cmd->adv_slot;
u8_t status;
status = ll_mesh_advertise_cancel(adv_slot);
if (!status) {
/* Yields 0xFF if no scan filter selected */
sf_curr = 0xFF;
}
rp = cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->opcode = BT_HCI_OC_MESH_ADVERTISE_CANCEL;
rp->adv_slot = adv_slot;
}
static int mesh_cmd_handle(struct net_buf *cmd, struct net_buf **evt)
{
struct bt_hci_cp_mesh *cp_mesh;
u8_t mesh_op;
if (cmd->len < sizeof(*cp_mesh)) {
BT_ERR("No HCI VSD Command header");
return -EINVAL;
}
cp_mesh = (void *)cmd->data;
mesh_op = cp_mesh->opcode;
net_buf_pull(cmd, sizeof(*cp_mesh));
switch (mesh_op) {
case BT_HCI_OC_MESH_GET_OPTS:
mesh_get_opts(cmd, evt);
break;
case BT_HCI_OC_MESH_SET_SCAN_FILTER:
mesh_set_scan_filter(cmd, evt);
break;
case BT_HCI_OC_MESH_ADVERTISE:
mesh_advertise(cmd, evt);
break;
case BT_HCI_OC_MESH_ADVERTISE_CANCEL:
mesh_advertise_cancel(cmd, evt);
break;
default:
return -EINVAL;
}
return 0;
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
static int vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
struct net_buf **evt)
{
@ -1957,6 +2154,12 @@ static int vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
break;
#endif /* CONFIG_BT_HCI_VS_EXT */
#if defined(CONFIG_BT_HCI_MESH_EXT)
case BT_OCF(BT_HCI_OP_VS_MESH):
mesh_cmd_handle(cmd, evt);
break;
#endif /* CONFIG_BT_HCI_MESH_EXT */
default:
return -EINVAL;
}
@ -2220,6 +2423,62 @@ static inline void le_dir_adv_report(struct pdu_adv *adv, struct net_buf *buf,
#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
#if defined(CONFIG_BT_OBSERVER)
#if defined(CONFIG_BT_HCI_MESH_EXT)
static inline bool scan_filter_apply(u8_t filter, u8_t *data, u8_t len)
{
struct scan_filter *f = &scan_filters[filter];
int i;
/* No patterns means filter out all advertising packets */
for (i = 0; i < f->count; i++) {
/* Require at least the length of the pattern */
if (len >= f->lengths[i] &&
!memcmp(data, f->patterns[i], f->lengths[i])) {
return true;
}
}
return false;
}
static inline void le_mesh_scan_report(struct pdu_adv *adv, struct net_buf *buf,
s8_t rssi, u8_t *extra)
{
u8_t data_len = (adv->len - BDADDR_SIZE);
struct bt_hci_evt_mesh_scanning_report *mep;
struct bt_hci_evt_mesh_scan_report *sr;
u32_t instant;
u8_t chan;
LL_ASSERT(adv->type == PDU_ADV_TYPE_NONCONN_IND);
/* Filter based on currently active Scan Filter */
if (sf_curr < ARRAY_SIZE(scan_filters) &&
!scan_filter_apply(sf_curr, &adv->adv_ind.data[0], data_len)) {
/* Drop the report */
return;
}
chan = *extra;
extra++;
instant = sys_get_le32(extra);
mep = mesh_evt(buf, BT_HCI_EVT_MESH_SCANNING_REPORT,
sizeof(*mep) + sizeof(*sr));
mep->num_reports = 1;
sr = (void *)(((u8_t *)mep) + sizeof(*mep));
sr->addr.type = adv->tx_addr;
memcpy(&sr->addr.a.val[0], &adv->adv_ind.addr[0], sizeof(bt_addr_t));
sr->chan = chan;
sr->rssi = rssi;
sys_put_le32(instant, (u8_t *)&sr->instant);
sr->data_len = data_len;
memcpy(&sr->data[0], &adv->adv_ind.data[0], data_len);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,
struct net_buf *buf)
{
@ -2270,6 +2529,13 @@ static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,
}
#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (((struct node_rx_pdu *)b)->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
le_mesh_scan_report(adv, buf, rssi, extra);
return;
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
!(le_event_mask & BT_EVT_MASK_LE_ADVERTISING_REPORT)) {
return;
@ -2660,6 +2926,17 @@ static void le_phy_upd_complete(struct pdu_data *pdu_data, u16_t handle,
#endif /* CONFIG_BT_CTLR_PHY */
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_HCI_MESH_EXT)
static void mesh_adv_cplt(struct pdu_data *pdu_data, u8_t *b,
struct net_buf *buf)
{
struct bt_hci_evt_mesh_adv_complete *mep;
mep = mesh_evt(buf, BT_HCI_EVT_MESH_ADV_COMPLETE, sizeof(*mep));
mep->adv_slot = ((u8_t *)pdu_data)[0];
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
static void encode_control(struct node_rx_pdu *node_rx,
struct pdu_data *pdu_data, struct net_buf *buf)
{
@ -2762,6 +3039,16 @@ static void encode_control(struct node_rx_pdu *node_rx,
return;
#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
#if defined(CONFIG_BT_HCI_MESH_EXT)
case NODE_RX_TYPE_MESH_ADV_CPLT:
mesh_adv_cplt(pdu_data, b, buf);
return;
case NODE_RX_TYPE_MESH_REPORT:
le_advertising_report(pdu_data, b, buf);
return;
#endif /* CONFIG_BT_HCI_MESH_EXT */
default:
LL_ASSERT(0);
return;
@ -3086,6 +3373,11 @@ s8_t hci_get_class(struct node_rx_pdu *node_rx)
return HCI_CLASS_EVT_DISCARDABLE;
#endif
#if defined(CONFIG_BT_HCI_MESH_EXT)
case NODE_RX_TYPE_MESH_ADV_CPLT:
case NODE_RX_TYPE_MESH_REPORT:
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CONN)
case NODE_RX_TYPE_CONNECTION:
return HCI_CLASS_EVT_REQUIRED;

View file

@ -30,14 +30,20 @@ u8_t ll_adv_data_set(u8_t len, u8_t const *const p_data);
u8_t ll_adv_scan_rsp_set(u8_t len, u8_t const *const p_data);
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
#if defined(CONFIG_BT_HCI_MESH_EXT)
u8_t ll_adv_enable(u16_t handle, u8_t enable,
u8_t at_anchor, u32_t ticks_anchor, u8_t retry,
u8_t scan_window, u8_t scan_delay);
#else /* !CONFIG_BT_HCI_MESH_EXT */
u8_t ll_adv_enable(u16_t handle, u8_t enable);
#else /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_HCI_MESH_EXT */
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
u8_t ll_adv_enable(u8_t enable);
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
u8_t ll_scan_params_set(u8_t type, u16_t interval, u16_t window,
u8_t own_addr_type, u8_t filter_policy);
u8_t own_addr_type, u8_t filter_policy);
u8_t ll_scan_enable(u8_t enable);
u8_t ll_wl_size_get(void);

View file

@ -119,6 +119,15 @@ struct advertiser {
u8_t rl_idx;
#endif /* CONFIG_BT_CTLR_PRIVACY */
#if defined(CONFIG_BT_HCI_MESH_EXT)
u8_t retry:3;
u8_t is_mesh:1;
u8_t rfu1:4;
u8_t scan_delay_ms;
u16_t scan_window_ms;
#endif /* CONFIG_BT_HCI_MESH_EXT */
struct radio_adv_data adv_data;
struct radio_adv_data scan_data;
@ -178,6 +187,10 @@ static struct {
struct advertiser advertiser;
struct scanner scanner;
#if defined(CONFIG_BT_HCI_MESH_EXT)
u32_t mesh_adv_end_us;
#endif /* CONFIG_BT_HCI_MESH_EXT */
void *conn_pool;
void *conn_free;
u8_t connection_count;
@ -258,15 +271,15 @@ static void ticker_update_adv_assert(u32_t status, void *params);
static void ticker_stop_adv_assert(u32_t status, void *params);
static void ticker_update_slave_assert(u32_t status, void *params);
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_PERIPHERAL)
static void ticker_stop_adv_stop(u32_t status, void *params);
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CENTRAL)
static void ticker_stop_scan_assert(u32_t status, void *params);
#endif /* CONFIG_BT_CENTRAL */
static void ticker_stop_conn_assert(u32_t status, void *params);
static void ticker_start_conn_assert(u32_t status, void *params);
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_PERIPHERAL) || defined(CONFIG_BT_HCI_MESH_EXT)
static void ticker_stop_adv_stop(u32_t status, void *params);
#endif /* CONFIG_BT_PERIPHERAL || CONFIG_BT_HCI_MESH_EXT */
static void event_inactive(u32_t ticks_at_expire, u32_t remainder,
u16_t lazy, void *context);
@ -1223,6 +1236,13 @@ static u32_t isr_rx_scan_report(u8_t rssi_ready, u8_t rl_idx, bool dir_report)
/* Prepare the report (adv or scan resp) */
node_rx->hdr.handle = 0xffff;
if (0) {
#if defined(CONFIG_BT_HCI_MESH_EXT)
} else if (_radio.advertiser.is_enabled &&
_radio.advertiser.is_mesh) {
node_rx->hdr.type = NODE_RX_TYPE_MESH_REPORT;
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
} else if (_radio.scanner.phy) {
switch (_radio.scanner.phy) {
@ -1257,11 +1277,38 @@ static u32_t isr_rx_scan_report(u8_t rssi_ready, u8_t rl_idx, bool dir_report)
*extra = rl_idx;
extra += PDU_AC_SIZE_PRIV;
#endif /* CONFIG_BT_CTLR_PRIVACY */
#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
/* save the directed adv report flag */
*extra = dir_report ? 1 : 0;
extra += PDU_AC_SIZE_SCFP;
#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
/* save the directed adv report flag */
*extra = _radio.scanner.chan - 1;
extra++;
sys_put_le32(_radio.ticks_anchor, extra);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
/* save the directed adv report flag */
*extra = _radio.scanner.chan - 1;
extra++;
sys_put_le32(_radio.ticks_anchor, extra);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
/* save the directed adv report flag */
*extra = _radio.scanner.chan - 1;
extra++;
sys_put_le32(_radio.ticks_anchor, extra);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
packet_rx_enqueue();
@ -3949,10 +3996,121 @@ static inline void isr_radio_state_rx(u8_t trx_done, u8_t crc_ok,
}
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
static void mayfly_mesh_stop(void *param)
{
struct radio_pdu_node_rx *node_rx;
u8_t *adv_slot;
/* Prepare the rx packet structure */
node_rx = packet_rx_reserve_get(1);
LL_ASSERT(node_rx);
/* Connection handle */
node_rx->hdr.handle = 0xffff;
node_rx->hdr.type = NODE_RX_TYPE_MESH_ADV_CPLT;
adv_slot = (u8_t *)node_rx->pdu_data;
*adv_slot = 0;
/* enqueue event into rx queue */
packet_rx_enqueue();
}
static void ticker_start_mesh_scan(u32_t status, void *params)
{
ARG_UNUSED(params);
/* Failed to schedule mesh advertise scan window */
if (status && !_radio.advertiser.retry) {
static memq_link_t s_link;
static struct mayfly s_mfy_mesh_stop = {0, 0, &s_link, NULL,
mayfly_mesh_stop};
u32_t retval;
/* Generate an event in WORKER Prio */
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_JOB,
RADIO_TICKER_USER_ID_WORKER, 0,
&s_mfy_mesh_stop);
LL_ASSERT(!retval);
}
}
static inline u32_t isr_close_adv_mesh(void)
{
u32_t ticks_slot_offset;
u32_t ticker_status;
u32_t ticks_anchor;
u32_t ret = 0;
if (!_radio.advertiser.retry) {
ticker_status = ticker_stop(RADIO_TICKER_INSTANCE_ID_RADIO,
RADIO_TICKER_USER_ID_WORKER,
RADIO_TICKER_ID_ADV,
ticker_stop_adv_stop,
(void *)__LINE__);
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
(ticker_status == TICKER_STATUS_BUSY));
ret = 1;
} else {
_radio.advertiser.retry--;
}
_radio.scanner.ticks_window =
HAL_TICKER_US_TO_TICKS(_radio.advertiser.scan_window_ms * 1000 +
radio_tmr_end_get() -
_radio.mesh_adv_end_us);
_radio.scanner.hdr.ticks_active_to_start =
_radio.ticks_active_to_start;
_radio.scanner.hdr.ticks_xtal_to_start =
HAL_TICKER_US_TO_TICKS(RADIO_TICKER_XTAL_OFFSET_US);
_radio.scanner.hdr.ticks_preempt_to_start =
HAL_TICKER_US_TO_TICKS(RADIO_TICKER_PREEMPT_PART_MIN_US);
_radio.scanner.hdr.ticks_slot =
_radio.scanner.ticks_window +
HAL_TICKER_US_TO_TICKS(RADIO_TICKER_START_PART_US);
ticks_slot_offset = (_radio.scanner.hdr.ticks_active_to_start <
_radio.scanner.hdr.ticks_xtal_to_start) ?
_radio.scanner.hdr.ticks_xtal_to_start :
_radio.scanner.hdr.ticks_active_to_start;
/* FIXME: remainder compensation and chain delays */
ticks_anchor = _radio.ticks_anchor +
HAL_TICKER_US_TO_TICKS(_radio.mesh_adv_end_us +
_radio.advertiser.scan_delay_ms *
1000 -
RADIO_TICKER_XTAL_OFFSET_US);
ticker_status = ticker_start(RADIO_TICKER_INSTANCE_ID_RADIO,
RADIO_TICKER_USER_ID_WORKER,
RADIO_TICKER_ID_SCAN,
ticks_anchor, 0, 0, 0, TICKER_NULL_LAZY,
(ticks_slot_offset +
_radio.scanner.hdr.ticks_slot),
event_scan_prepare, NULL,
ticker_start_mesh_scan, NULL);
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
(ticker_status == TICKER_STATUS_BUSY));
return ret;
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
static inline u32_t isr_close_adv(void)
{
u32_t dont_close = 0U;
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (_radio.advertiser.is_mesh &&
_radio.state == STATE_CLOSE &&
!_radio.mesh_adv_end_us) {
_radio.mesh_adv_end_us = radio_tmr_end_get();
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
if ((_radio.state == STATE_CLOSE) &&
(_radio.advertiser.chan_map_current != 0)) {
u32_t start_us;
@ -3988,10 +4146,20 @@ static inline u32_t isr_close_adv(void)
u32_t ticker_status;
u16_t random_delay;
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (_radio.advertiser.is_mesh) {
u32_t err;
err = isr_close_adv_mesh();
if (err) {
return 0;
}
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
entropy_get_entropy_isr(_radio.entropy,
(void *)&random_delay,
sizeof(random_delay), 0);
random_delay %= HAL_TICKER_US_TO_TICKS(10000);
random_delay += 1;
@ -4077,6 +4245,14 @@ static inline u32_t isr_close_scan(void)
} else {
radio_filter_disable();
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (_radio.advertiser.is_enabled &&
_radio.advertiser.is_mesh &&
!_radio.advertiser.retry) {
mayfly_mesh_stop(NULL);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
if (_radio.state == STATE_ABORT) {
/* Scanner stop can expire while here in this ISR.
* Deferred attempt to stop can fail as it would have
@ -4590,7 +4766,6 @@ static void ticker_update_slave_assert(u32_t status, void *params)
(_radio.ticker_id_stop == ticker_id) ||
(_radio.ticker_id_upd == ticker_id));
}
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CENTRAL)
@ -4940,6 +5115,7 @@ static void mayfly_xtal_stop_calc(void *params)
struct shdr *hdr_curr = NULL;
struct shdr *hdr_next = NULL;
u32_t ticks_slot_abs;
#endif /* CONFIG_BT_CONN */
ticker_id_next = 0xff;
ticks_to_expire = 0U;
@ -6263,6 +6439,11 @@ static void event_adv(u32_t ticks_at_expire, u32_t remainder,
_radio.advertiser.chan_map_current = _radio.advertiser.chan_map;
adv_setup();
#if defined(CONFIG_BT_HCI_MESH_EXT)
_radio.mesh_adv_end_us = 0;
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_PRIVACY)
if (ctrl_rl_enabled()) {
struct ll_filter *filter =
@ -6327,6 +6508,7 @@ static void event_adv(u32_t ticks_at_expire, u32_t remainder,
DEBUG_RADIO_START_A(0);
}
#if defined(CONFIG_BT_PERIPHERAL) || defined(CONFIG_BT_HCI_MESH_EXT)
#if defined(CONFIG_BT_PERIPHERAL)
static void mayfly_adv_stop(void *param)
{
@ -6500,6 +6682,12 @@ static void ticker_stop_adv_stop(u32_t status, void *params)
ticker_stop_adv_stop_active();
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (params) {
return;
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_PERIPHERAL)
/* Generate an event in WORKER Prio */
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_JOB,
@ -6532,6 +6720,7 @@ void event_adv_stop(u32_t ticks_at_expire, u32_t remainder, u16_t lazy,
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
(ticker_status == TICKER_STATUS_BUSY));
}
#endif /* CONFIG_BT_PERIPHERAL || CONFIG_BT_HCI_MESH_EXT */
static void event_scan_prepare(u32_t ticks_at_expire, u32_t remainder,
u16_t lazy, void *context)
@ -10257,6 +10446,18 @@ role_disable_cleanup:
return ret_cb ? BT_HCI_ERR_CMD_DISALLOWED : 0;
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT)
u32_t radio_adv_enable(u8_t phy_p, u16_t interval, u8_t chan_map,
u8_t filter_policy, u8_t rl_idx,
#else /* !CONFIG_BT_CTLR_ADV_EXT */
u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
u8_t rl_idx,
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
u8_t at_anchor, u32_t ticks_anchor, u8_t retry,
u8_t scan_window, u8_t scan_delay)
{
#else /* !CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
u32_t radio_adv_enable(u8_t phy_p, u16_t interval, u8_t chan_map,
u8_t filter_policy, u8_t rl_idx)
@ -10265,11 +10466,12 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
u8_t rl_idx)
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
{
u32_t ticks_anchor;
#endif /* !CONFIG_BT_HCI_MESH_EXT */
u32_t volatile ret_cb = TICKER_STATUS_BUSY;
u32_t ticks_slot_offset;
struct connection *conn;
struct pdu_adv *pdu_adv;
u32_t ticks_anchor;
u32_t slot_us;
u8_t chan_cnt;
u32_t ret;
@ -10278,9 +10480,18 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
return BT_HCI_ERR_CMD_DISALLOWED;
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (scan_delay) {
if (_radio.scanner.is_enabled) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
_radio.advertiser.is_mesh = 1;
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
pdu_adv = (void *)&_radio.advertiser.adv_data.data
[_radio.advertiser.adv_data.last][0];
if ((pdu_adv->type == PDU_ADV_TYPE_ADV_IND) ||
(pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND)) {
void *link;
@ -10440,13 +10651,51 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
slot_us = (RADIO_TICKER_START_PART_US + 376 + 152 + 176 +
152 + 376) * chan_cnt;
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (_radio.advertiser.is_mesh) {
u16_t interval_min_us;
_radio.advertiser.retry = retry;
_radio.advertiser.scan_delay_ms = scan_delay;
_radio.advertiser.scan_window_ms = scan_window;
interval_min_us = slot_us + (scan_delay + scan_window) * 1000;
if ((interval * 625) < interval_min_us) {
interval = (interval_min_us + (625 - 1)) / 625;
}
/* passive scanning */
_radio.scanner.type = 0;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* TODO: Coded PHY support */
_radio.scanner.phy = 0;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_PRIVACY)
/* TODO: Privacy support */
_radio.scanner.rpa_gen = 0;
_radio.scanner.rl_idx = rl_idx;
#endif /* CONFIG_BT_CTLR_PRIVACY */
_radio.scanner.filter_policy = filter_policy;
}
#endif /* CONFIG_BT_HCI_MESH_EXT */
_radio.advertiser.hdr.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us);
ticks_slot_offset =
max(_radio.advertiser.hdr.ticks_active_to_start,
_radio.advertiser.hdr.ticks_xtal_to_start);
#if !defined(CONFIG_BT_HCI_MESH_EXT)
ticks_anchor = ticker_ticks_now_get();
#else /* CONFIG_BT_HCI_MESH_EXT */
if (!at_anchor) {
ticks_anchor = ticker_ticks_now_get();
}
#endif /* !CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_PERIPHERAL)
/* High Duty Cycle Directed Advertising if interval is 0. */
@ -10512,9 +10761,17 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
if (ret_cb == TICKER_STATUS_SUCCESS) {
_radio.advertiser.is_enabled = 1U;
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (_radio.advertiser.is_mesh) {
_radio.scanner.is_enabled = 1;
ll_adv_scan_state_cb(BIT(0) | BIT(1));
}
#else /* !CONFIG_BT_HCI_MESH_EXT */
if (!_radio.scanner.is_enabled) {
ll_adv_scan_state_cb(BIT(0));
}
#endif /* !CONFIG_BT_HCI_MESH_EXT */
return 0;
}
@ -11559,6 +11816,11 @@ void ll_rx_dequeue(void)
case NODE_RX_TYPE_ADV_INDICATION:
#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
#if defined(CONFIG_BT_HCI_MESH_EXT)
case NODE_RX_TYPE_MESH_ADV_CPLT:
case NODE_RX_TYPE_MESH_REPORT:
#endif /* CONFIG_BT_HCI_MESH_EXT */
/* release data link credit quota */
LL_ASSERT(_radio.link_rx_data_quota <
(_radio.packet_rx_count - 1));
@ -11617,6 +11879,17 @@ void ll_rx_dequeue(void)
ll_adv_scan_state_cb(0);
}
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_HCI_MESH_EXT)
} else if (node_rx->hdr.type == NODE_RX_TYPE_MESH_ADV_CPLT) {
LL_ASSERT(_radio.advertiser.is_enabled);
_radio.advertiser.is_enabled = 0;
LL_ASSERT(_radio.scanner.is_enabled);
_radio.scanner.is_enabled = 0;
ll_adv_scan_state_cb(0);
#endif /* CONFIG_BT_HCI_MESH_EXT */
}
}
@ -11698,6 +11971,11 @@ void ll_rx_mem_release(void **node_rx)
case NODE_RX_TYPE_ADV_INDICATION:
#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
#if defined(CONFIG_BT_HCI_MESH_EXT)
case NODE_RX_TYPE_MESH_ADV_CPLT:
case NODE_RX_TYPE_MESH_REPORT:
#endif /* CONFIG_BT_HCI_MESH_EXT */
mem_release(_node_rx_free,
&_radio.pkt_rx_data_free);
break;

View file

@ -191,6 +191,17 @@ void radio_ticks_active_to_start_set(u32_t ticks_active_to_start);
struct radio_adv_data *radio_adv_data_get(void);
struct radio_adv_data *radio_scan_data_get(void);
#if defined(CONFIG_BT_HCI_MESH_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT)
u32_t radio_adv_enable(u8_t phy_p, u16_t interval, u8_t chan_map,
u8_t filter_policy, u8_t rl_idx,
#else /* !CONFIG_BT_CTLR_ADV_EXT */
u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
u8_t rl_idx,
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
u8_t at_anchor, u32_t ticks_anchor, u8_t retry,
u8_t scan_window, u8_t scan_delay);
#else /* !CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
u32_t radio_adv_enable(u8_t phy_p, u16_t interval, u8_t chan_map,
u8_t filter_policy, u8_t rl_idx);
@ -198,6 +209,7 @@ u32_t radio_adv_enable(u8_t phy_p, u16_t interval, u8_t chan_map,
u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
u8_t rl_idx);
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_HCI_MESH_EXT */
u8_t radio_adv_disable(void);
u32_t ll_adv_is_enabled(u16_t handle);

View file

@ -381,11 +381,17 @@ u8_t ll_adv_scan_rsp_set(u8_t len, u8_t const *const data)
return 0;
}
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
#if defined(CONFIG_BT_HCI_MESH_EXT)
u8_t ll_adv_enable(u16_t handle, u8_t enable,
u8_t at_anchor, u32_t ticks_anchor, u8_t retry,
u8_t scan_window, u8_t scan_delay)
#else /* !CONFIG_BT_HCI_MESH_EXT */
u8_t ll_adv_enable(u16_t handle, u8_t enable)
#else /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_HCI_MESH_EXT */
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
u8_t ll_adv_enable(u8_t enable)
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
{
struct radio_adv_data *radio_scan_data;
struct radio_adv_data *radio_adv_data;
@ -467,6 +473,18 @@ u8_t ll_adv_enable(u8_t enable)
}
}
#if defined(CONFIG_BT_HCI_MESH_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT)
status = radio_adv_enable(ll_adv.phy_p, ll_adv.interval,
ll_adv.chan_map, ll_adv.filter_policy,
rl_idx,
#else /* !CONFIG_BT_CTLR_ADV_EXT */
status = radio_adv_enable(ll_adv.interval, ll_adv.chan_map,
ll_adv.filter_policy, rl_idx,
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
at_anchor, ticks_anchor, retry,
scan_window, scan_delay);
#else /* !CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
status = radio_adv_enable(ll_adv.phy_p, ll_adv.interval,
ll_adv.chan_map, ll_adv.filter_policy,
@ -475,6 +493,6 @@ u8_t ll_adv_enable(u8_t enable)
status = radio_adv_enable(ll_adv.interval, ll_adv.chan_map,
ll_adv.filter_policy, rl_idx);
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_HCI_MESH_EXT */
return status;
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2017-2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <zephyr.h>
#include <bluetooth/hci.h>
#include "hal/ticker.h"
#include "ticker/ticker.h"
#include "ll.h"
#include "ll_mesh.h"
u8_t ll_mesh_advertise(u8_t handle, u8_t own_addr_type,
u8_t const *const rand_addr,
u8_t chan_map, u8_t tx_pwr,
u8_t min_tx_delay, u8_t max_tx_delay,
u8_t retry, u8_t interval,
u8_t scan_window, u8_t scan_delay, u8_t scan_filter,
u8_t data_len, u8_t const *const data)
{
u32_t ticks_anchor;
u8_t err;
/* convert to 625 us units for internal use */
interval = ((u32_t)interval + 1) * 10000 / 625;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* Non-conn Non-Scan advertising */
err = ll_adv_params_set(handle, 0, interval, 0x03, own_addr_type,
0, NULL, chan_map, 0, NULL, 0, 0, 0, 0, 0);
#else
err = ll_adv_params_set(interval, 0x03, own_addr_type, 0, NULL,
chan_map, 0);
#endif
if (err) {
return err;
}
/* TODO: use the supplied random address instead of global random
* address.
*/
/* TODO: Tx power */
/* TODO: multi-instance adv data support */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
ll_adv_data_set(handle, data_len, data);
#else
ll_adv_data_set(data_len, data);
#endif
/* TODO: scan filter */
/* TODO: calculate random tx delay */
ticks_anchor = ticker_ticks_now_get();
ticks_anchor += HAL_TICKER_US_TO_TICKS(min_tx_delay * 10000);
/* Enable advertising instance */
err = ll_adv_enable(handle, 1,
1, ticks_anchor, retry,
scan_window, scan_delay);
return err;
}
u8_t ll_mesh_advertise_cancel(u8_t handle)
{
u8_t err;
/* TODO: multi-instance support */
err = ll_adv_enable(handle, 0, 0, 0, 0, 0, 0);
return err;
}

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2017-2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
u8_t ll_mesh_advertise(u8_t handle, u8_t own_addr_type,
u8_t const *const rand_addr,
u8_t chan_map, u8_t tx_pwr,
u8_t min_tx_delay, u8_t max_tx_delay,
u8_t retry, u8_t interval,
u8_t scan_window, u8_t scan_delay, u8_t scan_filter,
u8_t data_len, u8_t const *const data);
u8_t ll_mesh_advertise_cancel(u8_t handle);

View file

@ -38,9 +38,9 @@ enum {
#if defined(CONFIG_BT_BROADCASTER)
TICKER_ID_ADV_STOP,
TICKER_ID_ADV_BASE,
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
TICKER_ID_ADV_LAST = ((TICKER_ID_ADV_BASE) + (CONFIG_BT_ADV_MAX) - 1),
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
#endif /* CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_OBSERVER)
@ -58,7 +58,8 @@ enum {
TICKER_ID_MAX,
};
#if defined(CONFIG_BT_BROADCASTER) && !defined(CONFIG_BT_CTLR_ADV_EXT)
#if defined(CONFIG_BT_BROADCASTER) && !defined(CONFIG_BT_CTLR_ADV_EXT) && \
!defined(CONFIG_BT_HCI_MESH_EXT)
#define TICKER_ID_ADV_LAST TICKER_ID_ADV_BASE
#endif
@ -162,6 +163,11 @@ enum node_rx_type {
#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
NODE_RX_TYPE_SCAN_INDICATION = 0x12,
#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
#if defined(CONFIG_BT_HCI_MESH_EXT)
NODE_RX_TYPE_MESH_ADV_CPLT = 0x13,
NODE_RX_TYPE_MESH_REPORT = 0x14,
#endif /* CONFIG_BT_HCI_MESH_EXT */
};
struct node_rx_hdr {

View file

@ -28,10 +28,16 @@
#else
#define PDU_AC_SIZE_SCFP 0
#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
#if defined(CONFIG_BT_HCI_MESH_EXT)
#define PDU_AC_SIZE_MESH 5
#else
#define PDU_AC_SIZE_MESH 0
#endif /* CONFIG_BT_HCI_MESH_EXT */
#define PDU_AC_SIZE_EXTRA (PDU_AC_SIZE_RSSI + \
PDU_AC_SIZE_PRIV + \
PDU_AC_SIZE_SCFP)
PDU_AC_SIZE_SCFP + \
PDU_AC_SIZE_MESH)
struct pdu_adv_adv_ind {
u8_t addr[BDADDR_SIZE];

View file

@ -260,7 +260,11 @@ do_enable:
disable:
shell_print(shell, "adv enable (%u)...", enable);
#if defined(CONFIG_BT_HCI_MESH_EXT)
err = ll_adv_enable(handle, enable, 0, 0, 0, 0, 0);
#else /* !CONFIG_BT_HCI_MESH_EXT */
err = ll_adv_enable(handle, enable);
#endif /* !CONFIG_BT_HCI_MESH_EXT */
if (err) {
goto exit;
}