1 /*
2  * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <errno.h>
9 
10 #include "mesh_common.h"
11 #include "settings_uid.h"
12 #include "settings.h"
13 
14 #if CONFIG_BLE_MESH_SETTINGS
15 
16 enum settings_type {
17     SETTINGS_CORE,
18 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
19     SETTINGS_UID,
20 #endif
21 };
22 
23 struct settings_context {
24     char *nvs_name;
25     bt_mesh_nvs_handle_t handle;
26 
27     int (*settings_init)(void);
28     int (*settings_load)(void);
29     int (*settings_commit)(void);
30 #if CONFIG_BLE_MESH_DEINIT
31     int (*settings_deinit)(void);
32     int (*settings_erase)(void);
33 #endif /* CONFIG_BLE_MESH_DEINIT */
34 };
35 
36 static struct settings_context settings_ctx[] = {
37     [SETTINGS_CORE] = {
38         .nvs_name = "mesh_core",
39         .settings_init = settings_core_init,
40         .settings_load = settings_core_load,
41         .settings_commit = settings_core_commit,
42 #if CONFIG_BLE_MESH_DEINIT
43         .settings_deinit = settings_core_deinit,
44         .settings_erase = settings_core_erase,
45 #endif /* CONFIG_BLE_MESH_DEINIT */
46     },
47 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
48     [SETTINGS_UID] = {
49         .nvs_name = "mesh_user_id",
50         .settings_init = settings_uid_init,
51         .settings_load = settings_uid_load,
52         .settings_commit = NULL,
53 #if CONFIG_BLE_MESH_DEINIT
54         .settings_deinit = settings_uid_deinit,
55         .settings_erase = settings_uid_erase,
56 #endif /* CONFIG_BLE_MESH_DEINIT */
57     },
58 #endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
59 };
60 
61 /* API used to initialize, load and commit BLE Mesh related settings */
62 
bt_mesh_settings_nvs_open(const char * name,bt_mesh_nvs_handle_t * handle)63 int bt_mesh_settings_nvs_open(const char* name, bt_mesh_nvs_handle_t *handle)
64 {
65 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
66     return nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, name, NVS_READWRITE, handle);
67 #else
68     return nvs_open(name, NVS_READWRITE, handle);
69 #endif
70 }
71 
bt_mesh_settings_nvs_close(bt_mesh_nvs_handle_t handle)72 void bt_mesh_settings_nvs_close(bt_mesh_nvs_handle_t handle)
73 {
74     nvs_close(handle);
75 }
76 
bt_mesh_settings_init_foreach(void)77 void bt_mesh_settings_init_foreach(void)
78 {
79     int err = 0;
80     int i;
81 
82 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
83     err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME);
84     if (err != ESP_OK) {
85         BT_ERR("Init mesh partition failed, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
86         return;
87     }
88 #endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */
89 
90     for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
91         struct settings_context *ctx = &settings_ctx[i];
92 
93         /* Settings initialization is always needed. */
94         if (ctx->settings_init && ctx->settings_init()) {
95             BT_ERR("Init settings failed, name %s", ctx->nvs_name);
96             return;
97         }
98 
99 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
100         /* If multiple nvs namespace functionality is enabled,
101          * no need to perform the following operations during
102          * initialization. And they will be performed when the
103          * application layer tries to open settings.
104          */
105         if (i != SETTINGS_UID) {
106             continue;
107         }
108 #endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
109 
110         err = bt_mesh_settings_nvs_open(ctx->nvs_name, &ctx->handle);
111         if (err) {
112             BT_ERR("Open nvs failed, name %s, err %d", ctx->nvs_name, err);
113             return;
114         }
115 
116         if (ctx->settings_load && ctx->settings_load()) {
117             BT_ERR("Load settings failed, name %s", ctx->nvs_name);
118             return;
119         }
120 
121         /* If not using multiple nvs namespaces, we will follow the normal
122          * procedure, i.e. restoring all the mesh information.
123          * If using multiple nvs namespaces, we will only restore user_id.
124          */
125         if (ctx->settings_commit && ctx->settings_commit()) {
126             BT_ERR("Commit settings failed, name %s", ctx->nvs_name);
127             return;
128         }
129     }
130 }
131 
132 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_settings_deinit_foreach(bool erase)133 void bt_mesh_settings_deinit_foreach(bool erase)
134 {
135     int i;
136 
137     for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
138         struct settings_context *ctx = &settings_ctx[i];
139 
140         if (ctx->settings_deinit && ctx->settings_deinit()) {
141             BT_ERR("Deinit settings failed, name %s", ctx->nvs_name);
142             continue;
143         }
144 
145         if (erase && ctx->settings_erase && ctx->settings_erase()) {
146             BT_ERR("Erase settings failed, name %s", ctx->nvs_name);
147             continue;
148         }
149 
150         bt_mesh_settings_nvs_close(ctx->handle);
151     }
152 
153 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
154     nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME);
155 #endif
156 }
157 #endif /* CONFIG_BLE_MESH_DEINIT */
158 
bt_mesh_settings_direct_open(bt_mesh_nvs_handle_t * handle)159 int bt_mesh_settings_direct_open(bt_mesh_nvs_handle_t *handle)
160 {
161     int err = 0;
162     int i;
163 
164 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
165     err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME);
166     if (err != ESP_OK) {
167         BT_ERR("Init mesh partition failed, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
168         return -EIO;
169     }
170 #endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */
171 
172     for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
173         struct settings_context *ctx = &settings_ctx[i];
174 
175         err = bt_mesh_settings_nvs_open(ctx->nvs_name, &ctx->handle);
176         if (err) {
177             BT_ERR("Open nvs failed, name %s, err %d", ctx->nvs_name, err);
178             return -EIO;
179         }
180 
181         if (i == SETTINGS_CORE && handle) {
182             *handle = ctx->handle;
183         }
184     }
185 
186     return 0;
187 }
188 
bt_mesh_settings_direct_close(void)189 void bt_mesh_settings_direct_close(void)
190 {
191     int i;
192 
193     for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
194         bt_mesh_settings_nvs_close(settings_ctx[i].handle);
195     }
196 
197 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
198     nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME);
199 #endif
200 }
201 
202 /* API used to get BLE Mesh related nvs handle */
203 
settings_get_nvs_handle(enum settings_type type)204 static inline bt_mesh_nvs_handle_t settings_get_nvs_handle(enum settings_type type)
205 {
206 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
207     if (type == SETTINGS_CORE) {
208         extern bt_mesh_nvs_handle_t get_core_settings_handle(void);
209         return get_core_settings_handle();
210     }
211 #endif
212     return settings_ctx[type].handle;
213 }
214 
215 /* API used to store/erase BLE Mesh related settings */
216 
settings_save(bt_mesh_nvs_handle_t handle,const char * key,const uint8_t * val,size_t len)217 static int settings_save(bt_mesh_nvs_handle_t handle, const char *key, const uint8_t *val, size_t len)
218 {
219     int err = 0;
220 
221     if (key == NULL) {
222         BT_ERR("%s, Invalid parameter", __func__);
223         return -EINVAL;
224     }
225 
226     BT_DBG("nvs %s, key %s", val ? "set" : "erase", key);
227 
228     if (val) {
229         err = nvs_set_blob(handle, key, val, len);
230     } else {
231         err = nvs_erase_key(handle, key);
232         if (err == ESP_ERR_NVS_NOT_FOUND) {
233             BT_DBG("%s not exists", key);
234             return 0;
235         }
236     }
237     if (err != ESP_OK) {
238         BT_ERR("Failed to %s %s data (err %d)",
239                 val ? "set" : "erase", key, err);
240         return -EIO;
241     }
242 
243     err = nvs_commit(handle);
244     if (err != ESP_OK) {
245         BT_ERR("Failed to commit settings (err %d)", err);
246         return -EIO;
247     }
248 
249     return 0;
250 }
251 
bt_mesh_save_settings(bt_mesh_nvs_handle_t handle,const char * key,const uint8_t * val,size_t len)252 int bt_mesh_save_settings(bt_mesh_nvs_handle_t handle, const char *key,
253                           const uint8_t *val, size_t len)
254 {
255     int err = 0;
256     bt_mesh_settings_lock();
257     err = settings_save(handle, key, val, len);
258     bt_mesh_settings_unlock();
259     return err;
260 }
261 
bt_mesh_save_core_settings(const char * key,const uint8_t * val,size_t len)262 int bt_mesh_save_core_settings(const char *key, const uint8_t *val, size_t len)
263 {
264     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE);
265     return bt_mesh_save_settings(handle, key, val, len);
266 }
267 
268 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
bt_mesh_save_uid_settings(const char * key,const uint8_t * val,size_t len)269 int bt_mesh_save_uid_settings(const char *key, const uint8_t *val, size_t len)
270 {
271     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
272     return bt_mesh_save_settings(handle, key, val, len);
273 }
274 #endif
275 
bt_mesh_erase_settings(bt_mesh_nvs_handle_t handle,const char * key)276 int bt_mesh_erase_settings(bt_mesh_nvs_handle_t handle, const char *key)
277 {
278     return bt_mesh_save_settings(handle, key, NULL, 0);
279 }
280 
bt_mesh_erase_core_settings(const char * key)281 int bt_mesh_erase_core_settings(const char *key)
282 {
283     return bt_mesh_save_core_settings(key, NULL, 0);
284 }
285 
286 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
bt_mesh_erase_uid_settings(const char * name)287 int bt_mesh_erase_uid_settings(const char *name)
288 {
289     return bt_mesh_save_uid_settings(name, NULL, 0);
290 }
291 #endif
292 
293 /* API used to load BLE Mesh related settings */
294 
settings_load(bt_mesh_nvs_handle_t handle,const char * key,uint8_t * buf,size_t buf_len,bool * exist)295 static int settings_load(bt_mesh_nvs_handle_t handle, const char *key,
296                          uint8_t *buf, size_t buf_len, bool *exist)
297 {
298     int err = 0;
299 
300     if (key == NULL || buf == NULL || exist == NULL) {
301         BT_ERR("%s, Invalid parameter", __func__);
302         return -EINVAL;
303     }
304 
305     err = nvs_get_blob(handle, key, buf, &buf_len);
306     if (err != ESP_OK) {
307         if (err == ESP_ERR_NVS_NOT_FOUND) {
308             BT_DBG("Settings %s not found", key);
309             *exist = false;
310             return 0;
311         }
312 
313         BT_ERR("Failed to get %s data (err %d)", key, err);
314         return -EIO;
315     }
316 
317     *exist = true;
318     return 0;
319 }
320 
bt_mesh_load_settings(bt_mesh_nvs_handle_t handle,const char * key,uint8_t * buf,size_t buf_len,bool * exist)321 int bt_mesh_load_settings(bt_mesh_nvs_handle_t handle, const char *key,
322                           uint8_t *buf, size_t buf_len, bool *exist)
323 {
324     int err = 0;
325     bt_mesh_settings_lock();
326     err = settings_load(handle, key, buf, buf_len, exist);
327     bt_mesh_settings_unlock();
328     return err;
329 }
330 
bt_mesh_load_core_settings(const char * key,uint8_t * buf,size_t buf_len,bool * exist)331 int bt_mesh_load_core_settings(const char *key, uint8_t *buf, size_t buf_len, bool *exist)
332 {
333     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE);
334     return bt_mesh_load_settings(handle, key, buf, buf_len, exist);
335 }
336 
337 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
bt_mesh_load_uid_settings(const char * key,uint8_t * buf,size_t buf_len,bool * exist)338 int bt_mesh_load_uid_settings(const char *key, uint8_t *buf, size_t buf_len, bool *exist)
339 {
340     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
341     return bt_mesh_load_settings(handle, key, buf, buf_len, exist);
342 }
343 #endif
344 
345 /* API used to get length of BLE Mesh related settings */
346 
settings_get_length(bt_mesh_nvs_handle_t handle,const char * key)347 static size_t settings_get_length(bt_mesh_nvs_handle_t handle, const char *key)
348 {
349     size_t len = 0U;
350     int err = 0;
351 
352     if (key == NULL) {
353         BT_ERR("%s, Invalid parameter", __func__);
354         return 0;
355     }
356 
357     err = nvs_get_blob(handle, key, NULL, &len);
358     if (err != ESP_OK) {
359         if (err != ESP_ERR_NVS_NOT_FOUND) {
360             BT_ERR("Failed to get %s length (err %d)", key, err);
361         }
362         return 0;
363     }
364 
365     return len;
366 }
367 
368 /* API used to get BLE Mesh related items. Here items mean model key, NetKey/AppKey
369  * Index, etc. which are going to be used as the prefix of the nvs keys of the BLE
370  * Mesh settings.
371  */
372 
settings_get_item(bt_mesh_nvs_handle_t handle,const char * key)373 static struct net_buf_simple *settings_get_item(bt_mesh_nvs_handle_t handle, const char *key)
374 {
375     struct net_buf_simple *buf = NULL;
376     size_t length = 0U;
377     bool exist = false;
378     int err = 0;
379 
380     length = settings_get_length(handle, key);
381     if (!length) {
382         BT_DBG("Empty %s", key);
383         return NULL;
384     }
385 
386     buf = bt_mesh_alloc_buf(length);
387     if (!buf) {
388         BT_ERR("%s, Out of memory", __func__);
389         /* TODO: in this case, erase all related settings? */
390         return NULL;
391     }
392 
393     err = settings_load(handle, key, buf->data, length, &exist);
394     if (err) {
395         BT_ERR("Failed to load %s", key);
396         /* TODO: in this case, erase all related settings? */
397         bt_mesh_free_buf(buf);
398         return NULL;
399     }
400 
401     if (exist == false) {
402         bt_mesh_free_buf(buf);
403         return NULL;
404     }
405 
406     buf->len = length;
407     return buf;
408 }
409 
bt_mesh_get_settings_item(bt_mesh_nvs_handle_t handle,const char * key)410 struct net_buf_simple *bt_mesh_get_settings_item(bt_mesh_nvs_handle_t handle, const char *key)
411 {
412     struct net_buf_simple *buf = NULL;
413     bt_mesh_settings_lock();
414     buf = settings_get_item(handle, key);
415     bt_mesh_settings_unlock();
416     return buf;
417 }
418 
bt_mesh_get_core_settings_item(const char * key)419 struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key)
420 {
421     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE);
422     return bt_mesh_get_settings_item(handle, key);
423 }
424 
425 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
bt_mesh_get_uid_settings_item(const char * key)426 struct net_buf_simple *bt_mesh_get_uid_settings_item(const char *key)
427 {
428     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
429     return bt_mesh_get_settings_item(handle, key);
430 }
431 #endif
432 
433 /* API used to check if the settings item exists */
434 
is_settings_item_exist(struct net_buf_simple * buf,const uint16_t val)435 static bool is_settings_item_exist(struct net_buf_simple *buf, const uint16_t val)
436 {
437     struct net_buf_simple_state state = {0};
438     size_t length = 0U;
439     int i;
440 
441     if (!buf) {
442         return false;
443     }
444 
445     net_buf_simple_save(buf, &state);
446 
447     length = buf->len;
448     for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) {
449         uint16_t item = net_buf_simple_pull_le16(buf);
450         if (item == val) {
451             net_buf_simple_restore(buf, &state);
452             return true;
453         }
454     }
455 
456     net_buf_simple_restore(buf, &state);
457     return false;
458 }
459 
460 /* API used to add the settings item */
461 
settings_add_item(bt_mesh_nvs_handle_t handle,const char * key,const uint16_t val)462 static int settings_add_item(bt_mesh_nvs_handle_t handle, const char *key, const uint16_t val)
463 {
464     struct net_buf_simple *store = NULL;
465     struct net_buf_simple *buf = NULL;
466     size_t length = 0U;
467     int err = 0;
468 
469     buf = settings_get_item(handle, key);
470 
471     /* Check if val already exists */
472     if (is_settings_item_exist(buf, val) == true) {
473         BT_DBG("0x%04x already exists", val);
474         bt_mesh_free_buf(buf);
475         return 0;
476     }
477 
478     length = (buf ? buf->len : 0) + sizeof(val);
479 
480     store = bt_mesh_alloc_buf(length);
481     if (!store) {
482         BT_ERR("%s, Out of memory", __func__);
483         bt_mesh_free_buf(buf);
484         return -ENOMEM;
485     }
486 
487     if (buf) {
488         net_buf_simple_add_mem(store, buf->data, buf->len);
489     }
490     net_buf_simple_add_mem(store, &val, sizeof(val));
491 
492     err = settings_save(handle, key, store->data, store->len);
493 
494     bt_mesh_free_buf(store);
495     bt_mesh_free_buf(buf);
496     return err;
497 }
498 
bt_mesh_add_settings_item(bt_mesh_nvs_handle_t handle,const char * key,const uint16_t val)499 int bt_mesh_add_settings_item(bt_mesh_nvs_handle_t handle, const char *key, const uint16_t val)
500 {
501     int err = 0;
502     bt_mesh_settings_lock();
503     err = settings_add_item(handle, key, val);
504     bt_mesh_settings_unlock();
505     return err;
506 }
507 
bt_mesh_add_core_settings_item(const char * key,const uint16_t val)508 int bt_mesh_add_core_settings_item(const char *key, const uint16_t val)
509 {
510     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE);
511     return bt_mesh_add_settings_item(handle, key, val);
512 }
513 
514 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
bt_mesh_add_uid_settings_item(const char * key,const uint16_t val)515 int bt_mesh_add_uid_settings_item(const char *key, const uint16_t val)
516 {
517     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
518     return bt_mesh_add_settings_item(handle, key, val);
519 }
520 #endif
521 
522 /* API used to remove the settings item */
523 
settings_remove_item(bt_mesh_nvs_handle_t handle,const char * key,const uint16_t val)524 static int settings_remove_item(bt_mesh_nvs_handle_t handle, const char *key, const uint16_t val)
525 {
526     struct net_buf_simple *store = NULL;
527     struct net_buf_simple *buf = NULL;
528     size_t length = 0U;
529     size_t buf_len = 0U;
530     int err = 0;
531     int i;
532 
533     buf = settings_get_item(handle, key);
534 
535     /* Check if val does exist */
536     if (is_settings_item_exist(buf, val) == false) {
537         BT_DBG("0x%04x not exists", val);
538         bt_mesh_free_buf(buf);
539         return 0;
540     }
541 
542     length = buf->len - sizeof(val);
543     if (!length) {
544         settings_save(handle, key, NULL, 0);
545         bt_mesh_free_buf(buf);
546         return 0;
547     }
548 
549     store = bt_mesh_alloc_buf(length);
550     if (!store) {
551         BT_ERR("%s, Out of memory", __func__);
552         bt_mesh_free_buf(buf);
553         return -ENOMEM;
554     }
555 
556     buf_len = buf->len;
557     for (i = 0; i < buf_len / SETTINGS_ITEM_SIZE; i++) {
558         uint16_t item = net_buf_simple_pull_le16(buf);
559         if (item != val) {
560             net_buf_simple_add_le16(store, item);
561         }
562     }
563 
564     err = settings_save(handle, key, store->data, store->len);
565 
566     bt_mesh_free_buf(store);
567     bt_mesh_free_buf(buf);
568     return err;
569 }
570 
bt_mesh_remove_settings_item(bt_mesh_nvs_handle_t handle,const char * key,const uint16_t val)571 int bt_mesh_remove_settings_item(bt_mesh_nvs_handle_t handle, const char *key, const uint16_t val)
572 {
573     int err = 0;
574     bt_mesh_settings_lock();
575     err = settings_remove_item(handle, key, val);
576     bt_mesh_settings_unlock();
577     return err;
578 }
579 
bt_mesh_remove_core_settings_item(const char * key,const uint16_t val)580 int bt_mesh_remove_core_settings_item(const char *key, const uint16_t val)
581 {
582     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE);
583     return bt_mesh_remove_settings_item(handle, key, val);
584 }
585 
586 #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
bt_mesh_remove_uid_settings_item(const char * key,const uint16_t val)587 int bt_mesh_remove_uid_settings_item(const char *key, const uint16_t val)
588 {
589     bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
590     return bt_mesh_remove_settings_item(handle, key, val);
591 }
592 #endif
593 
bt_mesh_settings_erase_key(bt_mesh_nvs_handle_t handle,const char * key)594 int bt_mesh_settings_erase_key(bt_mesh_nvs_handle_t handle, const char *key)
595 {
596     int err = 0;
597 
598     err = nvs_erase_key(handle, key);
599     if (err != ESP_OK) {
600         if (err == ESP_ERR_NVS_NOT_FOUND) {
601             return 0;
602         }
603 
604         BT_ERR("Failed to erase %s (err %d)", key, err);
605         return -EIO;
606     }
607 
608     err = nvs_commit(handle);
609     if (err != ESP_OK) {
610         BT_ERR("Failed to commit nvs (err %d)", err);
611         return -EIO;
612     }
613 
614     return 0;
615 }
616 
bt_mesh_settings_erase_all(bt_mesh_nvs_handle_t handle)617 int bt_mesh_settings_erase_all(bt_mesh_nvs_handle_t handle)
618 {
619     int err = 0;
620 
621     err = nvs_erase_all(handle);
622     if (err != ESP_OK) {
623         BT_ERR("Failed to erase all (err %d)", err);
624         return -EIO;
625     }
626 
627     err = nvs_commit(handle);
628     if (err != ESP_OK) {
629         BT_ERR("Failed to commit nvs (err %d)", err);
630         return -EIO;
631     }
632 
633     return 0;
634 }
635 #endif /* CONFIG_BLE_MESH_SETTINGS */
636