1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2017 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/debug/stack.h>
10 #include <zephyr/sys/util.h>
11 
12 #include <zephyr/net_buf.h>
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/hci.h>
15 #include <zephyr/bluetooth/conn.h>
16 #include <zephyr/bluetooth/mesh.h>
17 
18 #include "common/bt_str.h"
19 
20 #include "net.h"
21 #include "foundation.h"
22 #include "beacon.h"
23 #include "prov.h"
24 #include "proxy.h"
25 #include "pb_gatt_srv.h"
26 #include "solicitation.h"
27 #include "statistic.h"
28 
29 #define LOG_LEVEL CONFIG_BT_MESH_ADV_LOG_LEVEL
30 #include <zephyr/logging/log.h>
31 LOG_MODULE_REGISTER(bt_mesh_adv);
32 
33 /* Window and Interval are equal for continuous scanning */
34 #define MESH_SCAN_INTERVAL    BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_INTERVAL_MS)
35 #define MESH_SCAN_WINDOW      BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_WINDOW_MS)
36 
37 const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = {
38 	[BT_MESH_ADV_PROV]   = BT_DATA_MESH_PROV,
39 	[BT_MESH_ADV_DATA]   = BT_DATA_MESH_MESSAGE,
40 	[BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON,
41 	[BT_MESH_ADV_URI]    = BT_DATA_URI,
42 };
43 
44 static bool active_scanning;
45 static K_FIFO_DEFINE(bt_mesh_adv_queue);
46 static K_FIFO_DEFINE(bt_mesh_relay_queue);
47 static K_FIFO_DEFINE(bt_mesh_friend_queue);
48 
49 K_MEM_SLAB_DEFINE_STATIC(local_adv_pool, sizeof(struct bt_mesh_adv),
50 			 CONFIG_BT_MESH_ADV_BUF_COUNT, __alignof__(struct bt_mesh_adv));
51 
52 #if defined(CONFIG_BT_MESH_RELAY_BUF_COUNT)
53 K_MEM_SLAB_DEFINE_STATIC(relay_adv_pool, sizeof(struct bt_mesh_adv),
54 			 CONFIG_BT_MESH_RELAY_BUF_COUNT, __alignof__(struct bt_mesh_adv));
55 #endif
56 
57 #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
58 K_MEM_SLAB_DEFINE_STATIC(friend_adv_pool, sizeof(struct bt_mesh_adv),
59 			 CONFIG_BT_MESH_FRIEND_LPN_COUNT, __alignof__(struct bt_mesh_adv));
60 #endif
61 
bt_mesh_adv_send_start(uint16_t duration,int err,struct bt_mesh_adv_ctx * ctx)62 void bt_mesh_adv_send_start(uint16_t duration, int err, struct bt_mesh_adv_ctx *ctx)
63 {
64 	if (!ctx->started) {
65 		ctx->started = 1;
66 
67 		if (ctx->cb && ctx->cb->start) {
68 			ctx->cb->start(duration, err, ctx->cb_data);
69 		}
70 
71 		if (err) {
72 			ctx->cb = NULL;
73 		} else if (IS_ENABLED(CONFIG_BT_MESH_STATISTIC)) {
74 			bt_mesh_stat_succeeded_count(ctx);
75 		}
76 	}
77 }
78 
bt_mesh_adv_send_end(int err,struct bt_mesh_adv_ctx const * ctx)79 void bt_mesh_adv_send_end(int err, struct bt_mesh_adv_ctx const *ctx)
80 {
81 	if (ctx->started && ctx->cb && ctx->cb->end) {
82 		ctx->cb->end(err, ctx->cb_data);
83 	}
84 }
85 
adv_create_from_pool(struct k_mem_slab * buf_pool,enum bt_mesh_adv_type type,enum bt_mesh_adv_tag tag,uint8_t xmit,k_timeout_t timeout)86 static struct bt_mesh_adv *adv_create_from_pool(struct k_mem_slab *buf_pool,
87 						enum bt_mesh_adv_type type,
88 						enum bt_mesh_adv_tag tag,
89 						uint8_t xmit, k_timeout_t timeout)
90 {
91 	struct bt_mesh_adv_ctx *ctx;
92 	struct bt_mesh_adv *adv;
93 	int err;
94 
95 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
96 		LOG_WRN("Refusing to allocate buffer while suspended");
97 		return NULL;
98 	}
99 
100 	err = k_mem_slab_alloc(buf_pool, (void **)&adv, timeout);
101 	if (err) {
102 		return NULL;
103 	}
104 
105 	adv->__ref = 1;
106 
107 	net_buf_simple_init_with_data(&adv->b, adv->__bufs, BT_MESH_ADV_DATA_SIZE);
108 	net_buf_simple_reset(&adv->b);
109 
110 	ctx = &adv->ctx;
111 
112 	(void)memset(ctx, 0, sizeof(*ctx));
113 
114 	ctx->type         = type;
115 	ctx->tag          = tag;
116 	ctx->xmit         = xmit;
117 
118 	return adv;
119 }
120 
bt_mesh_adv_ref(struct bt_mesh_adv * adv)121 struct bt_mesh_adv *bt_mesh_adv_ref(struct bt_mesh_adv *adv)
122 {
123 	__ASSERT_NO_MSG(adv->__ref < UINT8_MAX);
124 
125 	adv->__ref++;
126 
127 	return adv;
128 }
129 
bt_mesh_adv_unref(struct bt_mesh_adv * adv)130 void bt_mesh_adv_unref(struct bt_mesh_adv *adv)
131 {
132 	__ASSERT_NO_MSG(adv->__ref > 0);
133 
134 	if (--adv->__ref > 0) {
135 		return;
136 	}
137 
138 	struct k_mem_slab *slab = &local_adv_pool;
139 
140 #if (defined(CONFIG_BT_MESH_RELAY) || defined(CONFIG_BT_MESH_BRG_CFG_SRV))
141 	if (adv->ctx.tag == BT_MESH_ADV_TAG_RELAY) {
142 		slab = &relay_adv_pool;
143 	}
144 #endif
145 
146 #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
147 	if (adv->ctx.tag == BT_MESH_ADV_TAG_FRIEND) {
148 		slab = &friend_adv_pool;
149 	}
150 #endif
151 
152 	k_mem_slab_free(slab, (void *)adv);
153 }
154 
bt_mesh_adv_create(enum bt_mesh_adv_type type,enum bt_mesh_adv_tag tag,uint8_t xmit,k_timeout_t timeout)155 struct bt_mesh_adv *bt_mesh_adv_create(enum bt_mesh_adv_type type,
156 				       enum bt_mesh_adv_tag tag,
157 				       uint8_t xmit, k_timeout_t timeout)
158 {
159 #if (defined(CONFIG_BT_MESH_RELAY) || defined(CONFIG_BT_MESH_BRG_CFG_SRV))
160 	if (tag == BT_MESH_ADV_TAG_RELAY) {
161 		return adv_create_from_pool(&relay_adv_pool,
162 					    type, tag, xmit, timeout);
163 	}
164 #endif
165 
166 #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
167 	if (tag == BT_MESH_ADV_TAG_FRIEND) {
168 		return adv_create_from_pool(&friend_adv_pool,
169 					    type, tag, xmit, timeout);
170 	}
171 #endif
172 
173 	return adv_create_from_pool(&local_adv_pool, type,
174 				    tag, xmit, timeout);
175 }
176 
process_events(struct k_poll_event * ev,int count)177 static struct bt_mesh_adv *process_events(struct k_poll_event *ev, int count)
178 {
179 	for (; count; ev++, count--) {
180 		LOG_DBG("ev->state %u", ev->state);
181 
182 		switch (ev->state) {
183 		case K_POLL_STATE_FIFO_DATA_AVAILABLE:
184 			return k_fifo_get(ev->fifo, K_NO_WAIT);
185 		case K_POLL_STATE_NOT_READY:
186 		case K_POLL_STATE_CANCELLED:
187 			break;
188 		default:
189 			LOG_WRN("Unexpected k_poll event state %u", ev->state);
190 			break;
191 		}
192 	}
193 
194 	return NULL;
195 }
196 
bt_mesh_adv_get(k_timeout_t timeout)197 struct bt_mesh_adv *bt_mesh_adv_get(k_timeout_t timeout)
198 {
199 	int err;
200 	struct k_poll_event events[] = {
201 		K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
202 						K_POLL_MODE_NOTIFY_ONLY,
203 						&bt_mesh_adv_queue,
204 						0),
205 #if (defined(CONFIG_BT_MESH_RELAY) || defined(CONFIG_BT_MESH_BRG_CFG_SRV)) && \
206 	(defined(CONFIG_BT_MESH_ADV_LEGACY) || \
207 	 defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) || \
208 	 !(CONFIG_BT_MESH_RELAY_ADV_SETS))
209 		K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
210 						K_POLL_MODE_NOTIFY_ONLY,
211 						&bt_mesh_relay_queue,
212 						0),
213 #endif
214 	};
215 
216 	err = k_poll(events, ARRAY_SIZE(events), timeout);
217 	if (err) {
218 		return NULL;
219 	}
220 
221 	return process_events(events, ARRAY_SIZE(events));
222 }
223 
bt_mesh_adv_get_by_tag(enum bt_mesh_adv_tag_bit tags,k_timeout_t timeout)224 struct bt_mesh_adv *bt_mesh_adv_get_by_tag(enum bt_mesh_adv_tag_bit tags, k_timeout_t timeout)
225 {
226 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) &&
227 	    tags & BT_MESH_ADV_TAG_BIT_FRIEND) {
228 		return k_fifo_get(&bt_mesh_friend_queue, timeout);
229 	}
230 
231 	if ((IS_ENABLED(CONFIG_BT_MESH_RELAY) || IS_ENABLED(CONFIG_BT_MESH_BRG_CFG_SRV)) &&
232 	    !(tags & BT_MESH_ADV_TAG_BIT_LOCAL)) {
233 		return k_fifo_get(&bt_mesh_relay_queue, timeout);
234 	}
235 
236 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) &&
237 	    tags & BT_MESH_ADV_TAG_BIT_PROXY) {
238 		return NULL;
239 	}
240 
241 	return bt_mesh_adv_get(timeout);
242 }
243 
bt_mesh_adv_get_cancel(void)244 void bt_mesh_adv_get_cancel(void)
245 {
246 	LOG_DBG("");
247 
248 	k_fifo_cancel_wait(&bt_mesh_adv_queue);
249 
250 	if ((IS_ENABLED(CONFIG_BT_MESH_RELAY) || IS_ENABLED(CONFIG_BT_MESH_BRG_CFG_SRV))) {
251 		k_fifo_cancel_wait(&bt_mesh_relay_queue);
252 	}
253 
254 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) {
255 		k_fifo_cancel_wait(&bt_mesh_friend_queue);
256 	}
257 }
258 
bt_mesh_adv_send(struct bt_mesh_adv * adv,const struct bt_mesh_send_cb * cb,void * cb_data)259 void bt_mesh_adv_send(struct bt_mesh_adv *adv, const struct bt_mesh_send_cb *cb,
260 		      void *cb_data)
261 {
262 	LOG_DBG("type 0x%02x len %u: %s", adv->ctx.type, adv->b.len,
263 		bt_hex(adv->b.data, adv->b.len));
264 
265 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
266 		LOG_WRN("Sending advertisement while suspended");
267 	}
268 
269 	adv->ctx.cb = cb;
270 	adv->ctx.cb_data = cb_data;
271 	adv->ctx.busy = 1U;
272 
273 	if (IS_ENABLED(CONFIG_BT_MESH_STATISTIC)) {
274 		bt_mesh_stat_planned_count(&adv->ctx);
275 	}
276 
277 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) &&
278 	    adv->ctx.tag == BT_MESH_ADV_TAG_FRIEND) {
279 		k_fifo_put(&bt_mesh_friend_queue, bt_mesh_adv_ref(adv));
280 		bt_mesh_adv_friend_ready();
281 		return;
282 	}
283 
284 	if (((IS_ENABLED(CONFIG_BT_MESH_RELAY) || IS_ENABLED(CONFIG_BT_MESH_BRG_CFG_SRV)) &&
285 	    adv->ctx.tag == BT_MESH_ADV_TAG_RELAY) ||
286 	    (IS_ENABLED(CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS) &&
287 	     adv->ctx.tag == BT_MESH_ADV_TAG_PROV)) {
288 		k_fifo_put(&bt_mesh_relay_queue, bt_mesh_adv_ref(adv));
289 		bt_mesh_adv_relay_ready();
290 		return;
291 	}
292 
293 	k_fifo_put(&bt_mesh_adv_queue, bt_mesh_adv_ref(adv));
294 	bt_mesh_adv_local_ready();
295 }
296 
bt_mesh_adv_gatt_send(void)297 int bt_mesh_adv_gatt_send(void)
298 {
299 	if (bt_mesh_is_provisioned()) {
300 		if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
301 			LOG_DBG("Proxy Advertising");
302 			return bt_mesh_proxy_adv_start();
303 		}
304 	} else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
305 		LOG_DBG("PB-GATT Advertising");
306 		return bt_mesh_pb_gatt_srv_adv_start();
307 	}
308 
309 	return -ENOTSUP;
310 }
311 
bt_mesh_scan_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)312 static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
313 			    uint8_t adv_type, struct net_buf_simple *buf)
314 {
315 	if (adv_type != BT_GAP_ADV_TYPE_ADV_NONCONN_IND) {
316 		return;
317 	}
318 
319 	LOG_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
320 
321 	while (buf->len > 1) {
322 		struct net_buf_simple_state state;
323 		uint8_t len, type;
324 
325 		len = net_buf_simple_pull_u8(buf);
326 		/* Check for early termination */
327 		if (len == 0U) {
328 			return;
329 		}
330 
331 		if (len > buf->len) {
332 			LOG_WRN("AD malformed");
333 			return;
334 		}
335 
336 		net_buf_simple_save(buf, &state);
337 
338 		type = net_buf_simple_pull_u8(buf);
339 
340 		buf->len = len - 1;
341 
342 		switch (type) {
343 		case BT_DATA_MESH_MESSAGE:
344 			bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
345 			break;
346 #if defined(CONFIG_BT_MESH_PB_ADV)
347 		case BT_DATA_MESH_PROV:
348 			bt_mesh_pb_adv_recv(buf);
349 			break;
350 #endif
351 		case BT_DATA_MESH_BEACON:
352 			bt_mesh_beacon_recv(buf);
353 			break;
354 		case BT_DATA_UUID16_SOME:
355 			/* Fall through */
356 		case BT_DATA_UUID16_ALL:
357 			if (IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)) {
358 				/* Restore buffer with Solicitation PDU */
359 				net_buf_simple_restore(buf, &state);
360 				bt_mesh_sol_recv(buf, len - 1);
361 			}
362 			break;
363 		default:
364 			break;
365 		}
366 
367 		net_buf_simple_restore(buf, &state);
368 		net_buf_simple_pull(buf, len);
369 	}
370 }
371 
bt_mesh_scan_active_set(bool active)372 int bt_mesh_scan_active_set(bool active)
373 {
374 	if (active_scanning == active) {
375 		return 0;
376 	}
377 
378 	active_scanning = active;
379 	bt_mesh_scan_disable();
380 	return bt_mesh_scan_enable();
381 }
382 
bt_mesh_scan_enable(void)383 int bt_mesh_scan_enable(void)
384 {
385 	struct bt_le_scan_param scan_param = {
386 		.type = active_scanning ? BT_LE_SCAN_TYPE_ACTIVE :
387 					  BT_LE_SCAN_TYPE_PASSIVE,
388 		.interval = MESH_SCAN_INTERVAL,
389 		.window = MESH_SCAN_WINDOW
390 	};
391 	int err;
392 
393 	LOG_DBG("");
394 
395 	err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
396 	if (err && err != -EALREADY) {
397 		LOG_ERR("starting scan failed (err %d)", err);
398 		return err;
399 	}
400 
401 	return 0;
402 }
403 
bt_mesh_scan_disable(void)404 int bt_mesh_scan_disable(void)
405 {
406 	int err;
407 
408 	LOG_DBG("");
409 
410 	err = bt_le_scan_stop();
411 	if (err && err != -EALREADY) {
412 		LOG_ERR("stopping scan failed (err %d)", err);
413 		return err;
414 	}
415 
416 	return 0;
417 }
418