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.h>
9 #include <debug/stack.h>
10 
11 #include <net/buf.h>
12 #include <bluetooth/bluetooth.h>
13 #include <bluetooth/mesh.h>
14 
15 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ADV)
16 #define LOG_MODULE_NAME bt_mesh_adv_ext
17 #include "common/log.h"
18 
19 #include "host/hci_core.h"
20 
21 #include "adv.h"
22 #include "net.h"
23 #include "proxy.h"
24 
25 /* Convert from ms to 0.625ms units */
26 #define ADV_INT_FAST_MS    20
27 
28 static struct bt_le_adv_param adv_param = {
29 	.id = BT_ID_DEFAULT,
30 	.interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
31 	.interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
32 #if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
33 	.options = BT_LE_ADV_OPT_USE_IDENTITY,
34 #endif
35 };
36 
37 enum {
38 	/** Controller is currently advertising */
39 	ADV_FLAG_ACTIVE,
40 	/** Currently performing proxy advertising */
41 	ADV_FLAG_PROXY,
42 	/** The send-call has been scheduled. */
43 	ADV_FLAG_SCHEDULED,
44 	/** Custom adv params have been set, we need to update the parameters on
45 	 *  the next send.
46 	 */
47 	ADV_FLAG_UPDATE_PARAMS,
48 
49 	/* Number of adv flags. */
50 	ADV_FLAGS_NUM
51 };
52 
53 static struct {
54 	ATOMIC_DEFINE(flags, ADV_FLAGS_NUM);
55 	struct bt_le_ext_adv *instance;
56 	struct net_buf *buf;
57 	uint64_t timestamp;
58 	struct k_work_delayable work;
59 } adv;
60 
adv_start(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)61 static int adv_start(const struct bt_le_adv_param *param,
62 		     struct bt_le_ext_adv_start_param *start,
63 		     const struct bt_data *ad, size_t ad_len,
64 		     const struct bt_data *sd, size_t sd_len)
65 {
66 	int err;
67 
68 	if (!adv.instance) {
69 		BT_ERR("Mesh advertiser not enabled");
70 		return -ENODEV;
71 	}
72 
73 	if (atomic_test_and_set_bit(adv.flags, ADV_FLAG_ACTIVE)) {
74 		BT_ERR("Advertiser is busy");
75 		return -EBUSY;
76 	}
77 
78 	if (atomic_test_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS)) {
79 		err = bt_le_ext_adv_update_param(adv.instance, param);
80 		if (err) {
81 			BT_ERR("Failed updating adv params: %d", err);
82 			atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
83 			return err;
84 		}
85 
86 		atomic_set_bit_to(adv.flags, ADV_FLAG_UPDATE_PARAMS,
87 				  param != &adv_param);
88 	}
89 
90 	err = bt_le_ext_adv_set_data(adv.instance, ad, ad_len, sd, sd_len);
91 	if (err) {
92 		BT_ERR("Failed setting adv data: %d", err);
93 		atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
94 		return err;
95 	}
96 
97 	adv.timestamp = k_uptime_get();
98 
99 	err = bt_le_ext_adv_start(adv.instance, start);
100 	if (err) {
101 		BT_ERR("Advertising failed: err %d", err);
102 		atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
103 	}
104 
105 	return err;
106 }
107 
buf_send(struct net_buf * buf)108 static int buf_send(struct net_buf *buf)
109 {
110 	struct bt_le_ext_adv_start_param start = {
111 		.num_events =
112 			BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1,
113 	};
114 	uint16_t duration, adv_int;
115 	struct bt_data ad;
116 	int err;
117 
118 	adv_int = MAX(ADV_INT_FAST_MS,
119 		      BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit));
120 	/* Upper boundary estimate: */
121 	duration = start.num_events * (adv_int + 10);
122 
123 	BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type,
124 	       buf->len, bt_hex(buf->data, buf->len));
125 	BT_DBG("count %u interval %ums duration %ums",
126 	       BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int,
127 	       duration);
128 
129 	ad.type = bt_mesh_adv_type[BT_MESH_ADV(buf)->type];
130 	ad.data_len = buf->len;
131 	ad.data = buf->data;
132 
133 	/* Only update advertising parameters if they're different */
134 	if (adv_param.interval_min != BT_MESH_ADV_SCAN_UNIT(adv_int)) {
135 		adv_param.interval_min = BT_MESH_ADV_SCAN_UNIT(adv_int);
136 		adv_param.interval_max = adv_param.interval_min;
137 		atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS);
138 	}
139 
140 	err = adv_start(&adv_param, &start, &ad, 1, NULL, 0);
141 	if (!err) {
142 		adv.buf = net_buf_ref(buf);
143 	}
144 
145 	bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf));
146 
147 	return err;
148 }
149 
send_pending_adv(struct k_work * work)150 static void send_pending_adv(struct k_work *work)
151 {
152 	struct net_buf *buf;
153 	int err;
154 
155 	atomic_clear_bit(adv.flags, ADV_FLAG_SCHEDULED);
156 
157 	while ((buf = net_buf_get(&bt_mesh_adv_queue, K_NO_WAIT))) {
158 		/* busy == 0 means this was canceled */
159 		if (!BT_MESH_ADV(buf)->busy) {
160 			net_buf_unref(buf);
161 			continue;
162 		}
163 
164 		BT_MESH_ADV(buf)->busy = 0U;
165 		err = buf_send(buf);
166 
167 		net_buf_unref(buf);
168 
169 		if (!err) {
170 			return; /* Wait for advertising to finish */
171 		}
172 	}
173 
174 	/* No more pending buffers */
175 	if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER)) {
176 		BT_DBG("Proxy Advertising");
177 		err = bt_mesh_proxy_adv_start();
178 		if (!err) {
179 			atomic_set_bit(adv.flags, ADV_FLAG_PROXY);
180 		}
181 	}
182 }
183 
schedule_send(void)184 static void schedule_send(void)
185 {
186 	uint64_t timestamp = adv.timestamp;
187 	int64_t delta;
188 
189 	if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) {
190 		bt_le_ext_adv_stop(adv.instance);
191 		atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
192 	}
193 
194 	if (atomic_test_bit(adv.flags, ADV_FLAG_ACTIVE) ||
195 	    atomic_test_and_set_bit(adv.flags, ADV_FLAG_SCHEDULED)) {
196 		return;
197 	}
198 
199 	/* The controller will send the next advertisement immediately.
200 	 * Introduce a delay here to avoid sending the next mesh packet closer
201 	 * to the previous packet than what's permitted by the specification.
202 	 */
203 	delta = k_uptime_delta(&timestamp);
204 	k_work_reschedule(&adv.work, K_MSEC(ADV_INT_FAST_MS - delta));
205 }
206 
bt_mesh_adv_update(void)207 void bt_mesh_adv_update(void)
208 {
209 	BT_DBG("");
210 
211 	schedule_send();
212 }
213 
bt_mesh_adv_buf_ready(void)214 void bt_mesh_adv_buf_ready(void)
215 {
216 	schedule_send();
217 }
218 
bt_mesh_adv_init(void)219 void bt_mesh_adv_init(void)
220 {
221 	k_work_init_delayable(&adv.work, send_pending_adv);
222 }
223 
adv_sent(struct bt_le_ext_adv * instance,struct bt_le_ext_adv_sent_info * info)224 static void adv_sent(struct bt_le_ext_adv *instance,
225 		     struct bt_le_ext_adv_sent_info *info)
226 {
227 	/* Calling k_uptime_delta on a timestamp moves it to the current time.
228 	 * This is essential here, as schedule_send() uses the end of the event
229 	 * as a reference to avoid sending the next advertisement too soon.
230 	 */
231 	int64_t duration = k_uptime_delta(&adv.timestamp);
232 
233 	BT_DBG("Advertising stopped after %u ms", (uint32_t)duration);
234 
235 	atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
236 
237 	if (!atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) {
238 		net_buf_unref(adv.buf);
239 	}
240 
241 	schedule_send();
242 }
243 
connected(struct bt_le_ext_adv * instance,struct bt_le_ext_adv_connected_info * info)244 static void connected(struct bt_le_ext_adv *instance,
245 		      struct bt_le_ext_adv_connected_info *info)
246 {
247 	if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) {
248 		atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
249 		schedule_send();
250 	}
251 }
252 
bt_mesh_adv_enable(void)253 int bt_mesh_adv_enable(void)
254 {
255 	static const struct bt_le_ext_adv_cb adv_cb = {
256 		.sent = adv_sent,
257 		.connected = connected,
258 	};
259 
260 	if (adv.instance) {
261 		/* Already initialized */
262 		return 0;
263 	}
264 
265 	return bt_le_ext_adv_create(&adv_param, &adv_cb, &adv.instance);
266 }
267 
bt_mesh_adv_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)268 int bt_mesh_adv_start(const struct bt_le_adv_param *param, int32_t duration,
269 		      const struct bt_data *ad, size_t ad_len,
270 		      const struct bt_data *sd, size_t sd_len)
271 {
272 	struct bt_le_ext_adv_start_param start = {
273 		/* Timeout is set in 10 ms steps, with 0 indicating "forever" */
274 		.timeout = (duration == SYS_FOREVER_MS) ? 0 : (duration / 10),
275 	};
276 
277 	BT_DBG("Start advertising %d ms", duration);
278 
279 	atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS);
280 
281 	return adv_start(param, &start, ad, ad_len, sd, sd_len);
282 }
283