1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/bluetooth/addr.h>
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/conn.h>
15 #include <zephyr/bluetooth/gatt.h>
16 #include <zephyr/bluetooth/hci.h>
17 #include <zephyr/bluetooth/uuid.h>
18 #include <zephyr/kernel.h>
19 #include <zephyr/types.h>
20 #include <zephyr/toolchain.h>
21 #include <zephyr/settings/settings.h>
22 
23 #include "babblekit/testcase.h"
24 
25 #include "common/bt_str.h"
26 
27 #define ID_1 1
28 #define ID_2 2
29 
30 #define ADV_SET_INDEX_1		0x00
31 #define ADV_SET_INDEX_2		0x01
32 #define ADV_SET_INDEX_3		0x02
33 #define ADV_SET_INDEX_4		0x03
34 
35 static struct bt_le_ext_adv *adv_set[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
36 
37 	static const struct bt_data ad_id[] = {
38 	BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA, ADV_SET_INDEX_1),
39 	BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA, ADV_SET_INDEX_2),
40 	BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA, ADV_SET_INDEX_3),
41 	BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA, ADV_SET_INDEX_4),
42 };
43 
rpa_expired_cb(struct bt_le_ext_adv * adv)44 bool rpa_expired_cb(struct bt_le_ext_adv *adv)
45 {
46 	/*	Return true to rotate the current RPA.
47 	 *	Return false to continue with old RPA.
48 	 */
49 	int	err;
50 	struct	bt_le_ext_adv_info info;
51 	static int rpa_count = -1;
52 	static int64_t	old_time;
53 	static int64_t	rpa_timeout_ms;
54 	int64_t	diff_ms;
55 
56 	diff_ms = k_uptime_get() - old_time;
57 	rpa_timeout_ms = CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC;
58 
59 	if (diff_ms >= rpa_timeout_ms) {
60 		rpa_count++;
61 		old_time = k_uptime_get();
62 	}
63 
64 	err = bt_le_ext_adv_get_info(adv, &info);
65 	if (err) {
66 		return false;
67 	}
68 	printk("%s advertiser[%d] RPA %s\n", __func__, info.id, bt_addr_le_str(info.addr));
69 
70 	/* Every rpa rotation one of the adv set returns false based on adv index */
71 	if (rpa_count == bt_le_ext_adv_get_index(adv)) {
72 		printk("adv index %d returns false\n", bt_le_ext_adv_get_index(adv));
73 		if (rpa_count == CONFIG_BT_EXT_ADV_MAX_ADV_SET - 1) {
74 			/* Reset RPA counter */
75 			rpa_count = -1;
76 		}
77 		return false;
78 	}
79 	return true;
80 }
81 
create_adv(struct bt_le_ext_adv ** adv,int id)82 static void create_adv(struct bt_le_ext_adv **adv, int id)
83 {
84 	int err;
85 	struct bt_le_adv_param params;
86 	static struct bt_le_ext_adv_cb cb_adv;
87 
88 	cb_adv.rpa_expired = rpa_expired_cb;
89 	memset(&params, 0, sizeof(struct bt_le_adv_param));
90 
91 	params.options |= BT_LE_ADV_OPT_EXT_ADV;
92 	params.id = id;
93 	params.sid = 0;
94 	params.interval_min = BT_GAP_ADV_FAST_INT_MIN_1;
95 	params.interval_max = BT_GAP_ADV_FAST_INT_MAX_1;
96 
97 	err = bt_le_ext_adv_create(&params, &cb_adv, adv);
98 	if (err) {
99 		TEST_FAIL("Failed to create advertiser (%d)", err);
100 	}
101 }
102 
start_rpa_advertising(void)103 void start_rpa_advertising(void)
104 {
105 	int err;
106 	size_t bt_id_count;
107 
108 	/* Enable bluetooth */
109 	err = bt_enable(NULL);
110 	if (err) {
111 		TEST_FAIL("Failed to enable bluetooth (err %d)", err);
112 	}
113 
114 	err = settings_load();
115 	if (err) {
116 		TEST_FAIL("Failed to enable settings (err %d)", err);
117 	}
118 
119 	bt_id_get(NULL, &bt_id_count);
120 
121 	if (bt_id_count == 1) {
122 		int id_a;
123 		int id_b;
124 
125 		printk("No extra identity found in settings, creating new ones...\n");
126 
127 		id_a = bt_id_create(NULL, NULL);
128 		if (id_a != ID_1) {
129 			TEST_FAIL("bt_id_create id_a failed (err %d)", id_a);
130 		}
131 
132 		id_b = bt_id_create(NULL, NULL);
133 		if (id_b != ID_2) {
134 			TEST_FAIL("bt_id_create id_b failed (err %d)", id_b);
135 		}
136 	} else {
137 		printk("Extra identities loaded from settings\n");
138 	}
139 
140 	bt_id_get(NULL, &bt_id_count);
141 	if (bt_id_count != CONFIG_BT_ID_MAX) {
142 		TEST_FAIL("bt_id_get returned incorrect number of identities %u", bt_id_count);
143 	}
144 
145 	for (int i = 0; i < CONFIG_BT_EXT_ADV_MAX_ADV_SET; i++) {
146 		/* Create first 2 advertising sets with one id and last 2 advertising sets with
147 		 * different id.
148 		 */
149 		if (i < 2) {
150 			create_adv(&adv_set[i], ID_1);
151 		} else {
152 			create_adv(&adv_set[i], ID_2);
153 		}
154 		/* Set extended advertising data */
155 		err = bt_le_ext_adv_set_data(adv_set[i], &ad_id[i], 1, NULL, 0);
156 		if (err) {
157 			TEST_FAIL("Failed to set advertising data for set %d (err %d)", i, err);
158 		}
159 
160 		err = bt_le_ext_adv_start(adv_set[i], BT_LE_EXT_ADV_START_DEFAULT);
161 		if (err) {
162 			TEST_FAIL("Failed to start advertising (err %d)", err);
163 		}
164 	}
165 }
166 
dut_rpa_expired_procedure(void)167 void dut_rpa_expired_procedure(void)
168 {
169 	start_rpa_advertising();
170 
171 	/* Nothing to do */
172 	TEST_PASS("PASS");
173 }
174