1
2
3
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
43
44
45
46
47
48
58
59
60
61
62
63
66
67
68
69
72
73
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
94
95
120
121
125
126
127
128
129
130
131
132
133
134
138
139
142
143
144
145
146
147
148
149
150
151
152
153
154
155
159
160
164
165
166
167
168
169
170
171
172
173
174
178
179
180
181
182
183
184
185
186
187
188
189
190
191
195
196
197
198
199
200
201
202
205
206
211
212
217
223
224
225
226
229
230
231
234
235
236
237
238
239
240
241
242
243
244
248
249
250
254
255
256
257
276
277
278
292
293
294
303
304
306
307
308
311
312
313
314
315
316
317
321
322
323
324
325
326
327
328
329
333
334
335
336
337
338
339
340
341
347
348
349
350
351
352
353
354
355
356
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
380
381
382
388
389
390
391
392
394
395
396
397
398
399
400
401
402
408
409
416
417
418
419
420
421
422
423
424
428
429
430
434
442
443
449
450
457
458
459
460
461
462
469
470
471
472
473
474
475
476
477
478
479
492
493
494
495
496
497
498
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
532
533
534
535
536
537
538
539
540
541
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
571
572
573
574
/* ... */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include "btc_ble_mesh_ble.h"
#include "mesh/config.h"
#include "mesh/trace.h"
#include "mesh/buf.h"
#include "mesh/uuid.h"
#include "scan.h"
#include "beacon.h"
#include "net.h"
#include "prov_node.h"
#include "proxy_client.h"
#include "proxy_server.h"
#include "prov_pvnr.h"
#include "mesh/adapter.h"17 includes
#if CONFIG_BLE_MESH_V11_SUPPORT
#include "mesh_v1.1/utils.h"
#endif
#define SCAN_INTERVAL 0x20
#define SCAN_WINDOW 0x20
#define PROV_SVC_DATA_LEN 0x12
#define PROXY_SVC_DATA_LEN_NET_ID 0x09
#define PROXY_SVC_DATA_LEN_NODE_ID 0x11
#define PROXY_SVC_DATA_LEN_PRIVATE_NET_ID 0x11
#define PROXY_SVC_DATA_LEN_PRIVATE_NODE_ID 0x117 defines
#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV)
static const bt_mesh_addr_t *unprov_dev_addr;
static uint8_t current_adv_type;
static struct {
uint8_t start_idx;
uint8_t end_idx;
uint8_t pair_num;
struct {
uint8_t uuid[16];
uint8_t adv_type;
uint8_t addr[6];
}{...} info[BLE_MESH_STORE_UNPROV_INFO_MAX_NUM];
}{...} unprov_dev_info_fifo;
int bt_mesh_unprov_dev_fifo_dequeue(uint8_t *uuid, uint8_t *addr)
{
uint8_t idx = 0;
if (unprov_dev_info_fifo.pair_num == 0) {
return 0;
}{...}
idx = unprov_dev_info_fifo.start_idx;
if (uuid) {
memcpy(uuid, unprov_dev_info_fifo.info[idx].uuid, 16);
}{...}
if (addr) {
memcpy(addr, unprov_dev_info_fifo.info[idx].addr, 6);
}{...}
idx = (idx + 1) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM;
unprov_dev_info_fifo.start_idx = idx;
unprov_dev_info_fifo.pair_num--;
return 0;
}{...}
int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6],
uint8_t *adv_type, uint8_t query_type)
{
uint8_t idx = 0;
uint8_t cnt = 0;
if (uuid == NULL || addr == NULL) {
BT_WARN("No available information to query");
return -1;
}{...}
while (cnt < unprov_dev_info_fifo.pair_num) {
idx = (cnt + unprov_dev_info_fifo.start_idx) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM;
if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_UUID) {
if (!memcmp(unprov_dev_info_fifo.info[idx].addr, addr, 6)) {
if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) {
return 0;
}{...} else {
memcpy(uuid, unprov_dev_info_fifo.info[idx].uuid, 16);
*adv_type = unprov_dev_info_fifo.info[idx].adv_type;
break;
}{...}
}{...}
}{...} else {
if (!memcmp(unprov_dev_info_fifo.info[idx].uuid, uuid, 16)) {
if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) {
return 0;
}{...} else {
memcpy(addr, unprov_dev_info_fifo.info[idx].addr, 6);
*adv_type = unprov_dev_info_fifo.info[idx].adv_type;
break;
}{...}
}{...}
}{...}
cnt++;
}{...}
if (cnt == unprov_dev_info_fifo.pair_num) {
BT_WARN("Didn't find info for %d", query_type);
return -1;
}{...}
return 0;
}{...}
int bt_mesh_unprov_dev_fifo_enqueue(uint8_t uuid[16], const uint8_t addr[6], uint8_t adv_type)
{
uint8_t idx = 0;
if (uuid == NULL || addr == NULL) {
BT_ERR("Invalid argument %s", __func__);
return -EINVAL;
}{...}
if (unprov_dev_info_fifo.pair_num == BLE_MESH_STORE_UNPROV_INFO_MAX_NUM) {
bt_mesh_unprov_dev_fifo_dequeue(NULL, NULL);
}{...}
idx = unprov_dev_info_fifo.end_idx;
memcpy(unprov_dev_info_fifo.info[idx].uuid, uuid, 16);
memcpy(unprov_dev_info_fifo.info[idx].addr, addr, 6);
unprov_dev_info_fifo.info[idx].adv_type = adv_type;
idx = (idx + 1) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM;
unprov_dev_info_fifo.end_idx = idx;
unprov_dev_info_fifo.pair_num++;
return 0;
}{...}
const bt_mesh_addr_t *bt_mesh_get_unprov_dev_addr(void)
{
return unprov_dev_addr;
}{...}
uint8_t bt_mesh_get_adv_type(void)
{
return current_adv_type;
}{...}
/* ... */
#endif
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX
static bool adv_flags_valid(struct net_buf_simple *buf)
{
uint8_t flags = 0U;
if (buf->len != 1U) {
BT_DBG("Unexpected adv flags length %d", buf->len);
return false;
}{...}
flags = net_buf_simple_pull_u8(buf);
BT_DBG("Received adv pkt with flags: 0x%02x", flags);
ARG_UNUSED(flags);
return true;
}{...}
static bool adv_service_uuid_valid(struct net_buf_simple *buf, uint16_t *uuid)
{
if (buf->len != 2U) {
BT_DBG("Length not match mesh service uuid");
return false;
}{...}
*uuid = net_buf_simple_pull_le16(buf);
BT_DBG("Received adv pkt with service UUID: %d", *uuid);
if (*uuid != BLE_MESH_UUID_MESH_PROV_VAL &&
*uuid != BLE_MESH_UUID_MESH_PROXY_VAL &&
*uuid != BLE_MESH_UUID_MESH_PROXY_SOLIC_VAL) {
return false;
}{...}
/* ... */
#if CONFIG_BLE_MESH_RPR_SRV
if (*uuid == BLE_MESH_UUID_MESH_PROV_VAL &&
!IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
return false;
}{...}
/* ... */#else
if (*uuid == BLE_MESH_UUID_MESH_PROV_VAL &&
(bt_mesh_is_provisioner_en() == false ||
!IS_ENABLED(CONFIG_BLE_MESH_PB_GATT))) {
return false;
}{...}
/* ... */#endif
if (*uuid == BLE_MESH_UUID_MESH_PROXY_VAL &&
!IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) {
return false;
}{...}
if (*uuid == BLE_MESH_UUID_MESH_PROXY_SOLIC_VAL &&
!IS_ENABLED(CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX)) {
return false;
}{...}
return true;
}{...}
static void handle_adv_service_data(struct net_buf_simple *buf,
const bt_mesh_addr_t *addr,
uint16_t uuid, int8_t rssi)
{
uint16_t type = 0U;
if (!buf || !addr) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}{...}
type = net_buf_simple_pull_le16(buf);
if (type != uuid) {
BT_DBG("Invalid Mesh Service Data UUID 0x%04x", type);
return;
}{...}
switch (type) {
#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
case BLE_MESH_UUID_MESH_PROV_VAL:
if (bt_mesh_is_provisioner_en()) {
if (buf->len != PROV_SVC_DATA_LEN) {
BT_WARN("Invalid Mesh Prov Service Data length %d", buf->len);
return;
}{...}
BT_DBG("Start to handle Mesh Prov Service Data");
bt_mesh_provisioner_prov_adv_recv(buf, addr, rssi);
}{...}
#if CONFIG_BLE_MESH_RPR_SRV
if (bt_mesh_is_provisioned()) {
const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr();
bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type());
bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi);
}{...}
/* ... */#endif
break;/* ... */
#endif
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
case BLE_MESH_UUID_MESH_PROXY_VAL:
if (buf->len != PROXY_SVC_DATA_LEN_NET_ID &&
buf->len != PROXY_SVC_DATA_LEN_NODE_ID) {
/* ... */
BT_WARN("Invalid Mesh Proxy Service Data length %d", buf->len);
return;
}{...}
BT_DBG("Start to handle Mesh Proxy Service Data");
bt_mesh_proxy_client_gatt_adv_recv(buf, addr, rssi);
break;/* ... */
#endif
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX
case BLE_MESH_UUID_MESH_PROXY_SOLIC_VAL:
if (buf->len != (1 + BLE_MESH_NET_HDR_LEN + 8)) {
BT_WARN("Invalid Mesh Proxy Solic Service Data length %d", buf->len);
return;
}{...}
BT_DBG("Start to handle Mesh Proxy Solic Service Data");
bt_mesh_proxy_server_solic_recv(buf, addr, rssi);
break;/* ... */
#endif
default:
break;...
}{...}
}{...}
/* ... */#endif
/* ... */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
static bool ble_scan_en;
int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param)
{
if (ble_scan_en == true) {
BT_WARN("%s, Already", __func__);
return -EALREADY;
}{...}
ble_scan_en = true;
return 0;
}{...}
int bt_mesh_stop_ble_scan(void)
{
if (ble_scan_en == false) {
BT_WARN("%s, Already", __func__);
return -EALREADY;
}{...}
ble_scan_en = false;
return 0;
}{...}
static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr,
uint8_t adv_type, uint8_t data[],
uint16_t length, int8_t rssi)
{
if (ble_scan_en) {
bt_mesh_ble_scan_cb_evt_to_btc(addr, adv_type, data, length, rssi);
}{...}
}{...}
/* ... */#endif
#if CONFIG_BLE_MESH_RPR_SRV
static bool rpr_ext_scan_handle_adv_pkt(const bt_mesh_addr_t *addr,
uint8_t data[], uint16_t length)
{
struct net_buf_simple buf = {0};
bool rpr_adv = false;
if (bt_mesh_is_provisioned() == false) {
return false;
}{...}
net_buf_simple_init_with_data(&buf, data, length);
bt_mesh_rpr_srv_extended_scan(&buf, addr, &rpr_adv);
return rpr_adv;
}{...}
/* ... */#endif
static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
int8_t rssi, uint8_t adv_type,
struct net_buf_simple *buf,
uint8_t scan_rsp_len)
{
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX
uint16_t uuid = 0U;
#endif
#if (CONFIG_BLE_MESH_RPR_SRV || CONFIG_BLE_MESH_SUPPORT_BLE_SCAN)
uint8_t *adv_data = buf->data;
uint16_t adv_len = buf->len;/* ... */
#endif
if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) {
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
return;
}{...}
BT_DBG("scan, len %u: %s", buf->len, bt_hex(buf->data, buf->len));
#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV)
unprov_dev_addr = addr;
current_adv_type = adv_type;/* ... */
#endif
while (buf->len > 1) {
struct net_buf_simple_state state;
uint8_t len, type;
len = net_buf_simple_pull_u8(buf);
if (len == 0U) {
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
return;
}{...}
if (len > buf->len) {
BT_DBG("AD malformed");
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
return;
}{...}
net_buf_simple_save(buf, &state);
type = net_buf_simple_pull_u8(buf);
buf->len = len - 1;
if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE ||
type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) {
BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_type);
return;
}{...}
switch (type) {
case BLE_MESH_DATA_MESH_MESSAGE:
bt_mesh_net_recv(buf, rssi, BLE_MESH_NET_IF_ADV);
break;
#if CONFIG_BLE_MESH_PB_ADV...
case BLE_MESH_DATA_MESH_PROV:
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node()) {
bt_mesh_pb_adv_recv(buf);
}{...}
if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
bt_mesh_provisioner_pb_adv_recv(buf);
}{...}
break;/* ... */
#endif
case BLE_MESH_DATA_MESH_BEACON:
bt_mesh_beacon_recv(buf, rssi);
break;
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX...
case BLE_MESH_DATA_FLAGS:
if (!adv_flags_valid(buf)) {
BT_DBG("Adv Flags mismatch, ignore this adv pkt");
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
return;
}{...}
break;...
case BLE_MESH_DATA_UUID16_ALL:
if (!adv_service_uuid_valid(buf, &uuid)) {
BT_DBG("Adv Service UUID mismatch, ignore this adv pkt");
#if CONFIG_BLE_MESH_RPR_SRV
if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) {
/* ... */
return;
}{...}
#endif/* ... */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
return;
}{...}
break;...
case BLE_MESH_DATA_SVC_DATA16:
handle_adv_service_data(buf, addr, uuid, rssi);
break;/* ... */
#endif
default:
#if CONFIG_BLE_MESH_RPR_SRV
if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) {
/* ... */
return;
}{...}
#endif/* ... */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
return;...
}{...}
net_buf_simple_restore(buf, &state);
net_buf_simple_pull(buf, len);
}{...}
#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
if (scan_rsp_len != 0) {
/* ... */
rpr_ext_scan_handle_adv_pkt(addr, adv_data + adv_len, scan_rsp_len);
}{...}
#endif/* ... */
}{ ... }
int bt_mesh_scan_enable(void)
{
int err = 0;
struct bt_mesh_scan_param scan_param = {
#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
.type = BLE_MESH_SCAN_ACTIVE,
#else
.type = BLE_MESH_SCAN_PASSIVE,
#endif
#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
#else
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
#endif
.interval = SCAN_INTERVAL,
.window = SCAN_WINDOW,
.scan_fil_policy = BLE_MESH_SP_ADV_ALL,
}{...};
err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
if (err && err != -EALREADY) {
BT_ERR("starting scan failed (err %d)", err);
return err;
}{...}
return 0;
}{ ... }
int bt_mesh_scan_disable(void)
{
int err = 0;
err = bt_le_scan_stop();
if (err && err != -EALREADY) {
BT_ERR("stopping scan failed (err %d)", err);
return err;
}{...}
return 0;
}{ ... }
#if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST
int bt_mesh_scan_with_wl_enable(void)
{
int err = 0;
struct bt_mesh_scan_param scan_param = {
.type = BLE_MESH_SCAN_PASSIVE,
#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
#else
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
#endif
.interval = SCAN_INTERVAL,
.window = SCAN_WINDOW,
.scan_fil_policy = BLE_MESH_SP_ADV_WL,
}{...};
err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
if (err && err != -EALREADY) {
BT_ERR("starting scan failed (err %d)", err);
return err;
}{...}
return 0;
}{...}
/* ... */#endif