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