Update to nimble 1.3 master branch commit 82153e744833821e20e9a8b0d61c38b2b0dbcfe1
WARNING : heartbeat task is disabled!
This commit is contained in:
@@ -69,6 +69,29 @@ extern "C" {
|
||||
/* Timing jitter as per spec is +/16 usecs */
|
||||
#define BLE_LL_JITTER_USECS (16)
|
||||
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_SCA) < 0
|
||||
#error Invalid SCA value
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 20
|
||||
#define BLE_LL_SCA_ENUM 7
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 30
|
||||
#define BLE_LL_SCA_ENUM 6
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 50
|
||||
#define BLE_LL_SCA_ENUM 5
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 75
|
||||
#define BLE_LL_SCA_ENUM 4
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 100
|
||||
#define BLE_LL_SCA_ENUM 3
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 150
|
||||
#define BLE_LL_SCA_ENUM 2
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 250
|
||||
#define BLE_LL_SCA_ENUM 1
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 500
|
||||
#define BLE_LL_SCA_ENUM 0
|
||||
#else
|
||||
#error Invalid SCA value
|
||||
#endif
|
||||
|
||||
/* Packet queue header definition */
|
||||
STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr);
|
||||
|
||||
@@ -373,6 +396,12 @@ struct ble_dev_addr
|
||||
#define BLE_LL_LLID_DATA_START (2)
|
||||
#define BLE_LL_LLID_CTRL (3)
|
||||
|
||||
#define BLE_LL_LLID_IS_CTRL(hdr) \
|
||||
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL)
|
||||
#define BLE_LL_LLID_IS_DATA(hdr) \
|
||||
((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \
|
||||
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG))
|
||||
|
||||
/*
|
||||
* CONNECT_REQ
|
||||
* -> InitA (6 bytes)
|
||||
@@ -545,6 +574,7 @@ void ble_ll_rand_sample(uint8_t rnum);
|
||||
int ble_ll_rand_data_get(uint8_t *buf, uint8_t len);
|
||||
void ble_ll_rand_prand_get(uint8_t *prand);
|
||||
int ble_ll_rand_start(void);
|
||||
uint32_t ble_ll_rand(void);
|
||||
|
||||
static inline int
|
||||
ble_ll_get_addr_type(uint8_t txrxflag)
|
||||
|
||||
@@ -58,6 +58,8 @@ extern "C" {
|
||||
/* Definition for RSSI when the RSSI is unknown */
|
||||
#define BLE_LL_CONN_UNKNOWN_RSSI (127)
|
||||
|
||||
#define BLE_LL_CONN_HANDLE_ISO_OFFSET (0x0100)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* Encryption states for a connection
|
||||
@@ -69,6 +71,7 @@ extern "C" {
|
||||
enum conn_enc_state {
|
||||
CONN_ENC_S_UNENCRYPTED = 1,
|
||||
CONN_ENC_S_ENCRYPTED,
|
||||
CONN_ENC_S_ENC_RSP_TO_BE_SENT,
|
||||
CONN_ENC_S_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_PAUSE_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_PAUSED,
|
||||
@@ -270,6 +273,10 @@ struct ble_ll_conn_sm
|
||||
uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we
|
||||
only use the MD bit now */
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
uint16_t cth_flow_pending;
|
||||
#endif
|
||||
|
||||
/* connection event mgmt */
|
||||
uint8_t reject_reason;
|
||||
uint8_t host_reply_opcode;
|
||||
|
||||
@@ -39,7 +39,9 @@ extern "C" {
|
||||
#define BLE_LL_CTRL_PROC_LE_PING (7)
|
||||
#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8)
|
||||
#define BLE_LL_CTRL_PROC_PHY_UPDATE (9)
|
||||
#define BLE_LL_CTRL_PROC_NUM (10)
|
||||
#define BLE_LL_CTRL_PROC_SCA_UPDATE (10)
|
||||
#define BLE_LL_CTRL_PROC_CIS_CREATE (11)
|
||||
#define BLE_LL_CTRL_PROC_NUM (12)
|
||||
#define BLE_LL_CTRL_PROC_IDLE (255)
|
||||
|
||||
/* Checks if a particular control procedure is running */
|
||||
@@ -54,45 +56,51 @@ extern "C" {
|
||||
* -> Opcode (1 byte)
|
||||
* -> Data (0 - 26 bytes)
|
||||
*/
|
||||
#define BLE_LL_CTRL_CONN_UPDATE_IND (0)
|
||||
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1)
|
||||
#define BLE_LL_CTRL_TERMINATE_IND (2)
|
||||
#define BLE_LL_CTRL_ENC_REQ (3)
|
||||
#define BLE_LL_CTRL_ENC_RSP (4)
|
||||
#define BLE_LL_CTRL_START_ENC_REQ (5)
|
||||
#define BLE_LL_CTRL_START_ENC_RSP (6)
|
||||
#define BLE_LL_CTRL_UNKNOWN_RSP (7)
|
||||
#define BLE_LL_CTRL_FEATURE_REQ (8)
|
||||
#define BLE_LL_CTRL_FEATURE_RSP (9)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_REQ (10)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_RSP (11)
|
||||
#define BLE_LL_CTRL_VERSION_IND (12)
|
||||
#define BLE_LL_CTRL_REJECT_IND (13)
|
||||
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14)
|
||||
#define BLE_LL_CTRL_CONN_PARM_REQ (15)
|
||||
#define BLE_LL_CTRL_CONN_PARM_RSP (16)
|
||||
#define BLE_LL_CTRL_REJECT_IND_EXT (17)
|
||||
#define BLE_LL_CTRL_PING_REQ (18)
|
||||
#define BLE_LL_CTRL_PING_RSP (19)
|
||||
#define BLE_LL_CTRL_LENGTH_REQ (20)
|
||||
#define BLE_LL_CTRL_LENGTH_RSP (21)
|
||||
#define BLE_LL_CTRL_PHY_REQ (22)
|
||||
#define BLE_LL_CTRL_PHY_RSP (23)
|
||||
#define BLE_LL_CTRL_PHY_UPDATE_IND (24)
|
||||
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25)
|
||||
#define BLE_LL_CTRL_CTE_REQ (26)
|
||||
#define BLE_LL_CTRL_CTE_RSP (27)
|
||||
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30)
|
||||
#define BLE_LL_CTRL_CONN_UPDATE_IND (0x00)
|
||||
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (0x01)
|
||||
#define BLE_LL_CTRL_TERMINATE_IND (0x02)
|
||||
#define BLE_LL_CTRL_ENC_REQ (0x03)
|
||||
#define BLE_LL_CTRL_ENC_RSP (0x04)
|
||||
#define BLE_LL_CTRL_START_ENC_REQ (0x05)
|
||||
#define BLE_LL_CTRL_START_ENC_RSP (0x06)
|
||||
#define BLE_LL_CTRL_UNKNOWN_RSP (0x07)
|
||||
#define BLE_LL_CTRL_FEATURE_REQ (0x08)
|
||||
#define BLE_LL_CTRL_FEATURE_RSP (0x09)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_REQ (0x0A)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_RSP (0x0B)
|
||||
#define BLE_LL_CTRL_VERSION_IND (0x0C)
|
||||
#define BLE_LL_CTRL_REJECT_IND (0x0D)
|
||||
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (0x0E)
|
||||
#define BLE_LL_CTRL_CONN_PARM_REQ (0x0F)
|
||||
#define BLE_LL_CTRL_CONN_PARM_RSP (0x10)
|
||||
#define BLE_LL_CTRL_REJECT_IND_EXT (0x11)
|
||||
#define BLE_LL_CTRL_PING_REQ (0x12)
|
||||
#define BLE_LL_CTRL_PING_RSP (0x13)
|
||||
#define BLE_LL_CTRL_LENGTH_REQ (0x14)
|
||||
#define BLE_LL_CTRL_LENGTH_RSP (0x15)
|
||||
#define BLE_LL_CTRL_PHY_REQ (0x16)
|
||||
#define BLE_LL_CTRL_PHY_RSP (0x17)
|
||||
#define BLE_LL_CTRL_PHY_UPDATE_IND (0x18)
|
||||
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (0x19)
|
||||
#define BLE_LL_CTRL_CTE_REQ (0x1A)
|
||||
#define BLE_LL_CTRL_CTE_RSP (0x1B)
|
||||
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (0x1C)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (0x1D)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (0x1E)
|
||||
#define BLE_LL_CTRL_CIS_REQ (0x1F)
|
||||
#define BLE_LL_CTRL_CIS_RSP (0x20)
|
||||
#define BLE_LL_CTRL_CIS_IND (0x21)
|
||||
#define BLE_LL_CTRL_CIS_TERMINATE_IND (0x22)
|
||||
|
||||
/* Maximum opcode value */
|
||||
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1)
|
||||
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CIS_TERMINATE_IND + 1)
|
||||
|
||||
extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES];
|
||||
|
||||
/* Maximum LL control PDU size */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#if MYNEWT_VAL(BLE_ISO)
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (42)
|
||||
#elif MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (35)
|
||||
#else
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (27)
|
||||
@@ -261,6 +269,12 @@ struct ble_ll_len_req
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1)
|
||||
|
||||
/* BLE ISO */
|
||||
#define BLE_LL_CTRL_CIS_REQ_LEN (42)
|
||||
#define BLE_LL_CTRL_CIS_RSP_LEN (8)
|
||||
#define BLE_LL_CTRL_CIS_IND_LEN (15)
|
||||
#define BLE_LL_CTRL_CIS_TERMINATE_LEN (3)
|
||||
|
||||
/* API */
|
||||
struct ble_ll_conn_sm;
|
||||
void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
|
||||
@@ -306,6 +320,11 @@ void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line);
|
||||
uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask);
|
||||
uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
void ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t status, uint8_t peer_sca);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@ extern "C" {
|
||||
#include "nimble/hci_common.h"
|
||||
|
||||
/* For supported commands */
|
||||
#define BLE_LL_SUPP_CMD_LEN (42)
|
||||
#define BLE_LL_SUPP_CMD_LEN (45)
|
||||
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
|
||||
|
||||
/* The largest event the controller will send. */
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_ISO
|
||||
#define H_BLE_LL_ISO
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
|
||||
int ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -225,6 +225,8 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options)
|
||||
if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) {
|
||||
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
|
||||
}
|
||||
#else
|
||||
(void)phy_options;
|
||||
#endif
|
||||
|
||||
return phy_mode;
|
||||
|
||||
@@ -247,9 +247,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
|
||||
/** Our random address */
|
||||
uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
|
||||
|
||||
/** Our supported features which can be controller by the host */
|
||||
uint64_t g_ble_ll_supported_host_features = 0;
|
||||
|
||||
static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] =
|
||||
{
|
||||
[BLE_PHY_MODE_1M] =
|
||||
@@ -1206,8 +1203,6 @@ ble_ll_task(void *arg)
|
||||
/* Tell the host that we are ready to receive packets */
|
||||
ble_ll_hci_send_noop();
|
||||
|
||||
ble_ll_rand_start();
|
||||
|
||||
while (1) {
|
||||
ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER);
|
||||
assert(ev);
|
||||
@@ -1305,10 +1300,6 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len)
|
||||
|
||||
mask = (uint64_t)1 << (cmd->bit_num);
|
||||
if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (!(mask & g_ble_ll_supported_host_features)) {
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@@ -1372,6 +1363,20 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
|
||||
ble_hdr->txinfo.hdr_byte = hdr;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_validate_task(void)
|
||||
{
|
||||
#ifdef MYNEWT
|
||||
#ifndef NDEBUG
|
||||
struct os_task_info oti;
|
||||
|
||||
os_task_info_get(&g_ble_ll_task, &oti);
|
||||
|
||||
BLE_LL_ASSERT(oti.oti_stkusage < oti.oti_stksize);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to reset the controller. This performs a "software reset" of the link
|
||||
* layer; it does not perform a HW reset of the controller nor does it reset
|
||||
@@ -1388,6 +1393,9 @@ ble_ll_reset(void)
|
||||
int rc;
|
||||
os_sr_t sr;
|
||||
|
||||
/* do sanity check on LL task stack */
|
||||
ble_ll_validate_task();
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
ble_phy_disable();
|
||||
ble_ll_sched_stop();
|
||||
@@ -1447,23 +1455,6 @@ ble_ll_reset(void)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_seed_prng(void)
|
||||
{
|
||||
uint32_t seed;
|
||||
int i;
|
||||
|
||||
/* Seed random number generator with least significant bytes of device
|
||||
* address.
|
||||
*/
|
||||
seed = 0;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
seed |= g_dev_addr[i];
|
||||
seed <<= 8;
|
||||
}
|
||||
srand(seed);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode)
|
||||
{
|
||||
@@ -1678,16 +1669,24 @@ ble_ll_init(void)
|
||||
features |= BLE_LL_FEAT_SYNC_TRANS_SEND;
|
||||
#endif
|
||||
|
||||
/* Initialize random number generation */
|
||||
ble_ll_rand_init();
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
features |= BLE_LL_FEAT_SCA_UPDATE;
|
||||
#endif
|
||||
|
||||
/* XXX: This really doesn't belong here, as the address probably has not
|
||||
* been set yet.
|
||||
*/
|
||||
ble_ll_seed_prng();
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
features |= BLE_LL_FEAT_CIS_MASTER;
|
||||
features |= BLE_LL_FEAT_CIS_SLAVE;
|
||||
features |= BLE_LL_FEAT_ISO_BROADCASTER;
|
||||
features |= BLE_LL_FEAT_ISO_HOST_SUPPORT;
|
||||
#endif
|
||||
|
||||
lldata->ll_supp_features = features;
|
||||
|
||||
/* Initialize random number generation */
|
||||
ble_ll_rand_init();
|
||||
/* Start the random number generator */
|
||||
ble_ll_rand_start();
|
||||
|
||||
rc = stats_init_and_reg(STATS_HDR(ble_ll_stats),
|
||||
STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32),
|
||||
STATS_NAME_INIT_PARMS(ble_ll_stats),
|
||||
|
||||
@@ -131,6 +131,7 @@ struct ble_ll_adv_sm
|
||||
uint8_t aux_index : 1;
|
||||
uint8_t aux_first_pdu : 1;
|
||||
uint8_t aux_not_scanned : 1;
|
||||
uint8_t aux_dropped : 1;
|
||||
struct ble_mbuf_hdr *rx_ble_hdr;
|
||||
struct os_mbuf **aux_data;
|
||||
struct ble_ll_adv_aux aux[2];
|
||||
@@ -685,7 +686,7 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm,
|
||||
dptr[8] = advsm->periodic_chanmap[4] & 0x1f;
|
||||
|
||||
/* SCA (3 bits) */
|
||||
dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
|
||||
dptr[8] |= BLE_LL_SCA_ENUM << 5;
|
||||
|
||||
/* AA (4 bytes) */
|
||||
put_le32(&dptr[9], advsm->periodic_access_addr);
|
||||
@@ -1269,7 +1270,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
|
||||
rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
|
||||
if (rc) {
|
||||
STATS_INC(ble_ll_stats, adv_late_starts);
|
||||
goto adv_tx_done;
|
||||
goto adv_aux_dropped;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
@@ -1304,7 +1305,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
|
||||
/* Transmit advertisement */
|
||||
rc = ble_phy_tx(pducb, advsm, end_trans);
|
||||
if (rc) {
|
||||
goto adv_tx_done;
|
||||
goto adv_aux_dropped;
|
||||
}
|
||||
|
||||
/* Enable/disable whitelisting based on filter policy */
|
||||
@@ -1322,7 +1323,8 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
|
||||
|
||||
return BLE_LL_SCHED_STATE_RUNNING;
|
||||
|
||||
adv_tx_done:
|
||||
adv_aux_dropped:
|
||||
advsm->aux_dropped = 1;
|
||||
ble_ll_adv_tx_done(advsm);
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
}
|
||||
@@ -1377,7 +1379,7 @@ ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm,
|
||||
g_ble_ll_conn_params.num_used_chans,
|
||||
g_ble_ll_conn_params.master_chan_map);
|
||||
#else
|
||||
aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS,
|
||||
aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS,
|
||||
g_ble_ll_conn_params.master_chan_map);
|
||||
#endif
|
||||
|
||||
@@ -1554,6 +1556,7 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm)
|
||||
advsm->aux_index = 0;
|
||||
advsm->aux_first_pdu = 1;
|
||||
advsm->aux_not_scanned = 0;
|
||||
advsm->aux_dropped = 0;
|
||||
|
||||
aux = AUX_CURRENT(advsm);
|
||||
ble_ll_adv_aux_calculate(advsm, aux, 0);
|
||||
@@ -1853,7 +1856,7 @@ ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm)
|
||||
* the previously used value.
|
||||
*/
|
||||
do {
|
||||
advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
|
||||
advsm->adi = (advsm->adi & 0xf000) | (ble_ll_rand() & 0x0fff);
|
||||
} while (old_adi == advsm->adi);
|
||||
}
|
||||
#endif
|
||||
@@ -2544,11 +2547,11 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
|
||||
advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans;
|
||||
advsm->periodic_event_cntr = 0;
|
||||
/* for chaining we start with random counter as we share access addr */
|
||||
advsm->periodic_chain_event_cntr = rand();
|
||||
advsm->periodic_chain_event_cntr = ble_ll_rand();
|
||||
advsm->periodic_access_addr = ble_ll_utils_calc_access_addr();
|
||||
advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^
|
||||
(advsm->periodic_access_addr & 0x0000ffff);
|
||||
advsm->periodic_crcinit = rand() & 0xffffff;
|
||||
advsm->periodic_crcinit = ble_ll_rand() & 0xffffff;
|
||||
|
||||
usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL;
|
||||
ticks = os_cputime_usecs_to_ticks(usecs);
|
||||
@@ -2737,7 +2740,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
|
||||
*/
|
||||
earliest_start_time = ble_ll_rfmgmt_enable_now();
|
||||
|
||||
start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
|
||||
start_delay_us = ble_ll_rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
|
||||
advsm->adv_pdu_start_time = os_cputime_get32() +
|
||||
os_cputime_usecs_to_ticks(start_delay_us);
|
||||
|
||||
@@ -4019,8 +4022,8 @@ ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm,
|
||||
|
||||
/* SID, AType, SCA */
|
||||
sync_ind[24] = (advsm->adi >> 12);
|
||||
sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ;
|
||||
sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
|
||||
sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4;
|
||||
sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
|
||||
|
||||
/* PHY */
|
||||
sync_ind[25] = (0x01 << (advsm->sec_phy - 1));
|
||||
@@ -4836,6 +4839,11 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
|
||||
/* We don't need RF anymore */
|
||||
ble_ll_rfmgmt_release();
|
||||
|
||||
if (advsm->aux_dropped) {
|
||||
ble_ll_adv_drop_event(advsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (advsm->aux_not_scanned) {
|
||||
ble_ll_sched_rmv_elem(&aux_next->sch);
|
||||
}
|
||||
|
||||
@@ -225,6 +225,166 @@ STATS_NAME_END(ble_ll_conn_stats)
|
||||
|
||||
static void ble_ll_conn_event_end(struct ble_npl_event *ev);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
struct ble_ll_conn_cth_flow {
|
||||
bool enabled;
|
||||
uint16_t max_buffers;
|
||||
uint16_t num_buffers;
|
||||
};
|
||||
|
||||
static struct ble_ll_conn_cth_flow g_ble_ll_conn_cth_flow;
|
||||
|
||||
static struct ble_npl_event g_ble_ll_conn_cth_flow_error_ev;
|
||||
|
||||
static bool
|
||||
ble_ll_conn_cth_flow_is_enabled(void)
|
||||
{
|
||||
return g_ble_ll_conn_cth_flow.enabled;
|
||||
}
|
||||
|
||||
static bool
|
||||
ble_ll_conn_cth_flow_alloc_credit(struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
if (!cth->num_buffers) {
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
return false;
|
||||
}
|
||||
|
||||
connsm->cth_flow_pending++;
|
||||
cth->num_buffers--;
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_conn_cth_flow_free_credit(struct ble_ll_conn_sm *connsm, uint16_t credits)
|
||||
{
|
||||
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
/*
|
||||
* It's not quite clear what we should do if host gives back more credits
|
||||
* that we have allocated. For now let's just set invalid values back to
|
||||
* sane values and continue.
|
||||
*/
|
||||
|
||||
cth->num_buffers += credits;
|
||||
if (cth->num_buffers > cth->max_buffers) {
|
||||
cth->num_buffers = cth->max_buffers;
|
||||
}
|
||||
|
||||
if (connsm->cth_flow_pending < credits) {
|
||||
connsm->cth_flow_pending = 0;
|
||||
} else {
|
||||
connsm->cth_flow_pending -= credits;
|
||||
}
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_conn_cth_flow_error_fn(struct ble_npl_event *ev)
|
||||
{
|
||||
struct ble_hci_ev *hci_ev;
|
||||
struct ble_hci_ev_command_complete *hci_ev_cp;
|
||||
uint16_t opcode;
|
||||
|
||||
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (!hci_ev) {
|
||||
/* Not much we can do anyway... */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are here in case length of HCI_Host_Number_Of_Completed_Packets was
|
||||
* invalid. We will send an error back to host and we can only hope host is
|
||||
* reasonable and will do some actions to recover, e.g. it should disconnect
|
||||
* all connections to guarantee that all credits are back in pool and we're
|
||||
* back in sync (although spec does not really say what should happen).
|
||||
*/
|
||||
|
||||
opcode = BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
|
||||
BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS);
|
||||
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE;
|
||||
hci_ev->length = sizeof(*hci_ev_cp);
|
||||
|
||||
hci_ev_cp = (void *)hci_ev->data;
|
||||
hci_ev_cp->num_packets = BLE_LL_CFG_NUM_HCI_CMD_PKTS;
|
||||
hci_ev_cp->opcode = htole16(opcode);
|
||||
hci_ev_cp->status = BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers)
|
||||
{
|
||||
BLE_LL_ASSERT(num_buffers);
|
||||
|
||||
g_ble_ll_conn_cth_flow.max_buffers = num_buffers;
|
||||
g_ble_ll_conn_cth_flow.num_buffers = num_buffers;
|
||||
}
|
||||
|
||||
bool
|
||||
ble_ll_conn_cth_flow_enable(bool enabled)
|
||||
{
|
||||
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
|
||||
|
||||
if (cth->enabled == enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cth->enabled = enabled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf)
|
||||
{
|
||||
const struct ble_hci_cmd *cmd;
|
||||
const struct ble_hci_cb_host_num_comp_pkts_cp *cp;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
int i;
|
||||
|
||||
cmd = (const void *)cmdbuf;
|
||||
cp = (const void *)cmd->data;
|
||||
|
||||
if (cmd->length != sizeof(cp->handles) + cp->handles * sizeof(cp->h[0])) {
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_conn_cth_flow_error_ev);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < cp->handles; i++) {
|
||||
/*
|
||||
* It's probably ok that we do not have active connection with given
|
||||
* handle - this can happen if disconnection already happened in LL but
|
||||
* host sent credits back before processing disconnection event. In such
|
||||
* case we can simply ignore command for that connection since credits
|
||||
* are returned by LL already.
|
||||
*/
|
||||
connsm = ble_ll_conn_find_active_conn(cp->h[i].handle);
|
||||
if (connsm) {
|
||||
ble_ll_conn_cth_flow_free_credit(connsm, cp->h[i].count);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
/**
|
||||
* Checks to see if we should start a PHY update procedure
|
||||
@@ -332,7 +492,7 @@ ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2)
|
||||
int rc;
|
||||
|
||||
/* Set time that we last serviced the schedule */
|
||||
if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) {
|
||||
if (CPUTIME_LT(s1->last_scheduled, s2->last_scheduled)) {
|
||||
rc = 1;
|
||||
} else {
|
||||
rc = 0;
|
||||
@@ -855,8 +1015,14 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
|
||||
/*
|
||||
* If we are encrypting, we are only allowed to send certain
|
||||
* kinds of LL control PDU's. If none is enqueued, send empty pdu!
|
||||
*
|
||||
* In Slave role, we are allowed to send unencrypted packets until
|
||||
* LL_ENC_RSP is sent.
|
||||
*/
|
||||
if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) {
|
||||
if (((connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) &&
|
||||
CONN_IS_MASTER(connsm)) ||
|
||||
((connsm->enc_data.enc_state > CONN_ENC_S_ENC_RSP_TO_BE_SENT) &&
|
||||
CONN_IS_SLAVE(connsm))) {
|
||||
if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) {
|
||||
CONN_F_EMPTY_PDU_TXD(connsm) = 1;
|
||||
goto conn_tx_pdu;
|
||||
@@ -991,10 +1157,10 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
|
||||
}
|
||||
|
||||
ticks = os_cputime_usecs_to_ticks(ticks);
|
||||
if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) {
|
||||
if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) {
|
||||
md = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we send an empty PDU we need to initialize the header */
|
||||
conn_tx_pdu:
|
||||
@@ -1450,10 +1616,10 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
|
||||
*/
|
||||
connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1;
|
||||
connsm->tx_win_off = 0;
|
||||
connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA);
|
||||
connsm->master_sca = BLE_LL_SCA_ENUM;
|
||||
|
||||
/* Hop increment is a random value between 5 and 16. */
|
||||
connsm->hop_inc = (rand() % 12) + 5;
|
||||
connsm->hop_inc = (ble_ll_rand() % 12) + 5;
|
||||
|
||||
/* Set channel map to map requested by host */
|
||||
connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans;
|
||||
@@ -1462,7 +1628,7 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
|
||||
|
||||
/* Calculate random access address and crc initialization value */
|
||||
connsm->access_addr = ble_ll_utils_calc_access_addr();
|
||||
connsm->crcinit = rand() & 0xffffff;
|
||||
connsm->crcinit = ble_ll_rand() & 0xffffff;
|
||||
|
||||
/* Set initial schedule callback */
|
||||
connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
|
||||
@@ -1861,6 +2027,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
/* Remove from the active connection list */
|
||||
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
ble_ll_conn_cth_flow_free_credit(connsm, connsm->cth_flow_pending);
|
||||
#endif
|
||||
|
||||
/* Free the current transmit pdu if there is one. */
|
||||
if (connsm->cur_tx_pdu) {
|
||||
os_mbuf_free_chain(connsm->cur_tx_pdu);
|
||||
@@ -3239,6 +3409,13 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
|
||||
*/
|
||||
memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
} else if (!ble_ll_is_rpa(adv_addr, adv_addr_type)) {
|
||||
/* undirected with ID address, assure privacy if on RL */
|
||||
rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
|
||||
if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
|
||||
rl->rl_has_peer) {
|
||||
goto init_rx_isr_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3452,129 +3629,142 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
uint16_t acl_hdr;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
if (BLE_MBUF_HDR_CRC_OK(hdr)) {
|
||||
/* XXX: there is a chance that the connection was thrown away and
|
||||
re-used before processing packets here. Fix this. */
|
||||
/* We better have a connection state machine */
|
||||
connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
|
||||
if (connsm) {
|
||||
/* Check state machine */
|
||||
ble_ll_conn_chk_csm_flags(connsm);
|
||||
/* Packets with invalid CRC are not sent to LL */
|
||||
BLE_LL_ASSERT(BLE_MBUF_HDR_CRC_OK(hdr));
|
||||
|
||||
/* Validate rx data pdu */
|
||||
rxbuf = rxpdu->om_data;
|
||||
hdr_byte = rxbuf[0];
|
||||
acl_len = rxbuf[1];
|
||||
llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
|
||||
/* XXX: there is a chance that the connection was thrown away and
|
||||
re-used before processing packets here. Fix this. */
|
||||
/* We better have a connection state machine */
|
||||
connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
|
||||
if (!connsm) {
|
||||
STATS_INC(ble_ll_conn_stats, no_conn_sm);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the LLID and payload length are reasonable.
|
||||
* Empty payload is only allowed for LLID == 01b.
|
||||
* */
|
||||
if ((llid == 0) ||
|
||||
((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_bad_llid);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
/* Check state machine */
|
||||
ble_ll_conn_chk_csm_flags(connsm);
|
||||
|
||||
/* Validate rx data pdu */
|
||||
rxbuf = rxpdu->om_data;
|
||||
hdr_byte = rxbuf[0];
|
||||
acl_len = rxbuf[1];
|
||||
llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
|
||||
|
||||
/*
|
||||
* Check that the LLID and payload length are reasonable.
|
||||
* Empty payload is only allowed for LLID == 01b.
|
||||
* */
|
||||
if ((llid == 0) || ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_bad_llid);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/* Check if PDU is allowed when encryption is started. If not,
|
||||
* terminate connection.
|
||||
*
|
||||
* Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) &&
|
||||
!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
/* Check if PDU is allowed when encryption is started. If not,
|
||||
* terminate connection.
|
||||
*
|
||||
* Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT &&
|
||||
CONN_IS_MASTER(connsm)) ||
|
||||
(connsm->enc_data.enc_state >= CONN_ENC_S_ENC_RSP_TO_BE_SENT &&
|
||||
CONN_IS_SLAVE(connsm))) {
|
||||
if (!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
/*
|
||||
* Reset authenticated payload timeout if valid MIC. NOTE: we dont
|
||||
* check the MIC failure bit as that would have terminated the
|
||||
* connection
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
|
||||
CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
/*
|
||||
* Reset authenticated payload timeout if valid MIC. NOTE: we dont
|
||||
* check the MIC failure bit as that would have terminated the
|
||||
* connection
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
|
||||
CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update RSSI */
|
||||
connsm->conn_rssi = hdr->rxinfo.rssi;
|
||||
/* Update RSSI */
|
||||
connsm->conn_rssi = hdr->rxinfo.rssi;
|
||||
|
||||
/*
|
||||
* If we are a slave, we can only start to use slave latency
|
||||
* once we have received a NESN of 1 from the master
|
||||
*/
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) {
|
||||
connsm->csmflags.cfbit.allow_slave_latency = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard the received PDU if the sequence number is the same
|
||||
* as the last received sequence number
|
||||
*/
|
||||
rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
|
||||
if (rxd_sn != connsm->last_rxd_sn) {
|
||||
/* Update last rxd sn */
|
||||
connsm->last_rxd_sn = rxd_sn;
|
||||
|
||||
/* No need to do anything if empty pdu */
|
||||
if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) {
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* XXX: should we check to see if we are in a state where we
|
||||
* might expect to get an encrypted PDU?
|
||||
*/
|
||||
if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
|
||||
STATS_INC(ble_ll_conn_stats, mic_failures);
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (llid == BLE_LL_LLID_CTRL) {
|
||||
/* Process control frame */
|
||||
STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
|
||||
if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus);
|
||||
}
|
||||
} else {
|
||||
/* Count # of received l2cap frames and byes */
|
||||
STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus);
|
||||
STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len);
|
||||
|
||||
/* NOTE: there should be at least two bytes available */
|
||||
BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
|
||||
os_mbuf_prepend(rxpdu, 2);
|
||||
rxbuf = rxpdu->om_data;
|
||||
|
||||
acl_hdr = (llid << 12) | connsm->conn_handle;
|
||||
put_le16(rxbuf, acl_hdr);
|
||||
put_le16(rxbuf + 2, acl_len);
|
||||
ble_hci_trans_ll_acl_tx(rxpdu);
|
||||
}
|
||||
|
||||
/* NOTE: we dont free the mbuf since we handed it off! */
|
||||
return;
|
||||
} else {
|
||||
STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
|
||||
}
|
||||
} else {
|
||||
STATS_INC(ble_ll_conn_stats, no_conn_sm);
|
||||
/*
|
||||
* If we are a slave, we can only start to use slave latency
|
||||
* once we have received a NESN of 1 from the master
|
||||
*/
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) {
|
||||
connsm->csmflags.cfbit.allow_slave_latency = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard the received PDU if the sequence number is the same
|
||||
* as the last received sequence number
|
||||
*/
|
||||
rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
|
||||
if (rxd_sn == connsm->last_rxd_sn) {
|
||||
STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
/* Update last rxd sn */
|
||||
connsm->last_rxd_sn = rxd_sn;
|
||||
|
||||
/* No need to do anything if empty pdu */
|
||||
if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) {
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* XXX: should we check to see if we are in a state where we
|
||||
* might expect to get an encrypted PDU?
|
||||
*/
|
||||
if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
|
||||
STATS_INC(ble_ll_conn_stats, mic_failures);
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (llid == BLE_LL_LLID_CTRL) {
|
||||
/* Process control frame */
|
||||
STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
|
||||
if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus);
|
||||
}
|
||||
} else {
|
||||
/* Count # of received l2cap frames and byes */
|
||||
STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus);
|
||||
STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len);
|
||||
|
||||
/* NOTE: there should be at least two bytes available */
|
||||
BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
|
||||
os_mbuf_prepend(rxpdu, 2);
|
||||
rxbuf = rxpdu->om_data;
|
||||
|
||||
acl_hdr = (llid << 12) | connsm->conn_handle;
|
||||
put_le16(rxbuf, acl_hdr);
|
||||
put_le16(rxbuf + 2, acl_len);
|
||||
ble_hci_trans_ll_acl_tx(rxpdu);
|
||||
}
|
||||
|
||||
/* NOTE: we dont free the mbuf since we handed it off! */
|
||||
return;
|
||||
|
||||
/* Free buffer */
|
||||
conn_rx_data_pdu_end:
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
/* Need to give credit back if we allocated one for this PDU */
|
||||
if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT) {
|
||||
ble_ll_conn_cth_flow_free_credit(connsm, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
os_mbuf_free_chain(rxpdu);
|
||||
}
|
||||
|
||||
@@ -3595,7 +3785,6 @@ int
|
||||
ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
{
|
||||
int rc;
|
||||
int is_ctrl;
|
||||
uint8_t hdr_byte;
|
||||
uint8_t hdr_sn;
|
||||
uint8_t hdr_nesn;
|
||||
@@ -3609,14 +3798,43 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
uint32_t add_usecs;
|
||||
struct os_mbuf *txpdu;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
struct os_mbuf *rxpdu;
|
||||
struct os_mbuf *rxpdu = NULL;
|
||||
struct ble_mbuf_hdr *txhdr;
|
||||
int rx_phy_mode;
|
||||
bool alloc_rxpdu = true;
|
||||
|
||||
rc = -1;
|
||||
connsm = g_ble_ll_conn_cur_sm;
|
||||
|
||||
/* Retrieve the header and payload length */
|
||||
hdr_byte = rxbuf[0];
|
||||
rx_pyld_len = rxbuf[1];
|
||||
|
||||
/*
|
||||
* No need to alloc rxpdu for packets with invalid CRC, we would throw them
|
||||
* away instantly from LL anyway.
|
||||
*/
|
||||
if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) {
|
||||
alloc_rxpdu = false;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
/*
|
||||
* If flow control is enabled, we need to have credit available for each
|
||||
* non-empty data packet that LL may send to host. If there are no credits
|
||||
* available, we don't need to allocate buffer for this packet so LL will
|
||||
* nak it.
|
||||
*/
|
||||
if (alloc_rxpdu && ble_ll_conn_cth_flow_is_enabled() &&
|
||||
BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) {
|
||||
if (ble_ll_conn_cth_flow_alloc_credit(connsm)) {
|
||||
rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT;
|
||||
} else {
|
||||
alloc_rxpdu = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need to attempt to allocate a buffer here. The reason we do this
|
||||
* now is that we should not ack the packet if we have no receive
|
||||
@@ -3624,14 +3842,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
* acked, but we should not ack the received frame if we cant hand it up.
|
||||
* NOTE: we hand up empty pdu's to the LL task!
|
||||
*/
|
||||
rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
|
||||
if (alloc_rxpdu) {
|
||||
rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* We should have a current connection state machine. If we dont, we just
|
||||
* hand the packet to the higher layer to count it.
|
||||
*/
|
||||
rc = -1;
|
||||
connsm = g_ble_ll_conn_cur_sm;
|
||||
if (!connsm) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn);
|
||||
goto conn_exit;
|
||||
@@ -3693,9 +3911,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
/* Set last received header byte */
|
||||
connsm->last_rxd_hdr_byte = hdr_byte;
|
||||
|
||||
is_ctrl = 0;
|
||||
if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
|
||||
is_ctrl = 1;
|
||||
if (BLE_LL_LLID_IS_CTRL(hdr_byte)) {
|
||||
opcode = rxbuf[2];
|
||||
}
|
||||
|
||||
@@ -3784,7 +4000,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
/* Adjust payload for max TX time and octets */
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
if (is_ctrl &&
|
||||
if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
|
||||
(connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
|
||||
(opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) {
|
||||
connsm->phy_tx_transition =
|
||||
@@ -3803,8 +4019,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
/* If this is a TERMINATE_IND, we have to reply */
|
||||
chk_rx_terminate_ind:
|
||||
/* If we received a terminate IND, we must set some flags */
|
||||
if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND)
|
||||
&& (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
|
||||
if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
|
||||
(opcode == BLE_LL_CTRL_TERMINATE_IND) &&
|
||||
(rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
|
||||
connsm->csmflags.cfbit.terminate_ind_rxd = 1;
|
||||
connsm->rxd_disconnect_reason = rxbuf[3];
|
||||
}
|
||||
@@ -4226,6 +4443,12 @@ ble_ll_conn_module_reset(void)
|
||||
g_ble_ll_conn_sync_transfer_params.mode = 0;
|
||||
g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
g_ble_ll_conn_cth_flow.enabled = false;
|
||||
g_ble_ll_conn_cth_flow.max_buffers = 1;
|
||||
g_ble_ll_conn_cth_flow.num_buffers = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initialize the connection module */
|
||||
@@ -4265,6 +4488,11 @@ ble_ll_conn_module_init(void)
|
||||
"ble_ll_conn");
|
||||
BLE_LL_ASSERT(rc == 0);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
ble_npl_event_init(&g_ble_ll_conn_cth_flow_error_ev,
|
||||
ble_ll_conn_cth_flow_error_fn, NULL);
|
||||
#endif
|
||||
|
||||
/* Call reset to finish reset of initialization */
|
||||
ble_ll_conn_module_reset();
|
||||
}
|
||||
|
||||
@@ -1128,16 +1128,11 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len)
|
||||
ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
|
||||
{
|
||||
int rc;
|
||||
uint16_t handle;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Check for valid parameters */
|
||||
handle = le16toh(cmd->conn_handle);
|
||||
@@ -1565,6 +1560,34 @@ ltk_key_cmd_complete:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
int
|
||||
ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
const struct ble_hci_le_request_peer_sca_cp *params = (const void *)cmdbuf;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = ble_ll_conn_find_active_conn(params->conn_handle);
|
||||
if (!connsm) {
|
||||
return BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SCA_UPDATE >> 24))) {
|
||||
return BLE_ERR_UNSUPP_REM_FEATURE;
|
||||
}
|
||||
|
||||
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE)) {
|
||||
/* Not really specified what we should return */
|
||||
return BLE_ERR_CTLR_BUSY;
|
||||
}
|
||||
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
/**
|
||||
* Read authenticated payload timeout (OGF=3, OCF==0x007B)
|
||||
|
||||
@@ -164,7 +164,7 @@ bool ble_ll_conn_init_pending_aux_conn_rsp(void);
|
||||
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t reason);
|
||||
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
|
||||
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
|
||||
@@ -196,12 +196,23 @@ int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
int ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
|
||||
#else
|
||||
#define ble_ll_conn_auth_pyld_timer_start(x)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
void ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers);
|
||||
bool ble_ll_conn_cth_flow_enable(bool enabled);
|
||||
void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf);
|
||||
#endif
|
||||
|
||||
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
|
||||
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
|
||||
|
||||
|
||||
@@ -112,6 +112,10 @@ const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] =
|
||||
BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN,
|
||||
BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN,
|
||||
BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN,
|
||||
BLE_LL_CTRL_CIS_REQ_LEN,
|
||||
BLE_LL_CTRL_CIS_RSP_LEN,
|
||||
BLE_LL_CTRL_CIS_IND_LEN,
|
||||
BLE_LL_CTRL_CIS_TERMINATE_LEN
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -505,6 +509,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *
|
||||
ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
|
||||
ble_ll_hci_ev_sca_update(connsm, BLE_ERR_UNSUPPORTED, 0);
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_SCA_UPDATE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_NUM;
|
||||
@@ -836,6 +846,20 @@ ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
|
||||
}
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
/**
|
||||
* Create a LL_CLOCK_ACCURACY_REQ or LL_CLOCK_ACCURACY_RSP pdu
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
* @param ctrdata: Pointer to where CtrData starts in pdu
|
||||
*/
|
||||
static void
|
||||
ble_ll_ctrl_sca_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
|
||||
{
|
||||
ctrdata[0] = BLE_LL_SCA_ENUM;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
|
||||
uint8_t *rsp)
|
||||
@@ -1040,11 +1064,70 @@ ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
connsm->sync_transfer_skip,
|
||||
connsm->sync_transfer_sync_timeout);
|
||||
}
|
||||
|
||||
return BLE_ERR_MAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
/**
|
||||
* Called when a BLE_LL_CTRL_CLOCK_ACCURACY_REQ PDU is received
|
||||
*
|
||||
* @param connsm
|
||||
* @param dptr
|
||||
* @param rsp Pointer to CtrData of BLE_LL_CTRL_CLOCK_ACCURACY_RSP.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_sca_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rsp)
|
||||
{
|
||||
ble_ll_ctrl_sca_req_rsp_make(connsm, rsp);
|
||||
return BLE_LL_CTRL_CLOCK_ACCURACY_RSP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a BLE_LL_CTRL_CLOCK_ACCURACY_RSP PDU is received
|
||||
*
|
||||
* @param connsm
|
||||
* @param dptr
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_sca_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
{
|
||||
if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_SCA_UPDATE) {
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
|
||||
ble_ll_hci_ev_sca_update(connsm, BLE_ERR_SUCCESS, dptr[0]);
|
||||
return BLE_ERR_MAX;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_cis_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rspdata)
|
||||
{
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_cis_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rspdata)
|
||||
{
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_cis_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
{
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Create a link layer length request or length response PDU.
|
||||
*
|
||||
@@ -1250,6 +1333,15 @@ ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
static void
|
||||
ble_ll_ctrl_cis_create(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
{
|
||||
/* TODO Implement */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a link layer control "encrypt request" PDU.
|
||||
*
|
||||
@@ -1351,7 +1443,7 @@ ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_TO_BE_SENT;
|
||||
|
||||
/* In case we were already encrypted we need to reset packet counters */
|
||||
connsm->enc_data.rx_pkt_cntr = 0;
|
||||
@@ -1676,6 +1768,12 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
*/
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_PROC_SCA_UPDATE:
|
||||
ble_ll_hci_ev_sca_update(connsm, ble_error, 0);
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2138,6 +2236,18 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
|
||||
opcode = BLE_LL_CTRL_PHY_REQ;
|
||||
ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_PROC_SCA_UPDATE:
|
||||
opcode = BLE_LL_CTRL_CLOCK_ACCURACY_REQ;
|
||||
ble_ll_ctrl_sca_req_rsp_make(connsm, ctrdata);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
case BLE_LL_CTRL_PROC_CIS_CREATE:
|
||||
opcode = BLE_LL_CTRL_CIS_REQ;
|
||||
ble_ll_ctrl_cis_create(connsm, ctrdata);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BLE_LL_ASSERT(0);
|
||||
@@ -2568,6 +2678,26 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
|
||||
rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
|
||||
rsp_opcode = ble_ll_ctrl_rx_sca_req(connsm, dptr, rspdata);
|
||||
break;
|
||||
case BLE_LL_CTRL_CLOCK_ACCURACY_RSP:
|
||||
rsp_opcode = ble_ll_ctrl_rx_sca_rsp(connsm, dptr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
case BLE_LL_CTRL_CIS_REQ:
|
||||
rsp_opcode = ble_ll_ctrl_rx_cis_req(connsm, dptr, rspdata);
|
||||
break;
|
||||
case BLE_LL_CTRL_CIS_RSP:
|
||||
rsp_opcode = ble_ll_ctrl_rx_cis_rsp(connsm, dptr, rspdata);
|
||||
break;
|
||||
case BLE_LL_CTRL_CIS_IND:
|
||||
rsp_opcode = ble_ll_ctrl_rx_cis_ind(connsm, dptr);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
case BLE_LL_CTRL_PERIODIC_SYNC_IND:
|
||||
rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr);
|
||||
@@ -2709,6 +2839,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm)
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT;
|
||||
break;
|
||||
case BLE_LL_CTRL_ENC_RSP:
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
|
||||
connsm->csmflags.cfbit.send_ltk_req = 1;
|
||||
break;
|
||||
case BLE_LL_CTRL_START_ENC_RSP:
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "controller/ble_ll_whitelist.h"
|
||||
#include "controller/ble_ll_resolv.h"
|
||||
#include "controller/ble_ll_sync.h"
|
||||
#include "controller/ble_ll_iso.h"
|
||||
#include "ble_ll_priv.h"
|
||||
#include "ble_ll_conn_priv.h"
|
||||
|
||||
@@ -327,6 +328,31 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
/**
|
||||
* HCI read buffer size v2 command. Returns the ACL and ISO data packet length and
|
||||
* num data packets.
|
||||
*
|
||||
* @param rspbuf Pointer to response buffer
|
||||
* @param rsplen Length of response buffer
|
||||
*
|
||||
* @return int BLE error code
|
||||
*/
|
||||
static int
|
||||
ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
struct ble_hci_le_rd_buf_size_v2_rp *rp = (void *) rspbuf;
|
||||
|
||||
rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size);
|
||||
rp->data_packets = g_ble_ll_data.ll_num_acl_pkts;
|
||||
rp->iso_data_len = 0;
|
||||
rp->iso_data_packets = 0;
|
||||
|
||||
*rsplen = sizeof(*rp);
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
/**
|
||||
* Checks the preferred phy masks for validity and places the preferred masks
|
||||
@@ -618,6 +644,9 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
|
||||
case BLE_HCI_OCF_LE_GEN_DHKEY:
|
||||
case BLE_HCI_OCF_LE_SET_PHY:
|
||||
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC:
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_HCI_OCF_LE_REQ_PEER_SCA:
|
||||
#endif
|
||||
rc = 1;
|
||||
break;
|
||||
default:
|
||||
@@ -1149,10 +1178,77 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC:
|
||||
rc = ble_ll_iso_read_tx_sync(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_SET_CIG_PARAM:
|
||||
rc = ble_ll_iso_set_cig_param(cmdbuf, len, rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_CIS:
|
||||
rc = ble_ll_iso_create_cis(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_REMOVE_CIG:
|
||||
rc = ble_ll_iso_remove_cig(cmdbuf, len, rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ACCEPT_CIS_REQ:
|
||||
rc = ble_ll_iso_accept_cis_req(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_REJECT_CIS_REQ:
|
||||
rc = ble_ll_iso_reject_cis_req(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_BIG:
|
||||
rc = ble_ll_iso_create_big(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_TERMINATE_BIG:
|
||||
rc = ble_ll_iso_terminate_big(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_BIG_CREATE_SYNC:
|
||||
rc = ble_ll_iso_big_create_sync(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC:
|
||||
rc = ble_ll_iso_big_terminate_sync(cmdbuf,len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH:
|
||||
rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH:
|
||||
rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2:
|
||||
rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
|
||||
case BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST:
|
||||
rc = ble_ll_iso_set_cig_param_test(cmdbuf, len, rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_BIG_TEST:
|
||||
rc = ble_ll_iso_create_big_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST:
|
||||
rc = ble_ll_iso_transmit_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_RECEIVE_TEST:
|
||||
rc = ble_ll_iso_receive_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS:
|
||||
rc = ble_ll_iso_read_counters_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_TEST_END:
|
||||
rc = ble_ll_iso_end_test(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_VERSION) >= 52
|
||||
case BLE_HCI_OCF_LE_SET_HOST_FEAT:
|
||||
rc = ble_ll_set_host_feat(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_HCI_OCF_LE_REQ_PEER_SCA:
|
||||
rc = ble_ll_conn_req_peer_sca(cmdbuf, len,
|
||||
rspbuf, rsplen);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
rc = BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
@@ -1174,6 +1270,26 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_lc_disconnect_cp *cmd;
|
||||
|
||||
cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
if (le16toh(cmd->conn_handle) >= BLE_LL_CONN_HANDLE_ISO_OFFSET) {
|
||||
return ble_ll_iso_disconnect_cmd(cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ble_ll_conn_hci_disconnect_cmd(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a link control command sent from the host to the controller. The HCI
|
||||
* command has a 3 byte command header followed by data. The header is:
|
||||
@@ -1194,7 +1310,7 @@ ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf)
|
||||
|
||||
switch (ocf) {
|
||||
case BLE_HCI_OCF_DISCONNECT_CMD:
|
||||
rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len);
|
||||
rc = ble_ll_hci_disconnect(cmdbuf, len);
|
||||
/* Send command status instead of command complete */
|
||||
rc += (BLE_ERR_MAX + 1);
|
||||
break;
|
||||
@@ -1227,6 +1343,64 @@ ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len)
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
static int
|
||||
ble_ll_hci_cb_set_ctrlr_to_host_fc(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_cb_ctlr_to_host_fc_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* We only allow to either disable flow control or enable for ACL only */
|
||||
if (cmd->enable > 1) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (!ble_ll_conn_cth_flow_enable(cmd->enable)) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_hci_cb_host_buf_size(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_cb_host_buf_size_cp *cmd = (const void *) cmdbuf;
|
||||
uint16_t acl_num;
|
||||
uint16_t acl_data_len;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* We do not support SCO so those parameters should be set to 0 */
|
||||
if (cmd->sco_num || cmd->sco_data_len) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Core 5.2 Vol 4 Part E section 7.3.39 states that "Both the Host and the
|
||||
* Controller shall support command and event packets, where the data portion
|
||||
* (excluding header) contained in the packets is 255 octets in size.".
|
||||
* This means we can basically accept any allowed value since LL does not
|
||||
* reassemble incoming data thus will not send more than 255 octets in single
|
||||
* data packet.
|
||||
*/
|
||||
acl_num = le16toh(cmd->acl_num);
|
||||
acl_data_len = le16toh(cmd->acl_data_len);
|
||||
if (acl_data_len < 255) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
ble_ll_conn_cth_flow_set_buffers(acl_num);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
@@ -1259,6 +1433,22 @@ ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
rc = ble_ll_reset();
|
||||
}
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
case BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC:
|
||||
rc = ble_ll_hci_cb_set_ctrlr_to_host_fc(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_CB_HOST_BUF_SIZE:
|
||||
rc = ble_ll_hci_cb_host_buf_size(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS:
|
||||
/*
|
||||
* HCI_Host_Number_Of_Completed_Packets is handled immediately when
|
||||
* received from transport so we should never receive it here.
|
||||
*/
|
||||
BLE_LL_ASSERT(0);
|
||||
rc = BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
break;
|
||||
#endif
|
||||
case BLE_HCI_OCF_CB_SET_EVENT_MASK2:
|
||||
rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len);
|
||||
break;
|
||||
@@ -1454,9 +1644,33 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
|
||||
* BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion.
|
||||
*/
|
||||
int
|
||||
ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
|
||||
ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg)
|
||||
{
|
||||
struct ble_npl_event *ev;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
const struct ble_hci_cmd *cmd;
|
||||
uint16_t opcode;
|
||||
uint16_t ocf;
|
||||
uint16_t ogf;
|
||||
|
||||
cmd = (const void *)cmdbuf;
|
||||
opcode = le16toh(cmd->opcode);
|
||||
ogf = BLE_HCI_OGF(opcode);
|
||||
ocf = BLE_HCI_OCF(opcode);
|
||||
|
||||
/*
|
||||
* HCI_Host_Number_Of_Completed_Packets is processed outside standard flow
|
||||
* thus it can be sent at any time, even if another command is already
|
||||
* pending. This means we should better process it here and send an event to
|
||||
* LL in case of error.
|
||||
*/
|
||||
if ((ogf == BLE_HCI_OGF_CTLR_BASEBAND) &&
|
||||
(ocf == BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS)) {
|
||||
ble_ll_conn_cth_flow_process_cmd(cmdbuf);
|
||||
ble_hci_trans_buf_free(cmdbuf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get an event structure off the queue */
|
||||
ev = &g_ble_ll_hci_cmd_ev;
|
||||
@@ -1465,7 +1679,7 @@ ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
|
||||
}
|
||||
|
||||
/* Fill out the event and post to Link Layer */
|
||||
ble_npl_event_set_arg(ev, cmd);
|
||||
ble_npl_event_set_arg(ev, cmdbuf);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -461,6 +461,37 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
void
|
||||
ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, uint8_t status,
|
||||
uint8_t peer_sca)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_peer_sca_complete *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (!hci_ev) {
|
||||
return;
|
||||
}
|
||||
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP;
|
||||
ev->status = status;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->sca = peer_sca;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line)
|
||||
{
|
||||
|
||||
146
src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c
Normal file
146
src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/hci_common.h"
|
||||
#include "controller/ble_ll_iso.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
|
||||
int
|
||||
ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
/* Nothing to do here for now when HCI is supported */
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
|
||||
int
|
||||
ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -17,6 +17,9 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* for jrand48 */
|
||||
#define _XOPEN_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@@ -120,6 +123,21 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Simple wrapper to allow easy replacement of rand() */
|
||||
uint32_t
|
||||
ble_ll_rand(void)
|
||||
{
|
||||
static unsigned short xsubi[3];
|
||||
static bool init = true;
|
||||
|
||||
if (init) {
|
||||
init = false;
|
||||
ble_ll_rand_data_get((uint8_t *)xsubi, sizeof(xsubi));
|
||||
}
|
||||
|
||||
return (uint32_t) jrand48(xsubi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2
|
||||
*
|
||||
|
||||
@@ -293,7 +293,7 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
|
||||
STATS_INC(ble_ll_stats, scan_req_txf);
|
||||
}
|
||||
|
||||
scansm->backoff_count = rand() & (scansm->upper_limit - 1);
|
||||
scansm->backoff_count = ble_ll_rand() & (scansm->upper_limit - 1);
|
||||
++scansm->backoff_count;
|
||||
BLE_LL_ASSERT(scansm->backoff_count <= 256);
|
||||
}
|
||||
@@ -305,7 +305,7 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
|
||||
ble_npl_time_t now;
|
||||
|
||||
now = ble_npl_time_get();
|
||||
if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) {
|
||||
if (CPUTIME_GEQ(now, scansm->scan_nrpa_timer)) {
|
||||
/* Generate new NRPA */
|
||||
ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
|
||||
scansm->scan_nrpa[5] &= ~0xc0;
|
||||
@@ -617,7 +617,7 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd,
|
||||
static int
|
||||
ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
|
||||
const uint8_t *addr, uint8_t addr_type,
|
||||
uint8_t rssi,
|
||||
int8_t rssi,
|
||||
uint8_t adv_data_len,
|
||||
struct os_mbuf *adv_data,
|
||||
const uint8_t *inita, uint8_t inita_type)
|
||||
@@ -1125,6 +1125,22 @@ ble_ll_scan_sm_stop(int chk_disable)
|
||||
scansm = &g_ble_ll_scan_sm;
|
||||
os_cputime_timer_stop(&scansm->scan_timer);
|
||||
|
||||
/* Only set state if we are currently in a scan window */
|
||||
if (chk_disable) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
lls = ble_ll_state_get();
|
||||
|
||||
if ((lls == BLE_LL_STATE_SCANNING) ||
|
||||
(lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
|
||||
/* Disable phy */
|
||||
ble_phy_disable();
|
||||
|
||||
/* Set LL state to standby */
|
||||
ble_ll_state_set(BLE_LL_STATE_STANDBY);
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
/* Disable scanning state machine */
|
||||
@@ -1149,22 +1165,6 @@ ble_ll_scan_sm_stop(int chk_disable)
|
||||
/* Count # of times stopped */
|
||||
STATS_INC(ble_ll_stats, scan_stops);
|
||||
|
||||
/* Only set state if we are currently in a scan window */
|
||||
if (chk_disable) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
lls = ble_ll_state_get();
|
||||
|
||||
if ((lls == BLE_LL_STATE_SCANNING) ||
|
||||
(lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
|
||||
/* Disable phy */
|
||||
ble_phy_disable();
|
||||
|
||||
/* Set LL state to standby */
|
||||
ble_ll_state_set(BLE_LL_STATE_STANDBY);
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
/* No need for RF anymore */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
ble_ll_rfmgmt_scan_changed(false, 0);
|
||||
@@ -1991,10 +1991,10 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad
|
||||
{
|
||||
struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
|
||||
struct ble_ll_scan_params *scanp = scansm->scanp;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo;
|
||||
struct ble_ll_resolv_entry *rl = NULL;
|
||||
#endif
|
||||
@@ -2227,6 +2227,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
|
||||
*/
|
||||
if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) {
|
||||
rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
rxinfo->rpa_index = aux_data->rpa_index;
|
||||
if (rxinfo->rpa_index >= 0) {
|
||||
rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED;
|
||||
@@ -2234,6 +2235,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
|
||||
if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) {
|
||||
rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED;
|
||||
}
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -3019,7 +3021,8 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om,
|
||||
|
||||
if (!BLE_MBUF_HDR_DEVMATCH(hdr) ||
|
||||
!BLE_MBUF_HDR_CRC_OK(hdr) ||
|
||||
BLE_MBUF_HDR_IGNORED(hdr)) {
|
||||
BLE_MBUF_HDR_IGNORED(hdr) ||
|
||||
!scansm->scan_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3058,10 +3061,6 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
|
||||
bool send_hci_report;
|
||||
int rc;
|
||||
|
||||
if (!scansm->ext_scanning) {
|
||||
goto scan_continue;
|
||||
}
|
||||
|
||||
if (aux_data) {
|
||||
aux_data->flags_ll |= aux_data->flags_isr;
|
||||
}
|
||||
@@ -3077,7 +3076,8 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
|
||||
BLE_MBUF_HDR_IGNORED(hdr) ||
|
||||
BLE_MBUF_HDR_AUX_INVALID(hdr) ||
|
||||
(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) ||
|
||||
(pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) {
|
||||
(pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) ||
|
||||
!scansm->scan_enabled) {
|
||||
if (aux_data) {
|
||||
ble_ll_scan_end_adv_evt(aux_data);
|
||||
ble_ll_scan_aux_data_unref(aux_data);
|
||||
|
||||
@@ -83,14 +83,14 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1,
|
||||
int rc;
|
||||
|
||||
rc = 1;
|
||||
if ((int32_t)(s1->start_time - s2->start_time) < 0) {
|
||||
if (CPUTIME_LT(s1->start_time, s2->start_time)) {
|
||||
/* Make sure this event does not overlap current event */
|
||||
if ((int32_t)(s1->end_time - s2->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(s1->end_time, s2->start_time)) {
|
||||
rc = 0;
|
||||
}
|
||||
} else {
|
||||
/* Check for overlap */
|
||||
if ((int32_t)(s1->start_time - s2->end_time) >= 0) {
|
||||
if (CPUTIME_GEQ(s1->start_time, s2->end_time)) {
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
|
||||
rc = 0;
|
||||
if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) {
|
||||
ce_end_time = ble_ll_conn_get_ce_end_time();
|
||||
if ((int32_t)(ce_end_time - sch->start_time) > 0) {
|
||||
if (CPUTIME_GT(ce_end_time, sch->start_time)) {
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
|
||||
sch->end_time = connsm->ce_end_time;
|
||||
|
||||
/* Better be past current time or we just leave */
|
||||
if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) {
|
||||
if (CPUTIME_LT(sch->start_time, os_cputime_get32())) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
|
||||
end_overlap = entry;
|
||||
}
|
||||
} else {
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
@@ -468,7 +468,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
|
||||
sch->end_time = earliest_end;
|
||||
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
if ((earliest_start - initial_start) <= itvl_t) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
@@ -655,7 +655,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
|
||||
sch->end_time = earliest_end;
|
||||
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
if ((earliest_start - initial_start) <= itvl_t) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
@@ -770,7 +770,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
|
||||
while (1) {
|
||||
next_sch = entry->link.tqe_next;
|
||||
/* Insert if event ends before next starts */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
@@ -1047,7 +1047,7 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb,
|
||||
os_cputime_timer_stop(&g_ble_ll_sched_timer);
|
||||
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
}
|
||||
@@ -1111,7 +1111,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
os_cputime_timer_stop(&g_ble_ll_sched_timer);
|
||||
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
}
|
||||
@@ -1200,7 +1200,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
end_overlap = entry;
|
||||
}
|
||||
} else {
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
before = entry;
|
||||
break;
|
||||
}
|
||||
@@ -1233,7 +1233,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
sch->end_time = sch->start_time + duration;
|
||||
while (1) {
|
||||
next_sch = entry->link.tqe_next;
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rand_ticks = entry->start_time - sch->end_time;
|
||||
before = entry;
|
||||
TAILQ_INSERT_BEFORE(before, sch, link);
|
||||
@@ -1266,7 +1266,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
if (!rc) {
|
||||
sch->enqueued = 1;
|
||||
if (rand_ticks) {
|
||||
sch->start_time += rand() % rand_ticks;
|
||||
sch->start_time += ble_ll_rand() % rand_ticks;
|
||||
}
|
||||
sch->end_time = sch->start_time + duration;
|
||||
*start = sch->start_time;
|
||||
@@ -1580,7 +1580,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode)
|
||||
while (sch) {
|
||||
/* Let's check if there is no scheduled item which want to start within
|
||||
* given usecs.*/
|
||||
if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) {
|
||||
if (CPUTIME_GT(sch->start_time, now + os_cputime_usecs_to_ticks(usec_dur))) {
|
||||
/* We are fine. Have time for scan req */
|
||||
return 0;
|
||||
}
|
||||
@@ -1670,7 +1670,7 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
|
||||
os_cputime_timer_stop(&g_ble_ll_sched_timer);
|
||||
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
sch->enqueued = 1;
|
||||
|
||||
@@ -36,7 +36,22 @@
|
||||
|
||||
/* Octet 10 */
|
||||
#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5)
|
||||
#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6)
|
||||
#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5)
|
||||
#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6)
|
||||
#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_10 \
|
||||
( \
|
||||
BLE_SUPP_CMD_RD_TX_PWR | \
|
||||
BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \
|
||||
BLE_SUPP_CMD_HOST_BUFFER_SIZE | \
|
||||
BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \
|
||||
)
|
||||
|
||||
/* Octet 14 */
|
||||
#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3)
|
||||
@@ -404,10 +419,77 @@
|
||||
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1)
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_41 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \
|
||||
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \
|
||||
BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \
|
||||
BLE_SUPP_CMD_LE_SET_CIG_PARAM \
|
||||
)
|
||||
|
||||
/* Octet 42 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_42 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \
|
||||
BLE_SUPP_CMD_LE_CREATE_CIS | \
|
||||
BLE_SUPP_CMD_LE_REMOVE_CIG | \
|
||||
BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \
|
||||
BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \
|
||||
BLE_SUPP_CMD_LE_CREATE_BIG | \
|
||||
BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \
|
||||
BLE_SUPP_CMD_LE_TERMINATE_BIG \
|
||||
)
|
||||
|
||||
/* Octet 43 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_43 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \
|
||||
)
|
||||
|
||||
/* Octet 44 */
|
||||
#if MYNEWT_VAL(BLE_VERSION) >= 52
|
||||
#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 0)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 0)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_44 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_SET_HOST_FEATURE \
|
||||
)
|
||||
|
||||
/* Defines the array of supported commands */
|
||||
@@ -455,4 +537,7 @@ const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
|
||||
BLE_LL_SUPP_CMD_OCTET_39,
|
||||
BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */
|
||||
BLE_LL_SUPP_CMD_OCTET_41,
|
||||
BLE_LL_SUPP_CMD_OCTET_42,
|
||||
BLE_LL_SUPP_CMD_OCTET_43,
|
||||
BLE_LL_SUPP_CMD_OCTET_44,
|
||||
};
|
||||
|
||||
@@ -2091,10 +2091,10 @@ ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm,
|
||||
if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) {
|
||||
sync_ind[24] |= 1 << 4;
|
||||
} else {
|
||||
sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ;
|
||||
sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4;
|
||||
}
|
||||
|
||||
sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
|
||||
sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
|
||||
|
||||
/* PHY */
|
||||
sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1));
|
||||
|
||||
@@ -50,8 +50,8 @@ ble_ll_utils_calc_access_addr(void)
|
||||
aa = 0;
|
||||
while (1) {
|
||||
/* Get two, 16-bit random numbers */
|
||||
aa_low = rand() & 0xFFFF;
|
||||
aa_high = rand() & 0xFFFF;
|
||||
aa_low = ble_ll_rand() & 0xFFFF;
|
||||
aa_high = ble_ll_rand() & 0xFFFF;
|
||||
|
||||
/* All four bytes cannot be equal */
|
||||
if (aa_low == aa_high) {
|
||||
@@ -292,8 +292,7 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point,
|
||||
time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point);
|
||||
if (time_since_last_anchor > 0) {
|
||||
delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
|
||||
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] +
|
||||
MYNEWT_VAL(BLE_LL_OUR_SCA);
|
||||
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + MYNEWT_VAL(BLE_LL_SCA);
|
||||
window_widening = (total_sca_ppm * delta_msec) / 1000;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,35 +38,10 @@ syscfg.defs:
|
||||
type: 'task_priority'
|
||||
value: 0
|
||||
|
||||
# Sleep clock accuracy (sca). This is the amount of drift in the system
|
||||
# during when the device is sleeping (in parts per million).
|
||||
#
|
||||
# NOTE: 'the' master sca is an enumerated value based on the sca. Rather
|
||||
# than have a piece of code calculate this value, the developer must set
|
||||
# this value based on the value of the SCA using the following table:
|
||||
#
|
||||
# SCA between 251 and 500 ppm (inclusive); master sca = 0
|
||||
# SCA between 151 and 250 ppm (inclusive); master sca = 1
|
||||
# SCA between 101 and 150 ppm (inclusive); master sca = 2
|
||||
# SCA between 76 and 100 ppm (inclusive); master sca = 3
|
||||
# SCA between 51 and 75 ppm (inclusive); master sca = 4
|
||||
# SCA between 31 and 50 ppm (inclusive); master sca = 5
|
||||
# SCA between 21 and 30 ppm (inclusive); master sca = 6
|
||||
# SCA between 0 and 20 ppm (inclusive); master sca = 7
|
||||
#
|
||||
# For example:
|
||||
# if your clock drift is 101 ppm, your master should be set to 2.
|
||||
# if your clock drift is 20, your master sca should be set to 7.
|
||||
#
|
||||
# The values provided below are merely meant to be an example and should
|
||||
# be replaced by values appropriate for your platform.
|
||||
BLE_LL_OUR_SCA:
|
||||
description: 'The system clock accuracy of the device.'
|
||||
value: '60' # in ppm
|
||||
|
||||
BLE_LL_MASTER_SCA:
|
||||
description: 'Enumerated value based on our sca'
|
||||
value: '4'
|
||||
BLE_LL_SCA:
|
||||
description: Sleep clock accuracy of our device (in ppm)
|
||||
value: MYNEWT_VAL(BLE_LL_OUR_SCA)
|
||||
range: 0..500
|
||||
|
||||
BLE_LL_TX_PWR_DBM:
|
||||
description: 'Transmit power level.'
|
||||
@@ -285,6 +260,35 @@ syscfg.defs:
|
||||
Advertising Sync Transfer Feature.
|
||||
value: MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
|
||||
BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL:
|
||||
description: >
|
||||
Enable controller-to-host flow control support. This allows host to
|
||||
limit number of ACL packets sent at once from controller to avoid
|
||||
congestion on HCI transport if feature is also supported by host.
|
||||
value: 0
|
||||
|
||||
BLE_LL_CFG_FEAT_LL_SCA_UPDATE:
|
||||
description: >
|
||||
This option is used to enable/disable support for SCA update procedure
|
||||
value: 0
|
||||
restrictions:
|
||||
- '(BLE_VERSION >= 52) if 1'
|
||||
|
||||
BLE_LL_CFG_FEAT_LL_ISO:
|
||||
description: >
|
||||
This option is used to enable/disable support for LE Isochronous Channels
|
||||
as per Bluetooth v5.2 channels
|
||||
value: MYNEWT_VAL(BLE_ISO)
|
||||
restrictions:
|
||||
- '(BLE_VERSION >= 52) if 1'
|
||||
|
||||
BLE_LL_CFG_FEAT_LL_ISO_TEST:
|
||||
description: >
|
||||
This option is used to enable/disbale test commands for ISO support
|
||||
value: MYNEWT_VAL(BLE_ISO_TEST)
|
||||
restrictions:
|
||||
- 'BLE_LL_CFG_FEAT_LL_ISO if 1'
|
||||
|
||||
BLE_LL_EXT_ADV_AUX_PTR_CNT:
|
||||
description: >
|
||||
This option configure a max number of scheduled outstanding auxiliary
|
||||
@@ -404,6 +408,10 @@ syscfg.defs:
|
||||
description: use BLE_LL_RFMGMT_ENABLE_TIME instead
|
||||
value: 0
|
||||
deprecated: 1
|
||||
BLE_LL_OUR_SCA:
|
||||
description: use BLE_LL_SCA instead
|
||||
value: 60
|
||||
deprecated: 1
|
||||
|
||||
# defunct settings (to be removed eventually)
|
||||
BLE_DEVICE:
|
||||
@@ -418,6 +426,10 @@ syscfg.defs:
|
||||
description: Superseded by BLE_LL_NUM_COMP_PKT_ITVL_MS
|
||||
value: '(2 * OS_TICKS_PER_SEC)'
|
||||
defunct: 1
|
||||
BLE_LL_MASTER_SCA:
|
||||
description: use BLE_LL_SCA instead
|
||||
value: 4
|
||||
defunct: 1
|
||||
|
||||
|
||||
syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV:
|
||||
|
||||
68
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md
Normal file
68
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
## How to run NimBLE controller on Dialog DA1469x
|
||||
|
||||
Dialog DA1469x has separate Cortex-M0+ core inside CMAC hw block which can run
|
||||
NimBLE controller. This means DA1469x can run full NimBLE stack: host is running
|
||||
on M33 core while controller is running on M0+ core. Both communicate using
|
||||
standard HCI H4 protocol exchanged over mailboxes located in shared memory.
|
||||
|
||||
### Basic setup
|
||||
|
||||
In order to run full NimBLE stack on DA1469x you will need two newt targets: one
|
||||
for M33 (e.g. `dialog_da1469x-dk-pro` BSP) and one for M0+ (`dialog_cmac` BSP).
|
||||
|
||||
Once everything is configured properly, you only need to build target for M33.
|
||||
Target configured for M0+ will be build automatically and image is linked with
|
||||
M33 image so everything can be flashed at once just as if there is only single
|
||||
target used.
|
||||
|
||||
Target for M33 should be set and configured as any other BLE application. In
|
||||
order to use NimBLE controller on CMAC, set proper HCI transport via syscfg:
|
||||
|
||||
BLE_HCI_TRANSPORT: dialog_cmac
|
||||
|
||||
This will include proper transport, driver and add M0+ target to build process.
|
||||
|
||||
For M0+, there is sample target provided in `targets/dialog_cmac` and it's used
|
||||
by default unless overrided by syscfg in M33 target:
|
||||
|
||||
CMAC_IMAGE_TARGET_NAME: "@apache-mynewt-nimble/targets/dialog_cmac"
|
||||
|
||||
If you wish to create own target for M0+, make sure your target is set the same
|
||||
way (`app`, `bsp` and `build_profile`) as sample. Also it is recommended to use
|
||||
syscfg settings from sample target in new target.
|
||||
|
||||
### NimBLE configuration
|
||||
|
||||
Since host and controller are running on different cores, they both use separate
|
||||
configuration: host configuration is in M33 target, controller configuration is
|
||||
in M0+ target. There is currently no way to automatically synchronize both, so
|
||||
care needs to be taken when enabling features in either of targets.
|
||||
|
||||
A possible workaround is to use separate `.yml` file with all the NimBLE syscfg
|
||||
values settings and include it in both targets using `$import` directive which
|
||||
is supported by recent versions of `newt` tool.
|
||||
|
||||
### Advanced settings
|
||||
|
||||
(tbd)
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XCVR_TX_SCHED_DELAY_USECS (250)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
33
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml
Normal file
33
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
pkg.name: nimble/drivers/dialog_cmac
|
||||
pkg.description: BLE driver for Dialog CMAC
|
||||
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
pkg.deps:
|
||||
- "@apache-mynewt-nimble/nimble/controller"
|
||||
- "@apache-mynewt-core/crypto/tinycrypt"
|
||||
pkg.apis:
|
||||
- ble_driver
|
||||
pkg.req_apis:
|
||||
- ble_transport
|
||||
340
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c
Normal file
340
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "mcu/mcu.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "controller/ble_hw.h"
|
||||
#include "CMAC.h"
|
||||
#include "cmac_driver/cmac_shared.h"
|
||||
#include "mcu/mcu.h"
|
||||
#include "tinycrypt/aes.h"
|
||||
|
||||
static struct tc_aes_key_sched_struct g_ctx;
|
||||
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
cmac_rand_set_isr_cb(cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
/* Chime the M33 in case we need random numbers generated */
|
||||
cmac_rand_start();
|
||||
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
cmac_rand_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BLE_HW_RESOLV_LIST_SIZE (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
|
||||
|
||||
struct ble_hw_resolv_irk {
|
||||
uint32_t key[4];
|
||||
};
|
||||
|
||||
struct ble_hw_resolv_list {
|
||||
uint8_t count;
|
||||
struct ble_hw_resolv_irk irk[BLE_HW_RESOLV_LIST_SIZE];
|
||||
};
|
||||
|
||||
struct ble_hw_resolv_proc {
|
||||
uint32_t hash;
|
||||
uint8_t f_configured;
|
||||
uint8_t f_active;
|
||||
uint8_t f_match;
|
||||
uint8_t f_done;
|
||||
struct ble_hw_resolv_irk *irk;
|
||||
struct ble_hw_resolv_irk *irk_end;
|
||||
uint32_t crypto_prand_in[4];
|
||||
uint32_t crypto_e_out[4];
|
||||
};
|
||||
|
||||
static struct ble_hw_resolv_list g_ble_hw_resolv_list;
|
||||
static struct ble_hw_resolv_proc g_ble_hw_resolv_proc;
|
||||
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
uint32_t in_addr;
|
||||
uint32_t out_addr;
|
||||
|
||||
/*
|
||||
* The following code bears some explanation. This function is called by
|
||||
* the LL task to encrypt blocks and calculate session keys. Address
|
||||
* resolution also calls this function. Furthermore, during connections,
|
||||
* the M0 crypto accelerator is used but this function is not called when
|
||||
* using it. During the entire connection event, the M0 crypto block cannot
|
||||
* be used as the crypto state (some of it) needs to remain un-changed.
|
||||
* Note that this is also true when address resolution is enabled: the
|
||||
* HW crypto block is set up and cannot be modified.
|
||||
*
|
||||
* Rather than attempt to share the M0 crypto block between the various
|
||||
* controller features which require it, we decided to use software to
|
||||
* perform the encryption task for anything being done at the link-layer
|
||||
* (outside of an ISR). If this function is called inside an ISR, and it
|
||||
* is when resolving addresses, the crypto accelerator is not being used
|
||||
* by a connection event. Thus, we check to see if we are inside of an ISR.
|
||||
* If so, we use the M0 crypto block. If outside of an ISR, we use the M33
|
||||
*/
|
||||
if (!os_arch_in_isr()) {
|
||||
tc_aes128_set_encrypt_key(&g_ctx, ecb->key);
|
||||
tc_aes_encrypt(ecb->cipher_text, ecb->plain_text, &g_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Need to retain state of in/out pointers */
|
||||
in_addr = CMAC->CM_CRYPTO_IN_ADR2_REG;
|
||||
out_addr = CMAC->CM_CRYPTO_OUT_ADR_REG;
|
||||
|
||||
while (CMAC->CM_CRYPTO_STAT_REG & CMAC_CM_CRYPTO_STAT_REG_CM_CRYPTO_BUSY_Msk);
|
||||
|
||||
/* RECB, memory in/out, encryption */
|
||||
CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ECB_ENC_EN_Msk |
|
||||
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
|
||||
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
|
||||
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
|
||||
|
||||
CMAC->CM_CRYPTO_KEY_31_0_REG = get_le32(&ecb->key[0]);
|
||||
CMAC->CM_CRYPTO_KEY_63_32_REG = get_le32(&ecb->key[4]);
|
||||
CMAC->CM_CRYPTO_KEY_95_64_REG = get_le32(&ecb->key[8]);
|
||||
CMAC->CM_CRYPTO_KEY_127_96_REG = get_le32(&ecb->key[12]);
|
||||
CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)ecb->plain_text;
|
||||
CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)ecb->cipher_text;
|
||||
|
||||
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
|
||||
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
|
||||
while (!(CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk));
|
||||
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
|
||||
|
||||
CMAC->CM_CRYPTO_IN_ADR2_REG = in_addr;
|
||||
CMAC->CM_CRYPTO_OUT_ADR_REG = out_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
g_ble_hw_resolv_list.count = 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
struct ble_hw_resolv_irk *e;
|
||||
|
||||
if (g_ble_hw_resolv_list.count == BLE_HW_RESOLV_LIST_SIZE) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
e = &g_ble_hw_resolv_list.irk[g_ble_hw_resolv_list.count];
|
||||
/* Prepare key here so we do not need to do it during resolving */
|
||||
e->key[0] = get_le32(&irk[0]);
|
||||
e->key[1] = get_le32(&irk[4]);
|
||||
e->key[2] = get_le32(&irk[8]);
|
||||
e->key[3] = get_le32(&irk[12]);
|
||||
|
||||
g_ble_hw_resolv_list.count++;
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
struct ble_hw_resolv_irk *e;
|
||||
|
||||
if (index < g_ble_hw_resolv_list.count) {
|
||||
g_ble_hw_resolv_list.count--;
|
||||
|
||||
e = &g_ble_hw_resolv_list.irk[index];
|
||||
memmove(e, e + 1, (g_ble_hw_resolv_list.count - index) * sizeof(e->key));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return BLE_HW_RESOLV_LIST_SIZE;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
return g_ble_hw_resolv_proc.f_match ?
|
||||
g_ble_hw_resolv_proc.irk - g_ble_hw_resolv_list.irk : -1;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hw_resolv_proc_next(void)
|
||||
{
|
||||
void *src = &g_ble_hw_resolv_proc.irk->key;
|
||||
|
||||
if (g_ble_hw_resolv_proc.irk == g_ble_hw_resolv_proc.irk_end) {
|
||||
g_ble_hw_resolv_proc.f_done = 1;
|
||||
g_ble_hw_resolv_proc.f_active = 0;
|
||||
} else {
|
||||
__asm__ volatile (".syntax unified \n"
|
||||
" ldm %[ptr]!, {r1, r2, r3, r4} \n"
|
||||
" ldr %[ptr], =%[reg] \n"
|
||||
" stm %[ptr]!, {r1, r2, r3, r4} \n"
|
||||
: [ptr] "+l" (src)
|
||||
: [reg] "i" (&CMAC->CM_CRYPTO_KEY_31_0_REG)
|
||||
: "r1", "r2", "r3", "r4", "memory");
|
||||
|
||||
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_resolv_proc_enable(void)
|
||||
{
|
||||
assert(!g_ble_hw_resolv_proc.f_active);
|
||||
|
||||
CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_ABORT_Msk;
|
||||
|
||||
CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ECB_ENC_EN_Msk |
|
||||
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
|
||||
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
|
||||
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
|
||||
|
||||
CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)g_ble_hw_resolv_proc.crypto_prand_in;
|
||||
CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)g_ble_hw_resolv_proc.crypto_e_out;
|
||||
|
||||
g_ble_hw_resolv_proc.irk = g_ble_hw_resolv_list.irk;
|
||||
g_ble_hw_resolv_proc.irk_end = g_ble_hw_resolv_list.irk +
|
||||
g_ble_hw_resolv_list.count;
|
||||
g_ble_hw_resolv_proc.f_configured = 1;
|
||||
g_ble_hw_resolv_proc.f_active = 0;
|
||||
|
||||
/*
|
||||
* It would be better to enable IRQ in ble_hw_resolv_proc_start, but this
|
||||
* would introduce a bit of latency when starting resolving procedure and
|
||||
* we need to save every us possible there in order to be able to resolve
|
||||
* RPA on time.
|
||||
*/
|
||||
NVIC_ClearPendingIRQ(CRYPTO_IRQn);
|
||||
NVIC_EnableIRQ(CRYPTO_IRQn);
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_resolv_proc_disable(void)
|
||||
{
|
||||
g_ble_hw_resolv_proc.f_configured = 0;
|
||||
g_ble_hw_resolv_proc.f_active = 0;
|
||||
g_ble_hw_resolv_proc.f_match = 0;
|
||||
g_ble_hw_resolv_proc.f_done = 1;
|
||||
|
||||
NVIC_DisableIRQ(CRYPTO_IRQn);
|
||||
}
|
||||
|
||||
void
|
||||
ble_hw_resolv_proc_start(const uint8_t *addr)
|
||||
{
|
||||
assert(g_ble_hw_resolv_proc.f_configured);
|
||||
|
||||
/* crypto_prand_in is already zeroed so prand is properly padded */
|
||||
g_ble_hw_resolv_proc.crypto_prand_in[3] = get_be24(&addr[3]) << 8;
|
||||
g_ble_hw_resolv_proc.hash = get_be24(&addr[0]);
|
||||
|
||||
g_ble_hw_resolv_proc.f_match = 0;
|
||||
g_ble_hw_resolv_proc.f_done = 0;
|
||||
g_ble_hw_resolv_proc.f_active = 1;
|
||||
|
||||
ble_hw_resolv_proc_next();
|
||||
}
|
||||
|
||||
void
|
||||
CRYPTO_IRQHandler(void)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
|
||||
|
||||
hash = g_ble_hw_resolv_proc.crypto_e_out[3] >> 8;
|
||||
if (g_ble_hw_resolv_proc.hash == hash) {
|
||||
g_ble_hw_resolv_proc.f_active = 0;
|
||||
g_ble_hw_resolv_proc.f_match = 1;
|
||||
g_ble_hw_resolv_proc.f_done = 1;
|
||||
} else {
|
||||
g_ble_hw_resolv_proc.irk++;
|
||||
ble_hw_resolv_proc_next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BLE_HW_PRIV_H_
|
||||
#define _BLE_HW_PRIV_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void ble_hw_resolv_proc_enable(void);
|
||||
void ble_hw_resolv_proc_disable(void);
|
||||
void ble_hw_resolv_proc_start(const uint8_t *addr);
|
||||
|
||||
#endif /* _BLE_HW_PRIV_H_ */
|
||||
1798
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c
Normal file
1798
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
747
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c
Normal file
747
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c
Normal file
@@ -0,0 +1,747 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "mcu/mcu.h"
|
||||
#include "mcu/cmac_timer.h"
|
||||
#include "controller/ble_phy.h"
|
||||
#include "cmac_driver/cmac_shared.h"
|
||||
#include "ble_rf_priv.h"
|
||||
|
||||
#define RF_CALIBRATION_0 (0x01)
|
||||
#define RF_CALIBRATION_1 (0x02)
|
||||
#define RF_CALIBRATION_2 (0x04)
|
||||
|
||||
static const int8_t g_ble_rf_power_lvls[] = {
|
||||
-18, -12, -8, -6, -3, -2, -1, 0, 1, 2, 3, 4, 4, 5, 6
|
||||
};
|
||||
|
||||
struct ble_phy_rf_data {
|
||||
uint8_t tx_power_cfg0;
|
||||
uint8_t tx_power_cfg1;
|
||||
uint8_t tx_power_cfg2;
|
||||
uint8_t tx_power_cfg3;
|
||||
uint32_t cal_res_1;
|
||||
uint32_t cal_res_2;
|
||||
uint32_t trim_val1_tx_1;
|
||||
uint32_t trim_val1_tx_2;
|
||||
uint32_t trim_val2_tx;
|
||||
uint32_t trim_val2_rx;
|
||||
uint8_t calibrate_req;
|
||||
};
|
||||
|
||||
static struct ble_phy_rf_data g_ble_phy_rf_data;
|
||||
|
||||
static inline uint32_t
|
||||
get_reg32(uint32_t addr)
|
||||
{
|
||||
volatile uint32_t *reg = (volatile uint32_t *)addr;
|
||||
|
||||
return *reg;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
get_reg32_bits(uint32_t addr, uint32_t mask)
|
||||
{
|
||||
volatile uint32_t *reg = (volatile uint32_t *)addr;
|
||||
|
||||
return (*reg & mask) >> __builtin_ctz(mask);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_reg8(uint32_t addr, uint8_t val)
|
||||
{
|
||||
volatile uint8_t *reg = (volatile uint8_t *)addr;
|
||||
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_reg16(uint32_t addr, uint16_t val)
|
||||
{
|
||||
volatile uint16_t *reg = (volatile uint16_t *)addr;
|
||||
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_reg32(uint32_t addr, uint32_t val)
|
||||
{
|
||||
volatile uint32_t *reg = (volatile uint32_t *)addr;
|
||||
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_reg32_bits(uint32_t addr, uint32_t mask, uint32_t val)
|
||||
{
|
||||
volatile uint32_t *reg = (volatile uint32_t *)addr;
|
||||
|
||||
*reg = (*reg & (~mask)) | (val << __builtin_ctz(mask));
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_reg32_mask(uint32_t addr, uint32_t mask, uint32_t val)
|
||||
{
|
||||
volatile uint32_t *reg = (volatile uint32_t *)addr;
|
||||
|
||||
*reg = (*reg & (~mask)) | (val & mask);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_reg16_mask(uint32_t addr, uint16_t mask, uint16_t val)
|
||||
{
|
||||
volatile uint16_t *reg = (volatile uint16_t *)addr;
|
||||
|
||||
*reg = (*reg & (~mask)) | (val & mask);
|
||||
}
|
||||
|
||||
static void
|
||||
delay_us(uint32_t delay_us)
|
||||
{
|
||||
while (delay_us--) {
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_apply_trim(volatile uint32_t *tv, unsigned len)
|
||||
{
|
||||
while (len) {
|
||||
*(volatile uint32_t *)tv[0] = tv[1];
|
||||
len -= 2;
|
||||
tv += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_apply_calibration(void)
|
||||
{
|
||||
set_reg32(0x40020094, g_ble_phy_rf_data.cal_res_1);
|
||||
if (g_ble_phy_rf_data.cal_res_2) {
|
||||
set_reg32_bits(0x40022018, 0xff800000, g_ble_phy_rf_data.cal_res_2);
|
||||
set_reg32_bits(0x40022018, 0x00007fc0, g_ble_phy_rf_data.cal_res_2);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_rf_ldo_on(void)
|
||||
{
|
||||
set_reg8(0x40020004, 9);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_rf_ldo_off(void)
|
||||
{
|
||||
set_reg8(0x40020004, 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_rf_rfcu_enable(void)
|
||||
{
|
||||
set_reg32_bits(0x50000010, 0x00000020, 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_rf_rfcu_disable(void)
|
||||
{
|
||||
set_reg32_bits(0x50000010, 0x00000020, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_rfcu_apply_recommended_settings(void)
|
||||
{
|
||||
set_reg16_mask(0x400200a0, 0x0001, 0x0001);
|
||||
set_reg16_mask(0x40021020, 0x03f0, 0x02f5);
|
||||
set_reg32_mask(0x40021018, 0x001fffff, 0x005a5809);
|
||||
set_reg32_mask(0x4002101c, 0x00001e01, 0x0040128c);
|
||||
set_reg32_mask(0x40021004, 0xffffff1f, 0x64442404);
|
||||
set_reg32_mask(0x40021008, 0xfcfcffff, 0x6b676665);
|
||||
set_reg32_mask(0x4002100c, 0x00fcfcfc, 0x9793736f);
|
||||
set_reg32_mask(0x40021010, 0x1f1f1c1f, 0x04072646);
|
||||
set_reg32_mask(0x40020000, 0x001ff000, 0x0f099820);
|
||||
set_reg16_mask(0x40020348, 0x00ff, 0x0855);
|
||||
set_reg16(0x40020350, 0x0234);
|
||||
set_reg16(0x40020354, 0x0a34);
|
||||
set_reg16(0x40020358, 0x0851);
|
||||
set_reg16(0x4002035c, 0x0a26);
|
||||
set_reg16(0x40020360, 0x0858);
|
||||
set_reg16(0x4002102c, 0xdfe7);
|
||||
set_reg32_mask(0x4002103c, 0x00c00000, 0x0024a19f);
|
||||
set_reg16_mask(0x40021000, 0x0008, 0x000b);
|
||||
set_reg16_mask(0x40020238, 0x03e0, 0x02c0);
|
||||
set_reg16_mask(0x4002023c, 0x03e0, 0x02c0);
|
||||
set_reg16_mask(0x40020244, 0x03e0, 0x0250);
|
||||
set_reg16_mask(0x40020248, 0x03e0, 0x02a0);
|
||||
set_reg16_mask(0x4002024c, 0x03e0, 0x02c0);
|
||||
set_reg16_mask(0x40020288, 0x03e0, 0x0300);
|
||||
set_reg16_mask(0x4002029c, 0x001f, 0x0019);
|
||||
set_reg16_mask(0x4002003c, 0x6000, 0x0788);
|
||||
set_reg16_mask(0x40020074, 0x7f00, 0x2007);
|
||||
set_reg32_mask(0x40020080, 0x00333330, 0x00222224);
|
||||
set_reg32_mask(0x40020068, 0x00000f0f, 0x00000f0d);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_rfcu_apply_settings(void)
|
||||
{
|
||||
ble_rf_apply_trim(g_cmac_shared_data.trim.rfcu,
|
||||
g_cmac_shared_data.trim.rfcu_len);
|
||||
ble_rf_rfcu_apply_recommended_settings();
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_rf_synth_enable(void)
|
||||
{
|
||||
set_reg8(0x40020005, 3);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_rf_synth_disable(void)
|
||||
{
|
||||
set_reg8(0x40020005, 0);
|
||||
__NOP();
|
||||
__NOP();
|
||||
}
|
||||
|
||||
static bool
|
||||
ble_rf_synth_is_enabled(void)
|
||||
{
|
||||
return get_reg32_bits(0x40020004, 256);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_synth_apply_recommended_settings(void)
|
||||
{
|
||||
set_reg32_mask(0x40022048, 0x0000000c, 0x000000d5);
|
||||
set_reg32_mask(0x40022050, 0x00000300, 0x00000300);
|
||||
set_reg16_mask(0x40022024, 0x0001, 0x0001);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_synth_apply_settings(void)
|
||||
{
|
||||
ble_rf_apply_trim(g_cmac_shared_data.trim.synth,
|
||||
g_cmac_shared_data.trim.synth_len);
|
||||
ble_rf_synth_apply_recommended_settings();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_calibration_0(void)
|
||||
{
|
||||
uint32_t bkp[10];
|
||||
|
||||
bkp[0] = get_reg32(0x40020208);
|
||||
bkp[1] = get_reg32(0x40020250);
|
||||
bkp[2] = get_reg32(0x40020254);
|
||||
bkp[3] = get_reg32(0x40021028);
|
||||
bkp[4] = get_reg32(0x40020020);
|
||||
bkp[5] = get_reg32(0x40020294);
|
||||
bkp[6] = get_reg32(0x4002103C);
|
||||
bkp[7] = get_reg32(0x400200A8);
|
||||
bkp[8] = get_reg32(0x40020000);
|
||||
bkp[9] = get_reg32(0x40022000);
|
||||
|
||||
set_reg32_bits(0x40020000, 0x00000002, 0);
|
||||
set_reg32_bits(0x40022000, 0x00000001, 0);
|
||||
set_reg32_mask(0x4002103C, 0x00201c00, 0x00001c00);
|
||||
set_reg32_bits(0x400200A8, 0x00000001, 1);
|
||||
set_reg8(0x40020006, 1);
|
||||
set_reg32(0x40020208, 0);
|
||||
set_reg32(0x40020250, 0);
|
||||
set_reg32(0x40020254, 0);
|
||||
set_reg32(0x40021028, 0x00F8A494);
|
||||
set_reg32(0x40020020, 8);
|
||||
set_reg32(0x40020294, 0);
|
||||
set_reg32(0x40020024, 0);
|
||||
|
||||
delay_us(5);
|
||||
if (get_reg32_bits(0x40020020, 0x00000002)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
set_reg32_bits(0x40020020, 0x00000001, 1);
|
||||
delay_us(15);
|
||||
if (!get_reg32_bits(0x40020020, 0x00000001)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
delay_us(300);
|
||||
if (get_reg32_bits(0x40020020, 0x00000001)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
set_reg32(0x40020024, 0);
|
||||
set_reg32(0x40020208, bkp[0]);
|
||||
set_reg32(0x40020250, bkp[1]);
|
||||
set_reg32(0x40020254, bkp[2]);
|
||||
set_reg32(0x40021028, bkp[3]);
|
||||
set_reg32(0x40020020, bkp[4]);
|
||||
set_reg32(0x40020294, bkp[5]);
|
||||
set_reg32(0x4002103C, bkp[6]);
|
||||
set_reg32(0x400200A8, bkp[7]);
|
||||
set_reg32(0x40020000, bkp[8]);
|
||||
set_reg32(0x40022000, bkp[9]);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_calibration_1(void)
|
||||
{
|
||||
uint32_t bkp[12];
|
||||
uint32_t val;
|
||||
|
||||
bkp[0] = get_reg32(0x40020020);
|
||||
bkp[1] = get_reg32(0x40020208);
|
||||
bkp[2] = get_reg32(0x40020250);
|
||||
bkp[3] = get_reg32(0x40020254);
|
||||
bkp[4] = get_reg32(0x40020218);
|
||||
bkp[5] = get_reg32(0x4002021c);
|
||||
bkp[6] = get_reg32(0x40020220);
|
||||
bkp[7] = get_reg32(0x40020270);
|
||||
bkp[8] = get_reg32(0x4002027c);
|
||||
bkp[9] = get_reg32(0x4002101c);
|
||||
bkp[10] = get_reg32(0x40020000);
|
||||
bkp[11] = get_reg32(0x40022000);
|
||||
|
||||
set_reg32(0x4002103c, 0x0124a21f);
|
||||
set_reg32(0x40020208, 0);
|
||||
set_reg32(0x40020250, 0);
|
||||
set_reg32(0x40020254, 0);
|
||||
set_reg32(0x40020218, 0);
|
||||
set_reg32(0x4002021c, 0);
|
||||
set_reg32(0x40020220, 0);
|
||||
set_reg32(0x40020270, 0);
|
||||
set_reg32(0x4002027c, 0);
|
||||
set_reg32(0x40020000, 0x0f168820);
|
||||
set_reg32_bits(0x40022000, 0x00000001, 0);
|
||||
set_reg32_bits(0x4002101c, 0x00001e00, 0);
|
||||
set_reg32_bits(0x4002001c, 0x0000003f, 47);
|
||||
set_reg8(0x40020006, 1);
|
||||
set_reg32(0x40020020, 16);
|
||||
set_reg32_bits(0x4002003c, 0x00000800, 1);
|
||||
set_reg32(0x40020024, 0);
|
||||
|
||||
delay_us(5);
|
||||
if (get_reg32_bits(0x40020020, 0x00000002)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
set_reg32_bits(0x40020020, 0x00000001, 1);
|
||||
delay_us(15);
|
||||
if (!get_reg32_bits(0x40020020, 0x00000001)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
delay_us(300);
|
||||
if (get_reg32_bits(0x40020020, 0x00000001)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
val = get_reg32(0x40020090);
|
||||
set_reg32_bits(0x40020094, 0x0000000f, val);
|
||||
set_reg32_bits(0x40020094, 0x00000f00, val);
|
||||
set_reg32_bits(0x40020094, 0x000f0000, val);
|
||||
set_reg32_bits(0x40020094, 0x0f000000, val);
|
||||
g_ble_phy_rf_data.cal_res_1 = get_reg32(0x40020094);
|
||||
|
||||
done:
|
||||
set_reg32(0x40020024, 0);
|
||||
set_reg32(0x40020020, bkp[0]);
|
||||
set_reg32(0x40020208, bkp[1]);
|
||||
set_reg32(0x40020250, bkp[2]);
|
||||
set_reg32(0x40020254, bkp[3]);
|
||||
set_reg32(0x40020218, bkp[4]);
|
||||
set_reg32(0x4002021c, bkp[5]);
|
||||
set_reg32(0x40020220, bkp[6]);
|
||||
set_reg32(0x40020270, bkp[7]);
|
||||
set_reg32(0x4002027c, bkp[8]);
|
||||
set_reg32(0x4002101c, bkp[9]);
|
||||
set_reg32(0x40020000, bkp[10]);
|
||||
set_reg32(0x40022000, bkp[11]);
|
||||
set_reg32_bits(0x4002003c, 0x00000800, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_calibration_2(void)
|
||||
{
|
||||
uint32_t bkp[2];
|
||||
uint32_t k1;
|
||||
|
||||
set_reg8(0x40020005, 3);
|
||||
set_reg32(0x40022000, 0x00000300);
|
||||
set_reg32_bits(0x40022004, 0x0000007f, 20);
|
||||
bkp[0] = get_reg32(0x40022040);
|
||||
set_reg32(0x40022040, 0xffffffff);
|
||||
set_reg32_bits(0x40022018, 0x0000003f, 0);
|
||||
set_reg32_bits(0x40022018, 0x00008000, 0);
|
||||
set_reg32_bits(0x4002201c, 0x00000600, 2);
|
||||
set_reg32_bits(0x4002201c, 0x00000070, 4);
|
||||
set_reg32_bits(0x40022030, 0x3f000000, 22);
|
||||
set_reg32_bits(0x40022030, 0x00000fc0, 24);
|
||||
set_reg32_bits(0x40022030, 0x0000003f, 24);
|
||||
set_reg8(0x4002201c, 0x43);
|
||||
set_reg8(0x40020006, 2);
|
||||
delay_us(2);
|
||||
bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
|
||||
set_reg32_bits(0x4002024c, 0x000003e0, 0);
|
||||
set_reg8(0x40020006, 1);
|
||||
set_reg32_bits(0x400200ac, 0x00000003, 3);
|
||||
delay_us(30);
|
||||
delay_us(100);
|
||||
set_reg8(0x40020005, 3);
|
||||
k1 = get_reg32_bits(0x40022088, 0x000001ff);
|
||||
set_reg32(0x400200ac, 0);
|
||||
delay_us(20);
|
||||
set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
|
||||
delay_us(10);
|
||||
|
||||
set_reg32_bits(0x40022018, 0xff800000, k1);
|
||||
set_reg32_bits(0x40022018, 0x00007fc0, k1);
|
||||
set_reg8(0x4002201c, 0x41);
|
||||
set_reg32_bits(0x4002201c, 0x00000600, 2);
|
||||
set_reg8(0x40020006, 2);
|
||||
delay_us(2);
|
||||
bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
|
||||
set_reg32_bits(0x4002024c, 0x000003e0, 0);
|
||||
set_reg8(0x40020006, 1);
|
||||
set_reg32_bits(0x400200ac, 0x00000003, 3);
|
||||
delay_us(30);
|
||||
delay_us(100);
|
||||
set_reg8(0x40020005, 3);
|
||||
k1 = get_reg32_bits(0x40022088, 0x1ff);
|
||||
set_reg32(0x400200ac, 0);
|
||||
delay_us(20);
|
||||
set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
|
||||
delay_us(10);
|
||||
|
||||
set_reg32_bits(0x40022018, 0xff800000, k1);
|
||||
set_reg32_bits(0x40022018, 0x00007fc0, k1);
|
||||
set_reg8(0x4002201c, 0x41);
|
||||
set_reg32_bits(0x4002201c, 0x00000600, 2);
|
||||
set_reg8(0x40020006, 2);
|
||||
delay_us(2);
|
||||
bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
|
||||
set_reg32_bits(0x4002024c, 0x000003e0, 0);
|
||||
set_reg8(0x40020006, 1);
|
||||
set_reg32_bits(0x400200ac, 0x00000003, 3);
|
||||
delay_us(30);
|
||||
delay_us(100);
|
||||
set_reg8(0x40020005, 3);
|
||||
k1 = get_reg32_bits(0x40022088, 0x000001ff);
|
||||
set_reg32_bits(0x40022018, 0xff800000, k1);
|
||||
set_reg32_bits(0x40022018, 0x00007fc0, k1);
|
||||
set_reg32_bits(0x4002201c, 0x00000001, 0);
|
||||
set_reg32(0x40022040, bkp[0]);
|
||||
set_reg32_bits(0x40022018, 0x0000003f, 0x1c);
|
||||
set_reg32_bits(0x40022018, 0x00008000, 0);
|
||||
set_reg32_bits(0x40022030, 0x3f000000, 28);
|
||||
set_reg32_bits(0x40022030, 0x00000fc0, 30);
|
||||
set_reg32_bits(0x40022030, 0x0000003f, 30);
|
||||
set_reg32(0x400200ac, 0);
|
||||
delay_us(20);
|
||||
set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
|
||||
delay_us(10);
|
||||
|
||||
g_ble_phy_rf_data.cal_res_2 = k1;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rf_calibrate_int(uint8_t mask)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
ble_rf_enable();
|
||||
delay_us(20);
|
||||
|
||||
ble_rf_synth_disable();
|
||||
ble_rf_synth_enable();
|
||||
ble_rf_synth_apply_settings();
|
||||
set_reg8(0x40020005, 1);
|
||||
|
||||
if (mask & RF_CALIBRATION_0) {
|
||||
ble_rf_calibration_0();
|
||||
}
|
||||
if (mask & RF_CALIBRATION_1) {
|
||||
ble_rf_calibration_1();
|
||||
}
|
||||
if (mask & RF_CALIBRATION_2) {
|
||||
ble_rf_calibration_2();
|
||||
}
|
||||
|
||||
ble_rf_disable();
|
||||
|
||||
__enable_irq();
|
||||
|
||||
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
|
||||
g_cmac_shared_data.debug.cal_res_1 = g_ble_phy_rf_data.cal_res_1;
|
||||
g_cmac_shared_data.debug.cal_res_2 = g_ble_phy_rf_data.cal_res_2;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ble_rf_try_recalibrate(uint32_t idle_time_us)
|
||||
{
|
||||
/* Run recalibration if we have at least 1ms of time to spare and RF is
|
||||
* currently disabled. Calibration is much shorter than 1ms, but that gives
|
||||
* us good margin to make sure we can finish before next event.
|
||||
*/
|
||||
if (!g_ble_phy_rf_data.calibrate_req || (idle_time_us < 1000) ||
|
||||
ble_rf_is_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ble_rf_calibrate_int(RF_CALIBRATION_2);
|
||||
|
||||
g_ble_phy_rf_data.calibrate_req = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ble_rf_find_trim_reg(volatile uint32_t *tv, unsigned len, uint32_t reg)
|
||||
{
|
||||
while (len) {
|
||||
if (tv[0] == reg) {
|
||||
return tv[1];
|
||||
}
|
||||
len -= 2;
|
||||
tv += 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_init(void)
|
||||
{
|
||||
static bool done = false;
|
||||
uint32_t val;
|
||||
|
||||
ble_rf_disable();
|
||||
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode1,
|
||||
g_cmac_shared_data.trim.rfcu_mode1_len,
|
||||
0x4002004c);
|
||||
g_ble_phy_rf_data.trim_val1_tx_1 = val;
|
||||
|
||||
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode2,
|
||||
g_cmac_shared_data.trim.rfcu_mode2_len,
|
||||
0x4002004c);
|
||||
g_ble_phy_rf_data.trim_val1_tx_2 = val;
|
||||
|
||||
if (!g_ble_phy_rf_data.trim_val1_tx_1 || !g_ble_phy_rf_data.trim_val1_tx_2) {
|
||||
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu,
|
||||
g_cmac_shared_data.trim.rfcu_len,
|
||||
0x4002004c);
|
||||
if (!val) {
|
||||
val = 0x0300;
|
||||
}
|
||||
g_ble_phy_rf_data.trim_val1_tx_1 = val;
|
||||
g_ble_phy_rf_data.trim_val1_tx_2 = val;
|
||||
}
|
||||
|
||||
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.synth,
|
||||
g_cmac_shared_data.trim.synth_len,
|
||||
0x40022038);
|
||||
if (!val) {
|
||||
val = 0x0198ff03;
|
||||
}
|
||||
g_ble_phy_rf_data.trim_val2_rx = val;
|
||||
g_ble_phy_rf_data.trim_val2_tx = val;
|
||||
set_reg32_bits((uint32_t)&g_ble_phy_rf_data.trim_val2_tx, 0x0001ff00, 0x87);
|
||||
|
||||
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
|
||||
g_cmac_shared_data.debug.trim_val1_tx_1 = g_ble_phy_rf_data.trim_val1_tx_1;
|
||||
g_cmac_shared_data.debug.trim_val1_tx_2 = g_ble_phy_rf_data.trim_val1_tx_2;
|
||||
g_cmac_shared_data.debug.trim_val2_tx = g_ble_phy_rf_data.trim_val2_tx;
|
||||
g_cmac_shared_data.debug.trim_val2_rx = g_ble_phy_rf_data.trim_val2_rx;
|
||||
#endif
|
||||
|
||||
ble_rf_rfcu_enable();
|
||||
ble_rf_rfcu_apply_settings();
|
||||
g_ble_phy_rf_data.tx_power_cfg1 = get_reg32_bits(0x500000a4, 0xf0);
|
||||
g_ble_phy_rf_data.tx_power_cfg2 = get_reg32_bits(0x40020238, 0x000003e0);
|
||||
g_ble_phy_rf_data.tx_power_cfg3 = 0;
|
||||
ble_rf_rfcu_disable();
|
||||
|
||||
ble_rf_calibrate_int(RF_CALIBRATION_0 | RF_CALIBRATION_1 | RF_CALIBRATION_2);
|
||||
|
||||
done = true;
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_enable(void)
|
||||
{
|
||||
if (ble_rf_is_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ble_rf_rfcu_enable();
|
||||
ble_rf_rfcu_apply_settings();
|
||||
ble_rf_ldo_on();
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_configure(void)
|
||||
{
|
||||
if (ble_rf_synth_is_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ble_rf_synth_enable();
|
||||
ble_rf_synth_apply_settings();
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_stop(void)
|
||||
{
|
||||
ble_rf_synth_disable();
|
||||
set_reg8(0x40020006, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_disable(void)
|
||||
{
|
||||
ble_rf_stop();
|
||||
ble_rf_ldo_off();
|
||||
ble_rf_rfcu_disable();
|
||||
}
|
||||
|
||||
bool
|
||||
ble_rf_is_enabled(void)
|
||||
{
|
||||
return get_reg32_bits(0x40020008, 5) == 5;
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_calibrate_req(void)
|
||||
{
|
||||
g_ble_phy_rf_data.calibrate_req = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_setup_tx(uint8_t rf_chan, uint8_t phy_mode)
|
||||
{
|
||||
set_reg32_bits(0x40020000, 0x0f000000, g_ble_phy_rf_data.tx_power_cfg0);
|
||||
set_reg32_bits(0x500000a4, 0x000000f0, g_ble_phy_rf_data.tx_power_cfg1);
|
||||
set_reg32_bits(0x40020238, 0x000003e0, g_ble_phy_rf_data.tx_power_cfg2);
|
||||
set_reg32_bits(0x40020234, 0x000003e0, g_ble_phy_rf_data.tx_power_cfg3);
|
||||
|
||||
if (g_ble_phy_rf_data.tx_power_cfg0 < 13) {
|
||||
set_reg32(0x4002004c, g_ble_phy_rf_data.trim_val1_tx_1);
|
||||
} else {
|
||||
set_reg32(0x4002004c, g_ble_phy_rf_data.trim_val1_tx_2);
|
||||
}
|
||||
set_reg8(0x40020005, 3);
|
||||
set_reg8(0x40022004, rf_chan);
|
||||
if (phy_mode == BLE_PHY_MODE_2M) {
|
||||
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
|
||||
set_reg32(0x40022000, 0x00000303);
|
||||
#else
|
||||
set_reg32(0x40022000, 0x00000003);
|
||||
#endif
|
||||
} else {
|
||||
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
|
||||
set_reg32(0x40022000, 0x00000300);
|
||||
#else
|
||||
set_reg32(0x40022000, 0x00000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
ble_rf_apply_calibration();
|
||||
|
||||
set_reg32_bits(0x40022050, 0x00000200, 1);
|
||||
set_reg32_bits(0x40022050, 0x00000100, 0);
|
||||
set_reg32_bits(0x40022048, 0x01ffff00, 0x7700);
|
||||
set_reg32(0x40022038, g_ble_phy_rf_data.trim_val2_tx);
|
||||
|
||||
set_reg8(0x40020006, 3);
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_setup_rx(uint8_t rf_chan, uint8_t phy_mode)
|
||||
{
|
||||
set_reg32_bits(0x500000a4, 0x000000f0, g_ble_phy_rf_data.tx_power_cfg1);
|
||||
set_reg8(0x40020005, 3);
|
||||
set_reg8(0x40022004, rf_chan);
|
||||
if (phy_mode == BLE_PHY_MODE_2M) {
|
||||
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
|
||||
set_reg32(0x40022000, 0x00000303);
|
||||
set_reg32(0x40020000, 0x0f11b823);
|
||||
set_reg32(0x4002103c, 0x0125261b);
|
||||
#else
|
||||
set_reg32(0x40022000, 0x00000003);
|
||||
set_reg32(0x40020000, 0x0f0c2803);
|
||||
set_reg32(0x4002103c, 0x0125a61b);
|
||||
#endif
|
||||
set_reg32(0x40021020, 0x000002f5);
|
||||
set_reg32(0x4002102c, 0x0000d1d5);
|
||||
} else {
|
||||
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
|
||||
set_reg32(0x40022000, 0x00000300);
|
||||
set_reg32(0x40020000, 0x0f099820);
|
||||
set_reg32(0x4002103c, 0x0124a21f);
|
||||
#else
|
||||
set_reg32(0x40022000, 0x00000000);
|
||||
set_reg32(0x40020000, 0x0f062800);
|
||||
set_reg32(0x4002103c, 0x01051e1f);
|
||||
#endif
|
||||
set_reg32(0x40021020, 0x000002f5);
|
||||
set_reg32(0x4002102c, 0x0000dfe7);
|
||||
}
|
||||
|
||||
ble_rf_apply_calibration();
|
||||
|
||||
set_reg32_bits(0x40022050, 0x00000200, 1);
|
||||
set_reg32_bits(0x40022050, 0x00000100, 1);
|
||||
set_reg32_bits(0x40022048, 0x01ffff00, 0);
|
||||
set_reg32(0x40022038, g_ble_phy_rf_data.trim_val2_rx);
|
||||
|
||||
set_reg8(0x40020006, 3);
|
||||
}
|
||||
|
||||
void
|
||||
ble_rf_set_tx_power(int dbm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(g_ble_rf_power_lvls); i++) {
|
||||
if (g_ble_rf_power_lvls[i] >= dbm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_ble_phy_rf_data.tx_power_cfg0 = i + 1;
|
||||
}
|
||||
|
||||
int8_t
|
||||
ble_rf_get_rssi(void)
|
||||
{
|
||||
return (501 * get_reg32_bits(0x40021038, 0x000003ff) - 493000) / 4096;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BLE_RF_PRIV_H_
|
||||
#define _BLE_RF_PRIV_H_
|
||||
|
||||
void ble_rf_init(void);
|
||||
void ble_rf_enable(void);
|
||||
void ble_rf_stop(void);
|
||||
void ble_rf_disable(void);
|
||||
bool ble_rf_is_enabled(void);
|
||||
void ble_rf_configure(void);
|
||||
|
||||
void ble_rf_calibrate(void);
|
||||
|
||||
void ble_rf_setup_tx(uint8_t rf_chan, uint8_t mode);
|
||||
void ble_rf_setup_rx(uint8_t rf_chan, uint8_t mode);
|
||||
|
||||
void ble_rf_set_tx_power(int dbm);
|
||||
int8_t ble_rf_get_rssi(void);
|
||||
|
||||
#endif /* _BLE_RF_PRIV_H_ */
|
||||
29
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml
Normal file
29
src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
syscfg.defs:
|
||||
BLE_PHY_RF_HP_MODE:
|
||||
description: Enable high-performance RF mode.
|
||||
value: 1
|
||||
|
||||
BLE_PHY_DEBUG_DSER:
|
||||
description: Enable DSER output from PHY
|
||||
value: 0
|
||||
|
||||
syscfg.restrictions:
|
||||
- BLE_LL_RFMGMT_ENABLE_TIME == 0 || BLE_LL_RFMGMT_ENABLE_TIME >= 20
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
#include "nimble/ble.h"
|
||||
@@ -32,6 +34,9 @@
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
static ble_rng_isr_cb_t rng_cb;
|
||||
static bool rng_started;
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
@@ -143,7 +148,8 @@ ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
return -1;
|
||||
rng_cb = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,7 +160,15 @@ ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
return -1;
|
||||
rng_started = true;
|
||||
|
||||
if (rng_cb) {
|
||||
while (rng_started) {
|
||||
rng_cb(rand());
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +179,8 @@ ble_hw_rng_start(void)
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
return -1;
|
||||
rng_started = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,7 +191,7 @@ ble_hw_rng_stop(void)
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
return 0;
|
||||
return rand();
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XCVR_RX_RADIO_RAMPUP_USECS (40)
|
||||
#define XCVR_TX_RADIO_RAMPUP_USECS (40)
|
||||
|
||||
/*
|
||||
* NOTE: we have to account for the RTC output compare issue. We want it to be
|
||||
* 5 ticks.
|
||||
*/
|
||||
#define XCVR_PROC_DELAY_USECS (153)
|
||||
#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS)
|
||||
#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS)
|
||||
#define XCVR_TX_SCHED_DELAY_USECS (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
#define XCVR_RX_SCHED_DELAY_USECS (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
31
src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml
Normal file
31
src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
pkg.name: nimble/drivers/nrf5340
|
||||
pkg.description: BLE driver for nRF5340 systems.
|
||||
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
|
||||
pkg.apis: ble_driver
|
||||
pkg.deps:
|
||||
- nimble
|
||||
- nimble/controller
|
||||
475
src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c
Normal file
475
src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <syscfg/syscfg.h>
|
||||
#include <os/os.h>
|
||||
#include <nimble/ble.h>
|
||||
#include <nimble/nimble_opt.h>
|
||||
#include <controller/ble_hw.h>
|
||||
|
||||
#include <ble/xcvr.h>
|
||||
#include <mcu/cmsis_nvic.h>
|
||||
#include <os/os_trace_api.h>
|
||||
|
||||
/* Total number of resolving list elements */
|
||||
#define BLE_HW_RESOLV_LIST_SIZE (16)
|
||||
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
/* Random number generator isr callback */
|
||||
static ble_rng_isr_cb_t ble_rng_isr_cb;
|
||||
|
||||
/* If LL privacy is enabled, allocate memory for AAR */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
|
||||
/* The NRF5340 supports up to 16 IRK entries */
|
||||
#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
|
||||
#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
|
||||
#else
|
||||
#define NRF_IRK_LIST_ENTRIES (16)
|
||||
#endif
|
||||
|
||||
/* NOTE: each entry is 16 bytes long. */
|
||||
uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
|
||||
|
||||
/* Current number of IRK entries */
|
||||
uint8_t g_nrf_num_irks;
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
uint32_t addr_high;
|
||||
uint32_t addr_low;
|
||||
|
||||
/* Does FICR have a public address */
|
||||
if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy into device address. We can do this because we know platform */
|
||||
addr_low = NRF_FICR_NS->DEVICEADDR[0];
|
||||
addr_high = NRF_FICR_NS->DEVICEADDR[1];
|
||||
memcpy(addr->val, &addr_low, 4);
|
||||
memcpy(&addr->val[4], &addr_high, 2);
|
||||
addr->type = BLE_ADDR_PUBLIC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) == 1) {
|
||||
memcpy(addr->val, (void *)&NRF_FICR_NS->DEVICEADDR[0], 4);
|
||||
memcpy(&addr->val[4], (void *)&NRF_FICR_NS->DEVICEADDR[1], 2);
|
||||
addr->val[5] |= 0xc0;
|
||||
addr->type = BLE_ADDR_RANDOM;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
NRF_RADIO_NS->DACNF = 0;
|
||||
g_ble_hw_whitelist_mask = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if ((mask & g_ble_hw_whitelist_mask) == 0) {
|
||||
NRF_RADIO_NS->DAB[i] = get_le32(addr);
|
||||
NRF_RADIO_NS->DAP[i] = get_le16(addr + 4);
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
NRF_RADIO_NS->DACNF |= (mask << 8);
|
||||
}
|
||||
g_ble_hw_whitelist_mask |= mask;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint16_t dap;
|
||||
uint16_t txadd;
|
||||
uint32_t dab;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
dab = get_le32(addr);
|
||||
dap = get_le16(addr + 4);
|
||||
txadd = NRF_RADIO_NS->DACNF >> 8;
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if (mask & g_ble_hw_whitelist_mask) {
|
||||
if ((dab == NRF_RADIO_NS->DAB[i]) && (dap == NRF_RADIO_NS->DAP[i])) {
|
||||
if (addr_type == !!(txadd & mask)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
if (i < BLE_HW_WHITE_LIST_SIZE) {
|
||||
g_ble_hw_whitelist_mask &= ~mask;
|
||||
NRF_RADIO_NS->DACNF &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the whitelist in HW
|
||||
*
|
||||
* @return int Number of devices allowed in whitelist
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return BLE_HW_WHITE_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
/* Enable the configured device addresses */
|
||||
NRF_RADIO_NS->DACNF |= g_ble_hw_whitelist_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
/* Disable all whitelist devices */
|
||||
NRF_RADIO_NS->DACNF &= 0x0000ff00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean function which returns true ('1') if there is a match on the
|
||||
* whitelist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return NRF_RADIO_NS->EVENTS_DEVMATCH;
|
||||
}
|
||||
|
||||
/* Encrypt data */
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
int rc;
|
||||
uint32_t end;
|
||||
uint32_t err;
|
||||
|
||||
/* Stop ECB */
|
||||
NRF_ECB_NS->TASKS_STOPECB = 1;
|
||||
/* XXX: does task stop clear these counters? Anyway to do this quicker? */
|
||||
NRF_ECB_NS->EVENTS_ENDECB = 0;
|
||||
NRF_ECB_NS->EVENTS_ERRORECB = 0;
|
||||
NRF_ECB_NS->ECBDATAPTR = (uint32_t)ecb;
|
||||
|
||||
/* Start ECB */
|
||||
NRF_ECB_NS->TASKS_STARTECB = 1;
|
||||
|
||||
/* Wait till error or done */
|
||||
rc = 0;
|
||||
while (1) {
|
||||
end = NRF_ECB_NS->EVENTS_ENDECB;
|
||||
err = NRF_ECB_NS->EVENTS_ERRORECB;
|
||||
if (end || err) {
|
||||
if (err) {
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Random number generator ISR.
|
||||
*/
|
||||
static void
|
||||
ble_rng_isr(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
os_trace_isr_enter();
|
||||
|
||||
/* No callback? Clear and disable interrupts */
|
||||
if (ble_rng_isr_cb == NULL) {
|
||||
NRF_RNG_NS->INTENCLR = 1;
|
||||
NRF_RNG_NS->EVENTS_VALRDY = 0;
|
||||
(void)NRF_RNG_NS->SHORTS;
|
||||
os_trace_isr_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is a value ready grab it */
|
||||
if (NRF_RNG_NS->EVENTS_VALRDY) {
|
||||
NRF_RNG_NS->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG_NS->VALUE;
|
||||
(*ble_rng_isr_cb)(rnum);
|
||||
}
|
||||
|
||||
os_trace_isr_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the random number generator
|
||||
*
|
||||
* @param cb
|
||||
* @param bias
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
/* Set bias */
|
||||
if (bias) {
|
||||
NRF_RNG_NS->CONFIG = 1;
|
||||
} else {
|
||||
NRF_RNG_NS->CONFIG = 0;
|
||||
}
|
||||
|
||||
/* If we were passed a function pointer we need to enable the interrupt */
|
||||
if (cb != NULL) {
|
||||
#ifndef RIOT_VERSION
|
||||
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
#endif
|
||||
#if MYNEWT
|
||||
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
#else
|
||||
ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr);
|
||||
#endif
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
ble_rng_isr_cb = cb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG_NS->EVENTS_VALRDY = 0;
|
||||
if (ble_rng_isr_cb) {
|
||||
NRF_RNG_NS->INTENSET = 1;
|
||||
}
|
||||
NRF_RNG_NS->TASKS_START = 1;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG_NS->INTENCLR = 1;
|
||||
NRF_RNG_NS->TASKS_STOP = 1;
|
||||
NRF_RNG_NS->EVENTS_VALRDY = 0;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
/* Wait for a sample */
|
||||
while (NRF_RNG_NS->EVENTS_VALRDY == 0) {
|
||||
}
|
||||
|
||||
NRF_RNG_NS->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG_NS->VALUE;
|
||||
|
||||
return rnum;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
g_nrf_num_irks = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw resolving list
|
||||
*
|
||||
* @param irk Pointer to IRK to add
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
uint32_t *nrf_entry;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* Copy into irk list */
|
||||
nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
|
||||
memcpy(nrf_entry, irk, 16);
|
||||
|
||||
/* Add to total */
|
||||
++g_nrf_num_irks;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw resolving list
|
||||
*
|
||||
* @param index Index of IRK to remove
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
uint32_t *irk_entry;
|
||||
|
||||
if (index < g_nrf_num_irks) {
|
||||
--g_nrf_num_irks;
|
||||
irk_entry = &g_nrf_irk_list[index];
|
||||
if (g_nrf_num_irks > index) {
|
||||
memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the resolving list. NOTE: this returns the maximum
|
||||
* allowable entries in the HW. Configuration options may limit this.
|
||||
*
|
||||
* @return int Number of devices allowed in resolving list
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return BLE_HW_RESOLV_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the address received was resolved.
|
||||
*
|
||||
* @return int Negative values indicate unresolved address; positive values
|
||||
* indicate index in resolving list of resolved address.
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (NRF_AAR_NS->EVENTS_END) {
|
||||
if (NRF_AAR_NS->EVENTS_RESOLVED) {
|
||||
index = NRF_AAR_NS->STATUS;
|
||||
return (int)index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
1820
src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c
Normal file
1820
src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <syscfg/syscfg.h>
|
||||
#include <os/os_trace_api.h>
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_SYSVIEW)
|
||||
|
||||
static os_trace_module_t g_ble_phy_trace_mod;
|
||||
uint32_t ble_phy_trace_off;
|
||||
|
||||
static void
|
||||
ble_phy_trace_module_send_desc(void)
|
||||
{
|
||||
os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u");
|
||||
os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u");
|
||||
os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable");
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_trace_init(void)
|
||||
{
|
||||
ble_phy_trace_off =
|
||||
os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3,
|
||||
ble_phy_trace_module_send_desc);
|
||||
}
|
||||
#endif
|
||||
23
src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml
Normal file
23
src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
syscfg.defs:
|
||||
BLE_PHY_SYSVIEW:
|
||||
description: >
|
||||
Enable SystemView tracing module for radio driver.
|
||||
value: 0
|
||||
@@ -39,41 +39,47 @@ extern "C" {
|
||||
struct hci_le_conn_complete;
|
||||
struct hci_conn_update;
|
||||
|
||||
#define BLE_GAP_ADV_ITVL_MS(t) ((t) * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_SCAN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_WIN_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_CONN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_CONN_ITVL)
|
||||
#define BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((t) / 10)
|
||||
|
||||
/** 30 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(30)
|
||||
|
||||
/** 60 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MAX BLE_GAP_ADV_ITVL_MS(60)
|
||||
|
||||
/** 100 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MIN (100 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(100)
|
||||
|
||||
/** 150 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MAX (150 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MAX BLE_GAP_ADV_ITVL_MS(150)
|
||||
|
||||
/** 30 ms; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MIN BLE_GAP_SCAN_ITVL_MS(30)
|
||||
|
||||
/** 60 ms; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MAX BLE_GAP_SCAN_ITVL_MS(60)
|
||||
|
||||
/** 11.25 ms; limited discovery interval. */
|
||||
#define BLE_GAP_LIM_DISC_SCAN_INT (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_LIM_DISC_SCAN_INT BLE_GAP_SCAN_ITVL_MS(11.25)
|
||||
|
||||
/** 11.25 ms; limited discovery window (not from the spec). */
|
||||
#define BLE_GAP_LIM_DISC_SCAN_WINDOW (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_LIM_DISC_SCAN_WINDOW BLE_GAP_SCAN_WIN_MS(11.25)
|
||||
|
||||
/** 30 ms; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_WINDOW (30 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_FAST_WINDOW BLE_GAP_SCAN_WIN_MS(30)
|
||||
|
||||
/* 30.72 seconds; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_PERIOD (30.72 * 1000)
|
||||
#define BLE_GAP_SCAN_FAST_PERIOD BLE_GAP_SCAN_ITVL_MS(30.72)
|
||||
|
||||
/** 1.28 seconds; background scanning. */
|
||||
#define BLE_GAP_SCAN_SLOW_INTERVAL1 (1280 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_SLOW_INTERVAL1 BLE_GAP_SCAN_ITVL_MS(1280)
|
||||
|
||||
/** 11.25 ms; background scanning. */
|
||||
#define BLE_GAP_SCAN_SLOW_WINDOW1 (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_SLOW_WINDOW1 BLE_GAP_SCAN_WIN_MS(11.25)
|
||||
|
||||
/** 10.24 seconds. */
|
||||
#define BLE_GAP_DISC_DUR_DFLT (10.24 * 1000)
|
||||
@@ -88,18 +94,18 @@ struct hci_conn_update;
|
||||
#define BLE_GAP_CONN_PAUSE_PERIPHERAL (5 * 1000)
|
||||
|
||||
/* 30 ms. */
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MIN (30 * 1000 / BLE_HCI_CONN_ITVL)
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MIN BLE_GAP_CONN_ITVL_MS(30)
|
||||
|
||||
/* 50 ms. */
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MAX (50 * 1000 / BLE_HCI_CONN_ITVL)
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MAX BLE_GAP_CONN_ITVL_MS(50)
|
||||
|
||||
/** Default channels mask: all three channels are used. */
|
||||
#define BLE_GAP_ADV_DFLT_CHANNEL_MAP 0x07
|
||||
|
||||
#define BLE_GAP_INITIAL_CONN_LATENCY 0
|
||||
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
|
||||
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010
|
||||
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300
|
||||
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000
|
||||
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000
|
||||
|
||||
#define BLE_GAP_ROLE_MASTER 0
|
||||
#define BLE_GAP_ROLE_SLAVE 1
|
||||
@@ -1896,6 +1902,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr);
|
||||
*/
|
||||
int ble_gap_unpair_oldest_peer(void);
|
||||
|
||||
/**
|
||||
* Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the
|
||||
* peer received in input parameters is not deleted.
|
||||
*
|
||||
* @param peer_addr Address of the peer (not to be deleted)
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A BLE host HCI return code if the controller
|
||||
* rejected the request;
|
||||
* A BLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);
|
||||
|
||||
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
|
||||
#define BLE_GAP_PRIVATE_MODE_DEVICE 1
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define H_BLE_HS_LOG_
|
||||
|
||||
#include "modlog/modlog.h"
|
||||
#include "log/log.h"
|
||||
|
||||
/* Only include the logcfg header if this version of newt can generate it. */
|
||||
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
|
||||
|
||||
@@ -28,14 +28,23 @@ extern "C" {
|
||||
#define BT_MESH_ADDR_RELAYS 0xfffe
|
||||
|
||||
#define BT_MESH_KEY_UNUSED 0xffff
|
||||
#define BT_MESH_KEY_ANY 0xffff
|
||||
#define BT_MESH_KEY_DEV 0xfffe
|
||||
#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV
|
||||
#define BT_MESH_KEY_DEV_REMOTE 0xfffd
|
||||
#define BT_MESH_KEY_DEV_ANY 0xfffc
|
||||
|
||||
#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
|
||||
#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
|
||||
#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
|
||||
#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
|
||||
|
||||
#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
|
||||
key == BT_MESH_KEY_DEV_REMOTE)
|
||||
|
||||
#define BT_MESH_APP_SEG_SDU_MAX 12
|
||||
#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
|
||||
#define BT_MESH_RX_SDU_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
|
||||
/** Helper to define a mesh element within an array.
|
||||
*
|
||||
* In case the element has no SIG or Vendor models the helper
|
||||
@@ -57,13 +66,13 @@ extern "C" {
|
||||
/** Abstraction that describes a Mesh Element */
|
||||
struct bt_mesh_elem {
|
||||
/* Unicast Address. Set at runtime during provisioning. */
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
|
||||
/* Location Descriptor (GATT Bluetooth Namespace Descriptors) */
|
||||
const u16_t loc;
|
||||
const uint16_t loc;
|
||||
|
||||
const u8_t model_count;
|
||||
const u8_t vnd_model_count;
|
||||
const uint8_t model_count;
|
||||
const uint8_t vnd_model_count;
|
||||
|
||||
struct bt_mesh_model * const models;
|
||||
struct bt_mesh_model * const vnd_models;
|
||||
@@ -132,33 +141,33 @@ struct bt_mesh_elem {
|
||||
/** Message sending context. */
|
||||
struct bt_mesh_msg_ctx {
|
||||
/** NetKey Index of the subnet to send the message on. */
|
||||
u16_t net_idx;
|
||||
uint16_t net_idx;
|
||||
|
||||
/** AppKey Index to encrypt the message with. */
|
||||
u16_t app_idx;
|
||||
uint16_t app_idx;
|
||||
|
||||
/** Remote address. */
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
|
||||
/** Destination address of a received message. Not used for sending. */
|
||||
u16_t recv_dst;
|
||||
uint16_t recv_dst;
|
||||
|
||||
/** RSSI of received packet. Not used for sending. */
|
||||
s8_t recv_rssi;
|
||||
int8_t recv_rssi;
|
||||
|
||||
/** Received TTL value. Not used for sending. */
|
||||
u8_t recv_ttl;
|
||||
uint8_t recv_ttl;
|
||||
|
||||
/** Force sending reliably by using segment acknowledgement */
|
||||
bool send_rel;
|
||||
|
||||
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
|
||||
u8_t send_ttl;
|
||||
uint8_t send_ttl;
|
||||
};
|
||||
|
||||
struct bt_mesh_model_op {
|
||||
/* OpCode encoded using the BT_MESH_MODEL_OP_* macros */
|
||||
const u32_t opcode;
|
||||
const uint32_t opcode;
|
||||
|
||||
/* Minimum required message length */
|
||||
const size_t min_len;
|
||||
@@ -324,7 +333,7 @@ struct bt_mesh_model_op {
|
||||
*
|
||||
* @return Transmission count (actual transmissions is N + 1).
|
||||
*/
|
||||
#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (u8_t)BIT_MASK(3)))
|
||||
#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3)))
|
||||
|
||||
/** @def BT_MESH_TRANSMIT_INT
|
||||
*
|
||||
@@ -375,23 +384,24 @@ struct bt_mesh_model_pub {
|
||||
/** The model the context belongs to. Initialized by the stack. */
|
||||
struct bt_mesh_model *mod;
|
||||
|
||||
u16_t addr; /**< Publish Address. */
|
||||
u16_t key; /**< Publish AppKey Index. */
|
||||
uint16_t addr; /**< Publish Address. */
|
||||
uint16_t key; /**< Publish AppKey Index. */
|
||||
|
||||
u8_t ttl; /**< Publish Time to Live. */
|
||||
u8_t retransmit; /**< Retransmit Count & Interval Steps. */
|
||||
u8_t period; /**< Publish Period. */
|
||||
u8_t period_div:4, /**< Divisor for the Period. */
|
||||
uint8_t ttl; /**< Publish Time to Live. */
|
||||
uint8_t retransmit; /**< Retransmit Count & Interval Steps. */
|
||||
uint8_t period; /**< Publish Period. */
|
||||
uint8_t period_div:4, /**< Divisor for the Period. */
|
||||
cred:1, /**< Friendship Credentials Flag. */
|
||||
send_rel:1,
|
||||
fast_period:1,/**< Use FastPeriodDivisor */
|
||||
count:3; /**< Retransmissions left. */
|
||||
|
||||
u32_t period_start; /**< Start of the current period. */
|
||||
uint32_t period_start; /**< Start of the current period. */
|
||||
|
||||
/** @brief Publication buffer, containing the publication message.
|
||||
*
|
||||
* The application is expected to initialize this with
|
||||
* a valid net_buf_simple pointer, with the help of e.g.
|
||||
* a valid os_mbuf pointer, with the help of e.g.
|
||||
* the NET_BUF_SIMPLE() macro. The publication buffer must
|
||||
* contain a valid publication message before calling the
|
||||
* bt_mesh_model_publish() API or after the publication's
|
||||
@@ -414,6 +424,10 @@ struct bt_mesh_model_pub {
|
||||
* will be called periodically and is expected to update
|
||||
* @ref bt_mesh_model_pub.msg with a valid publication
|
||||
* message.
|
||||
*
|
||||
* If the callback returns non-zero, the publication is skipped
|
||||
* and will resume on the next periodic publishing interval.
|
||||
*
|
||||
*
|
||||
* @param mod The Model the Publication Context belogs to.
|
||||
*
|
||||
@@ -432,16 +446,18 @@ struct bt_mesh_model_cb {
|
||||
* @sa settings_handler::h_set
|
||||
*
|
||||
* @param model Model to set the persistent data of.
|
||||
* @param name Name/key of the settings item.
|
||||
* @param val Data from the backend.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const settings_set)(struct bt_mesh_model *model, char *val);
|
||||
int (*const settings_set)(struct bt_mesh_model *model,
|
||||
const char *name, char *val);
|
||||
|
||||
/** @brief Callback called when all settings have been loaded.
|
||||
/** @brief Callback called when the mesh is started.
|
||||
*
|
||||
* This handler gets called after the settings have been loaded in
|
||||
* full.
|
||||
* This handler gets called after the node has been provisioned, or
|
||||
* after all mesh data has been loaded from persistent storage.
|
||||
*
|
||||
* @sa settings_handler::h_commit
|
||||
*
|
||||
@@ -449,12 +465,17 @@ struct bt_mesh_model_cb {
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const settings_commit)(struct bt_mesh_model *model);
|
||||
int (*const start)(struct bt_mesh_model *model);
|
||||
|
||||
/** @brief Model init callback.
|
||||
*
|
||||
* Called on every model instance during mesh initialization.
|
||||
*
|
||||
*
|
||||
* If any of the model init callbacks return an error, the Mesh
|
||||
* subsystem initialization will be aborted, and the error will be
|
||||
* returned to the caller of @ref bt_mesh_init.
|
||||
*
|
||||
* @param model Model to be initialized.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
@@ -466,6 +487,9 @@ struct bt_mesh_model_cb {
|
||||
* Called when the mesh node is reset. All model data is deleted on
|
||||
* reset, and the model should clear its state.
|
||||
*
|
||||
* @note If the model stores any persistent data, this needs to be
|
||||
* erased manually.
|
||||
*
|
||||
* @param model Model this callback belongs to.
|
||||
*/
|
||||
void (*const reset)(struct bt_mesh_model *model);
|
||||
@@ -474,26 +498,26 @@ struct bt_mesh_model_cb {
|
||||
/** Abstraction that describes a Mesh Model instance */
|
||||
struct bt_mesh_model {
|
||||
union {
|
||||
const u16_t id;
|
||||
const uint16_t id;
|
||||
struct {
|
||||
u16_t company;
|
||||
u16_t id;
|
||||
uint16_t company;
|
||||
uint16_t id;
|
||||
} vnd;
|
||||
};
|
||||
|
||||
/* Internal information, mainly for persistent storage */
|
||||
u8_t elem_idx; /* Belongs to Nth element */
|
||||
u8_t mod_idx; /* Is the Nth model in the element */
|
||||
u16_t flags; /* Model flags for internal bookkeeping */
|
||||
uint8_t elem_idx; /* Belongs to Nth element */
|
||||
uint8_t mod_idx; /* Is the Nth model in the element */
|
||||
uint16_t flags; /* Model flags for internal bookkeeping */
|
||||
|
||||
/* Model Publication */
|
||||
struct bt_mesh_model_pub * const pub;
|
||||
|
||||
/* AppKey List */
|
||||
u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
|
||||
uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
|
||||
|
||||
/* Subscription List (group or virtual addresses) */
|
||||
u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
|
||||
uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
|
||||
|
||||
const struct bt_mesh_model_op * const op;
|
||||
|
||||
@@ -511,11 +535,11 @@ struct bt_mesh_model {
|
||||
};
|
||||
|
||||
struct bt_mesh_send_cb {
|
||||
void (*start)(u16_t duration, int err, void *cb_data);
|
||||
void (*start)(uint16_t duration, int err, void *cb_data);
|
||||
void (*end)(int err, void *cb_data);
|
||||
};
|
||||
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode);
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode);
|
||||
|
||||
/** Special TTL value to request using configured default TTL */
|
||||
#define BT_MESH_TTL_DEFAULT 0xff
|
||||
@@ -574,7 +598,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
|
||||
* if no SIG model with the given ID exists in the given element.
|
||||
*/
|
||||
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
u16_t id);
|
||||
uint16_t id);
|
||||
|
||||
/** @brief Find a vendor model.
|
||||
*
|
||||
@@ -586,7 +610,7 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
* if no vendor model with the given ID exists in the given element.
|
||||
*/
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id);
|
||||
uint16_t company, uint16_t id);
|
||||
|
||||
/** @brief Get whether the model is in the primary element of the device.
|
||||
*
|
||||
@@ -603,13 +627,14 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
|
||||
*
|
||||
* @param mod Mesh model.
|
||||
* @param vnd This is a vendor model.
|
||||
* @param name Name/key of the settings item.
|
||||
* @param data Model data to store, or NULL to delete any model data.
|
||||
* @param data_len Length of the model data.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
|
||||
const void *data, size_t data_len);
|
||||
const char *name, const void *data, size_t data_len);
|
||||
|
||||
/** @brief Let a model extend another.
|
||||
*
|
||||
@@ -637,9 +662,9 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod,
|
||||
|
||||
/** Node Composition */
|
||||
struct bt_mesh_comp {
|
||||
u16_t cid;
|
||||
u16_t pid;
|
||||
u16_t vid;
|
||||
uint16_t cid;
|
||||
uint16_t pid;
|
||||
uint16_t vid;
|
||||
|
||||
size_t elem_count;
|
||||
struct bt_mesh_elem *elem;
|
||||
|
||||
409
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h
Normal file
409
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/* atomic operations */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-2015, Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ATOMIC_H__
|
||||
#define __ATOMIC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef int atomic_t;
|
||||
typedef atomic_t atomic_val_t;
|
||||
|
||||
/**
|
||||
* @defgroup atomic_apis Atomic Services APIs
|
||||
* @ingroup kernel_apis
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Atomic compare-and-set.
|
||||
*
|
||||
* This routine performs an atomic compare-and-set on @a target. If the current
|
||||
* value of @a target equals @a old_value, @a target is set to @a new_value.
|
||||
* If the current value of @a target does not equal @a old_value, @a target
|
||||
* is left unchanged.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param old_value Original value to compare against.
|
||||
* @param new_value New value to store.
|
||||
* @return 1 if @a new_value is written, 0 otherwise.
|
||||
*/
|
||||
static inline int atomic_cas(atomic_t *target, atomic_val_t old_value,
|
||||
atomic_val_t new_value)
|
||||
{
|
||||
return __atomic_compare_exchange_n(target, &old_value, new_value,
|
||||
0, __ATOMIC_SEQ_CST,
|
||||
__ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic addition.
|
||||
*
|
||||
* This routine performs an atomic addition on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to add.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic subtraction.
|
||||
*
|
||||
* This routine performs an atomic subtraction on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to subtract.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic increment.
|
||||
*
|
||||
* This routine performs an atomic increment by 1 on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_inc(atomic_t *target)
|
||||
{
|
||||
return atomic_add(target, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic decrement.
|
||||
*
|
||||
* This routine performs an atomic decrement by 1 on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_dec(atomic_t *target)
|
||||
{
|
||||
return atomic_sub(target, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic get.
|
||||
*
|
||||
* This routine performs an atomic read on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_get(const atomic_t *target)
|
||||
{
|
||||
return __atomic_load_n(target, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic get-and-set.
|
||||
*
|
||||
* This routine atomically sets @a target to @a value and returns
|
||||
* the previous value of @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to write to @a target.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
/* This builtin, as described by Intel, is not a traditional
|
||||
* test-and-set operation, but rather an atomic exchange operation. It
|
||||
* writes value into *ptr, and returns the previous contents of *ptr.
|
||||
*/
|
||||
return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic clear.
|
||||
*
|
||||
* This routine atomically sets @a target to zero and returns its previous
|
||||
* value. (Hence, it is equivalent to atomic_set(target, 0).)
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_clear(atomic_t *target)
|
||||
{
|
||||
return atomic_set(target, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise inclusive OR.
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise inclusive OR of
|
||||
* @a target and @a value.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to OR.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise exclusive OR (XOR).
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
|
||||
* @a target and @a value.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to XOR
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise AND.
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise AND of @a target
|
||||
* and @a value.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to AND.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise NAND.
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise NAND of @a target
|
||||
* and @a value. (This operation is equivalent to target = ~(target & value).)
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to NAND.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize an atomic variable.
|
||||
*
|
||||
* This macro can be used to initialize an atomic variable. For example,
|
||||
* @code atomic_t my_var = ATOMIC_INIT(75); @endcode
|
||||
*
|
||||
* @param i Value to assign to atomic variable.
|
||||
*/
|
||||
#define ATOMIC_INIT(i) (i)
|
||||
|
||||
/**
|
||||
* @cond INTERNAL_HIDDEN
|
||||
*/
|
||||
|
||||
#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
|
||||
#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1)))
|
||||
#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
|
||||
|
||||
/**
|
||||
* INTERNAL_HIDDEN @endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define an array of atomic variables.
|
||||
*
|
||||
* This macro defines an array of atomic variables containing at least
|
||||
* @a num_bits bits.
|
||||
*
|
||||
* @note
|
||||
* If used from file scope, the bits of the array are initialized to zero;
|
||||
* if used from within a function, the bits are left uninitialized.
|
||||
*
|
||||
* @param name Name of array of atomic variables.
|
||||
* @param num_bits Number of bits needed.
|
||||
*/
|
||||
#define ATOMIC_DEFINE(name, num_bits) \
|
||||
atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
|
||||
|
||||
/**
|
||||
* @brief Atomically test a bit.
|
||||
*
|
||||
* This routine tests whether bit number @a bit of @a target is set or not.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return 1 if the bit was set, 0 if it wasn't.
|
||||
*/
|
||||
static inline int
|
||||
atomic_test_bit(const atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
|
||||
|
||||
return (1 & (val >> (bit & (ATOMIC_BITS - 1))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically test and clear a bit.
|
||||
*
|
||||
* Atomically clear bit number @a bit of @a target and return its old value.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return 1 if the bit was set, 0 if it wasn't.
|
||||
*/
|
||||
static inline int
|
||||
atomic_test_and_clear_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
atomic_val_t old;
|
||||
|
||||
old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
|
||||
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically set a bit.
|
||||
*
|
||||
* Atomically set bit number @a bit of @a target and return its old value.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return 1 if the bit was set, 0 if it wasn't.
|
||||
*/
|
||||
static inline int
|
||||
atomic_test_and_set_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
atomic_val_t old;
|
||||
|
||||
old = atomic_or(ATOMIC_ELEM(target, bit), mask);
|
||||
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically clear a bit.
|
||||
*
|
||||
* Atomically clear bit number @a bit of @a target.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void
|
||||
atomic_clear_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
|
||||
atomic_and(ATOMIC_ELEM(target, bit), ~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically set a bit.
|
||||
*
|
||||
* Atomically set bit number @a bit of @a target.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void
|
||||
atomic_set_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
|
||||
atomic_or(ATOMIC_ELEM(target, bit), mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically set a bit to a given value.
|
||||
*
|
||||
* Atomically set bit number @a bit of @a target to value @a val.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
* @param val true for 1, false for 0.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
|
||||
if (val) {
|
||||
(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
|
||||
} else {
|
||||
(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ATOMIC_H__ */
|
||||
267
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h
Normal file
267
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Tobias Svehagen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BLUETOOTH_MESH_CDB_H_
|
||||
#define _BLUETOOTH_MESH_CDB_H_
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_CDB)
|
||||
#define NODE_COUNT CONFIG_BT_MESH_NODE_COUNT
|
||||
#define SUBNET_COUNT CONFIG_BT_MESH_SUBNET_COUNT
|
||||
#define APP_KEY_COUNT CONFIG_BT_MESH_APP_KEY_COUNT
|
||||
#else
|
||||
#define NODE_COUNT 0
|
||||
#define SUBNET_COUNT 0
|
||||
#define APP_KEY_COUNT 0
|
||||
#endif
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
enum {
|
||||
BT_MESH_CDB_NODE_CONFIGURED,
|
||||
BT_MESH_CDB_NODE_BLACKLISTED,
|
||||
|
||||
BT_MESH_CDB_NODE_FLAG_COUNT
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb_node {
|
||||
uint8_t uuid[16];
|
||||
uint16_t addr;
|
||||
uint16_t net_idx;
|
||||
uint8_t num_elem;
|
||||
uint8_t dev_key[16];
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb_subnet {
|
||||
uint16_t net_idx;
|
||||
|
||||
bool kr_flag;
|
||||
uint8_t kr_phase;
|
||||
|
||||
struct {
|
||||
uint8_t net_key[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb_app_key {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
|
||||
struct {
|
||||
uint8_t app_key[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
enum {
|
||||
BT_MESH_CDB_VALID,
|
||||
BT_MESH_CDB_SUBNET_PENDING,
|
||||
BT_MESH_CDB_KEYS_PENDING,
|
||||
BT_MESH_CDB_NODES_PENDING,
|
||||
BT_MESH_CDB_IVU_IN_PROGRESS,
|
||||
|
||||
BT_MESH_CDB_FLAG_COUNT,
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb {
|
||||
uint32_t iv_index;
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
|
||||
|
||||
struct bt_mesh_cdb_node nodes[NODE_COUNT];
|
||||
struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
|
||||
struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
|
||||
};
|
||||
|
||||
extern struct bt_mesh_cdb bt_mesh_cdb;
|
||||
|
||||
/** @brief Create the Mesh Configuration Database.
|
||||
*
|
||||
* Create and initialize the Mesh Configuration Database. A primary subnet,
|
||||
* ie one with NetIdx 0, will be added and the provided key will be used as
|
||||
* NetKey for that subnet.
|
||||
*
|
||||
* @param key The NetKey to be used for the primary subnet.
|
||||
*
|
||||
* @return 0 on success or negative error code on failure.
|
||||
*/
|
||||
int bt_mesh_cdb_create(const uint8_t key[16]);
|
||||
|
||||
/** @brief Clear the Mesh Configuration Database.
|
||||
*
|
||||
* Remove all nodes, subnets and app-keys stored in the database and mark
|
||||
* the database as invalid. The data will be cleared from persistent storage
|
||||
* if CONFIG_BT_SETTINGS is enabled.
|
||||
*/
|
||||
void bt_mesh_cdb_clear(void);
|
||||
|
||||
/** @brief Set and store the IV Index and IV Update flag.
|
||||
*
|
||||
* The IV Index stored in the CDB will be the one used during provisioning
|
||||
* of new nodes. This function is generally only used from inside the stack.
|
||||
*
|
||||
* This function will store the data to persistent storage if
|
||||
* CONFIG_BT_SETTINGS is enabled.
|
||||
*
|
||||
* @param iv_index The new IV Index to use.
|
||||
* @param iv_update True if there is an ongoing IV Update procedure.
|
||||
*/
|
||||
void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update);
|
||||
|
||||
/** @brief Allocate a node.
|
||||
*
|
||||
* Allocate a new node in the CDB.
|
||||
*
|
||||
* @param uuid UUID of the node.
|
||||
* @param addr Address of the node's primary element. If 0, the lowest
|
||||
* possible address available will be assigned to the node.
|
||||
* @param num_elem Number of elements that the node has.
|
||||
* @param net_idx NetIdx that the node was provisioned to.
|
||||
*
|
||||
* @return The new node or NULL if it cannot be allocated.
|
||||
*/
|
||||
struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
|
||||
uint8_t num_elem, uint16_t net_idx);
|
||||
|
||||
/** @brief Delete a node.
|
||||
*
|
||||
* Delete a node from the CDB.
|
||||
*
|
||||
* @param node The node to be deleted.
|
||||
* @param store If true, the node will be cleared from persistent storage.
|
||||
*/
|
||||
void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
|
||||
|
||||
/** @brief Get a node by address.
|
||||
*
|
||||
* Try to find the node that has the provided address assigned to one of its
|
||||
* elements.
|
||||
*
|
||||
* @param addr Address of the element to look for.
|
||||
*
|
||||
* @return The node that has an element with address addr or NULL if no such
|
||||
* node exists.
|
||||
*/
|
||||
struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr);
|
||||
|
||||
/** @brief Store node to persistent storage.
|
||||
*
|
||||
* @param node Node to be stored.
|
||||
*/
|
||||
void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
|
||||
|
||||
enum {
|
||||
BT_MESH_CDB_ITER_STOP = 0,
|
||||
BT_MESH_CDB_ITER_CONTINUE,
|
||||
};
|
||||
|
||||
/** @typedef bt_mesh_cdb_node_func_t
|
||||
* @brief Node iterator callback.
|
||||
*
|
||||
* @param node Node found.
|
||||
* @param user_data Data given.
|
||||
*
|
||||
* @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
|
||||
* or BT_MESH_CDB_ITER_STOP to stop.
|
||||
*/
|
||||
typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
|
||||
void *user_data);
|
||||
|
||||
/** @brief Node iterator.
|
||||
*
|
||||
* Iterate nodes in the Mesh Configuration Database. The callback function
|
||||
* will only be called for valid, ie allocated, nodes.
|
||||
*
|
||||
* @param func Callback function.
|
||||
* @param user_data Data to pass to the callback.
|
||||
*/
|
||||
void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
|
||||
|
||||
/** @brief Allocate a subnet.
|
||||
*
|
||||
* Allocate a new subnet in the CDB.
|
||||
*
|
||||
* @param net_idx NetIdx of the subnet.
|
||||
*
|
||||
* @return The new subnet or NULL if it cannot be allocated.
|
||||
*/
|
||||
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx);
|
||||
|
||||
/** @brief Delete a subnet.
|
||||
*
|
||||
* Delete a subnet from the CDB.
|
||||
*
|
||||
* @param sub The subnet to be deleted.
|
||||
* @param store If true, the subnet will be cleared from persistent storage.
|
||||
*/
|
||||
void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
|
||||
|
||||
/** @brief Get a subnet by NetIdx
|
||||
*
|
||||
* Try to find the subnet with the specified NetIdx.
|
||||
*
|
||||
* @param net_idx NetIdx of the subnet to look for.
|
||||
*
|
||||
* @return The subnet with the specified NetIdx or NULL if no such subnet
|
||||
* exists.
|
||||
*/
|
||||
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx);
|
||||
|
||||
/** @brief Store subnet to persistent storage.
|
||||
*
|
||||
* @param sub Subnet to be stored.
|
||||
*/
|
||||
void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
|
||||
|
||||
/** @brief Get the flags for a subnet
|
||||
*
|
||||
* @param sub The subnet to get flags for.
|
||||
*
|
||||
* @return The flags for the subnet.
|
||||
*/
|
||||
uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
|
||||
|
||||
|
||||
/** @brief Allocate an application key.
|
||||
*
|
||||
* Allocate a new application key in the CDB.
|
||||
*
|
||||
* @param net_idx NetIdx of NetKey that the application key is bound to.
|
||||
* @param app_idx AppIdx of the application key.
|
||||
*
|
||||
* @return The new application key or NULL if it cannot be allocated.
|
||||
*/
|
||||
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
|
||||
uint16_t app_idx);
|
||||
|
||||
/** @brief Delete an application key.
|
||||
*
|
||||
* Delete an application key from the CDB.
|
||||
*
|
||||
* @param key The application key to be deleted.
|
||||
* @param store If true, the key will be cleared from persistent storage.
|
||||
*/
|
||||
void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
|
||||
|
||||
/** @brief Get an application key by AppIdx
|
||||
*
|
||||
* Try to find the application key with the specified AppIdx.
|
||||
*
|
||||
* @param app_idx AppIdx of the application key to look for.
|
||||
*
|
||||
* @return The application key with the specified AppIdx or NULL if no such key
|
||||
* exists.
|
||||
*/
|
||||
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx);
|
||||
|
||||
/** @brief Store application key to persistent storage.
|
||||
*
|
||||
* @param key Application key to be stored.
|
||||
*/
|
||||
void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key);
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */
|
||||
485
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h
Normal file
485
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h
Normal file
@@ -0,0 +1,485 @@
|
||||
/** @file
|
||||
* @brief Bluetooth Mesh Runtime Configuration APIs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BT_MESH_CFG_H_
|
||||
#define _BT_MESH_CFG_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh Runtime Configuration API
|
||||
* @defgroup bt_mesh_cfg Bluetooth Mesh Runtime Configuration
|
||||
* @ingroup bt_mesh
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Bluetooth Mesh Feature states */
|
||||
enum bt_mesh_feat_state {
|
||||
/** Feature is supported, but disabled. */
|
||||
BT_MESH_FEATURE_DISABLED,
|
||||
/** Feature is supported and enabled. */
|
||||
BT_MESH_FEATURE_ENABLED,
|
||||
/** Feature is not supported, and cannot be enabled. */
|
||||
BT_MESH_FEATURE_NOT_SUPPORTED,
|
||||
};
|
||||
|
||||
/* Legacy feature defines */
|
||||
#define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_RELAY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
#define BT_MESH_BEACON_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_BEACON_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
|
||||
#define BT_MESH_GATT_PROXY_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_GATT_PROXY_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_GATT_PROXY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
#define BT_MESH_FRIEND_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_FRIEND_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_FRIEND_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
#define BT_MESH_NODE_IDENTITY_STOPPED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_NODE_IDENTITY_RUNNING BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
/** @brief Enable or disable sending of the Secure Network Beacon.
|
||||
*
|
||||
* @param beacon New Secure Network Beacon state.
|
||||
*/
|
||||
void bt_mesh_beacon_set(bool beacon);
|
||||
|
||||
/** @brief Get the current Secure Network Beacon state.
|
||||
*
|
||||
* @returns Whether the Secure Network Beacon feature is enabled.
|
||||
*/
|
||||
bool bt_mesh_beacon_enabled(void);
|
||||
|
||||
/** @brief Set the default TTL value.
|
||||
*
|
||||
* The default TTL value is used when no explicit TTL value is set. Models will
|
||||
* use the default TTL value when @ref bt_mesh_msg_ctx::send_ttl is
|
||||
* @ref BT_MESH_TTL_DEFAULT.
|
||||
*
|
||||
* @param default_ttl The new default TTL value. Valid values are 0x00 and 0x02
|
||||
* to @ref BT_MESH_TTL_MAX.
|
||||
*
|
||||
* @retval 0 Successfully set the default TTL value.
|
||||
* @retval -EINVAL Invalid TTL value.
|
||||
*/
|
||||
int bt_mesh_default_ttl_set(uint8_t default_ttl);
|
||||
|
||||
/** @brief Get the current default TTL value.
|
||||
*
|
||||
* @return The current default TTL value.
|
||||
*/
|
||||
uint8_t bt_mesh_default_ttl_get(void);
|
||||
|
||||
/** @brief Set the Network Transmit parameters.
|
||||
*
|
||||
* The Network Transmit parameters determine the parameters local messages are
|
||||
* transmitted with.
|
||||
*
|
||||
* @see BT_MESH_TRANSMIT
|
||||
*
|
||||
* @param xmit New Network Transmit parameters. Use @ref BT_MESH_TRANSMIT for
|
||||
* encoding.
|
||||
*/
|
||||
void bt_mesh_net_transmit_set(uint8_t xmit);
|
||||
|
||||
/** @brief Get the current Network Transmit parameters.
|
||||
*
|
||||
* The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
|
||||
* used to decode the Network Transmit parameters.
|
||||
*
|
||||
* @return The current Network Transmit parameters.
|
||||
*/
|
||||
uint8_t bt_mesh_net_transmit_get(void);
|
||||
|
||||
/** @brief Configure the Relay feature.
|
||||
*
|
||||
* Enable or disable the Relay feature, and configure the parameters to
|
||||
* transmit relayed messages with.
|
||||
*
|
||||
* Support for the Relay feature must be enabled through the
|
||||
* @c CONFIG_BT_MESH_RELAY configuration option.
|
||||
*
|
||||
* @see BT_MESH_TRANSMIT
|
||||
*
|
||||
* @param relay New Relay feature state. Must be one of
|
||||
* @ref BT_MESH_FEATURE_ENABLED and
|
||||
* @ref BT_MESH_FEATURE_DISABLED.
|
||||
* @param xmit New Relay retransmit parameters. Use @ref BT_MESH_TRANSMIT for
|
||||
* encoding.
|
||||
*
|
||||
* @retval 0 Successfully changed the Relay configuration.
|
||||
* @retval -ENOTSUP The Relay feature is not supported.
|
||||
* @retval -EINVAL Invalid parameter.
|
||||
* @retval -EALREADY Already using the given parameters.
|
||||
*/
|
||||
int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit);
|
||||
|
||||
/** @brief Get the current Relay feature state.
|
||||
*
|
||||
* @returns The Relay feature state.
|
||||
*/
|
||||
enum bt_mesh_feat_state bt_mesh_relay_get(void);
|
||||
|
||||
/** @brief Get the current Relay Retransmit parameters.
|
||||
*
|
||||
* The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
|
||||
* used to decode the Relay Retransmit parameters.
|
||||
*
|
||||
* @return The current Relay Retransmit parameters, or 0 if relay is not
|
||||
* supported.
|
||||
*/
|
||||
uint8_t bt_mesh_relay_retransmit_get(void);
|
||||
|
||||
/** @brief Enable or disable the GATT Proxy feature.
|
||||
*
|
||||
* Support for the GATT Proxy feature must be enabled through the
|
||||
* @c CONFIG_BT_MESH_GATT_PROXY configuration option.
|
||||
*
|
||||
* @note The GATT Proxy feature only controls a Proxy node's ability to relay
|
||||
* messages to the mesh network. A node that supports GATT Proxy will
|
||||
* still advertise Connectable Proxy beacons, even if the feature is
|
||||
* disabled. The Proxy feature can only be fully disabled through compile
|
||||
* time configuration.
|
||||
*
|
||||
* @param gatt_proxy New GATT Proxy state. Must be one of
|
||||
* @ref BT_MESH_FEATURE_ENABLED and
|
||||
* @ref BT_MESH_FEATURE_DISABLED.
|
||||
*
|
||||
* @retval 0 Successfully changed the GATT Proxy feature state.
|
||||
* @retval -ENOTSUP The GATT Proxy feature is not supported.
|
||||
* @retval -EINVAL Invalid parameter.
|
||||
* @retval -EALREADY Already in the given state.
|
||||
*/
|
||||
int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy);
|
||||
|
||||
/** @brief Get the current GATT Proxy state.
|
||||
*
|
||||
* @returns The GATT Proxy feature state.
|
||||
*/
|
||||
enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void);
|
||||
|
||||
/** @brief Enable or disable the Friend feature.
|
||||
*
|
||||
* Any active friendships will be terminated immediately if the Friend feature
|
||||
* is disabled.
|
||||
*
|
||||
* Support for the Friend feature must be enabled through the
|
||||
* @c CONFIG_BT_MESH_FRIEND configuration option.
|
||||
*
|
||||
* @param friendship New Friend feature state. Must be one of
|
||||
* @ref BT_MESH_FEATURE_ENABLED and
|
||||
* @ref BT_MESH_FEATURE_DISABLED.
|
||||
*
|
||||
* @retval 0 Successfully changed the Friend feature state.
|
||||
* @retval -ENOTSUP The Friend feature is not supported.
|
||||
* @retval -EINVAL Invalid parameter.
|
||||
* @retval -EALREADY Already in the given state.
|
||||
*/
|
||||
int bt_mesh_friend_set(enum bt_mesh_feat_state friendship);
|
||||
|
||||
/** @brief Get the current Friend state.
|
||||
*
|
||||
* @returns The Friend feature state.
|
||||
*/
|
||||
enum bt_mesh_feat_state bt_mesh_friend_get(void);
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh Subnet Configuration
|
||||
* @defgroup bt_mesh_cfg_subnet Bluetooth Mesh Subnet Configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Add a Subnet.
|
||||
*
|
||||
* Adds a subnet with the given network index and network key to the list of
|
||||
* known Subnets. All messages sent on the given Subnet will be processed by
|
||||
* this node, and the node may send and receive Network Beacons on the given
|
||||
* Subnet.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param key Root network key of the Subnet. All other keys are derived
|
||||
* from this.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Subnet was successfully added.
|
||||
* @retval STATUS_INSUFF_RESOURCES No room for this Subnet.
|
||||
* @retval STATUS_UNSPECIFIED The Subnet couldn't be created for some reason.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]);
|
||||
|
||||
/** @brief Update the given Subnet.
|
||||
*
|
||||
* Starts the Key Refresh procedure for this Subnet by adding a second set of
|
||||
* encryption keys. The Subnet will continue sending with the old key (but
|
||||
* receiving messages using both) until the Subnet enters Key Refresh phase 2.
|
||||
*
|
||||
* This allows a network configurator to replace old network and application
|
||||
* keys for the entire network, effectively removing access for all nodes that
|
||||
* aren't given the new keys.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param key New root network key of the Subnet.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Subnet was updated with a second key.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_IDX_ALREADY_STORED The @c key value is the same as the
|
||||
* current key.
|
||||
* @retval STATUS_CANNOT_UPDATE The Subnet cannot be updated for some reason.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]);
|
||||
|
||||
/** @brief Delete a Subnet.
|
||||
*
|
||||
* Removes the Subnet with the given network index from the node. The node will
|
||||
* stop sending Network Beacons with the given Subnet, and can no longer
|
||||
* process messages on this Subnet.
|
||||
*
|
||||
* All Applications bound to this Subnet are also deleted.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Subnet was deleted.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_del(uint16_t net_idx);
|
||||
|
||||
/** @brief Check whether a Subnet is known.
|
||||
*
|
||||
* @param net_idx Network index
|
||||
*
|
||||
* @return true if a Subnet with the given index exists, false otherwise.
|
||||
*/
|
||||
bool bt_mesh_subnet_exists(uint16_t net_idx);
|
||||
|
||||
/** @brief Set the Subnet's Key Refresh phase.
|
||||
*
|
||||
* The Key Refresh procedure is started by updating the Subnet keys through
|
||||
* @ref bt_mesh_subnet_update. This puts the Subnet in Key Refresh Phase 1.
|
||||
* Once all nodes have received the new Subnet key, Key Refresh Phase 2 can be
|
||||
* activated through this function to start transmitting with the new network
|
||||
* key. Finally, to revoke the old key, set the Key Refresh Phase to 3. This
|
||||
* removes the old keys from the node, and returns the Subnet back to normal
|
||||
* single-key operation with the new key set.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param phase Pointer to the new Key Refresh phase. Will return the actual
|
||||
* Key Refresh phase after updating.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Key Refresh phase of the Subnet was successfully
|
||||
* changed.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_CANNOT_UPDATE The given phase change is invalid.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase);
|
||||
|
||||
/** @brief Get the Subnet's Key Refresh phase.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param phase Pointer to the Key Refresh variable to fill.
|
||||
*
|
||||
* @retval STATUS_SUCCESS Successfully populated the @c phase variable.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase);
|
||||
|
||||
/** @brief Set the Node Identity state of the Subnet.
|
||||
*
|
||||
* The Node Identity state of a Subnet determines whether the Subnet advertises
|
||||
* connectable Node Identity beacons for Proxy Clients to connect to.
|
||||
* Once started, the Node Identity beacon runs for 60 seconds, or until it is
|
||||
* stopped.
|
||||
*
|
||||
* This function serves the same purpose as @ref bt_mesh_proxy_identity_enable,
|
||||
* but only acts on a single Subnet.
|
||||
*
|
||||
* GATT Proxy support must be enabled through
|
||||
* @option{CONFIG_BT_MESH_GATT_PROXY}.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param node_id New Node Identity state, must be either @ref
|
||||
* BT_MESH_FEATURE_ENABLED or @ref BT_MESH_FEATURE_DISABLED.
|
||||
*
|
||||
* @retval STATUS_SUCCESS Successfully set the Node Identity state of the
|
||||
* Subnet.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_FEAT_NOT_SUPP The Node Identity feature is not supported.
|
||||
* @retval STATUS_CANNOT_SET Couldn't set the Node Identity state.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
|
||||
enum bt_mesh_feat_state node_id);
|
||||
|
||||
/** @brief Get the Node Identity state of the Subnet.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param node_id Node Identity variable to fill.
|
||||
*
|
||||
* @retval STATUS_SUCCESS Successfully populated the @c node_id variable.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
|
||||
enum bt_mesh_feat_state *node_id);
|
||||
|
||||
/** @brief Get a list of all known Subnet indexes.
|
||||
*
|
||||
* Builds a list of all known Subnet indexes in the @c net_idxs array.
|
||||
* If the @c net_idxs array is smaller than the list of known Subnets, this
|
||||
* function fills all available entries and returns @c -ENOMEM. In this
|
||||
* case, the next @c max entries of the list can be read out by calling
|
||||
* @code
|
||||
* bt_mesh_subnets_get(list, max, max);
|
||||
* @endcode
|
||||
*
|
||||
* Note that any changes to the Subnet list between calls to this function
|
||||
* could change the order and number of entries in the list.
|
||||
*
|
||||
* @param net_idxs Array to fill.
|
||||
* @param max Max number of indexes to return.
|
||||
* @param skip Number of indexes to skip. Enables batched processing of the
|
||||
* list.
|
||||
*
|
||||
* @return The number of indexes added to the @c net_idxs array, or @c -ENOMEM
|
||||
* if the number of known Subnets exceeds the @c max parameter.
|
||||
*/
|
||||
ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh Application Configuration
|
||||
* @defgroup bt_mesh_cfg_app Bluetooth Mesh Application Configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Add an Application key.
|
||||
*
|
||||
* Adds the Application with the given index to the list of known applications.
|
||||
* Allows the node to send and receive model messages encrypted with this
|
||||
* Application key.
|
||||
*
|
||||
* Every Application is bound to a specific Subnet. The node must know the
|
||||
* Subnet the Application is bound to before it can add the Application.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
* @param net_idx Network index the Application is bound to.
|
||||
* @param key Application key value.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Application was successfully added.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_INSUFF_RESOURCES There's no room for storing this
|
||||
* Application.
|
||||
* @retval STATUS_INVALID_BINDING This AppIdx is already bound to another
|
||||
* Subnet.
|
||||
* @retval STATUS_IDX_ALREADY_STORED This AppIdx is already stored with a
|
||||
* different key value.
|
||||
* @retval STATUS_CANNOT_SET Cannot set the Application key for some reason.
|
||||
*/
|
||||
uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16]);
|
||||
|
||||
/** @brief Update an Application key.
|
||||
*
|
||||
* Update an Application with a second Application key, as part of the
|
||||
* Key Refresh procedure of the bound Subnet. The node will continue
|
||||
* transmitting with the old application key (but receiving on both) until the
|
||||
* Subnet enters Key Refresh phase 2. Once the Subnet enters Key Refresh phase
|
||||
* 3, the old application key will be deleted.
|
||||
*
|
||||
* @note The Application key can only be updated if the bound Subnet is in Key
|
||||
* Refresh phase 1.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
* @param net_idx Network index the Application is bound to, or
|
||||
* @ref BT_MESH_KEY_ANY to skip the binding check.
|
||||
* @param key New key value.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Application key was successfully updated.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
|
||||
* @retval STATUS_CANNOT_UPDATE The Application key cannot be updated for some
|
||||
* reason.
|
||||
* @retval STATUS_IDX_ALREADY_STORED This AppIdx is already updated with a
|
||||
* different key value.
|
||||
*/
|
||||
uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16]);
|
||||
|
||||
/** @brief Delete an Application key.
|
||||
*
|
||||
* All models bound to this application will remove this binding.
|
||||
* All models publishing with this application will stop publishing.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
* @param net_idx Network index.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Application key was successfully deleted.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
|
||||
*/
|
||||
uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx);
|
||||
|
||||
/** @brief Check if an Application key is known.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
*
|
||||
* @return true if the Application is known, false otherwise.
|
||||
*/
|
||||
bool bt_mesh_app_key_exists(uint16_t app_idx);
|
||||
|
||||
/** @brief Get a list of all known Application key indexes.
|
||||
*
|
||||
* Builds a list of all Application indexes for the given network index in the
|
||||
* @c app_idxs array. If the @c app_idxs array cannot fit all bound
|
||||
* Applications, this function fills all available entries and returns @c
|
||||
* -ENOMEM. In this case, the next @c max entries of the list can be read out
|
||||
* by calling
|
||||
* @code
|
||||
* bt_mesh_app_keys_get(net_idx, list, max, max);
|
||||
* @endcode
|
||||
*
|
||||
* Note that any changes to the Application key list between calls to this
|
||||
* function could change the order and number of entries in the list.
|
||||
*
|
||||
* @param net_idx Network Index to get the Applications of, or @ref
|
||||
* BT_MESH_KEY_ANY to get all Applications.
|
||||
* @param app_idxs Array to fill.
|
||||
* @param max Max number of indexes to return.
|
||||
* @param skip Number of indexes to skip. Enables batched processing of the
|
||||
* list.
|
||||
*
|
||||
* @return The number of indexes added to the @c app_idxs array, or @c -ENOMEM
|
||||
* if the number of known Applications exceeds the @c max parameter.
|
||||
*/
|
||||
ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
|
||||
off_t skip);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _BT_MESH_CFG_H_ */
|
||||
@@ -26,7 +26,7 @@ struct bt_mesh_cfg_cli {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
struct k_sem op_sync;
|
||||
u32_t op_pending;
|
||||
uint32_t op_pending;
|
||||
void *op_param;
|
||||
};
|
||||
|
||||
@@ -37,45 +37,81 @@ extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \
|
||||
cli_data, &bt_mesh_cfg_cli_cb)
|
||||
|
||||
int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
|
||||
u8_t *status, struct os_mbuf *comp);
|
||||
int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status);
|
||||
|
||||
int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status);
|
||||
int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
|
||||
uint8_t *status, struct os_mbuf *comp);
|
||||
|
||||
int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
|
||||
int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl);
|
||||
int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl);
|
||||
int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl);
|
||||
|
||||
int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status);
|
||||
int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl);
|
||||
|
||||
int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
|
||||
int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status);
|
||||
int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
|
||||
u8_t *transmit);
|
||||
int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
|
||||
u8_t new_transmit, u8_t *status, u8_t *transmit);
|
||||
int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
|
||||
uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
||||
const u8_t net_key[16], u8_t *status);
|
||||
int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
|
||||
uint8_t val, uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
||||
u16_t key_app_idx, const u8_t app_key[16],
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
|
||||
uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_app_idx, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
|
||||
uint8_t new_transmit, uint8_t *status, uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_app_idx, u16_t mod_id, u16_t cid,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
|
||||
const uint8_t net_key[16], uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
|
||||
size_t *key_cnt);
|
||||
|
||||
int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t key_net_idx, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
|
||||
uint16_t key_app_idx, const uint8_t app_key[16],
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
|
||||
uint8_t *status, uint16_t *keys, size_t *key_cnt);
|
||||
|
||||
int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, uint16_t mod_app_idx,
|
||||
uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, uint16_t mod_app_idx, uint16_t mod_id,
|
||||
uint16_t cid, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint8_t *status, uint16_t *apps,
|
||||
size_t *app_cnt);
|
||||
|
||||
int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid, uint8_t *status,
|
||||
uint16_t *apps, size_t *app_cnt);
|
||||
|
||||
/** @def BT_MESH_PUB_PERIOD_100MS
|
||||
*
|
||||
@@ -120,109 +156,117 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6))
|
||||
|
||||
struct bt_mesh_cfg_mod_pub {
|
||||
u16_t addr;
|
||||
u16_t app_idx;
|
||||
uint16_t addr;
|
||||
uint16_t app_idx;
|
||||
bool cred_flag;
|
||||
u8_t ttl;
|
||||
u8_t period;
|
||||
u8_t transmit;
|
||||
uint8_t ttl;
|
||||
uint8_t period;
|
||||
uint8_t transmit;
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, u16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, u16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u16_t cid,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u16_t cid,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
|
||||
u16_t elem_addr, u16_t sub_addr,
|
||||
u16_t mod_id, u16_t cid, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, uint16_t sub_addr,
|
||||
uint16_t mod_id, uint16_t cid, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t cid, u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t cid, uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t cid, u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t cid, uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
|
||||
u16_t elem_addr, const u8_t label[16],
|
||||
u16_t mod_id, u16_t *virt_addr,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, const uint8_t label[16],
|
||||
uint16_t mod_id, uint16_t *virt_addr,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
|
||||
u16_t elem_addr, const u8_t label[16],
|
||||
u16_t mod_id, u16_t cid,
|
||||
u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, const uint8_t label[16],
|
||||
uint16_t mod_id, uint16_t cid,
|
||||
uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint8_t *status, uint16_t *subs,
|
||||
size_t *sub_cnt);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid, uint8_t *status,
|
||||
uint16_t *subs, size_t *sub_cnt);
|
||||
|
||||
struct bt_mesh_cfg_hb_sub {
|
||||
u16_t src;
|
||||
u16_t dst;
|
||||
u8_t period;
|
||||
u8_t count;
|
||||
u8_t min;
|
||||
u8_t max;
|
||||
uint16_t src;
|
||||
uint16_t dst;
|
||||
uint8_t period;
|
||||
uint8_t count;
|
||||
uint8_t min;
|
||||
uint8_t max;
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
|
||||
|
||||
struct bt_mesh_cfg_hb_pub {
|
||||
u16_t dst;
|
||||
u8_t count;
|
||||
u8_t period;
|
||||
u8_t ttl;
|
||||
u16_t feat;
|
||||
u16_t net_idx;
|
||||
uint16_t dst;
|
||||
uint8_t count;
|
||||
uint8_t period;
|
||||
uint8_t ttl;
|
||||
uint16_t feat;
|
||||
uint16_t net_idx;
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
|
||||
const struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
|
||||
const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
|
||||
struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
|
||||
|
||||
s32_t bt_mesh_cfg_cli_timeout_get(void);
|
||||
void bt_mesh_cfg_cli_timeout_set(s32_t timeout);
|
||||
int32_t bt_mesh_cfg_cli_timeout_get(void);
|
||||
void bt_mesh_cfg_cli_timeout_set(int32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -21,51 +21,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Mesh Configuration Server Model Context */
|
||||
struct bt_mesh_cfg_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
u8_t net_transmit; /* Network Transmit state */
|
||||
u8_t relay; /* Relay Mode state */
|
||||
u8_t relay_retransmit; /* Relay Retransmit state */
|
||||
u8_t beacon; /* Secure Network Beacon state */
|
||||
u8_t gatt_proxy; /* GATT Proxy state */
|
||||
u8_t frnd; /* Friend state */
|
||||
u8_t default_ttl; /* Default TTL */
|
||||
|
||||
/* Heartbeat Publication */
|
||||
struct bt_mesh_hb_pub {
|
||||
struct k_delayed_work timer;
|
||||
|
||||
u16_t dst;
|
||||
u16_t count;
|
||||
u8_t period;
|
||||
u8_t ttl;
|
||||
u16_t feat;
|
||||
u16_t net_idx;
|
||||
} hb_pub;
|
||||
|
||||
/* Heartbeat Subscription */
|
||||
struct bt_mesh_hb_sub {
|
||||
s64_t expiry;
|
||||
|
||||
u16_t src;
|
||||
u16_t dst;
|
||||
u16_t count;
|
||||
u8_t min_hops;
|
||||
u8_t max_hops;
|
||||
|
||||
/* Optional subscription tracking function */
|
||||
void (*func)(u8_t hops, u16_t feat);
|
||||
} hb_sub;
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
|
||||
|
||||
#define BT_MESH_MODEL_CFG_SRV(srv_data) \
|
||||
#define BT_MESH_MODEL_CFG_SRV \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \
|
||||
srv_data, &bt_mesh_cfg_srv_cb)
|
||||
NULL, &bt_mesh_cfg_srv_cb)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -51,15 +51,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define u8_t uint8_t
|
||||
#define s8_t int8_t
|
||||
#define u16_t uint16_t
|
||||
#define s16_t int16_t
|
||||
#define u32_t uint32_t
|
||||
#define u64_t uint64_t
|
||||
#define s64_t int64_t
|
||||
#define s32_t int32_t
|
||||
|
||||
/** @brief Helper to declare elements of bt_data arrays
|
||||
*
|
||||
* This macro is mainly for creating an array of struct bt_data
|
||||
@@ -73,7 +64,7 @@ extern "C" {
|
||||
{ \
|
||||
.type = (_type), \
|
||||
.data_len = (_data_len), \
|
||||
.data = (const u8_t *)(_data), \
|
||||
.data = (const uint8_t *)(_data), \
|
||||
}
|
||||
|
||||
/** @brief Helper to declare elements of bt_data arrays
|
||||
@@ -85,8 +76,8 @@ extern "C" {
|
||||
* @param _bytes Variable number of single-byte parameters
|
||||
*/
|
||||
#define BT_DATA_BYTES(_type, _bytes...) \
|
||||
BT_DATA(_type, ((u8_t []) { _bytes }), \
|
||||
sizeof((u8_t []) { _bytes }))
|
||||
BT_DATA(_type, ((uint8_t []) { _bytes }), \
|
||||
sizeof((uint8_t []) { _bytes }))
|
||||
|
||||
/* EIR/AD data type definitions */
|
||||
#define BT_DATA_FLAGS 0x01 /* AD flags */
|
||||
@@ -119,9 +110,13 @@ extern "C" {
|
||||
|
||||
#define sys_put_be16(a,b) put_be16(b, a)
|
||||
#define sys_put_le16(a,b) put_le16(b, a)
|
||||
#define sys_put_le24(a,b) put_le24(b, a)
|
||||
#define sys_put_be24(a,b) put_be24(b, a)
|
||||
#define sys_put_be32(a,b) put_be32(b, a)
|
||||
#define sys_get_be16(a) get_be16(a)
|
||||
#define sys_get_be24(a) get_be24(a)
|
||||
#define sys_get_le16(a) get_le16(a)
|
||||
#define sys_get_le24(a) get_le24(a)
|
||||
#define sys_get_be32(a) get_be32(a)
|
||||
#define sys_cpu_to_be16(a) htobe16(a)
|
||||
#define sys_cpu_to_be32(a) htobe32(a)
|
||||
@@ -196,9 +191,9 @@ typedef ble_addr_t bt_addr_le_t;
|
||||
|
||||
struct net_buf_simple_state {
|
||||
/** Offset of the data pointer from the beginning of the storage */
|
||||
u16_t offset;
|
||||
uint16_t offset;
|
||||
/** Length of data */
|
||||
u16_t len;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
|
||||
@@ -238,6 +233,14 @@ static inline void net_buf_simple_init(struct os_mbuf *buf,
|
||||
buf->om_len = 0;
|
||||
}
|
||||
|
||||
#define net_buf_simple_init_with_data(buf, data, size) \
|
||||
os_mbuf_copyinto(buf, 0, data, size);
|
||||
|
||||
static inline void net_buf_simple_reset(struct os_mbuf *om)
|
||||
{
|
||||
net_buf_simple_init(om, 0);
|
||||
}
|
||||
|
||||
void net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *buf);
|
||||
void * net_buf_ref(struct os_mbuf *om);
|
||||
void net_buf_unref(struct os_mbuf *om);
|
||||
@@ -248,18 +251,20 @@ uint32_t net_buf_simple_pull_le32(struct os_mbuf *om);
|
||||
uint8_t net_buf_simple_pull_u8(struct os_mbuf *om);
|
||||
void net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val);
|
||||
void net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_simple_add_le32(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_add_zeros(struct os_mbuf *om, uint8_t len);
|
||||
void net_buf_simple_push_le16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val);
|
||||
void *net_buf_simple_pull(struct os_mbuf *om, uint8_t len);
|
||||
void *net_buf_simple_pull_mem(struct os_mbuf *om, uint8_t len);
|
||||
void *net_buf_simple_add(struct os_mbuf *om, uint8_t len);
|
||||
bool k_fifo_is_empty(struct ble_npl_eventq *q);
|
||||
void *net_buf_get(struct ble_npl_eventq *fifo,s32_t t);
|
||||
void *net_buf_get(struct ble_npl_eventq *fifo,int32_t t);
|
||||
uint8_t *net_buf_simple_push(struct os_mbuf *om, uint8_t len);
|
||||
void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
||||
|
||||
@@ -271,7 +276,7 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
||||
#define net_buf_clone(a, b) os_mbuf_dup(a)
|
||||
#define net_buf_add_be32(a, b) net_buf_simple_add_be32(a, b)
|
||||
#define net_buf_add_be16(a, b) net_buf_simple_add_be16(a, b)
|
||||
#define net_buf_pull(a, b) net_buf_simple_pull(a, b)
|
||||
#define net_buf_pull(a, b) net_buf_simple_pull_mem(a, b)
|
||||
#define net_buf_pull_mem(a, b) net_buf_simple_pull_mem(a, b)
|
||||
#define net_buf_pull_u8(a) net_buf_simple_pull_u8(a)
|
||||
#define net_buf_pull_be16(a) net_buf_simple_pull_be16(a)
|
||||
@@ -279,14 +284,16 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
||||
|
||||
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
/** Description of different data types that can be encoded into
|
||||
* advertising data. Used to form arrays that are passed to the
|
||||
* bt_le_adv_start() function.
|
||||
*/
|
||||
struct bt_data {
|
||||
u8_t type;
|
||||
u8_t data_len;
|
||||
const u8_t *data;
|
||||
uint8_t type;
|
||||
uint8_t data_len;
|
||||
const uint8_t *data;
|
||||
};
|
||||
|
||||
struct bt_pub_key_cb {
|
||||
@@ -298,18 +305,24 @@ struct bt_pub_key_cb {
|
||||
*
|
||||
* @param key The local public key, or NULL in case of no key.
|
||||
*/
|
||||
void (*func)(const u8_t key[64]);
|
||||
void (*func)(const uint8_t key[64]);
|
||||
|
||||
struct bt_pub_key_cb *_next;
|
||||
};
|
||||
|
||||
typedef void (*bt_dh_key_cb_t)(const u8_t key[32]);
|
||||
int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb);
|
||||
typedef void (*bt_dh_key_cb_t)(const uint8_t key[32]);
|
||||
int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb);
|
||||
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb);
|
||||
uint8_t *bt_pub_key_get(void);
|
||||
int bt_rand(void *buf, size_t len);
|
||||
const char * bt_hex(const void *buf, size_t len);
|
||||
int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data);
|
||||
int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
|
||||
size_t len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *plaintext, size_t mic_size);
|
||||
int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
|
||||
size_t len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *plaintext, size_t mic_size);
|
||||
void bt_mesh_register_gatt(void);
|
||||
int bt_le_adv_start(const struct ble_gap_adv_params *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
@@ -323,9 +336,10 @@ struct k_delayed_work {
|
||||
void k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler);
|
||||
void k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f);
|
||||
void k_delayed_work_cancel(struct k_delayed_work *w);
|
||||
bool k_delayed_work_pending(struct k_delayed_work *w);
|
||||
void k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms);
|
||||
int64_t k_uptime_get(void);
|
||||
u32_t k_uptime_get_32(void);
|
||||
uint32_t k_uptime_get_32(void);
|
||||
void k_sleep(int32_t duration);
|
||||
void k_work_submit(struct ble_npl_callout *w);
|
||||
void k_work_add_arg(struct ble_npl_callout *w, void *arg);
|
||||
@@ -355,18 +369,18 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
|
||||
src += length - 1;
|
||||
|
||||
for (; length > 0; length--) {
|
||||
*((u8_t *)dst++) = *((u8_t *)src--);
|
||||
*((uint8_t *)dst++) = *((uint8_t *)src--);
|
||||
}
|
||||
}
|
||||
|
||||
#define popcount(x) __builtin_popcount(x)
|
||||
|
||||
static inline unsigned int find_lsb_set(u32_t op)
|
||||
static inline unsigned int find_lsb_set(uint32_t op)
|
||||
{
|
||||
return __builtin_ffs(op);
|
||||
}
|
||||
|
||||
static inline unsigned int find_msb_set(u32_t op)
|
||||
static inline unsigned int find_msb_set(uint32_t op)
|
||||
{
|
||||
if (!op)
|
||||
return 0;
|
||||
@@ -374,43 +388,61 @@ static inline unsigned int find_msb_set(u32_t op)
|
||||
return 32 - __builtin_clz(op);
|
||||
}
|
||||
|
||||
#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
|
||||
#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
|
||||
#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
|
||||
#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
|
||||
#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
|
||||
#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
|
||||
#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
|
||||
#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
|
||||
#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
|
||||
#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
|
||||
#define CONFIG_BT_TESTING BLE_MESH_TESTING
|
||||
#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
|
||||
#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
|
||||
#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
|
||||
#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
|
||||
#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
|
||||
#define CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR BLE_MESH_LPN_SUB_ALL_NODES_ADDR
|
||||
#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
|
||||
#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
|
||||
#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
|
||||
#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
|
||||
#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
|
||||
#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
|
||||
#define CONFIG_BT_TESTING BLE_MESH_TESTING
|
||||
#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
|
||||
#define CONFIG_BT_MESH_PROV_DEVICE BLE_MESH_PROV_DEVICE
|
||||
|
||||
/* Above flags are used with IS_ENABLED macro */
|
||||
#define IS_ENABLED(config) MYNEWT_VAL(config)
|
||||
|
||||
#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
|
||||
#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
|
||||
#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
|
||||
#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
|
||||
#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
|
||||
#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
|
||||
#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
|
||||
#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
|
||||
#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
|
||||
#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
|
||||
#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
|
||||
#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_NODE_COUNT)
|
||||
#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
|
||||
#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
|
||||
#define CONFIG_BT_MESH_SEG_BUFS MYNEWT_VAL(BLE_MESH_SEG_BUFS )
|
||||
#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
|
||||
#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
|
||||
#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
|
||||
#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
|
||||
#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
|
||||
#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
|
||||
#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
|
||||
#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
|
||||
#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
|
||||
#define CONFIG_BT_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_RX_SEG_MSG_COUNT MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)
|
||||
#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)
|
||||
#define CONFIG_BT_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
|
||||
#define CONFIG_BT_MESH_DEFAULT_TTL MYNEWT_VAL(BLE_MESH_DEFAULT_TTL)
|
||||
#define CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_COUNT)
|
||||
#define CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_INTERVAL)
|
||||
#define CONFIG_BT_MESH_RELAY_ENABLED MYNEWT_VAL(BLE_MESH_RELAY_ENABLED)
|
||||
#define CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_INTERVAL)
|
||||
#define CONFIG_BT_MESH_BEACON_ENABLED MYNEWT_VAL(BLE_MESH_BEACON_ENABLED)
|
||||
#define CONFIG_BT_MESH_FRIEND_ENABLED MYNEWT_VAL(BLE_MESH_FRIEND_ENABLED)
|
||||
#define CONFIG_BT_MESH_RELAY MYNEWT_VAL(BLE_MESH_RELAY)
|
||||
#define CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_COUNT)
|
||||
#define CONFIG_BT_MESH_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
|
||||
#define CONFIG_BT_MESH_CDB BLE_MESH_CDB
|
||||
|
||||
#define printk console_printf
|
||||
|
||||
@@ -426,7 +458,7 @@ static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count,
|
||||
ble_npl_sem_init(sem, initial_count);
|
||||
}
|
||||
|
||||
static inline int k_sem_take(struct k_sem *sem, s32_t timeout)
|
||||
static inline int k_sem_take(struct k_sem *sem, int32_t timeout)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
@@ -448,8 +480,8 @@ static inline void k_sem_give(struct k_sem *sem)
|
||||
static inline int net_buf_id(struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf_pool *pool = buf->om_omp;
|
||||
u8_t *pool_start = (u8_t *)pool->omp_pool->mp_membuf_addr;
|
||||
u8_t *buf_ptr = (u8_t *)buf;
|
||||
uint8_t *pool_start = (uint8_t *)pool->omp_pool->mp_membuf_addr;
|
||||
uint8_t *buf_ptr = (uint8_t *)buf;
|
||||
|
||||
return (buf_ptr - pool_start) / BUF_SIZE(pool);
|
||||
}
|
||||
@@ -495,6 +527,46 @@ settings_load(void)
|
||||
|
||||
#define BUILD_ASSERT(cond) _Static_assert(cond, "")
|
||||
|
||||
|
||||
/* Memory slabs/blocks */
|
||||
|
||||
/** Memory slab structure */
|
||||
struct k_mem_slab {
|
||||
/**
|
||||
* _wait_q_t is not required now, as we don't implement zephyr timeouts -
|
||||
* if slab couldn't be allocated, we simply return error
|
||||
*/
|
||||
uint32_t num_blocks; /** number of memory blocks available for allocation */
|
||||
size_t block_size; /** size of single block */
|
||||
/**
|
||||
* buffer for blocks - must be alligned to N-byte, where N is a power of 2.
|
||||
* Minimal size of buffer is num_blocks * block_size
|
||||
*/
|
||||
char *buffer;
|
||||
char *free_list; /** list of free memory blocks */
|
||||
uint32_t num_used; /** count of used memory blocks */
|
||||
};
|
||||
|
||||
struct k_mem_block_id {
|
||||
uint32_t pool : 8;
|
||||
uint32_t level : 4;
|
||||
uint32_t block : 20;
|
||||
};
|
||||
|
||||
struct k_mem_block {
|
||||
void *data;
|
||||
struct k_mem_block_id id;
|
||||
};
|
||||
|
||||
extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
|
||||
extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem);
|
||||
static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
|
||||
{
|
||||
return slab->num_blocks - slab->num_used;
|
||||
}
|
||||
|
||||
int create_free_list(struct k_mem_slab *slab);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,12 +25,12 @@ extern "C" {
|
||||
struct bt_mesh_health_cli {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
void (*current_status)(struct bt_mesh_health_cli *cli, u16_t addr,
|
||||
u8_t test_id, u16_t cid, u8_t *faults,
|
||||
void (*current_status)(struct bt_mesh_health_cli *cli, uint16_t addr,
|
||||
uint8_t test_id, uint16_t cid, uint8_t *faults,
|
||||
size_t fault_count);
|
||||
|
||||
struct k_sem op_sync;
|
||||
u32_t op_pending;
|
||||
uint32_t op_pending;
|
||||
void *op_param;
|
||||
};
|
||||
|
||||
@@ -43,32 +43,30 @@ extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
|
||||
|
||||
int bt_mesh_health_cli_set(struct bt_mesh_model *model);
|
||||
|
||||
int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count);
|
||||
int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
size_t *fault_count);
|
||||
|
||||
int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count);
|
||||
int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
size_t *fault_count);
|
||||
|
||||
int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t test_id, u8_t *faults,
|
||||
size_t *fault_count);
|
||||
int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t test_id, uint8_t *faults,
|
||||
size_t *fault_count);
|
||||
|
||||
int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *divisor);
|
||||
int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor);
|
||||
|
||||
int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t divisor, u8_t *updated_divisor);
|
||||
int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
|
||||
uint8_t *updated_divisor);
|
||||
|
||||
int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *attention);
|
||||
int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention);
|
||||
|
||||
int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t attention, u8_t *updated_attention);
|
||||
int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
|
||||
uint8_t *updated_attention);
|
||||
|
||||
s32_t bt_mesh_health_cli_timeout_get(void);
|
||||
void bt_mesh_health_cli_timeout_set(s32_t timeout);
|
||||
int32_t bt_mesh_health_cli_timeout_get(void);
|
||||
void bt_mesh_health_cli_timeout_set(int32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -23,21 +23,21 @@ extern "C" {
|
||||
|
||||
struct bt_mesh_health_srv_cb {
|
||||
/* Fetch current faults */
|
||||
int (*fault_get_cur)(struct bt_mesh_model *model, u8_t *test_id,
|
||||
u16_t *company_id, u8_t *faults,
|
||||
u8_t *fault_count);
|
||||
int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id,
|
||||
uint16_t *company_id, uint8_t *faults,
|
||||
uint8_t *fault_count);
|
||||
|
||||
/* Fetch registered faults */
|
||||
int (*fault_get_reg)(struct bt_mesh_model *model, u16_t company_id,
|
||||
u8_t *test_id, u8_t *faults,
|
||||
u8_t *fault_count);
|
||||
int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
uint8_t *fault_count);
|
||||
|
||||
/* Clear registered faults */
|
||||
int (*fault_clear)(struct bt_mesh_model *model, u16_t company_id);
|
||||
int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id);
|
||||
|
||||
/* Run a specific test */
|
||||
int (*fault_test)(struct bt_mesh_model *model, u8_t test_id,
|
||||
u16_t company_id);
|
||||
int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id,
|
||||
uint16_t company_id);
|
||||
|
||||
/* Attention on */
|
||||
void (*attn_on)(struct bt_mesh_model *model);
|
||||
@@ -52,7 +52,7 @@ struct bt_mesh_health_srv_cb {
|
||||
*
|
||||
* @param max_faults Maximum number of faults the element can have.
|
||||
*
|
||||
* @return a New net_buf_simple of the needed size.
|
||||
* @return a New os_mbuf of the needed size.
|
||||
*/
|
||||
#define BT_MESH_HEALTH_FAULT_MSG(max_faults) \
|
||||
NET_BUF_SIMPLE(1 + 3 + (max_faults))
|
||||
|
||||
123
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h
Normal file
123
src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/** @file
|
||||
* @brief Bluetooth Mesh Heartbeat API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BLUETOOTH_MESH_HEARTBEAT_H_
|
||||
#define _BLUETOOTH_MESH_HEARTBEAT_H_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh
|
||||
* @defgroup bt_mesh_heartbeat Bluetooth Mesh Heartbeat
|
||||
* @ingroup bt_mesh
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Heartbeat Publication parameters */
|
||||
struct bt_mesh_hb_pub {
|
||||
/** Destination address. */
|
||||
uint16_t dst;
|
||||
/** Remaining publish count. */
|
||||
uint16_t count;
|
||||
/** Time To Live value. */
|
||||
uint8_t ttl;
|
||||
/**
|
||||
* Bitmap of features that trigger a Heartbeat publication if
|
||||
* they change. Legal values are @ref BT_MESH_FEAT_RELAY,
|
||||
* @ref BT_MESH_FEAT_PROXY, @ref BT_MESH_FEAT_FRIEND and
|
||||
* @ref BT_MESH_FEAT_LOW_POWER.
|
||||
*/
|
||||
uint16_t feat;
|
||||
/** Network index used for publishing. */
|
||||
uint16_t net_idx;
|
||||
/** Publication period in seconds. */
|
||||
uint32_t period;
|
||||
};
|
||||
|
||||
/** Heartbeat Subscription parameters. */
|
||||
struct bt_mesh_hb_sub {
|
||||
/** Subscription period in seconds. */
|
||||
uint32_t period;
|
||||
/** Remaining subscription time in seconds. */
|
||||
uint32_t remaining;
|
||||
/** Source address to receive Heartbeats from. */
|
||||
uint16_t src;
|
||||
/** Destination address to received Heartbeats on. */
|
||||
uint16_t dst;
|
||||
/** The number of received Heartbeat messages so far. */
|
||||
uint16_t count;
|
||||
/**
|
||||
* Minimum hops in received messages, ie the shortest registered
|
||||
* path from the publishing node to the subscribing node. A
|
||||
* Heartbeat received from an immediate neighbor has hop
|
||||
* count = 1.
|
||||
*/
|
||||
uint8_t min_hops;
|
||||
/**
|
||||
* Maximum hops in received messages, ie the longest registered
|
||||
* path from the publishing node to the subscribing node. A
|
||||
* Heartbeat received from an immediate neighbor has hop
|
||||
* count = 1.
|
||||
*/
|
||||
uint8_t max_hops;
|
||||
};
|
||||
|
||||
/** Heartbeat callback structure */
|
||||
struct bt_mesh_hb_cb {
|
||||
/** @brief Receive callback for heartbeats.
|
||||
*
|
||||
* Gets called on every received Heartbeat that matches the current
|
||||
* Heartbeat subscription parameters.
|
||||
*
|
||||
* @param sub Current Heartbeat subscription parameters.
|
||||
* @param hops The number of hops the Heartbeat was received
|
||||
* with.
|
||||
* @param feat The feature set of the publishing node. The
|
||||
* value is a bitmap of @ref BT_MESH_FEAT_RELAY,
|
||||
* @ref BT_MESH_FEAT_PROXY,
|
||||
* @ref BT_MESH_FEAT_FRIEND and
|
||||
* @ref BT_MESH_FEAT_LOW_POWER.
|
||||
*/
|
||||
void (*recv)(const struct bt_mesh_hb_sub *sub, uint8_t hops,
|
||||
uint16_t feat);
|
||||
|
||||
/** @brief Subscription end callback for heartbeats.
|
||||
*
|
||||
* Gets called when the subscription period ends, providing a summary
|
||||
* of the received heartbeat messages.
|
||||
*
|
||||
* @param sub Current Heartbeat subscription parameters.
|
||||
*/
|
||||
void (*sub_end)(const struct bt_mesh_hb_sub *sub);
|
||||
};
|
||||
|
||||
/** @brief Get the current Heartbeat publication parameters.
|
||||
*
|
||||
* @param get Heartbeat publication parameters return buffer.
|
||||
*/
|
||||
void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get);
|
||||
|
||||
/** @brief Get the current Heartbeat subscription parameters.
|
||||
*
|
||||
* @param get Heartbeat subscription parameters return buffer.
|
||||
*/
|
||||
void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get);
|
||||
|
||||
extern struct bt_mesh_hb_cb hb_cb;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */
|
||||
@@ -59,10 +59,37 @@ typedef enum {
|
||||
BT_MESH_PROV_OOB_ON_DEV = BIT(15),
|
||||
} bt_mesh_prov_oob_info_t;
|
||||
|
||||
/** Device Capabilities. */
|
||||
struct bt_mesh_dev_capabilities {
|
||||
/** Number of elements supported by the device */
|
||||
uint8_t elem_count;
|
||||
|
||||
/** Supported algorithms and other capabilities */
|
||||
uint16_t algorithms;
|
||||
|
||||
/** Supported public key types */
|
||||
uint8_t pub_key_type;
|
||||
|
||||
/** Supported static OOB Types */
|
||||
uint8_t static_oob;
|
||||
|
||||
/** Supported Output OOB Actions */
|
||||
bt_mesh_output_action_t output_actions;
|
||||
|
||||
/** Supported Input OOB Actions */
|
||||
bt_mesh_input_action_t input_actions;
|
||||
|
||||
/** Maximum size of Output OOB supported */
|
||||
uint8_t output_size;
|
||||
|
||||
/** Maximum size in octets of Input OOB supported */
|
||||
uint8_t input_size;
|
||||
};
|
||||
|
||||
/** Provisioning properties & capabilities. */
|
||||
struct bt_mesh_prov {
|
||||
/** The UUID that's used when advertising as unprovisioned */
|
||||
const u8_t *uuid;
|
||||
const uint8_t *uuid;
|
||||
|
||||
/** Optional URI. This will be advertised separately from the
|
||||
* unprovisioned beacon, however the unprovisioned beacon will
|
||||
@@ -75,19 +102,34 @@ struct bt_mesh_prov {
|
||||
bt_mesh_prov_oob_info_t oob_info;
|
||||
|
||||
/** Static OOB value */
|
||||
const u8_t *static_val;
|
||||
const uint8_t *static_val;
|
||||
/** Static OOB value length */
|
||||
u8_t static_val_len;
|
||||
uint8_t static_val_len;
|
||||
|
||||
/** Maximum size of Output OOB supported */
|
||||
u8_t output_size;
|
||||
uint8_t output_size;
|
||||
/** Supported Output OOB Actions */
|
||||
u16_t output_actions;
|
||||
uint16_t output_actions;
|
||||
|
||||
/* Maximum size of Input OOB supported */
|
||||
u8_t input_size;
|
||||
uint8_t input_size;
|
||||
/** Supported Input OOB Actions */
|
||||
u16_t input_actions;
|
||||
uint16_t input_actions;
|
||||
|
||||
/** @brief Provisioning Capabilities.
|
||||
*
|
||||
* This callback notifies the application that the provisioning capabilities
|
||||
* of the unprovisioned device has been received.
|
||||
*
|
||||
* The application can consequently call bt_mesh_auth_method_set_<*> to
|
||||
* select suitable provisioning oob authentication method.
|
||||
*
|
||||
* When this callback returns, the provisioner will start authentication with
|
||||
* the chosen method.
|
||||
*
|
||||
* @param cap capabilities supported by device.
|
||||
*/
|
||||
void (*capabilities)(const struct bt_mesh_dev_capabilities *cap);
|
||||
|
||||
/** @brief Output of a number is requested.
|
||||
*
|
||||
@@ -99,7 +141,7 @@ struct bt_mesh_prov {
|
||||
*
|
||||
* @return Zero on success or negative error code otherwise
|
||||
*/
|
||||
int (*output_number)(bt_mesh_output_action_t act, u32_t num);
|
||||
int (*output_number)(bt_mesh_output_action_t act, uint32_t num);
|
||||
|
||||
/** @brief Output of a string is requested.
|
||||
*
|
||||
@@ -126,7 +168,7 @@ struct bt_mesh_prov {
|
||||
*
|
||||
* @return Zero on success or negative error code otherwise
|
||||
*/
|
||||
int (*input)(bt_mesh_input_action_t act, u8_t size);
|
||||
int (*input)(bt_mesh_input_action_t act, uint8_t size);
|
||||
|
||||
/** @brief The other device finished their OOB input.
|
||||
*
|
||||
@@ -146,9 +188,9 @@ struct bt_mesh_prov {
|
||||
* @param uri_hash Pointer to URI Hash value. NULL if no hash was
|
||||
* present in the beacon.
|
||||
*/
|
||||
void (*unprovisioned_beacon)(u8_t uuid[16],
|
||||
void (*unprovisioned_beacon)(uint8_t uuid[16],
|
||||
bt_mesh_prov_oob_info_t oob_info,
|
||||
u32_t *uri_hash);
|
||||
uint32_t *uri_hash);
|
||||
|
||||
/** @brief Provisioning link has been opened.
|
||||
*
|
||||
@@ -177,7 +219,7 @@ struct bt_mesh_prov {
|
||||
* @param net_idx NetKeyIndex given during provisioning.
|
||||
* @param addr Primary element address.
|
||||
*/
|
||||
void (*complete)(u16_t net_idx, u16_t addr);
|
||||
void (*complete)(uint16_t net_idx, uint16_t addr);
|
||||
|
||||
/** @brief A new node has been added to the provisioning database.
|
||||
*
|
||||
@@ -186,10 +228,12 @@ struct bt_mesh_prov {
|
||||
* the specified NetKeyIndex and primary element address.
|
||||
*
|
||||
* @param net_idx NetKeyIndex given during provisioning.
|
||||
* @param uuid UUID of the added node
|
||||
* @param addr Primary element address.
|
||||
* @param num_elem Number of elements that this node has.
|
||||
*/
|
||||
void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem);
|
||||
void (*node_added)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
|
||||
uint8_t num_elem);
|
||||
|
||||
/** @brief Node has been reset.
|
||||
*
|
||||
@@ -222,7 +266,90 @@ int bt_mesh_input_string(const char *str);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_input_number(u32_t num);
|
||||
int bt_mesh_input_number(uint32_t num);
|
||||
|
||||
/** @brief Provide Device public key.
|
||||
*
|
||||
* @param public_key Device public key.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]);
|
||||
|
||||
/** @brief Use Input OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Instruct the unprovisioned device to use the specified Input OOB
|
||||
* authentication action. When using @ref BT_MESH_PUSH, @ref BT_MESH_TWIST or
|
||||
* @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_number callback is
|
||||
* called with a random number that has to be entered on the unprovisioned
|
||||
* device.
|
||||
*
|
||||
* When using @ref BT_MESH_ENTER_STRING, the @ref bt_mesh_prov::output_string
|
||||
* callback is called with a random string that has to be entered on the
|
||||
* unprovisioned device.
|
||||
*
|
||||
* @param action Authentication action used by the unprovisioned device.
|
||||
* @param size Authentication size.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size);
|
||||
|
||||
/** @brief Use Output OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Instruct the unprovisioned device to use the specified Output OOB
|
||||
* authentication action. The @ref bt_mesh_prov::input callback will
|
||||
* be called.
|
||||
*
|
||||
* When using @ref BT_MESH_BLINK, @ref BT_MESH_BEEP, @ref BT_MESH_VIBRATE
|
||||
* or @ref BT_MESH_DISPLAY_NUMBER, and the application has to call
|
||||
* @ref bt_mesh_input_number with the random number indicated by
|
||||
* the unprovisioned device.
|
||||
*
|
||||
* When using @ref BT_MESH_DISPLAY_STRING, the application has to call
|
||||
* @ref bt_mesh_input_string with the random string displayed by the
|
||||
* unprovisioned device.
|
||||
*
|
||||
* @param action Authentication action used by the unprovisioned device.
|
||||
* @param size Authentication size.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size);
|
||||
|
||||
/** @brief Use static OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Instruct the unprovisioned device to use static OOB authentication, and use
|
||||
* the given static authentication value when provisioning.
|
||||
*
|
||||
* @param static_val Static OOB value.
|
||||
* @param size Static OOB value size.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size);
|
||||
|
||||
/** @brief Don't use OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Don't use any authentication when provisioning new devices. This is the
|
||||
* default behavior.
|
||||
*
|
||||
* @warning Not using any authentication exposes the mesh network to
|
||||
* impersonation attacks, where attackers can pretend to be the
|
||||
* unprovisioned device to gain access to the network. Authentication
|
||||
* is strongly encouraged.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_none(void);
|
||||
|
||||
/** @brief Enable specific provisioning bearers
|
||||
*
|
||||
@@ -258,25 +385,6 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
|
||||
/* Primary Network Key index */
|
||||
#define BT_MESH_NET_PRIMARY 0x000
|
||||
|
||||
#define BT_MESH_RELAY_DISABLED 0x00
|
||||
#define BT_MESH_RELAY_ENABLED 0x01
|
||||
#define BT_MESH_RELAY_NOT_SUPPORTED 0x02
|
||||
|
||||
#define BT_MESH_BEACON_DISABLED 0x00
|
||||
#define BT_MESH_BEACON_ENABLED 0x01
|
||||
|
||||
#define BT_MESH_GATT_PROXY_DISABLED 0x00
|
||||
#define BT_MESH_GATT_PROXY_ENABLED 0x01
|
||||
#define BT_MESH_GATT_PROXY_NOT_SUPPORTED 0x02
|
||||
|
||||
#define BT_MESH_FRIEND_DISABLED 0x00
|
||||
#define BT_MESH_FRIEND_ENABLED 0x01
|
||||
#define BT_MESH_FRIEND_NOT_SUPPORTED 0x02
|
||||
|
||||
#define BT_MESH_NODE_IDENTITY_STOPPED 0x00
|
||||
#define BT_MESH_NODE_IDENTITY_RUNNING 0x01
|
||||
#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02
|
||||
|
||||
/* Features */
|
||||
#define BT_MESH_FEAT_RELAY BIT(0)
|
||||
#define BT_MESH_FEAT_PROXY BIT(1)
|
||||
@@ -299,7 +407,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_init(u8_t own_addr_type,
|
||||
int bt_mesh_init(uint8_t own_addr_type,
|
||||
const struct bt_mesh_prov *prov,
|
||||
const struct bt_mesh_comp *comp);
|
||||
|
||||
@@ -351,9 +459,9 @@ int bt_mesh_resume(void);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
u8_t flags, u32_t iv_index, u16_t addr,
|
||||
const u8_t dev_key[16]);
|
||||
int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
|
||||
uint8_t flags, uint32_t iv_index, uint16_t addr,
|
||||
const uint8_t dev_key[16]);
|
||||
|
||||
/** @brief Provision a Mesh Node using PB-ADV
|
||||
*
|
||||
@@ -365,8 +473,8 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration);
|
||||
int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
|
||||
uint8_t attention_duration);
|
||||
|
||||
/** @brief Check if the local node has been provisioned.
|
||||
*
|
||||
@@ -428,7 +536,17 @@ int bt_mesh_lpn_poll(void);
|
||||
*
|
||||
* @param cb Function to call when the Friendship status changes.
|
||||
*/
|
||||
void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established));
|
||||
void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established));
|
||||
|
||||
/** @brief Terminate Friendship.
|
||||
*
|
||||
* Terminated Friendship for given LPN.
|
||||
*
|
||||
* @param lpn_addr Low Power Node address.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_friend_terminate(uint16_t lpn_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -17,10 +17,15 @@
|
||||
#include "glue.h"
|
||||
#include "access.h"
|
||||
#include "main.h"
|
||||
#include "cfg.h"
|
||||
#include "cfg_srv.h"
|
||||
#include "health_srv.h"
|
||||
#include "cfg_cli.h"
|
||||
#include "health_cli.h"
|
||||
#include "proxy.h"
|
||||
#include "cdb.h"
|
||||
#include "cfg.h"
|
||||
#include "heartbeat.h"
|
||||
#include "../src/app_keys.h"
|
||||
|
||||
#endif /* __BT_MESH_H */
|
||||
|
||||
@@ -15,7 +15,7 @@ struct bt_mesh_gen_model_cli {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
struct k_sem op_sync;
|
||||
u32_t op_pending;
|
||||
uint32_t op_pending;
|
||||
void *op_param;
|
||||
};
|
||||
|
||||
@@ -33,14 +33,14 @@ extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb;
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, gen_level_cli_op, pub,\
|
||||
cli_data, &bt_mesh_gen_level_cli_cb)
|
||||
|
||||
int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *state);
|
||||
int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t val, u8_t *state);
|
||||
int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t *level);
|
||||
int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t val, s16_t *state);
|
||||
int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
uint8_t *state);
|
||||
int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
uint8_t val, uint8_t *state);
|
||||
int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
int16_t *level);
|
||||
int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
int16_t val, int16_t *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ extern "C" {
|
||||
struct bt_mesh_gen_onoff_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, u8_t *state);
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state);
|
||||
int (*get)(struct bt_mesh_model *model, uint8_t *state);
|
||||
int (*set)(struct bt_mesh_model *model, uint8_t state);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op gen_onoff_srv_op[];
|
||||
@@ -28,8 +28,8 @@ extern const struct bt_mesh_model_cb gen_onoff_srv_cb;
|
||||
struct bt_mesh_gen_level_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, s16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level);
|
||||
int (*get)(struct bt_mesh_model *model, int16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op gen_level_srv_op[];
|
||||
@@ -42,8 +42,8 @@ extern const struct bt_mesh_model_cb gen_level_srv_cb;
|
||||
struct bt_mesh_light_lightness_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, s16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level);
|
||||
int (*get)(struct bt_mesh_model *model, int16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op light_lightness_srv_op[];
|
||||
@@ -53,12 +53,12 @@ extern const struct bt_mesh_model_cb light_lightness_srv_cb;
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \
|
||||
light_lightness_srv_op, pub, srv, &light_lightness_srv_cb)
|
||||
|
||||
void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state));
|
||||
void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level));
|
||||
void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level));
|
||||
void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
|
||||
int (*set)(struct bt_mesh_model *model, uint8_t state));
|
||||
void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level));
|
||||
void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ extern "C" {
|
||||
* Allows access to Bluetooth stack internals, not exposed by public API.
|
||||
*/
|
||||
struct bt_test_cb {
|
||||
void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
|
||||
void (*mesh_net_recv)(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
|
||||
const void *payload, size_t payload_len);
|
||||
void (*mesh_model_bound)(u16_t addr, struct bt_mesh_model *model,
|
||||
u16_t key_idx);
|
||||
void (*mesh_model_unbound)(u16_t addr, struct bt_mesh_model *model,
|
||||
u16_t key_idx);
|
||||
void (*mesh_prov_invalid_bearer)(u8_t opcode);
|
||||
void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model,
|
||||
uint16_t key_idx);
|
||||
void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model,
|
||||
uint16_t key_idx);
|
||||
void (*mesh_prov_invalid_bearer)(uint8_t opcode);
|
||||
void (*mesh_trans_incomp_timer_exp)(void);
|
||||
|
||||
sys_snode_t node;
|
||||
@@ -66,7 +66,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_test_mesh_lpn_group_add(u16_t group);
|
||||
int bt_test_mesh_lpn_group_add(uint16_t group);
|
||||
|
||||
/** Send Friend Subscription List Remove message.
|
||||
*
|
||||
@@ -79,7 +79,7 @@ int bt_test_mesh_lpn_group_add(u16_t group);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
|
||||
int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count);
|
||||
|
||||
/** Clear replay protection list cache.
|
||||
*
|
||||
@@ -87,12 +87,12 @@ int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
|
||||
*/
|
||||
int bt_test_mesh_rpl_clear(void);
|
||||
|
||||
u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx);
|
||||
u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store);
|
||||
uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx);
|
||||
uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store);
|
||||
int cmd_mesh_init(int argc, char *argv[]);
|
||||
|
||||
int bt_test_shell_init(void);
|
||||
int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id);
|
||||
int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#endif
|
||||
|
||||
static const struct bt_mesh_comp *dev_comp;
|
||||
static u16_t dev_primary_addr;
|
||||
static uint16_t dev_primary_addr;
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
@@ -53,7 +53,7 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
}
|
||||
}
|
||||
|
||||
s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
{
|
||||
int period;
|
||||
|
||||
@@ -89,10 +89,10 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
}
|
||||
}
|
||||
|
||||
static s32_t next_period(struct bt_mesh_model *mod)
|
||||
static int32_t next_period(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
u32_t elapsed, period;
|
||||
uint32_t elapsed, period;
|
||||
|
||||
period = bt_mesh_model_pub_period_get(mod);
|
||||
if (!period) {
|
||||
@@ -115,7 +115,7 @@ static s32_t next_period(struct bt_mesh_model *mod)
|
||||
static void publish_sent(int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
s32_t delay;
|
||||
int32_t delay;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
|
||||
@@ -131,7 +131,7 @@ static void publish_sent(int err, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static void publish_start(u16_t duration, int err, void *user_data)
|
||||
static void publish_start(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
@@ -156,30 +156,18 @@ static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.addr = pub->addr,
|
||||
.send_ttl = pub->ttl,
|
||||
.app_idx = pub->key,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_model_elem(mod)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = pub->cred,
|
||||
};
|
||||
int err;
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tx.sub = bt_mesh_subnet_get(key->net_idx);
|
||||
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
|
||||
|
||||
@@ -187,15 +175,22 @@ static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
|
||||
err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(sdu);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub)
|
||||
{
|
||||
/* Cancel all retransmits for this publish attempt */
|
||||
pub->count = 0U;
|
||||
/* Make sure the publish timer gets reset */
|
||||
publish_sent(err, pub->mod);
|
||||
}
|
||||
|
||||
static void mod_publish(struct ble_npl_event *work)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work);
|
||||
s32_t period_ms;
|
||||
int32_t period_ms;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
@@ -227,7 +222,10 @@ static void mod_publish(struct ble_npl_event *work)
|
||||
|
||||
err = pub->update(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to update publication message");
|
||||
/* Cancel this publish attempt. */
|
||||
BT_DBG("Update failed, skipping publish (err: %d)", err);
|
||||
pub->period_start = k_uptime_get_32();
|
||||
publish_retransmit_end(err, pub);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -242,7 +240,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
|
||||
return &dev_comp->elem[mod->elem_idx];
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx)
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
|
||||
{
|
||||
struct bt_mesh_elem *elem;
|
||||
|
||||
@@ -274,6 +272,11 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
int i;
|
||||
int *err = user_data;
|
||||
|
||||
if (*err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod->pub) {
|
||||
mod->pub->mod = mod;
|
||||
@@ -293,12 +296,14 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
}
|
||||
|
||||
if (mod->cb && mod->cb->init) {
|
||||
mod->cb->init(mod);
|
||||
*err = mod->cb->init(mod);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* There must be at least one element */
|
||||
if (!comp->elem_count) {
|
||||
return -EINVAL;
|
||||
@@ -306,12 +311,13 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
|
||||
|
||||
dev_comp = comp;
|
||||
|
||||
bt_mesh_model_foreach(mod_init, NULL);
|
||||
err = 0;
|
||||
bt_mesh_model_foreach(mod_init, &err);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
void bt_mesh_comp_provision(u16_t addr)
|
||||
void bt_mesh_comp_provision(uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -334,16 +340,14 @@ void bt_mesh_comp_unprovision(void)
|
||||
BT_DBG("");
|
||||
|
||||
dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
bt_mesh_model_foreach(mod_init, NULL);
|
||||
}
|
||||
|
||||
u16_t bt_mesh_primary_addr(void)
|
||||
uint16_t bt_mesh_primary_addr(void)
|
||||
{
|
||||
return dev_primary_addr;
|
||||
}
|
||||
|
||||
static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
|
||||
static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -357,13 +361,13 @@ static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
|
||||
}
|
||||
|
||||
struct find_group_visitor_ctx {
|
||||
u16_t *entry;
|
||||
uint16_t *entry;
|
||||
struct bt_mesh_model *mod;
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
};
|
||||
|
||||
static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
|
||||
u32_t depth, void *user_data)
|
||||
uint32_t depth, void *user_data)
|
||||
{
|
||||
struct find_group_visitor_ctx *ctx = user_data;
|
||||
|
||||
@@ -380,7 +384,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
|
||||
uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
|
||||
{
|
||||
struct find_group_visitor_ctx ctx = {
|
||||
.mod = *mod,
|
||||
@@ -396,10 +400,10 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
|
||||
}
|
||||
|
||||
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
||||
u16_t group_addr)
|
||||
uint16_t group_addr)
|
||||
{
|
||||
struct bt_mesh_model *model;
|
||||
u16_t *match;
|
||||
uint16_t *match;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < elem->model_count; i++) {
|
||||
@@ -423,9 +427,9 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
|
||||
{
|
||||
u16_t index;
|
||||
uint16_t index;
|
||||
|
||||
if (BT_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
index = (addr - dev_comp->elem[0].addr);
|
||||
@@ -447,12 +451,12 @@ struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8_t bt_mesh_elem_count(void)
|
||||
uint8_t bt_mesh_elem_count(void)
|
||||
{
|
||||
return dev_comp->elem_count;
|
||||
}
|
||||
|
||||
static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
||||
static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -467,22 +471,26 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst)
|
||||
static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
|
||||
{
|
||||
if (BT_MESH_ADDR_IS_UNICAST(dst)) {
|
||||
return (dev_comp->elem[mod->elem_idx].addr == dst);
|
||||
} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
|
||||
return bt_mesh_model_find_group(&mod, dst);
|
||||
return !!bt_mesh_model_find_group(&mod, dst);
|
||||
}
|
||||
|
||||
return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
|
||||
/* If a message with a fixed group address is sent to the access layer,
|
||||
* the lower layers have already confirmed that we are subscribing to
|
||||
* it. All models on the primary element should receive the message.
|
||||
*/
|
||||
return mod->elem_idx == 0;
|
||||
}
|
||||
|
||||
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
||||
u8_t model_count, u32_t opcode,
|
||||
uint8_t model_count, uint32_t opcode,
|
||||
struct bt_mesh_model **model)
|
||||
{
|
||||
u8_t i;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < model_count; i++) {
|
||||
const struct bt_mesh_model_op *op;
|
||||
@@ -500,7 +508,7 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
|
||||
static int get_opcode(struct os_mbuf *buf, uint32_t *opcode)
|
||||
{
|
||||
switch (buf->om_data[0] >> 6) {
|
||||
case 0x00:
|
||||
@@ -527,6 +535,10 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
|
||||
}
|
||||
|
||||
*opcode = net_buf_simple_pull_u8(buf) << 16;
|
||||
/* Using LE for the CID since the model layer is defined as
|
||||
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
|
||||
* will declare the opcode in this way.
|
||||
*/
|
||||
*opcode |= net_buf_simple_pull_le16(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -534,29 +546,12 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr)
|
||||
{
|
||||
/* Check for fixed group addresses */
|
||||
switch (addr) {
|
||||
case BT_MESH_ADDR_ALL_NODES:
|
||||
return true;
|
||||
case BT_MESH_ADDR_PROXIES:
|
||||
return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
|
||||
case BT_MESH_ADDR_FRIENDS:
|
||||
return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
|
||||
case BT_MESH_ADDR_RELAYS:
|
||||
return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_model *models, *model;
|
||||
const struct bt_mesh_model_op *op;
|
||||
u32_t opcode;
|
||||
u8_t count;
|
||||
uint32_t opcode;
|
||||
uint8_t count;
|
||||
int i;
|
||||
|
||||
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
|
||||
@@ -615,7 +610,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode)
|
||||
{
|
||||
net_buf_simple_init(msg, 0);
|
||||
|
||||
@@ -628,6 +623,10 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
|
||||
break;
|
||||
case 3:
|
||||
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
|
||||
/* Using LE for the CID since the model layer is defined as
|
||||
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
|
||||
* will declare the opcode in this way.
|
||||
*/
|
||||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
break;
|
||||
default:
|
||||
@@ -674,11 +673,8 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(ctx->net_idx),
|
||||
.ctx = ctx,
|
||||
.src = bt_mesh_model_elem(model)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = 0,
|
||||
};
|
||||
|
||||
return model_send(model, &tx, false, msg, cb, cb_data);
|
||||
@@ -688,13 +684,15 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model_pub *pub = model->pub;
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.addr = pub->addr,
|
||||
.send_ttl = pub->ttl,
|
||||
.send_rel = pub->send_rel,
|
||||
.app_idx = pub->key,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_model_elem(model)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
};
|
||||
int err;
|
||||
|
||||
@@ -710,12 +708,6 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
goto done;
|
||||
}
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) {
|
||||
BT_ERR("Message does not fit maximum SDU size");
|
||||
err = -EMSGSIZE;
|
||||
@@ -730,13 +722,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
|
||||
|
||||
ctx.addr = pub->addr;
|
||||
ctx.send_ttl = pub->ttl;
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
tx.friend_cred = pub->cred;
|
||||
tx.sub = bt_mesh_subnet_get(ctx.net_idx),
|
||||
|
||||
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
|
||||
|
||||
@@ -745,10 +731,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
|
||||
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
|
||||
if (err) {
|
||||
/* Don't try retransmissions for this publish attempt */
|
||||
pub->count = 0;
|
||||
/* Make sure the publish timer gets reset */
|
||||
publish_sent(err, model);
|
||||
publish_retransmit_end(err, pub);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -757,9 +740,9 @@ done:
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id)
|
||||
uint16_t company, uint16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < elem->vnd_model_count; i++) {
|
||||
if (elem->vnd_models[i].vnd.company == company &&
|
||||
@@ -772,9 +755,9 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
u16_t id)
|
||||
uint16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < elem->model_count; i++) {
|
||||
if (elem->models[i].id == id) {
|
||||
@@ -802,29 +785,38 @@ struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod)
|
||||
|
||||
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
|
||||
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
|
||||
u32_t depth,
|
||||
uint32_t depth,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *m = root;
|
||||
u32_t depth = 0;
|
||||
int depth = 0;
|
||||
/* 'skip' is set to true when we ascend from child to parent node.
|
||||
* In that case, we want to skip calling the callback on the parent
|
||||
* node and we don't want to descend onto a child node as those
|
||||
* nodes have already been visited.
|
||||
*/
|
||||
bool skip = false;
|
||||
|
||||
do {
|
||||
if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
|
||||
if (!skip &&
|
||||
cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) {
|
||||
return;
|
||||
}
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
if (m->extends) {
|
||||
if (!skip && m->extends) {
|
||||
m = m->extends;
|
||||
depth++;
|
||||
} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
|
||||
m = m->next->next;
|
||||
m = m->next;
|
||||
depth--;
|
||||
skip = true;
|
||||
} else {
|
||||
m = m->next;
|
||||
skip = false;
|
||||
}
|
||||
#endif
|
||||
} while (m && m != root);
|
||||
} while (m && depth > 0);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
|
||||
@@ -16,8 +16,7 @@ enum {
|
||||
BT_MESH_MOD_BIND_PENDING = BIT(0),
|
||||
BT_MESH_MOD_SUB_PENDING = BIT(1),
|
||||
BT_MESH_MOD_PUB_PENDING = BIT(2),
|
||||
BT_MESH_MOD_DATA_PRESENT = BIT(3),
|
||||
BT_MESH_MOD_NEXT_IS_PARENT = BIT(4),
|
||||
BT_MESH_MOD_NEXT_IS_PARENT = BIT(3),
|
||||
};
|
||||
|
||||
/* Tree walk return codes */
|
||||
@@ -26,23 +25,21 @@ enum bt_mesh_walk {
|
||||
BT_MESH_WALK_CONTINUE,
|
||||
};
|
||||
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
|
||||
|
||||
u8_t bt_mesh_elem_count(void);
|
||||
uint8_t bt_mesh_elem_count(void);
|
||||
|
||||
/* Find local element based on unicast or group address */
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr);
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr);
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod);
|
||||
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
|
||||
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
|
||||
u32_t depth,
|
||||
uint32_t depth,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr);
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr);
|
||||
uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr);
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
@@ -50,16 +47,16 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
|
||||
int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
|
||||
|
||||
void bt_mesh_comp_provision(u16_t addr);
|
||||
void bt_mesh_comp_provision(uint16_t addr);
|
||||
void bt_mesh_comp_unprovision(void);
|
||||
|
||||
u16_t bt_mesh_primary_addr(void);
|
||||
uint16_t bt_mesh_primary_addr(void);
|
||||
|
||||
const struct bt_mesh_comp *bt_mesh_comp_get(void);
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx);
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx);
|
||||
|
||||
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
|
||||
|
||||
|
||||
@@ -38,19 +38,18 @@
|
||||
#define ADV_INT_DEFAULT_MS 100
|
||||
#define ADV_INT_FAST_MS 20
|
||||
|
||||
static s32_t adv_int_min = ADV_INT_DEFAULT_MS;
|
||||
static int32_t adv_int_min = ADV_INT_DEFAULT_MS;
|
||||
|
||||
/* TinyCrypt PRNG consumes a lot of stack space, so we need to have
|
||||
* an increased call stack whenever it's used.
|
||||
*/
|
||||
#if MYNEWT
|
||||
#define ADV_STACK_SIZE 768
|
||||
OS_TASK_STACK_DEFINE(g_blemesh_stack, ADV_STACK_SIZE);
|
||||
OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
|
||||
struct os_task adv_task;
|
||||
#endif
|
||||
|
||||
static struct ble_npl_eventq adv_queue;
|
||||
extern u8_t g_mesh_addr_type;
|
||||
extern uint8_t g_mesh_addr_type;
|
||||
static int adv_initialized = false;
|
||||
|
||||
static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
|
||||
@@ -60,14 +59,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
|
||||
struct os_mbuf_pool adv_os_mbuf_pool;
|
||||
static struct os_mempool adv_buf_mempool;
|
||||
|
||||
static const u8_t adv_type[] = {
|
||||
[BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV,
|
||||
[BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE,
|
||||
[BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON,
|
||||
[BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI,
|
||||
};
|
||||
|
||||
|
||||
static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
|
||||
|
||||
static struct bt_mesh_adv *adv_alloc(int id)
|
||||
@@ -75,7 +66,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
|
||||
return &adv_pool[id];
|
||||
}
|
||||
|
||||
static inline void adv_send_start(u16_t duration, int err,
|
||||
static inline void adv_send_start(uint16_t duration, int err,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
@@ -94,10 +85,17 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
|
||||
|
||||
static inline void adv_send(struct os_mbuf *buf)
|
||||
{
|
||||
static const uint8_t adv_type[] = {
|
||||
[BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV,
|
||||
[BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE,
|
||||
[BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON,
|
||||
[BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI,
|
||||
} ;
|
||||
|
||||
const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb;
|
||||
void *cb_data = BT_MESH_ADV(buf)->cb_data;
|
||||
struct ble_gap_adv_params param = { 0 };
|
||||
u16_t duration, adv_int;
|
||||
uint16_t duration, adv_int;
|
||||
struct bt_data ad;
|
||||
int err;
|
||||
|
||||
@@ -154,7 +152,7 @@ mesh_adv_thread(void *args)
|
||||
static struct ble_npl_event *ev;
|
||||
struct os_mbuf *buf;
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
s32_t timeout;
|
||||
int32_t timeout;
|
||||
#endif
|
||||
|
||||
BT_DBG("started");
|
||||
@@ -208,7 +206,7 @@ void bt_mesh_adv_update(void)
|
||||
struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
|
||||
bt_mesh_adv_alloc_t get_id,
|
||||
enum bt_mesh_adv_type type,
|
||||
u8_t xmit, s32_t timeout)
|
||||
uint8_t xmit, int32_t timeout)
|
||||
{
|
||||
struct bt_mesh_adv *adv;
|
||||
struct os_mbuf *buf;
|
||||
@@ -235,10 +233,11 @@ struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
|
||||
ble_npl_event_set_arg(&adv->ev, buf);
|
||||
|
||||
return buf;
|
||||
os_mbuf_free_chain(buf);
|
||||
}
|
||||
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
||||
s32_t timeout)
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
|
||||
int32_t timeout)
|
||||
{
|
||||
return bt_mesh_adv_create_from_pool(&adv_os_mbuf_pool, adv_alloc, type,
|
||||
xmit, timeout);
|
||||
@@ -257,8 +256,8 @@ void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
|
||||
net_buf_put(&adv_queue, net_buf_ref(buf));
|
||||
}
|
||||
|
||||
static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
u8_t adv_type, struct os_mbuf *buf)
|
||||
static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
|
||||
uint8_t adv_type, struct os_mbuf *buf)
|
||||
{
|
||||
if (adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
||||
return;
|
||||
@@ -270,7 +269,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
|
||||
while (buf->om_len > 1) {
|
||||
struct net_buf_simple_state state;
|
||||
u8_t len, type;
|
||||
uint8_t len, type;
|
||||
|
||||
len = net_buf_simple_pull_u8(buf);
|
||||
/* Check for early termination */
|
||||
@@ -304,7 +303,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
}
|
||||
|
||||
net_buf_simple_restore(buf, &state);
|
||||
net_buf_simple_pull(buf, len);
|
||||
net_buf_simple_pull_mem(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +332,7 @@ void bt_mesh_adv_init(void)
|
||||
#if MYNEWT
|
||||
os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL,
|
||||
MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER,
|
||||
g_blemesh_stack, ADV_STACK_SIZE);
|
||||
g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
|
||||
#endif
|
||||
|
||||
/* For BT5 controllers we can have fast advertising interval */
|
||||
@@ -362,7 +361,7 @@ ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg)
|
||||
case BLE_GAP_EVENT_EXT_DISC:
|
||||
ext_desc = &event->ext_disc;
|
||||
buf = os_mbuf_get_pkthdr(&adv_os_mbuf_pool, 0);
|
||||
if (!buf || os_mbuf_append(buf, ext_desc->data, ext_desc->length_data)) {
|
||||
if (!buf || os_mbuf_append(buf, ext_desc->om_data, ext_desc->length_data)) {
|
||||
BT_ERR("Could not append data");
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -31,23 +31,18 @@ enum bt_mesh_adv_type
|
||||
BT_MESH_ADV_URI,
|
||||
};
|
||||
|
||||
typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, u16_t duration,
|
||||
typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration,
|
||||
int err, void *user_data);
|
||||
|
||||
struct bt_mesh_adv {
|
||||
const struct bt_mesh_send_cb *cb;
|
||||
void *cb_data;
|
||||
|
||||
u8_t type:2,
|
||||
uint8_t type:2,
|
||||
busy:1;
|
||||
u8_t xmit;
|
||||
uint8_t xmit;
|
||||
|
||||
/* For transport layer segment sending */
|
||||
struct {
|
||||
u8_t attempts;
|
||||
} seg;
|
||||
|
||||
u8_t flags;
|
||||
uint8_t flags;
|
||||
|
||||
int ref_cnt;
|
||||
struct ble_npl_event ev;
|
||||
@@ -56,13 +51,13 @@ struct bt_mesh_adv {
|
||||
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
|
||||
|
||||
/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
||||
s32_t timeout);
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
|
||||
int32_t timeout);
|
||||
|
||||
struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
|
||||
bt_mesh_adv_alloc_t get_id,
|
||||
enum bt_mesh_adv_type type,
|
||||
u8_t xmit, s32_t timeout);
|
||||
uint8_t xmit, int32_t timeout);
|
||||
|
||||
void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data);
|
||||
|
||||
224
src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c
Normal file
224
src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "crypto.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
|
||||
static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
|
||||
{
|
||||
dst[0] = a[0] ^ b[0];
|
||||
dst[1] = a[1] ^ b[1];
|
||||
dst[2] = a[2] ^ b[2];
|
||||
dst[3] = a[3] ^ b[3];
|
||||
dst[4] = a[4] ^ b[4];
|
||||
dst[5] = a[5] ^ b[5];
|
||||
dst[6] = a[6] ^ b[6];
|
||||
dst[7] = a[7] ^ b[7];
|
||||
dst[8] = a[8] ^ b[8];
|
||||
dst[9] = a[9] ^ b[9];
|
||||
dst[10] = a[10] ^ b[10];
|
||||
dst[11] = a[11] ^ b[11];
|
||||
dst[12] = a[12] ^ b[12];
|
||||
dst[13] = a[13] ^ b[13];
|
||||
dst[14] = a[14] ^ b[14];
|
||||
dst[15] = a[15] ^ b[15];
|
||||
}
|
||||
|
||||
/* pmsg is assumed to have the nonce already present in bytes 1-13 */
|
||||
static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
|
||||
size_t mic_size, uint8_t msg_len, uint8_t b[16],
|
||||
uint8_t X0[16])
|
||||
{
|
||||
int i, j, err;
|
||||
|
||||
/* X_0 = e(AppKey, flags || nonce || length) */
|
||||
b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
|
||||
|
||||
sys_put_be16(msg_len, b + 14);
|
||||
|
||||
err = bt_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, b);
|
||||
|
||||
for (i = 0; i < sizeof(uint16_t); i++) {
|
||||
b[i] = X0[i] ^ b[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(uint16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
b[i] = X0[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = bt_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aad_len; i++, j++) {
|
||||
b[i] = X0[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
b[i] = X0[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
|
||||
size_t aad_len, uint8_t *mic, size_t mic_size)
|
||||
{
|
||||
uint8_t b[16], Xn[16], s0[16];
|
||||
uint16_t blk_cnt, last_blk;
|
||||
int err, j, i;
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16U;
|
||||
}
|
||||
|
||||
b[0] = 0x01;
|
||||
memcpy(b + 1, nonce, 13);
|
||||
|
||||
/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
sys_put_be16(0x0000, &b[14]);
|
||||
|
||||
err = bt_encrypt_be(key, b, s0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
if (j + 1 == blk_cnt) {
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
|
||||
}
|
||||
|
||||
memcpy(&b[i], &Xn[i], 16 - i);
|
||||
} else {
|
||||
xor16(b, Xn, &cleartext_msg[j * 16]);
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, b, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < mic_size; i++) {
|
||||
mic[i] = s0[i] ^ Xn[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
|
||||
const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
|
||||
{
|
||||
uint8_t a_i[16], s_i[16];
|
||||
uint16_t last_blk, blk_cnt;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16U;
|
||||
}
|
||||
|
||||
a_i[0] = 0x01;
|
||||
memcpy(&a_i[1], nonce, 13);
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
sys_put_be16(j + 1, &a_i[14]);
|
||||
|
||||
err = bt_encrypt_be(key, a_i, s_i);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
if (j < blk_cnt - 1) {
|
||||
xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
|
||||
} else {
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
in_msg[(j * 16) + i] ^ s_i[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg,
|
||||
size_t msg_len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
uint8_t mic[16];
|
||||
|
||||
if (aad_len >= 0xff00 || mic_size > sizeof(mic)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ccm_crypt(key, nonce, enc_msg, out_msg, msg_len);
|
||||
|
||||
ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
|
||||
|
||||
if (memcmp(mic, enc_msg + msg_len, mic_size)) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg,
|
||||
size_t msg_len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
uint8_t *mic = out_msg + msg_len;
|
||||
|
||||
BT_DBG("key %s", bt_hex(key, 16));
|
||||
BT_DBG("nonce %s", bt_hex(nonce, 13));
|
||||
BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
|
||||
BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
|
||||
|
||||
/* Unsupported AAD size */
|
||||
if (aad_len >= 0xff00 || mic_size > 16) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
|
||||
|
||||
ccm_crypt(key, nonce, msg, out_msg, msg_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
507
src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c
Normal file
507
src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "net.h"
|
||||
#include "app_keys.h"
|
||||
#include "rpl.h"
|
||||
#include "settings.h"
|
||||
#include "crypto.h"
|
||||
#include "adv.h"
|
||||
#include "proxy.h"
|
||||
#include "friend.h"
|
||||
#include "foundation.h"
|
||||
#include "access.h"
|
||||
#include "subnet.h"
|
||||
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
#include "log/log.h"
|
||||
|
||||
static struct bt_mesh_app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = {
|
||||
[0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
};
|
||||
|
||||
static void app_key_evt(struct bt_mesh_app_key *app, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) {
|
||||
if (bt_mesh_app_key_cb_list[i]) {
|
||||
BT_DBG("app_key_evt %d", i);
|
||||
bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *app_get(uint16_t app_idx)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
return &apps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app = NULL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
/* Check for already existing app_key */
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
return &apps[i];
|
||||
}
|
||||
|
||||
if (!app && apps[i].app_idx == BT_MESH_KEY_UNUSED) {
|
||||
app = &apps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
static void app_key_del(struct bt_mesh_app_key *app)
|
||||
{
|
||||
BT_DBG("AppIdx 0x%03x", app->app_idx);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_DELETED);
|
||||
|
||||
app->net_idx = BT_MESH_KEY_UNUSED;
|
||||
app->app_idx = BT_MESH_KEY_UNUSED;
|
||||
(void)memset(app->keys, 0, sizeof(app->keys));
|
||||
}
|
||||
|
||||
static void app_key_revoke(struct bt_mesh_app_key *app)
|
||||
{
|
||||
if (!app->updated) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&app->keys[0], &app->keys[1], sizeof(app->keys[0]));
|
||||
memset(&app->keys[1], 0, sizeof(app->keys[1]));
|
||||
app->updated = false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_REVOKED);
|
||||
}
|
||||
|
||||
|
||||
static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
if (evt == BT_MESH_KEY_UPDATED || evt == BT_MESH_KEY_ADDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (app->net_idx != sub->net_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (evt == BT_MESH_KEY_DELETED) {
|
||||
app_key_del(app);
|
||||
} else if (evt == BT_MESH_KEY_REVOKED) {
|
||||
app_key_revoke(app);
|
||||
} else if (evt == BT_MESH_KEY_SWAPPED && app->updated) {
|
||||
app_key_evt(app, BT_MESH_KEY_SWAPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
if (!bt_mesh_subnet_cb_list[0]) {
|
||||
bt_mesh_subnet_cb_list[0] = subnet_evt;
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
|
||||
bt_hex(key, 16));
|
||||
|
||||
if (!bt_mesh_subnet_get(net_idx)) {
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
app = app_key_alloc(app_idx);
|
||||
if (!app) {
|
||||
return STATUS_INSUFF_RESOURCES;
|
||||
}
|
||||
|
||||
if (app->app_idx == app_idx) {
|
||||
if (app->net_idx != net_idx) {
|
||||
return STATUS_INVALID_BINDING;
|
||||
}
|
||||
|
||||
if (memcmp(key, app->keys[0].val, 16)) {
|
||||
return STATUS_IDX_ALREADY_STORED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (bt_mesh_app_id(key, &app->keys[0].id)) {
|
||||
return STATUS_CANNOT_SET;
|
||||
}
|
||||
|
||||
BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
|
||||
|
||||
app->net_idx = net_idx;
|
||||
app->app_idx = app_idx;
|
||||
app->updated = false;
|
||||
memcpy(app->keys[0].val, key, 16);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing AppKey persistently");
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_ADDED);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (app) {
|
||||
return app;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
|
||||
bt_hex(key, 16));
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (!app) {
|
||||
return STATUS_INVALID_APPKEY;
|
||||
}
|
||||
|
||||
if (net_idx != BT_MESH_KEY_UNUSED && app->net_idx != net_idx) {
|
||||
return STATUS_INVALID_BINDING;
|
||||
}
|
||||
|
||||
sub = bt_mesh_subnet_get(app->net_idx);
|
||||
if (!sub) {
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
/* The AppKey Update message shall generate an error when node
|
||||
* is in normal operation, Phase 2, or Phase 3 or in Phase 1
|
||||
* when the AppKey Update message on a valid AppKeyIndex when
|
||||
* the AppKey value is different.
|
||||
*/
|
||||
if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
|
||||
return STATUS_CANNOT_UPDATE;
|
||||
}
|
||||
|
||||
if (app->updated) {
|
||||
if (memcmp(app->keys[1].val, key, 16)) {
|
||||
return STATUS_IDX_ALREADY_STORED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (bt_mesh_app_id(key, &app->keys[1].id)) {
|
||||
return STATUS_CANNOT_UPDATE;
|
||||
}
|
||||
|
||||
BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, app->keys[1].id);
|
||||
|
||||
app->updated = true;
|
||||
memcpy(app->keys[1].val, key, 16);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing AppKey persistently");
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_UPDATED);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
BT_DBG("AppIdx 0x%03x", app_idx);
|
||||
|
||||
if (net_idx != BT_MESH_KEY_UNUSED && !bt_mesh_subnet_get(net_idx)) {
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (!app) {
|
||||
/* This could be a retry of a previous attempt that had its
|
||||
* response lost, so pretend that it was a success.
|
||||
*/
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (net_idx != BT_MESH_KEY_UNUSED && net_idx != app->net_idx) {
|
||||
return STATUS_INVALID_BINDING;
|
||||
}
|
||||
|
||||
app_key_del(app);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t old_key[16], const uint8_t new_key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
app = app_key_alloc(app_idx);
|
||||
if (!app) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (app->app_idx == app_idx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
|
||||
|
||||
memcpy(app->keys[0].val, old_key, 16);
|
||||
if (bt_mesh_app_id(old_key, &app->keys[0].id)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (new_key) {
|
||||
memcpy(app->keys[1].val, new_key, 16);
|
||||
if (bt_mesh_app_id(new_key, &app->keys[1].id)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
app->net_idx = net_idx;
|
||||
app->app_idx = app_idx;
|
||||
app->updated = !!new_key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bt_mesh_app_key_exists(uint16_t app_idx)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
|
||||
off_t skip)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (net_idx != BT_MESH_KEY_ANY && app->net_idx != net_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count >= max) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
app_idxs[count++] = app->app_idx;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
|
||||
struct bt_mesh_subnet **sub,
|
||||
const uint8_t *app_key[16], uint8_t *aid)
|
||||
{
|
||||
struct bt_mesh_app_key *app = NULL;
|
||||
|
||||
if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
|
||||
/* With device keys, the application has to decide which subnet
|
||||
* to send on.
|
||||
*/
|
||||
*sub = bt_mesh_subnet_get(ctx->net_idx);
|
||||
if (!*sub) {
|
||||
BT_WARN("Unknown NetKey 0x%03x", ctx->net_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE &&
|
||||
!bt_mesh_elem_find(ctx->addr)) {
|
||||
struct bt_mesh_cdb_node *node;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
|
||||
BT_WARN("No DevKey for 0x%04x", ctx->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
node = bt_mesh_cdb_node_get(ctx->addr);
|
||||
if (!node) {
|
||||
BT_WARN("No DevKey for 0x%04x", ctx->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*app_key = node->dev_key;
|
||||
} else {
|
||||
*app_key = bt_mesh.dev_key;
|
||||
}
|
||||
|
||||
*aid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
app = app_get(ctx->app_idx);
|
||||
if (!app) {
|
||||
BT_WARN("Unknown AppKey 0x%03x", ctx->app_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*sub = bt_mesh_subnet_get(app->net_idx);
|
||||
if (!*sub) {
|
||||
BT_WARN("Unknown NetKey 0x%03x", app->net_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((*sub)->kr_phase == BT_MESH_KR_PHASE_2 && app->updated) {
|
||||
*aid = app->keys[1].id;
|
||||
*app_key = app->keys[1].val;
|
||||
} else {
|
||||
*aid = app->keys[0].id;
|
||||
*app_key = app->keys[0].val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
|
||||
struct bt_mesh_net_rx *rx,
|
||||
int (*cb)(struct bt_mesh_net_rx *rx,
|
||||
const uint8_t key[16], void *cb_data),
|
||||
void *cb_data)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
if (dev_key) {
|
||||
/* Attempt remote dev key first, as that is only available for
|
||||
* provisioner devices, which normally don't interact with nodes
|
||||
* that know their local dev key.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_CDB) &&
|
||||
rx->net_if != BT_MESH_NET_IF_LOCAL) {
|
||||
struct bt_mesh_cdb_node *node;
|
||||
|
||||
node = bt_mesh_cdb_node_get(rx->ctx.addr);
|
||||
if (node && !cb(rx, node->dev_key, cb_data)) {
|
||||
return BT_MESH_KEY_DEV_REMOTE;
|
||||
}
|
||||
}
|
||||
|
||||
/** Bluetooth Mesh Specification v1.0.1, section 3.4.3:
|
||||
* The Device key is only valid for unicast addresses.
|
||||
*/
|
||||
if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
|
||||
err = cb(rx, bt_mesh.dev_key, cb_data);
|
||||
if (!err) {
|
||||
return BT_MESH_KEY_DEV_LOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
return BT_MESH_KEY_UNUSED;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
const struct bt_mesh_app_key *app = &apps[i];
|
||||
const struct bt_mesh_app_cred *cred;
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (app->net_idx != rx->sub->net_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rx->new_key && app->updated) {
|
||||
cred = &app->keys[1];
|
||||
} else {
|
||||
cred = &app->keys[0];
|
||||
}
|
||||
|
||||
if (cred->id != aid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = cb(rx, cred->val, cb_data);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return app->app_idx;
|
||||
}
|
||||
|
||||
return BT_MESH_KEY_UNUSED;
|
||||
}
|
||||
|
||||
|
||||
void bt_mesh_app_keys_reset(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx != BT_MESH_KEY_UNUSED) {
|
||||
app_key_del(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h
Normal file
86
src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _BT_MESH_APP_KEYS_H_
|
||||
#define _BT_MESH_APP_KEYS_H_
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "subnet.h"
|
||||
|
||||
/** Mesh Application. */
|
||||
struct bt_mesh_app_key {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
bool updated;
|
||||
struct bt_mesh_app_cred {
|
||||
uint8_t id;
|
||||
uint8_t val[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
/** @brief Reset the app keys module. */
|
||||
void bt_mesh_app_keys_reset(void);
|
||||
|
||||
/** @brief Get the application key with the given AppIdx.
|
||||
*
|
||||
* @param app_idx App index.
|
||||
*
|
||||
* @return The matching application, or NULL if the application isn't known.
|
||||
*/
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx);
|
||||
|
||||
/** @brief Initialize a new application key with the given parameters.
|
||||
*
|
||||
* @param app_idx AppIndex.
|
||||
* @param net_idx NetIndex the application is bound to.
|
||||
* @param old_key Current application key.
|
||||
* @param new_key Updated application key, or NULL if not known.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t old_key[16], const uint8_t new_key[16]);
|
||||
|
||||
/** @brief Resolve the message encryption keys, given a message context.
|
||||
*
|
||||
* Will use the @c ctx::app_idx and @c ctx::net_idx fields to find a pair of
|
||||
* message encryption keys. If @c ctx::app_idx represents a device key, the
|
||||
* @c ctx::net_idx will be used to determine the net key. Otherwise, the
|
||||
* @c ctx::net_idx parameter will be ignored.
|
||||
*
|
||||
* @param ctx Message context.
|
||||
* @param sub Subnet return parameter.
|
||||
* @param app_key Application return parameter.
|
||||
* @param aid Application ID return parameter.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
|
||||
struct bt_mesh_subnet **sub,
|
||||
const uint8_t *app_key[16], uint8_t *aid);
|
||||
|
||||
/** @brief Iterate through all matching application keys and call @c cb on each.
|
||||
*
|
||||
* @param dev_key Whether to return device keys.
|
||||
* @param aid 7 bit application ID to match.
|
||||
* @param rx RX structure to match against.
|
||||
* @param cb Callback to call for every valid app key.
|
||||
* @param cb_data Callback data to pass to the callback.
|
||||
*
|
||||
* @return The AppIdx that yielded a 0-return from the callback.
|
||||
*/
|
||||
uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
|
||||
struct bt_mesh_net_rx *rx,
|
||||
int (*cb)(struct bt_mesh_net_rx *rx,
|
||||
const uint8_t key[16], void *cb_data),
|
||||
void *cb_data);
|
||||
|
||||
struct bt_mesh_app_key *app_get(uint16_t app_idx);
|
||||
|
||||
extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx,
|
||||
enum bt_mesh_key_evt evt);
|
||||
|
||||
#endif /* _BT_MESH_APP_KEYS_H_ */
|
||||
@@ -21,8 +21,8 @@
|
||||
#include "crypto.h"
|
||||
#include "beacon.h"
|
||||
#include "foundation.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#define UNPROVISIONED_INTERVAL (K_SECONDS(5))
|
||||
#define PROVISIONED_INTERVAL (K_SECONDS(10))
|
||||
|
||||
#define BEACON_TYPE_UNPROVISIONED 0x00
|
||||
@@ -36,26 +36,12 @@
|
||||
|
||||
static struct k_delayed_work beacon_timer;
|
||||
|
||||
static struct bt_mesh_subnet *cache_check(u8_t data[21])
|
||||
static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(sub->beacon_cache, data, 21)) {
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return !memcmp(sub->beacon_cache, beacon_data, 21);
|
||||
}
|
||||
|
||||
static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
|
||||
static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub)
|
||||
{
|
||||
memcpy(sub->beacon_cache, data, 21);
|
||||
}
|
||||
@@ -72,16 +58,12 @@ static void beacon_complete(int err, void *user_data)
|
||||
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
u8_t flags = bt_mesh_net_flags(sub);
|
||||
uint8_t flags = bt_mesh_net_flags(sub);
|
||||
struct bt_mesh_subnet_keys *keys;
|
||||
|
||||
net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
|
||||
|
||||
if (sub->kr_flag) {
|
||||
keys = &sub->keys[1];
|
||||
} else {
|
||||
keys = &sub->keys[0];
|
||||
}
|
||||
keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
|
||||
|
||||
net_buf_simple_add_u8(buf, flags);
|
||||
|
||||
@@ -103,53 +85,43 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
#define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \
|
||||
K_SECONDS(5))
|
||||
|
||||
static int secure_beacon_send(void)
|
||||
static int secure_beacon_send(struct bt_mesh_subnet *sub, void *cb_data)
|
||||
{
|
||||
static const struct bt_mesh_send_cb send_cb = {
|
||||
.end = beacon_complete,
|
||||
};
|
||||
u32_t now = k_uptime_get_32();
|
||||
int i;
|
||||
uint32_t now = k_uptime_get_32();
|
||||
struct os_mbuf *buf;
|
||||
uint32_t time_diff;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
struct os_mbuf *buf;
|
||||
u32_t time_diff;
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
time_diff = now - sub->beacon_sent;
|
||||
if (time_diff < K_SECONDS(600) &&
|
||||
time_diff < BEACON_THRESHOLD(sub)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
|
||||
K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate beacon buffer");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
bt_mesh_beacon_create(sub, buf);
|
||||
|
||||
bt_mesh_adv_send(buf, &send_cb, sub);
|
||||
net_buf_unref(buf);
|
||||
time_diff = now - sub->beacon_sent;
|
||||
if (time_diff < (600 * MSEC_PER_SEC) &&
|
||||
time_diff < BEACON_THRESHOLD(sub)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate beacon buffer");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_mesh_beacon_create(sub, buf);
|
||||
|
||||
bt_mesh_adv_send(buf, &send_cb, sub);
|
||||
net_buf_unref(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unprovisioned_beacon_send(void)
|
||||
{
|
||||
const struct bt_mesh_prov *prov;
|
||||
u8_t uri_hash[16] = { 0 };
|
||||
uint8_t uri_hash[16] = { 0 };
|
||||
struct os_mbuf *buf;
|
||||
u16_t oob_info;
|
||||
uint16_t oob_info;
|
||||
|
||||
BT_DBG("unprovisioned_beacon_send");
|
||||
|
||||
@@ -202,12 +174,11 @@ static int unprovisioned_beacon_send(void)
|
||||
|
||||
static void unprovisioned_beacon_recv(struct os_mbuf *buf)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_ADV)
|
||||
const struct bt_mesh_prov *prov;
|
||||
u8_t *uuid;
|
||||
u16_t oob_info;
|
||||
u32_t uri_hash_val;
|
||||
u32_t *uri_hash = NULL;
|
||||
uint8_t *uuid;
|
||||
uint16_t oob_info;
|
||||
uint32_t uri_hash_val;
|
||||
uint32_t *uri_hash = NULL;
|
||||
|
||||
if (buf->om_len != 18 && buf->om_len != 22) {
|
||||
BT_ERR("Invalid unprovisioned beacon length (%u)", buf->om_len);
|
||||
@@ -231,13 +202,17 @@ static void unprovisioned_beacon_recv(struct os_mbuf *buf)
|
||||
(bt_mesh_prov_oob_info_t)oob_info,
|
||||
uri_hash);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sub_update_beacon_observation(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
sub->beacons_last = sub->beacons_cur;
|
||||
sub->beacons_cur = 0U;
|
||||
}
|
||||
|
||||
static void update_beacon_observation(void)
|
||||
{
|
||||
static bool first_half;
|
||||
int i;
|
||||
|
||||
/* Observation period is 20 seconds, whereas the beacon timer
|
||||
* runs every 10 seconds. We process what's happened during the
|
||||
@@ -248,23 +223,15 @@ static void update_beacon_observation(void)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sub->beacons_last = sub->beacons_cur;
|
||||
sub->beacons_cur = 0;
|
||||
}
|
||||
bt_mesh_subnet_foreach(sub_update_beacon_observation);
|
||||
}
|
||||
|
||||
static void beacon_send(struct ble_npl_event *work)
|
||||
{
|
||||
/* Don't send anything if we have an active provisioning link */
|
||||
if ((MYNEWT_VAL(BLE_MESH_PROV)) && bt_prov_active()) {
|
||||
k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) {
|
||||
k_delayed_work_submit(&beacon_timer,
|
||||
K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,34 +239,81 @@ static void beacon_send(struct ble_npl_event *work)
|
||||
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
update_beacon_observation();
|
||||
secure_beacon_send();
|
||||
(void)bt_mesh_subnet_find(secure_beacon_send, NULL);
|
||||
|
||||
/* Only resubmit if beaconing is still enabled */
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
|
||||
if (bt_mesh_beacon_enabled() ||
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) {
|
||||
k_delayed_work_submit(&beacon_timer,
|
||||
PROVISIONED_INTERVAL);
|
||||
}
|
||||
} else if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
|
||||
unprovisioned_beacon_send();
|
||||
k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(BLE_MESH_PB_ADV)) {
|
||||
unprovisioned_beacon_send();
|
||||
k_delayed_work_submit(&beacon_timer,
|
||||
K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
|
||||
}
|
||||
}
|
||||
|
||||
struct beacon_params {
|
||||
const uint8_t *net_id;
|
||||
const uint8_t *auth;
|
||||
uint32_t iv_index;
|
||||
uint8_t flags;
|
||||
|
||||
bool new_key;
|
||||
};
|
||||
|
||||
static bool auth_match(struct bt_mesh_subnet_keys *keys,
|
||||
const struct beacon_params *params)
|
||||
{
|
||||
uint8_t net_auth[8];
|
||||
|
||||
if (memcmp(params->net_id, keys->net_id, 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bt_mesh_beacon_auth(keys->beacon, params->flags, keys->net_id,
|
||||
params->iv_index, net_auth);
|
||||
|
||||
if (memcmp(params->auth, net_auth, 8)) {
|
||||
BT_WARN("Authentication Value %s != %s",
|
||||
bt_hex(params->auth, 8), bt_hex(net_auth, 8));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int subnet_by_id(struct bt_mesh_subnet *sub, void *cb_data)
|
||||
{
|
||||
struct beacon_params *params = cb_data;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(sub->keys); i++) {
|
||||
if (sub->keys[i].valid && auth_match(&sub->keys[i], params)) {
|
||||
params->new_key = (i > 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void secure_beacon_recv(struct os_mbuf *buf)
|
||||
{
|
||||
u8_t *data, *net_id, *auth;
|
||||
struct beacon_params params;
|
||||
struct bt_mesh_subnet *sub;
|
||||
u32_t iv_index;
|
||||
bool new_key, kr_change, iv_change;
|
||||
u8_t flags;
|
||||
uint8_t *data;
|
||||
|
||||
if (buf->om_len < 21) {
|
||||
BT_ERR("Too short secure beacon (len %u)", buf->om_len);
|
||||
return;
|
||||
}
|
||||
|
||||
sub = cache_check(buf->om_data);
|
||||
sub = bt_mesh_subnet_find(cache_check, buf->om_data);
|
||||
if (sub) {
|
||||
/* We've seen this beacon before - just update the stats */
|
||||
goto update_stats;
|
||||
@@ -308,27 +322,30 @@ static void secure_beacon_recv(struct os_mbuf *buf)
|
||||
/* So we can add to the cache if auth matches */
|
||||
data = buf->om_data;
|
||||
|
||||
flags = net_buf_simple_pull_u8(buf);
|
||||
net_id = net_buf_simple_pull_mem(buf, 8);
|
||||
iv_index = net_buf_simple_pull_be32(buf);
|
||||
auth = buf->om_data;
|
||||
params.flags = net_buf_simple_pull_u8(buf);
|
||||
params.net_id = net_buf_simple_pull_mem(buf, 8);
|
||||
params.iv_index = net_buf_simple_pull_be32(buf);
|
||||
params.auth = buf->om_data;
|
||||
|
||||
BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
|
||||
flags, bt_hex(net_id, 8), (unsigned) iv_index);
|
||||
params.flags, bt_hex(params.net_id, 8), params.iv_index);
|
||||
|
||||
sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
|
||||
sub = bt_mesh_subnet_find(subnet_by_id, ¶ms);
|
||||
if (!sub) {
|
||||
BT_DBG("No subnet that matched beacon");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
|
||||
if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !params.new_key) {
|
||||
BT_WARN("Ignoring Phase 2 KR Update secured using old key");
|
||||
return;
|
||||
}
|
||||
|
||||
cache_add(data, sub);
|
||||
|
||||
bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(params.flags),
|
||||
params.new_key);
|
||||
|
||||
/* If we have NetKey0 accept initiation only from it */
|
||||
if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
|
||||
sub->net_idx != BT_MESH_KEY_PRIMARY) {
|
||||
@@ -337,31 +354,18 @@ static void secure_beacon_recv(struct os_mbuf *buf)
|
||||
}
|
||||
|
||||
BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
|
||||
sub->net_idx, (unsigned) iv_index, (unsigned) bt_mesh.iv_index);
|
||||
sub->net_idx, params.iv_index, bt_mesh.iv_index);
|
||||
|
||||
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
|
||||
(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
|
||||
BT_MESH_IV_UPDATE(flags))) {
|
||||
BT_MESH_IV_UPDATE(params.flags))) {
|
||||
bt_mesh_beacon_ivu_initiator(false);
|
||||
}
|
||||
|
||||
iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
|
||||
|
||||
kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
|
||||
if (kr_change) {
|
||||
bt_mesh_net_beacon_update(sub);
|
||||
}
|
||||
|
||||
if (iv_change) {
|
||||
/* Update all subnets */
|
||||
bt_mesh_net_sec_update(NULL);
|
||||
} else if (kr_change) {
|
||||
/* Key Refresh without IV Update only impacts one subnet */
|
||||
bt_mesh_net_sec_update(sub);
|
||||
}
|
||||
bt_mesh_net_iv_update(params.iv_index, BT_MESH_IV_UPDATE(params.flags));
|
||||
|
||||
update_stats:
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
|
||||
if (bt_mesh_beacon_enabled() &&
|
||||
sub->beacons_cur < 0xff) {
|
||||
sub->beacons_cur++;
|
||||
}
|
||||
@@ -369,7 +373,7 @@ update_stats:
|
||||
|
||||
void bt_mesh_beacon_recv(struct os_mbuf *buf)
|
||||
{
|
||||
u8_t type;
|
||||
uint8_t type;
|
||||
|
||||
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
@@ -381,7 +385,9 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
|
||||
type = net_buf_simple_pull_u8(buf);
|
||||
switch (type) {
|
||||
case BEACON_TYPE_UNPROVISIONED:
|
||||
unprovisioned_beacon_recv(buf);
|
||||
if (IS_ENABLED(BLE_MESH_PB_ADV)) {
|
||||
unprovisioned_beacon_recv(buf);
|
||||
}
|
||||
break;
|
||||
case BEACON_TYPE_SECURE:
|
||||
secure_beacon_recv(buf);
|
||||
@@ -392,8 +398,38 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_update(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
uint8_t flags = bt_mesh_net_flags(sub);
|
||||
struct bt_mesh_subnet_keys *keys;
|
||||
int err;
|
||||
|
||||
keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
|
||||
|
||||
BT_DBG("NetIndex 0x%03x Using %s key", sub->net_idx,
|
||||
SUBNET_KEY_TX_IDX(sub) ? "new" : "current");
|
||||
BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index);
|
||||
|
||||
err = bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
|
||||
bt_mesh.iv_index, sub->auth);
|
||||
if (err) {
|
||||
BT_ERR("Failed updating net beacon for 0x%03x", sub->net_idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
if (evt != BT_MESH_KEY_DELETED) {
|
||||
bt_mesh_beacon_update(sub);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_init(void)
|
||||
{
|
||||
if (!bt_mesh_subnet_cb_list[1]) {
|
||||
bt_mesh_subnet_cb_list[1] = subnet_evt;
|
||||
}
|
||||
|
||||
k_delayed_work_init(&beacon_timer, beacon_send);
|
||||
}
|
||||
|
||||
@@ -402,35 +438,30 @@ void bt_mesh_beacon_ivu_initiator(bool enable)
|
||||
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable);
|
||||
|
||||
if (enable) {
|
||||
k_work_submit(&beacon_timer.work);
|
||||
} else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
|
||||
k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
|
||||
} else if (!bt_mesh_beacon_enabled()) {
|
||||
k_delayed_work_cancel(&beacon_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void subnet_beacon_enable(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
sub->beacons_last = 0U;
|
||||
sub->beacons_cur = 0U;
|
||||
|
||||
bt_mesh_beacon_update(sub);
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_enable(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!bt_mesh_is_provisioned()) {
|
||||
k_work_submit(&beacon_timer.work);
|
||||
k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
bt_mesh_subnet_foreach(subnet_beacon_enable);
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sub->beacons_last = 0;
|
||||
sub->beacons_cur = 0;
|
||||
|
||||
bt_mesh_net_beacon_update(sub);
|
||||
}
|
||||
|
||||
k_work_submit(&beacon_timer.work);
|
||||
k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_disable(void)
|
||||
|
||||
@@ -22,5 +22,6 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
struct os_mbuf *buf);
|
||||
|
||||
void bt_mesh_beacon_init(void);
|
||||
void bt_mesh_beacon_update(struct bt_mesh_subnet *sub);
|
||||
|
||||
#endif
|
||||
|
||||
389
src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c
Normal file
389
src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Tobias Svehagen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if BLE_MESH_CDB
|
||||
#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB)
|
||||
#define LOG_MODULE_NAME bt_mesh_cdb
|
||||
#include "log/log.h"
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "settings.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "mesh/glue.h"
|
||||
|
||||
|
||||
struct bt_mesh_cdb bt_mesh_cdb = {
|
||||
.nodes = {
|
||||
[0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
|
||||
.addr = BT_MESH_ADDR_UNASSIGNED,
|
||||
}
|
||||
},
|
||||
.subnets = {
|
||||
[0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
|
||||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
},
|
||||
.app_keys = {
|
||||
[0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
|
||||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if an address range from addr_start for addr_start + num_elem - 1 is
|
||||
* free for use. When a conflict is found, next will be set to the next address
|
||||
* available after the conflicting range and -EAGAIN will be returned.
|
||||
*/
|
||||
static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
|
||||
{
|
||||
uint16_t addr_end = addr_start + num_elem - 1;
|
||||
uint16_t other_start, other_end;
|
||||
int i;
|
||||
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
|
||||
!BT_MESH_ADDR_IS_UNICAST(addr_end) ||
|
||||
num_elem == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
|
||||
struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
|
||||
|
||||
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
other_start = node->addr;
|
||||
other_end = other_start + node->num_elem - 1;
|
||||
|
||||
if (!(addr_end < other_start || addr_start > other_end)) {
|
||||
if (next) {
|
||||
*next = other_end + 1;
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the lowest possible starting address that can fit num_elem elements. If
|
||||
* a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
|
||||
* returned. Otherwise the first address in the range is returned.
|
||||
*
|
||||
* NOTE: This is quite an ineffective algorithm as it might need to look
|
||||
* through the array of nodes N+2 times. A more effective algorithm
|
||||
* could be used if the nodes were stored in a sorted list.
|
||||
*/
|
||||
static uint16_t find_lowest_free_addr(uint8_t num_elem)
|
||||
{
|
||||
uint16_t addr = 1, next = 0;
|
||||
int err, i;
|
||||
|
||||
/*
|
||||
* It takes a maximum of node count + 2 to find a free address if there
|
||||
* is any. +1 for our own address and +1 for making sure that the
|
||||
* address range is valid.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
|
||||
err = addr_is_free(addr, num_elem, &next);
|
||||
if (err == 0) {
|
||||
break;
|
||||
} else if (err != -EAGAIN) {
|
||||
addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
break;
|
||||
}
|
||||
|
||||
addr = next;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
int bt_mesh_cdb_create(const uint8_t key[16])
|
||||
{
|
||||
struct bt_mesh_cdb_subnet *sub;
|
||||
|
||||
if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
|
||||
BT_MESH_CDB_VALID)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
|
||||
if (sub == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(sub->keys[0].net_key, key, 16);
|
||||
bt_mesh_cdb.iv_index = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_cdb();
|
||||
bt_mesh_store_cdb_subnet(sub);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_clear(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
|
||||
if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
|
||||
bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
|
||||
if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
|
||||
bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
|
||||
if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
|
||||
bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_cdb();
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
|
||||
{
|
||||
BT_DBG("Updating IV index to %d\n", iv_index);
|
||||
|
||||
bt_mesh_cdb.iv_index = iv_index;
|
||||
|
||||
atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
|
||||
iv_update);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_cdb();
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
|
||||
{
|
||||
struct bt_mesh_cdb_subnet *sub;
|
||||
int i;
|
||||
|
||||
if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
|
||||
sub = &bt_mesh_cdb.subnets[i];
|
||||
|
||||
if (sub->net_idx != BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sub->net_idx = net_idx;
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
|
||||
{
|
||||
BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
|
||||
bt_mesh_clear_cdb_subnet(sub);
|
||||
}
|
||||
|
||||
sub->net_idx = BT_MESH_KEY_UNUSED;
|
||||
memset(sub->keys, 0, sizeof(sub->keys));
|
||||
}
|
||||
|
||||
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
|
||||
if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
|
||||
return &bt_mesh_cdb.subnets[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
|
||||
{
|
||||
if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_cdb_subnet(sub);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
|
||||
{
|
||||
uint8_t flags = 0x00;
|
||||
|
||||
if (sub && sub->kr_flag) {
|
||||
flags |= BT_MESH_NET_FLAG_KR;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
|
||||
flags |= BT_MESH_NET_FLAG_IVU;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
|
||||
uint8_t num_elem, uint16_t net_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
addr = find_lowest_free_addr(num_elem);
|
||||
if (addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (addr_is_free(addr, num_elem, NULL) < 0) {
|
||||
BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
|
||||
addr + num_elem - 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
|
||||
struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
|
||||
|
||||
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
memcpy(node->uuid, uuid, 16);
|
||||
node->addr = addr;
|
||||
node->num_elem = num_elem;
|
||||
node->net_idx = net_idx;
|
||||
atomic_set(node->flags, 0);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
|
||||
{
|
||||
BT_DBG("Node addr 0x%04x store %u", node->addr, store);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
|
||||
bt_mesh_clear_cdb_node(node);
|
||||
}
|
||||
|
||||
node->addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
memset(node->dev_key, 0, sizeof(node->dev_key));
|
||||
}
|
||||
|
||||
struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
|
||||
struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
|
||||
|
||||
if (addr >= node->addr &&
|
||||
addr <= node->addr + node->num_elem - 1) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
|
||||
{
|
||||
if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_cdb_node(node);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
|
||||
if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (func(&bt_mesh_cdb.nodes[i], user_data) ==
|
||||
BT_MESH_CDB_ITER_STOP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
|
||||
uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_cdb_app_key *key;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
|
||||
key = &bt_mesh_cdb.app_keys[i];
|
||||
|
||||
if (key->net_idx != BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key->net_idx = net_idx;
|
||||
key->app_idx = app_idx;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
|
||||
{
|
||||
BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
|
||||
bt_mesh_clear_cdb_app_key(key);
|
||||
}
|
||||
|
||||
key->net_idx = BT_MESH_ADDR_UNASSIGNED;
|
||||
memset(key->keys, 0, sizeof(key->keys));
|
||||
}
|
||||
|
||||
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
|
||||
struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
|
||||
|
||||
if (key->net_idx != BT_MESH_KEY_UNUSED &&
|
||||
key->app_idx == app_idx) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
|
||||
{
|
||||
if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_cdb_app_key(key);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
267
src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c
Normal file
267
src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "beacon.h"
|
||||
#include "settings.h"
|
||||
#include "heartbeat.h"
|
||||
#include "friend.h"
|
||||
#include "cfg.h"
|
||||
#include "mesh/glue.h"
|
||||
|
||||
void bt_mesh_beacon_set(bool beacon)
|
||||
{
|
||||
if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) {
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon);
|
||||
|
||||
if (beacon) {
|
||||
bt_mesh_beacon_enable();
|
||||
} else {
|
||||
bt_mesh_beacon_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
bt_mesh_store_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
bool bt_mesh_beacon_enabled(void)
|
||||
{
|
||||
return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON);
|
||||
}
|
||||
|
||||
static int feature_set(int feature_flag, enum bt_mesh_feat_state state)
|
||||
{
|
||||
if (state != BT_MESH_FEATURE_DISABLED &&
|
||||
state != BT_MESH_FEATURE_ENABLED) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_mesh.flags, feature_flag) ==
|
||||
(state == BT_MESH_FEATURE_ENABLED)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
atomic_set_bit_to(bt_mesh.flags, feature_flag,
|
||||
(state == BT_MESH_FEATURE_ENABLED));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum bt_mesh_feat_state feature_get(int feature_flag)
|
||||
{
|
||||
return atomic_test_bit(bt_mesh.flags, feature_flag) ?
|
||||
BT_MESH_FEATURE_ENABLED :
|
||||
BT_MESH_FEATURE_DISABLED;
|
||||
}
|
||||
|
||||
int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
bt_mesh_store_cfg();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
|
||||
return BT_MESH_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return feature_get(BT_MESH_GATT_PROXY);
|
||||
}
|
||||
|
||||
int bt_mesh_default_ttl_set(uint8_t default_ttl)
|
||||
{
|
||||
if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (default_ttl == bt_mesh.default_ttl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bt_mesh.default_ttl = default_ttl;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
bt_mesh_store_cfg();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_default_ttl_get(void)
|
||||
{
|
||||
return bt_mesh.default_ttl;
|
||||
}
|
||||
|
||||
int bt_mesh_friend_set(enum bt_mesh_feat_state friendship)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
err = feature_set(BT_MESH_FRIEND, friendship);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
bt_mesh_store_cfg();
|
||||
}
|
||||
|
||||
if (friendship == BT_MESH_FEATURE_DISABLED) {
|
||||
bt_mesh_friends_clear();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum bt_mesh_feat_state bt_mesh_friend_get(void)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
|
||||
return BT_MESH_FEATURE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return feature_get(BT_MESH_FRIEND);
|
||||
}
|
||||
|
||||
void bt_mesh_net_transmit_set(uint8_t xmit)
|
||||
{
|
||||
if (bt_mesh.net_xmit == xmit) {
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh.net_xmit = xmit;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
bt_mesh_store_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_net_transmit_get(void)
|
||||
{
|
||||
return bt_mesh.net_xmit;
|
||||
}
|
||||
|
||||
int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!CONFIG_BT_MESH_RELAY) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
err = feature_set(BT_MESH_RELAY, relay);
|
||||
if (err == -EINVAL) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (err == -EALREADY && bt_mesh.relay_xmit == xmit) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
bt_mesh.relay_xmit = xmit;
|
||||
bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
bt_mesh_store_cfg();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum bt_mesh_feat_state bt_mesh_relay_get(void)
|
||||
{
|
||||
return feature_get(BT_MESH_RELAY);
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_relay_retransmit_get(void)
|
||||
{
|
||||
if (!CONFIG_BT_MESH_RELAY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bt_mesh.relay_xmit;
|
||||
}
|
||||
|
||||
bool bt_mesh_fixed_group_match(uint16_t addr)
|
||||
{
|
||||
/* Check for fixed group addresses */
|
||||
switch (addr) {
|
||||
case BT_MESH_ADDR_ALL_NODES:
|
||||
return true;
|
||||
case BT_MESH_ADDR_PROXIES:
|
||||
return (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED);
|
||||
case BT_MESH_ADDR_FRIENDS:
|
||||
return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED);
|
||||
case BT_MESH_ADDR_RELAYS:
|
||||
return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_cfg_init(void)
|
||||
{
|
||||
bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL;
|
||||
bt_mesh.net_xmit =
|
||||
BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT,
|
||||
CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL);
|
||||
|
||||
#if defined(CONFIG_BT_MESH_RELAY)
|
||||
bt_mesh.relay_xmit =
|
||||
BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT,
|
||||
CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL);
|
||||
#endif
|
||||
|
||||
if (CONFIG_BT_MESH_RELAY_ENABLED) {
|
||||
atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY);
|
||||
}
|
||||
|
||||
if (CONFIG_BT_MESH_BEACON_ENABLED) {
|
||||
atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON);
|
||||
}
|
||||
|
||||
if (CONFIG_BT_MESH_GATT_PROXY_ENABLED) {
|
||||
atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY);
|
||||
}
|
||||
|
||||
if (CONFIG_BT_MESH_FRIEND_ENABLED) {
|
||||
atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND);
|
||||
}
|
||||
}
|
||||
9
src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h
Normal file
9
src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void bt_mesh_cfg_init(void);
|
||||
|
||||
bool bt_mesh_fixed_group_match(uint16_t addr);
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -24,8 +24,8 @@
|
||||
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
|
||||
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
|
||||
|
||||
int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
|
||||
size_t sg_len, u8_t mac[16])
|
||||
int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
|
||||
size_t sg_len, uint8_t mac[16])
|
||||
{
|
||||
struct tc_aes_key_sched_struct sched;
|
||||
struct tc_cmac_struct state;
|
||||
@@ -48,8 +48,8 @@ int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
|
||||
const char *info, u8_t okm[16])
|
||||
int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
|
||||
const char *info, uint8_t okm[16])
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -61,14 +61,14 @@ int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
|
||||
return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm);
|
||||
}
|
||||
|
||||
int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
|
||||
u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16])
|
||||
int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
|
||||
uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16])
|
||||
{
|
||||
struct bt_mesh_sg sg[3];
|
||||
u8_t salt[16];
|
||||
u8_t out[16];
|
||||
u8_t t[16];
|
||||
u8_t pad;
|
||||
uint8_t salt[16];
|
||||
uint8_t out[16];
|
||||
uint8_t t[16];
|
||||
uint8_t pad;
|
||||
int err;
|
||||
|
||||
BT_DBG("n %s", bt_hex(n, 16));
|
||||
@@ -126,11 +126,11 @@ int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_k3(const u8_t n[16], u8_t out[8])
|
||||
int bt_mesh_k3(const uint8_t n[16], uint8_t out[8])
|
||||
{
|
||||
u8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
|
||||
u8_t tmp[16];
|
||||
u8_t t[16];
|
||||
uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
|
||||
uint8_t tmp[16];
|
||||
uint8_t t[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1("smk3", tmp);
|
||||
@@ -153,11 +153,11 @@ int bt_mesh_k3(const u8_t n[16], u8_t out[8])
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_k4(const u8_t n[16], u8_t out[1])
|
||||
int bt_mesh_k4(const uint8_t n[16], uint8_t out[1])
|
||||
{
|
||||
u8_t id6[] = { 'i', 'd', '6', 0x01 };
|
||||
u8_t tmp[16];
|
||||
u8_t t[16];
|
||||
uint8_t id6[] = { 'i', 'd', '6', 0x01 };
|
||||
uint8_t tmp[16];
|
||||
uint8_t t[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1("smk4", tmp);
|
||||
@@ -180,10 +180,10 @@ int bt_mesh_k4(const u8_t n[16], u8_t out[1])
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
|
||||
int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
|
||||
{
|
||||
const char *id128 = "id128\x01";
|
||||
u8_t salt[16];
|
||||
uint8_t salt[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1(s, salt);
|
||||
@@ -194,326 +194,8 @@ int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
|
||||
return bt_mesh_k1(n, 16, salt, id128, out);
|
||||
}
|
||||
|
||||
static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t *enc_msg, size_t msg_len,
|
||||
const u8_t *aad, size_t aad_len,
|
||||
u8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
u8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16], mic[16];
|
||||
u16_t last_blk, blk_cnt;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
if (msg_len < 1 || aad_len >= 0xff00) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(0x0000, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmic);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* X_0 = e(AppKey, 0x09 || nonce || length) */
|
||||
if (mic_size == sizeof(u64_t)) {
|
||||
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
|
||||
} else {
|
||||
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
|
||||
}
|
||||
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(msg_len, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, pmsg);
|
||||
|
||||
for (i = 0; i < sizeof(u16_t); i++) {
|
||||
pmsg[i] = Xn[i] ^ pmsg[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(u16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aad_len; i++, j++) {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
pmsg[i] = Xn[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16;
|
||||
}
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
if (j + 1 == blk_cnt) {
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
|
||||
memcpy(out_msg + (j * 16), msg, last_blk);
|
||||
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[i];
|
||||
}
|
||||
|
||||
for (i = last_blk; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ 0x00;
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < sizeof(mic); i++) {
|
||||
mic[i] = cmic[i] ^ Xn[i];
|
||||
}
|
||||
} else {
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
for (i = 0; i < 16; i++) {
|
||||
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
|
||||
memcpy(out_msg + (j * 16), msg, 16);
|
||||
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(mic, enc_msg + msg_len, mic_size)) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t *msg, size_t msg_len,
|
||||
const u8_t *aad, size_t aad_len,
|
||||
u8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
u8_t pmsg[16], cmic[16], cmsg[16], mic[16], Xn[16];
|
||||
u16_t blk_cnt, last_blk;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
BT_DBG("key %s", bt_hex(key, 16));
|
||||
BT_DBG("nonce %s", bt_hex(nonce, 13));
|
||||
BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
|
||||
BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
|
||||
|
||||
/* Unsupported AAD size */
|
||||
if (aad_len >= 0xff00) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(0x0000, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmic);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* X_0 = e(AppKey, 0x09 || nonce || length) */
|
||||
if (mic_size == sizeof(u64_t)) {
|
||||
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
|
||||
} else {
|
||||
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
|
||||
}
|
||||
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(msg_len, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, pmsg);
|
||||
|
||||
for (i = 0; i < sizeof(u16_t); i++) {
|
||||
pmsg[i] = Xn[i] ^ pmsg[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(u16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aad_len; i++, j++) {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
pmsg[i] = Xn[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16;
|
||||
}
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
if (j + 1 == blk_cnt) {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
|
||||
}
|
||||
for (i = last_blk; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ 0x00;
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < sizeof(mic); i++) {
|
||||
mic[i] = cmic[i] ^ Xn[i];
|
||||
}
|
||||
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
} else {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_N */
|
||||
for (i = 0; i < 16; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(out_msg + msg_len, mic, mic_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
u32_t iv_index)
|
||||
static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
|
||||
uint32_t iv_index)
|
||||
{
|
||||
/* Nonce Type */
|
||||
nonce[0] = 0x03;
|
||||
@@ -538,8 +220,8 @@ static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
|
||||
static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
u32_t iv_index)
|
||||
static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu,
|
||||
uint32_t iv_index)
|
||||
{
|
||||
/* Nonce Type */
|
||||
nonce[0] = 0x00;
|
||||
@@ -564,11 +246,11 @@ static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
|
||||
int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
|
||||
const u8_t privacy_key[16])
|
||||
int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
|
||||
const uint8_t privacy_key[16])
|
||||
{
|
||||
u8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||
u8_t tmp[16];
|
||||
uint8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||
uint8_t tmp[16];
|
||||
int err, i;
|
||||
|
||||
BT_DBG("IVIndex %u, PrivacyKey %s", (unsigned) iv_index,
|
||||
@@ -591,11 +273,11 @@ int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
u32_t iv_index, bool proxy)
|
||||
int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
|
||||
uint32_t iv_index, bool proxy)
|
||||
{
|
||||
u8_t mic_len = NET_MIC_LEN(buf->om_data);
|
||||
u8_t nonce[13];
|
||||
uint8_t mic_len = NET_MIC_LEN(buf->om_data);
|
||||
uint8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("IVIndex %u EncKey %s mic_len %u", (unsigned) iv_index,
|
||||
@@ -610,7 +292,7 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
|
||||
err = bt_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
|
||||
NULL, 0, &buf->om_data[7], mic_len);
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, mic_len);
|
||||
@@ -619,11 +301,11 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
u32_t iv_index, bool proxy)
|
||||
int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
|
||||
uint32_t iv_index, bool proxy)
|
||||
{
|
||||
u8_t mic_len = NET_MIC_LEN(buf->om_data);
|
||||
u8_t nonce[13];
|
||||
uint8_t mic_len = NET_MIC_LEN(buf->om_data);
|
||||
uint8_t nonce[13];
|
||||
|
||||
BT_DBG("PDU (%u bytes) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
BT_DBG("iv_index %u, key %s mic_len %u", (unsigned) iv_index,
|
||||
@@ -639,118 +321,74 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
|
||||
buf->om_len -= mic_len;
|
||||
|
||||
return bt_mesh_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
|
||||
return bt_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
|
||||
NULL, 0, &buf->om_data[7], mic_len);
|
||||
}
|
||||
|
||||
static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
|
||||
u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
static void create_app_nonce(uint8_t nonce[13],
|
||||
const struct bt_mesh_app_crypto_ctx *ctx)
|
||||
{
|
||||
if (dev_key) {
|
||||
if (ctx->dev_key) {
|
||||
nonce[0] = 0x02;
|
||||
} else {
|
||||
nonce[0] = 0x01;
|
||||
}
|
||||
|
||||
sys_put_be32((seq_num | ((u32_t)aszmic << 31)), &nonce[1]);
|
||||
sys_put_be32((ctx->seq_num | ((uint32_t)ctx->aszmic << 31)), &nonce[1]);
|
||||
|
||||
sys_put_be16(src, &nonce[5]);
|
||||
sys_put_be16(dst, &nonce[7]);
|
||||
sys_put_be16(ctx->src, &nonce[5]);
|
||||
sys_put_be16(ctx->dst, &nonce[7]);
|
||||
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
sys_put_be32(ctx->iv_index, &nonce[9]);
|
||||
}
|
||||
|
||||
static int mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
int bt_mesh_app_encrypt(const uint8_t key[16],
|
||||
const struct bt_mesh_app_crypto_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
uint8_t nonce[13];
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
|
||||
BT_DBG("seq_num 0x%08x iv_index 0x%08x", (unsigned) seq_num,
|
||||
(unsigned) iv_index);
|
||||
BT_DBG("dev_key %u src 0x%04x dst 0x%04x", ctx->dev_key, ctx->src,
|
||||
ctx->dst);
|
||||
BT_DBG("seq_num 0x%08x iv_index 0x%08x", ctx->seq_num, ctx->iv_index);
|
||||
BT_DBG("Clear: %s", bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
|
||||
create_app_nonce(nonce, ctx);
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
return bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad,
|
||||
ad ? 16 : 0, buf->om_data,
|
||||
APP_MIC_LEN(aszmic));
|
||||
}
|
||||
err = bt_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
|
||||
ctx->ad ? 16 : 0, buf->om_data,
|
||||
APP_MIC_LEN(ctx->aszmic));
|
||||
|
||||
int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
|
||||
seq_num, iv_index);
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, APP_MIC_LEN(ctx->aszmic));
|
||||
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
int bt_mesh_app_decrypt(const uint8_t key[16],
|
||||
const struct bt_mesh_app_crypto_ctx *ctx,
|
||||
struct os_mbuf *buf, struct os_mbuf *out)
|
||||
{
|
||||
uint8_t nonce[13];
|
||||
int err;
|
||||
|
||||
err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
|
||||
seq_num, iv_index);
|
||||
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
|
||||
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, struct os_mbuf *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst,
|
||||
u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
|
||||
BT_DBG("EncData (len %u) %s", buf->om_len,
|
||||
bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
|
||||
create_app_nonce(nonce, ctx);
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
return bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad,
|
||||
ad ? 16 : 0, out->om_data,
|
||||
APP_MIC_LEN(aszmic));
|
||||
}
|
||||
|
||||
int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
return mesh_app_decrypt(key, dev_key, aszmic, buf, buf,
|
||||
ad, src, dst, seq_num, iv_index);
|
||||
}
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, struct os_mbuf *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mesh_app_decrypt(key, dev_key, aszmic, buf, out,
|
||||
ad, src, dst, seq_num, iv_index);
|
||||
err = bt_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
|
||||
ctx->ad ? 16 : 0, out->om_data,
|
||||
APP_MIC_LEN(ctx->aszmic));
|
||||
if (!err) {
|
||||
net_buf_simple_add(out, buf->om_len);
|
||||
}
|
||||
@@ -759,7 +397,7 @@ int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
}
|
||||
|
||||
/* reversed, 8-bit, poly=0x07 */
|
||||
static const u8_t crc_table[256] = {
|
||||
static const uint8_t crc_table[256] = {
|
||||
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
|
||||
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
|
||||
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
|
||||
@@ -801,9 +439,9 @@ static const u8_t crc_table[256] = {
|
||||
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
|
||||
};
|
||||
|
||||
u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
|
||||
uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len)
|
||||
{
|
||||
u8_t fcs = 0xff;
|
||||
uint8_t fcs = 0xff;
|
||||
|
||||
while (data_len--) {
|
||||
fcs = crc_table[fcs ^ *data++];
|
||||
@@ -814,11 +452,11 @@ u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
|
||||
return 0xff - fcs;
|
||||
}
|
||||
|
||||
bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
|
||||
bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs)
|
||||
{
|
||||
const u8_t *data = buf->om_data;
|
||||
u16_t data_len = buf->om_len;
|
||||
u8_t fcs = 0xff;
|
||||
const uint8_t *data = buf->om_data;
|
||||
uint16_t data_len = buf->om_len;
|
||||
uint8_t fcs = 0xff;
|
||||
|
||||
while (data_len--) {
|
||||
fcs = crc_table[fcs ^ *data++];
|
||||
@@ -827,10 +465,10 @@ bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
|
||||
return crc_table[fcs ^ received_fcs] == 0xcf;
|
||||
}
|
||||
|
||||
int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
|
||||
int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr)
|
||||
{
|
||||
u8_t salt[16];
|
||||
u8_t tmp[16];
|
||||
uint8_t salt[16];
|
||||
uint8_t tmp[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1("vtad", salt);
|
||||
@@ -848,21 +486,21 @@ int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16])
|
||||
int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16])
|
||||
{
|
||||
const u8_t conf_salt_key[16] = { 0 };
|
||||
const uint8_t conf_salt_key[16] = { 0 };
|
||||
|
||||
return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
|
||||
u8_t conf_key[16])
|
||||
int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
|
||||
uint8_t conf_key[16])
|
||||
{
|
||||
return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
|
||||
const u8_t auth[16], u8_t conf[16])
|
||||
int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
|
||||
const uint8_t auth[16], uint8_t conf[16])
|
||||
{
|
||||
struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } };
|
||||
|
||||
@@ -873,23 +511,23 @@ int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
|
||||
return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25 + 8], u8_t out[25])
|
||||
int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t data[25 + 8], uint8_t out[25])
|
||||
{
|
||||
return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
return bt_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25], u8_t out[25 + 8])
|
||||
int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t data[25], uint8_t out[25 + 8])
|
||||
{
|
||||
return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
return bt_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
}
|
||||
|
||||
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
||||
const u8_t net_id[8], u32_t iv_index,
|
||||
u8_t auth[8])
|
||||
int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
|
||||
const uint8_t net_id[8], uint32_t iv_index,
|
||||
uint8_t auth[8])
|
||||
{
|
||||
u8_t msg[13], tmp[16];
|
||||
uint8_t msg[13], tmp[16];
|
||||
int err;
|
||||
|
||||
BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16));
|
||||
|
||||
@@ -15,81 +15,81 @@ struct bt_mesh_sg {
|
||||
size_t len;
|
||||
};
|
||||
|
||||
int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
|
||||
size_t sg_len, u8_t mac[16]);
|
||||
int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
|
||||
size_t sg_len, uint8_t mac[16]);
|
||||
|
||||
static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m,
|
||||
size_t len, u8_t mac[16])
|
||||
static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
|
||||
size_t len, uint8_t mac[16])
|
||||
{
|
||||
struct bt_mesh_sg sg = { m, len };
|
||||
|
||||
return bt_mesh_aes_cmac(key, &sg, 1, mac);
|
||||
}
|
||||
|
||||
static inline bool bt_mesh_s1(const char *m, u8_t salt[16])
|
||||
static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
|
||||
{
|
||||
const u8_t zero[16] = { 0 };
|
||||
const uint8_t zero[16] = { 0 };
|
||||
|
||||
return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
|
||||
}
|
||||
|
||||
int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
|
||||
const char *info, u8_t okm[16]);
|
||||
int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
|
||||
const char *info, uint8_t okm[16]);
|
||||
|
||||
#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
|
||||
({ \
|
||||
const u8_t salt[16] = salt_str; \
|
||||
const uint8_t salt[16] = salt_str; \
|
||||
bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
|
||||
})
|
||||
|
||||
int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
|
||||
u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]);
|
||||
int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
|
||||
uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]);
|
||||
|
||||
int bt_mesh_k3(const u8_t n[16], u8_t out[8]);
|
||||
int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]);
|
||||
|
||||
int bt_mesh_k4(const u8_t n[16], u8_t out[1]);
|
||||
int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]);
|
||||
|
||||
int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]);
|
||||
int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]);
|
||||
|
||||
static inline int bt_mesh_id_resolving_key(const u8_t net_key[16],
|
||||
u8_t resolving_key[16])
|
||||
static inline int bt_mesh_id_resolving_key(const uint8_t net_key[16],
|
||||
uint8_t resolving_key[16])
|
||||
{
|
||||
return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_identity_key(const u8_t net_key[16],
|
||||
u8_t identity_key[16])
|
||||
static inline int bt_mesh_identity_key(const uint8_t net_key[16],
|
||||
uint8_t identity_key[16])
|
||||
{
|
||||
return bt_mesh_id128(net_key, "nkik", identity_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_beacon_key(const u8_t net_key[16],
|
||||
u8_t beacon_key[16])
|
||||
static inline int bt_mesh_beacon_key(const uint8_t net_key[16],
|
||||
uint8_t beacon_key[16])
|
||||
{
|
||||
return bt_mesh_id128(net_key, "nkbk", beacon_key);
|
||||
}
|
||||
|
||||
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
||||
const u8_t net_id[16], u32_t iv_index,
|
||||
u8_t auth[8]);
|
||||
int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
|
||||
const uint8_t net_id[16], uint32_t iv_index,
|
||||
uint8_t auth[8]);
|
||||
|
||||
static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
|
||||
static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1])
|
||||
{
|
||||
return bt_mesh_k4(app_key, app_id);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_session_key(const u8_t dhkey[32],
|
||||
const u8_t prov_salt[16],
|
||||
u8_t session_key[16])
|
||||
static inline int bt_mesh_session_key(const uint8_t dhkey[32],
|
||||
const uint8_t prov_salt[16],
|
||||
uint8_t session_key[16])
|
||||
{
|
||||
return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
|
||||
const u8_t prov_salt[16],
|
||||
u8_t nonce[13])
|
||||
static inline int bt_mesh_prov_nonce(const uint8_t dhkey[32],
|
||||
const uint8_t prov_salt[16],
|
||||
uint8_t nonce[13])
|
||||
{
|
||||
u8_t tmp[16];
|
||||
uint8_t tmp[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
|
||||
@@ -100,19 +100,19 @@ static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int bt_mesh_dev_key(const u8_t dhkey[32],
|
||||
const u8_t prov_salt[16],
|
||||
u8_t dev_key[16])
|
||||
static inline int bt_mesh_dev_key(const uint8_t dhkey[32],
|
||||
const uint8_t prov_salt[16],
|
||||
uint8_t dev_key[16])
|
||||
{
|
||||
return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
|
||||
const u8_t prov_rand[16],
|
||||
const u8_t dev_rand[16],
|
||||
u8_t prov_salt[16])
|
||||
static inline int bt_mesh_prov_salt(const uint8_t conf_salt[16],
|
||||
const uint8_t prov_rand[16],
|
||||
const uint8_t dev_rand[16],
|
||||
uint8_t prov_salt[16])
|
||||
{
|
||||
const u8_t prov_salt_key[16] = { 0 };
|
||||
const uint8_t prov_salt_key[16] = { 0 };
|
||||
struct bt_mesh_sg sg[] = {
|
||||
{ conf_salt, 16 },
|
||||
{ prov_rand, 16 },
|
||||
@@ -122,49 +122,50 @@ static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
|
||||
return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
|
||||
}
|
||||
|
||||
int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
|
||||
const u8_t privacy_key[16]);
|
||||
int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
|
||||
const uint8_t privacy_key[16]);
|
||||
|
||||
int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
u32_t iv_index, bool proxy);
|
||||
int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
|
||||
uint32_t iv_index, bool proxy);
|
||||
|
||||
int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
u32_t iv_index, bool proxy);
|
||||
int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
|
||||
uint32_t iv_index, bool proxy);
|
||||
|
||||
int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf*buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
struct bt_mesh_app_crypto_ctx {
|
||||
bool dev_key;
|
||||
uint8_t aszmic;
|
||||
uint16_t src;
|
||||
uint16_t dst;
|
||||
uint32_t seq_num;
|
||||
uint32_t iv_index;
|
||||
const uint8_t *ad;
|
||||
};
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf*buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
int bt_mesh_app_encrypt(const uint8_t key[16],
|
||||
const struct bt_mesh_app_crypto_ctx *ctx,
|
||||
struct os_mbuf *buf);
|
||||
|
||||
int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
int bt_mesh_app_decrypt(const uint8_t key[16],
|
||||
const struct bt_mesh_app_crypto_ctx *ctx,
|
||||
struct os_mbuf *buf, struct os_mbuf *out);
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf*buf, struct os_mbuf*out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index);
|
||||
uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len);
|
||||
|
||||
u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);
|
||||
bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs);
|
||||
|
||||
bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs);
|
||||
int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr);
|
||||
|
||||
int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr);
|
||||
int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]);
|
||||
|
||||
int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]);
|
||||
int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
|
||||
uint8_t conf_key[16]);
|
||||
|
||||
int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
|
||||
u8_t conf_key[16]);
|
||||
int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
|
||||
const uint8_t auth[16], uint8_t conf[16]);
|
||||
|
||||
int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
|
||||
const u8_t auth[16], u8_t conf[16]);
|
||||
int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t data[25 + 8], uint8_t out[25]);
|
||||
|
||||
int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25 + 8], u8_t out[25]);
|
||||
|
||||
int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25], u8_t out[25 + 8]);
|
||||
int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t data[25], uint8_t out[25 + 8]);
|
||||
#endif
|
||||
|
||||
@@ -115,57 +115,23 @@
|
||||
#define STATUS_UNSPECIFIED 0x10
|
||||
#define STATUS_INVALID_BINDING 0x11
|
||||
|
||||
enum {
|
||||
BT_MESH_VA_CHANGED, /* Label information changed */
|
||||
};
|
||||
|
||||
struct label {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
atomic_t flags[1];
|
||||
};
|
||||
|
||||
void bt_mesh_cfg_reset(void);
|
||||
|
||||
void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
|
||||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
|
||||
|
||||
struct label *get_label(u16_t index);
|
||||
|
||||
u8_t *bt_mesh_label_uuid_get(u16_t addr);
|
||||
|
||||
struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
|
||||
void bt_mesh_hb_pub_disable(void);
|
||||
struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void);
|
||||
|
||||
u8_t bt_mesh_net_transmit_get(void);
|
||||
u8_t bt_mesh_relay_get(void);
|
||||
u8_t bt_mesh_friend_get(void);
|
||||
u8_t bt_mesh_relay_retransmit_get(void);
|
||||
u8_t bt_mesh_beacon_get(void);
|
||||
u8_t bt_mesh_gatt_proxy_get(void);
|
||||
u8_t bt_mesh_default_ttl_get(void);
|
||||
|
||||
void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store);
|
||||
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx);
|
||||
void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store);
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time);
|
||||
|
||||
static inline void key_idx_pack(struct os_mbuf *buf,
|
||||
u16_t idx1, u16_t idx2)
|
||||
uint16_t idx1, uint16_t idx2)
|
||||
{
|
||||
net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12));
|
||||
net_buf_simple_add_u8(buf, idx2 >> 4);
|
||||
}
|
||||
|
||||
static inline void key_idx_unpack(struct os_mbuf *buf,
|
||||
u16_t *idx1, u16_t *idx2)
|
||||
uint16_t *idx1, uint16_t *idx2)
|
||||
{
|
||||
*idx1 = sys_get_le16(&buf->om_data[0]) & 0xfff;
|
||||
*idx2 = sys_get_le16(&buf->om_data[1]) >> 4;
|
||||
net_buf_simple_pull(buf, 3);
|
||||
net_buf_simple_pull_mem(buf, 3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,29 +17,29 @@ enum bt_mesh_friend_pdu_type {
|
||||
BT_MESH_FRIEND_PDU_COMPLETE,
|
||||
};
|
||||
|
||||
bool bt_mesh_friend_match(u16_t net_idx, u16_t addr);
|
||||
bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr);
|
||||
|
||||
struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
|
||||
struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
|
||||
bool valid, bool established);
|
||||
|
||||
bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
|
||||
u64_t *seq_auth, u8_t seg_count);
|
||||
bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
|
||||
uint64_t *seq_auth, uint8_t seg_count);
|
||||
|
||||
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
uint64_t *seq_auth, uint8_t seg_count,
|
||||
struct os_mbuf *sbuf);
|
||||
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
uint64_t *seq_auth, uint8_t seg_count,
|
||||
struct os_mbuf *sbuf);
|
||||
|
||||
void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
|
||||
u16_t dst, u64_t *seq_auth);
|
||||
void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
|
||||
uint16_t dst, uint64_t *seq_auth);
|
||||
|
||||
void bt_mesh_friend_sec_update(u16_t net_idx);
|
||||
void bt_mesh_friend_sec_update(uint16_t net_idx);
|
||||
|
||||
void bt_mesh_friend_clear_net_idx(u16_t net_idx);
|
||||
void bt_mesh_friends_clear(void);
|
||||
|
||||
int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
|
||||
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "base64/base64.h"
|
||||
#endif
|
||||
|
||||
extern u8_t g_mesh_addr_type;
|
||||
extern uint8_t g_mesh_addr_type;
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/* Store configuration for different bearers */
|
||||
@@ -44,8 +44,8 @@ bt_hex(const void *buf, size_t len)
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
static char hexbufs[4][137];
|
||||
static u8_t curbuf;
|
||||
const u8_t *b = buf;
|
||||
static uint8_t curbuf;
|
||||
const uint8_t *b = buf;
|
||||
char *str;
|
||||
int i;
|
||||
|
||||
@@ -214,6 +214,14 @@ net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val)
|
||||
ASSERT_NOT_CHAIN(om);
|
||||
}
|
||||
|
||||
void
|
||||
net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val)
|
||||
{
|
||||
val = htole32(val);
|
||||
os_mbuf_append(om, &val, 3);
|
||||
ASSERT_NOT_CHAIN(om);
|
||||
}
|
||||
|
||||
void
|
||||
net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val)
|
||||
{
|
||||
@@ -269,6 +277,22 @@ net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val)
|
||||
ASSERT_NOT_CHAIN(om);
|
||||
}
|
||||
|
||||
void
|
||||
net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val)
|
||||
{
|
||||
uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len];
|
||||
|
||||
assert(headroom >= 3);
|
||||
om->om_data -= 3;
|
||||
put_be24(om->om_data, val);
|
||||
om->om_len += 3;
|
||||
|
||||
if (om->om_pkthdr_len) {
|
||||
OS_MBUF_PKTHDR(om)->omp_len += 3;
|
||||
}
|
||||
ASSERT_NOT_CHAIN(om);
|
||||
}
|
||||
|
||||
void
|
||||
net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val)
|
||||
{
|
||||
@@ -333,7 +357,7 @@ k_fifo_is_empty(struct ble_npl_eventq *q)
|
||||
return ble_npl_eventq_is_empty(q);
|
||||
}
|
||||
|
||||
void * net_buf_get(struct ble_npl_eventq *fifo, s32_t t)
|
||||
void * net_buf_get(struct ble_npl_eventq *fifo, int32_t t)
|
||||
{
|
||||
struct ble_npl_event *ev = ble_npl_eventq_get(fifo, 0);
|
||||
|
||||
@@ -384,6 +408,12 @@ k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
k_delayed_work_pending(struct k_delayed_work *w)
|
||||
{
|
||||
return ble_npl_callout_is_active(&w->work);
|
||||
}
|
||||
|
||||
void
|
||||
k_delayed_work_cancel(struct k_delayed_work *w)
|
||||
{
|
||||
@@ -440,7 +470,7 @@ int64_t k_uptime_get(void)
|
||||
return ble_npl_time_ticks_to_ms32(ble_npl_time_get());
|
||||
}
|
||||
|
||||
u32_t k_uptime_get_32(void)
|
||||
uint32_t k_uptime_get_32(void)
|
||||
{
|
||||
return k_uptime_get();
|
||||
}
|
||||
@@ -459,7 +489,7 @@ static uint8_t priv[32];
|
||||
static bool has_pub = false;
|
||||
|
||||
int
|
||||
bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
|
||||
bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
|
||||
{
|
||||
uint8_t dh[32];
|
||||
|
||||
@@ -510,7 +540,7 @@ bt_pub_key_get(void)
|
||||
}
|
||||
|
||||
static int
|
||||
set_ad(const struct bt_data *ad, size_t ad_len, u8_t *buf, u8_t *buf_len)
|
||||
set_ad(const struct bt_data *ad, size_t ad_len, uint8_t *buf, uint8_t *buf_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -846,6 +876,52 @@ void net_buf_slist_merge_slist(struct net_buf_slist_t *list,
|
||||
}
|
||||
}
|
||||
|
||||
/** Memory slab methods */
|
||||
extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
|
||||
{
|
||||
**(char ***)mem = slab->free_list;
|
||||
slab->free_list = *(char **)mem;
|
||||
slab->num_used--;
|
||||
}
|
||||
|
||||
extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (slab->free_list != NULL) {
|
||||
/* take a free block */
|
||||
*mem = slab->free_list;
|
||||
slab->free_list = *(char **)(slab->free_list);
|
||||
slab->num_used++;
|
||||
result = 0;
|
||||
} else {
|
||||
*mem = NULL;
|
||||
result = -ENOMEM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int create_free_list(struct k_mem_slab *slab)
|
||||
{
|
||||
uint32_t j;
|
||||
char *p;
|
||||
|
||||
if(((slab->block_size | (uintptr_t)slab->buffer) &
|
||||
(sizeof(void *) - 1)) != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
slab->free_list = NULL;
|
||||
p = slab->buffer;
|
||||
|
||||
for (j = 0U; j < slab->num_blocks; j++) {
|
||||
*(char **)p = slab->free_list;
|
||||
slab->free_list = p;
|
||||
p += slab->block_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
|
||||
|
||||
int settings_bytes_from_str(char *val_str, void *vp, int *len)
|
||||
@@ -867,4 +943,3 @@ char *settings_str_from_bytes(const void *vp, int vp_len,
|
||||
}
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
#include "foundation.h"
|
||||
#include "mesh/health_cli.h"
|
||||
|
||||
static s32_t msg_timeout = K_SECONDS(5);
|
||||
static int32_t msg_timeout = K_SECONDS(5);
|
||||
|
||||
static struct bt_mesh_health_cli *health_cli;
|
||||
|
||||
struct health_fault_param {
|
||||
u16_t cid;
|
||||
u8_t *expect_test_id;
|
||||
u8_t *test_id;
|
||||
u8_t *faults;
|
||||
uint16_t cid;
|
||||
uint8_t *expect_test_id;
|
||||
uint8_t *test_id;
|
||||
uint8_t *faults;
|
||||
size_t *fault_count;
|
||||
};
|
||||
|
||||
@@ -38,8 +38,8 @@ static void health_fault_status(struct bt_mesh_model *model,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct health_fault_param *param;
|
||||
u8_t test_id;
|
||||
u16_t cid;
|
||||
uint8_t test_id;
|
||||
uint16_t cid;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
@@ -84,8 +84,8 @@ static void health_current_status(struct bt_mesh_model *model,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_health_cli *cli = model->user_data;
|
||||
u8_t test_id;
|
||||
u16_t cid;
|
||||
uint8_t test_id;
|
||||
uint16_t cid;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
@@ -106,7 +106,7 @@ static void health_current_status(struct bt_mesh_model *model,
|
||||
}
|
||||
|
||||
struct health_period_param {
|
||||
u8_t *divisor;
|
||||
uint8_t *divisor;
|
||||
};
|
||||
|
||||
static void health_period_status(struct bt_mesh_model *model,
|
||||
@@ -132,7 +132,7 @@ static void health_period_status(struct bt_mesh_model *model,
|
||||
}
|
||||
|
||||
struct health_attention_param {
|
||||
u8_t *attention;
|
||||
uint8_t *attention;
|
||||
};
|
||||
|
||||
static void health_attention_status(struct bt_mesh_model *model,
|
||||
@@ -167,7 +167,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
|
||||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int cli_prepare(void *param, u32_t op)
|
||||
static int cli_prepare(void *param, uint32_t op)
|
||||
{
|
||||
if (!health_cli) {
|
||||
BT_ERR("No available Health Client context!");
|
||||
@@ -202,12 +202,10 @@ static int cli_wait(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *attention)
|
||||
int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -237,12 +235,11 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t attention, u8_t *updated_attention)
|
||||
int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
|
||||
uint8_t *updated_attention)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_SET, 1);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -283,12 +280,10 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *divisor)
|
||||
int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -318,12 +313,11 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t divisor, u8_t *updated_divisor)
|
||||
int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
|
||||
uint8_t *updated_divisor)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_SET, 1);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -364,13 +358,12 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t test_id, uint8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_TEST, 3);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -415,13 +408,12 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_CLEAR, 2);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -465,13 +457,12 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_GET, 2);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
@@ -505,12 +496,12 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
s32_t bt_mesh_health_cli_timeout_get(void)
|
||||
int32_t bt_mesh_health_cli_timeout_get(void)
|
||||
{
|
||||
return msg_timeout;
|
||||
}
|
||||
|
||||
void bt_mesh_health_cli_timeout_set(s32_t timeout)
|
||||
void bt_mesh_health_cli_timeout_set(int32_t timeout)
|
||||
{
|
||||
msg_timeout = timeout;
|
||||
}
|
||||
@@ -523,6 +514,7 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model)
|
||||
}
|
||||
|
||||
health_cli = model->user_data;
|
||||
msg_timeout = 2 * MSEC_PER_SEC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
struct bt_mesh_health_srv *health_srv;
|
||||
|
||||
static void health_get_registered(struct bt_mesh_model *mod,
|
||||
u16_t company_id,
|
||||
uint16_t company_id,
|
||||
struct os_mbuf *msg)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = mod->user_data;
|
||||
u8_t *test_id;
|
||||
uint8_t *test_id;
|
||||
|
||||
BT_DBG("Company ID 0x%04x", company_id);
|
||||
|
||||
@@ -41,7 +41,7 @@ static void health_get_registered(struct bt_mesh_model *mod,
|
||||
net_buf_simple_add_le16(msg, company_id);
|
||||
|
||||
if (srv->cb && srv->cb->fault_get_reg) {
|
||||
u8_t fault_count = net_buf_simple_tailroom(msg) - 4;
|
||||
uint8_t fault_count = net_buf_simple_tailroom(msg) - 4;
|
||||
int err;
|
||||
|
||||
err = srv->cb->fault_get_reg(mod, company_id, test_id,
|
||||
@@ -64,9 +64,9 @@ static size_t health_get_current(struct bt_mesh_model *mod,
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = mod->user_data;
|
||||
const struct bt_mesh_comp *comp;
|
||||
u8_t *test_id, *company_ptr;
|
||||
u16_t company_id;
|
||||
u8_t fault_count;
|
||||
uint8_t *test_id, *company_ptr;
|
||||
uint16_t company_id;
|
||||
uint8_t fault_count;
|
||||
int err;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
|
||||
@@ -104,7 +104,7 @@ static void health_fault_get(struct bt_mesh_model *model,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
u16_t company_id;
|
||||
uint16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
@@ -124,7 +124,7 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
uint16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
@@ -141,7 +141,7 @@ static void health_fault_clear(struct bt_mesh_model *model,
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
uint16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
@@ -165,8 +165,8 @@ static void health_fault_test_unrel(struct bt_mesh_model *model,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
u8_t test_id;
|
||||
uint16_t company_id;
|
||||
uint8_t test_id;
|
||||
|
||||
test_id = net_buf_simple_pull_u8(buf);
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
@@ -184,8 +184,8 @@ static void health_fault_test(struct bt_mesh_model *model,
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
u8_t test_id;
|
||||
uint16_t company_id;
|
||||
uint8_t test_id;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
@@ -219,7 +219,7 @@ static void send_attention_status(struct bt_mesh_model *model,
|
||||
{
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u8_t time;
|
||||
uint8_t time;
|
||||
|
||||
time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
|
||||
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
|
||||
@@ -248,7 +248,7 @@ static void attention_set_unrel(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
u8_t time;
|
||||
uint8_t time;
|
||||
|
||||
time = net_buf_simple_pull_u8(buf);
|
||||
|
||||
@@ -297,7 +297,7 @@ static void health_period_set_unrel(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
u8_t period;
|
||||
uint8_t period;
|
||||
|
||||
period = net_buf_simple_pull_u8(buf);
|
||||
if (period > 15) {
|
||||
@@ -389,10 +389,6 @@ static int health_srv_init(struct bt_mesh_model *model)
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
|
||||
if (!srv) {
|
||||
if (!bt_mesh_model_in_primary(model)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BT_ERR("No Health Server context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -420,7 +416,7 @@ const struct bt_mesh_model_cb bt_mesh_health_srv_cb = {
|
||||
.init = health_srv_init,
|
||||
};
|
||||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv;
|
||||
|
||||
|
||||
351
src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c
Normal file
351
src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define MESH_LOG_MODULE BLE_MESH_HEARTBEAT_LOG
|
||||
|
||||
#include "mesh_priv.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "access.h"
|
||||
#include "lpn.h"
|
||||
#include "settings.h"
|
||||
#include "transport.h"
|
||||
#include "heartbeat.h"
|
||||
#include "foundation.h"
|
||||
#include "mesh/glue.h"
|
||||
|
||||
struct bt_mesh_hb_cb hb_cb;
|
||||
|
||||
static struct bt_mesh_hb_pub pub;
|
||||
static struct bt_mesh_hb_sub sub;
|
||||
static struct k_delayed_work sub_timer;
|
||||
static struct k_delayed_work pub_timer;
|
||||
|
||||
static int64_t sub_remaining(void)
|
||||
{
|
||||
if (sub.dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
return k_delayed_work_remaining_get(&sub_timer) / MSEC_PER_SEC;
|
||||
}
|
||||
|
||||
static void hb_publish_end_cb(int err, void *cb_data)
|
||||
{
|
||||
if (pub.period && pub.count > 1) {
|
||||
k_delayed_work_submit(&pub_timer, K_SECONDS(pub.period));
|
||||
}
|
||||
|
||||
if (pub.count != 0xffff) {
|
||||
pub.count--;
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_recv(uint8_t hops, uint16_t feat)
|
||||
{
|
||||
sub.remaining = sub_remaining();
|
||||
|
||||
if (hb_cb.recv != NULL) {
|
||||
hb_cb.recv(&sub, hops, feat);
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_sub_end(void)
|
||||
{
|
||||
sub.remaining = 0;
|
||||
|
||||
if (hb_cb.sub_end != NULL) {
|
||||
hb_cb.sub_end(&sub);
|
||||
}
|
||||
}
|
||||
|
||||
static void sub_end(struct ble_npl_event *work)
|
||||
{
|
||||
notify_sub_end();
|
||||
}
|
||||
|
||||
static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
uint16_t feat = 0U;
|
||||
struct __packed {
|
||||
uint8_t init_ttl;
|
||||
uint16_t feat;
|
||||
} hb;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = pub.net_idx,
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = pub.dst,
|
||||
.send_ttl = pub.ttl,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(pub.net_idx),
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
};
|
||||
|
||||
/* Do nothing if heartbeat publication is not enabled */
|
||||
if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
hb.init_ttl = pub.ttl;
|
||||
|
||||
if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
|
||||
feat |= BT_MESH_FEAT_RELAY;
|
||||
}
|
||||
|
||||
if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
|
||||
feat |= BT_MESH_FEAT_PROXY;
|
||||
}
|
||||
|
||||
if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
|
||||
feat |= BT_MESH_FEAT_FRIEND;
|
||||
}
|
||||
|
||||
if (bt_mesh_lpn_established()) {
|
||||
feat |= BT_MESH_FEAT_LOW_POWER;
|
||||
}
|
||||
|
||||
hb.feat = sys_cpu_to_be16(feat);
|
||||
|
||||
BT_DBG("InitTTL %u feat 0x%04x", pub.ttl, feat);
|
||||
|
||||
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
|
||||
cb, cb_data);
|
||||
}
|
||||
|
||||
static void hb_publish_start_cb(uint16_t duration, int err, void *cb_data)
|
||||
{
|
||||
if (err) {
|
||||
hb_publish_end_cb(err, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void hb_publish(struct ble_npl_event *work)
|
||||
{
|
||||
static const struct bt_mesh_send_cb publish_cb = {
|
||||
.start = hb_publish_start_cb,
|
||||
.end = hb_publish_end_cb,
|
||||
};
|
||||
struct bt_mesh_subnet *sub;
|
||||
int err;
|
||||
|
||||
BT_DBG("hb_pub.count: %u", pub.count);
|
||||
|
||||
sub = bt_mesh_subnet_get(pub.net_idx);
|
||||
if (!sub) {
|
||||
BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx);
|
||||
pub.dst = BT_MESH_ADDR_UNASSIGNED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pub.count == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = heartbeat_send(&publish_cb, NULL);
|
||||
if (err) {
|
||||
hb_publish_end_cb(err, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
uint8_t init_ttl, hops;
|
||||
uint16_t feat;
|
||||
|
||||
if (buf->om_len < 3) {
|
||||
BT_ERR("Too short heartbeat message");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
|
||||
feat = net_buf_simple_pull_be16(buf);
|
||||
|
||||
hops = (init_ttl - rx->ctx.recv_ttl + 1);
|
||||
|
||||
if (rx->ctx.addr != sub.src || rx->ctx.recv_dst != sub.dst) {
|
||||
BT_DBG("No subscription for received heartbeat");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!k_delayed_work_pending(&sub_timer)) {
|
||||
BT_DBG("Heartbeat subscription period expired");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub.min_hops = MIN(sub.min_hops, hops);
|
||||
sub.max_hops = MAX(sub.max_hops, hops);
|
||||
|
||||
if (sub.count < 0xffff) {
|
||||
sub.count++;
|
||||
}
|
||||
|
||||
BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
|
||||
rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
|
||||
(hops == 1U) ? "" : "s", feat);
|
||||
|
||||
notify_recv(hops, feat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pub_disable(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
pub.dst = BT_MESH_ADDR_UNASSIGNED;
|
||||
pub.count = 0U;
|
||||
pub.ttl = 0U;
|
||||
pub.period = 0U;
|
||||
|
||||
k_delayed_work_cancel(&pub_timer);
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub)
|
||||
{
|
||||
if (!new_pub || new_pub->dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
pub_disable();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
|
||||
bt_mesh_is_provisioned()) {
|
||||
bt_mesh_store_hb_pub();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!bt_mesh_subnet_get(new_pub->net_idx)) {
|
||||
BT_ERR("Unknown NetKey 0x%04x", new_pub->net_idx);
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
new_pub->feat &= BT_MESH_FEAT_SUPPORTED;
|
||||
pub = *new_pub;
|
||||
|
||||
if (!bt_mesh_is_provisioned()) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* The first Heartbeat message shall be published as soon as possible
|
||||
* after the Heartbeat Publication Period state has been configured for
|
||||
* periodic publishing.
|
||||
*/
|
||||
if (pub.period && pub.count) {
|
||||
k_delayed_work_submit(&pub_timer, K_NO_WAIT);
|
||||
} else {
|
||||
k_delayed_work_cancel(&pub_timer);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_hb_pub();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get)
|
||||
{
|
||||
*get = pub;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period)
|
||||
{
|
||||
if (src != BT_MESH_ADDR_UNASSIGNED && !BT_MESH_ADDR_IS_UNICAST(src)) {
|
||||
BT_WARN("Prohibited source address");
|
||||
return STATUS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (BT_MESH_ADDR_IS_VIRTUAL(dst) || BT_MESH_ADDR_IS_RFU(dst) ||
|
||||
(BT_MESH_ADDR_IS_UNICAST(dst) && dst != bt_mesh_primary_addr())) {
|
||||
BT_WARN("Prohibited destination address");
|
||||
return STATUS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (period > (1U << 16)) {
|
||||
BT_WARN("Prohibited subscription period %u s", period);
|
||||
return STATUS_CANNOT_SET;
|
||||
}
|
||||
|
||||
/* Only an explicit address change to unassigned should trigger clearing
|
||||
* of the values according to MESH/NODE/CFG/HBS/BV-02-C.
|
||||
*/
|
||||
if (src == BT_MESH_ADDR_UNASSIGNED || dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
sub.src = BT_MESH_ADDR_UNASSIGNED;
|
||||
sub.dst = BT_MESH_ADDR_UNASSIGNED;
|
||||
sub.min_hops = 0U;
|
||||
sub.max_hops = 0U;
|
||||
sub.count = 0U;
|
||||
sub.period = sub.period - sub_remaining();
|
||||
k_delayed_work_cancel(&sub_timer);
|
||||
notify_sub_end();
|
||||
} else if (period) {
|
||||
sub.src = src;
|
||||
sub.dst = dst;
|
||||
sub.min_hops = BT_MESH_TTL_MAX;
|
||||
sub.max_hops = 0U;
|
||||
sub.count = 0U;
|
||||
sub.period = period;
|
||||
k_delayed_work_submit(&sub_timer, K_SECONDS(period));
|
||||
} else {
|
||||
/* Clearing the period should stop heartbeat subscription
|
||||
* without clearing the parameters, so we can still read them.
|
||||
*/
|
||||
sub.period = sub.period - sub_remaining();
|
||||
k_delayed_work_cancel(&sub_timer);
|
||||
notify_sub_end();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get)
|
||||
{
|
||||
*get = sub;
|
||||
get->remaining = sub_remaining();
|
||||
}
|
||||
|
||||
void bt_mesh_hb_feature_changed(uint16_t features)
|
||||
{
|
||||
if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(pub.feat & features)) {
|
||||
return;
|
||||
}
|
||||
|
||||
heartbeat_send(NULL, NULL);
|
||||
}
|
||||
|
||||
void bt_mesh_hb_init(void)
|
||||
{
|
||||
pub.net_idx = BT_MESH_KEY_UNUSED;
|
||||
k_delayed_work_init(&pub_timer, hb_publish);
|
||||
k_delayed_work_init(&sub_timer, sub_end);
|
||||
}
|
||||
|
||||
void bt_mesh_hb_start(void)
|
||||
{
|
||||
if (pub.count && pub.period) {
|
||||
BT_DBG("Starting heartbeat publication");
|
||||
k_delayed_work_submit(&pub_timer, K_NO_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_hb_suspend(void)
|
||||
{
|
||||
k_delayed_work_cancel(&pub_timer);
|
||||
}
|
||||
|
||||
void bt_mesh_hb_resume(void)
|
||||
{
|
||||
if (pub.period && pub.count) {
|
||||
BT_DBG("Starting heartbeat publication");
|
||||
k_delayed_work_submit(&pub_timer, K_NO_WAIT);
|
||||
}
|
||||
}
|
||||
40
src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h
Normal file
40
src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "mesh/heartbeat.h"
|
||||
|
||||
static inline uint16_t bt_mesh_hb_pwr2(uint8_t val)
|
||||
{
|
||||
if (!val) {
|
||||
return 0x0000;
|
||||
} else if (val == 0xff || val == 0x11) {
|
||||
return 0xffff;
|
||||
} else {
|
||||
return (1 << (val - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t bt_mesh_hb_log(uint32_t val)
|
||||
{
|
||||
if (!val) {
|
||||
return 0x00;
|
||||
} else if (val == 0xffff) {
|
||||
return 0xff;
|
||||
} else {
|
||||
return 32 - __builtin_clz(val);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_hb_init(void);
|
||||
void bt_mesh_hb_start(void);
|
||||
void bt_mesh_hb_suspend(void);
|
||||
void bt_mesh_hb_resume(void);
|
||||
|
||||
int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
|
||||
void bt_mesh_hb_feature_changed(uint16_t features);
|
||||
|
||||
uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub);
|
||||
uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period);
|
||||
@@ -6,52 +6,52 @@
|
||||
#include "light_model.h"
|
||||
|
||||
|
||||
static u8_t gen_onoff_state;
|
||||
static s16_t gen_level_state;
|
||||
static uint8_t gen_onoff_state;
|
||||
static int16_t gen_level_state;
|
||||
|
||||
static void update_light_state(void)
|
||||
{
|
||||
console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (u16_t)gen_level_state);
|
||||
console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (uint16_t)gen_level_state);
|
||||
}
|
||||
|
||||
int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
|
||||
int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
|
||||
{
|
||||
*state = gen_onoff_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
|
||||
int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
|
||||
{
|
||||
gen_onoff_state = state;
|
||||
update_light_state();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
|
||||
int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
|
||||
{
|
||||
*level = gen_level_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
|
||||
int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
|
||||
{
|
||||
gen_level_state = level;
|
||||
if ((u16_t)gen_level_state > 0x0000) {
|
||||
if ((uint16_t)gen_level_state > 0x0000) {
|
||||
gen_onoff_state = 1;
|
||||
}
|
||||
if ((u16_t)gen_level_state == 0x0000) {
|
||||
if ((uint16_t)gen_level_state == 0x0000) {
|
||||
gen_onoff_state = 0;
|
||||
}
|
||||
update_light_state();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
|
||||
int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
|
||||
{
|
||||
return light_model_gen_level_get(model, lightness);
|
||||
}
|
||||
|
||||
int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
|
||||
int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
|
||||
{
|
||||
return light_model_gen_level_set(model, lightness);
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
|
||||
int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
|
||||
int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
|
||||
int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
|
||||
int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness);
|
||||
int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness);
|
||||
int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state);
|
||||
int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state);
|
||||
int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level);
|
||||
int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level);
|
||||
int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness);
|
||||
int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "adv.h"
|
||||
#include "net.h"
|
||||
#include "transport.h"
|
||||
#include "heartbeat.h"
|
||||
#include "access.h"
|
||||
#include "beacon.h"
|
||||
#include "foundation.h"
|
||||
@@ -42,27 +43,33 @@
|
||||
|
||||
#define POLL_RETRY_TIMEOUT K_MSEC(100)
|
||||
|
||||
#define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
|
||||
(lpn)->recv_win + POLL_RETRY_TIMEOUT))
|
||||
#define REQ_RETRY_DURATION(lpn) (LPN_RECV_DELAY + (lpn)->adv_duration + \
|
||||
(lpn)->recv_win + POLL_RETRY_TIMEOUT)
|
||||
|
||||
#define POLL_TIMEOUT_INIT (MYNEWT_VAL(BLE_MESH_LPN_INIT_POLL_TIMEOUT) * 100)
|
||||
#define POLL_TIMEOUT_MAX(lpn) ((MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT) * 100) - \
|
||||
REQ_RETRY_DURATION(lpn))
|
||||
#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4)
|
||||
|
||||
#define CLEAR_ATTEMPTS 2
|
||||
#define POLL_TIMEOUT (MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) * 100)
|
||||
|
||||
#define REQ_ATTEMPTS_MAX 6
|
||||
#define REQ_ATTEMPTS(lpn) MIN(REQ_ATTEMPTS_MAX, \
|
||||
POLL_TIMEOUT / REQ_RETRY_DURATION(lpn))
|
||||
|
||||
#define POLL_TIMEOUT_MAX(lpn) (POLL_TIMEOUT - \
|
||||
(REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn)))
|
||||
|
||||
#define CLEAR_ATTEMPTS 3
|
||||
|
||||
#define LPN_CRITERIA ((MYNEWT_VAL(BLE_MESH_LPN_MIN_QUEUE_SIZE)) | \
|
||||
(MYNEWT_VAL(BLE_MESH_LPN_RSSI_FACTOR) << 3) | \
|
||||
(MYNEWT_VAL(BLE_MESH_LPN_RECV_WIN_FACTOR) << 5))
|
||||
|
||||
#define POLL_TO(to) { (u8_t)((to) >> 16), (u8_t)((to) >> 8), (u8_t)(to) }
|
||||
#define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
|
||||
#define LPN_POLL_TO POLL_TO(MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT))
|
||||
|
||||
/* 2 transmissions, 20ms interval */
|
||||
#define POLL_XMIT BT_MESH_TRANSMIT(1, 20)
|
||||
|
||||
static void (*lpn_cb)(u16_t friend_addr, bool established);
|
||||
static void (*lpn_cb)(uint16_t friend_addr, bool established);
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
|
||||
static const char *state2str(int state)
|
||||
@@ -145,10 +152,7 @@ static void friend_clear_sent(int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
/* We're switching away from Low Power behavior, so permanently
|
||||
* enable scanning.
|
||||
*/
|
||||
bt_mesh_scan_enable();
|
||||
/* Scanning will enable if lpn state still enabled */
|
||||
|
||||
lpn->req_attempts++;
|
||||
|
||||
@@ -170,31 +174,30 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
|
||||
static int send_friend_clear(void)
|
||||
{
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = bt_mesh.sub[0].net_idx,
|
||||
.net_idx = bt_mesh.lpn.sub->net_idx,
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = bt_mesh.lpn.frnd,
|
||||
.send_ttl = 0,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = &bt_mesh.sub[0],
|
||||
.sub = bt_mesh.lpn.sub,
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
};
|
||||
struct bt_mesh_ctl_friend_clear req = {
|
||||
.lpn_addr = sys_cpu_to_be16(tx.src),
|
||||
.lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
|
||||
.lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.lpn_counter),
|
||||
};
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
|
||||
sizeof(req), NULL, &clear_sent_cb, NULL);
|
||||
sizeof(req), &clear_sent_cb, NULL);
|
||||
}
|
||||
|
||||
static void clear_friendship(bool force, bool disable)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
BT_DBG("force %u disable %u", force, disable);
|
||||
@@ -210,8 +213,6 @@ static void clear_friendship(bool force, bool disable)
|
||||
|
||||
k_delayed_work_cancel(&lpn->timer);
|
||||
|
||||
friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
|
||||
|
||||
if (lpn->clear_success) {
|
||||
lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
|
||||
} else {
|
||||
@@ -231,6 +232,7 @@ static void clear_friendship(bool force, bool disable)
|
||||
lpn->sent_req = 0;
|
||||
lpn->established = 0;
|
||||
lpn->clear_success = 0;
|
||||
lpn->sub = NULL;
|
||||
|
||||
group_zero(lpn->added);
|
||||
group_zero(lpn->pending);
|
||||
@@ -242,9 +244,7 @@ static void clear_friendship(bool force, bool disable)
|
||||
*/
|
||||
lpn->groups_changed = 1;
|
||||
|
||||
if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
|
||||
|
||||
if (disable) {
|
||||
lpn_set_state(BT_MESH_LPN_DISABLED);
|
||||
@@ -255,7 +255,7 @@ static void clear_friendship(bool force, bool disable)
|
||||
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static void friend_req_sent(u16_t duration, int err, void *user_data)
|
||||
static void friend_req_sent(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
@@ -284,33 +284,43 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
|
||||
{
|
||||
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = bt_mesh.sub[0].net_idx,
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = BT_MESH_ADDR_FRIENDS,
|
||||
.send_ttl = 0,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = &bt_mesh.sub[0],
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = POLL_XMIT,
|
||||
};
|
||||
|
||||
lpn->lpn_counter++;
|
||||
|
||||
struct bt_mesh_ctl_friend_req req = {
|
||||
.criteria = LPN_CRITERIA,
|
||||
.recv_delay = LPN_RECV_DELAY,
|
||||
.poll_to = LPN_POLL_TO,
|
||||
.prev_addr = lpn->old_friend,
|
||||
.prev_addr = sys_cpu_to_be16(lpn->old_friend),
|
||||
.num_elem = comp->elem_count,
|
||||
.lpn_counter = sys_cpu_to_be16(lpn->counter),
|
||||
.lpn_counter = sys_cpu_to_be16(lpn->lpn_counter),
|
||||
};
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
lpn->sub = bt_mesh_subnet_next(NULL);
|
||||
if (!lpn->sub) {
|
||||
BT_ERR("No subnets, can't start LPN mode");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ctx.net_idx = lpn->sub->net_idx;
|
||||
tx.sub = lpn->sub;
|
||||
|
||||
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
|
||||
sizeof(req), NULL, &friend_req_sent_cb, NULL);
|
||||
sizeof(req), &friend_req_sent_cb, NULL);
|
||||
}
|
||||
|
||||
static void req_sent(u16_t duration, int err, void *user_data)
|
||||
static void req_sent(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
@@ -337,6 +347,7 @@ static void req_sent(u16_t duration, int err, void *user_data)
|
||||
k_delayed_work_submit(&lpn->timer,
|
||||
LPN_RECV_DELAY - SCAN_LATENCY);
|
||||
} else {
|
||||
lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
|
||||
k_delayed_work_submit(&lpn->timer,
|
||||
LPN_RECV_DELAY + duration +
|
||||
lpn->recv_win);
|
||||
@@ -350,20 +361,20 @@ static const struct bt_mesh_send_cb req_sent_cb = {
|
||||
static int send_friend_poll(void)
|
||||
{
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = bt_mesh.sub[0].net_idx,
|
||||
.net_idx = bt_mesh.lpn.sub->net_idx,
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = bt_mesh.lpn.frnd,
|
||||
.send_ttl = 0,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = &bt_mesh.sub[0],
|
||||
.sub = bt_mesh.lpn.sub,
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = POLL_XMIT,
|
||||
.friend_cred = true,
|
||||
};
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
u8_t fsn = lpn->fsn;
|
||||
uint8_t fsn = lpn->fsn;
|
||||
int err;
|
||||
|
||||
BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
|
||||
@@ -377,7 +388,7 @@ static int send_friend_poll(void)
|
||||
}
|
||||
|
||||
err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
|
||||
NULL, &req_sent_cb, NULL);
|
||||
&req_sent_cb, NULL);
|
||||
if (err == 0) {
|
||||
lpn->pending_poll = 0;
|
||||
lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
|
||||
@@ -477,14 +488,22 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
|
||||
send_friend_poll();
|
||||
}
|
||||
|
||||
static int friend_cred_create(struct bt_mesh_net_cred *cred,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
return bt_mesh_friend_cred_create(cred, bt_mesh_primary_addr(),
|
||||
lpn->frnd, lpn->lpn_counter,
|
||||
lpn->frnd_counter, key);
|
||||
}
|
||||
|
||||
int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_ctl_friend_offer *msg = (void *)buf->om_data;
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
struct bt_mesh_subnet *sub = rx->sub;
|
||||
struct friend_cred *cred;
|
||||
u16_t frnd_counter;
|
||||
uint16_t frnd_counter;
|
||||
int err;
|
||||
|
||||
if (buf->om_len < sizeof(*msg)) {
|
||||
@@ -508,16 +527,24 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
|
||||
msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
|
||||
frnd_counter);
|
||||
|
||||
lpn->frnd_counter = frnd_counter;
|
||||
lpn->frnd = rx->ctx.addr;
|
||||
|
||||
cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
|
||||
if (!cred) {
|
||||
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
|
||||
return -ENOMEM;
|
||||
/* Create friend credentials for each of the valid keys in the
|
||||
* friendship subnet:
|
||||
*/
|
||||
for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
|
||||
if (!lpn->sub->keys[i].valid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = friend_cred_create(&lpn->cred[i], lpn->sub->keys[i].net);
|
||||
if (err) {
|
||||
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Add offer acceptance criteria check */
|
||||
|
||||
k_delayed_work_cancel(&lpn->timer);
|
||||
|
||||
lpn->recv_win = msg->recv_win;
|
||||
@@ -525,15 +552,13 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
|
||||
|
||||
err = send_friend_poll();
|
||||
if (err) {
|
||||
friend_cred_clear(cred);
|
||||
lpn->sub = NULL;
|
||||
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
|
||||
lpn->recv_win = 0;
|
||||
lpn->queue_size = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
lpn->counter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -542,7 +567,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
|
||||
{
|
||||
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
u16_t addr, counter;
|
||||
uint16_t addr, counter;
|
||||
|
||||
if (buf->om_len < sizeof(*msg)) {
|
||||
BT_WARN("Too short Friend Clear Confirm");
|
||||
@@ -559,7 +584,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
|
||||
|
||||
BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
|
||||
|
||||
if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
|
||||
if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) {
|
||||
BT_WARN("Invalid parameters in Friend Clear Confirm");
|
||||
return 0;
|
||||
}
|
||||
@@ -570,10 +595,10 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpn_group_add(u16_t group)
|
||||
static void lpn_group_add(uint16_t group)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
u16_t *free_slot = NULL;
|
||||
uint16_t *free_slot = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
|
||||
@@ -596,7 +621,7 @@ static void lpn_group_add(u16_t group)
|
||||
lpn->groups_changed = 1;
|
||||
}
|
||||
|
||||
static void lpn_group_del(u16_t group)
|
||||
static void lpn_group_del(uint16_t group)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
int i;
|
||||
@@ -627,18 +652,18 @@ static inline int group_popcount(atomic_t *target)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool sub_update(u8_t op)
|
||||
static bool sub_update(uint8_t op)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
int added_count = group_popcount(lpn->added);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = bt_mesh.sub[0].net_idx,
|
||||
.net_idx = lpn->sub->net_idx,
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = lpn->frnd,
|
||||
.send_ttl = 0,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = &bt_mesh.sub[0],
|
||||
.sub = lpn->sub,
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = POLL_XMIT,
|
||||
@@ -688,8 +713,8 @@ static bool sub_update(u8_t op)
|
||||
|
||||
req.xact = lpn->xact_next++;
|
||||
|
||||
if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL,
|
||||
&req_sent_cb, NULL) < 0) {
|
||||
if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
|
||||
&req_sent_cb, NULL) < 0) {
|
||||
group_zero(lpn->pending);
|
||||
return false;
|
||||
}
|
||||
@@ -711,7 +736,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn)
|
||||
bt_mesh_scan_disable();
|
||||
}
|
||||
|
||||
if (lpn->req_attempts < 6) {
|
||||
if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
|
||||
BT_WARN("Retrying first Friend Poll");
|
||||
lpn->sent_req = 0;
|
||||
if (send_friend_poll() == 0) {
|
||||
@@ -759,14 +784,14 @@ static void lpn_timeout(struct ble_npl_event *work)
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
|
||||
bt_mesh_scan_disable();
|
||||
}
|
||||
lpn->counter++;
|
||||
lpn->lpn_counter++;
|
||||
lpn_set_state(BT_MESH_LPN_ENABLED);
|
||||
lpn->sent_req = 0U;
|
||||
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
|
||||
break;
|
||||
case BT_MESH_LPN_ESTABLISHED:
|
||||
if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
|
||||
u8_t req = lpn->sent_req;
|
||||
uint8_t req = lpn->sent_req;
|
||||
|
||||
lpn->sent_req = 0;
|
||||
|
||||
@@ -800,7 +825,7 @@ static void lpn_timeout(struct ble_npl_event *work)
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_lpn_group_add(u16_t group)
|
||||
void bt_mesh_lpn_group_add(uint16_t group)
|
||||
{
|
||||
BT_DBG("group 0x%04x", group);
|
||||
|
||||
@@ -813,7 +838,7 @@ void bt_mesh_lpn_group_add(u16_t group)
|
||||
sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
|
||||
}
|
||||
|
||||
void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
|
||||
void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -831,7 +856,7 @@ void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
|
||||
sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
|
||||
}
|
||||
|
||||
static s32_t poll_timeout(struct bt_mesh_lpn *lpn)
|
||||
static int32_t poll_timeout(struct bt_mesh_lpn *lpn)
|
||||
{
|
||||
/* If we're waiting for segment acks keep polling at high freq */
|
||||
if (bt_mesh_tx_in_progress()) {
|
||||
@@ -908,7 +933,9 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
|
||||
}
|
||||
|
||||
if (!lpn->sent_req) {
|
||||
k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
|
||||
int32_t timeout = poll_timeout(lpn);
|
||||
|
||||
k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -920,7 +947,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
||||
struct bt_mesh_ctl_friend_update *msg = (void *)buf->om_data;
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
struct bt_mesh_subnet *sub = rx->sub;
|
||||
u32_t iv_index;
|
||||
uint32_t iv_index;
|
||||
|
||||
if (buf->om_len < sizeof(*msg)) {
|
||||
BT_WARN("Too short Friend Update");
|
||||
@@ -944,8 +971,6 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
||||
}
|
||||
|
||||
if (!lpn->established) {
|
||||
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
|
||||
|
||||
/* This is normally checked on the transport layer, however
|
||||
* in this state we're also still accepting master
|
||||
* credentials so we need to ensure the right ones (Friend
|
||||
@@ -960,9 +985,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
||||
|
||||
BT_INFO("Friendship established with 0x%04x", lpn->frnd);
|
||||
|
||||
if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
|
||||
|
||||
if (lpn_cb) {
|
||||
lpn_cb(lpn->frnd, true);
|
||||
@@ -980,11 +1003,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
||||
BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags,
|
||||
(unsigned) iv_index, msg->md);
|
||||
|
||||
if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags),
|
||||
rx->new_key)) {
|
||||
bt_mesh_net_beacon_update(sub);
|
||||
}
|
||||
|
||||
bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), rx->new_key);
|
||||
bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
|
||||
|
||||
if (lpn->groups_changed) {
|
||||
@@ -1002,7 +1021,9 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
||||
}
|
||||
|
||||
if (!lpn->sent_req) {
|
||||
k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
|
||||
int32_t timeout = poll_timeout(lpn);
|
||||
|
||||
k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1019,17 +1040,41 @@ int bt_mesh_lpn_poll(void)
|
||||
return send_friend_poll();
|
||||
}
|
||||
|
||||
void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established))
|
||||
void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established))
|
||||
{
|
||||
lpn_cb = cb;
|
||||
}
|
||||
|
||||
static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
switch (evt) {
|
||||
case BT_MESH_KEY_DELETED:
|
||||
if (sub == bt_mesh.lpn.sub) {
|
||||
BT_DBG("NetKey deleted");
|
||||
clear_friendship(true, false);
|
||||
}
|
||||
break;
|
||||
case BT_MESH_KEY_UPDATED:
|
||||
BT_DBG("NetKey updated");
|
||||
friend_cred_create(&bt_mesh.lpn.cred[1], sub->keys[1].net);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_lpn_init(void)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
if (!bt_mesh_subnet_cb_list[2]) {
|
||||
bt_mesh_subnet_cb_list[2] = subnet_evt;
|
||||
}
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
lpn->groups_changed = 0;
|
||||
|
||||
k_delayed_work_init(&lpn->timer, lpn_timeout);
|
||||
|
||||
if (lpn->state == BT_MESH_LPN_ENABLED) {
|
||||
|
||||
@@ -28,7 +28,7 @@ static inline bool bt_mesh_lpn_established(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool bt_mesh_lpn_match(u16_t addr)
|
||||
static inline bool bt_mesh_lpn_match(uint16_t addr)
|
||||
{
|
||||
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
|
||||
if (bt_mesh_lpn_established()) {
|
||||
@@ -58,8 +58,8 @@ static inline bool bt_mesh_lpn_timer(void)
|
||||
|
||||
void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx);
|
||||
|
||||
void bt_mesh_lpn_group_add(u16_t group);
|
||||
void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count);
|
||||
void bt_mesh_lpn_group_add(uint16_t group);
|
||||
void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count);
|
||||
|
||||
void bt_mesh_lpn_disable(bool force);
|
||||
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
#include "adv.h"
|
||||
#include "prov.h"
|
||||
#include "provisioner.h"
|
||||
#include "net.h"
|
||||
#include "subnet.h"
|
||||
#include "app_keys.h"
|
||||
#include "rpl.h"
|
||||
#include "cfg.h"
|
||||
#include "beacon.h"
|
||||
#include "lpn.h"
|
||||
#include "friend.h"
|
||||
@@ -26,16 +31,18 @@
|
||||
#include "access.h"
|
||||
#include "foundation.h"
|
||||
#include "proxy.h"
|
||||
#include "heartbeat.h"
|
||||
#include "shell.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "settings.h"
|
||||
|
||||
u8_t g_mesh_addr_type;
|
||||
|
||||
uint8_t g_mesh_addr_type;
|
||||
static struct ble_gap_event_listener mesh_event_listener;
|
||||
|
||||
int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
u8_t flags, u32_t iv_index, u16_t addr,
|
||||
const u8_t dev_key[16])
|
||||
int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
|
||||
uint8_t flags, uint32_t iv_index, uint16_t addr,
|
||||
const uint8_t dev_key[16])
|
||||
{
|
||||
bool pb_gatt_enabled;
|
||||
int err;
|
||||
@@ -58,6 +65,53 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
pb_gatt_enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* Should net_key and iv_index be over-ridden?
|
||||
*/
|
||||
if (IS_ENABLED(BLE_MESH_CDB)) {
|
||||
const struct bt_mesh_comp *comp;
|
||||
const struct bt_mesh_prov *prov;
|
||||
struct bt_mesh_cdb_node *node;
|
||||
|
||||
if (!atomic_test_bit(bt_mesh_cdb.flags,
|
||||
BT_MESH_CDB_VALID)) {
|
||||
BT_ERR("No valid network");
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
comp = bt_mesh_comp_get();
|
||||
if (comp == NULL) {
|
||||
BT_ERR("Failed to get node composition");
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!bt_mesh_cdb_subnet_get(net_idx)) {
|
||||
BT_ERR("No subnet with idx %d", net_idx);
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
prov = bt_mesh_prov_get();
|
||||
node = bt_mesh_cdb_node_alloc(prov->uuid, addr,
|
||||
comp->elem_count, net_idx);
|
||||
if (node == NULL) {
|
||||
BT_ERR("Failed to allocate database node");
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
addr = node->addr;
|
||||
iv_index = bt_mesh_cdb.iv_index;
|
||||
memcpy(node->dev_key, dev_key, 16);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_cdb_node(node);
|
||||
}
|
||||
}
|
||||
|
||||
err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
|
||||
if (err) {
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
|
||||
@@ -75,20 +129,18 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
|
||||
memcpy(bt_mesh.dev_key, dev_key, 16);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing network information persistently");
|
||||
bt_mesh_store_net();
|
||||
bt_mesh_store_subnet(&bt_mesh.sub[0]);
|
||||
bt_mesh_store_iv(false);
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
|
||||
IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
|
||||
bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES);
|
||||
}
|
||||
|
||||
bt_mesh_net_start();
|
||||
bt_mesh_start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration)
|
||||
int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
|
||||
uint8_t attention_duration)
|
||||
{
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
return -EINVAL;
|
||||
@@ -122,25 +174,30 @@ void bt_mesh_reset(void)
|
||||
|
||||
bt_mesh_cfg_reset();
|
||||
|
||||
bt_mesh_rx_reset();
|
||||
bt_mesh_tx_reset();
|
||||
bt_mesh_trans_reset();
|
||||
bt_mesh_app_keys_reset();
|
||||
bt_mesh_net_keys_reset();
|
||||
|
||||
bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY);
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
|
||||
uint16_t group = BT_MESH_ADDR_ALL_NODES;
|
||||
|
||||
bt_mesh_lpn_group_del(&group, 1);
|
||||
}
|
||||
|
||||
bt_mesh_lpn_disable(true);
|
||||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_FRIEND))) {
|
||||
bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
|
||||
bt_mesh_friends_clear();
|
||||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
|
||||
bt_mesh_proxy_gatt_disable();
|
||||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
|
||||
bt_mesh_proxy_prov_enable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_net();
|
||||
}
|
||||
@@ -162,55 +219,6 @@ bool bt_mesh_is_provisioned(void)
|
||||
return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
|
||||
{
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
char uuid_buf[BLE_UUID_STR_LEN];
|
||||
const struct bt_mesh_prov *prov = bt_mesh_prov_get();
|
||||
ble_uuid_t *uuid = BLE_UUID128_DECLARE();
|
||||
|
||||
memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16);
|
||||
BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
/* Make sure we're scanning for provisioning inviations */
|
||||
bt_mesh_scan_enable();
|
||||
/* Enable unprovisioned beacon sending */
|
||||
bt_mesh_beacon_enable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
bt_mesh_proxy_prov_enable();
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
|
||||
{
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
bt_mesh_beacon_disable();
|
||||
bt_mesh_scan_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
bt_mesh_proxy_prov_disable(true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
@@ -251,9 +259,9 @@ int bt_mesh_suspend(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_hb_pub_disable();
|
||||
bt_mesh_hb_suspend();
|
||||
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
|
||||
if (bt_mesh_beacon_enabled()) {
|
||||
bt_mesh_beacon_disable();
|
||||
}
|
||||
|
||||
@@ -266,7 +274,7 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
if (mod->pub && mod->pub->update) {
|
||||
s32_t period_ms = bt_mesh_model_pub_period_get(mod);
|
||||
int32_t period_ms = bt_mesh_model_pub_period_get(mod);
|
||||
|
||||
if (period_ms) {
|
||||
k_delayed_work_submit(&mod->pub->timer, period_ms);
|
||||
@@ -293,7 +301,9 @@ int bt_mesh_resume(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
|
||||
bt_mesh_hb_resume();
|
||||
|
||||
if (bt_mesh_beacon_enabled()) {
|
||||
bt_mesh_beacon_enable();
|
||||
}
|
||||
|
||||
@@ -317,6 +327,10 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
|
||||
return err;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
bt_mesh_proxy_init();
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROV))
|
||||
err = bt_mesh_prov_init(prov);
|
||||
if (err) {
|
||||
@@ -324,38 +338,65 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
bt_mesh_proxy_init();
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROV))
|
||||
/* Need this to proper link.rx.buf allocation */
|
||||
bt_mesh_prov_reset_link();
|
||||
#endif
|
||||
|
||||
bt_mesh_cfg_init();
|
||||
bt_mesh_net_init();
|
||||
bt_mesh_trans_init();
|
||||
bt_mesh_hb_init();
|
||||
bt_mesh_beacon_init();
|
||||
bt_mesh_adv_init();
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
/* Make sure we're scanning for provisioning inviations */
|
||||
bt_mesh_scan_enable();
|
||||
/* Enable unprovisioned beacon sending */
|
||||
|
||||
bt_mesh_beacon_enable();
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
|
||||
bt_mesh_proxy_prov_enable();
|
||||
#endif
|
||||
|
||||
ble_gap_event_listener_register(&mesh_event_listener,
|
||||
bt_mesh_gap_event, NULL);
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
|
||||
bt_mesh_settings_init();
|
||||
#endif
|
||||
|
||||
ble_gap_event_listener_register(&mesh_event_listener,
|
||||
bt_mesh_gap_event, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
if (mod->cb && mod->cb->start) {
|
||||
mod->cb->start(mod);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_start(void)
|
||||
{
|
||||
if (bt_mesh_beacon_enabled()) {
|
||||
bt_mesh_beacon_enable();
|
||||
} else {
|
||||
bt_mesh_beacon_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
|
||||
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
|
||||
bt_mesh_proxy_gatt_enable();
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_init();
|
||||
} else {
|
||||
bt_mesh_scan_enable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
|
||||
bt_mesh_friend_init();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
|
||||
struct bt_mesh_subnet *sub = bt_mesh_subnet_next(NULL);
|
||||
uint16_t addr = bt_mesh_primary_addr();
|
||||
|
||||
bt_mesh_prov_complete(sub->net_idx, addr);
|
||||
}
|
||||
|
||||
bt_mesh_hb_start();
|
||||
|
||||
bt_mesh_model_foreach(model_start, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -8,14 +8,28 @@
|
||||
#ifndef __MESH_PRIV_H
|
||||
#define __MESH_PRIV_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BT_MESH_KEY_PRIMARY 0x0000
|
||||
#define BT_MESH_KEY_ANY 0xffff
|
||||
|
||||
#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
|
||||
#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
|
||||
#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
|
||||
#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
|
||||
enum bt_mesh_key_evt {
|
||||
BT_MESH_KEY_ADDED, /* New key added */
|
||||
BT_MESH_KEY_DELETED, /* Existing key deleted */
|
||||
BT_MESH_KEY_UPDATED, /* KR phase 1, second key added */
|
||||
BT_MESH_KEY_SWAPPED, /* KR phase 2, now sending on second key */
|
||||
BT_MESH_KEY_REVOKED, /* KR phase 3, old key removed */
|
||||
};
|
||||
|
||||
/** Appkey callback. Instantiate with @ref BT_MESH_APP_KEY_CB */
|
||||
struct bt_mesh_app_key_cb {
|
||||
void (*evt_handler)(uint16_t app_idx, uint16_t net_idx,
|
||||
enum bt_mesh_key_evt evt);
|
||||
};
|
||||
|
||||
struct bt_mesh_net;
|
||||
int bt_mesh_start(void);
|
||||
|
||||
#define OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
|
||||
#define OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
|
||||
|
||||
@@ -11,19 +11,19 @@
|
||||
#include "mesh/model_cli.h"
|
||||
#include "mesh_priv.h"
|
||||
|
||||
static s32_t msg_timeout = K_SECONDS(5);
|
||||
static int32_t msg_timeout = K_SECONDS(5);
|
||||
|
||||
static struct bt_mesh_gen_model_cli *gen_onoff_cli;
|
||||
static struct bt_mesh_gen_model_cli *gen_level_cli;
|
||||
|
||||
static u8_t transaction_id = 0;
|
||||
static uint8_t transaction_id = 0;
|
||||
|
||||
struct gen_onoff_param {
|
||||
u8_t *state;
|
||||
uint8_t *state;
|
||||
};
|
||||
|
||||
struct gen_level_param {
|
||||
s16_t *level;
|
||||
int16_t *level;
|
||||
};
|
||||
|
||||
static void gen_onoff_status(struct bt_mesh_model *model,
|
||||
@@ -32,7 +32,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
|
||||
{
|
||||
struct bt_mesh_gen_model_cli *cli = model->user_data;
|
||||
struct gen_onoff_param *param;
|
||||
u8_t state;
|
||||
uint8_t state;
|
||||
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
@@ -62,7 +62,7 @@ static void gen_level_status(struct bt_mesh_model *model,
|
||||
{
|
||||
struct bt_mesh_gen_model_cli *cli = model->user_data;
|
||||
struct gen_level_param *param;
|
||||
s16_t level;
|
||||
int16_t level;
|
||||
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
@@ -138,7 +138,7 @@ const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = {
|
||||
.init = level_cli_init,
|
||||
};
|
||||
|
||||
static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
|
||||
static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, uint32_t op)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -155,8 +155,8 @@ static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *state)
|
||||
int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
uint8_t *state)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
@@ -184,8 +184,8 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t val, u8_t *state)
|
||||
int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
uint8_t val, uint8_t *state)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
@@ -227,8 +227,8 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t *level)
|
||||
int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
int16_t *level)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
@@ -256,8 +256,8 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t val, s16_t *state)
|
||||
int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
int16_t val, int16_t *state)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
|
||||
@@ -20,7 +20,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
|
||||
{
|
||||
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(3);
|
||||
u8_t *state;
|
||||
uint8_t *state;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS);
|
||||
state = net_buf_simple_add(msg, 1);
|
||||
@@ -51,7 +51,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
|
||||
u8_t state;
|
||||
uint8_t state;
|
||||
|
||||
state = buf->om_data[0];
|
||||
|
||||
@@ -77,7 +77,7 @@ static void gen_level_status(struct bt_mesh_model *model,
|
||||
{
|
||||
struct bt_mesh_gen_level_srv *cb = model->user_data;
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
|
||||
s16_t *level;
|
||||
int16_t *level;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS);
|
||||
level = net_buf_simple_add(msg, 2);
|
||||
@@ -107,9 +107,9 @@ static void gen_level_set_unack(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf) {
|
||||
struct bt_mesh_gen_level_srv *cb = model->user_data;
|
||||
s16_t level;
|
||||
int16_t level;
|
||||
|
||||
level = (s16_t) net_buf_simple_pull_le16(buf);
|
||||
level = (int16_t) net_buf_simple_pull_le16(buf);
|
||||
BT_DBG("level: %d", level);
|
||||
|
||||
if (cb && cb->set) {
|
||||
@@ -130,7 +130,7 @@ static void light_lightness_status(struct bt_mesh_model *model,
|
||||
{
|
||||
struct bt_mesh_light_lightness_srv *cb = model->user_data;
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
|
||||
s16_t *lightness;
|
||||
int16_t *lightness;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS);
|
||||
lightness = net_buf_simple_add(msg, 2);
|
||||
@@ -160,9 +160,9 @@ static void light_lightness_set_unack(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf) {
|
||||
struct bt_mesh_light_lightness_srv *cb = model->user_data;
|
||||
s16_t lightness;
|
||||
int16_t lightness;
|
||||
|
||||
lightness = (s16_t) net_buf_simple_pull_le16(buf);
|
||||
lightness = (int16_t) net_buf_simple_pull_le16(buf);
|
||||
BT_DBG("lightness: %d", lightness);
|
||||
|
||||
if (cb && cb->set) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,13 +9,7 @@
|
||||
#ifndef __NET_H__
|
||||
#define __NET_H__
|
||||
|
||||
#define BT_MESH_NET_FLAG_KR BIT(0)
|
||||
#define BT_MESH_NET_FLAG_IVU BIT(1)
|
||||
|
||||
#define BT_MESH_KR_NORMAL 0x00
|
||||
#define BT_MESH_KR_PHASE_1 0x01
|
||||
#define BT_MESH_KR_PHASE_2 0x02
|
||||
#define BT_MESH_KR_PHASE_3 0x03
|
||||
#include "subnet.h"
|
||||
|
||||
#define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01)
|
||||
#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01)
|
||||
@@ -31,64 +25,13 @@
|
||||
CONFIG_BT_MESH_IVU_DIVIDER)
|
||||
#define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS)
|
||||
|
||||
struct bt_mesh_app_key {
|
||||
u16_t net_idx;
|
||||
u16_t app_idx;
|
||||
bool updated;
|
||||
struct bt_mesh_app_keys {
|
||||
u8_t id;
|
||||
u8_t val[16];
|
||||
} keys[2];
|
||||
};
|
||||
struct bt_mesh_net_cred;
|
||||
|
||||
struct bt_mesh_node {
|
||||
u16_t addr;
|
||||
u16_t net_idx;
|
||||
u8_t dev_key[16];
|
||||
u8_t num_elem;
|
||||
};
|
||||
|
||||
struct bt_mesh_subnet {
|
||||
u32_t beacon_sent; /* Timestamp of last sent beacon */
|
||||
u8_t beacons_last; /* Number of beacons during last
|
||||
* observation window
|
||||
*/
|
||||
u8_t beacons_cur; /* Number of beaconds observed during
|
||||
* currently ongoing window.
|
||||
*/
|
||||
|
||||
u8_t beacon_cache[21]; /* Cached last authenticated beacon */
|
||||
|
||||
u16_t net_idx; /* NetKeyIndex */
|
||||
|
||||
bool kr_flag; /* Key Refresh Flag */
|
||||
u8_t kr_phase; /* Key Refresh Phase */
|
||||
|
||||
u8_t node_id; /* Node Identity State */
|
||||
u32_t node_id_start; /* Node Identity started timestamp */
|
||||
|
||||
u8_t auth[8]; /* Beacon Authentication Value */
|
||||
|
||||
struct bt_mesh_subnet_keys {
|
||||
u8_t net[16]; /* NetKey */
|
||||
u8_t nid; /* NID */
|
||||
u8_t enc[16]; /* EncKey */
|
||||
u8_t net_id[8]; /* Network ID */
|
||||
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
|
||||
u8_t identity[16]; /* IdentityKey */
|
||||
#endif
|
||||
u8_t privacy[16]; /* PrivacyKey */
|
||||
u8_t beacon[16]; /* BeaconKey */
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
struct bt_mesh_rpl {
|
||||
u16_t src;
|
||||
bool old_iv;
|
||||
#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
|
||||
bool store;
|
||||
#endif
|
||||
u32_t seq;
|
||||
uint16_t addr;
|
||||
uint16_t net_idx;
|
||||
uint8_t dev_key[16];
|
||||
uint8_t num_elem;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_FRIEND)
|
||||
@@ -100,23 +43,23 @@ struct bt_mesh_rpl {
|
||||
#endif
|
||||
|
||||
struct bt_mesh_friend {
|
||||
u16_t lpn;
|
||||
u8_t recv_delay;
|
||||
u8_t fsn:1,
|
||||
uint16_t lpn;
|
||||
uint8_t recv_delay;
|
||||
uint8_t fsn:1,
|
||||
send_last:1,
|
||||
pending_req:1,
|
||||
sec_update:1,
|
||||
pending_buf:1,
|
||||
valid:1,
|
||||
established:1;
|
||||
s32_t poll_to;
|
||||
u8_t num_elem;
|
||||
u16_t lpn_counter;
|
||||
u16_t counter;
|
||||
int32_t poll_to;
|
||||
uint8_t num_elem;
|
||||
uint16_t lpn_counter;
|
||||
uint16_t counter;
|
||||
|
||||
u16_t net_idx;
|
||||
struct bt_mesh_subnet *subnet;
|
||||
|
||||
u16_t sub_list[FRIEND_SUB_LIST_SIZE];
|
||||
struct bt_mesh_net_cred cred[2];
|
||||
|
||||
uint16_t sub_list[FRIEND_SUB_LIST_SIZE];
|
||||
|
||||
struct k_delayed_work timer;
|
||||
|
||||
@@ -127,19 +70,19 @@ struct bt_mesh_friend {
|
||||
* the current number of segments, in the queue. This is
|
||||
* used for Friend Queue free space calculations.
|
||||
*/
|
||||
u8_t seg_count;
|
||||
uint8_t seg_count;
|
||||
} seg[FRIEND_SEG_RX];
|
||||
|
||||
struct os_mbuf *last;
|
||||
|
||||
struct net_buf_slist_t queue;
|
||||
u32_t queue_size;
|
||||
uint32_t queue_size;
|
||||
|
||||
/* Friend Clear Procedure */
|
||||
struct {
|
||||
u32_t start; /* Clear Procedure start */
|
||||
u16_t frnd; /* Previous Friend's address */
|
||||
u16_t repeat_sec; /* Repeat timeout in seconds */
|
||||
uint32_t start; /* Clear Procedure start */
|
||||
uint16_t frnd; /* Previous Friend's address */
|
||||
uint16_t repeat_sec; /* Repeat timeout in seconds */
|
||||
struct k_delayed_work timer; /* Repeat timer */
|
||||
} clear;
|
||||
};
|
||||
@@ -165,23 +108,23 @@ struct bt_mesh_lpn {
|
||||
} state;
|
||||
|
||||
/* Transaction Number (used for subscription list) */
|
||||
u8_t xact_next;
|
||||
u8_t xact_pending;
|
||||
u8_t sent_req;
|
||||
uint8_t xact_next;
|
||||
uint8_t xact_pending;
|
||||
uint8_t sent_req;
|
||||
|
||||
/* Address of our Friend when we're a LPN. Unassigned if we don't
|
||||
* have a friend yet.
|
||||
*/
|
||||
u16_t frnd;
|
||||
uint16_t frnd;
|
||||
|
||||
/* Value from the friend offer */
|
||||
u8_t recv_win;
|
||||
uint8_t recv_win;
|
||||
|
||||
u8_t req_attempts; /* Number of Request attempts */
|
||||
uint8_t req_attempts; /* Number of Request attempts */
|
||||
|
||||
s32_t poll_timeout;
|
||||
int32_t poll_timeout;
|
||||
|
||||
u8_t groups_changed:1, /* Friend Subscription List needs updating */
|
||||
uint8_t groups_changed:1, /* Friend Subscription List needs updating */
|
||||
pending_poll:1, /* Poll to be sent after subscription */
|
||||
disable:1, /* Disable LPN after clearing */
|
||||
fsn:1, /* Friend Sequence Number */
|
||||
@@ -189,22 +132,29 @@ struct bt_mesh_lpn {
|
||||
clear_success:1; /* Friend Clear Confirm received */
|
||||
|
||||
/* Friend Queue Size */
|
||||
u8_t queue_size;
|
||||
uint8_t queue_size;
|
||||
|
||||
/* FriendCounter */
|
||||
uint16_t frnd_counter;
|
||||
|
||||
/* LPNCounter */
|
||||
u16_t counter;
|
||||
uint16_t lpn_counter;
|
||||
|
||||
/* Previous Friend of this LPN */
|
||||
u16_t old_friend;
|
||||
uint16_t old_friend;
|
||||
|
||||
/* Duration reported for last advertising packet */
|
||||
u16_t adv_duration;
|
||||
uint16_t adv_duration;
|
||||
|
||||
/* Next LPN related action timer */
|
||||
struct k_delayed_work timer;
|
||||
|
||||
/* Subscribed groups */
|
||||
u16_t groups[LPN_GROUPS];
|
||||
uint16_t groups[LPN_GROUPS];
|
||||
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
struct bt_mesh_net_cred cred[2];
|
||||
|
||||
/* Bit fields for tracking which groups the Friend knows about */
|
||||
ATOMIC_DEFINE(added, LPN_GROUPS);
|
||||
@@ -231,15 +181,20 @@ enum {
|
||||
BT_MESH_CFG_PENDING,
|
||||
BT_MESH_MOD_PENDING,
|
||||
BT_MESH_VA_PENDING,
|
||||
BT_MESH_NODES_PENDING,
|
||||
|
||||
/* Feature flags */
|
||||
BT_MESH_RELAY,
|
||||
BT_MESH_BEACON,
|
||||
BT_MESH_GATT_PROXY,
|
||||
BT_MESH_FRIEND,
|
||||
|
||||
/* Don't touch - intentionally last */
|
||||
BT_MESH_FLAG_COUNT,
|
||||
};
|
||||
|
||||
struct bt_mesh_net {
|
||||
u32_t iv_index; /* Current IV Index */
|
||||
u32_t seq; /* Next outgoing sequence number (24 bits) */
|
||||
uint32_t iv_index; /* Current IV Index */
|
||||
uint32_t seq; /* Next outgoing sequence number (24 bits) */
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT);
|
||||
|
||||
@@ -257,22 +212,16 @@ struct bt_mesh_net {
|
||||
#endif
|
||||
|
||||
/* Number of hours in current IV Update state */
|
||||
u8_t ivu_duration;
|
||||
uint8_t ivu_duration;
|
||||
|
||||
uint8_t net_xmit;
|
||||
uint8_t relay_xmit;
|
||||
uint8_t default_ttl;
|
||||
|
||||
/* Timer to track duration in current IV Update state */
|
||||
struct k_delayed_work ivu_timer;
|
||||
|
||||
u8_t dev_key[16];
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
struct bt_mesh_node nodes[MYNEWT_VAL(BLE_MESH_NODE_COUNT)];
|
||||
#endif
|
||||
|
||||
struct bt_mesh_app_key app_keys[MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)];
|
||||
|
||||
struct bt_mesh_subnet sub[MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)];
|
||||
|
||||
struct bt_mesh_rpl rpl[MYNEWT_VAL(BLE_MESH_CRPL)];
|
||||
uint8_t dev_key[16];
|
||||
};
|
||||
|
||||
/* Network interface */
|
||||
@@ -287,24 +236,24 @@ enum bt_mesh_net_if {
|
||||
struct bt_mesh_net_rx {
|
||||
struct bt_mesh_subnet *sub;
|
||||
struct bt_mesh_msg_ctx ctx;
|
||||
u32_t seq; /* Sequence Number */
|
||||
u8_t old_iv:1, /* iv_index - 1 was used */
|
||||
uint32_t seq; /* Sequence Number */
|
||||
uint8_t old_iv:1, /* iv_index - 1 was used */
|
||||
new_key:1, /* Data was encrypted with updated key */
|
||||
friend_cred:1, /* Data was encrypted with friend cred */
|
||||
ctl:1, /* Network Control */
|
||||
net_if:2, /* Network interface */
|
||||
local_match:1, /* Matched a local element */
|
||||
friend_match:1; /* Matched an LPN we're friends for */
|
||||
u16_t msg_cache_idx; /* Index of entry in message cache */
|
||||
uint16_t msg_cache_idx; /* Index of entry in message cache */
|
||||
};
|
||||
|
||||
/* Encoding context for Network/Transport data */
|
||||
struct bt_mesh_net_tx {
|
||||
struct bt_mesh_subnet *sub;
|
||||
struct bt_mesh_msg_ctx *ctx;
|
||||
u16_t src;
|
||||
u8_t xmit;
|
||||
u8_t friend_cred:1,
|
||||
uint16_t src;
|
||||
uint8_t xmit;
|
||||
uint8_t friend_cred:1,
|
||||
aszmic:1,
|
||||
aid:6;
|
||||
};
|
||||
@@ -318,80 +267,36 @@ extern struct bt_mesh_net bt_mesh;
|
||||
|
||||
#define BT_MESH_NET_HDR_LEN 9
|
||||
|
||||
int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
|
||||
const u8_t key[16]);
|
||||
static inline void *net_buf_user_data(const struct os_mbuf *buf)
|
||||
{
|
||||
return (void *)buf->om_data;
|
||||
}
|
||||
|
||||
int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
|
||||
u32_t iv_index);
|
||||
int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
|
||||
uint32_t iv_index);
|
||||
|
||||
u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
|
||||
|
||||
bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key);
|
||||
|
||||
void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
|
||||
|
||||
int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
|
||||
|
||||
void bt_mesh_rpl_reset(void);
|
||||
|
||||
bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update);
|
||||
|
||||
void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
|
||||
|
||||
struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx);
|
||||
|
||||
struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
|
||||
u32_t iv_index, const u8_t auth[8],
|
||||
bool *new_key);
|
||||
bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
|
||||
|
||||
int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
|
||||
bool proxy);
|
||||
|
||||
int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
|
||||
struct bt_mesh_net_rx *rx, struct os_mbuf *out);
|
||||
|
||||
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data);
|
||||
|
||||
int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
|
||||
bool new_key, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data);
|
||||
|
||||
int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
|
||||
struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
|
||||
|
||||
void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
|
||||
void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi,
|
||||
enum bt_mesh_net_if net_if);
|
||||
|
||||
u32_t bt_mesh_next_seq(void);
|
||||
void bt_mesh_net_loopback_clear(uint16_t net_idx);
|
||||
|
||||
void bt_mesh_net_start(void);
|
||||
uint32_t bt_mesh_next_seq(void);
|
||||
|
||||
void bt_mesh_net_init(void);
|
||||
void bt_mesh_net_header_parse(struct os_mbuf *buf,
|
||||
struct bt_mesh_net_rx *rx);
|
||||
|
||||
/* Friendship Credential Management */
|
||||
struct friend_cred {
|
||||
u16_t net_idx;
|
||||
u16_t addr;
|
||||
|
||||
u16_t lpn_counter;
|
||||
u16_t frnd_counter;
|
||||
|
||||
struct {
|
||||
u8_t nid; /* NID */
|
||||
u8_t enc[16]; /* EncKey */
|
||||
u8_t privacy[16]; /* PrivacyKey */
|
||||
} cred[2];
|
||||
};
|
||||
|
||||
int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
|
||||
const u8_t **enc, const u8_t **priv);
|
||||
int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]);
|
||||
void friend_cred_refresh(u16_t net_idx);
|
||||
int friend_cred_update(struct bt_mesh_subnet *sub);
|
||||
struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
|
||||
u16_t lpn_counter, u16_t frnd_counter);
|
||||
void friend_cred_clear(struct friend_cred *cred);
|
||||
int friend_cred_del(u16_t net_idx, u16_t addr);
|
||||
|
||||
static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
|
||||
888
src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c
Normal file
888
src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c
Normal file
@@ -0,0 +1,888 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "mesh/mesh.h"
|
||||
#include <os/os_mbuf.h>
|
||||
#include "testing.h"
|
||||
#include "net.h"
|
||||
#include "prov.h"
|
||||
#include "adv.h"
|
||||
#include "crypto.h"
|
||||
#include "beacon.h"
|
||||
#include "prov.h"
|
||||
#include "mesh/glue.h"
|
||||
|
||||
#define GPCF(gpc) (gpc & 0x03)
|
||||
#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
|
||||
#define GPC_ACK 0x01
|
||||
#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
|
||||
#define GPC_CTL(op) (((op) << 2) | 0x03)
|
||||
|
||||
#define START_PAYLOAD_MAX 20
|
||||
#define CONT_PAYLOAD_MAX 23
|
||||
|
||||
#define START_LAST_SEG(gpc) (gpc >> 2)
|
||||
#define CONT_SEG_INDEX(gpc) (gpc >> 2)
|
||||
|
||||
#define BEARER_CTL(gpc) (gpc >> 2)
|
||||
#define LINK_OPEN 0x00
|
||||
#define LINK_ACK 0x01
|
||||
#define LINK_CLOSE 0x02
|
||||
|
||||
#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
|
||||
#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
|
||||
|
||||
#define XACT_ID_MAX 0x7f
|
||||
#define XACT_ID_NVAL 0xff
|
||||
#define SEG_NVAL 0xff
|
||||
|
||||
#define RETRANSMIT_TIMEOUT K_MSEC(MYNEWT_VAL(BLE_MESH_PB_ADV_RETRANS_TIMEOUT))
|
||||
#define BUF_TIMEOUT K_MSEC(400)
|
||||
#define CLOSING_TIMEOUT K_SECONDS(3)
|
||||
#define TRANSACTION_TIMEOUT K_SECONDS(30)
|
||||
|
||||
/* Acked messages, will do retransmissions manually, taking acks into account:
|
||||
*/
|
||||
#define RETRANSMITS_RELIABLE 0
|
||||
/* Unacked messages: */
|
||||
#define RETRANSMITS_UNRELIABLE 2
|
||||
/* PDU acks: */
|
||||
#define RETRANSMITS_ACK 2
|
||||
|
||||
enum {
|
||||
ADV_LINK_ACTIVE, /* Link has been opened */
|
||||
ADV_LINK_ACK_RECVD, /* Ack for link has been received */
|
||||
ADV_LINK_CLOSING, /* Link is closing down */
|
||||
ADV_LINK_INVALID, /* Error occurred during provisioning */
|
||||
ADV_ACK_PENDING, /* An acknowledgment is being sent */
|
||||
ADV_PROVISIONER, /* The link was opened as provisioner */
|
||||
|
||||
ADV_NUM_FLAGS,
|
||||
};
|
||||
|
||||
struct pb_adv {
|
||||
uint32_t id; /* Link ID */
|
||||
|
||||
ATOMIC_DEFINE(flags, ADV_NUM_FLAGS);
|
||||
|
||||
const struct prov_bearer_cb *cb;
|
||||
void *cb_data;
|
||||
|
||||
struct {
|
||||
uint8_t id; /* Most recent transaction ID */
|
||||
uint8_t seg; /* Bit-field of unreceived segments */
|
||||
uint8_t last_seg; /* Last segment (to check length) */
|
||||
uint8_t fcs; /* Expected FCS value */
|
||||
struct os_mbuf *buf;
|
||||
} rx;
|
||||
|
||||
struct {
|
||||
/* Start timestamp of the transaction */
|
||||
int64_t start;
|
||||
|
||||
/* Transaction id */
|
||||
uint8_t id;
|
||||
|
||||
/* Current ack id */
|
||||
uint8_t pending_ack;
|
||||
|
||||
/* Pending outgoing buffer(s) */
|
||||
struct os_mbuf *buf[3];
|
||||
|
||||
prov_bearer_send_complete_t cb;
|
||||
|
||||
void *cb_data;
|
||||
|
||||
/* Retransmit timer */
|
||||
struct k_delayed_work retransmit;
|
||||
} tx;
|
||||
|
||||
/* Protocol timeout */
|
||||
struct k_delayed_work prot_timer;
|
||||
};
|
||||
|
||||
struct prov_rx {
|
||||
uint32_t link_id;
|
||||
uint8_t xact_id;
|
||||
uint8_t gpc;
|
||||
};
|
||||
|
||||
static struct os_mbuf *rx_buf;
|
||||
static struct pb_adv link;
|
||||
|
||||
static void gen_prov_ack_send(uint8_t xact_id);
|
||||
static void link_open(struct prov_rx *rx, struct os_mbuf *buf);
|
||||
static void link_ack(struct prov_rx *rx, struct os_mbuf *buf);
|
||||
static void link_close(struct prov_rx *rx, struct os_mbuf *buf);
|
||||
|
||||
static void buf_sent(int err, void *user_data)
|
||||
{
|
||||
BT_DBG("buf_send");
|
||||
|
||||
if (!link.tx.buf[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("submit retransmit");
|
||||
k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
|
||||
}
|
||||
|
||||
static struct bt_mesh_send_cb buf_sent_cb = {
|
||||
.end = buf_sent,
|
||||
};
|
||||
|
||||
static uint8_t last_seg(uint8_t len)
|
||||
{
|
||||
if (len <= START_PAYLOAD_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len -= START_PAYLOAD_MAX;
|
||||
|
||||
return 1 + (len / CONT_PAYLOAD_MAX);
|
||||
}
|
||||
|
||||
static void free_segments(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
|
||||
struct os_mbuf *buf = link.tx.buf[i];
|
||||
|
||||
if (!buf) {
|
||||
break;
|
||||
}
|
||||
|
||||
link.tx.buf[i] = NULL;
|
||||
/* Mark as canceled */
|
||||
BT_MESH_ADV(buf)->busy = 0U;
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t next_transaction_id(uint8_t id)
|
||||
{
|
||||
return (((id + 1) & XACT_ID_MAX) | (id & (XACT_ID_MAX+1)));
|
||||
}
|
||||
|
||||
static void prov_clear_tx(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
k_delayed_work_cancel(&link.tx.retransmit);
|
||||
|
||||
free_segments();
|
||||
}
|
||||
|
||||
static void reset_adv_link(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
prov_clear_tx();
|
||||
|
||||
k_delayed_work_cancel(&link.prot_timer);
|
||||
|
||||
if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
|
||||
/* Clear everything except the retransmit and protocol timer
|
||||
* delayed work objects.
|
||||
*/
|
||||
(void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit));
|
||||
link.rx.id = XACT_ID_NVAL;
|
||||
} else {
|
||||
/* Accept another provisioning attempt */
|
||||
link.id = 0;
|
||||
atomic_clear(link.flags);
|
||||
link.rx.id = XACT_ID_MAX;
|
||||
link.tx.id = XACT_ID_NVAL;
|
||||
}
|
||||
link.tx.pending_ack = XACT_ID_NVAL;
|
||||
if (!rx_buf) {
|
||||
rx_buf = NET_BUF_SIMPLE(65);
|
||||
}
|
||||
link.rx.buf = rx_buf;
|
||||
net_buf_simple_reset(link.rx.buf);
|
||||
}
|
||||
|
||||
static void close_link(enum prov_bearer_link_status reason)
|
||||
{
|
||||
const struct prov_bearer_cb *cb = link.cb;
|
||||
void *cb_data = link.cb_data;
|
||||
|
||||
reset_adv_link();
|
||||
cb->link_closed(&pb_adv, cb_data, reason);
|
||||
}
|
||||
|
||||
static struct os_mbuf *adv_buf_create(uint8_t retransmits)
|
||||
{
|
||||
struct os_mbuf *buf;
|
||||
|
||||
buf = bt_mesh_adv_create(BT_MESH_ADV_PROV,
|
||||
BT_MESH_TRANSMIT(retransmits, 20),
|
||||
BUF_TIMEOUT);
|
||||
if (!buf) {
|
||||
BT_ERR("Out of provisioning buffers");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void ack_complete(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
BT_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack);
|
||||
atomic_clear_bit(link.flags, ADV_ACK_PENDING);
|
||||
}
|
||||
|
||||
static bool ack_pending(void)
|
||||
{
|
||||
return atomic_test_bit(link.flags, ADV_ACK_PENDING);
|
||||
}
|
||||
|
||||
static void prov_failed(uint8_t err)
|
||||
{
|
||||
BT_DBG("%u", err);
|
||||
link.cb->error(&pb_adv, link.cb_data, err);
|
||||
atomic_set_bit(link.flags, ADV_LINK_INVALID);
|
||||
}
|
||||
|
||||
static void prov_msg_recv(void)
|
||||
{
|
||||
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
|
||||
|
||||
if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
|
||||
BT_ERR("Incorrect FCS");
|
||||
return;
|
||||
}
|
||||
|
||||
gen_prov_ack_send(link.rx.id);
|
||||
|
||||
if (atomic_test_bit(link.flags, ADV_LINK_INVALID)) {
|
||||
BT_WARN("Unexpected msg 0x%02x on invalidated link",
|
||||
link.rx.buf->om_data[0]);
|
||||
prov_failed(PROV_ERR_UNEXP_PDU);
|
||||
return;
|
||||
}
|
||||
|
||||
link.cb->recv(&pb_adv, link.cb_data, link.rx.buf);
|
||||
}
|
||||
|
||||
static void protocol_timeout(struct ble_npl_event *work)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
link.rx.seg = 0U;
|
||||
close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Generic provisioning
|
||||
******************************************************************************/
|
||||
|
||||
static void gen_prov_ack_send(uint8_t xact_id)
|
||||
{
|
||||
static const struct bt_mesh_send_cb cb = {
|
||||
.start = ack_complete,
|
||||
};
|
||||
const struct bt_mesh_send_cb *complete;
|
||||
struct os_mbuf *buf;
|
||||
bool pending = atomic_test_and_set_bit(link.flags, ADV_ACK_PENDING);
|
||||
|
||||
BT_DBG("xact_id 0x%x", xact_id);
|
||||
|
||||
if (pending && link.tx.pending_ack == xact_id) {
|
||||
BT_DBG("Not sending duplicate ack");
|
||||
return;
|
||||
}
|
||||
|
||||
buf = adv_buf_create(RETRANSMITS_ACK);
|
||||
if (!buf) {
|
||||
atomic_clear_bit(link.flags, ADV_ACK_PENDING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending) {
|
||||
complete = NULL;
|
||||
} else {
|
||||
link.tx.pending_ack = xact_id;
|
||||
complete = &cb;
|
||||
}
|
||||
|
||||
net_buf_add_be32(buf, link.id);
|
||||
net_buf_add_u8(buf, xact_id);
|
||||
net_buf_add_u8(buf, GPC_ACK);
|
||||
|
||||
bt_mesh_adv_send(buf, complete, NULL);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
uint8_t seg = CONT_SEG_INDEX(rx->gpc);
|
||||
|
||||
BT_DBG("len %u, seg_index %u", buf->om_len, seg);
|
||||
|
||||
if (!link.rx.seg && link.rx.id == rx->xact_id) {
|
||||
if (!ack_pending()) {
|
||||
BT_DBG("Resending ack");
|
||||
gen_prov_ack_send(rx->xact_id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!link.rx.seg &&
|
||||
next_transaction_id(link.rx.id) == rx->xact_id) {
|
||||
BT_DBG("Start segment lost");
|
||||
|
||||
link.rx.id = rx->xact_id;
|
||||
|
||||
net_buf_simple_reset(link.rx.buf);
|
||||
link.rx.seg = SEG_NVAL;
|
||||
link.rx.last_seg = SEG_NVAL;
|
||||
|
||||
prov_clear_tx();
|
||||
} else if (rx->xact_id != link.rx.id) {
|
||||
BT_WARN("Data for unknown transaction (0x%x != 0x%x)",
|
||||
rx->xact_id, link.rx.id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (seg > link.rx.last_seg) {
|
||||
BT_ERR("Invalid segment index %u", seg);
|
||||
prov_failed(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(link.rx.seg & BIT(seg))) {
|
||||
BT_DBG("Ignoring already received segment");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
|
||||
XACT_SEG_RECV(seg);
|
||||
|
||||
if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) {
|
||||
uint8_t expect_len;
|
||||
|
||||
expect_len = (link.rx.buf->om_len - 20U -
|
||||
((link.rx.last_seg - 1) * 23U));
|
||||
if (expect_len != buf->om_len) {
|
||||
BT_ERR("Incorrect last seg len: %u != %u", expect_len,
|
||||
buf->om_len);
|
||||
prov_failed(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!link.rx.seg) {
|
||||
prov_msg_recv();
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("len %u", buf->om_len);
|
||||
|
||||
if (!link.tx.buf[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rx->xact_id == link.tx.id) {
|
||||
/* Don't clear resending of link_close messages */
|
||||
if (!atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
|
||||
prov_clear_tx();
|
||||
}
|
||||
|
||||
if (link.tx.cb) {
|
||||
link.tx.cb(0, link.tx.cb_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
uint8_t seg = SEG_NVAL;
|
||||
|
||||
if (rx->xact_id == link.rx.id) {
|
||||
if (!link.rx.seg) {
|
||||
if (!ack_pending()) {
|
||||
BT_DBG("Resending ack");
|
||||
gen_prov_ack_send(rx->xact_id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(link.rx.seg & BIT(0))) {
|
||||
BT_DBG("Ignoring duplicate segment");
|
||||
return;
|
||||
}
|
||||
} else if (rx->xact_id != next_transaction_id(link.rx.id)) {
|
||||
BT_WARN("Unexpected xact 0x%x, expected 0x%x", rx->xact_id,
|
||||
next_transaction_id(link.rx.id));
|
||||
return;
|
||||
}
|
||||
|
||||
net_buf_simple_reset(link.rx.buf);
|
||||
link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
|
||||
link.rx.id = rx->xact_id;
|
||||
link.rx.fcs = net_buf_simple_pull_u8(buf);
|
||||
|
||||
BT_DBG("%p len %u last_seg %u total_len %u fcs 0x%02x", link.rx.buf, buf->om_len,
|
||||
START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
|
||||
|
||||
if (link.rx.buf->om_len < 1) {
|
||||
BT_ERR("Ignoring zero-length provisioning PDU");
|
||||
prov_failed(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20U) {
|
||||
BT_ERR("Too small total length for multi-segment PDU");
|
||||
prov_failed(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
prov_clear_tx();
|
||||
|
||||
link.rx.last_seg = START_LAST_SEG(rx->gpc);
|
||||
if ((link.rx.seg & BIT(0)) &&
|
||||
(find_msb_set((~link.rx.seg) & SEG_NVAL) - 1 > link.rx.last_seg)) {
|
||||
BT_ERR("Invalid segment index %u", seg);
|
||||
prov_failed(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (link.rx.seg) {
|
||||
seg = link.rx.seg;
|
||||
}
|
||||
|
||||
link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1);
|
||||
memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
|
||||
XACT_SEG_RECV(0);
|
||||
|
||||
if (!link.rx.seg) {
|
||||
prov_msg_recv();
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
|
||||
|
||||
switch (BEARER_CTL(rx->gpc)) {
|
||||
case LINK_OPEN:
|
||||
link_open(rx, buf);
|
||||
break;
|
||||
case LINK_ACK:
|
||||
if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
link_ack(rx, buf);
|
||||
break;
|
||||
case LINK_CLOSE:
|
||||
if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
link_close(rx, buf);
|
||||
break;
|
||||
default:
|
||||
BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_TESTING)) {
|
||||
bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
|
||||
bool require_link;
|
||||
uint8_t min_len;
|
||||
} gen_prov[] = {
|
||||
{ gen_prov_start, true, 3 },
|
||||
{ gen_prov_ack, true, 0 },
|
||||
{ gen_prov_cont, true, 0 },
|
||||
{ gen_prov_ctl, false, 0 },
|
||||
};
|
||||
|
||||
static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
|
||||
BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE) &&
|
||||
gen_prov[GPCF(rx->gpc)].require_link) {
|
||||
BT_DBG("Ignoring message that requires active link");
|
||||
return;
|
||||
}
|
||||
|
||||
gen_prov[GPCF(rx->gpc)].func(rx, buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TX
|
||||
******************************************************************************/
|
||||
|
||||
static void send_reliable(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
link.tx.start = k_uptime_get();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
|
||||
struct os_mbuf *buf = link.tx.buf[i];
|
||||
|
||||
if (!buf) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
|
||||
bt_mesh_adv_send(buf, NULL, NULL);
|
||||
} else {
|
||||
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_retransmit(struct ble_npl_event *work)
|
||||
{
|
||||
int32_t timeout_ms;
|
||||
int i;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
|
||||
BT_WARN("Link not active");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to mesh profile spec (5.3.1.4.3), the close message should
|
||||
* be restransmitted at least three times. Retransmit the link_close
|
||||
* message until CLOSING_TIMEOUT has elapsed.
|
||||
*/
|
||||
if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
|
||||
timeout_ms = CLOSING_TIMEOUT;
|
||||
} else {
|
||||
timeout_ms = TRANSACTION_TIMEOUT;
|
||||
}
|
||||
|
||||
if (k_uptime_get() - link.tx.start > timeout_ms) {
|
||||
if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
|
||||
close_link(PROV_BEARER_LINK_STATUS_SUCCESS);
|
||||
} else {
|
||||
BT_WARN("Giving up transaction");
|
||||
close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
|
||||
struct os_mbuf *buf = link.tx.buf[i];
|
||||
|
||||
if (!buf) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (BT_MESH_ADV(buf)->busy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
|
||||
bt_mesh_adv_send(buf, NULL, NULL);
|
||||
} else {
|
||||
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len,
|
||||
bool reliable)
|
||||
{
|
||||
struct os_mbuf *buf;
|
||||
|
||||
BT_DBG("op 0x%02x data_len %u", op, data_len);
|
||||
|
||||
prov_clear_tx();
|
||||
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
|
||||
|
||||
buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE :
|
||||
RETRANSMITS_UNRELIABLE);
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
net_buf_add_be32(buf, link.id);
|
||||
/* Transaction ID, always 0 for Bearer messages */
|
||||
net_buf_add_u8(buf, 0x00);
|
||||
net_buf_add_u8(buf, GPC_CTL(op));
|
||||
net_buf_add_mem(buf, data, data_len);
|
||||
|
||||
if (reliable) {
|
||||
link.tx.buf[0] = buf;
|
||||
send_reliable();
|
||||
} else {
|
||||
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prov_send_adv(struct os_mbuf *msg,
|
||||
prov_bearer_send_complete_t cb, void *cb_data)
|
||||
{
|
||||
struct os_mbuf *start, *buf;
|
||||
uint8_t seg_len, seg_id;
|
||||
|
||||
prov_clear_tx();
|
||||
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
|
||||
|
||||
start = adv_buf_create(RETRANSMITS_RELIABLE);
|
||||
if (!start) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
link.tx.id = next_transaction_id(link.tx.id);
|
||||
net_buf_add_be32(start, link.id);
|
||||
net_buf_add_u8(start, link.tx.id);
|
||||
|
||||
net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
|
||||
net_buf_add_be16(start, msg->om_len);
|
||||
net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
|
||||
|
||||
link.tx.buf[0] = start;
|
||||
link.tx.cb = cb;
|
||||
link.tx.cb_data = cb_data;
|
||||
|
||||
BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->om_len);
|
||||
|
||||
seg_len = MIN(msg->om_len, START_PAYLOAD_MAX);
|
||||
BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
|
||||
net_buf_add_mem(start, msg->om_data, seg_len);
|
||||
net_buf_simple_pull_mem(msg, seg_len);
|
||||
|
||||
buf = start;
|
||||
for (seg_id = 1U; msg->om_len > 0; seg_id++) {
|
||||
if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
|
||||
BT_ERR("Too big message");
|
||||
free_segments();
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
buf = adv_buf_create(RETRANSMITS_RELIABLE);
|
||||
if (!buf) {
|
||||
free_segments();
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
link.tx.buf[seg_id] = buf;
|
||||
|
||||
seg_len = MIN(msg->om_len, CONT_PAYLOAD_MAX);
|
||||
|
||||
BT_DBG("seg %u len %u: %s", seg_id, seg_len,
|
||||
bt_hex(msg->om_data, seg_len));
|
||||
|
||||
net_buf_add_be32(buf, link.id);
|
||||
net_buf_add_u8(buf, link.tx.id);
|
||||
net_buf_add_u8(buf, GPC_CONT(seg_id));
|
||||
net_buf_add_mem(buf, msg->om_data, seg_len);
|
||||
net_buf_simple_pull_mem(msg, seg_len);
|
||||
}
|
||||
|
||||
send_reliable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Link management rx
|
||||
******************************************************************************/
|
||||
|
||||
static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("len %u", buf->om_len);
|
||||
|
||||
if (buf->om_len < 16) {
|
||||
BT_ERR("Too short bearer open message (len %u)", buf->om_len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
|
||||
/* Send another link ack if the provisioner missed the last */
|
||||
if (link.id == rx->link_id) {
|
||||
BT_DBG("Resending link ack");
|
||||
bearer_ctl_send(LINK_ACK, NULL, 0, false);
|
||||
} else {
|
||||
BT_DBG("Ignoring bearer open: link already active");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(buf->om_data, bt_mesh_prov_get()->uuid, 16)) {
|
||||
BT_DBG("Bearer open message not for us");
|
||||
return;
|
||||
}
|
||||
|
||||
link.id = rx->link_id;
|
||||
atomic_set_bit(link.flags, ADV_LINK_ACTIVE);
|
||||
net_buf_simple_reset(link.rx.buf);
|
||||
|
||||
bearer_ctl_send(LINK_ACK, NULL, 0, false);
|
||||
|
||||
link.cb->link_opened(&pb_adv, link.cb_data);
|
||||
}
|
||||
|
||||
static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("len %u", buf->om_len);
|
||||
|
||||
if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
|
||||
if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACK_RECVD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
prov_clear_tx();
|
||||
|
||||
link.cb->link_opened(&pb_adv, link.cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("len %u", buf->om_len);
|
||||
|
||||
if (buf->om_len != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
close_link(net_buf_simple_pull_u8(buf));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Higher level functionality
|
||||
******************************************************************************/
|
||||
|
||||
void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
|
||||
{
|
||||
struct prov_rx rx;
|
||||
|
||||
if (!link.cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->om_len < 6) {
|
||||
BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
|
||||
return;
|
||||
}
|
||||
|
||||
rx.link_id = net_buf_simple_pull_be32(buf);
|
||||
rx.xact_id = net_buf_simple_pull_u8(buf);
|
||||
rx.gpc = net_buf_simple_pull_u8(buf);
|
||||
|
||||
if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && link.id != rx.link_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("link_id 0x%08x xact_id 0x%x", rx.link_id, rx.xact_id);
|
||||
|
||||
gen_prov_recv(&rx, buf);
|
||||
}
|
||||
|
||||
static int prov_link_open(const uint8_t uuid[16], int32_t timeout,
|
||||
const struct prov_bearer_cb *cb, void *cb_data)
|
||||
{
|
||||
BT_DBG("uuid %s", bt_hex(uuid, 16));
|
||||
|
||||
if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
atomic_set_bit(link.flags, ADV_PROVISIONER);
|
||||
|
||||
bt_rand(&link.id, sizeof(link.id));
|
||||
link.tx.id = XACT_ID_MAX;
|
||||
link.rx.id = XACT_ID_NVAL;
|
||||
link.cb = cb;
|
||||
link.cb_data = cb_data;
|
||||
|
||||
net_buf_simple_reset(link.rx.buf);
|
||||
|
||||
bearer_ctl_send(LINK_OPEN, uuid, 16, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data)
|
||||
{
|
||||
if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
link.rx.id = XACT_ID_MAX;
|
||||
link.tx.id = XACT_ID_NVAL;
|
||||
link.cb = cb;
|
||||
link.cb_data = cb_data;
|
||||
|
||||
/* Make sure we're scanning for provisioning inviations */
|
||||
bt_mesh_scan_enable();
|
||||
/* Enable unprovisioned beacon sending */
|
||||
bt_mesh_beacon_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prov_link_close(enum prov_bearer_link_status status)
|
||||
{
|
||||
if (atomic_test_and_set_bit(link.flags, ADV_LINK_CLOSING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bearer_ctl_send(LINK_CLOSE, &status, 1, true);
|
||||
}
|
||||
|
||||
void pb_adv_init(void)
|
||||
{
|
||||
k_delayed_work_init(&link.prot_timer, protocol_timeout);
|
||||
k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
|
||||
|
||||
if (!rx_buf) {
|
||||
rx_buf = NET_BUF_SIMPLE(65);
|
||||
}
|
||||
link.rx.buf = rx_buf;
|
||||
net_buf_simple_reset(link.rx.buf);
|
||||
}
|
||||
|
||||
void pb_adv_reset(void)
|
||||
{
|
||||
reset_adv_link();
|
||||
}
|
||||
|
||||
const struct prov_bearer pb_adv = {
|
||||
.type = BT_MESH_PROV_ADV,
|
||||
.link_open = prov_link_open,
|
||||
.link_accept = prov_link_accept,
|
||||
.link_close = prov_link_close,
|
||||
.send = prov_send_adv,
|
||||
.clear_tx = prov_clear_tx,
|
||||
};
|
||||
158
src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c
Normal file
158
src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "prov.h"
|
||||
#include "net.h"
|
||||
#include "proxy.h"
|
||||
#include "adv.h"
|
||||
#include "prov.h"
|
||||
|
||||
struct prov_link {
|
||||
uint16_t conn_handle;
|
||||
const struct prov_bearer_cb *cb;
|
||||
void *cb_data;
|
||||
struct {
|
||||
uint8_t id; /* Transaction ID */
|
||||
uint8_t prev_id; /* Previous Transaction ID */
|
||||
uint8_t seg; /* Bit-field of unreceived segments */
|
||||
uint8_t last_seg; /* Last segment (to check length) */
|
||||
uint8_t fcs; /* Expected FCS value */
|
||||
struct os_mbuf *buf;
|
||||
} rx;
|
||||
struct k_delayed_work prot_timer;
|
||||
};
|
||||
|
||||
static struct prov_link link;
|
||||
|
||||
static void reset_state(void)
|
||||
{
|
||||
link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||
|
||||
k_delayed_work_cancel(&link.prot_timer);
|
||||
|
||||
link.rx.buf = bt_mesh_proxy_get_buf();
|
||||
}
|
||||
|
||||
static void link_closed(enum prov_bearer_link_status status)
|
||||
{
|
||||
const struct prov_bearer_cb *cb = link.cb;
|
||||
|
||||
void *cb_data = link.cb_data;
|
||||
|
||||
reset_state();
|
||||
|
||||
cb->link_closed(&pb_gatt, cb_data, status);
|
||||
}
|
||||
|
||||
static void protocol_timeout(struct ble_npl_event *work)
|
||||
{
|
||||
BT_DBG("Protocol timeout");
|
||||
|
||||
link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT);
|
||||
}
|
||||
|
||||
int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
if (link.conn_handle != conn_handle || !link.cb) {
|
||||
BT_WARN("Data for unexpected connection");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (buf->om_len < 1) {
|
||||
BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
|
||||
|
||||
link.cb->recv(&pb_gatt, link.cb_data, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_pb_gatt_open(uint16_t conn_handle)
|
||||
{
|
||||
BT_DBG("conn %p", conn_handle);
|
||||
|
||||
if (link.conn_handle) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
link.conn_handle = conn_handle;
|
||||
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
|
||||
|
||||
link.cb->link_opened(&pb_gatt, link.cb_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_pb_gatt_close(uint16_t conn_handle)
|
||||
{
|
||||
BT_DBG("conn %p", conn_handle);
|
||||
|
||||
if (link.conn_handle != conn_handle) {
|
||||
BT_DBG("Not connected");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
link.cb->link_closed(&pb_gatt, link.cb_data,
|
||||
PROV_BEARER_LINK_STATUS_SUCCESS);
|
||||
|
||||
reset_state();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_accept(const struct prov_bearer_cb *cb, void *cb_data)
|
||||
{
|
||||
bt_mesh_proxy_prov_enable();
|
||||
bt_mesh_adv_update();
|
||||
|
||||
link.cb = cb;
|
||||
link.cb_data = cb_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
|
||||
void *cb_data)
|
||||
{
|
||||
if (!link.conn_handle) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
|
||||
|
||||
return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf);
|
||||
}
|
||||
|
||||
static void clear_tx(void)
|
||||
{
|
||||
/* No action */
|
||||
}
|
||||
|
||||
void pb_gatt_init(void)
|
||||
{
|
||||
k_delayed_work_init(&link.prot_timer, protocol_timeout);
|
||||
}
|
||||
|
||||
void pb_gatt_reset(void)
|
||||
{
|
||||
reset_state();
|
||||
}
|
||||
const struct prov_bearer pb_gatt = {
|
||||
.type = BT_MESH_PROV_GATT,
|
||||
.link_accept = link_accept,
|
||||
.send = buf_send,
|
||||
.clear_tx = clear_tx,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,16 +9,131 @@
|
||||
#ifndef __PROV_H__
|
||||
#define __PROV_H__
|
||||
|
||||
#include "prov_bearer.h"
|
||||
#include "os/os_mbuf.h"
|
||||
#include "mesh/mesh.h"
|
||||
#include "../src/ble_hs_conn_priv.h"
|
||||
|
||||
int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration);
|
||||
#define PROV_ERR_NONE 0x00
|
||||
#define PROV_ERR_NVAL_PDU 0x01
|
||||
#define PROV_ERR_NVAL_FMT 0x02
|
||||
#define PROV_ERR_UNEXP_PDU 0x03
|
||||
#define PROV_ERR_CFM_FAILED 0x04
|
||||
#define PROV_ERR_RESOURCES 0x05
|
||||
#define PROV_ERR_DECRYPT 0x06
|
||||
#define PROV_ERR_UNEXP_ERR 0x07
|
||||
#define PROV_ERR_ADDR 0x08
|
||||
|
||||
void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
|
||||
#define AUTH_METHOD_NO_OOB 0x00
|
||||
#define AUTH_METHOD_STATIC 0x01
|
||||
#define AUTH_METHOD_OUTPUT 0x02
|
||||
#define AUTH_METHOD_INPUT 0x03
|
||||
|
||||
bool bt_prov_active(void);
|
||||
#define OUTPUT_OOB_BLINK 0x00
|
||||
#define OUTPUT_OOB_BEEP 0x01
|
||||
#define OUTPUT_OOB_VIBRATE 0x02
|
||||
#define OUTPUT_OOB_NUMBER 0x03
|
||||
#define OUTPUT_OOB_STRING 0x04
|
||||
|
||||
#define INPUT_OOB_PUSH 0x00
|
||||
#define INPUT_OOB_TWIST 0x01
|
||||
#define INPUT_OOB_NUMBER 0x02
|
||||
#define INPUT_OOB_STRING 0x03
|
||||
|
||||
#define PUB_KEY_NO_OOB 0x00
|
||||
#define PUB_KEY_OOB 0x01
|
||||
|
||||
#define PROV_INVITE 0x00
|
||||
#define PROV_CAPABILITIES 0x01
|
||||
#define PROV_START 0x02
|
||||
#define PROV_PUB_KEY 0x03
|
||||
#define PROV_INPUT_COMPLETE 0x04
|
||||
#define PROV_CONFIRM 0x05
|
||||
#define PROV_RANDOM 0x06
|
||||
#define PROV_DATA 0x07
|
||||
#define PROV_COMPLETE 0x08
|
||||
#define PROV_FAILED 0x09
|
||||
|
||||
#define PROV_NO_PDU 0xff
|
||||
|
||||
#define PROV_ALG_P256 0x00
|
||||
|
||||
#define PROV_BUF(len) \
|
||||
NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + len)
|
||||
|
||||
enum {
|
||||
WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
|
||||
LINK_ACTIVE, /* Link has been opened */
|
||||
WAIT_NUMBER, /* Waiting for number input from user */
|
||||
WAIT_STRING, /* Waiting for string input from user */
|
||||
NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
|
||||
PROVISIONER, /* The link was opened as provisioner */
|
||||
OOB_PUB_KEY, /* OOB Public key used */
|
||||
PUB_KEY_SENT, /* Public key has been sent */
|
||||
REMOTE_PUB_KEY, /* Remote key has been received */
|
||||
INPUT_COMPLETE, /* Device input completed */
|
||||
WAIT_CONFIRM, /* Wait for send confirm */
|
||||
WAIT_AUTH, /* Wait for auth response */
|
||||
OOB_STATIC_KEY, /* OOB Static Authentication */
|
||||
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
||||
/** Provisioning role */
|
||||
struct bt_mesh_prov_role {
|
||||
void (*link_opened)(void);
|
||||
|
||||
void (*link_closed)(void);
|
||||
|
||||
void (*error)(uint8_t reason);
|
||||
|
||||
void (*input_complete)(void);
|
||||
|
||||
void (*op[10])(const uint8_t *data);
|
||||
};
|
||||
|
||||
struct bt_mesh_prov_link {
|
||||
ATOMIC_DEFINE(flags, NUM_FLAGS);
|
||||
|
||||
const struct prov_bearer *bearer;
|
||||
const struct bt_mesh_prov_role *role;
|
||||
|
||||
uint8_t oob_method; /* Authen method */
|
||||
uint8_t oob_action; /* Authen action */
|
||||
uint8_t oob_size; /* Authen size */
|
||||
uint8_t auth[16]; /* Authen value */
|
||||
|
||||
uint8_t dhkey[32]; /* Calculated DHKey */
|
||||
uint8_t expect; /* Next expected PDU */
|
||||
uint8_t conf[16]; /* Remote Confirmation */
|
||||
uint8_t rand[16]; /* Local Random */
|
||||
|
||||
uint8_t conf_salt[16]; /* ConfirmationSalt */
|
||||
uint8_t conf_key[16]; /* ConfirmationKey */
|
||||
uint8_t conf_inputs[145]; /* ConfirmationInputs */
|
||||
uint8_t prov_salt[16]; /* Provisioning Salt */
|
||||
};
|
||||
|
||||
extern struct bt_mesh_prov_link bt_mesh_prov_link;
|
||||
extern const struct bt_mesh_prov *bt_mesh_prov;
|
||||
|
||||
static inline int bt_mesh_prov_send(struct os_mbuf *buf,
|
||||
prov_bearer_send_complete_t cb)
|
||||
{
|
||||
return bt_mesh_prov_link.bearer->send(buf, cb, NULL);
|
||||
}
|
||||
|
||||
static inline void bt_mesh_prov_buf_init(struct os_mbuf *buf, uint8_t type)
|
||||
{
|
||||
net_buf_reserve(buf, PROV_BEARER_BUF_HEADROOM);
|
||||
net_buf_simple_add_u8(buf, type);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]));
|
||||
|
||||
bool bt_mesh_prov_active(void);
|
||||
|
||||
int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size);
|
||||
|
||||
int bt_mesh_pb_gatt_open(uint16_t conn_handle);
|
||||
int bt_mesh_pb_gatt_close(uint16_t conn_handle);
|
||||
@@ -26,12 +141,14 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf);
|
||||
|
||||
const struct bt_mesh_prov *bt_mesh_prov_get(void);
|
||||
|
||||
int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
|
||||
|
||||
void bt_mesh_prov_reset_link(void);
|
||||
|
||||
void bt_mesh_prov_complete(u16_t net_idx, u16_t addr);
|
||||
void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem);
|
||||
void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr);
|
||||
void bt_mesh_prov_reset(void);
|
||||
|
||||
const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void);
|
||||
|
||||
void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
|
||||
|
||||
int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
|
||||
#endif
|
||||
|
||||
116
src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h
Normal file
116
src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define PROTOCOL_TIMEOUT K_SECONDS(60)
|
||||
|
||||
/** @def PROV_BEARER_BUF_HEADROOM
|
||||
*
|
||||
* @brief Required headroom for the bearer packet buffers.
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_GATT)
|
||||
#define PROV_BEARER_BUF_HEADROOM 5
|
||||
#else
|
||||
#define PROV_BEARER_BUF_HEADROOM 0
|
||||
#endif
|
||||
|
||||
enum prov_bearer_link_status {
|
||||
PROV_BEARER_LINK_STATUS_SUCCESS,
|
||||
PROV_BEARER_LINK_STATUS_TIMEOUT,
|
||||
PROV_BEARER_LINK_STATUS_FAIL,
|
||||
};
|
||||
|
||||
struct prov_bearer;
|
||||
|
||||
/** Callbacks from bearer to host */
|
||||
struct prov_bearer_cb {
|
||||
|
||||
void (*link_opened)(const struct prov_bearer *bearer, void *cb_data);
|
||||
|
||||
void (*link_closed)(const struct prov_bearer *bearer, void *cb_data,
|
||||
enum prov_bearer_link_status reason);
|
||||
|
||||
void (*error)(const struct prov_bearer *bearer, void *cb_data,
|
||||
uint8_t err);
|
||||
|
||||
void (*recv)(const struct prov_bearer *bearer, void *cb_data,
|
||||
struct os_mbuf *buf);
|
||||
};
|
||||
|
||||
typedef void (*prov_bearer_send_complete_t)(int err, void *cb_data);
|
||||
|
||||
/** Provisioning bearer API */
|
||||
struct prov_bearer {
|
||||
/** Provisioning bearer type. */
|
||||
bt_mesh_prov_bearer_t type;
|
||||
|
||||
/** @brief Enable link establishment as a provisionee.
|
||||
*
|
||||
* Prompts the bearer to make itself visible to provisioners, and
|
||||
* start accepting link open messages.
|
||||
*
|
||||
* @param cb Bearer event callbacks used for the duration of the link.
|
||||
* @param cb_data Context parameter to pass to the bearer callbacks.
|
||||
*
|
||||
* @return Zero on success, or (negative) error code otherwise.
|
||||
*/
|
||||
int (*link_accept)(const struct prov_bearer_cb *cb, void *cb_data);
|
||||
|
||||
/** @brief Send a packet on an established link.
|
||||
*
|
||||
* @param buf Payload buffer. Requires @ref
|
||||
* PROV_BEARER_BUF_HEADROOM bytes of headroom.
|
||||
* @param cb Callback to call when sending is complete.
|
||||
* @param cb_data Callback data.
|
||||
*
|
||||
* @return Zero on success, or (negative) error code otherwise.
|
||||
*/
|
||||
int (*send)(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
|
||||
void *cb_data);
|
||||
|
||||
/** @brief Clear any ongoing transmissions, if possible.
|
||||
*
|
||||
* Bearers that don't support tx clearing must implement this callback
|
||||
* and leave it empty.
|
||||
*/
|
||||
void (*clear_tx)(void);
|
||||
|
||||
/* Only available in provisioners: */
|
||||
|
||||
/** @brief Open a new link as a provisioner.
|
||||
*
|
||||
* Only available in provisioners. Bearers that don't support the
|
||||
* provisioner role should leave this as NULL.
|
||||
*
|
||||
* @param uuid UUID of the node to establish a link to.
|
||||
* @param timeout Protocol timeout.
|
||||
* @param cb Bearer event callbacks used for the duration of the link.
|
||||
* @param cb_data Context parameter to pass to the bearer callbacks.
|
||||
*
|
||||
* @return Zero on success, or (negative) error code otherwise.
|
||||
*/
|
||||
int (*link_open)(const uint8_t uuid[16], int32_t timeout,
|
||||
const struct prov_bearer_cb *cb, void *cb_data);
|
||||
|
||||
/** @brief Close the current link.
|
||||
*
|
||||
* Only available in provisioners. Bearers that don't support the
|
||||
* provisioner role should leave this as NULL.
|
||||
*
|
||||
* @param status Link status for the link close message.
|
||||
*/
|
||||
void (*link_close)(enum prov_bearer_link_status status);
|
||||
};
|
||||
|
||||
extern const struct prov_bearer pb_adv;
|
||||
extern const struct prov_bearer pb_gatt;
|
||||
|
||||
void pb_adv_init(void);
|
||||
void pb_gatt_init(void);
|
||||
|
||||
void pb_adv_reset(void);
|
||||
void pb_gatt_reset(void);
|
||||
569
src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c
Normal file
569
src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Lingao Meng
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
|
||||
|
||||
#include "testing.h"
|
||||
#include "crypto.h"
|
||||
#include "adv.h"
|
||||
#include "mesh/mesh.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "beacon.h"
|
||||
#include "access.h"
|
||||
#include "foundation.h"
|
||||
#include "proxy.h"
|
||||
#include "prov.h"
|
||||
#include "settings.h"
|
||||
|
||||
static void send_pub_key(void);
|
||||
static void pub_key_ready(const uint8_t *pkey);
|
||||
|
||||
static int reset_state(void)
|
||||
{
|
||||
return bt_mesh_prov_reset_state(pub_key_ready);
|
||||
}
|
||||
|
||||
static void prov_send_fail_msg(uint8_t err)
|
||||
{
|
||||
struct os_mbuf *buf = PROV_BUF(2);
|
||||
|
||||
BT_DBG("%u", err);
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_NO_PDU;
|
||||
|
||||
bt_mesh_prov_buf_init(buf, PROV_FAILED);
|
||||
net_buf_simple_add_u8(buf, err);
|
||||
|
||||
if (bt_mesh_prov_send(buf, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Failed message");
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_fail(uint8_t reason)
|
||||
{
|
||||
/* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
|
||||
* provisioner just closes the link when something fails, while the
|
||||
* provisionee sends the fail message, and waits for the provisioner to
|
||||
* close the link.
|
||||
*/
|
||||
prov_send_fail_msg(reason);
|
||||
}
|
||||
|
||||
static void prov_invite(const uint8_t *data)
|
||||
{
|
||||
struct os_mbuf *buf = PROV_BUF(12);
|
||||
|
||||
BT_DBG("Attention Duration: %u seconds", data[0]);
|
||||
|
||||
if (data[0]) {
|
||||
bt_mesh_attention(NULL, data[0]);
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.conf_inputs[0] = data[0];
|
||||
|
||||
bt_mesh_prov_buf_init(buf, PROV_CAPABILITIES);
|
||||
|
||||
/* Number of Elements supported */
|
||||
net_buf_simple_add_u8(buf, bt_mesh_elem_count());
|
||||
|
||||
/* Supported algorithms - FIPS P-256 Eliptic Curve */
|
||||
net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256));
|
||||
|
||||
/* Public Key Type, Only "No OOB" Public Key is supported */
|
||||
net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB);
|
||||
|
||||
/* Static OOB Type */
|
||||
net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00);
|
||||
|
||||
/* Output OOB Size */
|
||||
net_buf_simple_add_u8(buf, bt_mesh_prov->output_size);
|
||||
|
||||
/* Output OOB Action */
|
||||
net_buf_simple_add_be16(buf, bt_mesh_prov->output_actions);
|
||||
|
||||
/* Input OOB Size */
|
||||
net_buf_simple_add_u8(buf, bt_mesh_prov->input_size);
|
||||
|
||||
/* Input OOB Action */
|
||||
net_buf_simple_add_be16(buf, bt_mesh_prov->input_actions);
|
||||
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[1], &buf->om_data[1], 11);
|
||||
|
||||
if (bt_mesh_prov_send(buf, NULL)) {
|
||||
BT_ERR("Failed to send capabilities");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_START;
|
||||
}
|
||||
|
||||
static void prov_start(const uint8_t *data)
|
||||
{
|
||||
BT_DBG("Algorithm: 0x%02x", data[0]);
|
||||
BT_DBG("Public Key: 0x%02x", data[1]);
|
||||
BT_DBG("Auth Method: 0x%02x", data[2]);
|
||||
BT_DBG("Auth Action: 0x%02x", data[3]);
|
||||
BT_DBG("Auth Size: 0x%02x", data[4]);
|
||||
|
||||
if (data[0] != PROV_ALG_P256) {
|
||||
BT_ERR("Unknown algorithm 0x%02x", data[0]);
|
||||
prov_fail(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data[1] != PUB_KEY_NO_OOB) {
|
||||
BT_ERR("Invalid public key type: 0x%02x", data[1]);
|
||||
prov_fail(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5);
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_PUB_KEY;
|
||||
|
||||
if (bt_mesh_prov_auth(data[2], data[3], data[4]) < 0) {
|
||||
BT_ERR("Invalid authentication method: 0x%02x; "
|
||||
"action: 0x%02x; size: 0x%02x", data[2], data[3],
|
||||
data[4]);
|
||||
prov_fail(PROV_ERR_NVAL_FMT);
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) {
|
||||
memcpy(bt_mesh_prov_link.auth + 16 - bt_mesh_prov->static_val_len,
|
||||
bt_mesh_prov->static_val, bt_mesh_prov->static_val_len);
|
||||
(void)memset(bt_mesh_prov_link.auth, 0,
|
||||
sizeof(bt_mesh_prov_link.auth) - bt_mesh_prov->static_val_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_confirm(void)
|
||||
{
|
||||
struct os_mbuf *cfm = PROV_BUF(17);
|
||||
|
||||
BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64));
|
||||
BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64));
|
||||
BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17));
|
||||
|
||||
if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
|
||||
bt_mesh_prov_link.conf_salt)) {
|
||||
BT_ERR("Unable to generate confirmation salt");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
|
||||
|
||||
if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey, bt_mesh_prov_link.conf_salt,
|
||||
bt_mesh_prov_link.conf_key)) {
|
||||
BT_ERR("Unable to generate confirmation key");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
|
||||
|
||||
if (bt_rand(bt_mesh_prov_link.rand, 16)) {
|
||||
BT_ERR("Unable to generate random number");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
|
||||
|
||||
bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
|
||||
|
||||
if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, bt_mesh_prov_link.rand,
|
||||
bt_mesh_prov_link.auth, net_buf_simple_add(cfm, 16))) {
|
||||
BT_ERR("Unable to generate confirmation value");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_send(cfm, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Confirm");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_RANDOM;
|
||||
|
||||
}
|
||||
|
||||
static void send_input_complete(void)
|
||||
{
|
||||
struct os_mbuf *buf = PROV_BUF(1);
|
||||
|
||||
bt_mesh_prov_buf_init(buf, PROV_INPUT_COMPLETE);
|
||||
if (bt_mesh_prov_send(buf, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Input Complete");
|
||||
}
|
||||
bt_mesh_prov_link.expect = PROV_CONFIRM;
|
||||
}
|
||||
|
||||
static void public_key_sent(int err, void *cb_data)
|
||||
{
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE)) {
|
||||
send_input_complete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void send_pub_key(void)
|
||||
{
|
||||
struct os_mbuf *buf = PROV_BUF(65);
|
||||
const uint8_t *key;
|
||||
|
||||
key = bt_pub_key_get();
|
||||
if (!key) {
|
||||
BT_ERR("No public key available");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
|
||||
|
||||
bt_mesh_prov_buf_init(buf, PROV_PUB_KEY);
|
||||
|
||||
/* Swap X and Y halves independently to big-endian */
|
||||
sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
|
||||
sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
|
||||
|
||||
/* PublicKeyRemote */
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[81], &buf->om_data[1], 64);
|
||||
|
||||
if (bt_mesh_prov_send(buf, public_key_sent)) {
|
||||
BT_ERR("Failed to send Public Key");
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
|
||||
atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
|
||||
bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */
|
||||
} else {
|
||||
bt_mesh_prov_link.expect = PROV_CONFIRM;
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_dh_key_cb(const uint8_t dhkey[32])
|
||||
{
|
||||
BT_DBG("%p", dhkey);
|
||||
|
||||
if (!dhkey) {
|
||||
BT_ERR("DHKey generation failed");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
|
||||
|
||||
BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
|
||||
|
||||
send_pub_key();
|
||||
}
|
||||
|
||||
static void prov_dh_key_gen(void)
|
||||
{
|
||||
uint8_t remote_pk_le[64], *remote_pk;
|
||||
|
||||
remote_pk = &bt_mesh_prov_link.conf_inputs[17];
|
||||
|
||||
/* Copy remote key in little-endian for bt_dh_key_gen().
|
||||
* X and Y halves are swapped independently. The bt_dh_key_gen()
|
||||
* will also take care of validating the remote public key.
|
||||
*/
|
||||
sys_memcpy_swap(remote_pk_le, remote_pk, 32);
|
||||
sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
|
||||
|
||||
if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
|
||||
BT_ERR("Failed to generate DHKey");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_pub_key(const uint8_t *data)
|
||||
{
|
||||
BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
|
||||
|
||||
/* PublicKeyProvisioner */
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[17], data, 64);
|
||||
|
||||
if (!bt_pub_key_get()) {
|
||||
/* Clear retransmit timer */
|
||||
bt_mesh_prov_link.bearer->clear_tx();
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
|
||||
BT_WARN("Waiting for local public key");
|
||||
return;
|
||||
}
|
||||
|
||||
prov_dh_key_gen();
|
||||
}
|
||||
|
||||
static void pub_key_ready(const uint8_t *pkey)
|
||||
{
|
||||
if (!pkey) {
|
||||
BT_WARN("Public key not available");
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Local public key ready");
|
||||
|
||||
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
|
||||
prov_dh_key_gen();
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_input_complete(void)
|
||||
{
|
||||
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
|
||||
NOTIFY_INPUT_COMPLETE) &&
|
||||
bt_mesh_prov->input_complete) {
|
||||
bt_mesh_prov->input_complete();
|
||||
}
|
||||
}
|
||||
|
||||
static void send_random(void)
|
||||
{
|
||||
struct os_mbuf *rnd = PROV_BUF(17);
|
||||
|
||||
bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
|
||||
net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
|
||||
|
||||
if (bt_mesh_prov_send(rnd, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Random");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_DATA;
|
||||
}
|
||||
|
||||
static void prov_random(const uint8_t *data)
|
||||
{
|
||||
uint8_t conf_verify[16];
|
||||
|
||||
BT_DBG("Remote Random: %s", bt_hex(data, 16));
|
||||
if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
|
||||
BT_ERR("Random value is identical to ours, rejecting.");
|
||||
prov_fail(PROV_ERR_CFM_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, data,
|
||||
bt_mesh_prov_link.auth, conf_verify)) {
|
||||
BT_ERR("Unable to calculate confirmation verification");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
|
||||
BT_ERR("Invalid confirmation value");
|
||||
BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
|
||||
BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
|
||||
prov_fail(PROV_ERR_CFM_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt, data,
|
||||
bt_mesh_prov_link.rand, bt_mesh_prov_link.prov_salt)) {
|
||||
BT_ERR("Failed to generate provisioning salt");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
|
||||
|
||||
send_random();
|
||||
}
|
||||
|
||||
static void prov_confirm(const uint8_t *data)
|
||||
{
|
||||
BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
|
||||
|
||||
memcpy(bt_mesh_prov_link.conf, data, 16);
|
||||
|
||||
notify_input_complete();
|
||||
|
||||
send_confirm();
|
||||
}
|
||||
|
||||
static inline bool is_pb_gatt(void)
|
||||
{
|
||||
return bt_mesh_prov_link.bearer &&
|
||||
bt_mesh_prov_link.bearer->type == BT_MESH_PROV_GATT;
|
||||
}
|
||||
|
||||
static void prov_data(const uint8_t *data)
|
||||
{
|
||||
struct os_mbuf *msg = PROV_BUF(1);
|
||||
uint8_t session_key[16];
|
||||
uint8_t nonce[13];
|
||||
uint8_t dev_key[16];
|
||||
uint8_t pdu[25];
|
||||
uint8_t flags;
|
||||
uint32_t iv_index;
|
||||
uint16_t addr;
|
||||
uint16_t net_idx;
|
||||
int err;
|
||||
bool identity_enable;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.prov_salt, session_key);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate session key");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
|
||||
|
||||
err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.prov_salt, nonce);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate session nonce");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Nonce: %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
|
||||
if (err) {
|
||||
BT_ERR("Unable to decrypt provisioning data");
|
||||
prov_fail(PROV_ERR_DECRYPT);
|
||||
return;
|
||||
}
|
||||
|
||||
err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.prov_salt, dev_key);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate device key");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
|
||||
|
||||
net_idx = sys_get_be16(&pdu[16]);
|
||||
flags = pdu[18];
|
||||
iv_index = sys_get_be32(&pdu[19]);
|
||||
addr = sys_get_be16(&pdu[23]);
|
||||
|
||||
BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
|
||||
net_idx, iv_index, addr);
|
||||
|
||||
bt_mesh_prov_buf_init(msg, PROV_COMPLETE);
|
||||
if (bt_mesh_prov_send(msg, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Complete");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore any further PDUs on this link */
|
||||
bt_mesh_prov_link.expect = PROV_NO_PDU;
|
||||
|
||||
/* Store info, since bt_mesh_provision() will end up clearing it */
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
|
||||
identity_enable = is_pb_gatt();
|
||||
} else {
|
||||
identity_enable = false;
|
||||
}
|
||||
|
||||
err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
|
||||
if (err) {
|
||||
BT_ERR("Failed to provision (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* After PB-GATT provisioning we should start advertising
|
||||
* using Node Identity.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
|
||||
bt_mesh_proxy_identity_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void local_input_complete(void)
|
||||
{
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT)) {
|
||||
send_input_complete();
|
||||
} else {
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_link_closed(void)
|
||||
{
|
||||
reset_state();
|
||||
}
|
||||
|
||||
static void prov_link_opened(void)
|
||||
{
|
||||
bt_mesh_prov_link.expect = PROV_INVITE;
|
||||
}
|
||||
|
||||
static const struct bt_mesh_prov_role role_device = {
|
||||
.input_complete = local_input_complete,
|
||||
.link_opened = prov_link_opened,
|
||||
.link_closed = prov_link_closed,
|
||||
.error = prov_fail,
|
||||
.op = {
|
||||
[PROV_INVITE] = prov_invite,
|
||||
[PROV_START] = prov_start,
|
||||
[PROV_PUB_KEY] = prov_pub_key,
|
||||
[PROV_CONFIRM] = prov_confirm,
|
||||
[PROV_RANDOM] = prov_random,
|
||||
[PROV_DATA] = prov_data,
|
||||
},
|
||||
};
|
||||
|
||||
int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
|
||||
{
|
||||
BT_DBG("bt_mesh_prov_enable");
|
||||
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
pb_adv.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
pb_gatt.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
|
||||
}
|
||||
|
||||
BT_DBG("bt_mesh_prov_link.role = &role_device");
|
||||
bt_mesh_prov_link.role = &role_device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
|
||||
{
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
bt_mesh_beacon_disable();
|
||||
bt_mesh_scan_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
bt_mesh_proxy_prov_disable(true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
746
src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c
Normal file
746
src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c
Normal file
@@ -0,0 +1,746 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Lingao Meng
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
|
||||
|
||||
#include "testing.h"
|
||||
|
||||
#include "crypto.h"
|
||||
#include "adv.h"
|
||||
#include "mesh/mesh.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "beacon.h"
|
||||
#include "access.h"
|
||||
#include "foundation.h"
|
||||
#include "proxy.h"
|
||||
#include "prov.h"
|
||||
#include "settings.h"
|
||||
|
||||
static struct {
|
||||
struct bt_mesh_cdb_node *node;
|
||||
uint16_t addr;
|
||||
uint16_t net_idx;
|
||||
uint8_t attention_duration;
|
||||
uint8_t uuid[16];
|
||||
} prov_device;
|
||||
|
||||
static void send_pub_key(void);
|
||||
static void prov_dh_key_gen(void);
|
||||
static void pub_key_ready(const uint8_t *pkey);
|
||||
|
||||
static int reset_state(void)
|
||||
{
|
||||
#if BLE_MESH_CDB
|
||||
if (prov_device.node != NULL) {
|
||||
bt_mesh_cdb_node_del(prov_device.node, false);
|
||||
}
|
||||
#endif
|
||||
return bt_mesh_prov_reset_state(pub_key_ready);
|
||||
}
|
||||
|
||||
static void prov_link_close(enum prov_bearer_link_status status)
|
||||
{
|
||||
BT_DBG("%u", status);
|
||||
bt_mesh_prov_link.expect = PROV_NO_PDU;
|
||||
|
||||
bt_mesh_prov_link.bearer->link_close(status);
|
||||
}
|
||||
|
||||
static void prov_fail(uint8_t reason)
|
||||
{
|
||||
/* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
|
||||
* provisioner just closes the link when something fails, while the
|
||||
* provisionee sends the fail message, and waits for the provisioner to
|
||||
* close the link.
|
||||
*/
|
||||
prov_link_close(PROV_BEARER_LINK_STATUS_FAIL);
|
||||
}
|
||||
|
||||
static void send_invite(void)
|
||||
{
|
||||
struct os_mbuf *inv = PROV_BUF(2);
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
bt_mesh_prov_buf_init(inv, PROV_INVITE);
|
||||
net_buf_simple_add_u8(inv, prov_device.attention_duration);
|
||||
|
||||
bt_mesh_prov_link.conf_inputs[0] = prov_device.attention_duration;
|
||||
|
||||
if (bt_mesh_prov_send(inv, NULL)) {
|
||||
BT_ERR("Failed to send invite");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_CAPABILITIES;
|
||||
}
|
||||
|
||||
static void start_sent(int err, void *cb_data)
|
||||
{
|
||||
if (!bt_pub_key_get()) {
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
|
||||
BT_WARN("Waiting for local public key");
|
||||
} else {
|
||||
send_pub_key();
|
||||
}
|
||||
}
|
||||
|
||||
static void send_start(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
uint8_t method, action;
|
||||
struct os_mbuf *start = PROV_BUF(6);
|
||||
|
||||
const uint8_t *data = &bt_mesh_prov_link.conf_inputs[1 + 3];
|
||||
|
||||
bt_mesh_prov_buf_init(start, PROV_START);
|
||||
net_buf_simple_add_u8(start, PROV_ALG_P256);
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) &&
|
||||
*data == PUB_KEY_OOB) {
|
||||
net_buf_simple_add_u8(start, PUB_KEY_OOB);
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY);
|
||||
} else {
|
||||
net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
|
||||
method = AUTH_METHOD_OUTPUT;
|
||||
if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
|
||||
action = OUTPUT_OOB_STRING;
|
||||
} else {
|
||||
action = OUTPUT_OOB_NUMBER;
|
||||
}
|
||||
|
||||
} else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
|
||||
method = AUTH_METHOD_INPUT;
|
||||
if (bt_mesh_prov_link.oob_action == OUTPUT_OOB_STRING) {
|
||||
action = INPUT_OOB_STRING;
|
||||
} else {
|
||||
action = INPUT_OOB_NUMBER;
|
||||
}
|
||||
} else {
|
||||
method = bt_mesh_prov_link.oob_method;
|
||||
action = 0x00;
|
||||
}
|
||||
|
||||
net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_method);
|
||||
|
||||
net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_action);
|
||||
|
||||
net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_size);
|
||||
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[12], &start->om_data[1], 5);
|
||||
|
||||
if (bt_mesh_prov_auth(method, action, bt_mesh_prov_link.oob_size) < 0) {
|
||||
BT_ERR("Invalid authentication method: 0x%02x; "
|
||||
"action: 0x%02x; size: 0x%02x", method,
|
||||
action, bt_mesh_prov_link.oob_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_send(start, start_sent)) {
|
||||
BT_ERR("Failed to send Provisioning Start");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static bool prov_check_method(struct bt_mesh_dev_capabilities *caps)
|
||||
{
|
||||
if (bt_mesh_prov_link.oob_method == AUTH_METHOD_STATIC) {
|
||||
if (!caps->static_oob) {
|
||||
BT_WARN("Device not support OOB static authentication provisioning");
|
||||
return false;
|
||||
}
|
||||
} else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
|
||||
if (bt_mesh_prov_link.oob_size > caps->input_size) {
|
||||
BT_WARN("The required input length (0x%02x) "
|
||||
"exceeds the device capacity (0x%02x)",
|
||||
bt_mesh_prov_link.oob_size, caps->input_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(BIT(bt_mesh_prov_link.oob_action) & caps->input_actions)) {
|
||||
BT_WARN("The required input action (0x%02x) "
|
||||
"not supported by the device (0x%02x)",
|
||||
bt_mesh_prov_link.oob_action, caps->input_actions);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
|
||||
if (!bt_mesh_prov->output_string) {
|
||||
BT_WARN("Not support output string");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!bt_mesh_prov->output_number) {
|
||||
BT_WARN("Not support output number");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
|
||||
if (bt_mesh_prov_link.oob_size > caps->output_size) {
|
||||
BT_WARN("The required output length (0x%02x) "
|
||||
"exceeds the device capacity (0x%02x)",
|
||||
bt_mesh_prov_link.oob_size, caps->output_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(BIT(bt_mesh_prov_link.oob_action) & caps->output_actions)) {
|
||||
BT_WARN("The required output action (0x%02x) "
|
||||
"not supported by the device (0x%02x)",
|
||||
bt_mesh_prov_link.oob_action, caps->output_actions);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bt_mesh_prov->input) {
|
||||
BT_WARN("Not support input");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void prov_capabilities(const uint8_t *data)
|
||||
{
|
||||
struct bt_mesh_dev_capabilities caps;
|
||||
|
||||
caps.elem_count = data[0];
|
||||
BT_DBG("Elements: %u", caps.elem_count);
|
||||
|
||||
caps.algorithms = sys_get_be16(&data[1]);
|
||||
BT_DBG("Algorithms: %u", caps.algorithms);
|
||||
|
||||
caps.pub_key_type = data[3];
|
||||
caps.static_oob = data[4];
|
||||
caps.output_size = data[5];
|
||||
BT_DBG("Public Key Type: 0x%02x", caps.pub_key_type);
|
||||
BT_DBG("Static OOB Type: 0x%02x", caps.static_oob);
|
||||
BT_DBG("Output OOB Size: %u", caps.output_size);
|
||||
|
||||
caps.output_actions = (bt_mesh_output_action_t)data[6];
|
||||
caps.input_size = data[8];
|
||||
caps.input_actions = (bt_mesh_input_action_t)data[9];
|
||||
BT_DBG("Output OOB Action: 0x%04x", caps.output_actions);
|
||||
BT_DBG("Input OOB Size: %u", caps.input_size);
|
||||
BT_DBG("Input OOB Action: 0x%04x", caps.input_actions);
|
||||
|
||||
if (data[0] == 0) {
|
||||
BT_ERR("Invalid number of elements");
|
||||
prov_fail(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
#if BLE_MESH_CDB
|
||||
prov_device.node =
|
||||
bt_mesh_cdb_node_alloc(prov_device.uuid,
|
||||
prov_device.addr, data[0],
|
||||
prov_device.net_idx);
|
||||
if (prov_device.node == NULL) {
|
||||
BT_ERR("Failed allocating node 0x%04x", prov_device.addr);
|
||||
prov_fail(PROV_ERR_RESOURCES);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[1], data, 11);
|
||||
|
||||
if (bt_mesh_prov->capabilities) {
|
||||
bt_mesh_prov->capabilities(&caps);
|
||||
}
|
||||
|
||||
if (!prov_check_method(&caps)) {
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
send_start();
|
||||
}
|
||||
|
||||
static void send_confirm(void)
|
||||
{
|
||||
struct os_mbuf *cfm = PROV_BUF(17);
|
||||
|
||||
BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64));
|
||||
BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64));
|
||||
BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17));
|
||||
|
||||
if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
|
||||
bt_mesh_prov_link.conf_salt)) {
|
||||
BT_ERR("Unable to generate confirmation salt");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
|
||||
|
||||
if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.conf_salt, bt_mesh_prov_link.conf_key)) {
|
||||
BT_ERR("Unable to generate confirmation key");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
|
||||
|
||||
if (bt_rand(bt_mesh_prov_link.rand, 16)) {
|
||||
BT_ERR("Unable to generate random number");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
|
||||
|
||||
bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
|
||||
|
||||
if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
|
||||
bt_mesh_prov_link.rand, bt_mesh_prov_link.auth,
|
||||
net_buf_simple_add(cfm, 16))) {
|
||||
BT_ERR("Unable to generate confirmation value");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_send(cfm, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Confirm");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_CONFIRM;
|
||||
}
|
||||
|
||||
static void public_key_sent(int err, void *cb_data)
|
||||
{
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY) &&
|
||||
atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
|
||||
prov_dh_key_gen();
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_PUB_KEY;
|
||||
}
|
||||
|
||||
static void send_pub_key(void)
|
||||
{
|
||||
struct os_mbuf *buf = PROV_BUF(65);
|
||||
const uint8_t *key;
|
||||
|
||||
key = bt_pub_key_get();
|
||||
if (!key) {
|
||||
BT_ERR("No public key available");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
|
||||
|
||||
bt_mesh_prov_buf_init(buf, PROV_PUB_KEY);
|
||||
|
||||
/* Swap X and Y halves independently to big-endian */
|
||||
sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
|
||||
sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
|
||||
|
||||
/* PublicKeyProvisioner */
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_databuf[1], 64);
|
||||
|
||||
if (bt_mesh_prov_send(buf, public_key_sent)) {
|
||||
BT_ERR("Failed to send Public Key");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_dh_key_cb(const uint8_t dhkey[32])
|
||||
{
|
||||
BT_DBG("%p", dhkey);
|
||||
|
||||
if (!dhkey) {
|
||||
BT_ERR("DHKey generation failed");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
|
||||
|
||||
BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) ||
|
||||
atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
|
||||
atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM);
|
||||
return;
|
||||
}
|
||||
|
||||
send_confirm();
|
||||
}
|
||||
|
||||
static void prov_dh_key_gen(void)
|
||||
{
|
||||
uint8_t remote_pk_le[64], *remote_pk;
|
||||
|
||||
remote_pk = &bt_mesh_prov_link.conf_inputs[81];
|
||||
|
||||
/* Copy remote key in little-endian for bt_dh_key_gen().
|
||||
* X and Y halves are swapped independently. The bt_dh_key_gen()
|
||||
* will also take care of validating the remote public key.
|
||||
*/
|
||||
sys_memcpy_swap(remote_pk_le, remote_pk, 32);
|
||||
sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
|
||||
|
||||
if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
|
||||
BT_ERR("Failed to generate DHKey");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
|
||||
bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_pub_key(const uint8_t *data)
|
||||
{
|
||||
BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
|
||||
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY);
|
||||
|
||||
/* PublicKeyDevice */
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[81], data, 64);
|
||||
bt_mesh_prov_link.bearer->clear_tx();
|
||||
|
||||
prov_dh_key_gen();
|
||||
}
|
||||
|
||||
static void pub_key_ready(const uint8_t *pkey)
|
||||
{
|
||||
if (!pkey) {
|
||||
BT_WARN("Public key not available");
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Local public key ready");
|
||||
|
||||
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
|
||||
send_pub_key();
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_input_complete(void)
|
||||
{
|
||||
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
|
||||
NOTIFY_INPUT_COMPLETE) &&
|
||||
bt_mesh_prov->input_complete) {
|
||||
bt_mesh_prov->input_complete();
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_input_complete(const uint8_t *data)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
notify_input_complete();
|
||||
|
||||
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
|
||||
send_confirm();
|
||||
}
|
||||
}
|
||||
|
||||
static void send_prov_data(void)
|
||||
{
|
||||
struct os_mbuf *pdu = PROV_BUF(34);
|
||||
#if BLE_MESH_CDB
|
||||
struct bt_mesh_cdb_subnet *sub;
|
||||
#endif
|
||||
uint8_t session_key[16];
|
||||
uint8_t nonce[13];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.prov_salt, session_key);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate session key");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
|
||||
|
||||
err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.prov_salt, nonce);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate session nonce");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Nonce: %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
|
||||
bt_mesh_prov_link.prov_salt, prov_device.node->dev_key);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate device key");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("DevKey: %s", bt_hex(prov_device.node->dev_key, 16));
|
||||
#if BLE_MESH_CDB
|
||||
sub = bt_mesh_cdb_subnet_get(prov_device.node->net_idx);
|
||||
if (sub == NULL) {
|
||||
BT_ERR("No subnet with net_idx %u",
|
||||
prov_device.node->net_idx);
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bt_mesh_prov_buf_init(pdu, PROV_DATA);
|
||||
#if BLE_MESH_CDB
|
||||
net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net_key, 16);
|
||||
net_buf_simple_add_be16(pdu, prov_device.node->net_idx);
|
||||
net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub));
|
||||
net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index);
|
||||
#endif
|
||||
net_buf_simple_add_be16(pdu, prov_device.node->addr);
|
||||
net_buf_simple_add(pdu, 8); /* For MIC */
|
||||
|
||||
BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
|
||||
prov_device.node->net_idx, bt_mesh.iv_index,
|
||||
prov_device.node->addr);
|
||||
|
||||
err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
|
||||
&pdu->om_data[1]);
|
||||
if (err) {
|
||||
BT_ERR("Unable to encrypt provisioning data");
|
||||
prov_fail(PROV_ERR_DECRYPT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_send(pdu, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Data");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_COMPLETE;
|
||||
}
|
||||
|
||||
static void prov_complete(const uint8_t *data)
|
||||
{
|
||||
struct bt_mesh_cdb_node *node = prov_device.node;
|
||||
|
||||
BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
|
||||
bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
|
||||
node->addr);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_cdb_node(node);
|
||||
}
|
||||
|
||||
prov_device.node = NULL;
|
||||
prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS);
|
||||
|
||||
if (bt_mesh_prov->node_added) {
|
||||
bt_mesh_prov->node_added(node->net_idx, node->uuid, node->addr,
|
||||
node->num_elem);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_random(void)
|
||||
{
|
||||
struct os_mbuf *rnd = PROV_BUF(17);
|
||||
|
||||
bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
|
||||
net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
|
||||
|
||||
if (bt_mesh_prov_send(rnd, NULL)) {
|
||||
BT_ERR("Failed to send Provisioning Random");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_prov_link.expect = PROV_RANDOM;
|
||||
}
|
||||
|
||||
static void prov_random(const uint8_t *data)
|
||||
{
|
||||
uint8_t conf_verify[16];
|
||||
|
||||
BT_DBG("Remote Random: %s", bt_hex(data, 16));
|
||||
if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
|
||||
BT_ERR("Random value is identical to ours, rejecting.");
|
||||
prov_fail(PROV_ERR_CFM_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
|
||||
data, bt_mesh_prov_link.auth, conf_verify)) {
|
||||
BT_ERR("Unable to calculate confirmation verification");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
|
||||
BT_ERR("Invalid confirmation value");
|
||||
BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
|
||||
BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
|
||||
prov_fail(PROV_ERR_CFM_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt,
|
||||
bt_mesh_prov_link.rand, data, bt_mesh_prov_link.prov_salt)) {
|
||||
BT_ERR("Failed to generate provisioning salt");
|
||||
prov_fail(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
|
||||
|
||||
send_prov_data();
|
||||
}
|
||||
|
||||
static void prov_confirm(const uint8_t *data)
|
||||
{
|
||||
BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
|
||||
|
||||
memcpy(bt_mesh_prov_link.conf, data, 16);
|
||||
|
||||
send_random();
|
||||
}
|
||||
|
||||
static void prov_failed(const uint8_t *data)
|
||||
{
|
||||
BT_WARN("Error: 0x%02x", data[0]);
|
||||
reset_state();
|
||||
}
|
||||
|
||||
static void local_input_complete(void)
|
||||
{
|
||||
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
|
||||
send_confirm();
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_link_closed(void)
|
||||
{
|
||||
reset_state();
|
||||
}
|
||||
|
||||
static void prov_link_opened(void)
|
||||
{
|
||||
send_invite();
|
||||
}
|
||||
|
||||
static const struct bt_mesh_prov_role role_provisioner = {
|
||||
.input_complete = local_input_complete,
|
||||
.link_opened = prov_link_opened,
|
||||
.link_closed = prov_link_closed,
|
||||
.error = prov_fail,
|
||||
.op = {
|
||||
[PROV_CAPABILITIES] = prov_capabilities,
|
||||
[PROV_PUB_KEY] = prov_pub_key,
|
||||
[PROV_INPUT_COMPLETE] = prov_input_complete,
|
||||
[PROV_CONFIRM] = prov_confirm,
|
||||
[PROV_RANDOM] = prov_random,
|
||||
[PROV_COMPLETE] = prov_complete,
|
||||
[PROV_FAILED] = prov_failed,
|
||||
},
|
||||
};
|
||||
|
||||
static void prov_set_method(uint8_t method, uint8_t action, uint8_t size)
|
||||
{
|
||||
bt_mesh_prov_link.oob_method = method;
|
||||
bt_mesh_prov_link.oob_action = action;
|
||||
bt_mesh_prov_link.oob_size = size;
|
||||
}
|
||||
|
||||
int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size)
|
||||
{
|
||||
if (!action || !size || size > 8) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prov_set_method(AUTH_METHOD_INPUT, find_msb_set(action) - 1, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size)
|
||||
{
|
||||
if (!action || !size || size > 8) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prov_set_method(AUTH_METHOD_OUTPUT, find_msb_set(action) - 1, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size)
|
||||
{
|
||||
if (!size || !static_val || size > 16) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prov_set_method(AUTH_METHOD_STATIC, 0, 0);
|
||||
|
||||
memcpy(bt_mesh_prov_link.auth + 16 - size, static_val, size);
|
||||
if (size < 16) {
|
||||
(void)memset(bt_mesh_prov_link.auth, 0,
|
||||
sizeof(bt_mesh_prov_link.auth) - size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_auth_method_set_none(void)
|
||||
{
|
||||
prov_set_method(AUTH_METHOD_NO_OOB, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64])
|
||||
{
|
||||
if (public_key == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
/* Swap X and Y halves independently to big-endian */
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 32);
|
||||
memcpy(&bt_mesh_prov_link.conf_inputs[81 + 32], &public_key[32], 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_MESH_PB_ADV)
|
||||
int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
|
||||
uint8_t attention_duration)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER);
|
||||
memcpy(prov_device.uuid, uuid, 16);
|
||||
prov_device.addr = addr;
|
||||
prov_device.net_idx = net_idx;
|
||||
prov_device.attention_duration = attention_duration;
|
||||
bt_mesh_prov_link.bearer = &pb_adv;
|
||||
bt_mesh_prov_link.role = &role_provisioner;
|
||||
|
||||
err = bt_mesh_prov_link.bearer->link_open(prov_device.uuid, PROTOCOL_TIMEOUT,
|
||||
bt_mesh_prov_bearer_cb_get(), NULL);
|
||||
if (err) {
|
||||
atomic_clear_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
10
src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h
Normal file
10
src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
|
||||
uint8_t attention_duration);
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "mesh_priv.h"
|
||||
#include "adv.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "prov.h"
|
||||
#include "beacon.h"
|
||||
#include "foundation.h"
|
||||
@@ -28,6 +29,9 @@
|
||||
#define PDU_TYPE(data) (data[0] & BIT_MASK(6))
|
||||
#define PDU_SAR(data) (data[0] >> 6)
|
||||
|
||||
#define BT_UUID_16_ENCODE(w16) \
|
||||
(((w16) >> 0) & 0xFF), \
|
||||
(((w16) >> 8) & 0xFF)
|
||||
/* Mesh Profile 1.0 Section 6.6:
|
||||
* "The timeout for the SAR transfer is 20 seconds. When the timeout
|
||||
* expires, the Proxy Server shall disconnect."
|
||||
@@ -110,14 +114,14 @@ static bool prov_fast_adv;
|
||||
|
||||
static struct bt_mesh_proxy_client {
|
||||
uint16_t conn_handle;
|
||||
u16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
|
||||
uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
|
||||
enum __packed {
|
||||
NONE,
|
||||
WHITELIST,
|
||||
BLACKLIST,
|
||||
PROV,
|
||||
} filter_type;
|
||||
u8_t msg_type;
|
||||
uint8_t msg_type;
|
||||
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
|
||||
struct ble_npl_callout send_beacons;
|
||||
#endif
|
||||
@@ -127,6 +131,9 @@ static struct bt_mesh_proxy_client {
|
||||
[0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 },
|
||||
};
|
||||
|
||||
static sys_slist_t idle_waiters;
|
||||
static atomic_t pending_notifications;
|
||||
|
||||
/* Track which service is enabled */
|
||||
static enum {
|
||||
MESH_GATT_NONE,
|
||||
@@ -195,15 +202,15 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle)
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
|
||||
/* Next subnet in queue to be advertised */
|
||||
static int next_idx;
|
||||
static struct bt_mesh_subnet *beacon_sub;
|
||||
|
||||
static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
|
||||
static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
|
||||
struct os_mbuf *msg);
|
||||
|
||||
static int filter_set(struct bt_mesh_proxy_client *client,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
u8_t type;
|
||||
uint8_t type;
|
||||
|
||||
if (buf->om_len < 1) {
|
||||
BT_WARN("Too short Filter Set message");
|
||||
@@ -230,7 +237,7 @@ static int filter_set(struct bt_mesh_proxy_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
|
||||
static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -254,7 +261,7 @@ static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
|
||||
}
|
||||
}
|
||||
|
||||
static void filter_remove(struct bt_mesh_proxy_client *client, u16_t addr)
|
||||
static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -281,7 +288,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client,
|
||||
.ctx = &rx->ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
};
|
||||
u16_t filter_size;
|
||||
uint16_t filter_size;
|
||||
int i, err;
|
||||
|
||||
/* Configuration messages always have dst unassigned */
|
||||
@@ -323,7 +330,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
|
||||
{
|
||||
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
|
||||
struct bt_mesh_net_rx rx;
|
||||
u8_t opcode;
|
||||
uint8_t opcode;
|
||||
int err;
|
||||
|
||||
err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG,
|
||||
@@ -333,8 +340,16 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
|
||||
goto done;
|
||||
}
|
||||
|
||||
rx.local_match = 1U;
|
||||
|
||||
if (bt_mesh_rpl_check(&rx, NULL)) {
|
||||
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
|
||||
rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Remove network headers */
|
||||
net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
|
||||
net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN);
|
||||
|
||||
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
@@ -351,7 +366,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
|
||||
break;
|
||||
case CFG_FILTER_ADD:
|
||||
while (buf->om_len >= 2) {
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
|
||||
addr = net_buf_simple_pull_be16(buf);
|
||||
filter_add(client, addr);
|
||||
@@ -360,7 +375,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
|
||||
break;
|
||||
case CFG_FILTER_REMOVE:
|
||||
while (buf->om_len >= 2) {
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
|
||||
addr = net_buf_simple_pull_be16(buf);
|
||||
filter_remove(client, addr);
|
||||
@@ -389,21 +404,20 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_proxy_client *client = cb_data;
|
||||
|
||||
return beacon_send(client->conn_handle, sub);
|
||||
}
|
||||
|
||||
static void proxy_send_beacons(struct ble_npl_event *work)
|
||||
{
|
||||
struct bt_mesh_proxy_client *client;
|
||||
int i;
|
||||
|
||||
|
||||
client = ble_npl_event_get_arg(work);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx != BT_MESH_KEY_UNUSED) {
|
||||
beacon_send(client->conn_handle, sub);
|
||||
}
|
||||
}
|
||||
(void)bt_mesh_subnet_find(send_beacon_cb, client);
|
||||
}
|
||||
|
||||
static void proxy_sar_timeout(struct ble_npl_event *work)
|
||||
@@ -429,12 +443,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
|
||||
|
||||
if (!sub) {
|
||||
/* NULL means we send on all subnets */
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
|
||||
bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -445,13 +454,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
|
||||
static void node_id_start(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
|
||||
sub->node_id_start = k_uptime_get_32();
|
||||
}
|
||||
|
||||
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
node_id_start(sub);
|
||||
/* Prioritize the recently enabled subnet */
|
||||
next_idx = sub - bt_mesh.sub;
|
||||
beacon_sub = sub;
|
||||
}
|
||||
|
||||
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
|
||||
@@ -462,30 +475,13 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
|
||||
|
||||
int bt_mesh_proxy_identity_enable(void)
|
||||
{
|
||||
int i, count = 0;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!bt_mesh_is_provisioned()) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bt_mesh_proxy_identity_start(sub);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
if (bt_mesh_subnet_foreach(node_id_start)) {
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
@@ -528,9 +524,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
|
||||
static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
struct bt_mesh_proxy_client *client;
|
||||
const u8_t *data = ctxt->om->om_data;
|
||||
u16_t len = ctxt->om->om_len;
|
||||
struct bt_mesh_proxy_client *client = find_client(conn_handle);
|
||||
const uint8_t *data = ctxt->om->om_data;
|
||||
uint16_t len = ctxt->om->om_len;
|
||||
|
||||
client = find_client(conn_handle);
|
||||
|
||||
@@ -652,7 +648,9 @@ static void proxy_connected(uint16_t conn_handle)
|
||||
static void proxy_disconnected(uint16_t conn_handle, int reason)
|
||||
{
|
||||
int i;
|
||||
bool disconnected = false;
|
||||
|
||||
BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason);
|
||||
conn_count--;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clients); i++) {
|
||||
struct bt_mesh_proxy_client *client = &clients[i];
|
||||
@@ -665,16 +663,11 @@ static void proxy_disconnected(uint16_t conn_handle, int reason)
|
||||
|
||||
k_delayed_work_cancel(&client->sar_timer);
|
||||
client->conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||
conn_count--;
|
||||
disconnected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (disconnected) {
|
||||
BT_INFO("conn_handle %d reason %d", conn_handle, reason);
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
struct os_mbuf *bt_mesh_proxy_get_buf(void)
|
||||
@@ -887,7 +880,7 @@ int bt_mesh_proxy_gatt_disable(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
|
||||
void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr)
|
||||
{
|
||||
struct bt_mesh_proxy_client *client = NULL;
|
||||
int i;
|
||||
@@ -911,7 +904,7 @@ void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
|
||||
}
|
||||
|
||||
static bool client_filter_match(struct bt_mesh_proxy_client *client,
|
||||
u16_t addr)
|
||||
uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -942,7 +935,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
|
||||
bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst)
|
||||
{
|
||||
bool relayed = false;
|
||||
int i;
|
||||
@@ -978,9 +971,25 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */
|
||||
|
||||
static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
|
||||
static void notify_complete(void)
|
||||
{
|
||||
sys_snode_t *n;
|
||||
|
||||
if (atomic_dec(&pending_notifications) > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
while ((n = sys_slist_get(&idle_waiters))) {
|
||||
CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb();
|
||||
}
|
||||
}
|
||||
|
||||
static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len)
|
||||
{
|
||||
struct os_mbuf *om;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("%u bytes: %s", len, bt_hex(data, len));
|
||||
|
||||
@@ -988,7 +997,8 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
|
||||
if (gatt_svc == MESH_GATT_PROXY) {
|
||||
om = ble_hs_mbuf_from_flat(data, len);
|
||||
assert(om);
|
||||
ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
|
||||
err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
|
||||
notify_complete();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -996,17 +1006,22 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
|
||||
if (gatt_svc == MESH_GATT_PROV) {
|
||||
om = ble_hs_mbuf_from_flat(data, len);
|
||||
assert(om);
|
||||
ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
|
||||
err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
|
||||
notify_complete();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
if (!err) {
|
||||
atomic_inc(&pending_notifications);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
|
||||
static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
|
||||
struct os_mbuf *msg)
|
||||
{
|
||||
u16_t mtu;
|
||||
uint16_t mtu;
|
||||
|
||||
BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len,
|
||||
bt_hex(msg->om_data, msg->om_len));
|
||||
@@ -1020,7 +1035,7 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
|
||||
|
||||
net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
|
||||
proxy_send(conn_handle, msg->om_data, mtu);
|
||||
net_buf_simple_pull(msg, mtu);
|
||||
net_buf_simple_pull_mem(msg, mtu);
|
||||
|
||||
while (msg->om_len) {
|
||||
if (msg->om_len + 1 < mtu) {
|
||||
@@ -1031,13 +1046,13 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
|
||||
|
||||
net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
|
||||
proxy_send(conn_handle, msg->om_data, mtu);
|
||||
net_buf_simple_pull(msg, mtu);
|
||||
net_buf_simple_pull_mem(msg, mtu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
|
||||
int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type,
|
||||
struct os_mbuf *msg)
|
||||
{
|
||||
struct bt_mesh_proxy_client *client = find_client(conn_handle);
|
||||
@@ -1056,11 +1071,14 @@ int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
|
||||
static u8_t prov_svc_data[20] = { 0x27, 0x18, };
|
||||
static uint8_t prov_svc_data[20] = {
|
||||
BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL),
|
||||
};
|
||||
|
||||
static const struct bt_data prov_ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x27, 0x18),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL,
|
||||
BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)),
|
||||
BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
|
||||
};
|
||||
#endif /* PB_GATT */
|
||||
@@ -1075,23 +1093,27 @@ static const struct bt_data prov_ad[] = {
|
||||
|
||||
#define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT)
|
||||
|
||||
static u8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, };
|
||||
static uint8_t proxy_svc_data[NODE_ID_LEN] = {
|
||||
BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL),
|
||||
};
|
||||
|
||||
static const struct bt_data node_id_ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL,
|
||||
BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
|
||||
BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN),
|
||||
};
|
||||
|
||||
static const struct bt_data net_id_ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL,
|
||||
BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
|
||||
BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
|
||||
};
|
||||
|
||||
static int node_id_adv(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
u8_t tmp[16];
|
||||
uint8_t tmp[16];
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
@@ -1107,7 +1129,8 @@ static int node_id_adv(struct bt_mesh_subnet *sub)
|
||||
memcpy(tmp + 6, proxy_svc_data + 11, 8);
|
||||
sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
|
||||
|
||||
err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
|
||||
err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp,
|
||||
tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -1135,9 +1158,9 @@ static int net_id_adv(struct bt_mesh_subnet *sub)
|
||||
proxy_svc_data[2] = ID_TYPE_NET;
|
||||
|
||||
BT_DBG("Advertising with NetId %s",
|
||||
bt_hex(sub->keys[sub->kr_flag].net_id, 8));
|
||||
bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8));
|
||||
|
||||
memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
|
||||
memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8);
|
||||
|
||||
err = bt_le_adv_start(&slow_adv_param, net_id_ad,
|
||||
ARRAY_SIZE(net_id_ad), NULL, 0);
|
||||
@@ -1158,60 +1181,75 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub)
|
||||
}
|
||||
|
||||
return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
|
||||
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED);
|
||||
bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
|
||||
}
|
||||
|
||||
static struct bt_mesh_subnet *next_sub(void)
|
||||
{
|
||||
int i;
|
||||
struct bt_mesh_subnet *sub = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)];
|
||||
if (advertise_subnet(sub)) {
|
||||
next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub);
|
||||
return sub;
|
||||
if (!beacon_sub) {
|
||||
beacon_sub = bt_mesh_subnet_next(NULL);
|
||||
if (!beacon_sub) {
|
||||
/* No valid subnets */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
sub = beacon_sub;
|
||||
do {
|
||||
if (advertise_subnet(sub)) {
|
||||
beacon_sub = sub;
|
||||
return sub;
|
||||
}
|
||||
|
||||
sub = bt_mesh_subnet_next(sub);
|
||||
} while (sub != beacon_sub);
|
||||
|
||||
/* No subnets to advertise on */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sub_count(void)
|
||||
static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data)
|
||||
{
|
||||
int i, count = 0;
|
||||
int *count = cb_data;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (advertise_subnet(sub)) {
|
||||
count++;
|
||||
}
|
||||
if (advertise_subnet(sub)) {
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sub_count(void)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
(void)bt_mesh_subnet_find(sub_count_cb, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
|
||||
static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
s32_t remaining = K_FOREVER;
|
||||
int32_t remaining = K_FOREVER;
|
||||
int subnet_count;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (conn_count == CONFIG_BT_MAX_CONN) {
|
||||
BT_DBG("Connectable advertising deferred (max connections)");
|
||||
return remaining;
|
||||
BT_DBG("Connectable advertising deferred (max connections %d)", conn_count);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub);
|
||||
if (!sub) {
|
||||
BT_WARN("No subnets to advertise on");
|
||||
return remaining;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
|
||||
u32_t active = k_uptime_get_32() - sub->node_id_start;
|
||||
uint32_t active = k_uptime_get_32() - sub->node_id_start;
|
||||
|
||||
if (active < NODE_ID_TIMEOUT) {
|
||||
remaining = NODE_ID_TIMEOUT - active;
|
||||
@@ -1231,7 +1269,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
|
||||
subnet_count = sub_count();
|
||||
BT_DBG("sub_count %u", subnet_count);
|
||||
if (subnet_count > 1) {
|
||||
s32_t max_timeout;
|
||||
int32_t max_timeout;
|
||||
|
||||
/* We use NODE_ID_TIMEOUT as a starting point since it may
|
||||
* be less than 60 seconds. Divide this period into at least
|
||||
@@ -1249,6 +1287,8 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
|
||||
BT_DBG("Advertising %d ms for net_idx 0x%04x",
|
||||
(int) remaining, sub->net_idx);
|
||||
|
||||
beacon_sub = bt_mesh_subnet_next(beacon_sub);
|
||||
|
||||
return remaining;
|
||||
}
|
||||
#endif /* GATT_PROXY */
|
||||
@@ -1299,7 +1339,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2])
|
||||
}
|
||||
#endif /* PB_GATT */
|
||||
|
||||
s32_t bt_mesh_proxy_adv_start(void)
|
||||
int32_t bt_mesh_proxy_adv_start(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
@@ -1361,6 +1401,19 @@ void bt_mesh_proxy_adv_stop(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_MESH_GATT_PROXY)
|
||||
static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
if (evt == BT_MESH_KEY_DELETED) {
|
||||
if (sub == beacon_sub) {
|
||||
beacon_sub = NULL;
|
||||
}
|
||||
} else {
|
||||
bt_mesh_proxy_beacon_send(sub);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
@@ -1477,6 +1530,12 @@ int bt_mesh_proxy_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
|
||||
if (!bt_mesh_subnet_cb_list[4]) {
|
||||
bt_mesh_subnet_cb_list[4] = subnet_evt;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) {
|
||||
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
|
||||
k_work_init(&clients[i].send_beacons, proxy_send_beacons);
|
||||
@@ -1496,4 +1555,14 @@ int bt_mesh_proxy_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb)
|
||||
{
|
||||
if (!atomic_get(&pending_notifications)) {
|
||||
cb->cb();
|
||||
return;
|
||||
}
|
||||
|
||||
sys_slist_append(&idle_waiters, &cb->n);
|
||||
}
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */
|
||||
|
||||
@@ -15,8 +15,14 @@
|
||||
#define BT_MESH_PROXY_PROV 0x03
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh/slist.h"
|
||||
|
||||
int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg);
|
||||
struct bt_mesh_proxy_idle_cb {
|
||||
sys_snode_t n;
|
||||
void (*cb)(void);
|
||||
};
|
||||
|
||||
int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg);
|
||||
|
||||
int bt_mesh_proxy_prov_enable(void);
|
||||
int bt_mesh_proxy_prov_disable(bool disconnect);
|
||||
@@ -29,16 +35,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub);
|
||||
|
||||
struct os_mbuf *bt_mesh_proxy_get_buf(void);
|
||||
|
||||
s32_t bt_mesh_proxy_adv_start(void);
|
||||
int32_t bt_mesh_proxy_adv_start(void);
|
||||
void bt_mesh_proxy_adv_stop(void);
|
||||
|
||||
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub);
|
||||
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub);
|
||||
|
||||
bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst);
|
||||
void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr);
|
||||
bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst);
|
||||
void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr);
|
||||
|
||||
int bt_mesh_proxy_init(void);
|
||||
void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb);
|
||||
|
||||
int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg);
|
||||
|
||||
|
||||
162
src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c
Normal file
162
src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Lingao Meng
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define MESH_LOG_MODULE BLE_MESH_RPL_LOG
|
||||
|
||||
#include "log/log.h"
|
||||
|
||||
#include "mesh_priv.h"
|
||||
#include "adv.h"
|
||||
#include "net.h"
|
||||
#include "rpl.h"
|
||||
#include "settings.h"
|
||||
|
||||
static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)];
|
||||
|
||||
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
|
||||
struct bt_mesh_net_rx *rx)
|
||||
{
|
||||
rpl->src = rx->ctx.addr;
|
||||
rpl->seq = rx->seq;
|
||||
rpl->old_iv = rx->old_iv;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_rpl(rpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the Replay Protection List for a replay attempt. If non-NULL match
|
||||
* parameter is given the RPL slot is returned but it is not immediately
|
||||
* updated (needed for segmented messages), whereas if a NULL match is given
|
||||
* the RPL is immediately updated (used for unsegmented messages).
|
||||
*/
|
||||
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
|
||||
struct bt_mesh_rpl **match)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Don't bother checking messages from ourselves */
|
||||
if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The RPL is used only for the local node */
|
||||
if (!rx->local_match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
|
||||
struct bt_mesh_rpl *rpl = &replay_list[i];
|
||||
|
||||
/* Empty slot */
|
||||
if (!rpl->src) {
|
||||
if (match) {
|
||||
*match = rpl;
|
||||
} else {
|
||||
bt_mesh_rpl_update(rpl, rx);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Existing slot for given address */
|
||||
if (rpl->src == rx->ctx.addr) {
|
||||
if (rx->old_iv && !rpl->old_iv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!rx->old_iv && rpl->old_iv) ||
|
||||
rpl->seq < rx->seq) {
|
||||
if (match) {
|
||||
*match = rpl;
|
||||
} else {
|
||||
bt_mesh_rpl_update(rpl, rx);
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BT_ERR("RPL is full!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void bt_mesh_rpl_clear(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_rpl();
|
||||
} else {
|
||||
(void)memset(replay_list, 0, sizeof(replay_list));
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
|
||||
if (replay_list[i].src == src) {
|
||||
return &replay_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
|
||||
if (!replay_list[i].src) {
|
||||
replay_list[i].src = src;
|
||||
return &replay_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
|
||||
func(&replay_list[i], user_data);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_rpl_reset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Discard "old old" IV Index entries from RPL and flag
|
||||
* any other ones (which are valid) as old.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
|
||||
struct bt_mesh_rpl *rpl = &replay_list[i];
|
||||
|
||||
if (rpl->src) {
|
||||
if (rpl->old_iv) {
|
||||
(void)memset(rpl, 0, sizeof(*rpl));
|
||||
} else {
|
||||
rpl->old_iv = true;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_rpl(rpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user