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