1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "bs_bt_utils.h"
8 #include <zephyr/bluetooth/addr.h>
9 #include <zephyr/bluetooth/conn.h>
10 #include <stdint.h>
11 #include <zephyr/bluetooth/bluetooth.h>
12
13 #include "common/bt_str.h"
14
15 #define EXPECTED_NUM_ROTATIONS 5
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(tester, 4);
19
20 struct test_data_t {
21 bt_addr_le_t old_addr;
22 int64_t old_time;
23 int rpa_rotations;
24 bool addr_set;
25 } static test_data;
26
27 extern bt_addr_le_t dut_addr;
28
print_address(const bt_addr_le_t * addr)29 void print_address(const bt_addr_le_t *addr)
30 {
31 char array[BT_ADDR_LE_STR_LEN];
32
33 bt_addr_le_to_str(addr, array, sizeof(array));
34 LOG_DBG("Address : %s", array);
35 }
36
cb_expect_rpa(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)37 static void cb_expect_rpa(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
38 struct net_buf_simple *ad)
39 {
40 int64_t diff_ms, rpa_timeout_ms;
41
42 if (bt_addr_le_eq(addr, &dut_addr)) {
43 FAIL("DUT used identity addr instead of RPA\n");
44 }
45
46 /* Only save the address + time if this is the first scan */
47 if (bt_addr_le_eq(&test_data.old_addr, BT_ADDR_LE_ANY)) {
48 bt_addr_le_copy(&test_data.old_addr, addr);
49 test_data.old_time = k_uptime_get();
50 return;
51 }
52
53 /* Compare old and new address */
54 if (bt_addr_le_eq(&test_data.old_addr, addr)) {
55 return;
56 }
57 test_data.addr_set = true;
58 LOG_DBG("Old ");
59 print_address(&test_data.old_addr);
60 LOG_DBG("New ");
61 print_address(addr);
62
63 test_data.rpa_rotations++;
64
65 /* Ensure the RPA rotation occurs within +-10% of CONFIG_BT_RPA_TIMEOUT */
66 diff_ms = k_uptime_get() - test_data.old_time;
67 rpa_timeout_ms = CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC;
68
69 if (abs(diff_ms - rpa_timeout_ms) > (rpa_timeout_ms / 10)) {
70 FAIL("RPA rotation did not occur within +-10% of CONFIG_BT_RPA_TIMEOUT\n");
71 }
72
73 bt_addr_le_copy(&test_data.old_addr, addr);
74 test_data.old_time = k_uptime_get();
75
76 if (test_data.rpa_rotations > EXPECTED_NUM_ROTATIONS) {
77 PASS("PASS\n");
78 }
79 }
80
cb_expect_id(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)81 static void cb_expect_id(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
82 struct net_buf_simple *ad)
83 {
84 int err;
85
86 LOG_DBG("expecting addr:");
87 print_address(&dut_addr);
88 LOG_DBG("got addr:");
89 print_address(addr);
90
91 if (addr->type != BT_ADDR_LE_RANDOM) {
92 FAIL("Expected public address (0x%x) got 0x%x\n",
93 BT_ADDR_LE_RANDOM, addr->type);
94 }
95
96 if (!bt_addr_le_eq(&dut_addr, addr)) {
97 FAIL("DUT not using identity address\n");
98 }
99
100 err = bt_le_scan_stop();
101 if (err) {
102 FAIL("Failed to stop scan: %d\n", err);
103 }
104
105 backchannel_sync_send();
106 }
107
start_scanning(bool expect_rpa)108 void start_scanning(bool expect_rpa)
109 {
110 int err;
111 struct bt_le_scan_param scan_param = {
112 .type = BT_HCI_LE_SCAN_PASSIVE,
113 .options = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
114 .interval = 0x0040,
115 .window = 0x0020,
116 };
117
118 if (expect_rpa) {
119 err = bt_le_scan_start(&scan_param, cb_expect_rpa);
120 } else {
121 err = bt_le_scan_start(&scan_param, cb_expect_id);
122 }
123
124 if (err) {
125 FAIL("Failed to start scanning\n");
126 }
127 }
128
tester_procedure(void)129 void tester_procedure(void)
130 {
131 int err;
132
133 /* open a backchannel to the peer */
134 backchannel_init(PERIPHERAL_SIM_ID);
135
136 err = bt_enable(NULL);
137 if (err) {
138 FAIL("Failed to enable bluetooth (err %d\n)", err);
139 }
140
141 start_scanning(false);
142
143 backchannel_sync_wait();
144
145 start_scanning(true);
146 }
147