Make it possible to provision devices over advertising bearer (PB-ADV). Many messages in the provisioning protocol are the same for provisioner and device so much of the code could be reused by only changing when they are expected to arrive. This introduces to concept of local and remote device keys. The models for cfg_cli and cfg_srv have been updated to reflect this concept. Both the send and receive path in the transport layer have been updated to support encrypting/decrypting with local and remote device keys. When a node has been provisioned it is stored in bt_mesh_net.nodes. If CONFIG_BT_SETTINGS is enabled, they are also saved to settings. If the callback node_added in bt_mesh_prov has been set, it will be called for every node that gets provisioned. This includes when they are retrieved from settings. The configuration CONFIG_BT_MESH_NODE_COUNT controls how many nodes that can be provisioned. Signed-off-by: Tobias Svehagen <tobias.svehagen@gmail.com>
1452 lines
33 KiB
C
1452 lines
33 KiB
C
/* Bluetooth Mesh */
|
|
|
|
/*
|
|
* Copyright (c) 2017 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <zephyr/types.h>
|
|
#include <sys/util.h>
|
|
#include <sys/byteorder.h>
|
|
|
|
#include <bluetooth/bluetooth.h>
|
|
#include <bluetooth/conn.h>
|
|
#include <bluetooth/mesh.h>
|
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
|
|
#define LOG_MODULE_NAME bt_mesh_cfg_cli
|
|
#include "common/log.h"
|
|
|
|
#include "net.h"
|
|
#include "foundation.h"
|
|
|
|
#define CID_NVAL 0xffff
|
|
|
|
/* 2 byte dummy opcode for getting compile time buffer sizes. */
|
|
#define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff)
|
|
|
|
struct comp_data {
|
|
u8_t *status;
|
|
struct net_buf_simple *comp;
|
|
};
|
|
|
|
static s32_t msg_timeout = K_SECONDS(2);
|
|
|
|
static struct bt_mesh_cfg_cli *cli;
|
|
|
|
static void comp_data_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct comp_data *param;
|
|
size_t to_copy;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_DEV_COMP_DATA_STATUS) {
|
|
BT_WARN("Unexpected Composition Data Status");
|
|
return;
|
|
}
|
|
|
|
param = cli->op_param;
|
|
|
|
*(param->status) = net_buf_simple_pull_u8(buf);
|
|
to_copy = MIN(net_buf_simple_tailroom(param->comp), buf->len);
|
|
net_buf_simple_add_mem(param->comp, buf->data, to_copy);
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
static void state_status_u8(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf,
|
|
u32_t expect_status)
|
|
{
|
|
u8_t *status;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != expect_status) {
|
|
BT_WARN("Unexpected Status (0x%08x != 0x%08x)",
|
|
cli->op_pending, expect_status);
|
|
return;
|
|
}
|
|
|
|
status = cli->op_param;
|
|
*status = net_buf_simple_pull_u8(buf);
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
static void beacon_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
state_status_u8(model, ctx, buf, OP_BEACON_STATUS);
|
|
}
|
|
|
|
static void ttl_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
state_status_u8(model, ctx, buf, OP_DEFAULT_TTL_STATUS);
|
|
}
|
|
|
|
static void friend_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
state_status_u8(model, ctx, buf, OP_FRIEND_STATUS);
|
|
}
|
|
|
|
static void gatt_proxy_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
state_status_u8(model, ctx, buf, OP_GATT_PROXY_STATUS);
|
|
}
|
|
|
|
struct relay_param {
|
|
u8_t *status;
|
|
u8_t *transmit;
|
|
};
|
|
|
|
static void relay_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct relay_param *param;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_RELAY_STATUS) {
|
|
BT_WARN("Unexpected Relay Status message");
|
|
return;
|
|
}
|
|
|
|
param = cli->op_param;
|
|
*param->status = net_buf_simple_pull_u8(buf);
|
|
*param->transmit = net_buf_simple_pull_u8(buf);
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct net_key_param {
|
|
u8_t *status;
|
|
u16_t net_idx;
|
|
};
|
|
|
|
static void net_key_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct net_key_param *param;
|
|
u16_t net_idx, app_idx;
|
|
u8_t status;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_NET_KEY_STATUS) {
|
|
BT_WARN("Unexpected Net Key Status message");
|
|
return;
|
|
}
|
|
|
|
status = net_buf_simple_pull_u8(buf);
|
|
key_idx_unpack(buf, &net_idx, &app_idx);
|
|
|
|
param = cli->op_param;
|
|
if (param->net_idx != net_idx) {
|
|
BT_WARN("Net Key Status key index does not match");
|
|
return;
|
|
}
|
|
|
|
if (param->status) {
|
|
*param->status = status;
|
|
}
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct app_key_param {
|
|
u8_t *status;
|
|
u16_t net_idx;
|
|
u16_t app_idx;
|
|
};
|
|
|
|
static void app_key_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct app_key_param *param;
|
|
u16_t net_idx, app_idx;
|
|
u8_t status;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_APP_KEY_STATUS) {
|
|
BT_WARN("Unexpected App Key Status message");
|
|
return;
|
|
}
|
|
|
|
status = net_buf_simple_pull_u8(buf);
|
|
key_idx_unpack(buf, &net_idx, &app_idx);
|
|
|
|
param = cli->op_param;
|
|
if (param->net_idx != net_idx || param->app_idx != app_idx) {
|
|
BT_WARN("App Key Status key indices did not match");
|
|
return;
|
|
}
|
|
|
|
if (param->status) {
|
|
*param->status = status;
|
|
}
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct mod_app_param {
|
|
u8_t *status;
|
|
u16_t elem_addr;
|
|
u16_t mod_app_idx;
|
|
u16_t mod_id;
|
|
u16_t cid;
|
|
};
|
|
|
|
static void mod_app_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
u16_t elem_addr, mod_app_idx, mod_id, cid;
|
|
struct mod_app_param *param;
|
|
u8_t status;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_MOD_APP_STATUS) {
|
|
BT_WARN("Unexpected Model App Status message");
|
|
return;
|
|
}
|
|
|
|
status = net_buf_simple_pull_u8(buf);
|
|
elem_addr = net_buf_simple_pull_le16(buf);
|
|
mod_app_idx = net_buf_simple_pull_le16(buf);
|
|
|
|
if (buf->len >= 4U) {
|
|
cid = net_buf_simple_pull_le16(buf);
|
|
} else {
|
|
cid = CID_NVAL;
|
|
}
|
|
|
|
mod_id = net_buf_simple_pull_le16(buf);
|
|
|
|
param = cli->op_param;
|
|
if (param->elem_addr != elem_addr ||
|
|
param->mod_app_idx != mod_app_idx || param->mod_id != mod_id ||
|
|
param->cid != cid) {
|
|
BT_WARN("Model App Status parameters did not match");
|
|
return;
|
|
}
|
|
|
|
if (param->status) {
|
|
*param->status = status;
|
|
}
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct mod_pub_param {
|
|
u16_t mod_id;
|
|
u16_t cid;
|
|
u16_t elem_addr;
|
|
u8_t *status;
|
|
struct bt_mesh_cfg_mod_pub *pub;
|
|
};
|
|
|
|
static void mod_pub_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
u16_t mod_id, cid, elem_addr;
|
|
struct mod_pub_param *param;
|
|
u8_t status;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_MOD_PUB_STATUS) {
|
|
BT_WARN("Unexpected Model Pub Status message");
|
|
return;
|
|
}
|
|
|
|
param = cli->op_param;
|
|
if (param->cid != CID_NVAL) {
|
|
if (buf->len < 14) {
|
|
BT_WARN("Unexpected Mod Pub Status with SIG Model");
|
|
return;
|
|
}
|
|
|
|
cid = sys_get_le16(&buf->data[10]);
|
|
mod_id = sys_get_le16(&buf->data[12]);
|
|
} else {
|
|
if (buf->len > 12) {
|
|
BT_WARN("Unexpected Mod Pub Status with Vendor Model");
|
|
return;
|
|
}
|
|
|
|
cid = CID_NVAL;
|
|
mod_id = sys_get_le16(&buf->data[10]);
|
|
}
|
|
|
|
if (mod_id != param->mod_id || cid != param->cid) {
|
|
BT_WARN("Mod Pub Model ID or Company ID mismatch");
|
|
return;
|
|
}
|
|
|
|
status = net_buf_simple_pull_u8(buf);
|
|
|
|
elem_addr = net_buf_simple_pull_le16(buf);
|
|
if (elem_addr != param->elem_addr) {
|
|
BT_WARN("Model Pub Status for unexpected element (0x%04x)",
|
|
elem_addr);
|
|
return;
|
|
}
|
|
|
|
if (param->status) {
|
|
*param->status = status;
|
|
}
|
|
|
|
if (param->pub) {
|
|
param->pub->addr = net_buf_simple_pull_le16(buf);
|
|
param->pub->app_idx = net_buf_simple_pull_le16(buf);
|
|
param->pub->cred_flag = (param->pub->app_idx & BIT(12));
|
|
param->pub->app_idx &= BIT_MASK(12);
|
|
param->pub->ttl = net_buf_simple_pull_u8(buf);
|
|
param->pub->period = net_buf_simple_pull_u8(buf);
|
|
param->pub->transmit = net_buf_simple_pull_u8(buf);
|
|
}
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct mod_sub_param {
|
|
u8_t *status;
|
|
u16_t elem_addr;
|
|
u16_t *sub_addr;
|
|
u16_t *expect_sub;
|
|
u16_t mod_id;
|
|
u16_t cid;
|
|
};
|
|
|
|
static void mod_sub_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
u16_t elem_addr, sub_addr, mod_id, cid;
|
|
struct mod_sub_param *param;
|
|
u8_t status;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_MOD_SUB_STATUS) {
|
|
BT_WARN("Unexpected Model Subscription Status message");
|
|
return;
|
|
}
|
|
|
|
status = net_buf_simple_pull_u8(buf);
|
|
elem_addr = net_buf_simple_pull_le16(buf);
|
|
sub_addr = net_buf_simple_pull_le16(buf);
|
|
|
|
if (buf->len >= 4U) {
|
|
cid = net_buf_simple_pull_le16(buf);
|
|
} else {
|
|
cid = CID_NVAL;
|
|
}
|
|
|
|
mod_id = net_buf_simple_pull_le16(buf);
|
|
|
|
param = cli->op_param;
|
|
if (param->elem_addr != elem_addr || param->mod_id != mod_id ||
|
|
(param->expect_sub && *param->expect_sub != sub_addr) ||
|
|
param->cid != cid) {
|
|
BT_WARN("Model Subscription Status parameters did not match");
|
|
return;
|
|
}
|
|
|
|
if (param->sub_addr) {
|
|
*param->sub_addr = sub_addr;
|
|
}
|
|
|
|
if (param->status) {
|
|
*param->status = status;
|
|
}
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct hb_sub_param {
|
|
u8_t *status;
|
|
struct bt_mesh_cfg_hb_sub *sub;
|
|
};
|
|
|
|
static void hb_sub_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct hb_sub_param *param;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_HEARTBEAT_SUB_STATUS) {
|
|
BT_WARN("Unexpected Heartbeat Subscription Status message");
|
|
return;
|
|
}
|
|
|
|
param = cli->op_param;
|
|
|
|
*param->status = net_buf_simple_pull_u8(buf);
|
|
|
|
param->sub->src = net_buf_simple_pull_le16(buf);
|
|
param->sub->dst = net_buf_simple_pull_le16(buf);
|
|
param->sub->period = net_buf_simple_pull_u8(buf);
|
|
param->sub->count = net_buf_simple_pull_u8(buf);
|
|
param->sub->min = net_buf_simple_pull_u8(buf);
|
|
param->sub->max = net_buf_simple_pull_u8(buf);
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
struct hb_pub_param {
|
|
u8_t *status;
|
|
struct bt_mesh_cfg_hb_pub *pub;
|
|
};
|
|
|
|
static void hb_pub_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct hb_pub_param *param;
|
|
|
|
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
|
bt_hex(buf->data, buf->len));
|
|
|
|
if (cli->op_pending != OP_HEARTBEAT_PUB_STATUS) {
|
|
BT_WARN("Unexpected Heartbeat Publication Status message");
|
|
return;
|
|
}
|
|
|
|
param = cli->op_param;
|
|
|
|
*param->status = net_buf_simple_pull_u8(buf);
|
|
|
|
if (param->pub) {
|
|
param->pub->dst = net_buf_simple_pull_le16(buf);
|
|
param->pub->count = net_buf_simple_pull_u8(buf);
|
|
param->pub->period = net_buf_simple_pull_u8(buf);
|
|
param->pub->ttl = net_buf_simple_pull_u8(buf);
|
|
param->pub->feat = net_buf_simple_pull_u8(buf);
|
|
param->pub->net_idx = net_buf_simple_pull_u8(buf);
|
|
}
|
|
|
|
k_sem_give(&cli->op_sync);
|
|
}
|
|
|
|
const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
|
|
{ OP_DEV_COMP_DATA_STATUS, 15, comp_data_status },
|
|
{ OP_BEACON_STATUS, 1, beacon_status },
|
|
{ OP_DEFAULT_TTL_STATUS, 1, ttl_status },
|
|
{ OP_FRIEND_STATUS, 1, friend_status },
|
|
{ OP_GATT_PROXY_STATUS, 1, gatt_proxy_status },
|
|
{ OP_RELAY_STATUS, 2, relay_status },
|
|
{ OP_NET_KEY_STATUS, 3, net_key_status },
|
|
{ OP_APP_KEY_STATUS, 4, app_key_status },
|
|
{ OP_MOD_APP_STATUS, 7, mod_app_status },
|
|
{ OP_MOD_PUB_STATUS, 12, mod_pub_status },
|
|
{ OP_MOD_SUB_STATUS, 7, mod_sub_status },
|
|
{ OP_HEARTBEAT_SUB_STATUS, 9, hb_sub_status },
|
|
{ OP_HEARTBEAT_PUB_STATUS, 10, hb_pub_status },
|
|
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 and both the local
|
|
* and remote keys are allowed to access this model.
|
|
*/
|
|
model->keys[0] = BT_MESH_KEY_DEV_ANY;
|
|
|
|
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) {
|
|
BT_ERR("No available Configuration Client context!");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (cli->op_pending) {
|
|
BT_WARN("Another synchronous operation pending");
|
|
return -EBUSY;
|
|
}
|
|
|
|
cli->op_param = param;
|
|
cli->op_pending = op;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cli_reset(void)
|
|
{
|
|
cli->op_pending = 0U;
|
|
cli->op_param = NULL;
|
|
}
|
|
|
|
static int cli_wait(void)
|
|
{
|
|
int err;
|
|
|
|
err = k_sem_take(&cli->op_sync, msg_timeout);
|
|
|
|
cli_reset();
|
|
|
|
return err;
|
|
}
|
|
|
|
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)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_DEV_COMP_DATA_GET, 1);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct comp_data param = {
|
|
.status = status,
|
|
.comp = comp,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_DEV_COMP_DATA_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_DEV_COMP_DATA_GET);
|
|
net_buf_simple_add_u8(&msg, page);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
static int get_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
|
|
u8_t *val)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 0);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(val, rsp);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, op);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
static int set_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
|
|
u8_t new_val, u8_t *val)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 1);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(val, rsp);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, op);
|
|
net_buf_simple_add_u8(&msg, new_val);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status)
|
|
{
|
|
return get_state_u8(net_idx, addr, OP_BEACON_GET, OP_BEACON_STATUS,
|
|
status);
|
|
}
|
|
|
|
int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
|
|
{
|
|
return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS,
|
|
val, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl)
|
|
{
|
|
return get_state_u8(net_idx, addr, OP_DEFAULT_TTL_GET,
|
|
OP_DEFAULT_TTL_STATUS, ttl);
|
|
}
|
|
|
|
int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl)
|
|
{
|
|
return set_state_u8(net_idx, addr, OP_DEFAULT_TTL_SET,
|
|
OP_DEFAULT_TTL_STATUS, val, ttl);
|
|
}
|
|
|
|
int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status)
|
|
{
|
|
return get_state_u8(net_idx, addr, OP_FRIEND_GET,
|
|
OP_FRIEND_STATUS, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
|
|
{
|
|
return set_state_u8(net_idx, addr, OP_FRIEND_SET, OP_FRIEND_STATUS,
|
|
val, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status)
|
|
{
|
|
return get_state_u8(net_idx, addr, OP_GATT_PROXY_GET,
|
|
OP_GATT_PROXY_STATUS, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
|
|
u8_t *status)
|
|
{
|
|
return set_state_u8(net_idx, addr, OP_GATT_PROXY_SET,
|
|
OP_GATT_PROXY_STATUS, val, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
|
|
u8_t *transmit)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_GET, 0);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct relay_param param = {
|
|
.status = status,
|
|
.transmit = transmit,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_RELAY_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_RELAY_GET);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
|
|
u8_t new_transmit, u8_t *status, u8_t *transmit)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_SET, 2);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct relay_param param = {
|
|
.status = status,
|
|
.transmit = transmit,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_RELAY_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_RELAY_SET);
|
|
net_buf_simple_add_u8(&msg, new_relay);
|
|
net_buf_simple_add_u8(&msg, new_transmit);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
|
const u8_t net_key[16], u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_ADD, 18);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct net_key_param param = {
|
|
.status = status,
|
|
.net_idx = key_net_idx,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_NET_KEY_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_NET_KEY_ADD);
|
|
net_buf_simple_add_le16(&msg, key_net_idx);
|
|
net_buf_simple_add_mem(&msg, net_key, 16);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
|
u16_t key_app_idx, const u8_t app_key[16],
|
|
u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_ADD, 19);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct app_key_param param = {
|
|
.status = status,
|
|
.net_idx = key_net_idx,
|
|
.app_idx = key_app_idx,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_APP_KEY_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_APP_KEY_ADD);
|
|
key_idx_pack(&msg, key_net_idx, key_app_idx);
|
|
net_buf_simple_add_mem(&msg, app_key, 16);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
static int mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_app_idx, u16_t mod_id, u16_t cid,
|
|
u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_BIND, 8);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct mod_app_param param = {
|
|
.status = status,
|
|
.elem_addr = elem_addr,
|
|
.mod_app_idx = mod_app_idx,
|
|
.mod_id = mod_id,
|
|
.cid = cid,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_MOD_APP_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_MOD_APP_BIND);
|
|
net_buf_simple_add_le16(&msg, elem_addr);
|
|
net_buf_simple_add_le16(&msg, mod_app_idx);
|
|
|
|
if (cid != CID_NVAL) {
|
|
net_buf_simple_add_le16(&msg, cid);
|
|
}
|
|
|
|
net_buf_simple_add_le16(&msg, mod_id);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_app_idx, u16_t mod_id, u8_t *status)
|
|
{
|
|
return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
|
|
CID_NVAL, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_app_idx, u16_t mod_id, u16_t cid,
|
|
u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id, cid,
|
|
status);
|
|
}
|
|
|
|
static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t sub_addr, u16_t mod_id, u16_t cid, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 8);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct mod_sub_param param = {
|
|
.status = status,
|
|
.elem_addr = elem_addr,
|
|
.expect_sub = &sub_addr,
|
|
.mod_id = mod_id,
|
|
.cid = cid,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_MOD_SUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, op);
|
|
net_buf_simple_add_le16(&msg, elem_addr);
|
|
net_buf_simple_add_le16(&msg, sub_addr);
|
|
|
|
if (cid != CID_NVAL) {
|
|
net_buf_simple_add_le16(&msg, cid);
|
|
}
|
|
|
|
net_buf_simple_add_le16(&msg, mod_id);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t sub_addr, u16_t mod_id, u8_t *status)
|
|
{
|
|
return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
|
|
mod_id, CID_NVAL, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t sub_addr, u16_t mod_id, u16_t cid,
|
|
u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
|
|
mod_id, cid, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t sub_addr, u16_t mod_id, u8_t *status)
|
|
{
|
|
return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
|
|
mod_id, CID_NVAL, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t sub_addr, u16_t mod_id, u16_t cid,
|
|
u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
|
|
mod_id, cid, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t sub_addr, u16_t mod_id, u8_t *status)
|
|
{
|
|
return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
|
|
sub_addr, mod_id, CID_NVAL, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
|
|
u16_t elem_addr, u16_t sub_addr,
|
|
u16_t mod_id, u16_t cid, u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
|
|
sub_addr, mod_id, cid, status);
|
|
}
|
|
|
|
static int mod_sub_va(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
const u8_t label[16], u16_t mod_id, u16_t cid,
|
|
u16_t *virt_addr, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 22);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct mod_sub_param param = {
|
|
.status = status,
|
|
.elem_addr = elem_addr,
|
|
.sub_addr = virt_addr,
|
|
.mod_id = mod_id,
|
|
.cid = cid,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_MOD_SUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x label %s",
|
|
net_idx, addr, elem_addr, label);
|
|
BT_DBG("mod_id 0x%04x cid 0x%04x", mod_id, cid);
|
|
|
|
bt_mesh_model_msg_init(&msg, op);
|
|
net_buf_simple_add_le16(&msg, elem_addr);
|
|
net_buf_simple_add_mem(&msg, label, 16);
|
|
|
|
if (cid != CID_NVAL) {
|
|
net_buf_simple_add_le16(&msg, cid);
|
|
}
|
|
|
|
net_buf_simple_add_le16(&msg, mod_id);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
const u8_t label[16], u16_t mod_id,
|
|
u16_t *virt_addr, u8_t *status)
|
|
{
|
|
return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
|
|
mod_id, CID_NVAL, virt_addr, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
const u8_t label[16], u16_t mod_id,
|
|
u16_t cid, u16_t *virt_addr, u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
|
|
mod_id, cid, virt_addr, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
const u8_t label[16], u16_t mod_id,
|
|
u16_t *virt_addr, u8_t *status)
|
|
{
|
|
return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
|
|
mod_id, CID_NVAL, virt_addr, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
const u8_t label[16], u16_t mod_id,
|
|
u16_t cid, u16_t *virt_addr, u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
|
|
mod_id, cid, virt_addr, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
|
|
u16_t elem_addr, const u8_t label[16],
|
|
u16_t mod_id, u16_t *virt_addr,
|
|
u8_t *status)
|
|
{
|
|
return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
|
|
label, mod_id, CID_NVAL, virt_addr, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
|
|
u16_t elem_addr, const u8_t label[16],
|
|
u16_t mod_id, u16_t cid,
|
|
u16_t *virt_addr, u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
|
|
label, mod_id, cid, virt_addr, status);
|
|
}
|
|
|
|
static int mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_id, u16_t cid,
|
|
struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_GET, 6);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct mod_pub_param param = {
|
|
.mod_id = mod_id,
|
|
.cid = cid,
|
|
.elem_addr = elem_addr,
|
|
.status = status,
|
|
.pub = pub,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_MOD_PUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_MOD_PUB_GET);
|
|
|
|
net_buf_simple_add_le16(&msg, elem_addr);
|
|
|
|
if (cid != CID_NVAL) {
|
|
net_buf_simple_add_le16(&msg, cid);
|
|
}
|
|
|
|
net_buf_simple_add_le16(&msg, mod_id);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
|
u8_t *status)
|
|
{
|
|
return mod_pub_get(net_idx, addr, elem_addr, mod_id, CID_NVAL,
|
|
pub, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_id, u16_t cid,
|
|
struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status);
|
|
}
|
|
|
|
static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_id, u16_t cid,
|
|
struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_SET, 13);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct mod_pub_param param = {
|
|
.mod_id = mod_id,
|
|
.cid = cid,
|
|
.elem_addr = elem_addr,
|
|
.status = status,
|
|
.pub = pub,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_MOD_PUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_MOD_PUB_SET);
|
|
|
|
net_buf_simple_add_le16(&msg, elem_addr);
|
|
net_buf_simple_add_le16(&msg, pub->addr);
|
|
net_buf_simple_add_le16(&msg, (pub->app_idx & (pub->cred_flag << 12)));
|
|
net_buf_simple_add_u8(&msg, pub->ttl);
|
|
net_buf_simple_add_u8(&msg, pub->period);
|
|
net_buf_simple_add_u8(&msg, pub->transmit);
|
|
|
|
if (cid != CID_NVAL) {
|
|
net_buf_simple_add_le16(&msg, cid);
|
|
}
|
|
|
|
net_buf_simple_add_le16(&msg, mod_id);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
|
u8_t *status)
|
|
{
|
|
return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL,
|
|
pub, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|
u16_t mod_id, u16_t cid,
|
|
struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
|
|
{
|
|
if (cid == CID_NVAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status);
|
|
}
|
|
|
|
int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
|
|
struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_SET, 5);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct hb_sub_param param = {
|
|
.status = status,
|
|
.sub = sub,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_SUB_SET);
|
|
net_buf_simple_add_le16(&msg, sub->src);
|
|
net_buf_simple_add_le16(&msg, sub->dst);
|
|
net_buf_simple_add_u8(&msg, sub->period);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
|
|
struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_GET, 0);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct hb_sub_param param = {
|
|
.status = status,
|
|
.sub = sub,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_SUB_GET);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
|
|
const struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_SET, 9);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct hb_pub_param param = {
|
|
.status = status,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_SET);
|
|
net_buf_simple_add_le16(&msg, pub->dst);
|
|
net_buf_simple_add_u8(&msg, pub->count);
|
|
net_buf_simple_add_u8(&msg, pub->period);
|
|
net_buf_simple_add_u8(&msg, pub->ttl);
|
|
net_buf_simple_add_le16(&msg, pub->feat);
|
|
net_buf_simple_add_le16(&msg, pub->net_idx);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
|
|
struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_GET, 0);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
|
.addr = addr,
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct hb_pub_param param = {
|
|
.status = status,
|
|
.pub = pub,
|
|
};
|
|
int err;
|
|
|
|
err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_GET);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
BT_ERR("model_send() failed (err %d)", err);
|
|
cli_reset();
|
|
return err;
|
|
}
|
|
|
|
if (!status) {
|
|
cli_reset();
|
|
return 0;
|
|
}
|
|
|
|
return cli_wait();
|
|
}
|
|
|
|
s32_t bt_mesh_cfg_cli_timeout_get(void)
|
|
{
|
|
return msg_timeout;
|
|
}
|
|
|
|
void bt_mesh_cfg_cli_timeout_set(s32_t timeout)
|
|
{
|
|
msg_timeout = timeout;
|
|
}
|