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