1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/bluetooth/mesh.h>
8 #include <zephyr/bluetooth/mesh/access.h>
9
10 #include <common/bt_str.h>
11
12 #include "net.h"
13 #include "access.h"
14 #include "foundation.h"
15 #include "mesh.h"
16 #include "sar_cfg_internal.h"
17
18 #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(bt_mesh_sar_cfg_cli);
21
22 static struct bt_mesh_sar_cfg_cli *cli;
23
transmitter_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)24 static int transmitter_status(const struct bt_mesh_model *model,
25 struct bt_mesh_msg_ctx *ctx,
26 struct net_buf_simple *buf)
27 {
28 struct bt_mesh_sar_tx *rsp;
29
30 if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS,
31 ctx->addr, (void **)&rsp)) {
32 return 0;
33 }
34
35 bt_mesh_sar_tx_decode(buf, rsp);
36
37 LOG_DBG("SAR TX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}",
38 rsp->seg_int_step, rsp->unicast_retrans_count,
39 rsp->unicast_retrans_without_prog_count,
40 rsp->unicast_retrans_int_step, rsp->unicast_retrans_int_inc,
41 rsp->multicast_retrans_count, rsp->multicast_retrans_int);
42
43 bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
44
45 return 0;
46 }
47
receiver_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)48 static int receiver_status(const struct bt_mesh_model *model,
49 struct bt_mesh_msg_ctx *ctx,
50 struct net_buf_simple *buf)
51 {
52 struct bt_mesh_sar_rx *rsp;
53
54 LOG_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
55 ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
56 bt_hex(buf->data, buf->len));
57
58 if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS,
59 ctx->addr, (void **)&rsp)) {
60 return 0;
61 }
62
63 bt_mesh_sar_rx_decode(buf, rsp);
64
65 LOG_DBG("SAR RX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}", rsp->seg_thresh,
66 rsp->ack_delay_inc, rsp->discard_timeout, rsp->rx_seg_int_step,
67 rsp->ack_retrans_count);
68
69 bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
70
71 return 0;
72 }
73
74 const struct bt_mesh_model_op _bt_mesh_sar_cfg_cli_op[] = {
75 { OP_SAR_CFG_TX_STATUS, BT_MESH_LEN_EXACT(BT_MESH_SAR_TX_LEN), transmitter_status },
76 { OP_SAR_CFG_RX_STATUS, BT_MESH_LEN_EXACT(BT_MESH_SAR_RX_LEN), receiver_status },
77 BT_MESH_MODEL_OP_END,
78 };
79
bt_mesh_sar_cfg_cli_timeout_get(void)80 int32_t bt_mesh_sar_cfg_cli_timeout_get(void)
81 {
82 return cli->timeout;
83 }
84
bt_mesh_sar_cfg_cli_timeout_set(int32_t timeout)85 void bt_mesh_sar_cfg_cli_timeout_set(int32_t timeout)
86 {
87 cli->timeout = timeout;
88 }
89
bt_mesh_sar_cfg_cli_init(const struct bt_mesh_model * model)90 static int bt_mesh_sar_cfg_cli_init(const struct bt_mesh_model *model)
91 {
92 if (!bt_mesh_model_in_primary(model)) {
93 LOG_ERR("SAR Configuration Client only allowed in primary element");
94 return -EINVAL;
95 }
96
97 if (!model->rt->user_data) {
98 LOG_ERR("No SAR Configuration Client context provided");
99 return -EINVAL;
100 }
101
102 cli = model->rt->user_data;
103 cli->model = model;
104 cli->timeout = 2 * MSEC_PER_SEC;
105
106 model->keys[0] = BT_MESH_KEY_DEV_ANY;
107 model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY;
108
109 bt_mesh_msg_ack_ctx_init(&cli->ack_ctx);
110
111 return 0;
112 }
113
bt_mesh_sar_cfg_cli_reset(const struct bt_mesh_model * model)114 static void bt_mesh_sar_cfg_cli_reset(const struct bt_mesh_model *model)
115 {
116 struct bt_mesh_sar_cfg_cli *model_cli;
117
118 model_cli = model->rt->user_data;
119
120 bt_mesh_msg_ack_ctx_clear(&model_cli->ack_ctx);
121 }
122
123 const struct bt_mesh_model_cb _bt_mesh_sar_cfg_cli_cb = {
124 .init = bt_mesh_sar_cfg_cli_init,
125 .reset = bt_mesh_sar_cfg_cli_reset,
126 };
127
bt_mesh_sar_cfg_cli_transmitter_get(uint16_t net_idx,uint16_t addr,struct bt_mesh_sar_tx * rsp)128 int bt_mesh_sar_cfg_cli_transmitter_get(uint16_t net_idx, uint16_t addr,
129 struct bt_mesh_sar_tx *rsp)
130 {
131 BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_GET, 0);
132 struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
133 int err;
134
135 err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS, addr, rsp);
136 if (err) {
137 return err;
138 }
139
140 bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_GET);
141
142 err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
143 if (err) {
144 LOG_ERR("model_send() failed (err %d)", err);
145 bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
146 return err;
147 }
148
149 return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
150 }
151
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)152 int bt_mesh_sar_cfg_cli_transmitter_set(uint16_t net_idx, uint16_t addr,
153 const struct bt_mesh_sar_tx *set,
154 struct bt_mesh_sar_tx *rsp)
155 {
156 BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_SET, BT_MESH_SAR_TX_LEN);
157 struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
158 int err;
159
160 err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS, addr, rsp);
161 if (err) {
162 return err;
163 }
164
165 bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_SET);
166 bt_mesh_sar_tx_encode(&msg, set);
167
168 err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
169 if (err) {
170 LOG_ERR("model_send() failed (err %d)", err);
171 bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
172 return err;
173 }
174
175 return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
176 }
177
bt_mesh_sar_cfg_cli_receiver_get(uint16_t net_idx,uint16_t addr,struct bt_mesh_sar_rx * rsp)178 int bt_mesh_sar_cfg_cli_receiver_get(uint16_t net_idx, uint16_t addr,
179 struct bt_mesh_sar_rx *rsp)
180 {
181 BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_GET, 0);
182 struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
183 int err;
184
185 err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS, addr, rsp);
186 if (err) {
187 return err;
188 }
189
190 bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_GET);
191
192 err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
193 if (err) {
194 LOG_ERR("model_send() failed (err %d)", err);
195 bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
196 return err;
197 }
198
199 return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
200 }
201
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)202 int bt_mesh_sar_cfg_cli_receiver_set(uint16_t net_idx, uint16_t addr,
203 const struct bt_mesh_sar_rx *set,
204 struct bt_mesh_sar_rx *rsp)
205 {
206 BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_SET, BT_MESH_SAR_RX_LEN);
207 struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr);
208 int err;
209
210 err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS, addr, rsp);
211 if (err) {
212 return err;
213 }
214
215 bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_SET);
216 bt_mesh_sar_rx_encode(&msg, set);
217
218 err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
219 if (err) {
220 LOG_ERR("model_send() failed (err %d)", err);
221 bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
222 return err;
223 }
224
225 return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
226 }
227