ble_mesh: Add Provisioner NVS functionality

This commit is contained in:
lly
2019-10-25 16:06:44 +08:00
parent ec0abdf5fc
commit 830e690f18
12 changed files with 1130 additions and 383 deletions

View File

@@ -1455,7 +1455,7 @@ if BLE_MESH
config BLE_MESH_SEQ_STORE_RATE
int "How often the sequence number gets updated in storage"
range 0 1000000
default 128
default 6
help
This value defines how often the local sequence number gets updated in
persistent storage (i.e. flash). e.g. a value of 100 means that the

View File

@@ -276,6 +276,13 @@ struct bt_mesh_prov {
#endif /* CONFIG_BLE_MESH_PROVISIONER */
};
enum ble_mesh_role {
NODE = 0,
PROVISIONER,
FAST_PROV,
ROLE_NVAL,
};
/** @brief Provide provisioning input OOB string.
*
* This is intended to be called after the bt_mesh_prov input callback

View File

@@ -160,11 +160,11 @@ void bt_mesh_reset(void)
bt_mesh_proxy_gatt_disable();
}
#if defined(CONFIG_BLE_MESH_SETTINGS)
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_net();
bt_mesh_clear_role();
}
#endif
memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key));
memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
@@ -206,6 +206,10 @@ int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
bt_mesh_adv_update();
}
if(IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_role(NODE);
}
provisioner_en = false;
return 0;
@@ -229,6 +233,10 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
bt_mesh_adv_update();
}
if(IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_role();
}
return 0;
}
@@ -291,6 +299,10 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers)
provisioner_pb_gatt_enable();
}
if(IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_role(PROVISIONER);
}
provisioner_en = true;
return 0;
@@ -315,6 +327,10 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers)
bt_mesh_scan_disable();
}
if(IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_role();
}
provisioner_en = false;
return 0;
@@ -375,8 +391,7 @@ u8_t bt_mesh_set_fast_prov_action(u8_t action)
provisioner_set_fast_prov_flag(false);
provisioner_en = false;
if (action == ACTION_EXIT) {
provisioner_upper_reset_all_nodes();
provisioner_prov_reset_all_nodes();
provisioner_reset_all_nodes();
}
}
@@ -461,6 +476,10 @@ int bt_mesh_init(const struct bt_mesh_prov *prov,
#endif
}
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_settings_init();
}
#if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER
/* If node & provisioner are both enabled and the
* device starts as a node, it must finish provisioning */
@@ -470,11 +489,5 @@ int bt_mesh_init(const struct bt_mesh_prov *prov,
}
#endif
#if defined(CONFIG_BLE_MESH_SETTINGS)
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_settings_init();
}
#endif
return 0;
}

View File

@@ -148,6 +148,19 @@ static bool msg_cache_match(struct bt_mesh_net_rx *rx,
return false;
}
void bt_mesh_msg_cache_clear(u16_t unicast_addr, u8_t elem_num)
{
u16_t src;
int i;
for (i = 0; i < ARRAY_SIZE(msg_cache); i++) {
src = (((u8_t)(msg_cache[i] >> 16)) << 8) | (u8_t)(msg_cache[i] >> 24);
if (src >= unicast_addr && src < unicast_addr + elem_num) {
memset(&msg_cache[i], 0x0, sizeof(msg_cache[i]));
}
}
}
struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx)
{
int i;
@@ -740,7 +753,7 @@ u32_t bt_mesh_next_seq(void)
{
u32_t seq = bt_mesh.seq++;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_seq();
}
@@ -1024,11 +1037,6 @@ static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc,
return -ENOENT;
}
/* TODO: For provisioner, when a device is re-provisioned and start to
* send the same message(e.g. cfg_appkey_add), the status message is easy
* to be filtered here. So when a device is re-provisioned, the related
* msg_cache should be cleared. Will do it later.
*/
if (rx->net_if == BLE_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) {
BT_WARN("Duplicate found in Network Message Cache");
return -EALREADY;
@@ -1416,7 +1424,7 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi,
BT_WARN("%s, Provisioner is disabled", __func__);
return;
}
if (!provisioner_get_prov_node_count()) {
if (!provisioner_get_node_count()) {
return;
}
#endif

View File

@@ -316,6 +316,8 @@ extern struct bt_mesh_net bt_mesh;
#define BLE_MESH_NET_HDR_LEN 9
void bt_mesh_msg_cache_clear(u16_t unicast_addr, u8_t elem_num);
int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
const u8_t key[16]);

View File

