Referring to MshDFU_v1.0 Sections 6.1.1, 6.2.1 and 7.1.1 model descriptions: DFU/DFD server/clients extend BLOB Transfer root models and DFD server requires Firmware Update Client on the same element. For this reason we need to make sure that those main models or root models exist on the same element. And also firmware update client can not be forced to be in the first element. For all model extention call return the error code in case of an error. Signed-off-by: alperen sener <alperen.sener@nordicsemi.no>
273 lines
6.9 KiB
C
273 lines
6.9 KiB
C
/*
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <zephyr/bluetooth/mesh.h>
|
|
#include "net.h"
|
|
#include <zephyr/bluetooth/conn.h>
|
|
#include "proxy.h"
|
|
#include "foundation.h"
|
|
#include "beacon.h"
|
|
#include "cfg.h"
|
|
#include "settings.h"
|
|
|
|
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(bt_mesh_priv_beacon_srv);
|
|
|
|
static const struct bt_mesh_model *priv_beacon_srv;
|
|
|
|
/* Private Beacon configuration server model states */
|
|
struct {
|
|
uint8_t state;
|
|
uint8_t interval;
|
|
uint8_t proxy_state;
|
|
} priv_beacon_state;
|
|
|
|
static int priv_beacon_store(bool delete)
|
|
{
|
|
if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
|
return 0;
|
|
}
|
|
|
|
const void *data = delete ? NULL : &priv_beacon_state;
|
|
size_t len = delete ? 0 : sizeof(priv_beacon_state);
|
|
|
|
return bt_mesh_model_data_store(priv_beacon_srv, false, "pb", data, len);
|
|
}
|
|
|
|
static int beacon_status_rsp(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_BEACON_STATUS, 2);
|
|
bt_mesh_model_msg_init(&buf, OP_PRIV_BEACON_STATUS);
|
|
|
|
net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_get());
|
|
net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_update_interval_get());
|
|
|
|
bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int handle_beacon_get(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
LOG_DBG("");
|
|
|
|
beacon_status_rsp(mod, ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int handle_beacon_set(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
uint8_t beacon;
|
|
|
|
if (buf->len > 2U) {
|
|
return -EMSGSIZE;
|
|
}
|
|
|
|
beacon = net_buf_simple_pull_u8(buf);
|
|
if (beacon != BT_MESH_BEACON_DISABLED &&
|
|
beacon != BT_MESH_BEACON_ENABLED) {
|
|
LOG_WRN("Invalid beacon value %u", beacon);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (buf->len == 1U) {
|
|
bt_mesh_priv_beacon_update_interval_set(net_buf_simple_pull_u8(buf));
|
|
}
|
|
|
|
(void)bt_mesh_priv_beacon_set(beacon);
|
|
beacon_status_rsp(mod, ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void gatt_proxy_status_rsp(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_GATT_PROXY_STATUS, 1);
|
|
bt_mesh_model_msg_init(&buf, OP_PRIV_GATT_PROXY_STATUS);
|
|
|
|
net_buf_simple_add_u8(&buf, bt_mesh_priv_gatt_proxy_get());
|
|
|
|
bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
|
|
}
|
|
|
|
static int handle_gatt_proxy_get(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
LOG_DBG("");
|
|
|
|
gatt_proxy_status_rsp(mod, ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int handle_gatt_proxy_set(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
uint8_t gatt_proxy;
|
|
|
|
gatt_proxy = net_buf_simple_pull_u8(buf);
|
|
if (gatt_proxy != BT_MESH_GATT_PROXY_DISABLED &&
|
|
gatt_proxy != BT_MESH_GATT_PROXY_ENABLED) {
|
|
LOG_WRN("Invalid GATT proxy value %u", gatt_proxy);
|
|
return -EINVAL;
|
|
}
|
|
|
|
LOG_DBG("%u", gatt_proxy);
|
|
|
|
bt_mesh_priv_gatt_proxy_set(gatt_proxy);
|
|
|
|
gatt_proxy_status_rsp(mod, ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void node_id_status_rsp(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx, uint8_t status,
|
|
uint16_t net_idx, uint8_t node_id)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_NODE_ID_STATUS, 4);
|
|
bt_mesh_model_msg_init(&buf, OP_PRIV_NODE_ID_STATUS);
|
|
|
|
net_buf_simple_add_u8(&buf, status);
|
|
net_buf_simple_add_le16(&buf, net_idx);
|
|
net_buf_simple_add_u8(&buf, node_id);
|
|
|
|
bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
|
|
}
|
|
|
|
static int handle_node_id_get(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
uint8_t node_id, status;
|
|
uint16_t net_idx;
|
|
|
|
net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
|
|
|
|
status = bt_mesh_subnet_priv_node_id_get(net_idx, (enum bt_mesh_feat_state *)&node_id);
|
|
node_id_status_rsp(mod, ctx, status, net_idx, node_id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int handle_node_id_set(const struct bt_mesh_model *mod,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
uint8_t node_id, status;
|
|
uint16_t net_idx;
|
|
|
|
net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
|
|
node_id = net_buf_simple_pull_u8(buf);
|
|
if (node_id != BT_MESH_NODE_IDENTITY_RUNNING &&
|
|
node_id != BT_MESH_NODE_IDENTITY_STOPPED) {
|
|
LOG_ERR("Invalid node ID value 0x%02x", node_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
status = bt_mesh_subnet_priv_node_id_set(net_idx, node_id);
|
|
node_id_status_rsp(mod, ctx, status, net_idx, node_id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct bt_mesh_model_op bt_mesh_priv_beacon_srv_op[] = {
|
|
{ OP_PRIV_BEACON_GET, BT_MESH_LEN_EXACT(0), handle_beacon_get },
|
|
{ OP_PRIV_BEACON_SET, BT_MESH_LEN_MIN(1), handle_beacon_set },
|
|
{ OP_PRIV_GATT_PROXY_GET, BT_MESH_LEN_EXACT(0), handle_gatt_proxy_get },
|
|
{ OP_PRIV_GATT_PROXY_SET, BT_MESH_LEN_EXACT(1), handle_gatt_proxy_set },
|
|
{ OP_PRIV_NODE_ID_GET, BT_MESH_LEN_EXACT(2), handle_node_id_get },
|
|
{ OP_PRIV_NODE_ID_SET, BT_MESH_LEN_EXACT(3), handle_node_id_set },
|
|
BT_MESH_MODEL_OP_END
|
|
};
|
|
|
|
static int priv_beacon_srv_init(const struct bt_mesh_model *mod)
|
|
{
|
|
int err;
|
|
const struct bt_mesh_model *config_srv =
|
|
bt_mesh_model_find(bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_CFG_SRV);
|
|
|
|
if (config_srv == NULL) {
|
|
LOG_ERR("Private Beacon server cannot extend Configuration server");
|
|
return -EINVAL;
|
|
}
|
|
|
|
priv_beacon_srv = mod;
|
|
mod->keys[0] = BT_MESH_KEY_DEV_LOCAL;
|
|
|
|
err = bt_mesh_model_extend(mod, config_srv);
|
|
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void priv_beacon_srv_reset(const struct bt_mesh_model *model)
|
|
{
|
|
(void)memset(&priv_beacon_state, 0, sizeof(priv_beacon_state));
|
|
priv_beacon_store(true);
|
|
}
|
|
|
|
#ifdef CONFIG_BT_SETTINGS
|
|
static int priv_beacon_srv_settings_set(const struct bt_mesh_model *model, const char *name,
|
|
size_t len_rd, settings_read_cb read_cb, void *cb_data)
|
|
{
|
|
int err;
|
|
|
|
if (len_rd == 0) {
|
|
LOG_DBG("Cleared configuration state");
|
|
return 0;
|
|
}
|
|
|
|
err = bt_mesh_settings_set(read_cb, cb_data, &priv_beacon_state, sizeof(priv_beacon_state));
|
|
if (err) {
|
|
LOG_ERR("Failed to set Private Beacon state");
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_priv_beacon_set(priv_beacon_state.state);
|
|
bt_mesh_priv_beacon_update_interval_set(priv_beacon_state.interval);
|
|
bt_mesh_priv_gatt_proxy_set(priv_beacon_state.proxy_state);
|
|
return 0;
|
|
}
|
|
|
|
static void priv_beacon_srv_pending_store(const struct bt_mesh_model *model)
|
|
{
|
|
priv_beacon_state.state = bt_mesh_priv_beacon_get();
|
|
priv_beacon_state.interval = bt_mesh_priv_beacon_update_interval_get();
|
|
priv_beacon_state.proxy_state = bt_mesh_priv_gatt_proxy_get();
|
|
|
|
priv_beacon_store(false);
|
|
}
|
|
#endif
|
|
|
|
const struct bt_mesh_model_cb bt_mesh_priv_beacon_srv_cb = {
|
|
.init = priv_beacon_srv_init,
|
|
.reset = priv_beacon_srv_reset,
|
|
#ifdef CONFIG_BT_SETTINGS
|
|
.settings_set = priv_beacon_srv_settings_set,
|
|
.pending_store = priv_beacon_srv_pending_store,
|
|
#endif
|
|
};
|
|
|
|
void bt_mesh_priv_beacon_srv_store_schedule(void)
|
|
{
|
|
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
|
bt_mesh_model_data_store_schedule(priv_beacon_srv);
|
|
}
|
|
}
|