From efb68ca2da855edb330384e45f429f00b56a0d70 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 10 May 2018 09:38:24 +0300 Subject: [PATCH] Bluetooth: Mesh: Support for storing model publication persistently Add support for storing the model publication information persistently. The addresses are stored under the settings key bt/mesh/s//pub for SIG models and bt/mesh/v//pub for vendor models. Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/mesh/access.h | 1 + subsys/bluetooth/host/mesh/cfg_srv.c | 8 ++ subsys/bluetooth/host/mesh/settings.c | 121 ++++++++++++++++++++++++++ subsys/bluetooth/host/mesh/settings.h | 1 + 4 files changed, 131 insertions(+) diff --git a/subsys/bluetooth/host/mesh/access.h b/subsys/bluetooth/host/mesh/access.h index 9d7720ac15d..a6b9d0eaa3d 100644 --- a/subsys/bluetooth/host/mesh/access.h +++ b/subsys/bluetooth/host/mesh/access.h @@ -10,6 +10,7 @@ enum { BT_MESH_MOD_BIND_PENDING = BIT(0), BT_MESH_MOD_SUB_PENDING = BIT(1), + BT_MESH_MOD_PUB_PENDING = BIT(2), }; void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count); diff --git a/subsys/bluetooth/host/mesh/cfg_srv.c b/subsys/bluetooth/host/mesh/cfg_srv.c index 8d543e06c04..c5afcf11026 100644 --- a/subsys/bluetooth/host/mesh/cfg_srv.c +++ b/subsys/bluetooth/host/mesh/cfg_srv.c @@ -272,6 +272,10 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, k_delayed_work_cancel(&model->pub->timer); } + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_mod_pub(model); + } + return STATUS_SUCCESS; } @@ -299,6 +303,10 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, } } + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_mod_pub(model); + } + return STATUS_SUCCESS; } diff --git a/subsys/bluetooth/host/mesh/settings.c b/subsys/bluetooth/host/mesh/settings.c index 6ac7deb76f3..098c92c6573 100644 --- a/subsys/bluetooth/host/mesh/settings.c +++ b/subsys/bluetooth/host/mesh/settings.c @@ -84,6 +84,16 @@ struct app_key_val { u8_t val[2][16]; } __packed; +struct mod_pub_val { + u16_t addr; + u16_t key; + u8_t ttl; + u8_t retransmit; + u8_t period; + u8_t period_div:4, + cred:1; +}; + static int net_set(int argc, char **argv, char *val) { struct net_val net; @@ -458,6 +468,55 @@ static int mod_set_sub(struct bt_mesh_model *mod, char *val) return 0; } +static int mod_set_pub(struct bt_mesh_model *mod, char *val) +{ + struct mod_pub_val pub; + int len, err; + + if (!mod->pub) { + BT_WARN("Model has no publication context!"); + return -EINVAL; + } + + if (!val) { + mod->pub->addr = BT_MESH_ADDR_UNASSIGNED; + mod->pub->key = 0; + mod->pub->cred = 0; + mod->pub->ttl = 0; + mod->pub->period = 0; + mod->pub->retransmit = 0; + mod->pub->count = 0; + + BT_DBG("Cleared publication for model"); + return 0; + } + + len = sizeof(pub); + err = settings_bytes_from_str(val, &pub, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return -EINVAL; + } + + if (len != sizeof(pub)) { + BT_ERR("Invalid length for model publication"); + return -EINVAL; + } + + mod->pub->addr = pub.addr; + mod->pub->key = pub.key; + mod->pub->cred = pub.cred; + mod->pub->ttl = pub.ttl; + mod->pub->period = pub.period; + mod->pub->retransmit = pub.retransmit; + mod->pub->count = 0; + + BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", + pub.addr, pub.key); + + return 0; +} + static int mod_set(bool vnd, int argc, char **argv, char *val) { struct bt_mesh_model *mod; @@ -491,6 +550,10 @@ static int mod_set(bool vnd, int argc, char **argv, char *val) return mod_set_sub(mod, val); } + if (!strcmp(argv[1], "pub")) { + return mod_set_pub(mod, val); + } + BT_WARN("Unknown module key %s", argv[1]); return -ENOENT; } @@ -575,6 +638,19 @@ static int subnet_init(struct bt_mesh_subnet *sub) return 0; } +static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, + bool vnd, bool primary, void *user_data) +{ + if (mod->pub && mod->pub->update && + mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) { + s32_t ms = bt_mesh_model_pub_period_get(mod); + if (ms) { + BT_DBG("Starting publish timer (period %u ms)", ms); + k_delayed_work_submit(&mod->pub->timer, ms); + } + } +} + static int mesh_commit(void) { int i; @@ -613,6 +689,8 @@ static int mesh_commit(void) BT_MESH_NET_IVU_TIMEOUT); } + bt_mesh_model_foreach(commit_mod, NULL); + bt_mesh.valid = 1; bt_mesh_net_start(); @@ -993,6 +1071,38 @@ static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) settings_save_one(path, val); } +static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; + struct mod_pub_val pub; + char path[20]; + char *val; + + if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) { + val = NULL; + } else { + pub.addr = mod->pub->addr; + pub.key = mod->pub->key; + pub.ttl = mod->pub->ttl; + pub.retransmit = mod->pub->retransmit; + pub.period = mod->pub->period; + pub.period_div = mod->pub->period_div; + pub.cred = mod->pub->cred; + + val = settings_str_from_bytes(&pub, sizeof(pub), + buf, sizeof(buf)); + if (!val) { + BT_ERR("Unable to encode model publication as value"); + return; + } + } + + encode_mod_path(mod, vnd, "pub", path, sizeof(path)); + + BT_DBG("Saving %s as %s", path, val ? val : "(null)"); + settings_save_one(path, val); +} + static void store_pending_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) @@ -1010,6 +1120,11 @@ static void store_pending_mod(struct bt_mesh_model *mod, mod->flags &= ~BT_MESH_MOD_SUB_PENDING; store_pending_mod_sub(mod, vnd); } + + if (mod->flags & BT_MESH_MOD_PUB_PENDING) { + mod->flags &= ~BT_MESH_MOD_PUB_PENDING; + store_pending_mod_pub(mod, vnd); + } } static void store_pending(struct k_work *work) @@ -1215,6 +1330,12 @@ void bt_mesh_store_mod_sub(struct bt_mesh_model *mod) schedule_store(BT_MESH_MOD_PENDING); } +void bt_mesh_store_mod_pub(struct bt_mesh_model *mod) +{ + mod->flags |= BT_MESH_MOD_PUB_PENDING; + schedule_store(BT_MESH_MOD_PENDING); +} + void bt_mesh_settings_init(void) { k_delayed_work_init(&pending_store, store_pending); diff --git a/subsys/bluetooth/host/mesh/settings.h b/subsys/bluetooth/host/mesh/settings.h index cfb38d1bd68..c8a8e4674e9 100644 --- a/subsys/bluetooth/host/mesh/settings.h +++ b/subsys/bluetooth/host/mesh/settings.h @@ -12,6 +12,7 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub); void bt_mesh_store_app_key(struct bt_mesh_app_key *key); 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_net(void); void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);