@@ -17,6 +17,7 @@
#include "sdkconfig.h"
#include "osi/allocator.h"
#include "osi/mutex.h"
#include "mesh_util.h"
#include "mesh_main.h"
@@ -28,6 +29,7 @@
#include "adv.h"
#include "net.h"
#include "access.h"
#include "settings.h"
#include "provisioner_prov.h"
#include "provisioner_proxy.h"
@@ -39,10 +41,30 @@ static const struct bt_mesh_prov *prov;
static const struct bt_mesh_comp *comp;
static struct bt_mesh_node_t *mesh_nodes[CONFIG_BLE_MESH_MAX_STORED_NODES];
static u32_t mesh_node_count;
static osi_mutex_t provisioner_mutex;
static u16_t all_node_count;
static u16_t prov_node_count;
static bool prov_upper_init = false;
void bt_mesh_provisioner_mutex_new(void)
{
if (!provisioner_mutex) {
osi_mutex_new(&provisioner_mutex);
__ASSERT(provisioner_mutex, "%s, fail", __func__);
}
}
static void bt_mesh_provisioner_lock(void)
{
osi_mutex_lock(&provisioner_mutex, OSI_MUTEX_MAX_TIMEOUT);
}
static void bt_mesh_provisioner_unlock(void)
{
osi_mutex_unlock(&provisioner_mutex);
}
static int provisioner_index_check(int node_index)
{
struct bt_mesh_node_t *node = NULL;
@@ -68,96 +90,211 @@ static int provisioner_index_check(int node_index)
return 0;
}
int provisioner_node_provision(int node_index, const u8_t uuid[16], u16_t oob_info,
u16_t unicast_addr, u8_t element_num, u16_t net_idx,
u8_t flags, u32_t iv_index, const u8_t dev_key[16])
static void provisioner_node_count_inc(bool prov)
{
struct bt_mesh_node_t *node = NULL;
all_node_count++;
if (prov) {
prov_node_count++;
}
}
static void provisioner_node_count_dec(bool prov)
{
if (all_node_count) {
all_node_count--;
}
if (prov) {
if (prov_node_count) {
prov_node_count--;
}
}
}
u16_t provisioner_get_prov_node_count(void)
{
return prov_node_count;
}
u16_t provisioner_get_node_count(void)
{
return all_node_count;
}
static int provisioner_store_node(struct bt_mesh_node_t *node, bool prov, int *index)
{
u16_t min, max;
int err = 0;
int i;
bt_mesh_provisioner_lock();
/**
* 0 ~ (CONFIG_BLE_MESH_MAX_PROV_NODES - 1) are used to store
* the information of self-provisioned nodes.
*/
if (prov) {
min = 0;
max = CONFIG_BLE_MESH_MAX_PROV_NODES;
} else {
min = CONFIG_BLE_MESH_MAX_PROV_NODES;
max = ARRAY_SIZE(mesh_nodes);
}
for (i = min; i < max; i++) {
if (mesh_nodes[i] == NULL) {
mesh_nodes[i] = osi_calloc(sizeof(struct bt_mesh_node_t));
if (!mesh_nodes[i]) {
BT_ERR("%s, Failed to allocate memory", __func__);
err = -ENOMEM;
goto unlock;
}
memcpy(mesh_nodes[i], node, sizeof(struct bt_mesh_node_t));
provisioner_node_count_inc(prov);
if (index) {
*index = i;
}
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_node_info(mesh_nodes[i], prov);
}
goto unlock;
}
}
BT_ERR("%s, Node queue is full", __func__);
err = -ENOMEM;
unlock:
bt_mesh_provisioner_unlock();
return err;
}
int provisioner_node_provision(const bt_mesh_addr_t *addr, const u8_t uuid[16], u16_t oob_info,
u16_t unicast_addr, u8_t element_num, u16_t net_idx, u8_t flags,
u32_t iv_index, const u8_t dev_key[16], int *index)
{
struct bt_mesh_node_t node = {0};
BT_DBG("%s", __func__);
if (mesh_node_count >= ARRAY_SIZE(mesh_nodes)) {
BT_ERR("%s, Node queue is full", __func__);
return -ENOMEM;
}
if (node_index >= ARRAY_SIZE(mesh_nodes) || !uuid || !dev_key) {
if (!addr || !uuid || !dev_key || !index) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
node = osi_calloc(sizeof(struct bt_mesh_node_t));
if (!node) {
BT_ERR("%s, Failed to allocate memory", __func__);
return -ENOMEM;
}
BT_DBG("node_index: 0x%x, unicast_addr: 0x%x, element_num: 0x%x, net_idx: 0x%x",
node_index, unicast_addr, element_num, net_idx);
BT_DBG("unicast_addr: 0x%x, element_num: 0x%x, net_idx: 0x%x",
unicast_addr, element_num, net_idx);
BT_DBG("dev_uuid: %s", bt_hex(uuid, 16));
BT_DBG("dev_key: %s", bt_hex(dev_key, 16));
mesh_nodes[node_index] = node;
memcpy(&node.addr, addr, sizeof(bt_mesh_addr_t));
memcpy(node.dev_uuid, uuid, 16);
node.oob_info = oob_info;
node.unicast_addr = unicast_addr;
node.element_num = element_num;
node.net_idx = net_idx;
node.flags = flags;
node.iv_index = iv_index;
memcpy(node.dev_key, dev_key, 16);
memcpy(node->dev_uuid, uuid, 16);
node->oob_info = oob_info;
node->unicast_addr = unicast_addr;
node->element_num = element_num;
node->net_idx = net_idx;
node->flags = flags;
node->iv_index = iv_index;
memcpy(node->dev_key, dev_key, 16);
mesh_node_count++;
return 0;
return provisioner_store_node(&node, true, index);
}
int provisioner_node_reset(int node_index)
static int provisioner_reset_node(int node_index)
{
struct bt_mesh_node_t *node = NULL;
struct bt_mesh_rpl *rpl = NULL;
struct bt_mesh_rpl *rpl = NULL;
bool is_prov;
int i;
BT_DBG("%s, reset node %d", __func__, node_index);
if (!mesh_node_count) {
BT_ERR("%s, Node queue is empty", __func__);
return -ENODEV;
}
bt_mesh_provisioner_lock();
if (provisioner_index_check(node_index)) {
BT_ERR("%s, Failed to check node index", __func__);
return -EINVAL;
if (mesh_nodes[node_index] == NULL) {
bt_mesh_provisioner_unlock();
return 0;
}
node = mesh_nodes[node_index];
/* Reset corresponding network cache when reset the node */
bt_mesh_msg_cache_clear(node->unicast_addr, node->element_num);
/* Reset corresponding rpl when reset the node */
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
rpl = &bt_mesh.rpl[i];
if (rpl->src >= node->unicast_addr &&
rpl->src < node->unicast_addr + node->element_num) {
memset(rpl, 0, sizeof(struct bt_mesh_rpl));
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_rpl_single(node->unicast_addr);
}
}
}
is_prov = node_index < CONFIG_BLE_MESH_MAX_PROV_NODES ? true : false;
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_node_info(node->unicast_addr, is_prov);
}
osi_free(mesh_nodes[node_index]);
mesh_nodes[node_index] = NULL;
mesh_node_count--;
provisioner_node_count_dec(is_prov);
bt_mesh_provisioner_unlock();
return 0;
}
int provisioner_upper_reset_all_nodes(void)
bool provisioner_find_reset_node_with_uuid(const u8_t uuid[16], bool reset)
{
int i;
for (i = 0; i < CONFIG_BLE_MESH_MAX_PROV_NODES; i++) {
if (mesh_nodes[i]) {
if (!memcmp(mesh_nodes[i]->dev_uuid, uuid, 16)) {
if (reset) {
provisioner_reset_node(i);
}
return true;
}
}
}
return false;
}
bool provisioner_find_reset_node_with_addr(const bt_mesh_addr_t *addr, bool reset)
{
int i;
for (i = 0; i < CONFIG_BLE_MESH_MAX_PROV_NODES; i++) {
if (mesh_nodes[i]) {
if (!memcmp(mesh_nodes[i]->addr.val, addr->val, BLE_MESH_ADDR_LEN) &&
mesh_nodes[i]->addr.type == addr->type) {
if (reset) {
provisioner_reset_node(i);
}
return true;
}
}
}
return false;
}
int provisioner_reset_all_nodes(void)
{
int i, err;
BT_DBG("%s", __func__);
for (i = 0; i < ARRAY_SIZE(mesh_nodes); i++) {
err = provisioner_node_reset(i);
err = provisioner_reset_node(i);
if (err == -ENODEV) {
return 0;
}
@@ -166,15 +303,11 @@ int provisioner_upper_reset_all_nodes(void)
return 0;
}
/** For Provisioner, we use the same data structure
* (like, struct bt_mesh_subnet, etc.) for netkey
* & appkey because if not we need to change a lot
* of APIs.
*/
int provisioner_upper_init(void)
{
struct bt_mesh_subnet *sub = NULL;
u8_t p_key[16] = {0};
int i;
BT_DBG("%s", __func__);
@@ -198,6 +331,13 @@ int provisioner_upper_init(void)
each element's address. */
bt_mesh_comp_provision(prov->prov_unicast_addr);
for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
if (bt_mesh.p_sub[i]) {
BT_DBG("Keys of Provisioner restored from flash");
goto end;
}
}
/* Generate the primary netkey */
if (bt_mesh_rand(p_key, 16)) {
BT_ERR("%s, Failed to generate Primary NetKey", __func__);
@@ -236,24 +376,29 @@ int provisioner_upper_init(void)
bt_mesh.p_app_idx_next = 0x0000;
bt_mesh.p_net_idx_next = 0x0001;
/* In this function, we use the values of struct bt_mesh_prov
which has been initialized in the application layer */
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_p_net_idx();
bt_mesh_store_p_app_idx();
bt_mesh_store_p_subnet(bt_mesh.p_sub[0]);
}
bt_mesh.iv_index = prov->iv_index;
bt_mesh.iv_update = BLE_MESH_IV_UPDATE(prov->flags);
/* Set initial IV Update procedure state time-stamp */
bt_mesh.last_update = k_uptime_get();
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_iv();
}
end:
prov_upper_init = true;
BT_DBG("kr_flag: %d, kr_phase: %d, net_idx: 0x%02x, node_id %d",
sub->kr_flag, sub->kr_phase, sub->net_idx, sub->node_id);
BT_DBG("netkey: %s, nid: 0x%x", bt_hex(sub->keys[0].net, 16), sub->keys[0].nid);
BT_DBG("enckey: %s", bt_hex(sub->keys[0].enc, 16));
BT_DBG("network id: %s", bt_hex(sub->keys[0].net_id, 8));
BT_DBG("identity: %s", bt_hex(sub->keys[0].identity, 16));
BT_DBG("privacy: %s", bt_hex(sub->keys[0].privacy, 16));
BT_DBG("beacon: %s", bt_hex(sub->keys[0].beacon, 16));
BT_DBG("net_idx 0x%03x, netkey %s, nid 0x%02x",
sub->net_idx, bt_hex(sub->keys[0].net, 16), sub->keys[0].nid);
bt_mesh_provisioner_mutex_new();
return 0;
}
@@ -372,108 +517,24 @@ struct bt_mesh_app_key *provisioner_app_key_find(u16_t app_idx)
return NULL;
}
u32_t provisioner_get_prov_node_count(void)
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node_t *node, bool prov)
{
return mesh_node_count;
}
/* The following APIs are for provisioner application use */
#if 0
static int bt_mesh_provisioner_set_kr_flag(u16_t net_idx, bool kr_flag)
{
struct bt_mesh_subnet *sub = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
sub = bt_mesh.p_sub[i];
if (!sub || (sub->net_idx != net_idx)) {
continue;
}
sub->kr_flag = kr_flag;
break;
}
if (i == ARRAY_SIZE(bt_mesh.p_sub)) {
return -ENODEV;
}
/* TODO: When kr_flag is changed, provisioner may need
* to change the netkey of the subnet and update
* corresponding appkey.
*/
return 0;
}
static void bt_mesh_provisioner_set_iv_index(u32_t iv_index)
{
bt_mesh.iv_index = iv_index;
/* TODO: When iv_index is changed, provisioner may need to
* start iv update procedure. And the ivu_initiator
* & iv_update flags may also need to be set.
*/
}
#endif
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node_t *node_info)
{
struct bt_mesh_node_t *node = NULL;
int i;
if (!node_info) {
if (!node) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
/* Check if the device uuid already exists */
for (i = 0; i < ARRAY_SIZE(mesh_nodes); i++) {
node = mesh_nodes[i];
if (node && !memcmp(node->dev_uuid, node_info->dev_uuid, 16)) {
BT_WARN("%s, Node info already exists", __func__);
if (mesh_nodes[i] && !memcmp(mesh_nodes[i]->dev_uuid, node->dev_uuid, 16)) {
BT_WARN("%s, Node already exists", __func__);
return -EEXIST;
}
}
/* 0 ~ (CONFIG_BLE_MESH_MAX_PROV_NODES-1) are left for self-provisioned nodes */
for (i = CONFIG_BLE_MESH_MAX_PROV_NODES; i < ARRAY_SIZE(mesh_nodes); i++) {
node = mesh_nodes[i];
if (!node) {
node = osi_calloc(sizeof(struct bt_mesh_node_t));
if (!node) {
BT_ERR("%s, Failed to allocate memory", __func__);
return -ENOMEM;
}
memcpy(node, node_info, sizeof(struct bt_mesh_node_t));
mesh_nodes[i] = node;
mesh_node_count++;
return 0;
}
}
BT_ERR("%s, Node info is full", __func__);
return -ENOMEM;
}
int bt_mesh_provisioner_get_all_node_unicast_addr(struct net_buf_simple *buf)
{
struct bt_mesh_node_t *node = NULL;
int i;
if (!buf) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(mesh_nodes); i++) {
node = mesh_nodes[i];
if (!node || !BLE_MESH_ADDR_IS_UNICAST(node->unicast_addr)) {
continue;
}
net_buf_simple_add_le16(buf, node->unicast_addr);
}
return 0;
return provisioner_store_node(node, prov, NULL);
}
int bt_mesh_provisioner_set_node_name(int node_index, const char *name)
@@ -802,6 +863,11 @@ int bt_mesh_provisioner_local_app_key_add(const u8_t app_key[16], u16_t net_idx,
bt_mesh.p_app_keys[add] = key;
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_p_app_idx();
bt_mesh_store_p_app_key(key);
}
return 0;
}
@@ -836,6 +902,64 @@ const u8_t *bt_mesh_provisioner_local_app_key_get(u16_t net_idx, u16_t app_idx)
return NULL;
}
static void model_pub_clear(struct bt_mesh_model *model)
{
if (!model->pub) {
return;
}
if (model->pub->addr == BLE_MESH_ADDR_UNASSIGNED) {
return;
}
model->pub->addr = BLE_MESH_ADDR_UNASSIGNED;
model->pub->key = 0;
model->pub->cred = 0;
model->pub->ttl = 0;
model->pub->period = 0;
model->pub->retransmit = 0;
model->pub->count = 0;
if (model->pub->update) {
k_delayed_work_cancel(&model->pub->timer);
}
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_mod_pub(model);
}
return;
}
static void model_unbind(struct bt_mesh_model *model, u16_t app_idx)
{
int i;
BT_DBG("model %p key_idx 0x%03x", model, app_idx);
for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
if (model->keys[i] != app_idx) {
continue;
}
model->keys[i] = BLE_MESH_KEY_UNUSED;
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_mod_bind(model);
}
model_pub_clear(model);
}
}
static void _model_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
u16_t app_idx = *(u16_t *)user_data;
model_unbind(mod, app_idx);
}
int bt_mesh_provisioner_local_app_key_delete(u16_t net_idx, u16_t app_idx)
{
struct bt_mesh_app_key *key = NULL;
@@ -857,6 +981,13 @@ int bt_mesh_provisioner_local_app_key_delete(u16_t net_idx, u16_t app_idx)
key = bt_mesh.p_app_keys[i];
if (key && key->net_idx == net_idx &&
key->app_idx == app_idx) {
/* Remove the AppKey from the models if they are bound with it */
bt_mesh_model_foreach(_model_unbind, &app_idx);
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_p_app_key(key);
}
osi_free(bt_mesh.p_app_keys[i]);
bt_mesh.p_app_keys[i] = NULL;
return 0;
@@ -946,6 +1077,11 @@ int bt_mesh_provisioner_local_net_key_add(const u8_t net_key[16], u16_t *net_idx
bt_mesh.p_sub[add] = sub;
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_p_net_idx();
bt_mesh_store_p_subnet(sub);
}
return 0;
}
@@ -977,7 +1113,7 @@ const u8_t *bt_mesh_provisioner_local_net_key_get(u16_t net_idx)
int bt_mesh_provisioner_local_net_key_delete(u16_t net_idx)
{
struct bt_mesh_subnet *sub = NULL;
int i;
int i, j;
BT_DBG("%s", __func__);
@@ -989,6 +1125,18 @@ int bt_mesh_provisioner_local_net_key_delete(u16_t net_idx)
for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
sub = bt_mesh.p_sub[i];
if (sub && sub->net_idx == net_idx) {
/* Delete any app keys bound to this NetKey index */
for (j = 0; j < ARRAY_SIZE(bt_mesh.p_app_keys); j++) {
struct bt_mesh_app_key *key = bt_mesh.p_app_keys[j];
if (key->net_idx == sub->net_idx) {
bt_mesh_provisioner_local_app_key_delete(key->net_idx, key->app_idx);
}
}
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_clear_p_subnet(sub);
}
osi_free(bt_mesh.p_sub[i]);
bt_mesh.p_sub[i] = NULL;
return 0;
@@ -1060,6 +1208,10 @@ int bt_mesh_provisioner_bind_local_model_app_idx(u16_t elem_addr, u16_t mod_id,
for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
if (model->keys[i] == BLE_MESH_KEY_UNUSED) {
model->keys[i] = app_idx;
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_mod_bind(model);
}
return 0;
}
}

