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 "adv.h"
22 #include "net.h"
23 #include "proxy.h"
24 #include "solicitation.h"
25
26 #define LOG_LEVEL CONFIG_BT_MESH_ADV_LOG_LEVEL
27 #include <zephyr/logging/log.h>
28 LOG_MODULE_REGISTER(bt_mesh_adv_ext);
29
30 /* Convert from ms to 0.625ms units */
31 #define ADV_INT_FAST_MS 20
32
33 #ifndef CONFIG_BT_MESH_RELAY_ADV_SETS
34 #define CONFIG_BT_MESH_RELAY_ADV_SETS 0
35 #endif
36
37 enum {
38 /** Controller is currently advertising */
39 ADV_FLAG_ACTIVE,
40 /** Advertising sending completed */
41 ADV_FLAG_SENT,
42 /** Currently performing proxy advertising */
43 ADV_FLAG_PROXY,
44 /** The proxy has been start, but maybe pending. */
45 ADV_FLAG_PROXY_START,
46 /** The send-call has been scheduled. */
47 ADV_FLAG_SCHEDULED,
48 /** The send-call has been pending. */
49 ADV_FLAG_SCHEDULE_PENDING,
50 /** Custom adv params have been set, we need to update the parameters on
51 * the next send.
52 */
53 ADV_FLAG_UPDATE_PARAMS,
54
55 /* Number of adv flags. */
56 ADV_FLAGS_NUM
57 };
58
59 struct bt_mesh_ext_adv {
60 uint8_t tag;
61 ATOMIC_DEFINE(flags, ADV_FLAGS_NUM);
62 struct bt_le_ext_adv *instance;
63 struct net_buf *buf;
64 uint64_t timestamp;
65 struct k_work_delayable work;
66 struct bt_le_adv_param adv_param;
67 };
68
69 static void send_pending_adv(struct k_work *work);
70 static bool schedule_send(struct bt_mesh_ext_adv *adv);
71
72 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = {
73 .tag = (
74 #if !defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
75 BT_MESH_FRIEND_ADV |
76 #endif
77 #if !defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
78 BT_MESH_PROXY_ADV |
79 #endif /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
80 #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET)
81 BT_MESH_RELAY_ADV |
82 #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */
83 BT_MESH_LOCAL_ADV),
84
85 .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv),
86 };
87
88 #if CONFIG_BT_MESH_RELAY_ADV_SETS
89 static STRUCT_SECTION_ITERABLE_ARRAY(bt_mesh_ext_adv, adv_relay, CONFIG_BT_MESH_RELAY_ADV_SETS) = {
90 [0 ... CONFIG_BT_MESH_RELAY_ADV_SETS - 1] = {
91 .tag = BT_MESH_RELAY_ADV,
92 .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv),
93 }
94 };
95 #endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */
96
97 #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
98 #define ADV_EXT_FRIEND 1
99 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = {
100 .tag = BT_MESH_FRIEND_ADV,
101 .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv),
102 };
103 #else /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */
104 #define ADV_EXT_FRIEND 0
105 #endif /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */
106
107 #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
108 #define ADV_EXT_GATT 1
109 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_gatt) = {
110 .tag = BT_MESH_PROXY_ADV,
111 .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv),
112 };
113 #else /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
114 #define ADV_EXT_GATT 0
115 #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
116
117 #define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_RELAY_ADV_SETS + ADV_EXT_FRIEND + ADV_EXT_GATT)
118
119 BUILD_ASSERT(CONFIG_BT_EXT_ADV_MAX_ADV_SET >= BT_MESH_ADV_COUNT,
120 "Insufficient adv instances");
121
relay_adv_get(void)122 static inline struct bt_mesh_ext_adv *relay_adv_get(void)
123 {
124 #if CONFIG_BT_MESH_RELAY_ADV_SETS
125 return adv_relay;
126 #else /* !CONFIG_BT_MESH_RELAY_ADV_SETS */
127 return &adv_main;
128 #endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */
129 }
130
gatt_adv_get(void)131 static inline struct bt_mesh_ext_adv *gatt_adv_get(void)
132 {
133 #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
134 return &adv_gatt;
135 #else /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
136 return &adv_main;
137 #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
138 }
139
adv_start(struct bt_mesh_ext_adv * 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)140 static int adv_start(struct bt_mesh_ext_adv *adv,
141 const struct bt_le_adv_param *param,
142 struct bt_le_ext_adv_start_param *start,
143 const struct bt_data *ad, size_t ad_len,
144 const struct bt_data *sd, size_t sd_len)
145 {
146 int err;
147
148 if (!adv->instance) {
149 LOG_ERR("Mesh advertiser not enabled");
150 return -ENODEV;
151 }
152
153 if (atomic_test_and_set_bit(adv->flags, ADV_FLAG_ACTIVE)) {
154 LOG_ERR("Advertiser is busy");
155 return -EBUSY;
156 }
157
158 if (atomic_test_bit(adv->flags, ADV_FLAG_UPDATE_PARAMS)) {
159 err = bt_le_ext_adv_update_param(adv->instance, param);
160 if (err) {
161 LOG_ERR("Failed updating adv params: %d", err);
162 atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
163 return err;
164 }
165
166 atomic_set_bit_to(adv->flags, ADV_FLAG_UPDATE_PARAMS,
167 param != &adv->adv_param);
168 }
169
170 err = bt_le_ext_adv_set_data(adv->instance, ad, ad_len, sd, sd_len);
171 if (err) {
172 LOG_ERR("Failed setting adv data: %d", err);
173 atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
174 return err;
175 }
176
177 adv->timestamp = k_uptime_get();
178
179 err = bt_le_ext_adv_start(adv->instance, start);
180 if (err) {
181 LOG_ERR("Advertising failed: err %d", err);
182 atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
183 }
184
185 return err;
186 }
187
bt_data_send(struct bt_mesh_ext_adv * adv,uint8_t num_events,uint16_t adv_interval,const struct bt_data * ad,size_t ad_len)188 static int bt_data_send(struct bt_mesh_ext_adv *adv, uint8_t num_events, uint16_t adv_interval,
189 const struct bt_data *ad, size_t ad_len)
190 {
191 struct bt_le_ext_adv_start_param start = {
192 .num_events = num_events,
193 };
194
195 adv_interval = MAX(ADV_INT_FAST_MS, adv_interval);
196
197 /* Only update advertising parameters if they're different */
198 if (adv->adv_param.interval_min != BT_MESH_ADV_SCAN_UNIT(adv_interval)) {
199 adv->adv_param.interval_min = BT_MESH_ADV_SCAN_UNIT(adv_interval);
200 adv->adv_param.interval_max = adv->adv_param.interval_min;
201 atomic_set_bit(adv->flags, ADV_FLAG_UPDATE_PARAMS);
202 }
203
204 return adv_start(adv, &adv->adv_param, &start, ad, ad_len, NULL, 0);
205 }
206
buf_send(struct bt_mesh_ext_adv * adv,struct net_buf * buf)207 static int buf_send(struct bt_mesh_ext_adv *adv, struct net_buf *buf)
208 {
209 uint8_t num_events = BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1;
210 uint16_t duration, adv_int;
211 struct bt_data ad;
212 int err;
213
214 adv_int = BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit);
215 /* Upper boundary estimate: */
216 duration = num_events * (adv_int + 10);
217
218 LOG_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type,
219 buf->len, bt_hex(buf->data, buf->len));
220 LOG_DBG("count %u interval %ums duration %ums",
221 num_events, adv_int, duration);
222
223 ad.type = bt_mesh_adv_type[BT_MESH_ADV(buf)->type];
224 ad.data_len = buf->len;
225 ad.data = buf->data;
226
227 err = bt_data_send(adv, num_events, adv_int, &ad, 1);
228 if (!err) {
229 adv->buf = net_buf_ref(buf);
230 }
231
232 bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf));
233
234 return err;
235 }
236
adv_tag_to_str(enum bt_mesh_adv_tag tag)237 static const char *adv_tag_to_str(enum bt_mesh_adv_tag tag)
238 {
239 if (tag & BT_MESH_LOCAL_ADV) {
240 return "local adv";
241 } else if (tag & BT_MESH_PROXY_ADV) {
242 return "proxy adv";
243 } else if (tag & BT_MESH_RELAY_ADV) {
244 return "relay adv";
245 } else if (tag & BT_MESH_FRIEND_ADV) {
246 return "friend adv";
247 } else {
248 return "(unknown tag)";
249 }
250 }
251
send_pending_adv(struct k_work * work)252 static void send_pending_adv(struct k_work *work)
253 {
254 struct bt_mesh_ext_adv *adv;
255 struct net_buf *buf;
256 int err;
257
258 adv = CONTAINER_OF(work, struct bt_mesh_ext_adv, work.work);
259
260 if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_SENT)) {
261 /* Calling k_uptime_delta on a timestamp moves it to the current time.
262 * This is essential here, as schedule_send() uses the end of the event
263 * as a reference to avoid sending the next advertisement too soon.
264 */
265 int64_t duration = k_uptime_delta(&adv->timestamp);
266
267 LOG_DBG("Advertising stopped after %u ms for (%u) %s", (uint32_t)duration, adv->tag,
268 adv_tag_to_str(adv->tag));
269
270 atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
271 atomic_clear_bit(adv->flags, ADV_FLAG_PROXY);
272 atomic_clear_bit(adv->flags, ADV_FLAG_PROXY_START);
273
274 if (adv->buf) {
275 net_buf_unref(adv->buf);
276 adv->buf = NULL;
277 }
278
279 (void)schedule_send(adv);
280
281 return;
282 }
283
284 atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULED);
285
286 while ((buf = bt_mesh_adv_buf_get_by_tag(adv->tag, K_NO_WAIT))) {
287 /* busy == 0 means this was canceled */
288 if (!BT_MESH_ADV(buf)->busy) {
289 net_buf_unref(buf);
290 continue;
291 }
292
293 BT_MESH_ADV(buf)->busy = 0U;
294 err = buf_send(adv, buf);
295
296 net_buf_unref(buf);
297
298 if (!err) {
299 return; /* Wait for advertising to finish */
300 }
301 }
302
303 if (!IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) ||
304 !(adv->tag & BT_MESH_PROXY_ADV)) {
305 return;
306 }
307
308 if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) &&
309 !bt_mesh_sol_send()) {
310 return;
311 }
312
313 atomic_set_bit(adv->flags, ADV_FLAG_PROXY_START);
314
315 if (!bt_mesh_adv_gatt_send()) {
316 atomic_set_bit(adv->flags, ADV_FLAG_PROXY);
317 }
318
319 if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING)) {
320 schedule_send(adv);
321 }
322 }
323
schedule_send(struct bt_mesh_ext_adv * adv)324 static bool schedule_send(struct bt_mesh_ext_adv *adv)
325 {
326 uint64_t timestamp;
327 int64_t delta;
328
329 timestamp = adv->timestamp;
330
331 if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_PROXY)) {
332 atomic_clear_bit(adv->flags, ADV_FLAG_PROXY_START);
333 (void)bt_le_ext_adv_stop(adv->instance);
334
335 atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
336 }
337
338 if (atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE)) {
339 atomic_set_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING);
340 return false;
341 } else if (atomic_test_and_set_bit(adv->flags, ADV_FLAG_SCHEDULED)) {
342 return false;
343 }
344
345 atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING);
346
347 if ((IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && adv->tag & BT_MESH_FRIEND_ADV) ||
348 (CONFIG_BT_MESH_RELAY_ADV_SETS > 0 && adv->tag == BT_MESH_RELAY_ADV)) {
349 k_work_reschedule(&adv->work, K_NO_WAIT);
350 } else {
351 /* The controller will send the next advertisement immediately.
352 * Introduce a delay here to avoid sending the next mesh packet closer
353 * to the previous packet than what's permitted by the specification.
354 */
355 delta = k_uptime_delta(×tamp);
356 k_work_reschedule(&adv->work, K_MSEC(ADV_INT_FAST_MS - delta));
357 }
358
359 return true;
360 }
361
bt_mesh_adv_gatt_update(void)362 void bt_mesh_adv_gatt_update(void)
363 {
364 (void)schedule_send(gatt_adv_get());
365 }
366
bt_mesh_adv_buf_local_ready(void)367 void bt_mesh_adv_buf_local_ready(void)
368 {
369 (void)schedule_send(&adv_main);
370 }
371
bt_mesh_adv_buf_relay_ready(void)372 void bt_mesh_adv_buf_relay_ready(void)
373 {
374 struct bt_mesh_ext_adv *adv = relay_adv_get();
375
376 for (int i = 0; i < CONFIG_BT_MESH_RELAY_ADV_SETS; i++) {
377 if (schedule_send(&adv[i])) {
378 return;
379 }
380 }
381
382 /* Attempt to use the main adv set for the sending of relay messages. */
383 if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET)) {
384 (void)schedule_send(&adv_main);
385 }
386 }
387
bt_mesh_adv_buf_friend_ready(void)388 void bt_mesh_adv_buf_friend_ready(void)
389 {
390 #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)
391 (void)schedule_send(&adv_friend);
392 #endif
393 }
394
bt_mesh_adv_init(void)395 void bt_mesh_adv_init(void)
396 {
397 struct bt_le_adv_param adv_param = {
398 .id = BT_ID_DEFAULT,
399 .interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
400 .interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
401 #if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
402 .options = BT_LE_ADV_OPT_USE_IDENTITY,
403 #endif
404 };
405 STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) {
406 (void)memcpy(&adv->adv_param, &adv_param, sizeof(adv_param));
407 }
408 }
409
adv_instance_find(struct bt_le_ext_adv * instance)410 static struct bt_mesh_ext_adv *adv_instance_find(struct bt_le_ext_adv *instance)
411 {
412 STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) {
413 if (adv->instance == instance) {
414 return adv;
415 }
416 }
417
418 return NULL;
419 }
420
adv_sent(struct bt_le_ext_adv * instance,struct bt_le_ext_adv_sent_info * info)421 static void adv_sent(struct bt_le_ext_adv *instance,
422 struct bt_le_ext_adv_sent_info *info)
423 {
424 struct bt_mesh_ext_adv *adv = adv_instance_find(instance);
425
426 if (!adv) {
427 LOG_WRN("Unexpected adv instance");
428 return;
429 }
430
431 if (!atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE)) {
432 return;
433 }
434
435 atomic_set_bit(adv->flags, ADV_FLAG_SENT);
436
437 k_work_submit(&adv->work.work);
438 }
439
440 #if defined(CONFIG_BT_MESH_GATT_SERVER)
connected(struct bt_le_ext_adv * instance,struct bt_le_ext_adv_connected_info * info)441 static void connected(struct bt_le_ext_adv *instance,
442 struct bt_le_ext_adv_connected_info *info)
443 {
444 struct bt_mesh_ext_adv *adv = gatt_adv_get();
445
446 if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_PROXY_START)) {
447 atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
448 (void)schedule_send(adv);
449 }
450 }
451 #endif /* CONFIG_BT_MESH_GATT_SERVER */
452
bt_mesh_adv_enable(void)453 int bt_mesh_adv_enable(void)
454 {
455 int err;
456
457 static const struct bt_le_ext_adv_cb adv_cb = {
458 .sent = adv_sent,
459 #if defined(CONFIG_BT_MESH_GATT_SERVER)
460 .connected = connected,
461 #endif /* CONFIG_BT_MESH_GATT_SERVER */
462 };
463
464 if (adv_main.instance) {
465 /* Already initialized */
466 return 0;
467 }
468
469
470 STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) {
471 err = bt_le_ext_adv_create(&adv->adv_param, &adv_cb,
472 &adv->instance);
473 if (err) {
474 return err;
475 }
476 }
477
478 return 0;
479 }
480
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)481 int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param,
482 int32_t duration,
483 const struct bt_data *ad, size_t ad_len,
484 const struct bt_data *sd, size_t sd_len)
485 {
486 struct bt_mesh_ext_adv *adv = gatt_adv_get();
487 struct bt_le_ext_adv_start_param start = {
488 /* Timeout is set in 10 ms steps, with 0 indicating "forever" */
489 .timeout = (duration == SYS_FOREVER_MS) ? 0 : MAX(1, duration / 10),
490 };
491
492 LOG_DBG("Start advertising %d ms", duration);
493
494 atomic_set_bit(adv->flags, ADV_FLAG_UPDATE_PARAMS);
495
496 return adv_start(adv, param, &start, ad, ad_len, sd, sd_len);
497 }
498
bt_mesh_adv_bt_data_send(uint8_t num_events,uint16_t adv_interval,const struct bt_data * ad,size_t ad_len)499 int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
500 const struct bt_data *ad, size_t ad_len)
501 {
502 return bt_data_send(&adv_main, num_events, adv_interval, ad, ad_len);
503 }
504