1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/bluetooth/mesh.h>
7 #include "net.h"
8 #include <zephyr/bluetooth/conn.h>
9 #include "proxy.h"
10 #include "foundation.h"
11 #include "beacon.h"
12 #include "cfg.h"
13 #include "settings.h"
14
15 #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(bt_mesh_priv_beacon_srv);
18
19 static const struct bt_mesh_model *priv_beacon_srv;
20
21 /* Private Beacon configuration server model states */
22 struct {
23 uint8_t state;
24 uint8_t interval;
25 uint8_t proxy_state;
26 } priv_beacon_state;
27
priv_beacon_store(bool delete)28 static int priv_beacon_store(bool delete)
29 {
30 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
31 return 0;
32 }
33
34 const void *data = delete ? NULL : &priv_beacon_state;
35 size_t len = delete ? 0 : sizeof(priv_beacon_state);
36
37 return bt_mesh_model_data_store(priv_beacon_srv, false, "pb", data, len);
38 }
39
beacon_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx)40 static int beacon_status_rsp(const struct bt_mesh_model *mod,
41 struct bt_mesh_msg_ctx *ctx)
42 {
43 BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_BEACON_STATUS, 2);
44 bt_mesh_model_msg_init(&buf, OP_PRIV_BEACON_STATUS);
45
46 net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_get());
47 net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_update_interval_get());
48
49 bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
50
51 return 0;
52 }
53
handle_beacon_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)54 static int handle_beacon_get(const struct bt_mesh_model *mod,
55 struct bt_mesh_msg_ctx *ctx,
56 struct net_buf_simple *buf)
57 {
58 LOG_DBG("");
59
60 beacon_status_rsp(mod, ctx);
61
62 return 0;
63 }
64
handle_beacon_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)65 static int handle_beacon_set(const struct bt_mesh_model *mod,
66 struct bt_mesh_msg_ctx *ctx,
67 struct net_buf_simple *buf)
68 {
69 uint8_t beacon;
70
71 if (buf->len > 2U) {
72 return -EMSGSIZE;
73 }
74
75 beacon = net_buf_simple_pull_u8(buf);
76 if (beacon != BT_MESH_BEACON_DISABLED &&
77 beacon != BT_MESH_BEACON_ENABLED) {
78 LOG_WRN("Invalid beacon value %u", beacon);
79 return -EINVAL;
80 }
81
82 if (buf->len == 1U) {
83 bt_mesh_priv_beacon_update_interval_set(net_buf_simple_pull_u8(buf));
84 }
85
86 (void)bt_mesh_priv_beacon_set(beacon);
87 beacon_status_rsp(mod, ctx);
88
89 return 0;
90 }
91
gatt_proxy_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx)92 static void gatt_proxy_status_rsp(const struct bt_mesh_model *mod,
93 struct bt_mesh_msg_ctx *ctx)
94 {
95 BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_GATT_PROXY_STATUS, 1);
96 bt_mesh_model_msg_init(&buf, OP_PRIV_GATT_PROXY_STATUS);
97
98 net_buf_simple_add_u8(&buf, bt_mesh_priv_gatt_proxy_get());
99
100 bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
101 }
102
handle_gatt_proxy_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)103 static int handle_gatt_proxy_get(const struct bt_mesh_model *mod,
104 struct bt_mesh_msg_ctx *ctx,
105 struct net_buf_simple *buf)
106 {
107 LOG_DBG("");
108
109 gatt_proxy_status_rsp(mod, ctx);
110
111 return 0;
112 }
113
handle_gatt_proxy_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)114 static int handle_gatt_proxy_set(const struct bt_mesh_model *mod,
115 struct bt_mesh_msg_ctx *ctx,
116 struct net_buf_simple *buf)
117 {
118 uint8_t gatt_proxy;
119
120 gatt_proxy = net_buf_simple_pull_u8(buf);
121 if (gatt_proxy != BT_MESH_GATT_PROXY_DISABLED &&
122 gatt_proxy != BT_MESH_GATT_PROXY_ENABLED) {
123 LOG_WRN("Invalid GATT proxy value %u", gatt_proxy);
124 return -EINVAL;
125 }
126
127 LOG_DBG("%u", gatt_proxy);
128
129 bt_mesh_priv_gatt_proxy_set(gatt_proxy);
130
131 gatt_proxy_status_rsp(mod, ctx);
132
133 return 0;
134 }
135
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)136 static void node_id_status_rsp(const struct bt_mesh_model *mod,
137 struct bt_mesh_msg_ctx *ctx, uint8_t status,
138 uint16_t net_idx, uint8_t node_id)
139 {
140 BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_NODE_ID_STATUS, 4);
141 bt_mesh_model_msg_init(&buf, OP_PRIV_NODE_ID_STATUS);
142
143 net_buf_simple_add_u8(&buf, status);
144 net_buf_simple_add_le16(&buf, net_idx);
145 net_buf_simple_add_u8(&buf, node_id);
146
147 bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
148 }
149
handle_node_id_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)150 static int handle_node_id_get(const struct bt_mesh_model *mod,
151 struct bt_mesh_msg_ctx *ctx,
152 struct net_buf_simple *buf)
153 {
154 uint8_t node_id, status;
155 uint16_t net_idx;
156
157 net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
158
159 status = bt_mesh_subnet_priv_node_id_get(net_idx, (enum bt_mesh_feat_state *)&node_id);
160 node_id_status_rsp(mod, ctx, status, net_idx, node_id);
161
162 return 0;
163 }
164
handle_node_id_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)165 static int handle_node_id_set(const struct bt_mesh_model *mod,
166 struct bt_mesh_msg_ctx *ctx,
167 struct net_buf_simple *buf)
168 {
169 uint8_t node_id, status;
170 uint16_t net_idx;
171
172 net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
173 node_id = net_buf_simple_pull_u8(buf);
174 if (node_id != BT_MESH_NODE_IDENTITY_RUNNING &&
175 node_id != BT_MESH_NODE_IDENTITY_STOPPED) {
176 LOG_ERR("Invalid node ID value 0x%02x", node_id);
177 return -EINVAL;
178 }
179
180 status = bt_mesh_subnet_priv_node_id_set(net_idx, node_id);
181 node_id_status_rsp(mod, ctx, status, net_idx, node_id);
182
183 return 0;
184 }
185
186 const struct bt_mesh_model_op bt_mesh_priv_beacon_srv_op[] = {
187 { OP_PRIV_BEACON_GET, BT_MESH_LEN_EXACT(0), handle_beacon_get },
188 { OP_PRIV_BEACON_SET, BT_MESH_LEN_MIN(1), handle_beacon_set },
189 { OP_PRIV_GATT_PROXY_GET, BT_MESH_LEN_EXACT(0), handle_gatt_proxy_get },
190 { OP_PRIV_GATT_PROXY_SET, BT_MESH_LEN_EXACT(1), handle_gatt_proxy_set },
191 { OP_PRIV_NODE_ID_GET, BT_MESH_LEN_EXACT(2), handle_node_id_get },
192 { OP_PRIV_NODE_ID_SET, BT_MESH_LEN_EXACT(3), handle_node_id_set },
193 BT_MESH_MODEL_OP_END
194 };
195
priv_beacon_srv_init(const struct bt_mesh_model * mod)196 static int priv_beacon_srv_init(const struct bt_mesh_model *mod)
197 {
198 int err;
199 const struct bt_mesh_model *config_srv =
200 bt_mesh_model_find(bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_CFG_SRV);
201
202 if (config_srv == NULL) {
203 LOG_ERR("Private Beacon server cannot extend Configuration server");
204 return -EINVAL;
205 }
206
207 priv_beacon_srv = mod;
208 mod->keys[0] = BT_MESH_KEY_DEV_LOCAL;
209
210 err = bt_mesh_model_extend(mod, config_srv);
211
212 if (err) {
213 return err;
214 }
215
216 return 0;
217 }
218
priv_beacon_srv_reset(const struct bt_mesh_model * model)219 static void priv_beacon_srv_reset(const struct bt_mesh_model *model)
220 {
221 (void)memset(&priv_beacon_state, 0, sizeof(priv_beacon_state));
222 priv_beacon_store(true);
223 }
224
225 #ifdef CONFIG_BT_SETTINGS
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)226 static int priv_beacon_srv_settings_set(const struct bt_mesh_model *model, const char *name,
227 size_t len_rd, settings_read_cb read_cb, void *cb_data)
228 {
229 int err;
230
231 if (len_rd == 0) {
232 LOG_DBG("Cleared configuration state");
233 return 0;
234 }
235
236 err = bt_mesh_settings_set(read_cb, cb_data, &priv_beacon_state, sizeof(priv_beacon_state));
237 if (err) {
238 LOG_ERR("Failed to set Private Beacon state");
239 return err;
240 }
241
242 bt_mesh_priv_beacon_set(priv_beacon_state.state);
243 bt_mesh_priv_beacon_update_interval_set(priv_beacon_state.interval);
244 bt_mesh_priv_gatt_proxy_set(priv_beacon_state.proxy_state);
245 return 0;
246 }
247
priv_beacon_srv_pending_store(const struct bt_mesh_model * model)248 static void priv_beacon_srv_pending_store(const struct bt_mesh_model *model)
249 {
250 priv_beacon_state.state = bt_mesh_priv_beacon_get();
251 priv_beacon_state.interval = bt_mesh_priv_beacon_update_interval_get();
252 priv_beacon_state.proxy_state = bt_mesh_priv_gatt_proxy_get();
253
254 priv_beacon_store(false);
255 }
256 #endif
257
258 const struct bt_mesh_model_cb bt_mesh_priv_beacon_srv_cb = {
259 .init = priv_beacon_srv_init,
260 .reset = priv_beacon_srv_reset,
261 #ifdef CONFIG_BT_SETTINGS
262 .settings_set = priv_beacon_srv_settings_set,
263 .pending_store = priv_beacon_srv_pending_store,
264 #endif
265 };
266
bt_mesh_priv_beacon_srv_store_schedule(void)267 void bt_mesh_priv_beacon_srv_store_schedule(void)
268 {
269 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
270 bt_mesh_model_data_store_schedule(priv_beacon_srv);
271 }
272 }
273