1 /*
2  * Copyright (c) 2021 Xiaomi Corporation
3  * Copyright (c) 2018 Nordic Semiconductor ASA
4  * Copyright (c) 2017 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/debug/stack.h>
11 #include <zephyr/sys/iterable_sections.h>
12 #include <zephyr/net_buf.h>
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/hci.h>
15 #include <zephyr/bluetooth/mesh.h>
16 
17 #include "common/bt_str.h"
18 
19 #include "host/hci_core.h"
20 
21 #include "net.h"
22 #include "proxy.h"
23 #include "solicitation.h"
24 
25 #define LOG_LEVEL CONFIG_BT_MESH_ADV_LOG_LEVEL
26 #include <zephyr/logging/log.h>
27 LOG_MODULE_REGISTER(bt_mesh_adv_ext);
28 
29 /* Convert from ms to 0.625ms units */
30 #define ADV_INT_FAST_MS    20
31 
32 #ifndef CONFIG_BT_MESH_RELAY_ADV_SETS
33 #define CONFIG_BT_MESH_RELAY_ADV_SETS 0
34 #endif
35 
36 #ifdef CONFIG_BT_MESH_ADV_STACK_SIZE
37 #define MESH_WORKQ_PRIORITY   CONFIG_BT_MESH_ADV_PRIO
38 #define MESH_WORKQ_STACK_SIZE CONFIG_BT_MESH_ADV_STACK_SIZE
39 #else
40 #define MESH_WORKQ_PRIORITY   0
41 #define MESH_WORKQ_STACK_SIZE 0
42 #endif
43 
44 enum {
45 	/** Controller is currently advertising */
46 	ADV_FLAG_ACTIVE,
47 	/** Advertising sending completed */
48 	ADV_FLAG_SENT,
49 	/** Currently performing proxy advertising */
50 	ADV_FLAG_PROXY,
51 	/** Custom adv params have been set, we need to update the parameters on
52 	 *  the next send.
53 	 */
54 	ADV_FLAG_UPDATE_PARAMS,
55 
56 	/** The advertiser is suspending. */
57 	ADV_FLAG_SUSPENDING,
58 
59 	/* Number of adv flags. */
60 	ADV_FLAGS_NUM
61 };
62 
63 struct bt_mesh_ext_adv {
64 	const enum bt_mesh_adv_tag_bit tags;
65 	ATOMIC_DEFINE(flags, ADV_FLAGS_NUM);
66 	struct bt_le_ext_adv *instance;
67 	struct bt_mesh_adv *adv;
68 	uint32_t timestamp;
69 	struct k_work work;
70 	struct bt_le_adv_param adv_param;
71 };
72 
73 static void send_pending_adv(struct k_work *work);
74 static bool schedule_send(struct bt_mesh_ext_adv *ext_adv);
75 
76 static struct k_work_q bt_mesh_workq;
77 static K_KERNEL_STACK_DEFINE(thread_stack, MESH_WORKQ_STACK_SIZE);
78 
79 #if defined(CONFIG_BT_MESH_WORKQ_MESH)
80 #define MESH_WORKQ &bt_mesh_workq
81 #else /* CONFIG_BT_MESH_WORKQ_SYS */
82 #define MESH_WORKQ &k_sys_work_q
83 #endif /* CONFIG_BT_MESH_WORKQ_MESH */
84 
85 static struct bt_mesh_ext_adv advs[] = {
86 	[0] = {
87 		.tags = (
88 #if !defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
89 			BT_MESH_ADV_TAG_BIT_FRIEND |
90 #endif
91 #if !defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
92 			BT_MESH_ADV_TAG_BIT_PROXY |
93 #endif /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
94 #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET)
95 			BT_MESH_ADV_TAG_BIT_RELAY |
96 #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */
97 #if defined(CONFIG_BT_MESH_PB_ADV)
98 			BT_MESH_ADV_TAG_BIT_PROV |
99 #endif /* CONFIG_BT_MESH_PB_ADV */
100 			BT_MESH_ADV_TAG_BIT_LOCAL
101 		),
102 		.work = Z_WORK_INITIALIZER(send_pending_adv),
103 	},
104 #if CONFIG_BT_MESH_RELAY_ADV_SETS
105 	[1 ... CONFIG_BT_MESH_RELAY_ADV_SETS] = {
106 		.tags = (
107 #if (defined(CONFIG_BT_MESH_RELAY) || defined(CONFIG_BT_MESH_BRG_CFG_SRV))
108 			BT_MESH_ADV_TAG_BIT_RELAY |
109 #endif /* CONFIG_BT_MESH_RELAY || CONFIG_BT_MESH_BRG_CFG_SRV */
110 #if defined(CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS)
111 			BT_MESH_ADV_TAG_BIT_PROV |
112 #endif /* CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS */
113 		0),
114 		.work = Z_WORK_INITIALIZER(send_pending_adv),
115 	},
116 #endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */
117 #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
118 	{
119 		.tags = BT_MESH_ADV_TAG_BIT_FRIEND,
120 		.work = Z_WORK_INITIALIZER(send_pending_adv),
121 	},
122 #endif /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */
123 #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
124 	{
125 		.tags = BT_MESH_ADV_TAG_BIT_PROXY,
126 		.work = Z_WORK_INITIALIZER(send_pending_adv),
127 	},
128 #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
129 };
130 
131 BUILD_ASSERT(ARRAY_SIZE(advs) <= CONFIG_BT_EXT_ADV_MAX_ADV_SET,
132 	     "Insufficient adv instances");
133 
relay_adv_get(void)134 static inline struct bt_mesh_ext_adv *relay_adv_get(void)
135 {
136 	if (!!(CONFIG_BT_MESH_RELAY_ADV_SETS)) {
137 		return &advs[1];
138 	} else {
139 		return &advs[0];
140 	}
141 }
142 
gatt_adv_get(void)143 static inline struct bt_mesh_ext_adv *gatt_adv_get(void)
144 {
145 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)) {
146 		return &advs[ARRAY_SIZE(advs) - 1];
147 	} else {
148 		return &advs[0];
149 	}
150 }
151 
adv_start(struct bt_mesh_ext_adv * ext_adv,const struct bt_le_adv_param * param,struct bt_le_ext_adv_start_param * start,const struct bt_data * ad,size_t ad_len,const struct bt_data * sd,size_t sd_len)152 static int adv_start(struct bt_mesh_ext_adv *ext_adv,
153 		     const struct bt_le_adv_param *param,
154 		     struct bt_le_ext_adv_start_param *start,
155 		     const struct bt_data *ad, size_t ad_len,
156 		     const struct bt_data *sd, size_t sd_len)
157 {
158 	int err;
159 
160 	if (!ext_adv->instance) {
161 		LOG_ERR("Mesh advertiser not enabled");
162 		return -ENODEV;
163 	}
164 
165 	if (atomic_test_and_set_bit(ext_adv->flags, ADV_FLAG_ACTIVE)) {
166 		LOG_ERR("Advertiser is busy");
167 		return -EBUSY;
168 	}
169 
170 	if (atomic_test_bit(ext_adv->flags, ADV_FLAG_UPDATE_PARAMS)) {
171 		err = bt_le_ext_adv_update_param(ext_adv->instance, param);
172 		if (err) {
173 			LOG_ERR("Failed updating adv params: %d", err);
174 			atomic_clear_bit(ext_adv->flags, ADV_FLAG_ACTIVE);
175 			return err;
176 		}
177 
178 		atomic_set_bit_to(ext_adv->flags, ADV_FLAG_UPDATE_PARAMS,
179 				  param != &ext_adv->adv_param);
180 	}
181 
182 	err = bt_le_ext_adv_set_data(ext_adv->instance, ad, ad_len, sd, sd_len);
183 	if (err) {
184 		LOG_ERR("Failed setting adv data: %d", err);
185 		atomic_clear_bit(ext_adv->flags, ADV_FLAG_ACTIVE);
186 		return err;
187 	}
188 
189 	ext_adv->timestamp = k_uptime_get_32();
190 
191 	err = bt_le_ext_adv_start(ext_adv->instance, start);
192 	if (err) {
193 		LOG_ERR("Advertising failed: err %d", err);
194 		atomic_clear_bit(ext_adv->flags, ADV_FLAG_ACTIVE);
195 	}
196 
197 	return err;
198 }
199 
bt_data_send(struct bt_mesh_ext_adv * ext_adv,uint8_t num_events,uint16_t adv_interval,const struct bt_data * ad,size_t ad_len)200 static int bt_data_send(struct bt_mesh_ext_adv *ext_adv, uint8_t num_events, uint16_t adv_interval,
201 			const struct bt_data *ad, size_t ad_len)
202 {
203 	struct bt_le_ext_adv_start_param start = {
204 		.num_events = num_events,
205 	};
206 
207 	adv_interval = MAX(ADV_INT_FAST_MS, adv_interval);
208 
209 	/* Only update advertising parameters if they're different */
210 	if (ext_adv->adv_param.interval_min != BT_MESH_ADV_SCAN_UNIT(adv_interval)) {
211 		ext_adv->adv_param.interval_min = BT_MESH_ADV_SCAN_UNIT(adv_interval);
212 		ext_adv->adv_param.interval_max = ext_adv->adv_param.interval_min;
213 		atomic_set_bit(ext_adv->flags, ADV_FLAG_UPDATE_PARAMS);
214 	}
215 
216 	return adv_start(ext_adv, &ext_adv->adv_param, &start, ad, ad_len, NULL, 0);
217 }
218 
adv_send(struct bt_mesh_ext_adv * ext_adv,struct bt_mesh_adv * adv)219 static int adv_send(struct bt_mesh_ext_adv *ext_adv, struct bt_mesh_adv *adv)
220 {
221 	uint8_t num_events = BT_MESH_TRANSMIT_COUNT(adv->ctx.xmit) + 1;
222 	uint16_t duration, adv_int;
223 	struct bt_data ad;
224 	int err;
225 
226 	adv_int = BT_MESH_TRANSMIT_INT(adv->ctx.xmit);
227 	/* Upper boundary estimate: */
228 	duration = num_events * (adv_int + 10);
229 
230 	LOG_DBG("type %u len %u: %s", adv->ctx.type,
231 	       adv->b.len, bt_hex(adv->b.data, adv->b.len));
232 	LOG_DBG("count %u interval %ums duration %ums",
233 	       num_events, adv_int, duration);
234 
235 	ad.type = bt_mesh_adv_type[adv->ctx.type];
236 	ad.data_len = adv->b.len;
237 	ad.data = adv->b.data;
238 
239 	err = bt_data_send(ext_adv, num_events, adv_int, &ad, 1);
240 	if (!err) {
241 		ext_adv->adv = bt_mesh_adv_ref(adv);
242 	}
243 
244 	bt_mesh_adv_send_start(duration, err, &adv->ctx);
245 
246 	return err;
247 }
248 
stop_proxy_adv(struct bt_mesh_ext_adv * ext_adv)249 static int stop_proxy_adv(struct bt_mesh_ext_adv *ext_adv)
250 {
251 	int err;
252 
253 	if (atomic_test_bit(ext_adv->flags, ADV_FLAG_PROXY)) {
254 		err = bt_le_ext_adv_stop(ext_adv->instance);
255 		if (err) {
256 			LOG_ERR("Failed to stop proxy advertising: %d", err);
257 			return err;
258 		}
259 
260 		atomic_clear_bit(ext_adv->flags, ADV_FLAG_PROXY);
261 		atomic_clear_bit(ext_adv->flags, ADV_FLAG_ACTIVE);
262 	}
263 
264 	return 0;
265 }
266 
adv_queue_send_process(struct bt_mesh_ext_adv * ext_adv)267 static int adv_queue_send_process(struct bt_mesh_ext_adv *ext_adv)
268 {
269 	struct bt_mesh_adv *adv;
270 	int err = -ENOENT;
271 
272 	while ((adv = bt_mesh_adv_get_by_tag(ext_adv->tags, K_NO_WAIT))) {
273 		/* busy == 0 means this was canceled */
274 		if (!adv->ctx.busy) {
275 			bt_mesh_adv_unref(adv);
276 			continue;
277 		}
278 
279 		if (stop_proxy_adv(ext_adv)) {
280 			LOG_WRN("Advertising %p canceled due to proxy adv failed to stop", adv);
281 			bt_mesh_adv_send_start(0, -ECANCELED, &adv->ctx);
282 			bt_mesh_adv_unref(adv);
283 			continue;
284 		}
285 
286 		adv->ctx.busy = 0U;
287 		err = adv_send(ext_adv, adv);
288 
289 		bt_mesh_adv_unref(adv);
290 
291 		if (!err) {
292 			return 0; /* Wait for advertising to finish */
293 		}
294 	}
295 
296 	return err;
297 }
298 
start_proxy_sol_or_proxy_adv(struct bt_mesh_ext_adv * ext_adv)299 static void start_proxy_sol_or_proxy_adv(struct bt_mesh_ext_adv *ext_adv)
300 {
301 	if (ext_adv->instance == NULL) {
302 		LOG_DBG("Advertiser is suspended or deleted");
303 		return;
304 	}
305 
306 	if (!(ext_adv->tags & BT_MESH_ADV_TAG_BIT_PROXY)) {
307 		return;
308 	}
309 
310 	if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION)) {
311 		if (stop_proxy_adv(ext_adv)) {
312 			return;
313 		}
314 
315 		if (!bt_mesh_sol_send()) {
316 			return;
317 		}
318 	}
319 
320 	if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER)) {
321 		if (stop_proxy_adv(ext_adv)) {
322 			return;
323 		}
324 
325 		if (!atomic_test_and_set_bit(ext_adv->flags, ADV_FLAG_PROXY)) {
326 			if (bt_mesh_adv_gatt_send()) {
327 				atomic_clear_bit(ext_adv->flags, ADV_FLAG_PROXY);
328 				return;
329 			}
330 		}
331 	}
332 }
333 
send_pending_adv(struct k_work * work)334 static void send_pending_adv(struct k_work *work)
335 {
336 	static const char * const adv_tag_to_str[] = {
337 		[BT_MESH_ADV_TAG_LOCAL]  = "local",
338 		[BT_MESH_ADV_TAG_RELAY]  = "relay",
339 		[BT_MESH_ADV_TAG_PROXY]  = "proxy",
340 		[BT_MESH_ADV_TAG_FRIEND] = "friend",
341 		[BT_MESH_ADV_TAG_PROV]   = "prov",
342 	};
343 	struct bt_mesh_ext_adv *ext_adv;
344 	int err;
345 
346 	ext_adv = CONTAINER_OF(work, struct bt_mesh_ext_adv, work);
347 
348 	if (atomic_test_bit(ext_adv->flags, ADV_FLAG_SUSPENDING)) {
349 		LOG_DBG("Advertiser is suspending");
350 		return;
351 	}
352 
353 	if (atomic_test_and_clear_bit(ext_adv->flags, ADV_FLAG_SENT)) {
354 		LOG_DBG("Advertising stopped after %u ms for %s adv",
355 			k_uptime_get_32() - ext_adv->timestamp,
356 			ext_adv->adv ? adv_tag_to_str[ext_adv->adv->ctx.tag]
357 				     : adv_tag_to_str[BT_MESH_ADV_TAG_PROXY]);
358 
359 		atomic_clear_bit(ext_adv->flags, ADV_FLAG_ACTIVE);
360 		atomic_clear_bit(ext_adv->flags, ADV_FLAG_PROXY);
361 
362 		if (ext_adv->adv) {
363 			struct bt_mesh_adv_ctx ctx = ext_adv->adv->ctx;
364 
365 			ext_adv->adv->ctx.started = 0;
366 			bt_mesh_adv_unref(ext_adv->adv);
367 			bt_mesh_adv_send_end(0, &ctx);
368 
369 			ext_adv->adv = NULL;
370 		}
371 	}
372 
373 	err = adv_queue_send_process(ext_adv);
374 	if (!err) {
375 		return;
376 	}
377 
378 	start_proxy_sol_or_proxy_adv(ext_adv);
379 }
380 
schedule_send(struct bt_mesh_ext_adv * ext_adv)381 static bool schedule_send(struct bt_mesh_ext_adv *ext_adv)
382 {
383 	if (atomic_test_bit(ext_adv->flags, ADV_FLAG_ACTIVE)) {
384 		/* We don't need to resubmit the `send_pending_adv` work if the mesh advertiser
385 		 * is sending a mesh packet. The `send_pending_adv` work is resubmitted when the
386 		 * current advertising is finished, which is done through the `adv_sent` callback.
387 		 *
388 		 * The proxy advertisement in turns doesn't timeout or stop quickly and has less
389 		 * priority than regular mesh messages, thus needs to be stopped immeditaly.
390 		 */
391 		if (!atomic_test_bit(ext_adv->flags, ADV_FLAG_PROXY)) {
392 			return false;
393 		}
394 	}
395 
396 	bt_mesh_wq_submit(&ext_adv->work);
397 
398 	return true;
399 }
400 
bt_mesh_adv_gatt_update(void)401 void bt_mesh_adv_gatt_update(void)
402 {
403 	(void)schedule_send(gatt_adv_get());
404 }
405 
bt_mesh_adv_local_ready(void)406 void bt_mesh_adv_local_ready(void)
407 {
408 	(void)schedule_send(advs);
409 }
410 
bt_mesh_adv_relay_ready(void)411 void bt_mesh_adv_relay_ready(void)
412 {
413 	struct bt_mesh_ext_adv *ext_adv = relay_adv_get();
414 
415 	for (int i = 0; i < CONFIG_BT_MESH_RELAY_ADV_SETS; i++) {
416 		if (schedule_send(&ext_adv[i])) {
417 			return;
418 		}
419 	}
420 
421 	/* Use the main adv set for the sending of relay messages. */
422 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) ||
423 	    CONFIG_BT_MESH_RELAY_ADV_SETS == 0) {
424 		(void)schedule_send(advs);
425 	}
426 }
427 
bt_mesh_adv_friend_ready(void)428 void bt_mesh_adv_friend_ready(void)
429 {
430 	if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) {
431 		schedule_send(&advs[1 + CONFIG_BT_MESH_RELAY_ADV_SETS]);
432 	} else {
433 		schedule_send(&advs[0]);
434 	}
435 }
436 
adv_sent(struct bt_mesh_ext_adv * ext_adv)437 static void adv_sent(struct bt_mesh_ext_adv *ext_adv)
438 {
439 	atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);
440 
441 	bt_mesh_wq_submit(&ext_adv->work);
442 }
443 
bt_mesh_adv_terminate(struct bt_mesh_adv * adv)444 int bt_mesh_adv_terminate(struct bt_mesh_adv *adv)
445 {
446 	int err;
447 
448 	for (int i = 0; i < ARRAY_SIZE(advs); i++) {
449 		struct bt_mesh_ext_adv *ext_adv = &advs[i];
450 
451 		if (ext_adv->adv != adv) {
452 			continue;
453 		}
454 
455 		if (!atomic_test_bit(ext_adv->flags, ADV_FLAG_ACTIVE)) {
456 			return 0;
457 		}
458 
459 		err = bt_le_ext_adv_stop(ext_adv->instance);
460 		if (err) {
461 			LOG_ERR("Failed to stop adv %d", err);
462 			return err;
463 		}
464 
465 		/* Do not call `cb:end`, since this user action */
466 		adv->ctx.cb = NULL;
467 
468 		adv_sent(ext_adv);
469 
470 		return 0;
471 	}
472 
473 	return -EINVAL;
474 }
475 
bt_mesh_adv_init(void)476 void bt_mesh_adv_init(void)
477 {
478 	struct bt_le_adv_param adv_param = {
479 		.id = BT_ID_DEFAULT,
480 		.interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
481 		.interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
482 #if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
483 		.options = BT_LE_ADV_OPT_USE_IDENTITY,
484 #endif
485 	};
486 
487 	for (int i = 0; i < ARRAY_SIZE(advs); i++) {
488 		(void)memcpy(&advs[i].adv_param, &adv_param, sizeof(adv_param));
489 	}
490 
491 	if (IS_ENABLED(CONFIG_BT_MESH_WORKQ_MESH)) {
492 		k_work_queue_init(&bt_mesh_workq);
493 		k_work_queue_start(&bt_mesh_workq, thread_stack, MESH_WORKQ_STACK_SIZE,
494 				   K_PRIO_COOP(MESH_WORKQ_PRIORITY), NULL);
495 		k_thread_name_set(&bt_mesh_workq.thread, "BT MESH WQ");
496 	}
497 }
498 
adv_instance_find(struct bt_le_ext_adv * instance)499 static struct bt_mesh_ext_adv *adv_instance_find(struct bt_le_ext_adv *instance)
500 {
501 	for (int i = 0; i < ARRAY_SIZE(advs); i++) {
502 		if (advs[i].instance == instance) {
503 			return &advs[i];
504 		}
505 	}
506 
507 	return NULL;
508 }
509 
ext_adv_set_sent(struct bt_le_ext_adv * instance,struct bt_le_ext_adv_sent_info * info)510 static void ext_adv_set_sent(struct bt_le_ext_adv *instance, struct bt_le_ext_adv_sent_info *info)
511 {
512 	struct bt_mesh_ext_adv *ext_adv = adv_instance_find(instance);
513 
514 	if (!ext_adv) {
515 		LOG_WRN("Unexpected adv instance");
516 		return;
517 	}
518 
519 	if (!atomic_test_bit(ext_adv->flags, ADV_FLAG_ACTIVE)) {
520 		LOG_DBG("Advertiser %p ADV_FLAG_ACTIVE not set", ext_adv);
521 		return;
522 	}
523 
524 	adv_sent(ext_adv);
525 }
526 
bt_mesh_adv_enable(void)527 int bt_mesh_adv_enable(void)
528 {
529 	int err;
530 
531 	static const struct bt_le_ext_adv_cb adv_cb = {
532 		.sent = ext_adv_set_sent,
533 	};
534 
535 	if (advs[0].instance) {
536 		/* Already initialized */
537 		return 0;
538 	}
539 
540 	for (int i = 0; i < ARRAY_SIZE(advs); i++) {
541 		err = bt_le_ext_adv_create(&advs[i].adv_param, &adv_cb, &advs[i].instance);
542 		if (err) {
543 			return err;
544 		}
545 	}
546 
547 	return 0;
548 }
549 
bt_mesh_adv_disable(void)550 int bt_mesh_adv_disable(void)
551 {
552 	struct k_work_sync sync;
553 	int err;
554 
555 	for (int i = 0; i < ARRAY_SIZE(advs); i++) {
556 		atomic_set_bit(advs[i].flags, ADV_FLAG_SUSPENDING);
557 
558 		if (k_current_get() != k_work_queue_thread_get(MESH_WORKQ) ||
559 		    (k_work_busy_get(&advs[i].work) & K_WORK_RUNNING) == 0) {
560 			k_work_flush(&advs[i].work, &sync);
561 		}
562 
563 		err = bt_le_ext_adv_stop(advs[i].instance);
564 		if (err) {
565 			LOG_ERR("Failed to stop adv %d", err);
566 			return err;
567 		}
568 
569 		err = bt_le_ext_adv_delete(advs[i].instance);
570 		if (err) {
571 			LOG_ERR("Failed to delete adv %d", err);
572 			return err;
573 		}
574 
575 		advs[i].instance = NULL;
576 
577 		atomic_clear_bit(advs[i].flags, ADV_FLAG_SUSPENDING);
578 
579 		/* `adv_sent` is called to finish transmission of an adv buffer that was pushed to
580 		 * the host before the advertiser was stopped, but did not finish.
581 		 */
582 		adv_sent(&advs[i]);
583 	}
584 
585 	return 0;
586 }
587 
bt_mesh_adv_gatt_start(const struct bt_le_adv_param * param,int32_t duration,const struct bt_data * ad,size_t ad_len,const struct bt_data * sd,size_t sd_len)588 int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param,
589 			   int32_t duration,
590 			   const struct bt_data *ad, size_t ad_len,
591 			   const struct bt_data *sd, size_t sd_len)
592 {
593 	struct bt_mesh_ext_adv *ext_adv = gatt_adv_get();
594 	struct bt_le_ext_adv_start_param start = {
595 		/* Timeout is set in 10 ms steps, with 0 indicating "forever" */
596 		.timeout = (duration == SYS_FOREVER_MS) ? 0 : MAX(1, duration / 10),
597 	};
598 
599 	LOG_DBG("Start advertising %d ms", duration);
600 
601 	atomic_set_bit(ext_adv->flags, ADV_FLAG_UPDATE_PARAMS);
602 
603 	return adv_start(ext_adv, param, &start, ad, ad_len, sd, sd_len);
604 }
605 
bt_mesh_adv_bt_data_send(uint8_t num_events,uint16_t adv_interval,const struct bt_data * ad,size_t ad_len)606 int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
607 			     const struct bt_data *ad, size_t ad_len)
608 {
609 	return bt_data_send(advs, num_events, adv_interval, ad, ad_len);
610 }
611 
bt_mesh_wq_submit(struct k_work * work)612 int bt_mesh_wq_submit(struct k_work *work)
613 {
614 	return k_work_submit_to_queue(MESH_WORKQ, work);
615 }
616