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 #include <zephyr/settings/settings.h>
13 
14 #define EXPECTED_NUM_ROTATIONS 5
15 
16 struct adv_set_data_t {
17 	bt_addr_le_t	old_addr;
18 	int64_t		old_time;
19 	int		rpa_rotations;
20 	bool            addr_set;
21 };
22 
23 static	uint8_t	adv_index;
24 static	struct	adv_set_data_t	adv_set_data[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
25 
data_cb(struct bt_data * data,void * user_data)26 static bool data_cb(struct bt_data *data, void *user_data)
27 {
28 	switch (data->type) {
29 	case BT_DATA_MANUFACTURER_DATA:
30 		adv_index = data->data[0];
31 		return false;
32 	default:
33 		return true;
34 	}
35 }
36 
validate_rpa_addr_generated_for_adv_sets(void)37 static void validate_rpa_addr_generated_for_adv_sets(void)
38 {
39 	for (int i = 0; i < CONFIG_BT_EXT_ADV_MAX_ADV_SET; i++) {
40 		if (!adv_set_data[i].addr_set) {
41 			return;
42 		}
43 	}
44 	if (bt_addr_le_eq(&adv_set_data[0].old_addr, &adv_set_data[1].old_addr)) {
45 		/* With RPA sharing mode disabled, the first two adv sets should have
46 		 * a different address even though they use the same Bluetooth ID.
47 		 */
48 		if (!IS_ENABLED(CONFIG_BT_RPA_SHARING)) {
49 			FAIL("RPA same for adv sets with same id and RPA sharing disabled\n");
50 		}
51 	} else {
52 		/* In the RPA sharing mode, the first two adv sets should have
53 		 * the same address as they use the same Bluetooth ID.
54 		 */
55 		if (IS_ENABLED(CONFIG_BT_RPA_SHARING)) {
56 			FAIL("RPA not same for adv sets with same id and RPA sharing enabled\n");
57 		}
58 	}
59 	if (bt_addr_le_eq(&adv_set_data[0].old_addr, &adv_set_data[3].old_addr)) {
60 		FAIL("RPA same for adv sets with different id's\n");
61 	}
62 	if (bt_addr_le_eq(&adv_set_data[1].old_addr, &adv_set_data[3].old_addr)) {
63 		FAIL("RPA same for adv sets with different id's\n");
64 	}
65 	adv_set_data[0].addr_set	= false;
66 	adv_set_data[1].addr_set	= false;
67 	adv_set_data[2].addr_set	= false;
68 }
69 
test_address(bt_addr_le_t * addr)70 static void test_address(bt_addr_le_t *addr)
71 {
72 	int64_t diff_ms, rpa_timeout_ms;
73 
74 	if (!BT_ADDR_IS_RPA(&addr->a)) {
75 		FAIL("Bluetooth address is not RPA\n");
76 	}
77 
78 	/* Only save the address + time if this is the first scan */
79 	if (bt_addr_le_eq(&adv_set_data[adv_index].old_addr, BT_ADDR_LE_ANY)) {
80 		bt_addr_le_copy(&adv_set_data[adv_index].old_addr, addr);
81 		adv_set_data[adv_index].old_time = k_uptime_get();
82 		return;
83 	}
84 
85 	/* Compare old and new address */
86 	if (bt_addr_le_eq(&adv_set_data[adv_index].old_addr, addr)) {
87 		return;
88 	}
89 	adv_set_data[adv_index].addr_set = true;
90 	printk("Ad set %d Old ", adv_index);
91 	print_address(&adv_set_data[adv_index].old_addr);
92 	printk("Ad set %d New ", adv_index);
93 	print_address(addr);
94 
95 	adv_set_data[adv_index].rpa_rotations++;
96 
97 	/* Ensure the RPA rotation occurs within +-10% of CONFIG_BT_RPA_TIMEOUT */
98 	diff_ms = k_uptime_get() - adv_set_data[adv_index].old_time;
99 	rpa_timeout_ms = CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC;
100 
101 	if (abs(diff_ms - rpa_timeout_ms) > (rpa_timeout_ms / 10)) {
102 		FAIL("RPA rotation did not occur within +-10%% of CONFIG_BT_RPA_TIMEOUT\n");
103 	}
104 
105 	bt_addr_le_copy(&adv_set_data[adv_index].old_addr, addr);
106 	adv_set_data[adv_index].old_time = k_uptime_get();
107 	validate_rpa_addr_generated_for_adv_sets();
108 
109 	if (adv_set_data[adv_index].rpa_rotations > EXPECTED_NUM_ROTATIONS) {
110 		PASS("PASS\n");
111 	}
112 }
113 
cb_device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)114 static void cb_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
115 			    struct net_buf_simple *ad)
116 {
117 	bt_data_parse(ad, data_cb, NULL);
118 	test_address((bt_addr_le_t *)addr);
119 }
120 
start_scanning(void)121 void start_scanning(void)
122 {
123 	/* Start passive scanning */
124 	struct bt_le_scan_param scan_param = {
125 		.type       = BT_LE_SCAN_TYPE_PASSIVE,
126 		.options    = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
127 		.interval   = 0x0040,
128 		.window     = 0x0020,
129 	};
130 
131 	int err = bt_le_scan_start(&scan_param, cb_device_found);
132 
133 	if (err) {
134 		FAIL("Failed to start scanning");
135 	}
136 }
137 
tester_procedure(void)138 void tester_procedure(void)
139 {
140 	/* Enable bluetooth */
141 	int err = bt_enable(NULL);
142 
143 	if (err) {
144 		FAIL("Failed to enable bluetooth (err %d\n)", err);
145 	}
146 
147 	err = settings_load();
148 	if (err) {
149 		FAIL("Failed to enable settings (err %d\n)", err);
150 	}
151 
152 	start_scanning();
153 
154 	/* The rest of the test is driven by the callback */
155 }
156