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