1 /* Bluetooth Mesh */
2
3 /*
4 * SPDX-FileCopyrightText: 2017 Intel Corporation
5 * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <errno.h>
13
14 #include "btc_ble_mesh_ble.h"
15
16 #include "mesh_config.h"
17 #include "mesh_trace.h"
18 #include "mesh_buf.h"
19 #include "mesh_uuid.h"
20 #include "scan.h"
21 #include "beacon.h"
22 #include "net.h"
23 #include "prov.h"
24 #include "proxy_client.h"
25 #include "proxy_server.h"
26 #include "provisioner_prov.h"
27 #include "mesh_bearer_adapt.h"
28
29 /* Scan Window and Interval are equal for continuous scanning */
30 #define SCAN_INTERVAL 0x20
31 #define SCAN_WINDOW 0x20
32
33 #define PROV_SVC_DATA_LEN 0x12
34 #define PROXY_SVC_DATA_LEN_NET_ID 0x09
35 #define PROXY_SVC_DATA_LEN_NODE_ID 0x11
36
37 #if CONFIG_BLE_MESH_PROVISIONER
38 static const bt_mesh_addr_t *unprov_dev_addr;
39
bt_mesh_get_unprov_dev_addr(void)40 const bt_mesh_addr_t *bt_mesh_get_unprov_dev_addr(void)
41 {
42 return unprov_dev_addr;
43 }
44 #endif /* CONFIG_BLE_MESH_PROVISIONER */
45
46 #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
47 CONFIG_BLE_MESH_GATT_PROXY_CLIENT
adv_flags_valid(struct net_buf_simple * buf)48 static bool adv_flags_valid(struct net_buf_simple *buf)
49 {
50 uint8_t flags = 0U;
51
52 if (buf->len != 1U) {
53 BT_DBG("Unexpected adv flags length %d", buf->len);
54 return false;
55 }
56
57 flags = net_buf_simple_pull_u8(buf);
58
59 BT_DBG("Received adv pkt with flags: 0x%02x", flags);
60
61 /* Flags context will not be checked currently */
62 ARG_UNUSED(flags);
63
64 return true;
65 }
66
adv_service_uuid_valid(struct net_buf_simple * buf,uint16_t * uuid)67 static bool adv_service_uuid_valid(struct net_buf_simple *buf, uint16_t *uuid)
68 {
69 if (buf->len != 2U) {
70 BT_DBG("Length not match mesh service uuid");
71 return false;
72 }
73
74 *uuid = net_buf_simple_pull_le16(buf);
75
76 BT_DBG("Received adv pkt with service UUID: %d", *uuid);
77
78 if (*uuid != BLE_MESH_UUID_MESH_PROV_VAL &&
79 *uuid != BLE_MESH_UUID_MESH_PROXY_VAL) {
80 return false;
81 }
82
83 if (*uuid == BLE_MESH_UUID_MESH_PROV_VAL &&
84 bt_mesh_is_provisioner_en() == false) {
85 return false;
86 }
87
88 if (*uuid == BLE_MESH_UUID_MESH_PROXY_VAL &&
89 !IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) {
90 return false;
91 }
92
93 return true;
94 }
95
handle_adv_service_data(struct net_buf_simple * buf,const bt_mesh_addr_t * addr,uint16_t uuid,int8_t rssi)96 static void handle_adv_service_data(struct net_buf_simple *buf,
97 const bt_mesh_addr_t *addr,
98 uint16_t uuid, int8_t rssi)
99 {
100 uint16_t type = 0U;
101
102 if (!buf || !addr) {
103 BT_ERR("%s, Invalid parameter", __func__);
104 return;
105 }
106
107 type = net_buf_simple_pull_le16(buf);
108 if (type != uuid) {
109 BT_DBG("Invalid Mesh Service Data UUID 0x%04x", type);
110 return;
111 }
112
113 switch (type) {
114 #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
115 case BLE_MESH_UUID_MESH_PROV_VAL:
116 if (bt_mesh_is_provisioner_en()) {
117 if (buf->len != PROV_SVC_DATA_LEN) {
118 BT_WARN("Invalid Mesh Prov Service Data length %d", buf->len);
119 return;
120 }
121
122 BT_DBG("Start to handle Mesh Prov Service Data");
123 bt_mesh_provisioner_prov_adv_recv(buf, addr, rssi);
124 }
125 break;
126 #endif
127 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
128 case BLE_MESH_UUID_MESH_PROXY_VAL:
129 if (buf->len != PROXY_SVC_DATA_LEN_NET_ID &&
130 buf->len != PROXY_SVC_DATA_LEN_NODE_ID) {
131 BT_WARN("Invalid Mesh Proxy Service Data length %d", buf->len);
132 return;
133 }
134
135 BT_DBG("Start to handle Mesh Proxy Service Data");
136 bt_mesh_proxy_client_gatt_adv_recv(buf, addr, rssi);
137 break;
138 #endif
139 default:
140 break;
141 }
142 }
143 #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
144 CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
145
146 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
147 static bool ble_scan_en;
148
bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param * param)149 int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param)
150 {
151 if (ble_scan_en == true) {
152 BT_WARN("%s, Already", __func__);
153 return -EALREADY;
154 }
155
156 ble_scan_en = true;
157
158 return 0;
159 }
160
bt_mesh_stop_ble_scan(void)161 int bt_mesh_stop_ble_scan(void)
162 {
163 if (ble_scan_en == false) {
164 BT_WARN("%s, Already", __func__);
165 return -EALREADY;
166 }
167
168 ble_scan_en = false;
169
170 return 0;
171 }
172
callback_ble_adv_pkt(const bt_mesh_addr_t * addr,uint8_t adv_type,uint8_t data[],uint16_t length,int8_t rssi)173 static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr,
174 uint8_t adv_type, uint8_t data[],
175 uint16_t length, int8_t rssi)
176 {
177 if (ble_scan_en) {
178 bt_mesh_ble_scan_cb_evt_to_btc(addr, adv_type, data, length, rssi);
179 }
180 }
181 #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
182
bt_mesh_scan_cb(const bt_mesh_addr_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)183 static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
184 int8_t rssi, uint8_t adv_type,
185 struct net_buf_simple *buf)
186 {
187 #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
188 CONFIG_BLE_MESH_GATT_PROXY_CLIENT
189 uint16_t uuid = 0U;
190 #endif
191 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
192 uint8_t *adv_data = buf->data;
193 uint16_t adv_len = buf->len;
194 #endif
195
196 if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) {
197 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
198 callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
199 #endif
200 return;
201 }
202
203 BT_DBG("scan, len %u: %s", buf->len, bt_hex(buf->data, buf->len));
204
205 #if CONFIG_BLE_MESH_PROVISIONER
206 unprov_dev_addr = addr;
207 #endif
208
209 while (buf->len > 1) {
210 struct net_buf_simple_state state;
211 uint8_t len, type;
212
213 len = net_buf_simple_pull_u8(buf);
214 /* Check for early termination */
215 if (len == 0U) {
216 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
217 callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
218 #endif
219 return;
220 }
221
222 if (len > buf->len) {
223 BT_DBG("AD malformed");
224 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
225 callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
226 #endif
227 return;
228 }
229
230 net_buf_simple_save(buf, &state);
231
232 type = net_buf_simple_pull_u8(buf);
233
234 buf->len = len - 1;
235
236 if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE ||
237 type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) {
238 BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_type);
239 return;
240 }
241
242 switch (type) {
243 case BLE_MESH_DATA_MESH_MESSAGE:
244 bt_mesh_net_recv(buf, rssi, BLE_MESH_NET_IF_ADV);
245 break;
246 #if CONFIG_BLE_MESH_PB_ADV
247 case BLE_MESH_DATA_MESH_PROV:
248 if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node()) {
249 bt_mesh_pb_adv_recv(buf);
250 }
251 if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
252 bt_mesh_provisioner_pb_adv_recv(buf);
253 }
254 break;
255 #endif /* CONFIG_BLE_MESH_PB_ADV */
256 case BLE_MESH_DATA_MESH_BEACON:
257 bt_mesh_beacon_recv(buf, rssi);
258 break;
259 #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
260 CONFIG_BLE_MESH_GATT_PROXY_CLIENT
261 case BLE_MESH_DATA_FLAGS:
262 if (!adv_flags_valid(buf)) {
263 BT_DBG("Adv Flags mismatch, ignore this adv pkt");
264 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
265 callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
266 #endif
267 return;
268 }
269 break;
270 case BLE_MESH_DATA_UUID16_ALL:
271 if (!adv_service_uuid_valid(buf, &uuid)) {
272 BT_DBG("Adv Service UUID mismatch, ignore this adv pkt");
273 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
274 callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
275 #endif
276 return;
277 }
278 break;
279 case BLE_MESH_DATA_SVC_DATA16:
280 handle_adv_service_data(buf, addr, uuid, rssi);
281 break;
282 #endif
283 default:
284 #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
285 callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
286 #endif
287 return;
288 }
289
290 net_buf_simple_restore(buf, &state);
291 net_buf_simple_pull(buf, len);
292 }
293 }
294
bt_mesh_scan_enable(void)295 int bt_mesh_scan_enable(void)
296 {
297 int err = 0;
298
299 struct bt_mesh_scan_param scan_param = {
300 .type = BLE_MESH_SCAN_PASSIVE,
301 #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
302 .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
303 #else
304 .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
305 #endif
306 .interval = SCAN_INTERVAL,
307 .window = SCAN_WINDOW,
308 .scan_fil_policy = BLE_MESH_SP_ADV_ALL,
309 };
310
311 BT_DBG("%s", __func__);
312
313 err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
314 if (err && err != -EALREADY) {
315 BT_ERR("starting scan failed (err %d)", err);
316 return err;
317 }
318
319 return 0;
320 }
321
bt_mesh_scan_disable(void)322 int bt_mesh_scan_disable(void)
323 {
324 int err = 0;
325
326 BT_DBG("%s", __func__);
327
328 err = bt_le_scan_stop();
329 if (err && err != -EALREADY) {
330 BT_ERR("stopping scan failed (err %d)", err);
331 return err;
332 }
333
334 return 0;
335 }
336
337 #if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST
bt_mesh_scan_with_wl_enable(void)338 int bt_mesh_scan_with_wl_enable(void)
339 {
340 int err = 0;
341
342 struct bt_mesh_scan_param scan_param = {
343 .type = BLE_MESH_SCAN_PASSIVE,
344 #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
345 .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
346 #else
347 .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
348 #endif
349 .interval = SCAN_INTERVAL,
350 .window = SCAN_WINDOW,
351 .scan_fil_policy = BLE_MESH_SP_ADV_WL,
352 };
353
354 BT_DBG("%s", __func__);
355
356 err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
357 if (err && err != -EALREADY) {
358 BT_ERR("starting scan failed (err %d)", err);
359 return err;
360 }
361
362 return 0;
363 }
364 #endif /* CONFIG_BLE_MESH_TEST_USE_WHITE_LIST */
365