Bluetooth: Mesh: Add support for Models Metadata Page 128
This patch adds for handling Models Metadata Get Page 128. Signed-off-by: Michal Narajowski <michal.narajowski@codecoup.pl> Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
parent
007bca7b63
commit
d95fe3f52b
7 changed files with 175 additions and 31 deletions
|
@ -897,6 +897,15 @@ bool bt_mesh_model_is_extended(struct bt_mesh_model *model);
|
|||
*/
|
||||
int bt_mesh_comp_change_prepare(void);
|
||||
|
||||
/** @brief Indicate that the metadata will change on next bootup.
|
||||
*
|
||||
* Tell the config server that the models metadata is expected to change on
|
||||
* the next bootup, and the current models metadata should be backed up.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_models_metadata_change_prepare(void);
|
||||
|
||||
/** Node Composition */
|
||||
struct bt_mesh_comp {
|
||||
uint16_t cid; /**< Company ID */
|
||||
|
|
|
@ -1235,8 +1235,19 @@ config BT_MESH_LARGE_COMP_DATA_SRV
|
|||
help
|
||||
Enable support for the Large Composition Data Server model.
|
||||
|
||||
if BT_MESH_LARGE_COMP_DATA_SRV
|
||||
|
||||
config BT_MESH_MODELS_METADATA_PAGE_LEN
|
||||
int "Maximum length of the Models Metadata Page"
|
||||
default 150
|
||||
help
|
||||
This value is the combined total metadata length for
|
||||
all models on the device.
|
||||
|
||||
endif # BT_MESH_LARGE_COMP_DATA_SRV
|
||||
|
||||
config BT_MESH_LARGE_COMP_DATA_CLI
|
||||
bool "Support for Large Composition Data Client Model"
|
||||
bool "Support for Large Composition Data Client model"
|
||||
help
|
||||
Enable support for the Large Composition Data Client model.
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV
|
||||
#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
|
||||
static void data_buf_add_mem_offset(struct net_buf_simple *buf,
|
||||
const void *mem, size_t len,
|
||||
size_t *offset)
|
||||
|
@ -190,6 +190,10 @@ static size_t metadata_model_size(struct bt_mesh_model *mod,
|
|||
const struct bt_mesh_models_metadata_entry *entry;
|
||||
size_t size = 0;
|
||||
|
||||
if (!mod->metadata) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (vnd) {
|
||||
size += sizeof(mod->vnd.company);
|
||||
size += sizeof(mod->vnd.id);
|
||||
|
@ -199,10 +203,6 @@ static size_t metadata_model_size(struct bt_mesh_model *mod,
|
|||
|
||||
size += sizeof(uint8_t);
|
||||
|
||||
if (!mod->metadata) {
|
||||
return size;
|
||||
}
|
||||
|
||||
for (entry = *mod->metadata; entry && entry->len; ++entry) {
|
||||
size += sizeof(entry->len) + sizeof(entry->id) + entry->len;
|
||||
}
|
||||
|
@ -254,13 +254,13 @@ static int metadata_add_model(struct bt_mesh_model *mod,
|
|||
|
||||
model_size = metadata_model_size(mod, elem, vnd);
|
||||
|
||||
if (*offset <= model_size) {
|
||||
if (*offset >= model_size) {
|
||||
*offset -= model_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (net_buf_simple_tailroom(buf) < (model_size + BT_MESH_MIC_SHORT)) {
|
||||
LOG_ERR("Too large metadata");
|
||||
LOG_DBG("Model metadata didn't fit in the buffer");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,6 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset)
|
|||
};
|
||||
uint8_t *mod_count_ptr;
|
||||
uint8_t *vnd_count_ptr;
|
||||
uint8_t mod_count = 0;
|
||||
int i, j, err;
|
||||
|
||||
comp = bt_mesh_comp_get();
|
||||
|
@ -317,19 +316,16 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset)
|
|||
continue;
|
||||
}
|
||||
|
||||
++mod_count;
|
||||
err = metadata_add_model(model, elem, false, &arg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (mod_count_ptr) {
|
||||
*mod_count_ptr = mod_count;
|
||||
if (mod_count_ptr) {
|
||||
(*mod_count_ptr) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
mod_count = 0;
|
||||
|
||||
for (j = 0; j < elem->vnd_model_count; j++) {
|
||||
struct bt_mesh_model *model = &elem->vnd_models[j];
|
||||
|
||||
|
@ -337,15 +333,14 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset)
|
|||
continue;
|
||||
}
|
||||
|
||||
++mod_count;
|
||||
err = metadata_add_model(model, elem, true, &arg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (vnd_count_ptr) {
|
||||
*vnd_count_ptr = mod_count;
|
||||
if (vnd_count_ptr) {
|
||||
(*vnd_count_ptr) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1990,6 +1985,116 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
|
|||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
|
||||
static int metadata_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
/* Only need to know that the entry exists. Will load the contents on
|
||||
* demand.
|
||||
*/
|
||||
if (len_rd > 0) {
|
||||
atomic_set_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
BT_MESH_SETTINGS_DEFINE(metadata, "metadata", metadata_set);
|
||||
|
||||
int bt_mesh_models_metadata_store(void)
|
||||
{
|
||||
NET_BUF_SIMPLE_DEFINE(buf, CONFIG_BT_MESH_MODELS_METADATA_PAGE_LEN);
|
||||
size_t total_size;
|
||||
int err;
|
||||
|
||||
total_size = bt_mesh_metadata_page_0_size();
|
||||
LOG_DBG("bt/mesh/metadata total %d", total_size);
|
||||
|
||||
net_buf_simple_init(&buf, 0);
|
||||
net_buf_simple_add_le16(&buf, total_size);
|
||||
|
||||
err = bt_mesh_metadata_get_page_0(&buf, 0);
|
||||
if (err == -E2BIG) {
|
||||
LOG_ERR("Metadata too large");
|
||||
return err;
|
||||
}
|
||||
if (err) {
|
||||
LOG_ERR("Failed to read models metadata: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_DBG("bt/mesh/metadata len %d", buf.len);
|
||||
|
||||
err = settings_save_one("bt/mesh/metadata", buf.data, buf.len);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to store models metadata: %d", err);
|
||||
} else {
|
||||
LOG_DBG("Stored models metadata");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_models_metadata_read(struct net_buf_simple *buf, size_t offset)
|
||||
{
|
||||
NET_BUF_SIMPLE_DEFINE(stored_buf, CONFIG_BT_MESH_MODELS_METADATA_PAGE_LEN);
|
||||
size_t original_len = buf->len;
|
||||
int err;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
net_buf_simple_init(&stored_buf, 0);
|
||||
|
||||
err = settings_load_subtree_direct("bt/mesh/metadata", read_comp_cb, &stored_buf);
|
||||
if (err) {
|
||||
LOG_ERR("Failed reading models metadata: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* First two bytes are total length */
|
||||
offset += 2;
|
||||
|
||||
net_buf_simple_add_mem(buf, &stored_buf.data, MIN(net_buf_simple_tailroom(buf), 2));
|
||||
|
||||
if (offset >= stored_buf.len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
net_buf_simple_add_mem(buf, &stored_buf.data[offset],
|
||||
MIN(net_buf_simple_tailroom(buf), stored_buf.len - offset));
|
||||
|
||||
LOG_DBG("metadata read %d", buf->len);
|
||||
|
||||
if (buf->len == original_len) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bt_mesh_models_metadata_clear(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = settings_delete("bt/mesh/metadata");
|
||||
if (err) {
|
||||
LOG_ERR("Failed to clear models metadata: %d", err);
|
||||
} else {
|
||||
LOG_DBG("Cleared models metadata");
|
||||
}
|
||||
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY);
|
||||
}
|
||||
|
||||
int bt_mesh_models_metadata_change_prepare(void)
|
||||
{
|
||||
#if !IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
return bt_mesh_models_metadata_store();
|
||||
}
|
||||
|
||||
static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
|
|
|
@ -65,6 +65,10 @@ int bt_mesh_comp_store(void);
|
|||
void bt_mesh_comp_clear(void);
|
||||
int bt_mesh_comp_read(struct net_buf_simple *buf);
|
||||
|
||||
int bt_mesh_models_metadata_store(void);
|
||||
void bt_mesh_models_metadata_clear(void);
|
||||
int bt_mesh_models_metadata_read(struct net_buf_simple *buf, size_t offset);
|
||||
|
||||
void bt_mesh_model_pending_store(void);
|
||||
void bt_mesh_model_bind_store(struct bt_mesh_model *mod);
|
||||
void bt_mesh_model_sub_store(struct bt_mesh_model *mod);
|
||||
|
|
|
@ -91,8 +91,8 @@ static int handle_models_metadata_get(struct bt_mesh_model *model, struct bt_mes
|
|||
{
|
||||
BT_MESH_MODEL_BUF_DEFINE(rsp, OP_MODELS_METADATA_STATUS,
|
||||
BT_MESH_MODEL_PAYLOAD_MAX);
|
||||
uint8_t page;
|
||||
size_t offset, total_size;
|
||||
uint8_t page;
|
||||
int err;
|
||||
|
||||
LOG_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
|
@ -104,25 +104,38 @@ static int handle_models_metadata_get(struct bt_mesh_model *model, struct bt_mes
|
|||
|
||||
LOG_DBG("page %u offset %u", page, offset);
|
||||
|
||||
bt_mesh_model_msg_init(&rsp, OP_MODELS_METADATA_STATUS);
|
||||
|
||||
if (page != 0U) {
|
||||
LOG_DBG("Composition page %u not available", page);
|
||||
if (page >= 128U && atomic_test_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY)) {
|
||||
LOG_DBG("Models Metadata Page 128");
|
||||
page = 128U;
|
||||
} else if (page != 0U) {
|
||||
LOG_DBG("Models Metadata Page %u not available", page);
|
||||
page = 0U;
|
||||
}
|
||||
|
||||
bt_mesh_model_msg_init(&rsp, OP_MODELS_METADATA_STATUS);
|
||||
net_buf_simple_add_u8(&rsp, page);
|
||||
|
||||
total_size = bt_mesh_metadata_page_0_size();
|
||||
net_buf_simple_add_le16(&rsp, offset);
|
||||
net_buf_simple_add_le16(&rsp, total_size);
|
||||
|
||||
if (offset < total_size) {
|
||||
err = bt_mesh_metadata_get_page_0(&rsp, offset);
|
||||
if (err && err != -E2BIG) {
|
||||
LOG_ERR("bt_mesh_metadata_get_page_0 returned error");
|
||||
if (atomic_test_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY) == (page == 0U)) {
|
||||
rsp.size -= BT_MESH_MIC_SHORT;
|
||||
err = bt_mesh_models_metadata_read(&rsp, offset);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to get stored models metadata");
|
||||
return err;
|
||||
}
|
||||
|
||||
rsp.size += BT_MESH_MIC_SHORT;
|
||||
} else {
|
||||
total_size = bt_mesh_metadata_page_0_size();
|
||||
net_buf_simple_add_le16(&rsp, total_size);
|
||||
|
||||
if (offset < total_size) {
|
||||
err = bt_mesh_metadata_get_page_0(&rsp, offset);
|
||||
if (err && err != -E2BIG) {
|
||||
LOG_ERR("Failed to get Models Metadata Page 0: %d", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, &rsp, NULL, NULL)) {
|
||||
|
|
|
@ -161,6 +161,7 @@ void bt_mesh_reprovision(uint16_t addr)
|
|||
bt_mesh_net_pending_net_store();
|
||||
bt_mesh_net_pending_seq_store();
|
||||
bt_mesh_comp_clear();
|
||||
bt_mesh_models_metadata_clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ enum {
|
|||
BT_MESH_IVU_PENDING, /* Update blocked by SDU in progress */
|
||||
BT_MESH_COMP_DIRTY, /* Composition data is dirty */
|
||||
BT_MESH_DEVKEY_CAND, /* Has device key candidate */
|
||||
BT_MESH_METADATA_DIRTY, /* Models metadata is dirty */
|
||||
|
||||
/* Feature flags */
|
||||
BT_MESH_RELAY,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue