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 uint8_t rpa_rotations;
19 int64_t old_time;
20 };
21
22 static uint8_t adv_index;
23 static struct adv_set_data_t adv_set_data[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
24
data_cb(struct bt_data * data,void * user_data)25 static bool data_cb(struct bt_data *data, void *user_data)
26 {
27 switch (data->type) {
28 case BT_DATA_MANUFACTURER_DATA:
29 adv_index = data->data[0];
30 return false;
31 default:
32 return true;
33 }
34 }
35
test_address(bt_addr_le_t * addr)36 static void test_address(bt_addr_le_t *addr)
37 {
38 int64_t diff_ms;
39 static int64_t rpa_timeout_ms = CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC;
40
41 if (!BT_ADDR_IS_RPA(&addr->a)) {
42 FAIL("Bluetooth address is not RPA\n");
43 }
44
45 /* Only save the address if this is the first scan */
46 if (bt_addr_le_eq(&adv_set_data[adv_index].old_addr, BT_ADDR_LE_ANY)) {
47 bt_addr_le_copy(&adv_set_data[adv_index].old_addr, addr);
48 adv_set_data[adv_index].old_time = k_uptime_get();
49 return;
50 }
51
52 diff_ms = k_uptime_get() - adv_set_data[adv_index].old_time;
53
54 if (diff_ms < rpa_timeout_ms) {
55 return;
56 }
57
58 printk("Ad set %d Old ", adv_index);
59 print_address(&adv_set_data[adv_index].old_addr);
60 printk("Ad set %d New ", adv_index);
61 print_address(addr);
62
63 /* For the first 2 rpa rotations, either of the first 2 adv sets returns false.
64 * Hence first 2 adv sets continue with old rpa in first 2 rpa rotations.
65 * For the next 2 rpa rotations, either of the last 2 adv sets returns false.
66 * Hence last 2 adv sets continue with old rpa in next 2 rpa rotations.
67 */
68 if ((adv_set_data[adv_index].rpa_rotations % CONFIG_BT_EXT_ADV_MAX_ADV_SET) < 2) {
69
70 if (adv_index < 2) {
71 if (!bt_addr_le_eq(addr, &adv_set_data[adv_index].old_addr)) {
72 FAIL("Adv sets should continue with old rpa\n");
73 }
74 } else {
75 if (bt_addr_le_eq(addr, &adv_set_data[adv_index].old_addr)) {
76 FAIL("New RPA should have been generated\n");
77 }
78 }
79 } else {
80 if (adv_index < 2) {
81 if (bt_addr_le_eq(addr, &adv_set_data[adv_index].old_addr)) {
82 FAIL("New RPA should have been generated\n");
83 }
84 } else {
85 if (!bt_addr_le_eq(addr, &adv_set_data[adv_index].old_addr)) {
86 FAIL("Adv sets should continue with old rpa\n");
87 }
88 }
89 }
90
91 adv_set_data[adv_index].rpa_rotations++;
92 if (adv_set_data[adv_index].rpa_rotations > EXPECTED_NUM_ROTATIONS) {
93 PASS("PASS\n");
94 }
95
96 adv_set_data[adv_index].old_time = k_uptime_get();
97 bt_addr_le_copy(&adv_set_data[adv_index].old_addr, addr);
98 }
99
cb_device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)100 static void cb_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
101 struct net_buf_simple *ad)
102 {
103 bt_data_parse(ad, data_cb, NULL);
104 test_address((bt_addr_le_t *)addr);
105 }
106
start_rpa_scanning(void)107 void start_rpa_scanning(void)
108 {
109 /* Start passive scanning */
110 struct bt_le_scan_param scan_param = {
111 .type = BT_LE_SCAN_TYPE_PASSIVE,
112 .options = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
113 .interval = 0x0040,
114 .window = 0x0020,
115 };
116
117 int err = bt_le_scan_start(&scan_param, cb_device_found);
118
119 if (err) {
120 FAIL("Failed to start scanning");
121 }
122 }
123
tester_verify_rpa_procedure(void)124 void tester_verify_rpa_procedure(void)
125 {
126 /* Enable bluetooth */
127 int err = bt_enable(NULL);
128
129 if (err) {
130 FAIL("Failed to enable bluetooth (err %d\n)", err);
131 }
132
133 err = settings_load();
134 if (err) {
135 FAIL("Failed to enable settings (err %d\n)", err);
136 }
137
138 start_rpa_scanning();
139 /* The rest of the test is driven by the callback */
140 }
141