mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ble_mesh: Persistent storage of Virtual Address
The 16-bit format group addresses will be stored, but we don't store (or restore) the virtual label UUIDs, i.e. after a power cycle the 16-bit group addresses would be meaningless.
This commit is contained in:
parent
51616eacee
commit
4405560483
@ -47,11 +47,7 @@
|
||||
|
||||
static struct bt_mesh_cfg_srv *conf;
|
||||
|
||||
static struct label {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
} labels[CONFIG_BLE_MESH_LABEL_COUNT];
|
||||
static struct label labels[CONFIG_BLE_MESH_LABEL_COUNT];
|
||||
|
||||
static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem,
|
||||
bool primary)
|
||||
@ -1152,25 +1148,61 @@ send_status:
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
|
||||
static u8_t va_add(u8_t *label_uuid, u16_t *addr)
|
||||
struct label *get_label(u16_t index)
|
||||
{
|
||||
struct label *free_slot = NULL;
|
||||
if (index >= ARRAY_SIZE(labels)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &labels[index];
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
|
||||
static inline void va_store(struct label *store)
|
||||
{
|
||||
bt_mesh_atomic_set_bit(store->flags, BLE_MESH_VA_CHANGED);
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_label();
|
||||
}
|
||||
}
|
||||
|
||||
static struct label *va_find(const u8_t *label_uuid,
|
||||
struct label **free_slot)
|
||||
{
|
||||
struct label *match = NULL;
|
||||
int i;
|
||||
|
||||
if (free_slot != NULL) {
|
||||
*free_slot = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(labels); i++) {
|
||||
if (!labels[i].ref) {
|
||||
free_slot = &labels[i];
|
||||
if (labels[i].ref == 0) {
|
||||
if (free_slot != NULL) {
|
||||
*free_slot = &labels[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(labels[i].uuid, label_uuid, 16)) {
|
||||
*addr = labels[i].addr;
|
||||
labels[i].ref++;
|
||||
return STATUS_SUCCESS;
|
||||
match = &labels[i];
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static u8_t va_add(u8_t *label_uuid, u16_t *addr)
|
||||
{
|
||||
struct label *update, *free_slot = NULL;
|
||||
|
||||
update = va_find(label_uuid, &free_slot);
|
||||
if (update) {
|
||||
update->ref++;
|
||||
va_store(update);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!free_slot) {
|
||||
return STATUS_INSUFF_RESOURCES;
|
||||
}
|
||||
@ -1182,23 +1214,24 @@ static u8_t va_add(u8_t *label_uuid, u16_t *addr)
|
||||
free_slot->ref = 1U;
|
||||
free_slot->addr = *addr;
|
||||
memcpy(free_slot->uuid, label_uuid, 16);
|
||||
va_store(free_slot);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static u8_t va_del(u8_t *label_uuid, u16_t *addr)
|
||||
{
|
||||
int i;
|
||||
struct label *update;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(labels); i++) {
|
||||
if (!memcmp(labels[i].uuid, label_uuid, 16)) {
|
||||
if (addr) {
|
||||
*addr = labels[i].addr;
|
||||
}
|
||||
update = va_find(label_uuid, NULL);
|
||||
if (update) {
|
||||
update->ref--;
|
||||
|
||||
labels[i].ref--;
|
||||
return STATUS_SUCCESS;
|
||||
if (addr) {
|
||||
*addr = update->addr;
|
||||
}
|
||||
|
||||
va_store(update);
|
||||
}
|
||||
|
||||
if (addr) {
|
||||
|
@ -117,6 +117,17 @@
|
||||
#define STATUS_UNSPECIFIED 0x10
|
||||
#define STATUS_INVALID_BINDING 0x11
|
||||
|
||||
enum {
|
||||
BLE_MESH_VA_CHANGED, /* Label information changed */
|
||||
};
|
||||
|
||||
struct label {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
bt_mesh_atomic_t flags[1];
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary);
|
||||
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary);
|
||||
|
||||
@ -129,6 +140,8 @@ void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
|
||||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
|
||||
|
||||
struct label *get_label(u16_t index);
|
||||
|
||||
u8_t *bt_mesh_label_uuid_get(u16_t addr);
|
||||
|
||||
struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
|
||||
|
@ -224,6 +224,7 @@ enum {
|
||||
BLE_MESH_HB_PUB_PENDING,
|
||||
BLE_MESH_CFG_PENDING,
|
||||
BLE_MESH_MOD_PENDING,
|
||||
BLE_MESH_VA_PENDING,
|
||||
|
||||
/* Don't touch - intentionally last */
|
||||
BLE_MESH_FLAG_COUNT,
|
||||
|
@ -55,6 +55,8 @@
|
||||
* key: "mesh/v/xxxx/b" -> write/read to set/get VENDOR MODEL Bind AppKey List
|
||||
* key: "mesh/v/xxxx/s" -> write/read to set/get VENDOR MODEL Subscription List
|
||||
* key: "mesh/v/xxxx/p" -> write/read to set/get VENDOR MODEL Publication
|
||||
* key: "mesh/vaddr" -> write/read to set/get all virtual addresses
|
||||
* key: "mesh/va/xxxx" -> write/read to set/get the "xxxx" virtual address
|
||||
*/
|
||||
|
||||
#if CONFIG_BLE_MESH_SETTINGS
|
||||
@ -142,6 +144,13 @@ struct mod_pub_val {
|
||||
cred: 1;
|
||||
};
|
||||
|
||||
/* Virtual Address information */
|
||||
struct va_val {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
} __packed;
|
||||
|
||||
/* We need this so we don't overwrite app-hardcoded values in case FCB
|
||||
* contains a history of changes but then has a NULL at the end.
|
||||
*/
|
||||
@ -695,6 +704,66 @@ static int vnd_mod_set(const char *name)
|
||||
return model_set(true, name);
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
|
||||
static int va_set(const char *name)
|
||||
{
|
||||
struct net_buf_simple *buf = NULL;
|
||||
struct va_val va = {0};
|
||||
char get[16] = {'\0'};
|
||||
struct label *lab;
|
||||
size_t length;
|
||||
bool exist;
|
||||
int err = 0;
|
||||
u16_t i;
|
||||
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
buf = bt_mesh_get_core_settings_item(name);
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = buf->len;
|
||||
|
||||
for (i = 0U; i < length / SETTINGS_ITEM_SIZE; i++) {
|
||||
u16_t index = net_buf_simple_pull_le16(buf);
|
||||
sprintf(get, "mesh/va/%04x", index);
|
||||
|
||||
err = bt_mesh_load_core_settings(get, (u8_t *)&va, sizeof(va), &exist);
|
||||
if (err) {
|
||||
BT_ERR("%s, Failed to load virtual address %s", __func__, get);
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (exist == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (va.ref == 0) {
|
||||
BT_DBG("Ignore virtual address %s with ref = 0", get);
|
||||
goto free;
|
||||
}
|
||||
|
||||
lab = get_label(index);
|
||||
if (lab == NULL) {
|
||||
BT_WARN("%s, Out of labels buffers", __func__);
|
||||
err = -ENOBUFS;
|
||||
goto free;
|
||||
}
|
||||
|
||||
memcpy(lab->uuid, va.uuid, 16);
|
||||
lab->addr = va.addr;
|
||||
lab->ref = va.ref;
|
||||
|
||||
BT_DBG("Restore virtual address 0x%04x ref 0x%04x", index, lab->ref);
|
||||
}
|
||||
|
||||
free:
|
||||
bt_mesh_free_buf(buf);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct bt_mesh_setting {
|
||||
const char *name;
|
||||
int (*func)(const char *name);
|
||||
@ -709,6 +778,9 @@ const struct bt_mesh_setting {
|
||||
{ "mesh/cfg", cfg_set },
|
||||
{ "mesh/sig", sig_mod_set },
|
||||
{ "mesh/vnd", vnd_mod_set },
|
||||
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
|
||||
{ "mesh/vaddr", va_set },
|
||||
#endif
|
||||
};
|
||||
|
||||
int settings_core_load(void)
|
||||
@ -1331,6 +1403,52 @@ static void store_pending_mod(struct bt_mesh_model *model,
|
||||
}
|
||||
}
|
||||
|
||||
#define IS_VA_DEL(_label) ((_label)->ref == 0)
|
||||
static void store_pending_va(void)
|
||||
{
|
||||
struct va_val va = {0};
|
||||
char name[16] = {'\0'};
|
||||
struct label *lab;
|
||||
u16_t i;
|
||||
int err;
|
||||
|
||||
for (i = 0U; (lab = get_label(i)) != NULL; i++) {
|
||||
if (!bt_mesh_atomic_test_and_clear_bit(lab->flags,
|
||||
BLE_MESH_VA_CHANGED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(name, "mesh/va/%04x", i);
|
||||
|
||||
if (IS_VA_DEL(lab)) {
|
||||
err = bt_mesh_save_core_settings(name, NULL, 0);
|
||||
} else {
|
||||
va.ref = lab->ref;
|
||||
va.addr = lab->addr;
|
||||
memcpy(va.uuid, lab->uuid, 16);
|
||||
err = bt_mesh_save_core_settings(name, (const u8_t *)&va, sizeof(va));
|
||||
}
|
||||
if (err) {
|
||||
BT_ERR("%s, Failed to %s virtual address %s", __func__,
|
||||
IS_VA_DEL(lab) ? "delete" : "store", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_VA_DEL(lab)) {
|
||||
err = bt_mesh_remove_core_settings_item("mesh/vaddr", i);
|
||||
} else {
|
||||
err = bt_mesh_add_core_settings_item("mesh/vaddr", i);
|
||||
}
|
||||
if (err) {
|
||||
BT_ERR("%s, Failed to %s 0x%04x in mesh/vaddr", __func__,
|
||||
IS_VA_DEL(lab) ? "delete" : "store", i);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("%s virtual address 0x%04x", IS_VA_DEL(lab) ? "Delete" : "Store", i);
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending(struct k_work *work)
|
||||
{
|
||||
BT_DBG("%s", __func__);
|
||||
@ -1386,6 +1504,10 @@ static void store_pending(struct k_work *work)
|
||||
bt_mesh_save_core_settings("mesh/vnd", NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_VA_PENDING)) {
|
||||
store_pending_va();
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
|
||||
@ -1570,6 +1692,11 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *model)
|
||||
schedule_store(BLE_MESH_MOD_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_store_label(void)
|
||||
{
|
||||
schedule_store(BLE_MESH_VA_PENDING);
|
||||
}
|
||||
|
||||
int settings_core_init(void)
|
||||
{
|
||||
BT_DBG("%s", __func__);
|
||||
|
@ -28,6 +28,7 @@ void bt_mesh_store_cfg(void);
|
||||
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_store_label(void);
|
||||
|
||||
void bt_mesh_clear_net(void);
|
||||
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
|
||||
|
Loading…
x
Reference in New Issue
Block a user