diff --git a/include/bluetooth/mesh/access.h b/include/bluetooth/mesh/access.h index 8ae18a7aa49..64f47dc6066 100644 --- a/include/bluetooth/mesh/access.h +++ b/include/bluetooth/mesh/access.h @@ -174,7 +174,18 @@ struct bt_mesh_model_op { /** Helper to define an empty model array */ #define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){}) -#define BT_MESH_MODEL(_id, _op, _pub, _user_data) \ + +/** @def BT_MESH_MODEL_CB + * + * @brief Composition data SIG model entry with callback functions. + * + * @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 _cb Callback structure, or NULL to keep no callbacks. + */ +#define BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, _cb) \ { \ .id = (_id), \ .op = _op, \ @@ -184,9 +195,21 @@ struct bt_mesh_model_op { .groups = { [0 ... (CONFIG_BT_MESH_MODEL_GROUP_COUNT - 1)] = \ BT_MESH_ADDR_UNASSIGNED }, \ .user_data = _user_data, \ + .cb = _cb, \ } -#define BT_MESH_MODEL_VND(_company, _id, _op, _pub, _user_data) \ +/** @def BT_MESH_MODEL_VND_CB + * + * @brief Composition data vendor model entry with callback functions. + * + * @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 _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), \ @@ -197,8 +220,35 @@ struct bt_mesh_model_op { .groups = { [0 ... (CONFIG_BT_MESH_MODEL_GROUP_COUNT - 1)] = \ BT_MESH_ADDR_UNASSIGNED }, \ .user_data = _user_data, \ + .cb = _cb, \ } + +/** @def BT_MESH_MODEL + * + * @brief Composition data SIG model entry. + * + * @param _id Model ID. + * @param _op Array of model opcode handlers. + * @param _pub Model publish parameters. + * @param _user_data User data for the model. + */ +#define BT_MESH_MODEL(_id, _op, _pub, _user_data) \ + BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, NULL) + +/** @def BT_MESH_MODEL_VND + * + * @brief Composition data vendor model entry. + * + * @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. + */ +#define BT_MESH_MODEL_VND(_company, _id, _op, _pub, _user_data) \ + BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, NULL) + /** @def BT_MESH_TRANSMIT * * @brief Encode transmission count & interval steps. @@ -330,6 +380,19 @@ struct bt_mesh_model_pub { .msg = &bt_mesh_pub_msg_##_name, \ } +/** Model callback functions. */ +struct bt_mesh_model_cb { + /** @brief Model init callback. + * + * Called on every model instance during mesh initialization. + * + * @param model Model to be initialized. + * + * @return 0 on success, error otherwise. + */ + int (*const init)(struct bt_mesh_model *model); +}; + /** Abstraction that describes a Mesh Model instance */ struct bt_mesh_model { union { @@ -356,6 +419,9 @@ struct bt_mesh_model { const struct bt_mesh_model_op * const op; + /* Model callback structure. */ + const struct bt_mesh_model_cb * const cb; + /* Model-specific user data */ void *user_data; }; @@ -438,6 +504,17 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, u16_t company, u16_t id); +/** @brief Get whether the model is in the primary element of the device. + * + * @param mod Mesh model. + * + * @return true if the model is on the primary element, false otherwise. + */ +static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod) +{ + return (mod->elem_idx == 0); +} + /** Node Composition */ struct bt_mesh_comp { u16_t cid; diff --git a/include/bluetooth/mesh/cfg_cli.h b/include/bluetooth/mesh/cfg_cli.h index 96e47e1e2e7..84fc7802dfb 100644 --- a/include/bluetooth/mesh/cfg_cli.h +++ b/include/bluetooth/mesh/cfg_cli.h @@ -31,10 +31,11 @@ struct bt_mesh_cfg_cli { }; extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[]; +extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb; -#define BT_MESH_MODEL_CFG_CLI(cli_data) \ - BT_MESH_MODEL(BT_MESH_MODEL_ID_CFG_CLI, \ - bt_mesh_cfg_cli_op, NULL, cli_data) +#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) int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page, u8_t *status, struct net_buf_simple *comp); diff --git a/include/bluetooth/mesh/cfg_srv.h b/include/bluetooth/mesh/cfg_srv.h index a28efdeafae..06b5d46b044 100644 --- a/include/bluetooth/mesh/cfg_srv.h +++ b/include/bluetooth/mesh/cfg_srv.h @@ -61,10 +61,11 @@ struct bt_mesh_cfg_srv { }; extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[]; +extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb; -#define BT_MESH_MODEL_CFG_SRV(srv_data) \ - BT_MESH_MODEL(BT_MESH_MODEL_ID_CFG_SRV, \ - bt_mesh_cfg_srv_op, NULL, srv_data) +#define BT_MESH_MODEL_CFG_SRV(srv_data) \ + BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \ + srv_data, &bt_mesh_cfg_srv_cb) #ifdef __cplusplus } diff --git a/include/bluetooth/mesh/health_cli.h b/include/bluetooth/mesh/health_cli.h index 8ebd8012b1d..80701abcb19 100644 --- a/include/bluetooth/mesh/health_cli.h +++ b/include/bluetooth/mesh/health_cli.h @@ -35,10 +35,11 @@ struct bt_mesh_health_cli { }; extern const struct bt_mesh_model_op bt_mesh_health_cli_op[]; +extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb; -#define BT_MESH_MODEL_HEALTH_CLI(cli_data) \ - BT_MESH_MODEL(BT_MESH_MODEL_ID_HEALTH_CLI, \ - bt_mesh_health_cli_op, NULL, cli_data) +#define BT_MESH_MODEL_HEALTH_CLI(cli_data) \ + BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_op, \ + NULL, cli_data, &bt_mesh_health_cli_cb) int bt_mesh_health_cli_set(struct bt_mesh_model *model); diff --git a/include/bluetooth/mesh/health_srv.h b/include/bluetooth/mesh/health_srv.h index 2215ae0f6fe..60b507f5960 100644 --- a/include/bluetooth/mesh/health_srv.h +++ b/include/bluetooth/mesh/health_srv.h @@ -70,6 +70,7 @@ struct bt_mesh_health_srv { int bt_mesh_fault_update(struct bt_mesh_elem *elem); extern const struct bt_mesh_model_op bt_mesh_health_srv_op[]; +extern const struct bt_mesh_model_cb bt_mesh_health_srv_cb; /** @def BT_MESH_MODEL_HEALTH_SRV * @@ -83,9 +84,9 @@ extern const struct bt_mesh_model_op bt_mesh_health_srv_op[]; * * @return New mesh model instance. */ -#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \ - BT_MESH_MODEL(BT_MESH_MODEL_ID_HEALTH_SRV, \ - bt_mesh_health_srv_op, pub, srv) +#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \ + BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_op, \ + pub, srv, &bt_mesh_health_srv_cb) #ifdef __cplusplus } diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index cfcf9858603..902c6cdc784 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -30,20 +30,6 @@ static const struct bt_mesh_comp *dev_comp; static u16_t dev_primary_addr; -static const struct { - const u16_t id; - int (*const init)(struct bt_mesh_model *model, bool primary); -} model_init[] = { - { BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_init }, - { BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_init }, -#if defined(CONFIG_BT_MESH_CFG_CLI) - { BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_init }, -#endif -#if defined(CONFIG_BT_MESH_HEALTH_CLI) - { BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_init }, -#endif -}; - void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, @@ -302,14 +288,8 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, mod->mod_idx = mod - elem->models; } - if (vnd) { - return; - } - - for (i = 0; i < ARRAY_SIZE(model_init); i++) { - if (model_init[i].id == mod->id) { - model_init[i].init(mod, primary); - } + if (mod->cb && mod->cb->init) { + mod->cb->init(mod); } } diff --git a/subsys/bluetooth/mesh/cfg_cli.c b/subsys/bluetooth/mesh/cfg_cli.c index a6414a39429..fd1a8fdaf70 100644 --- a/subsys/bluetooth/mesh/cfg_cli.c +++ b/subsys/bluetooth/mesh/cfg_cli.c @@ -487,6 +487,33 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { BT_MESH_MODEL_OP_END, }; +static int cfg_cli_init(struct bt_mesh_model *model) +{ + if (!bt_mesh_model_in_primary(model)) { + BT_ERR("Configuration Client only allowed in primary element"); + return -EINVAL; + } + + if (!model->user_data) { + BT_ERR("No Configuration Client context provided"); + return -EINVAL; + } + + cli = model->user_data; + cli->model = model; + + /* Configuration Model security is device-key based */ + model->keys[0] = BT_MESH_KEY_DEV; + + k_sem_init(&cli->op_sync, 0, 1); + + return 0; +} + +const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = { + .init = cfg_cli_init, +}; + static int cli_prepare(void *param, u32_t op) { if (!cli) { @@ -1417,28 +1444,3 @@ void bt_mesh_cfg_cli_timeout_set(s32_t timeout) { msg_timeout = timeout; } - -int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary) -{ - BT_DBG("primary %u", primary); - - if (!primary) { - BT_ERR("Configuration Client only allowed in primary element"); - return -EINVAL; - } - - if (!model->user_data) { - BT_ERR("No Configuration Client context provided"); - return -EINVAL; - } - - cli = model->user_data; - cli->model = model; - - /* Configuration Model security is device-key based */ - model->keys[0] = BT_MESH_KEY_DEV; - - k_sem_init(&cli->op_sync, 0, 1); - - return 0; -} diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index ce0b3b06b1b..7a002a4213a 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -3233,10 +3233,15 @@ static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg) return true; } -int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary) +static int cfg_srv_init(struct bt_mesh_model *model) { struct bt_mesh_cfg_srv *cfg = model->user_data; + if (!bt_mesh_model_in_primary(model)) { + BT_ERR("Configuration Server only allowed in primary element"); + return -EINVAL; + } + if (!cfg) { BT_ERR("No Configuration Server context provided"); return -EINVAL; @@ -3273,6 +3278,10 @@ int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary) return 0; } +const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb = { + .init = cfg_srv_init, +}; + static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { diff --git a/subsys/bluetooth/mesh/foundation.h b/subsys/bluetooth/mesh/foundation.h index 000087dd6e7..25c24c0685d 100644 --- a/subsys/bluetooth/mesh/foundation.h +++ b/subsys/bluetooth/mesh/foundation.h @@ -112,12 +112,6 @@ #define STATUS_UNSPECIFIED 0x10 #define STATUS_INVALID_BINDING 0x11 -int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary); -int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary); - -int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary); -int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary); - void bt_mesh_cfg_reset(void); void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat); diff --git a/subsys/bluetooth/mesh/health_cli.c b/subsys/bluetooth/mesh/health_cli.c index d286231dd76..1ac5d06a287 100644 --- a/subsys/bluetooth/mesh/health_cli.c +++ b/subsys/bluetooth/mesh/health_cli.c @@ -510,11 +510,11 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model) return 0; } -int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary) +static int health_cli_init(struct bt_mesh_model *model) { struct bt_mesh_health_cli *cli = model->user_data; - BT_DBG("primary %u", primary); + BT_DBG("primary %u", bt_mesh_model_in_primary(model)); if (!cli) { BT_ERR("No Health Client context provided"); @@ -533,3 +533,7 @@ int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary) return 0; } + +const struct bt_mesh_model_cb bt_mesh_health_cli_cb = { + .init = health_cli_init, +}; diff --git a/subsys/bluetooth/mesh/health_srv.c b/subsys/bluetooth/mesh/health_srv.c index 93e5888b54b..91767977a04 100644 --- a/subsys/bluetooth/mesh/health_srv.c +++ b/subsys/bluetooth/mesh/health_srv.c @@ -384,12 +384,12 @@ static void attention_off(struct k_work *work) } } -int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary) +static int health_srv_init(struct bt_mesh_model *model) { struct bt_mesh_health_srv *srv = model->user_data; if (!srv) { - if (!primary) { + if (!bt_mesh_model_in_primary(model)) { return 0; } @@ -408,13 +408,17 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary) srv->model = model; - if (primary) { + if (bt_mesh_model_in_primary(model)) { health_srv = srv; } return 0; } +const struct bt_mesh_model_cb bt_mesh_health_srv_cb = { + .init = health_srv_init, +}; + void bt_mesh_attention(struct bt_mesh_model *model, u8_t time) { struct bt_mesh_health_srv *srv;