160 lines
3.5 KiB
C
160 lines
3.5 KiB
C
/*
|
|
* Copyright (c) 2022 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/bluetooth/mesh.h>
|
|
|
|
#include "access.h"
|
|
#include "foundation.h"
|
|
#include "net.h"
|
|
#include "mesh.h"
|
|
#include "transport.h"
|
|
#include "op_agg.h"
|
|
|
|
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(bt_mesh_op_agg_srv);
|
|
|
|
NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX);
|
|
|
|
/** Mesh Opcodes Aggregator Server Model Context */
|
|
static struct bt_mesh_op_agg_srv {
|
|
/** Composition data model entry pointer. */
|
|
const struct bt_mesh_model *model;
|
|
/** Response error code. */
|
|
int rsp_err;
|
|
/** Indicates that the received aggregated message
|
|
* was acknowledged by local server model.
|
|
*/
|
|
bool ack;
|
|
/** Aggregator context. */
|
|
struct op_agg_ctx ctx;
|
|
} srv = {.ctx.sdu = &sdu};
|
|
|
|
static int handle_sequence(const struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct net_buf_simple_state state;
|
|
struct net_buf_simple msg;
|
|
uint16_t elem;
|
|
uint8_t *status;
|
|
int err;
|
|
|
|
elem = net_buf_simple_pull_le16(buf);
|
|
ctx->recv_dst = elem;
|
|
|
|
bt_mesh_model_msg_init(srv.ctx.sdu, OP_OPCODES_AGGREGATOR_STATUS);
|
|
status = net_buf_simple_add_u8(srv.ctx.sdu, 0);
|
|
net_buf_simple_add_le16(srv.ctx.sdu, elem);
|
|
|
|
srv.ctx.net_idx = ctx->net_idx;
|
|
srv.ctx.app_idx = ctx->app_idx;
|
|
srv.ctx.addr = ctx->addr;
|
|
srv.ctx.initialized = true;
|
|
|
|
if (!BT_MESH_ADDR_IS_UNICAST(elem)) {
|
|
LOG_WRN("Address is not unicast, ignoring.");
|
|
return -EINVAL;
|
|
}
|
|
|
|
net_buf_simple_save(buf, &state);
|
|
while (buf->len > 0) {
|
|
err = bt_mesh_op_agg_decode_msg(&msg, buf);
|
|
if (err) {
|
|
LOG_ERR("Unable to parse Opcodes Aggregator Sequence message (err %d)",
|
|
err);
|
|
return err;
|
|
}
|
|
}
|
|
net_buf_simple_restore(buf, &state);
|
|
|
|
if (!bt_mesh_elem_find(elem)) {
|
|
*status = ACCESS_STATUS_INVALID_ADDRESS;
|
|
goto send;
|
|
}
|
|
|
|
while (buf->len > 0) {
|
|
(void) bt_mesh_op_agg_decode_msg(&msg, buf);
|
|
|
|
srv.ack = false;
|
|
srv.rsp_err = 0;
|
|
err = bt_mesh_model_recv(ctx, &msg);
|
|
|
|
if (srv.rsp_err) {
|
|
*status = srv.rsp_err;
|
|
break;
|
|
}
|
|
|
|
if (err) {
|
|
*status = err;
|
|
break;
|
|
}
|
|
|
|
if (!srv.ack) {
|
|
net_buf_simple_add_u8(srv.ctx.sdu, 0);
|
|
}
|
|
}
|
|
|
|
send:
|
|
srv.ctx.initialized = false;
|
|
err = bt_mesh_model_send(model, ctx, srv.ctx.sdu, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("Unable to send Opcodes Aggregator Status");
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct bt_mesh_model_op _bt_mesh_op_agg_srv_op[] = {
|
|
{ OP_OPCODES_AGGREGATOR_SEQUENCE, BT_MESH_LEN_MIN(2), handle_sequence },
|
|
BT_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
static int op_agg_srv_init(const struct bt_mesh_model *model)
|
|
{
|
|
if (!bt_mesh_model_in_primary(model)) {
|
|
LOG_ERR("Opcodes Aggregator Server only allowed in primary element");
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Opcodes Aggregator Server model shall use the device key and
|
|
* application keys.
|
|
*/
|
|
model->keys[0] = BT_MESH_KEY_DEV_ANY;
|
|
|
|
srv.model = model;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_op_agg_srv_send(const struct bt_mesh_model *model, struct net_buf_simple *msg)
|
|
{
|
|
int err;
|
|
|
|
/* Model responded so mark this message as acknowledged */
|
|
srv.ack = true;
|
|
|
|
err = bt_mesh_op_agg_encode_msg(msg, srv.ctx.sdu);
|
|
if (err) {
|
|
srv.rsp_err = ACCESS_STATUS_RESPONSE_OVERFLOW;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
|
|
{
|
|
|
|
return srv.ctx.initialized && (ctx->net_idx == srv.ctx.net_idx) &&
|
|
(ctx->addr == srv.ctx.addr) && (ctx->app_idx == srv.ctx.app_idx) &&
|
|
!bt_mesh_op_agg_is_op_agg_msg(buf);
|
|
}
|
|
|
|
const struct bt_mesh_model_cb _bt_mesh_op_agg_srv_cb = {
|
|
.init = op_agg_srv_init,
|
|
};
|