From 830e690f180386b16c11fce61efe2d9fcdb996fe Mon Sep 17 00:00:00 2001 From: lly Date: Fri, 25 Oct 2019 16:06:44 +0800 Subject: [PATCH] ble_mesh: Add Provisioner NVS functionality --- components/bt/Kconfig | 2 +- .../bt/ble_mesh/mesh_core/include/mesh_main.h | 7 + components/bt/ble_mesh/mesh_core/mesh_main.c | 33 +- components/bt/ble_mesh/mesh_core/net.c | 22 +- components/bt/ble_mesh/mesh_core/net.h | 2 + .../bt/ble_mesh/mesh_core/provisioner_main.c | 450 ++++++---- .../bt/ble_mesh/mesh_core/provisioner_main.h | 31 +- .../bt/ble_mesh/mesh_core/provisioner_prov.c | 146 +--- .../bt/ble_mesh/mesh_core/provisioner_prov.h | 7 - components/bt/ble_mesh/mesh_core/settings.c | 790 ++++++++++++++++-- components/bt/ble_mesh/mesh_core/settings.h | 15 + .../mesh_models/include/model_common.h | 8 - 12 files changed, 1130 insertions(+), 383 deletions(-) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index abb0326384..3d5c1ed2cb 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -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 diff --git a/components/bt/ble_mesh/mesh_core/include/mesh_main.h b/components/bt/ble_mesh/mesh_core/include/mesh_main.h index f0ad314da0..bae5bf3081 100644 --- a/components/bt/ble_mesh/mesh_core/include/mesh_main.h +++ b/components/bt/ble_mesh/mesh_core/include/mesh_main.h @@ -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 diff --git a/components/bt/ble_mesh/mesh_core/mesh_main.c b/components/bt/ble_mesh/mesh_core/mesh_main.c index 75a4718095..07f4f21c09 100644 --- a/components/bt/ble_mesh/mesh_core/mesh_main.c +++ b/components/bt/ble_mesh/mesh_core/mesh_main.c @@ -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; } diff --git a/components/bt/ble_mesh/mesh_core/net.c b/components/bt/ble_mesh/mesh_core/net.c index d2b43a0918..d1ac33e816 100644 --- a/components/bt/ble_mesh/mesh_core/net.c +++ b/components/bt/ble_mesh/mesh_core/net.c @@ -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 diff --git a/components/bt/ble_mesh/mesh_core/net.h b/components/bt/ble_mesh/mesh_core/net.h index 9bedf9fcf6..3dade9fc10 100644 --- a/components/bt/ble_mesh/mesh_core/net.h +++ b/components/bt/ble_mesh/mesh_core/net.h @@ -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]); diff --git a/components/bt/ble_mesh/mesh_core/provisioner_main.c b/components/bt/ble_mesh/mesh_core/provisioner_main.c index 4fbff9ea2b..9f3853cbdf 100644 --- a/components/bt/ble_mesh/mesh_core/provisioner_main.c +++ b/components/bt/ble_mesh/mesh_core/provisioner_main.c @@ -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; } } diff --git a/components/bt/ble_mesh/mesh_core/provisioner_main.h b/components/bt/ble_mesh/mesh_core/provisioner_main.h index a4b6a38c84..59a857c6ad 100644 --- a/components/bt/ble_mesh/mesh_core/provisioner_main.h +++ b/components/bt/ble_mesh/mesh_core/provisioner_main.h @@ -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 diff --git a/components/bt/ble_mesh/mesh_core/provisioner_prov.c b/components/bt/ble_mesh/mesh_core/provisioner_prov.c index e535c8f237..ae9abcca50 100644 --- a/components/bt/ble_mesh/mesh_core/provisioner_prov.c +++ b/components/bt/ble_mesh/mesh_core/provisioner_prov.c @@ -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); diff --git a/components/bt/ble_mesh/mesh_core/provisioner_prov.h b/components/bt/ble_mesh/mesh_core/provisioner_prov.h index f6a367da0d..280b75c41a 100644 --- a/components/bt/ble_mesh/mesh_core/provisioner_prov.h +++ b/components/bt/ble_mesh/mesh_core/provisioner_prov.h @@ -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 diff --git a/components/bt/ble_mesh/mesh_core/settings.c b/components/bt/ble_mesh/mesh_core/settings.c index bc659a08ae..40963a9ac7 100644 --- a/components/bt/ble_mesh/mesh_core/settings.c +++ b/components/bt/ble_mesh/mesh_core/settings.c @@ -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__); diff --git a/components/bt/ble_mesh/mesh_core/settings.h b/components/bt/ble_mesh/mesh_core/settings.h index d7e04d9af3..97c3849183 100644 --- a/components/bt/ble_mesh/mesh_core/settings.h +++ b/components/bt/ble_mesh/mesh_core/settings.h @@ -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_ */ diff --git a/components/bt/ble_mesh/mesh_models/include/model_common.h b/components/bt/ble_mesh/mesh_models/include/model_common.h index 29a88ea482..8e1db867f1 100644 --- a/components/bt/ble_mesh/mesh_models/include/model_common.h +++ b/components/bt/ble_mesh/mesh_models/include/model_common.h @@ -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 */