From 93709a735947ca38852ce38b0936f5c1c6717aa3 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Wed, 2 Nov 2022 19:31:26 +0800 Subject: [PATCH] Bluetooth: Mesh: Add specific number of keys & groups Since Mesh Spec and Mesh model sayes, some model no need groups and no need keys, such as Config Server, but the current implementation, all model use same configuration, which cause some ram ext comsume. So that, change to specific way, but will consume more footprint size. Signed-off-by: Lingao Meng --- include/zephyr/bluetooth/mesh/access.h | 103 +++++++++++++++++------- include/zephyr/bluetooth/mesh/cfg_cli.h | 7 +- include/zephyr/bluetooth/mesh/cfg_srv.h | 7 +- subsys/bluetooth/mesh/access.c | 21 ++--- subsys/bluetooth/mesh/cfg_srv.c | 18 ++--- 5 files changed, 101 insertions(+), 55 deletions(-) diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index dd2db05bb54..ebc1c06f1a6 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -17,12 +17,10 @@ /* Internal macros used to initialize array members */ #define BT_MESH_KEY_UNUSED_ELT_(IDX, _) BT_MESH_KEY_UNUSED #define BT_MESH_ADDR_UNASSIGNED_ELT_(IDX, _) BT_MESH_ADDR_UNASSIGNED -#define BT_MESH_MODEL_KEYS_UNUSED \ - { LISTIFY(CONFIG_BT_MESH_MODEL_KEY_COUNT, \ - BT_MESH_KEY_UNUSED_ELT_, (,)) } -#define BT_MESH_MODEL_GROUPS_UNASSIGNED \ - { LISTIFY(CONFIG_BT_MESH_MODEL_GROUP_COUNT, \ - BT_MESH_ADDR_UNASSIGNED_ELT_, (,)) } +#define BT_MESH_MODEL_KEYS_UNUSED(_keys) \ + { LISTIFY(_keys, BT_MESH_KEY_UNUSED_ELT_, (,)) } +#define BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps) \ + { LISTIFY(_grps, BT_MESH_ADDR_UNASSIGNED_ELT_, (,)) } /** * @brief Access layer @@ -228,6 +226,62 @@ struct bt_mesh_model_op { /** Helper to define an empty model array */ #define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){}) +/** + * @brief Composition data SIG model entry with callback functions + * with specific number of keys & groups. + * + * @param _id Model ID. + * @param _op Array of model opcode handlers. + * @param _pub Model publish parameters. + * @param _user_data User data for the model. + * @param _keys Number of keys that can be bound to the model. + * Shall not exceed @kconfig{CONFIG_BT_MESH_MODEL_KEY_COUNT}. + * @param _grps Number of addresses that the model can be subscribed to. + * Shall not exceed @kconfig{CONFIG_BT_MESH_MODEL_GROUP_COUNT}. + * @param _cb Callback structure, or NULL to keep no callbacks. + */ +#define BT_MESH_MODEL_CNT_CB(_id, _op, _pub, _user_data, _keys, _grps, _cb) \ +{ \ + .id = (_id), \ + .pub = _pub, \ + .keys = (uint16_t []) BT_MESH_MODEL_KEYS_UNUSED(_keys), \ + .keys_cnt = _keys, \ + .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps), \ + .groups_cnt = _grps, \ + .op = _op, \ + .cb = _cb, \ + .user_data = _user_data, \ +} + +/** + * @brief Composition data vendor model entry with callback functions + * with specific number of keys & groups. + * + * @param _company Company ID. + * @param _id Model ID. + * @param _op Array of model opcode handlers. + * @param _pub Model publish parameters. + * @param _user_data User data for the model. + * @param _keys Number of keys that can be bound to the model. + * Shall not exceed @kconfig{CONFIG_BT_MESH_MODEL_KEY_COUNT}. + * @param _grps Number of addresses that the model can be subscribed to. + * Shall not exceed @kconfig{CONFIG_BT_MESH_MODEL_GROUP_COUNT}. + * @param _cb Callback structure, or NULL to keep no callbacks. + */ +#define BT_MESH_MODEL_CNT_VND_CB(_company, _id, _op, _pub, _user_data, _keys, _grps, _cb) \ +{ \ + .vnd.company = (_company), \ + .vnd.id = (_id), \ + .op = _op, \ + .pub = _pub, \ + .keys = (uint16_t []) BT_MESH_MODEL_KEYS_UNUSED(_keys), \ + .keys_cnt = _keys, \ + .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps), \ + .groups_cnt = _grps, \ + .user_data = _user_data, \ + .cb = _cb, \ +} + /** * @brief Composition data SIG model entry with callback functions. * @@ -237,16 +291,11 @@ struct bt_mesh_model_op { * @param _user_data User data for the model. * @param _cb Callback structure, or NULL to keep no callbacks. */ -#define BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, _cb) \ -{ \ - .id = (_id), \ - .pub = _pub, \ - .keys = BT_MESH_MODEL_KEYS_UNUSED, \ - .groups = BT_MESH_MODEL_GROUPS_UNASSIGNED, \ - .op = _op, \ - .cb = _cb, \ - .user_data = _user_data, \ -} +#define BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, _cb) \ + BT_MESH_MODEL_CNT_CB(_id, _op, _pub, _user_data, \ + CONFIG_BT_MESH_MODEL_KEY_COUNT, \ + CONFIG_BT_MESH_MODEL_GROUP_COUNT, _cb) + /** * @brief Composition data vendor model entry with callback functions. @@ -258,18 +307,10 @@ struct bt_mesh_model_op { * @param _user_data User data for the model. * @param _cb Callback structure, or NULL to keep no callbacks. */ -#define BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, _cb) \ -{ \ - .vnd.company = (_company), \ - .vnd.id = (_id), \ - .op = _op, \ - .pub = _pub, \ - .keys = BT_MESH_MODEL_KEYS_UNUSED, \ - .groups = BT_MESH_MODEL_GROUPS_UNASSIGNED, \ - .user_data = _user_data, \ - .cb = _cb, \ -} - +#define BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, _cb) \ + BT_MESH_MODEL_CNT_VND_CB(_company, _id, _op, _pub, _user_data, \ + CONFIG_BT_MESH_MODEL_KEY_COUNT, \ + CONFIG_BT_MESH_MODEL_GROUP_COUNT, _cb) /** * @brief Composition data SIG model entry. @@ -533,10 +574,12 @@ struct bt_mesh_model { struct bt_mesh_model_pub * const pub; /** AppKey List */ - uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; + uint16_t * const keys; + const uint16_t keys_cnt; /** Subscription List (group or virtual addresses) */ - uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; + uint16_t * const groups; + const uint16_t groups_cnt; /** Opcode handler list */ const struct bt_mesh_model_op * const op; diff --git a/include/zephyr/bluetooth/mesh/cfg_cli.h b/include/zephyr/bluetooth/mesh/cfg_cli.h index eefb0e86e73..b097bf89966 100644 --- a/include/zephyr/bluetooth/mesh/cfg_cli.h +++ b/include/zephyr/bluetooth/mesh/cfg_cli.h @@ -201,9 +201,10 @@ struct bt_mesh_cfg_cli { * * @param cli_data Pointer to a @ref bt_mesh_cfg_cli instance. */ -#define BT_MESH_MODEL_CFG_CLI(cli_data) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \ - cli_data, &bt_mesh_cfg_cli_cb) +#define BT_MESH_MODEL_CFG_CLI(cli_data) \ + BT_MESH_MODEL_CNT_CB(BT_MESH_MODEL_ID_CFG_CLI, \ + bt_mesh_cfg_cli_op, NULL, \ + cli_data, 1, 0, &bt_mesh_cfg_cli_cb) /** @brief Reset the target node and remove it from the network. * diff --git a/include/zephyr/bluetooth/mesh/cfg_srv.h b/include/zephyr/bluetooth/mesh/cfg_srv.h index 71abd7ac7b4..5a8b88b86ab 100644 --- a/include/zephyr/bluetooth/mesh/cfg_srv.h +++ b/include/zephyr/bluetooth/mesh/cfg_srv.h @@ -24,9 +24,10 @@ extern "C" { /** * @brief Generic Configuration Server model composition data entry. */ -#define BT_MESH_MODEL_CFG_SRV \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \ - NULL, &bt_mesh_cfg_srv_cb) +#define BT_MESH_MODEL_CFG_SRV \ + BT_MESH_MODEL_CNT_CB(BT_MESH_MODEL_ID_CFG_SRV, \ + bt_mesh_cfg_srv_op, NULL, \ + NULL, 1, 0, &bt_mesh_cfg_srv_cb) /** @cond INTERNAL_HIDDEN */ extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[]; diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index e1df0293bb0..123b89887e5 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -344,7 +344,7 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, k_work_init_delayable(&mod->pub->timer, mod_publish); } - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { + for (i = 0; i < mod->keys_cnt; i++) { mod->keys[i] = BT_MESH_KEY_UNUSED; } @@ -419,7 +419,7 @@ static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr) { int i; - for (i = 0; i < ARRAY_SIZE(mod->groups); i++) { + for (i = 0; i < mod->groups_cnt; i++) { if (mod->groups[i] == addr) { return &mod->groups[i]; } @@ -569,7 +569,7 @@ bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key) { int i; - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { + for (i = 0; i < mod->keys_cnt; i++) { if (mod->keys[i] == key || (mod->keys[i] == BT_MESH_KEY_DEV_ANY && BT_MESH_IS_DEV_KEY(key))) { @@ -899,7 +899,7 @@ static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd, int i; /* Start with empty array regardless of cleared or set value */ - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { + for (i = 0; i < mod->keys_cnt; i++) { mod->keys[i] = BT_MESH_KEY_UNUSED; } @@ -908,7 +908,7 @@ static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd, return 0; } - len = read_cb(cb_arg, mod->keys, sizeof(mod->keys)); + len = read_cb(cb_arg, mod->keys, mod->keys_cnt * sizeof(mod->keys[0])); if (len < 0) { BT_ERR("Failed to read value (err %zd)", len); return len; @@ -923,17 +923,18 @@ static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd, static int mod_set_sub(struct bt_mesh_model *mod, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { + size_t size = mod->groups_cnt * sizeof(mod->groups[0]); ssize_t len; /* Start with empty array regardless of cleared or set value */ - (void)memset(mod->groups, 0, sizeof(mod->groups)); + (void)memset(mod->groups, 0, size); if (len_rd == 0) { BT_DBG("Cleared subscriptions for model"); return 0; } - len = read_cb(cb_arg, mod->groups, sizeof(mod->groups)); + len = read_cb(cb_arg, mod->groups, size); if (len < 0) { BT_ERR("Failed to read value (err %zd)", len); return len; @@ -1100,7 +1101,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) char path[20]; int i, count, err; - for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) { + for (i = 0, count = 0; i < mod->keys_cnt; i++) { if (mod->keys[i] != BT_MESH_KEY_UNUSED) { keys[count++] = mod->keys[i]; BT_DBG("model key 0x%04x", mod->keys[i]); @@ -1128,7 +1129,7 @@ static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) char path[20]; int i, count, err; - for (i = 0, count = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++) { + for (i = 0, count = 0; i < mod->groups_cnt; i++) { if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { groups[count++] = mod->groups[i]; } @@ -1270,7 +1271,7 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, return; } - for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) { + for (int i = 0; i < mod->groups_cnt; i++) { if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { bt_mesh_lpn_group_add(mod->groups[i]); } diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index f961a275377..a0a081069f2 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -279,14 +279,14 @@ static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) return STATUS_INVALID_APPKEY; } - for (i = 0; i < ARRAY_SIZE(model->keys); i++) { + for (i = 0; i < model->keys_cnt; i++) { /* Treat existing binding as success */ if (model->keys[i] == key_idx) { return STATUS_SUCCESS; } } - for (i = 0; i < ARRAY_SIZE(model->keys); i++) { + for (i = 0; i < model->keys_cnt; i++) { if (model->keys[i] == BT_MESH_KEY_UNUSED) { model->keys[i] = key_idx; @@ -311,7 +311,7 @@ static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool st return STATUS_INVALID_APPKEY; } - for (i = 0; i < ARRAY_SIZE(model->keys); i++) { + for (i = 0; i < model->keys_cnt; i++) { if (model->keys[i] != key_idx) { continue; } @@ -874,7 +874,7 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) int i; /* Unref stored labels related to this model */ - for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) { + for (i = 0, clear_count = 0; i < mod->groups_cnt; i++) { if (!BT_MESH_ADDR_IS_VIRTUAL(mod->groups[i])) { if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { mod->groups[i] = BT_MESH_ADDR_UNASSIGNED; @@ -1156,7 +1156,7 @@ send_status: static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, void *user_data) { if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups)); + bt_mesh_lpn_group_del(mod->groups, mod->groups_cnt); } mod_sub_list_clear(mod); @@ -1212,7 +1212,7 @@ static int mod_sub_overwrite(struct bt_mesh_model *model, } - if (ARRAY_SIZE(mod->groups) > 0) { + if (mod->groups_cnt > 0) { bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); mod->groups[0] = sub_addr; @@ -1303,7 +1303,7 @@ static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, void *c return BT_MESH_WALK_CONTINUE; } - for (i = 0; i < ARRAY_SIZE(mod->groups); i++) { + for (i = 0; i < mod->groups_cnt; i++) { if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) { continue; } @@ -1637,7 +1637,7 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model, } - if (ARRAY_SIZE(mod->groups) > 0) { + if (mod->groups_cnt > 0) { status = bt_mesh_va_add(label_uuid, &sub_addr); if (status == STATUS_SUCCESS) { @@ -2061,7 +2061,7 @@ send_list: if (mod) { int i; - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { + for (i = 0; i < mod->keys_cnt; i++) { if (mod->keys[i] != BT_MESH_KEY_UNUSED) { net_buf_simple_add_le16(&msg, mod->keys[i]); }