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 "host/hci_core.h"
21 
22 #include "net.h"
23 #include "foundation.h"
24 #include "beacon.h"
25 #include "prov.h"
26 #include "solicitation.h"
27 
28 #define LOG_LEVEL CONFIG_BT_MESH_ADV_LOG_LEVEL
29 #include <zephyr/logging/log.h>
30 LOG_MODULE_REGISTER(bt_mesh_adv_legacy);
31 
32 /* Pre-5.0 controllers enforce a minimum interval of 100ms
33  * whereas 5.0+ controllers can go down to 20ms.
34  */
35 #define ADV_INT_DEFAULT_MS 100
36 #define ADV_INT_FAST_MS    20
37 
38 static struct k_thread adv_thread_data;
39 static K_KERNEL_STACK_DEFINE(adv_thread_stack, CONFIG_BT_MESH_ADV_STACK_SIZE);
40 static int32_t adv_timeout;
41 
is_mesh_suspended(void)42 static bool is_mesh_suspended(void)
43 {
44 	return atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
45 }
46 
bt_data_send(uint8_t num_events,uint16_t adv_int,const struct bt_data * ad,size_t ad_len,struct bt_mesh_adv_ctx * ctx)47 static int bt_data_send(uint8_t num_events, uint16_t adv_int,
48 			const struct bt_data *ad, size_t ad_len,
49 			struct bt_mesh_adv_ctx *ctx)
50 {
51 	struct bt_le_adv_param param = {};
52 	uint64_t uptime = k_uptime_get();
53 	uint16_t duration;
54 	int err;
55 	const int32_t adv_int_min =
56 		((bt_dev.hci_version >= BT_HCI_VERSION_5_0) ?
57 		 ADV_INT_FAST_MS :
58 		 ADV_INT_DEFAULT_MS);
59 
60 	adv_int = MAX(adv_int_min, adv_int);
61 
62 	ARG_UNUSED(uptime);
63 
64 	/* Zephyr Bluetooth Low Energy Controller for mesh stack uses
65 	 * pre-emptible continuous scanning, allowing advertising events to be
66 	 * transmitted without delay when advertising is enabled. No need to
67 	 * compensate with scan window duration.
68 	 * An advertising event could be delayed by upto one interval when
69 	 * advertising is stopped and started in quick succession, hence add
70 	 * advertising interval to the total advertising duration.
71 	 */
72 	duration = adv_int + num_events * (adv_int + 10);
73 
74 	/* Zephyr Bluetooth Low Energy Controller built for nRF51x SoCs use
75 	 * CONFIG_BT_CTLR_LOW_LAT=y, and continuous scanning cannot be
76 	 * pre-empted, hence, scanning will block advertising events from
77 	 * being transmitted. Increase the advertising duration by the
78 	 * amount of scan window duration to compensate for the blocked
79 	 * advertising events.
80 	 */
81 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
82 		duration += BT_MESH_SCAN_WINDOW_MS;
83 	}
84 
85 	LOG_DBG("count %u interval %ums duration %ums",
86 		num_events, adv_int, duration);
87 
88 	if (IS_ENABLED(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)) {
89 		param.options = BT_LE_ADV_OPT_USE_IDENTITY;
90 	} else {
91 		param.options = 0U;
92 	}
93 
94 	param.id = BT_ID_DEFAULT;
95 	param.interval_min = BT_MESH_ADV_SCAN_UNIT(adv_int);
96 	param.interval_max = param.interval_min;
97 
98 	err = bt_le_adv_start(&param, ad, ad_len, NULL, 0);
99 
100 	if (err) {
101 		LOG_ERR("Advertising failed: err %d", err);
102 		return err;
103 	}
104 
105 	LOG_DBG("Advertising started. Sleeping %u ms", duration);
106 
107 	if (ctx) {
108 		bt_mesh_adv_send_start(duration, err, ctx);
109 	}
110 
111 	if (!is_mesh_suspended()) {
112 		k_sleep(K_MSEC(duration));
113 	}
114 
115 	err = bt_le_adv_stop();
116 	if (err) {
117 		LOG_ERR("Stopping advertising failed: err %d", err);
118 		return err;
119 	}
120 
121 	LOG_DBG("Advertising stopped (%u ms)", (uint32_t) k_uptime_delta(&uptime));
122 
123 	return 0;
124 }
125 
bt_mesh_adv_bt_data_send(uint8_t num_events,uint16_t adv_int,const struct bt_data * ad,size_t ad_len)126 int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_int,
127 			     const struct bt_data *ad, size_t ad_len)
128 {
129 	return bt_data_send(num_events, adv_int, ad, ad_len, NULL);
130 }
131 
adv_send(struct bt_mesh_adv * adv)132 static inline void adv_send(struct bt_mesh_adv *adv)
133 {
134 	uint16_t num_events = BT_MESH_TRANSMIT_COUNT(adv->ctx.xmit) + 1;
135 	uint16_t adv_int;
136 	struct bt_data ad;
137 
138 	adv_int = BT_MESH_TRANSMIT_INT(adv->ctx.xmit);
139 
140 	LOG_DBG("type %u len %u: %s", adv->ctx.type,
141 	       adv->b.len, bt_hex(adv->b.data, adv->b.len));
142 
143 	ad.type = bt_mesh_adv_type[adv->ctx.type];
144 	ad.data_len = adv->b.len;
145 	ad.data = adv->b.data;
146 
147 	bt_data_send(num_events, adv_int, &ad, 1, &adv->ctx);
148 }
149 
adv_thread(void * p1,void * p2,void * p3)150 static void adv_thread(void *p1, void *p2, void *p3)
151 {
152 	LOG_DBG("started");
153 	struct bt_mesh_adv *adv;
154 
155 	while (!is_mesh_suspended()) {
156 		if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER)) {
157 			adv = bt_mesh_adv_get(K_NO_WAIT);
158 			if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) && !adv) {
159 				(void)bt_mesh_sol_send();
160 			}
161 
162 			while (!adv) {
163 
164 				/* Adv timeout may be set by a call from proxy
165 				 * to bt_mesh_adv_gatt_start:
166 				 */
167 				adv_timeout = SYS_FOREVER_MS;
168 				(void)bt_mesh_adv_gatt_send();
169 
170 				adv = bt_mesh_adv_get(SYS_TIMEOUT_MS(adv_timeout));
171 				bt_le_adv_stop();
172 
173 				if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) && !adv) {
174 					(void)bt_mesh_sol_send();
175 				}
176 			}
177 		} else {
178 			adv = bt_mesh_adv_get(K_FOREVER);
179 		}
180 
181 		if (!adv) {
182 			continue;
183 		}
184 
185 		/* busy == 0 means this was canceled */
186 		if (adv->ctx.busy) {
187 			adv->ctx.busy = 0U;
188 			adv_send(adv);
189 		}
190 
191 		struct bt_mesh_adv_ctx ctx = adv->ctx;
192 
193 		adv->ctx.started = 0;
194 		bt_mesh_adv_unref(adv);
195 		bt_mesh_adv_send_end(0, &ctx);
196 
197 		/* Give other threads a chance to run */
198 		k_yield();
199 	}
200 
201 	/* Empty the advertising pool when advertising is disabled */
202 	while ((adv = bt_mesh_adv_get(K_NO_WAIT))) {
203 		bt_mesh_adv_send_start(0, -ENODEV, &adv->ctx);
204 		bt_mesh_adv_unref(adv);
205 	}
206 }
207 
bt_mesh_adv_local_ready(void)208 void bt_mesh_adv_local_ready(void)
209 {
210 	/* Will be handled automatically */
211 }
212 
bt_mesh_adv_relay_ready(void)213 void bt_mesh_adv_relay_ready(void)
214 {
215 	/* Will be handled automatically */
216 }
217 
bt_mesh_adv_gatt_update(void)218 void bt_mesh_adv_gatt_update(void)
219 {
220 	bt_mesh_adv_get_cancel();
221 }
222 
bt_mesh_adv_terminate(struct bt_mesh_adv * adv)223 int bt_mesh_adv_terminate(struct bt_mesh_adv *adv)
224 {
225 	ARG_UNUSED(adv);
226 
227 	return 0;
228 }
229 
bt_mesh_adv_init(void)230 void bt_mesh_adv_init(void)
231 {
232 	k_thread_create(&adv_thread_data, adv_thread_stack,
233 			K_KERNEL_STACK_SIZEOF(adv_thread_stack), adv_thread,
234 			NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_MESH_ADV_PRIO),
235 			0, K_FOREVER);
236 	k_thread_name_set(&adv_thread_data, "BT Mesh adv");
237 }
238 
bt_mesh_adv_enable(void)239 int bt_mesh_adv_enable(void)
240 {
241 	/* The advertiser thread relies on BT_MESH_SUSPENDED flag. No point in starting the
242 	 * advertiser thread if the flag is not set.
243 	 */
244 	if (is_mesh_suspended()) {
245 		return -EINVAL;
246 	}
247 
248 	k_thread_start(&adv_thread_data);
249 	return 0;
250 }
251 
bt_mesh_adv_disable(void)252 int bt_mesh_adv_disable(void)
253 {
254 	int err;
255 
256 	/* k_thread_join will sleep forever if BT_MESH_SUSPENDED flag is not set. The advertiser
257 	 * thread will exit once the flag is set. The flag is set by the higher layer function. Here
258 	 * we need to check that the flag is dropped and ensure that the thread is stopped.
259 	 */
260 	if (!is_mesh_suspended()) {
261 		return -EINVAL;
262 	}
263 
264 	err = k_thread_join(&adv_thread_data, K_FOREVER);
265 	LOG_DBG("Advertising disabled: %d", err);
266 
267 	/* Since the thread will immediately stop after this function call and won’t perform any
268 	 * further operations, it’s safe to ignore the deadlock error (EDEADLK).
269 	 */
270 	return err == -EDEADLK ? 0 : err;
271 }
272 
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)273 int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param, int32_t duration,
274 			   const struct bt_data *ad, size_t ad_len,
275 			   const struct bt_data *sd, size_t sd_len)
276 {
277 	adv_timeout = duration;
278 	return bt_le_adv_start(param, ad, ad_len, sd, sd_len);
279 }
280 
bt_mesh_wq_submit(struct k_work * work)281 int bt_mesh_wq_submit(struct k_work *work)
282 {
283 	return k_work_submit(work);
284 }
285