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]); }