1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdbool.h>
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/bluetooth/bluetooth.h>
11 #include <zephyr/logging/log.h>
12 #include <sys/types.h>
13
14 #include "ad.h"
15 #include "babblekit/testcase.h"
16
17 LOG_MODULE_REGISTER(advertiser, LOG_LEVEL_INF);
18
create_adv(struct bt_le_ext_adv ** adv)19 static void create_adv(struct bt_le_ext_adv **adv)
20 {
21 int err;
22 struct bt_le_adv_param params;
23
24 memset(¶ms, 0, sizeof(struct bt_le_adv_param));
25
26 params.options |= BT_LE_ADV_OPT_EXT_ADV;
27
28 params.id = BT_ID_DEFAULT;
29 params.sid = 0;
30 params.interval_min = BT_GAP_ADV_SLOW_INT_MIN;
31 params.interval_max = BT_GAP_ADV_SLOW_INT_MAX;
32
33 err = bt_le_ext_adv_create(¶ms, NULL, adv);
34 if (err) {
35 TEST_FAIL("Failed to create advertiser (%d)\n", err);
36 }
37 }
38
start_adv(struct bt_le_ext_adv * adv)39 static void start_adv(struct bt_le_ext_adv *adv)
40 {
41 int err;
42 int32_t timeout = 0;
43 uint8_t num_events = 0;
44
45 struct bt_le_ext_adv_start_param start_params;
46
47 start_params.timeout = timeout;
48 start_params.num_events = num_events;
49
50 err = bt_le_ext_adv_start(adv, &start_params);
51 if (err) {
52 TEST_FAIL("Failed to start advertiser (%d)\n", err);
53 }
54 }
55
ad_deserialize(const uint8_t * input,size_t input_size,struct bt_data output[])56 static size_t ad_deserialize(const uint8_t *input, size_t input_size, struct bt_data output[])
57 {
58 uint8_t type;
59 uint8_t data_len;
60 const uint8_t *data;
61
62 size_t idx = 0;
63 size_t ad_len = 0;
64
65 while (idx < input_size) {
66 data_len = input[idx] - 1;
67 type = input[idx + 1];
68 data = &input[idx + 2];
69
70 if (data_len + 2 > input_size - idx) {
71 TEST_FAIL("malformed advertising data, expected %d bytes of data but got "
72 "only %d "
73 "bytes",
74 data_len + 1, input_size - idx);
75 return -1;
76 }
77
78 output[ad_len].data = data;
79 output[ad_len].type = type;
80 output[ad_len].data_len = data_len;
81
82 ad_len += 1;
83 idx += data_len + 2;
84 }
85
86 return ad_len;
87 }
88
set_ad_data(struct bt_le_ext_adv * adv,const uint8_t * serialized_ad,size_t serialized_ad_size)89 static int set_ad_data(struct bt_le_ext_adv *adv, const uint8_t *serialized_ad,
90 size_t serialized_ad_size)
91 {
92 int err;
93 size_t ad_len = 0;
94 uint8_t max_ad_len = 10;
95
96 struct bt_data ad[max_ad_len];
97
98 ad_len = ad_deserialize(serialized_ad, serialized_ad_size, ad);
99
100 err = bt_le_ext_adv_set_data(adv, ad, ad_len, NULL, 0);
101 if (err != 0 && err != -EDOM) {
102 TEST_FAIL("Failed to set advertising data (%d)\n", err);
103 }
104
105 return err;
106 }
107
entrypoint_advertiser(void)108 void entrypoint_advertiser(void)
109 {
110 /* Test purpose:
111 *
112 * Verifies that we can send Advertising Data up to the size set in the
113 * Kconfig. And if we try to set data too large we get the correct
114 * error code.
115 *
116 * Two devices:
117 * - `advertiser`: tries to send the data
118 * - `scanner`: will receive the data and check that they match with the
119 * data sent
120 *
121 * Procedure:
122 * - [advertiser] try to use `test_ad1` as advertising data
123 * - [advertiser] get the expected error (adv or scan resp too large)
124 * - [advertiser] try to use `test_ad2` as advertising data
125 * - [advertiser] get a success
126 * - [advertiser] start advertiser
127 * - [scanner] start scanner
128 * - [scanner] wait until receiving advertising data matching `test_ad2`
129 *
130 * [verdict]
131 * - advertiser receives the correct error code when trying to set
132 * advertising data
133 * - scanner receives the correct data in advertising data
134 */
135 int err;
136 struct bt_le_ext_adv *adv = NULL;
137
138 TEST_START("advertiser");
139
140 err = bt_enable(NULL);
141 TEST_ASSERT(err == 0, "Can't enable Bluetooth (err %d)", err);
142
143 LOG_DBG("Bluetooth initialized");
144
145 create_adv(&adv);
146 LOG_DBG("Advertiser created");
147
148 err = set_ad_data(adv, test_ad1, ARRAY_SIZE(test_ad1));
149 TEST_ASSERT(err == -EDOM,
150 "Tried to set Advertising Data larger than the controller can accept, "
151 "expected failure with error code %d but got %d",
152 -EDOM, err);
153
154 err = set_ad_data(adv, test_ad2, ARRAY_SIZE(test_ad2));
155 TEST_ASSERT(err == 0,
156 "Tried to set Advertising Data as large as the maximum advertising data size "
157 "the controller can accept, expected success but got error code %d",
158 err);
159 LOG_DBG("AD set");
160
161 start_adv(adv);
162 LOG_DBG("Advertiser started");
163
164 TEST_PASS("advertiser");
165 }
166