Currently only keep func pointer for the followings: - Invalid parameter (mesh btc & mesh stack) - Out of memory (mesh btc & mesh stack) - Unknown act (mesh btc) - Invalid model user data (mesh stack) - BT_DBG("%s", __func__) (mesh btc & mesh stack) - A few other specific situations (buf ref debug, send status check)
406 lines
10 KiB
C
406 lines
10 KiB
C
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "nvs.h"
|
|
#include "nvs_flash.h"
|
|
|
|
#include "mesh_common.h"
|
|
#include "settings_nvs.h"
|
|
#include "settings.h"
|
|
|
|
#if CONFIG_BLE_MESH_SETTINGS
|
|
|
|
enum settings_type {
|
|
SETTINGS_CORE,
|
|
SETTINGS_SERVER,
|
|
};
|
|
|
|
struct settings_context {
|
|
char *nvs_name;
|
|
nvs_handle handle;
|
|
|
|
int (*settings_init)(void);
|
|
int (*settings_load)(void);
|
|
int (*settings_commit)(void);
|
|
int (*settings_deinit)(void);
|
|
int (*settings_erase)(void);
|
|
};
|
|
|
|
static struct settings_context settings_ctx[] = {
|
|
[SETTINGS_CORE] = {
|
|
.nvs_name = "mesh_core",
|
|
.settings_init = settings_core_init,
|
|
.settings_load = settings_core_load,
|
|
.settings_commit = settings_core_commit,
|
|
.settings_deinit = settings_core_deinit,
|
|
},
|
|
[SETTINGS_SERVER] = {
|
|
.nvs_name = "mesh_server",
|
|
.settings_init = NULL,
|
|
.settings_load = NULL,
|
|
.settings_commit = NULL,
|
|
},
|
|
};
|
|
|
|
/* API used to initialize, load and commit BLE Mesh related settings */
|
|
|
|
void bt_mesh_settings_foreach(void)
|
|
{
|
|
int err = 0;
|
|
int i;
|
|
|
|
#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
|
|
err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME);
|
|
if (err != ESP_OK) {
|
|
BT_ERR("Failed to init mesh partition, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
|
|
struct settings_context *ctx = &settings_ctx[i];
|
|
|
|
#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
|
|
err = nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, ctx->nvs_name, NVS_READWRITE, &ctx->handle);
|
|
#else
|
|
err = nvs_open(ctx->nvs_name, NVS_READWRITE, &ctx->handle);
|
|
#endif
|
|
if (err != ESP_OK) {
|
|
BT_ERR("Open nvs failed, name %s, err %d", ctx->nvs_name, err);
|
|
continue;
|
|
}
|
|
|
|
if (ctx->settings_init && ctx->settings_init()) {
|
|
BT_ERR("Init settings failed, name %s", ctx->nvs_name);
|
|
continue;
|
|
}
|
|
|
|
if (ctx->settings_load && ctx->settings_load()) {
|
|
BT_ERR("Load settings failed, name %s", ctx->nvs_name);
|
|
continue;
|
|
}
|
|
|
|
if (ctx->settings_commit && ctx->settings_commit()) {
|
|
BT_ERR("Commit settings failed, name %s", ctx->nvs_name);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bt_mesh_settings_deforeach(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
|
|
struct settings_context *ctx = &settings_ctx[i];
|
|
|
|
if (ctx->settings_deinit && ctx->settings_deinit()) {
|
|
BT_ERR("Deinit settings failed, name %s", ctx->nvs_name);
|
|
continue;
|
|
}
|
|
|
|
nvs_close(ctx->handle);
|
|
}
|
|
|
|
#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
|
|
nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME);
|
|
#endif
|
|
}
|
|
|
|
/* API used to get BLE Mesh related nvs handle */
|
|
|
|
static inline nvs_handle settings_get_nvs_handle(enum settings_type type)
|
|
{
|
|
return settings_ctx[type].handle;
|
|
}
|
|
|
|
/* API used to store/erase BLE Mesh related settings */
|
|
|
|
static int settings_save(nvs_handle handle, const char *key, const u8_t *val, size_t len)
|
|
{
|
|
int err = 0;
|
|
|
|
if (key == NULL) {
|
|
BT_ERR("%s, Invalid parameter", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
BT_DBG("nvs %s, key %s", val ? "set" : "erase", key);
|
|
|
|
if (val) {
|
|
err = nvs_set_blob(handle, key, val, len);
|
|
} else {
|
|
err = nvs_erase_key(handle, key);
|
|
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
|
BT_DBG("%s not exists", key);
|
|
return 0;
|
|
}
|
|
}
|
|
if (err != ESP_OK) {
|
|
BT_ERR("Failed to %s %s data (err %d)",
|
|
val ? "set" : "erase", key, err);
|
|
return -EIO;
|
|
}
|
|
|
|
err = nvs_commit(handle);
|
|
if (err != ESP_OK) {
|
|
BT_ERR("Failed to commit settings (err %d)", err);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_save_core_settings(const char *key, const u8_t *val, size_t len)
|
|
{
|
|
nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE);
|
|
return settings_save(handle, key, val, len);
|
|
}
|
|
|
|
/* API used to load BLE Mesh related settings */
|
|
|
|
static int settings_load(nvs_handle handle, const char *key,
|
|
u8_t *buf, size_t buf_len, bool *exist)
|
|
{
|
|
int err = 0;
|
|
|
|
if (key == NULL || buf == NULL || exist == NULL) {
|
|
BT_ERR("%s, Invalid parameter", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
err = nvs_get_blob(handle, key, buf, &buf_len);
|
|
if (err != ESP_OK) {
|
|
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
|
BT_DBG("Settings %s not found", key);
|
|
*exist = false;
|
|
return 0;
|
|
}
|
|
|
|
BT_ERR("Failed to get %s data (err %d)", key, err);
|
|
return -EIO;
|
|
}
|
|
|
|
*exist = true;
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_load_core_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist)
|
|
{
|
|
nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE);
|
|
return settings_load(handle, key, buf, buf_len, exist);
|
|
}
|
|
|
|
/* API used to get length of BLE Mesh related settings */
|
|
|
|
static size_t settings_get_length(nvs_handle handle, const char *key)
|
|
{
|
|
size_t len = 0U;
|
|
int err = 0;
|
|
|
|
if (key == NULL) {
|
|
BT_ERR("%s, Invalid parameter", __func__);
|
|
return 0;
|
|
}
|
|
|
|
err = nvs_get_blob(handle, key, NULL, &len);
|
|
if (err != ESP_OK) {
|
|
if (err != ESP_ERR_NVS_NOT_FOUND) {
|
|
BT_ERR("Failed to get %s length (err %d)", key, err);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
/* API used to get BLE Mesh related items. Here items mean model key, NetKey/AppKey
|
|
* Index, etc. which are going to be used as the prefix of the nvs keys of the BLE
|
|
* Mesh settings.
|
|
*/
|
|
|
|
static struct net_buf_simple *settings_get_item(nvs_handle handle, const char *key)
|
|
{
|
|
struct net_buf_simple *buf = NULL;
|
|
size_t length = 0U;
|
|
bool exist = false;
|
|
int err = 0;
|
|
|
|
length = settings_get_length(handle, key);
|
|
if (!length) {
|
|
BT_DBG("Empty %s", key);
|
|
return NULL;
|
|
}
|
|
|
|
buf = bt_mesh_alloc_buf(length);
|
|
if (!buf) {
|
|
BT_ERR("%s, Out of memory", __func__);
|
|
/* TODO: in this case, erase all related settings? */
|
|
return NULL;
|
|
}
|
|
|
|
err = settings_load(handle, key, buf->data, length, &exist);
|
|
if (err) {
|
|
BT_ERR("Failed to load %s", key);
|
|
/* TODO: in this case, erase all related settings? */
|
|
bt_mesh_free_buf(buf);
|
|
return NULL;
|
|
}
|
|
|
|
if (exist == false) {
|
|
bt_mesh_free_buf(buf);
|
|
return NULL;
|
|
}
|
|
|
|
buf->len = length;
|
|
return buf;
|
|
}
|
|
|
|
struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key)
|
|
{
|
|
nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE);
|
|
return settings_get_item(handle, key);
|
|
}
|
|
|
|
/* API used to check if the settings item exists */
|
|
|
|
static bool is_settings_item_exist(struct net_buf_simple *buf, const u16_t val)
|
|
{
|
|
struct net_buf_simple_state state = {0};
|
|
size_t length = 0U;
|
|
int i;
|
|
|
|
if (!buf) {
|
|
return false;
|
|
}
|
|
|
|
net_buf_simple_save(buf, &state);
|
|
|
|
length = buf->len;
|
|
for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) {
|
|
u16_t item = net_buf_simple_pull_le16(buf);
|
|
if (item == val) {
|
|
net_buf_simple_restore(buf, &state);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
net_buf_simple_restore(buf, &state);
|
|
return false;
|
|
}
|
|
|
|
/* API used to add the settings item */
|
|
|
|
static int settings_add_item(nvs_handle handle, const char *key, const u16_t val)
|
|
{
|
|
struct net_buf_simple *store = NULL;
|
|
struct net_buf_simple *buf = NULL;
|
|
size_t length = 0U;
|
|
int err = 0;
|
|
|
|
buf = settings_get_item(handle, key);
|
|
|
|
/* Check if val already exists */
|
|
if (is_settings_item_exist(buf, val) == true) {
|
|
BT_DBG("0x%04x already exists", val);
|
|
bt_mesh_free_buf(buf);
|
|
return 0;
|
|
}
|
|
|
|
length = (buf ? buf->len : 0) + sizeof(val);
|
|
|
|
store = bt_mesh_alloc_buf(length);
|
|
if (!store) {
|
|
BT_ERR("%s, Out of memory", __func__);
|
|
bt_mesh_free_buf(buf);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (buf) {
|
|
net_buf_simple_add_mem(store, buf->data, buf->len);
|
|
}
|
|
net_buf_simple_add_mem(store, &val, sizeof(val));
|
|
|
|
err = settings_save(handle, key, store->data, store->len);
|
|
|
|
bt_mesh_free_buf(store);
|
|
bt_mesh_free_buf(buf);
|
|
return err;
|
|
}
|
|
|
|
int bt_mesh_add_core_settings_item(const char *key, const u16_t val)
|
|
{
|
|
nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE);
|
|
return settings_add_item(handle, key, val);
|
|
}
|
|
|
|
/* API used to remove the settings item */
|
|
|
|
static int settings_remove_item(nvs_handle handle, const char *key, const u16_t val)
|
|
{
|
|
struct net_buf_simple *store = NULL;
|
|
struct net_buf_simple *buf = NULL;
|
|
size_t length = 0U;
|
|
size_t buf_len = 0U;
|
|
int err = 0;
|
|
int i;
|
|
|
|
buf = settings_get_item(handle, key);
|
|
|
|
/* Check if val does exist */
|
|
if (is_settings_item_exist(buf, val) == false) {
|
|
BT_DBG("0x%04x not exists", val);
|
|
bt_mesh_free_buf(buf);
|
|
return 0;
|
|
}
|
|
|
|
length = buf->len - sizeof(val);
|
|
if (!length) {
|
|
settings_save(handle, key, NULL, 0);
|
|
bt_mesh_free_buf(buf);
|
|
return 0;
|
|
}
|
|
|
|
store = bt_mesh_alloc_buf(length);
|
|
if (!store) {
|
|
BT_ERR("%s, Out of memory", __func__);
|
|
bt_mesh_free_buf(buf);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
buf_len = buf->len;
|
|
for (i = 0; i < buf_len / SETTINGS_ITEM_SIZE; i++) {
|
|
u16_t item = net_buf_simple_pull_le16(buf);
|
|
if (item != val) {
|
|
net_buf_simple_add_le16(store, item);
|
|
}
|
|
}
|
|
|
|
err = settings_save(handle, key, store->data, store->len);
|
|
|
|
bt_mesh_free_buf(store);
|
|
bt_mesh_free_buf(buf);
|
|
return err;
|
|
}
|
|
|
|
int bt_mesh_remove_core_settings_item(const char *key, const u16_t val)
|
|
{
|
|
nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE);
|
|
return settings_remove_item(handle, key, val);
|
|
}
|
|
|
|
#endif /* CONFIG_BLE_MESH_SETTINGS */
|