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