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(¶ms, 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(¶ms, &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