From 91ca7ca763505f12bbbcd5ba4d2db4dc40f29d3f Mon Sep 17 00:00:00 2001 From: Trond Einar Snekvik Date: Mon, 19 Aug 2019 10:44:32 +0200 Subject: [PATCH] Bluetooth: Mesh: Add persistent model user data Adds user data file in the model settings, allowing each model instance to store some application specific data without having to reinvent the settings path encoding for model element/ID combinations. Exposes the settings_handler interface in the model callback structure and adds a data store function. Signed-off-by: Trond Einar Snekvik --- include/bluetooth/mesh/access.h | 43 ++++++++++++++++++++++++++++++++ subsys/bluetooth/mesh/settings.c | 30 ++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/include/bluetooth/mesh/access.h b/include/bluetooth/mesh/access.h index 64f47dc6066..90a75da02f3 100644 --- a/include/bluetooth/mesh/access.h +++ b/include/bluetooth/mesh/access.h @@ -10,6 +10,8 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_ACCESS_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_ACCESS_H_ +#include + /** * @brief Bluetooth Mesh Access Layer * @defgroup bt_mesh_access Bluetooth Mesh Access Layer @@ -382,6 +384,35 @@ struct bt_mesh_model_pub { /** Model callback functions. */ struct bt_mesh_model_cb { + /** @brief Set value handler of user data tied to the model. + * + * @sa settings_handler::h_set + * + * @param model Model to set the persistent data of. + * @param len_rd The size of the data found in the backend. + * @param read_cb Function provided to read the data from the backend. + * @param cb_arg Arguments for the read function provided by the + * backend. + * + * @return 0 on success, error otherwise. + */ + int (*const settings_set)(struct bt_mesh_model *model, + size_t len_rd, settings_read_cb read_cb, + void *cb_arg); + + /** @brief Callback called when all settings have been loaded. + * + * This handler gets called after the settings have been loaded in + * full. + * + * @sa settings_handler::h_commit + * + * @param model Model this callback belongs to. + * + * @return 0 on success, error otherwise. + */ + int (*const settings_commit)(struct bt_mesh_model *model); + /** @brief Model init callback. * * Called on every model instance during mesh initialization. @@ -515,6 +546,18 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod) return (mod->elem_idx == 0); } +/** @brief Immediately store the model's user data in persistent storage. + * + * @param mod Mesh model. + * @param vnd This is a vendor model. + * @param data Model data to store, or NULL to delete any model data. + * @param data_len Length of the model data. + * + * @return 0 on success, or (negative) error code on failure. + */ +int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, + const void *data, size_t data_len); + /** Node Composition */ struct bt_mesh_comp { u16_t cid; diff --git a/subsys/bluetooth/mesh/settings.c b/subsys/bluetooth/mesh/settings.c index 1ac2b85bff8..a1583491030 100644 --- a/subsys/bluetooth/mesh/settings.c +++ b/subsys/bluetooth/mesh/settings.c @@ -660,6 +660,10 @@ static int mod_set(bool vnd, const char *name, size_t len_rd, return mod_set_pub(mod, len_rd, read_cb, cb_arg); } + if (!strncmp(next, "data", len) && mod->cb && mod->cb->settings_set) { + return mod->cb->settings_set(mod, len_rd, read_cb, cb_arg); + } + BT_WARN("Unknown module key %s", next); return -ENOENT; } @@ -759,6 +763,10 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, k_delayed_work_submit(&mod->pub->timer, ms); } } + + if (mod->cb && mod->cb->settings_commit) { + mod->cb->settings_commit(mod); + } } static int mesh_commit(void) @@ -1574,6 +1582,28 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *mod) schedule_store(BT_MESH_MOD_PENDING); } +int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, + const void *data, size_t data_len) +{ + char path[20]; + int err; + + encode_mod_path(mod, vnd, "data", path, sizeof(path)); + + if (data_len) { + err = settings_save_one(path, data, data_len); + } else { + err = settings_delete(path); + } + + if (err) { + BT_ERR("Failed to store %s value", log_strdup(path)); + } else { + BT_DBG("Stored %s value", log_strdup(path)); + } + return err; +} + void bt_mesh_settings_init(void) { k_delayed_work_init(&pending_store, store_pending);