View File

@@ -22,12 +22,11 @@
#define MESH_NAME_SIZE 31
#if CONFIG_BLE_MESH_PROVISIONER
/* Each node information stored by provisioner */
struct bt_mesh_node_t {
char node_name[MESH_NAME_SIZE]; /* Node name */
u8_t dev_uuid[16]; /* Device UUID pointer, stored in provisioner_prov.c */
bt_mesh_addr_t addr; /* Device address */
u8_t dev_uuid[16]; /* Device UUID */
u16_t oob_info; /* Node OOB information */
u16_t unicast_addr; /* Node unicast address */
u8_t element_num; /* Node element number */
@@ -39,13 +38,21 @@ struct bt_mesh_node_t {
/* The following APIs are for key init, node provision & node reset. */
int provisioner_node_provision(int node_index, const u8_t uuid[16], u16_t oob_info,
u16_t unicast_addr, u8_t element_num, u16_t net_idx,
u8_t flags, u32_t iv_index, const u8_t dev_key[16]);
void bt_mesh_provisioner_mutex_new(void);
int provisioner_node_reset(int node_index);
u16_t provisioner_get_prov_node_count(void);
int provisioner_upper_reset_all_nodes(void);
u16_t provisioner_get_node_count(void);
int provisioner_node_provision(const bt_mesh_addr_t *addr, const u8_t uuid[16], u16_t oob_info,
u16_t unicast_addr, u8_t element_num, u16_t net_idx, u8_t flags,
u32_t iv_index, const u8_t dev_key[16], int *index);
bool provisioner_find_reset_node_with_uuid(const u8_t uuid[16], bool reset);
bool provisioner_find_reset_node_with_addr(const bt_mesh_addr_t *addr, bool reset);
int provisioner_reset_all_nodes(void);
int provisioner_upper_init(void);
@@ -61,13 +68,9 @@ const u8_t *provisioner_get_device_key(u16_t dst_addr);
struct bt_mesh_app_key *provisioner_app_key_find(u16_t app_idx);
u32_t provisioner_get_prov_node_count(void);
/* The following APIs are for provisioner application use. */
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node_t *node_info);
int bt_mesh_provisioner_get_all_node_unicast_addr(struct net_buf_simple *buf);
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node_t *node, bool prov);
int bt_mesh_provisioner_set_node_name(int node_index, const char *name);
@@ -105,8 +108,6 @@ int bt_mesh_provisioner_bind_local_app_net_idx(u16_t net_idx, u16_t app_idx);
/* Provisioner print own element information */
int bt_mesh_provisioner_print_local_element_info(void);
#endif /* CONFIG_BLE_MESH_PROVISIONER */
/* The following APIs are for fast provisioning */
#if CONFIG_BLE_MESH_FAST_PROV

