227 lines
5.9 KiB
C
227 lines
5.9 KiB
C
/*
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/bluetooth/mesh.h>
|
|
#include <zephyr/bluetooth/mesh/access.h>
|
|
|
|
#include <common/bt_str.h>
|
|
|
|
#include "net.h"
|
|
#include "access.h"
|
|
#include "foundation.h"
|
|
#include "mesh.h"
|
|
#include "sar_cfg_internal.h"
|
|
|
|
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(bt_mesh_sar_cfg_cli);
|
|
|
|
static struct bt_mesh_sar_cfg_cli *cli;
|
|
|
|
static int transmitter_status(const struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_sar_tx *rsp;
|
|
|
|
if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS,
|
|
ctx->addr, (void **)&rsp)) {
|
|
return 0;
|
|
}
|
|
|
|
bt_mesh_sar_tx_decode(buf, rsp);
|
|
|
|
LOG_DBG("SAR TX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}",
|
|
rsp->seg_int_step, rsp->unicast_retrans_count,
|
|
rsp->unicast_retrans_without_prog_count,
|
|
rsp->unicast_retrans_int_step, rsp->unicast_retrans_int_inc,
|
|
rsp->multicast_retrans_count, rsp->multicast_retrans_int);
|
|
|
|
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int receiver_status(const struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_sar_rx *rsp;
|
|
|
|
LOG_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 (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS,
|
|
ctx->addr, (void **)&rsp)) {
|
|
return 0;
|
|
}
|
|
|
|
bt_mesh_sar_rx_decode(buf, rsp);
|
|
|
|
LOG_DBG("SAR RX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}", rsp->seg_thresh,
|
|
rsp->ack_delay_inc, rsp->discard_timeout, rsp->rx_seg_int_step,
|
|
rsp->ack_retrans_count);
|
|
|
|
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct bt_mesh_model_op _bt_mesh_sar_cfg_cli_op[] = {
|
|
{ OP_SAR_CFG_TX_STATUS, BT_MESH_LEN_EXACT(BT_MESH_SAR_TX_LEN), transmitter_status },
|
|
{ OP_SAR_CFG_RX_STATUS, BT_MESH_LEN_EXACT(BT_MESH_SAR_RX_LEN), receiver_status },
|
|
BT_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
int32_t bt_mesh_sar_cfg_cli_timeout_get(void)
|
|
{
|
|
return cli->timeout;
|
|
}
|
|
|
|
void bt_mesh_sar_cfg_cli_timeout_set(int32_t timeout)
|
|
{
|
|
cli->timeout = timeout;
|
|
}
|
|
|
|
static int bt_mesh_sar_cfg_cli_init(const struct bt_mesh_model *model)
|
|
{
|
|
if (!bt_mesh_model_in_primary(model)) {
|
|
LOG_ERR("SAR Configuration Client only allowed in primary element");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!model->rt->user_data) {
|
|
LOG_ERR("No SAR Configuration Client context provided");
|
|
return -EINVAL;
|
|
}
|
|
|
|
cli = model->rt->user_data;
|
|
cli->model = model;
|
|
cli->timeout = 2 * MSEC_PER_SEC;
|
|
|
|
model->keys[0] = BT_MESH_KEY_DEV_ANY;
|
|
model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY;
|
|
|
|
bt_mesh_msg_ack_ctx_init(&cli->ack_ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void bt_mesh_sar_cfg_cli_reset(const struct bt_mesh_model *model)
|
|
{
|
|
struct bt_mesh_sar_cfg_cli *model_cli;
|
|
|
|
model_cli = model->rt->user_data;
|
|
|
|
bt_mesh_msg_ack_ctx_clear(&model_cli->ack_ctx);
|
|
}
|
|
|
|
const struct bt_mesh_model_cb _bt_mesh_sar_cfg_cli_cb = {
|
|
.init = bt_mesh_sar_cfg_cli_init,
|
|
.reset = bt_mesh_sar_cfg_cli_reset,
|
|
};
|
|
|
|
int bt_mesh_sar_cfg_cli_transmitter_get(uint16_t net_idx, uint16_t addr,
|
|
struct bt_mesh_sar_tx *rsp)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_GET, 0);
|
|
struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
|
|
int err;
|
|
|
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS, addr, rsp);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_GET);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("model_send() failed (err %d)", err);
|
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
|
return err;
|
|
}
|
|
|
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
|
}
|
|
|
|
int bt_mesh_sar_cfg_cli_transmitter_set(uint16_t net_idx, uint16_t addr,
|
|
const struct bt_mesh_sar_tx *set,
|
|
struct bt_mesh_sar_tx *rsp)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_SET, BT_MESH_SAR_TX_LEN);
|
|
struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
|
|
int err;
|
|
|
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS, addr, rsp);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_SET);
|
|
bt_mesh_sar_tx_encode(&msg, set);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("model_send() failed (err %d)", err);
|
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
|
return err;
|
|
}
|
|
|
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
|
}
|
|
|
|
int bt_mesh_sar_cfg_cli_receiver_get(uint16_t net_idx, uint16_t addr,
|
|
struct bt_mesh_sar_rx *rsp)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_GET, 0);
|
|
struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
|
|
int err;
|
|
|
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS, addr, rsp);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_GET);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("model_send() failed (err %d)", err);
|
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
|
return err;
|
|
}
|
|
|
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
|
}
|
|
|
|
int bt_mesh_sar_cfg_cli_receiver_set(uint16_t net_idx, uint16_t addr,
|
|
const struct bt_mesh_sar_rx *set,
|
|
struct bt_mesh_sar_rx *rsp)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_SET, BT_MESH_SAR_RX_LEN);
|
|
struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
|
|
int err;
|
|
|
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS, addr, rsp);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_SET);
|
|
bt_mesh_sar_rx_encode(&msg, set);
|
|
|
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("model_send() failed (err %d)", err);
|
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
|
return err;
|
|
}
|
|
|
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
|
}
|