Bluetooth: Mesh: Add model callback structure
Adds a structure of callbacks for each model instance. This allows for more flexible model implementations, that can interact with the Mesh stack without going through the application. For now, only an init callback is added, replacing the init mechanism in the foundation models. The init callback does not provide the primary flag that used to be in the foundation model callbacks, but replaces this with an inline function in access.h. Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
This commit is contained in:
parent
9608a8e64e
commit
c2c05c916a
11 changed files with 147 additions and 73 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue