/* * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #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 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)); }