ble_mesh: Add Provisioner NVS functionality
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__);
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user