View File

@@ -227,9 +227,6 @@ struct prov_ctx_t {
/* Provisioner random */
u8_t random[16];
/* Number of provisioned devices */
u16_t node_count;
/* Current number of PB-ADV provisioned devices simultaneously */
u8_t pba_count;
@@ -284,20 +281,6 @@ struct prov_ctx_t {
static struct prov_ctx_t prov_ctx;
struct prov_node_info {
bool provisioned; /* device provisioned flag */
bt_mesh_addr_t addr; /* device address */
u8_t uuid[16]; /* node uuid */
u16_t oob_info; /* oob info contained in adv pkt */
u8_t element_num; /* element contained in this node */
u16_t unicast_addr; /* primary unicast address of this node */
u16_t net_idx; /* Netkey index got during provisioning */
u8_t flags; /* Key refresh flag and iv update flag */
u32_t iv_index; /* IV Index */
};
static struct prov_node_info prov_nodes[CONFIG_BLE_MESH_MAX_PROV_NODES];
struct unprov_dev_queue {
bt_mesh_addr_t addr;
u8_t uuid[16];
@@ -430,23 +413,6 @@ const struct bt_mesh_prov *provisioner_get_prov_info(void)
return prov;
}
int provisioner_prov_reset_all_nodes(void)
{
int i;
BT_DBG("%s", __func__);
for (i = 0; i < ARRAY_SIZE(prov_nodes); i++) {
if (prov_nodes[i].provisioned) {
memset(&prov_nodes[i], 0, sizeof(struct prov_node_info));
}
}
prov_ctx.node_count = 0;
return 0;
}
static int provisioner_dev_find(const bt_mesh_addr_t *addr, const u8_t uuid[16], int *index)
{
bool uuid_match = false;
@@ -517,13 +483,9 @@ static bool is_unprov_dev_being_provision(const u8_t uuid[16])
* Unprovisioned Device Beacon when Transaction ACK for Provisioning Complete
* is received). So in Fast Provisioning the Provisioner should ignore this.
*/
for (i = 0; i < ARRAY_SIZE(prov_nodes); i++) {
if (prov_nodes[i].provisioned) {
if (!memcmp(prov_nodes[i].uuid, uuid, 16)) {
BT_WARN("Device has already been provisioned");
return -EALREADY;
}
}
if (provisioner_find_reset_node_with_uuid(uuid, false)) {
BT_WARN("Device has already been provisioned");
return -EALREADY;
}
#endif
@@ -560,8 +522,6 @@ static bool is_unprov_dev_uuid_match(const u8_t uuid[16])
static int provisioner_check_unprov_dev_info(const u8_t uuid[16])
{
int i;
if (!uuid) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
@@ -584,22 +544,13 @@ static int provisioner_check_unprov_dev_info(const u8_t uuid[16])
}
/* Check if the device has already been provisioned */
for (i = 0; i < ARRAY_SIZE(prov_nodes); i++) {
if (prov_nodes[i].provisioned) {
if (!memcmp(prov_nodes[i].uuid, uuid, 16)) {
BT_WARN("Provisioned before, start to provision again");
provisioner_node_reset(i);
memset(&prov_nodes[i], 0, sizeof(struct prov_node_info));
if (prov_ctx.node_count) {
prov_ctx.node_count--;
}
return 0;
}
}
if (provisioner_find_reset_node_with_uuid(uuid, true)) {
BT_WARN("Provisioned before, start to provision again");
return 0;
}
/* Check if the prov_nodes queue is full */
if (prov_ctx.node_count == ARRAY_SIZE(prov_nodes)) {
/* Check if the provisioned nodes queue is full */
if (provisioner_get_prov_node_count() == CONFIG_BLE_MESH_MAX_PROV_NODES) {
BT_WARN("Current provisioned devices reach max limit");
return -ENOMEM;
}
@@ -808,8 +759,8 @@ start:
}
/* Check if current provisioned node count + active link reach max limit */
if (prov_ctx.node_count + prov_ctx.pba_count + \
prov_ctx.pbg_count >= ARRAY_SIZE(prov_nodes)) {
if (provisioner_get_prov_node_count() + prov_ctx.pba_count + \
prov_ctx.pbg_count >= CONFIG_BLE_MESH_MAX_PROV_NODES) {
BT_WARN("%s, Node count + active link count reach max limit", __func__);
return -EIO;
}
@@ -853,7 +804,7 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev)
* 2. device is being provisioned, need to close link & remove from device queue.
* 3. device is been provisioned, need to send config_node_reset and may need to
* remove from device queue. config _node_reset can be added in function
* provisioner_node_reset() in provisioner_main.c.
* provisioner_reset_node() in provisioner_main.c.
*/
bt_mesh_addr_t del_addr = {0};
u8_t zero[16] = {0};
@@ -906,25 +857,15 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev)
}
/* Third: find if the device is been provisioned */
for (i = 0; i < ARRAY_SIZE(prov_nodes); i++) {
if (addr_cmp && (del_dev->addr_type <= BLE_MESH_ADDR_RANDOM)) {
if (!memcmp(prov_nodes[i].addr.val, del_dev->addr, BLE_MESH_ADDR_LEN) &&
prov_nodes[i].addr.type == del_dev->addr_type) {
addr_match = true;
}
if (addr_cmp && (del_dev->addr_type <= BLE_MESH_ADDR_RANDOM)) {
if (provisioner_find_reset_node_with_addr(&del_addr, true)) {
return 0;
}
if (uuid_cmp) {
if (!memcmp(prov_nodes[i].uuid, del_dev->uuid, 16)) {
uuid_match = true;
}
}
if (addr_match || uuid_match) {
memset(&prov_nodes[i], 0, sizeof(struct prov_node_info));
provisioner_node_reset(i);
if (prov_ctx.node_count) {
prov_ctx.node_count--;
}
break;
}
if (uuid_cmp) {
if (provisioner_find_reset_node_with_uuid(del_dev->uuid, true)) {
return 0;
}
}
@@ -2370,7 +2311,9 @@ fail:
static void prov_complete(const u8_t *data)
{
u8_t device_key[16];
int i = prov_get_pb_index(), j;
int i = prov_get_pb_index();
u16_t net_idx;
int index;
int err, rm = 0;
/* Make sure received pdu is ok and cancel the timeout timer */
@@ -2378,10 +2321,6 @@ static void prov_complete(const u8_t *data)
k_delayed_work_cancel(&link[i].timeout);
}
/* If provisioning complete is received, the provisioning device
* will be stored into the prov_node_info structure and become a
* node within the mesh network
*/
err = bt_mesh_dev_key(link[i].dhkey, link[i].prov_salt, device_key);
if (err) {
BT_ERR("%s, Failed to generate device key", __func__);
@@ -2389,38 +2328,15 @@ static void prov_complete(const u8_t *data)
return;
}
for (j = 0; j < ARRAY_SIZE(prov_nodes); j++) {
if (!prov_nodes[j].provisioned) {
prov_nodes[j].provisioned = true;
prov_nodes[j].oob_info = link[i].oob_info;
prov_nodes[j].element_num = link[i].element_num;
prov_nodes[j].unicast_addr = link[i].unicast_addr;
if (FAST_PROV_FLAG_GET()) {
prov_nodes[j].net_idx = fast_prov_info.net_idx;
} else {
prov_nodes[j].net_idx = prov_ctx.curr_net_idx;
}
prov_nodes[j].flags = link[i].ki_flags;
prov_nodes[j].iv_index = link[i].iv_index;
prov_nodes[j].addr.type = link[i].addr.type;
memcpy(prov_nodes[j].addr.val, link[i].addr.val, BLE_MESH_ADDR_LEN);
memcpy(prov_nodes[j].uuid, link[i].uuid, 16);
break;
}
if (FAST_PROV_FLAG_GET()) {
net_idx = fast_prov_info.net_idx;
} else {
net_idx = prov_ctx.curr_net_idx;
}
if (j == ARRAY_SIZE(prov_nodes)) {
BT_ERR("%s, Provisioned node queue is full", __func__);
close_link(i, CLOSE_REASON_FAILED);
return;
}
prov_ctx.node_count++;
err = provisioner_node_provision(j, prov_nodes[j].uuid, prov_nodes[j].oob_info,
prov_nodes[j].unicast_addr, prov_nodes[j].element_num,
prov_nodes[j].net_idx, prov_nodes[j].flags,
prov_nodes[j].iv_index, device_key);
err = provisioner_node_provision(&link[i].addr, link[i].uuid, link[i].oob_info,
link[i].unicast_addr, link[i].element_num, net_idx,
link[i].ki_flags, link[i].iv_index, device_key, &index);
if (err) {
BT_ERR("%s, Failed to store node info", __func__);
close_link(i, CLOSE_REASON_FAILED);
@@ -2428,8 +2344,8 @@ static void prov_complete(const u8_t *data)
}
if (prov->prov_complete) {
prov->prov_complete(j, prov_nodes[j].uuid, prov_nodes[j].unicast_addr,
prov_nodes[j].element_num, prov_nodes[j].net_idx);
prov->prov_complete(index, link[i].uuid, link[i].unicast_addr,
link[i].element_num, net_idx);
}
err = provisioner_dev_find(&link[i].addr, link[i].uuid, &rm);

View File

@@ -202,13 +202,6 @@ void provisioner_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t
*/
const struct bt_mesh_prov *provisioner_get_prov_info(void);
/**
* @brief This function resets all nodes information in provisioner_prov.c.
*
* @return Zero
*/
int provisioner_prov_reset_all_nodes(void);
/* The following APIs are for primary provisioner application use */
/** @brief Add unprovisioned device info to unprov_dev queue

View File

@@ -31,6 +31,7 @@
#include "cfg_srv.h"
#include "settings_nvs.h"
#include "provisioner_main.h"
/* BLE Mesh NVS Key and corresponding data struct.
* Note: The length of nvs key must be <= 15.
@@ -153,6 +154,38 @@ static struct {
struct cfg_val cfg;
} stored_cfg;
struct node_update {
bt_mesh_addr_t addr; /* Device address */
u8_t dev_uuid[16]; /* Device UUID */
u16_t oob_info; /* Node OOB information */
u16_t unicast_addr; /* Node unicast address */
u8_t element_num; /* Node element number */
u8_t dev_key[16]; /* Node device key */
} __packed;
static u8_t dev_role = ROLE_NVAL;
static int role_set(const char *name)
{
bool exist;
int err;
BT_DBG("%s", __func__);
err = bt_mesh_load_core_settings(name, (u8_t *)&dev_role, sizeof(dev_role), &exist);
if (err) {
return err;
}
if (exist == false) {
return 0;
}
BT_DBG("Device role 0x%02x", dev_role);
return 0;
}
static int net_set(const char *name)
{
struct net_val net = {0};
@@ -233,15 +266,15 @@ static int seq_set(const char *name)
bt_mesh.seq = ((u32_t)seq.val[0] | ((u32_t)seq.val[1] << 8) |
((u32_t)seq.val[2] << 16));
if (CONFIG_BLE_MESH_SEQ_STORE_RATE > 0) {
/* Make sure we have a large enough sequence number. We
* subtract 1 so that the first transmission causes a write
* to the settings storage.
*/
bt_mesh.seq += (CONFIG_BLE_MESH_SEQ_STORE_RATE -
(bt_mesh.seq % CONFIG_BLE_MESH_SEQ_STORE_RATE));
bt_mesh.seq--;
}
#if CONFIG_BLE_MESH_SEQ_STORE_RATE > 0
/* Make sure we have a large enough sequence number. We
* subtract 1 so that the first transmission causes a write
* to the settings storage.
*/
bt_mesh.seq += (CONFIG_BLE_MESH_SEQ_STORE_RATE -
(bt_mesh.seq % CONFIG_BLE_MESH_SEQ_STORE_RATE));
bt_mesh.seq--;
#endif
BT_DBG("Sequence Number 0x%06x", bt_mesh.seq);
@@ -697,22 +730,356 @@ static int vnd_mod_set(const char *name)
return model_set(true, name);
}
#if CONFIG_BLE_MESH_PROVISIONER
static int subnet_init(struct bt_mesh_subnet *sub);
/**
* The following variable is used to check whether Provisioner
* needs to continue restoring network keys and application keys
* during initialization.
* Because if a Provisioner starts to work at the first time, and
* after trying to restore the "bt_mesh.p_net_idx_next", nothing
* will be recovered. Hence there will be no need to restore the
* network keys and application keys. And during the Provisioner
* initialization, it will generate the primary network key.
* And if "p_key_exist" is false, which also means the Provisioner
* has not provisioned any node.
*/
static bool p_key_exist;
static int p_net_idx_set(const char *name)
{
u16_t net_idx;
bool exist;
int err;
BT_DBG("%s", __func__);
err = bt_mesh_load_core_settings(name, (u8_t *)&net_idx, sizeof(net_idx), &exist);
if (err) {
BT_ERR("%s, Failed to load Provisioner keys", __func__);
p_key_exist = false;
return 0;
}
if (exist == false) {
p_key_exist = false;
return 0;
}
bt_mesh.p_net_idx_next = net_idx;
p_key_exist = true;
BT_DBG("p_net_idx_next 0x%04x", bt_mesh.p_net_idx_next);
return 0;
}
static int p_app_idx_set(const char *name)
{
u16_t app_idx;
bool exist;
int err;
BT_DBG("%s", __func__);
if (p_key_exist == false) {
/**
* Directly return here if a Provisioner fails to restore the
* bt_mesh.p_net_idx_next, which means the corresponding keys
* have not be stored in the flash for the Provisioner.
*/
return 0;
}
err = bt_mesh_load_core_settings(name, (u8_t *)&app_idx, sizeof(app_idx), &exist);
if (err) {
return 0;
}
if (exist == false) {
return 0;
}
bt_mesh.p_app_idx_next = app_idx;
BT_DBG("p_app_idx_next 0x%04x", bt_mesh.p_app_idx_next);
return 0;
}
static struct bt_mesh_subnet *p_subnet_alloc(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
if (bt_mesh.p_sub[i] == NULL) {
bt_mesh.p_sub[i] = osi_calloc(sizeof(struct bt_mesh_subnet));
if (!bt_mesh.p_sub[i]) {
BT_ERR("%s, Failed to allocate memory", __func__);
return NULL;
}
return bt_mesh.p_sub[i];
}
}
return NULL;
}
static struct bt_mesh_app_key *p_appkey_alloc(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) {
if (bt_mesh.p_app_keys[i] == NULL) {
bt_mesh.p_app_keys[i] = osi_calloc(sizeof(struct bt_mesh_app_key));
if (!bt_mesh.p_app_keys[i]) {
BT_ERR("%s, Failed to allocate memory", __func__);
return NULL;
}
return bt_mesh.p_app_keys[i];
}
}
return NULL;
}
static int p_net_key_set(const char *name)
{
struct net_buf_simple *buf = NULL;
struct bt_mesh_subnet *sub = NULL;
struct net_key_val key = {0};
char get[16] = {'\0'};
size_t length;
bool exist;
int err = 0;
int i;
BT_DBG("%s", __func__);
if (p_key_exist == false) {
return 0;
}
buf = bt_mesh_get_core_settings_item(name);
if (!buf) {
return 0;
}
length = buf->len;
for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) {
u16_t net_idx = net_buf_simple_pull_le16(buf);
sprintf(get, "mesh/pnk/%04x", net_idx);
err = bt_mesh_load_core_settings(get, (u8_t *)&key, sizeof(key), &exist);
if (err) {
BT_ERR("%s, Failed to load Provisioner NetKey %s", __func__, get);
goto free;
}
if (exist == false) {
continue;
}
sub = provisioner_subnet_get(net_idx);
if (!sub) {
sub = p_subnet_alloc();
if (!sub) {
BT_ERR("%s, No space for a new subnet 0x%03x", __func__, net_idx);
err = -ENOMEM;
goto free;
}
}
BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
sub->net_idx = net_idx;
sub->kr_flag = key.kr_flag;
sub->kr_phase = key.kr_phase;
memcpy(sub->keys[0].net, &key.val[0], 16);
memcpy(sub->keys[1].net, &key.val[1], 16);
err = subnet_init(sub);
if (err) {
BT_ERR("%s, Failed to init Provisioner subnet 0x%03x", __func__, sub->net_idx);
}
sub->node_id = BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED;
}
free:
bt_mesh_free_buf(buf);
return err;
}
static int p_app_key_set(const char *name)
{
struct bt_mesh_app_key *app = NULL;
struct bt_mesh_subnet *sub = NULL;
struct net_buf_simple *buf = NULL;
struct app_key_val key = {0};
char get[16] = {'\0'};
size_t length;
bool exist;
int err = 0;
int i;
BT_DBG("%s", __func__);
if (p_key_exist == false) {
return 0;
}
buf = bt_mesh_get_core_settings_item(name);
if (!buf) {
return 0;
}
length = buf->len;
for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) {
u16_t app_idx = net_buf_simple_pull_le16(buf);
sprintf(get, "mesh/pak/%04x", app_idx);
err = bt_mesh_load_core_settings(get, (u8_t *)&key, sizeof(key), &exist);
if (err) {
BT_ERR("%s, Failed to load Provisioner AppKey %s", __func__, get);
goto free;
}
if (exist == false) {
continue;
}
sub = provisioner_subnet_get(key.net_idx);
if (!sub) {
BT_ERR("%s, Failed to find subnet 0x%03x", __func__, key.net_idx);
err = -ENOENT;
goto free;
}
app = provisioner_app_key_find(app_idx);
if (!app) {
app = p_appkey_alloc();
if (!app) {
BT_ERR("%s, No space for a new app key 0x%03x", __func__, app_idx);
err = -ENOMEM;
goto free;
}
}
BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
app->net_idx = key.net_idx;
app->app_idx = app_idx;
app->updated = key.updated;
memcpy(app->keys[0].val, key.val[0], 16);
memcpy(app->keys[1].val, key.val[1], 16);
bt_mesh_app_id(app->keys[0].val, &app->keys[0].id);
bt_mesh_app_id(app->keys[1].val, &app->keys[1].id);
}
free:
bt_mesh_free_buf(buf);
return err;
}
static int p_node_set(const char *name)
{
struct net_buf_simple *buf = NULL;
struct bt_mesh_node_t node = {0};
struct node_update val = {0};
char get[16] = {'\0'};
bool exist, prov;
size_t length;
int err = 0;
int i;
if (p_key_exist == false) {
return 0;
}
buf = bt_mesh_get_core_settings_item(name);
if (!buf) {
return 0;
}
prov = strcmp(name, "mesh/p_pnode") == 0 ? true : false;
length = buf->len;
for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) {
u16_t addr = net_buf_simple_pull_le16(buf);
sprintf(get, prov ? "mesh/pnd/%04x" : "mesh/snd/%04x", addr);
err = bt_mesh_load_core_settings(get, (u8_t *)&val, sizeof(val), &exist);
if (err) {
BT_ERR("%s, Failed to load node %s", __func__, get);
goto free;
}
if (exist == false) {
continue;
}
memcpy(&node.addr, &val.addr, sizeof(bt_mesh_addr_t));
memcpy(node.dev_uuid, val.dev_uuid, 16);
node.oob_info = val.oob_info;
node.unicast_addr = val.unicast_addr;
node.element_num = val.element_num;
memcpy(node.dev_key, val.dev_key, 16);
err = bt_mesh_provisioner_store_node_info(&node, prov);
if (err) {
BT_ERR("%s, Failed to store node 0x%04x", __func__, node.unicast_addr);
goto free;
}
}
free:
bt_mesh_free_buf(buf);
return err;
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
const struct bt_mesh_setting {
const char *name;
int (*func)(const char *name);
} settings[] = {
{ "mesh/net", net_set },
{ "mesh/iv", iv_set },
{ "mesh/seq", seq_set },
{ "mesh/rpl", rpl_set },
{ "mesh/netkey", net_key_set },
{ "mesh/appkey", app_key_set },
{ "mesh/hb_pub", hb_pub_set },
{ "mesh/cfg", cfg_set },
{ "mesh/sig", sig_mod_set },
{ "mesh/vnd", vnd_mod_set },
{ "mesh/role", role_set },
{ "mesh/net", net_set },
{ "mesh/iv", iv_set },
{ "mesh/seq", seq_set },
{ "mesh/rpl", rpl_set },
{ "mesh/netkey", net_key_set },
{ "mesh/appkey", app_key_set },
{ "mesh/hb_pub", hb_pub_set },
{ "mesh/cfg", cfg_set },
{ "mesh/sig", sig_mod_set },
{ "mesh/vnd", vnd_mod_set },
#if CONFIG_BLE_MESH_PROVISIONER
{ "mesh/p_netidx", p_net_idx_set },
{ "mesh/p_appidx", p_app_idx_set },
{ "mesh/p_netkey", p_net_key_set },
{ "mesh/p_appkey", p_app_key_set },
{ "mesh/p_pnode", p_node_set },
{ "mesh/p_snode", p_node_set },
#endif
};
/**
* For Provisioner, the load operation needs the following actions:
* net_set: Not needed
* iv_set: Need, although Provisioner will do some initialization of IV Index
* during startup, but we need to restore the last IV Index status
* seq_set: Need, restore the previous sequence number
* rpl_set: Need, restore the previous Replay Protection List
* net_key_set: Need, restore the previous network keys
* app_key_set: Need, restore the previous application keys
* hb_pub_set: Not needed currently
* cfg_set: Not needed currently
* sig_mod_set: Need, restore SIG models related info (app, sub, pub)
* vnd_mod_set: Need, restore vendor models related info (app, sub, pub)
*/
int settings_core_load(void)
{
int i;
@@ -720,7 +1087,39 @@ int settings_core_load(void)
BT_DBG("%s", __func__);
for (i = 0; i < ARRAY_SIZE(settings); i++) {
if ((!strcmp(settings[i].name, "mesh/net") ||
!strcmp(settings[i].name, "mesh/netkey") ||
!strcmp(settings[i].name, "mesh/appkey") ||
!strcmp(settings[i].name, "mesh/hb_pub") ||
!strcmp(settings[i].name, "mesh/cfg")) &&
(!IS_ENABLED(CONFIG_BLE_MESH_NODE) || dev_role == PROVISIONER)) {
BT_DBG("Not restoring %s for Provisioner", settings[i].name);
continue;
}
if ((!strcmp(settings[i].name, "mesh/p_netidx") ||
!strcmp(settings[i].name, "mesh/p_appidx") ||
!strcmp(settings[i].name, "mesh/p_netkey") ||
!strcmp(settings[i].name, "mesh/p_appkey") ||
!strcmp(settings[i].name, "mesh/p_pnode") ||
!strcmp(settings[i].name, "mesh/p_snode")) &&
(!IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) || dev_role == NODE)) {
BT_DBG("Not restoring %s for node", settings[i].name);
continue;
}
settings[i].func(settings[i].name);
if (!strcmp(settings[i].name, "mesh/role")) {
if (dev_role == ROLE_NVAL) {
BT_DBG("Device just starts up");
return 0;
}
if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && dev_role == PROVISIONER) {
bt_mesh_provisioner_mutex_new();
}
}
}
return 0;
@@ -776,30 +1175,31 @@ int settings_core_commit(void)
struct bt_mesh_cfg_srv *cfg = NULL;
int i;
BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE) {
if (bt_mesh.sub[0].net_idx == BLE_MESH_KEY_UNUSED) {
/* Nothing to do since we're not yet provisioned */
return 0;
}
BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
#if defined(CONFIG_BLE_MESH_NODE)
bt_mesh_proxy_prov_disable();
#endif
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
int err;
if (sub->net_idx == BLE_MESH_KEY_UNUSED) {
continue;
if (bt_mesh.sub[0].net_idx == BLE_MESH_KEY_UNUSED) {
/* Nothing to do since we're not yet provisioned */
return 0;
}
err = subnet_init(sub);
if (err) {
BT_ERR("%s, Failed to init subnet 0x%03x", __func__, sub->net_idx);
if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
bt_mesh_proxy_prov_disable();
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
int err;
if (sub->net_idx == BLE_MESH_KEY_UNUSED) {
continue;
}
err = subnet_init(sub);
if (err) {
BT_ERR("%s, Failed to init subnet 0x%03x", __func__, sub->net_idx);
}
}
}
@@ -809,30 +1209,29 @@ int settings_core_commit(void)
bt_mesh_model_foreach(commit_model, NULL);
hb_pub = bt_mesh_hb_pub_get();
if (hb_pub && hb_pub->dst != BLE_MESH_ADDR_UNASSIGNED &&
hb_pub->count && hb_pub->period) {
BT_DBG("Starting heartbeat publication");
k_work_submit(&hb_pub->timer.work);
if(IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE) {
hb_pub = bt_mesh_hb_pub_get();
if (hb_pub && hb_pub->dst != BLE_MESH_ADDR_UNASSIGNED &&
hb_pub->count && hb_pub->period) {
BT_DBG("Starting heartbeat publication");
k_work_submit(&hb_pub->timer.work);
}
cfg = bt_mesh_cfg_get();
if (cfg && stored_cfg.valid) {
cfg->net_transmit = stored_cfg.cfg.net_transmit;
cfg->relay = stored_cfg.cfg.relay;
cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
cfg->beacon = stored_cfg.cfg.beacon;
cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
cfg->frnd = stored_cfg.cfg.frnd;
cfg->default_ttl = stored_cfg.cfg.default_ttl;
}
bt_mesh.valid = 1;
bt_mesh_net_start();
}
cfg = bt_mesh_cfg_get();
if (cfg && stored_cfg.valid) {
cfg->net_transmit = stored_cfg.cfg.net_transmit;
cfg->relay = stored_cfg.cfg.relay;
cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
cfg->beacon = stored_cfg.cfg.beacon;
cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
cfg->frnd = stored_cfg.cfg.frnd;
cfg->default_ttl = stored_cfg.cfg.default_ttl;
}
bt_mesh.valid = 1;
#if defined(CONFIG_BLE_MESH_NODE)
bt_mesh_net_start();
#endif
return 0;
}
@@ -888,6 +1287,13 @@ static void store_pending_net(void)
bt_mesh_save_core_settings("mesh/net", (const u8_t *)&net, sizeof(net));
}
void bt_mesh_store_role(u8_t role)
{
BT_DBG("Device role 0x%02x", dev_role);
bt_mesh_save_core_settings("mesh/role", (const u8_t *)&role, sizeof(role));
}
void bt_mesh_store_net(void)
{
schedule_store(BLE_MESH_NET_PENDING);
@@ -1195,7 +1601,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *model, bool vnd)
sprintf(name, "mesh/%s/%04x/b", vnd ? "v" : "s", model_key);
if (!bt_mesh.valid) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE && !bt_mesh.valid) {
bt_mesh_save_core_settings(name, NULL, 0);
return;
}
@@ -1225,7 +1631,7 @@ static void store_pending_mod_sub(struct bt_mesh_model *model, bool vnd)
sprintf(name, "mesh/%s/%04x/s", vnd ? "v" : "s", model_key);
if (!bt_mesh.valid) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE && !bt_mesh.valid) {
bt_mesh_save_core_settings(name, NULL, 0);
return;
}
@@ -1269,7 +1675,7 @@ static void store_pending_mod_pub(struct bt_mesh_model *model, bool vnd)
sprintf(name, "mesh/%s/%04x/p", vnd ? "v" : "s", model_key);
if (!bt_mesh.valid) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE && !bt_mesh.valid) {
bt_mesh_save_core_settings(name, NULL, 0);
return;
}
@@ -1318,18 +1724,20 @@ static void store_pending(struct k_work *work)
BT_DBG("%s", __func__);
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_RPL_PENDING)) {
if (bt_mesh.valid) {
if (!IS_ENABLED(CONFIG_BLE_MESH_NODE) || bt_mesh.valid) {
store_pending_rpl();
} else {
clear_rpl();
}
}
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_KEYS_PENDING)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE &&
bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_KEYS_PENDING)) {
store_pending_keys();
}
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_NET_PENDING)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE &&
bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_NET_PENDING)) {
if (bt_mesh.valid) {
store_pending_net();
} else {
@@ -1338,7 +1746,7 @@ static void store_pending(struct k_work *work)
}
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_IV_PENDING)) {
if (bt_mesh.valid) {
if (!IS_ENABLED(CONFIG_BLE_MESH_NODE) || bt_mesh.valid) {
store_pending_iv();
} else {
clear_iv();
@@ -1349,11 +1757,13 @@ static void store_pending(struct k_work *work)
store_pending_seq();
}
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_HB_PUB_PENDING)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE &&
bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_HB_PUB_PENDING)) {
store_pending_hb_pub();
}
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_CFG_PENDING)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE &&
bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_CFG_PENDING)) {
if (bt_mesh.valid) {
store_pending_cfg();
} else {
@@ -1363,7 +1773,7 @@ static void store_pending(struct k_work *work)
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_MOD_PENDING)) {
bt_mesh_model_foreach(store_pending_mod, NULL);
if (!bt_mesh.valid) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && dev_role == NODE && !bt_mesh.valid) {
bt_mesh_save_core_settings("mesh/sig", NULL, 0);
bt_mesh_save_core_settings("mesh/vnd", NULL, 0);
}
@@ -1468,6 +1878,12 @@ void bt_mesh_store_cfg(void)
schedule_store(BLE_MESH_CFG_PENDING);
}
void bt_mesh_clear_role(void)
{
BT_DBG("Clearing device role");
bt_mesh_save_core_settings("mesh/role", NULL, 0);
}
void bt_mesh_clear_net(void)
{
schedule_store(BLE_MESH_NET_PENDING);
@@ -1552,6 +1968,238 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *model)
schedule_store(BLE_MESH_MOD_PENDING);
}
#if CONFIG_BLE_MESH_PROVISIONER
/**
* key: "mesh/p_netidx" -> write/read to set/get bt_mesh.p_net_idx_next
* key: "mesh/p_appidx" -> write/read to set/get bt_mesh.p_app_idx_next
* key: "mesh/p_netkey" -> write/read to set/get all Provisioner NetKey Index
* key: "mesh/pnk/xxxx" -> write/read to set/get the "xxxx" NetKey
* key: "mesh/p_appkey" -> write/read to set/get all Provisioner AppKey Index
* key: "mesh/pak/xxxx" -> write/read to set/get the "xxxx" AppKey
* key: "mesh/p_pnode" -> write/read to set/get all self-provisioned nodes info
* key: "mesh/pnd/xxxx" -> write/read to set/get the "xxxx" provisioned node info
* key: "mesh/p_snode" -> write/read to set/get all locally stored nodes info
* key: "mesh/snd/xxxx" -> write/read to set/get the "xxxx" stored node info
*/
static void clear_p_net_key(u16_t net_idx)
{
char name[16] = {'\0'};
int err;
sprintf(name, "mesh/pnk/%04x", net_idx);
bt_mesh_save_core_settings(name, NULL, 0);
err = bt_mesh_remove_core_settings_item("mesh/p_netkey", net_idx);
if (err) {
BT_ERR("%s, Failed to remove 0x%04x from mesh/p_netkey", __func__, net_idx);
}
}
static void clear_p_app_key(u16_t app_idx)
{
char name[16] = {'\0'};
int err;
sprintf(name, "mesh/pak/%04x", app_idx);
bt_mesh_save_core_settings(name, NULL, 0);
err = bt_mesh_remove_core_settings_item("mesh/p_appkey", app_idx);
if (err) {
BT_ERR("%s, Failed to remove 0x%03x from mesh/p_appkey", __func__, app_idx);
}
}
static void store_p_net_key(struct bt_mesh_subnet *sub)
{
struct net_key_val key = {0};
char name[16] = {'\0'};
int err;
memcpy(&key.val[0], sub->keys[0].net, 16);
memcpy(&key.val[1], sub->keys[1].net, 16);
key.kr_flag = sub->kr_flag;
key.kr_phase = sub->kr_phase;
sprintf(name, "mesh/pnk/%04x", sub->net_idx);
err = bt_mesh_save_core_settings(name, (const u8_t *)&key, sizeof(key));
if (err) {
BT_ERR("%s, Failed to save NetKey %s", __func__, name);
return;
}
err = bt_mesh_add_core_settings_item("mesh/p_netkey", sub->net_idx);
if (err) {
BT_ERR("%s, Failed to add 0x%04x to mesh/p_netkey", __func__, sub->net_idx);
}
}
static void store_p_app_key(struct bt_mesh_app_key *app)
{
struct app_key_val key = {0};
char name[16] = {'\0'};
int err;
key.net_idx = app->net_idx;
key.updated = app->updated;
memcpy(key.val[0], app->keys[0].val, 16);
memcpy(key.val[1], app->keys[1].val, 16);
sprintf(name, "mesh/pak/%04x", app->app_idx);
err = bt_mesh_save_core_settings(name, (const u8_t *)&key, sizeof(key));
if (err) {
BT_ERR("%s, Failed to save AppKey %s", __func__, name);
return;
}
err = bt_mesh_add_core_settings_item("mesh/p_appkey", app->app_idx);
if (err) {
BT_ERR("%s, Failed to add 0x%04x to mesh/p_appkey", __func__, app->app_idx);
}
}
void bt_mesh_store_p_net_idx(void)
{
BT_DBG("p_net_idx_next 0x%03x", bt_mesh.p_net_idx_next);
bt_mesh_save_core_settings("mesh/p_netidx",
(const u8_t *)&bt_mesh.p_net_idx_next, sizeof(bt_mesh.p_net_idx_next));
}
void bt_mesh_store_p_app_idx(void)
{
BT_DBG("p_app_idx_next 0x%03x", bt_mesh.p_app_idx_next);
bt_mesh_save_core_settings("mesh/p_appidx",
(const u8_t *)&bt_mesh.p_app_idx_next, sizeof(bt_mesh.p_app_idx_next));
}
void bt_mesh_store_p_subnet(struct bt_mesh_subnet *sub)
{
if (sub == NULL) {
BT_ERR("%s, Invalid subnet",__func__);
return;
}
BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
bt_hex(sub->keys[0].net, 16));
store_p_net_key(sub);
}
void bt_mesh_store_p_app_key(struct bt_mesh_app_key *key)
{
if (key == NULL) {
BT_ERR("%s, Invalid AppKey",__func__);
return;
}
BT_DBG("AppKeyIndex 0x%03x AppKey %s", key->app_idx,
bt_hex(key->keys[0].val, 16));
store_p_app_key(key);
}
void bt_mesh_clear_p_subnet(struct bt_mesh_subnet *sub)
{
if (sub == NULL) {
BT_ERR("%s, Invalid subnet",__func__);
return;
}
BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
clear_p_net_key(sub->net_idx);
}
void bt_mesh_clear_p_app_key(struct bt_mesh_app_key *key)
{
if (key == NULL) {
BT_ERR("%s, Invalid AppKey",__func__);
return;
}
BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
clear_p_app_key(key->app_idx);
}
void bt_mesh_clear_rpl_single(u16_t src)
{
char name[16] = {'\0'};
int err;
if (!BLE_MESH_ADDR_IS_UNICAST(src)) {
BT_ERR("%s, Invalid source address 0x%04x", __func__, src);
return;
}
sprintf(name, "mesh/rpl/%04x", src);
bt_mesh_save_core_settings(name, NULL, 0);
err = bt_mesh_remove_core_settings_item("mesh/rpl", src);
if (err) {
BT_ERR("%s, Failed to remove 0x%04x from mesh/rpl", __func__, src);
}
}
void bt_mesh_store_node_info(struct bt_mesh_node_t *node, bool prov)
{
struct node_update val = {0};
char name[16] = {'\0'};
int err;
if (node == NULL) {
BT_ERR("%s, Invalid node", __func__);
return;
}
memcpy(&val.addr, &node->addr, sizeof(bt_mesh_addr_t));
memcpy(val.dev_uuid, node->dev_uuid, 16);
val.oob_info = node->oob_info;
val.unicast_addr = node->unicast_addr;
val.element_num = node->element_num;
memcpy(val.dev_key, node->dev_key, 16);
sprintf(name, prov ? "mesh/pnd/%04x" : "mesh/snd/%04x", node->unicast_addr);
err = bt_mesh_save_core_settings(name, (const u8_t *)&val, sizeof(val));
if (err) {
BT_ERR("%s, Failed to save node %s", __func__, name);
return;
}
err = bt_mesh_add_core_settings_item(prov ? "mesh/p_pnode" : "mesh/p_snode", node->unicast_addr);
if (err) {
BT_ERR("%s, Failed to add node 0x%04x", __func__, node->unicast_addr);
}
}
static void clear_node(u16_t addr, bool prov)
{
char name[16] = {'\0'};
int err;
sprintf(name, prov ? "mesh/pnd/%04x" : "mesh/snd/%04x", addr);
bt_mesh_save_core_settings(name, NULL, 0);
err = bt_mesh_remove_core_settings_item(prov ? "mesh/p_pnode" : "mesh/p_snode", addr);
if (err) {
BT_ERR("%s, Failed to remove node 0x%04x", __func__, addr);
}
}
void bt_mesh_clear_node_info(u16_t unicast_addr, bool prov)
{
if (!BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) {
BT_ERR("%s, Invalid unicast address 0x%04x", __func__, unicast_addr);
return;
}
BT_DBG("Unicast address 0x%04x", unicast_addr);
clear_node(unicast_addr, prov);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
int settings_core_init(void)
{
BT_DBG("%s", __func__);

View File

@@ -12,11 +12,13 @@
#include "net.h"
#include "mesh_access.h"
#include "mesh_bearer_adapt.h"
#include "provisioner_main.h"
int settings_core_init(void);
int settings_core_load(void);
int settings_core_commit(void);
void bt_mesh_store_role(u8_t role);
void bt_mesh_store_net(void);
void bt_mesh_store_iv(void);
void bt_mesh_store_seq(void);
@@ -29,11 +31,24 @@ void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
void bt_mesh_clear_role(void);
void bt_mesh_clear_net(void);
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
void bt_mesh_clear_rpl(void);
#if CONFIG_BLE_MESH_PROVISIONER
void bt_mesh_store_p_net_idx(void);
void bt_mesh_store_p_app_idx(void);
void bt_mesh_store_p_subnet(struct bt_mesh_subnet *sub);
void bt_mesh_store_p_app_key(struct bt_mesh_app_key *key);
void bt_mesh_clear_p_subnet(struct bt_mesh_subnet *sub);
void bt_mesh_clear_p_app_key(struct bt_mesh_app_key *key);
void bt_mesh_clear_rpl_single(u16_t src);
void bt_mesh_store_node_info(struct bt_mesh_node_t *node, bool prov);
void bt_mesh_clear_node_info(u16_t unicast_addr, bool prov);
#endif
int bt_mesh_settings_init(void);
#endif /* _SETTINGS_H_ */

View File

@@ -92,14 +92,6 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model,
int bt_mesh_client_free_node(bt_mesh_client_node_t *node);
enum {
NODE = 0,
PROVISIONER,
FAST_PROV,
};
#define ROLE_NVAL 0xFF
struct bt_mesh_common_param {
u32_t opcode; /* Message opcode */
struct bt_mesh_model *model; /* Pointer to cli structure */