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:
parent
44d046ff8d
commit
254a97af93
14 changed files with 904 additions and 26 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
79
subsys/bluetooth/controller/ll_sw/ll_mesh.c
Normal file
79
subsys/bluetooth/controller/ll_sw/ll_mesh.c
Normal 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;
|
||||
}
|
14
subsys/bluetooth/controller/ll_sw/ll_mesh.h
Normal file
14
subsys/bluetooth/controller/ll_sw/ll_mesh.h
Normal 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);
|
|
@ -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 {
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue