1 /* Copyright (c) 2023 Codecoup
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5 #include <zephyr/bluetooth/att.h>
6 #include <zephyr/bluetooth/bluetooth.h>
7 #include <zephyr/bluetooth/gatt.h>
8 #include <zephyr/bluetooth/l2cap.h>
9 #include <zephyr/sys/__assert.h>
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/logging/log.h>
12
13 #include "../common_defs.h"
14 #include "../test_utils.h"
15
16 #include <testlib/conn.h>
17 #include "testlib/scan.h"
18 #include "testlib/security.h"
19
20 LOG_MODULE_REGISTER(client, LOG_LEVEL_DBG);
21
22 DEFINE_FLAG(flag_attr_read_success);
23
gatt_attr_read_cb(struct bt_conn * conn,uint8_t att_err,struct bt_gatt_read_params * params,const void * data,uint16_t len)24 static uint8_t gatt_attr_read_cb(struct bt_conn *conn, uint8_t att_err,
25 struct bt_gatt_read_params *params, const void *data, uint16_t len)
26 {
27 __ASSERT_NO_MSG(!att_err);
28
29 SET_FLAG(flag_attr_read_success);
30
31 return BT_GATT_ITER_STOP;
32 }
33
gatt_attr_read(struct bt_conn * conn)34 static void gatt_attr_read(struct bt_conn *conn)
35 {
36 static struct bt_gatt_read_params params;
37 static struct bt_uuid_128 uuid;
38 int err;
39
40 memset(¶ms, 0, sizeof(params));
41 params.func = gatt_attr_read_cb;
42 params.by_uuid.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
43 params.by_uuid.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
44 memcpy(&uuid.uuid, TEST_CHRC_UUID, sizeof(uuid));
45 params.by_uuid.uuid = &uuid.uuid;
46
47 err = bt_gatt_read(conn, ¶ms);
48 __ASSERT_NO_MSG(!err);
49 }
50
51 DEFINE_FLAG(flag_conn_encrypted);
52
security_changed_cb(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)53 static void security_changed_cb(struct bt_conn *conn, bt_security_t level,
54 enum bt_security_err err)
55 {
56 if (err != BT_SECURITY_ERR_SUCCESS || level < BT_SECURITY_L2) {
57 return;
58 }
59
60 SET_FLAG(flag_conn_encrypted);
61 }
62
63 static struct bt_conn_cb conn_cb = {
64 .security_changed = security_changed_cb,
65 };
66
test_client(void)67 static void test_client(void)
68 {
69 struct bt_conn *conn = NULL;
70 bt_addr_le_t scan_result;
71 int err;
72
73 err = bt_enable(NULL);
74 __ASSERT_NO_MSG(!err);
75
76 bt_conn_cb_register(&conn_cb);
77
78 err = bt_testlib_scan_find_name(&scan_result, "d1");
79 __ASSERT_NO_MSG(!err);
80
81 err = bt_testlib_connect(&scan_result, &conn);
82 __ASSERT_NO_MSG(!err);
83
84 /* Read characteristic value that requires encryption */
85 gatt_attr_read(conn);
86
87 /* Expect link encryption */
88 WAIT_FOR_FLAG(flag_conn_encrypted);
89
90 /* Wait for successful Read Response */
91 WAIT_FOR_FLAG(flag_attr_read_success);
92
93 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
94 __ASSERT_NO_MSG(!err);
95
96 bt_conn_unref(conn);
97 conn = NULL;
98
99 PASS("PASS\n");
100 }
101
102 DEFINE_FLAG(flag_pairing_in_progress);
103
auth_cancel_cb(struct bt_conn * conn)104 static void auth_cancel_cb(struct bt_conn *conn)
105 {
106
107 }
108
auth_pairing_confirm_cb(struct bt_conn * conn)109 static void auth_pairing_confirm_cb(struct bt_conn *conn)
110 {
111 SET_FLAG(flag_pairing_in_progress);
112 }
113
114 static struct bt_conn_auth_cb auth_cb = {
115 .cancel = auth_cancel_cb,
116 .pairing_confirm = auth_pairing_confirm_cb,
117 };
118
test_client_security_request(void)119 static void test_client_security_request(void)
120 {
121 struct bt_conn *conn = NULL;
122 bt_addr_le_t scan_result;
123 int err;
124
125 err = bt_enable(NULL);
126 __ASSERT_NO_MSG(!err);
127
128 bt_conn_cb_register(&conn_cb);
129
130 err = bt_conn_auth_cb_register(&auth_cb);
131 __ASSERT_NO_MSG(!err);
132
133 err = bt_testlib_scan_find_name(&scan_result, "d1");
134 __ASSERT_NO_MSG(!err);
135
136 err = bt_testlib_connect(&scan_result, &conn);
137 __ASSERT_NO_MSG(!err);
138
139 /* Wait for peripheral to initaiate pairing */
140 WAIT_FOR_FLAG(flag_pairing_in_progress);
141
142 /* Read characteristic value that requires encryption */
143 gatt_attr_read(conn);
144
145 /* Accept pairing */
146 err = bt_conn_auth_pairing_confirm(conn);
147 __ASSERT_NO_MSG(!err);
148
149 /* Expect link encryption */
150 WAIT_FOR_FLAG(flag_conn_encrypted);
151
152 /* Wait for successful Read Response */
153 WAIT_FOR_FLAG(flag_attr_read_success);
154
155 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
156 __ASSERT_NO_MSG(!err);
157
158 bt_conn_unref(conn);
159 conn = NULL;
160
161 PASS("PASS\n");
162 }
163
164 static const struct bst_test_instance client_tests[] = {
165 {
166 .test_id = "test_client",
167 .test_pre_init_f = test_init,
168 .test_tick_f = test_tick,
169 .test_main_f = test_client,
170 },
171 {
172 .test_id = "test_client_security_request",
173 .test_pre_init_f = test_init,
174 .test_tick_f = test_tick,
175 .test_main_f = test_client_security_request,
176 },
177 BSTEST_END_MARKER,
178 };
179
client_tests_install(struct bst_test_list * tests)180 static struct bst_test_list *client_tests_install(struct bst_test_list *tests)
181 {
182 return bst_add_tests(tests, client_tests);
183 };
184
185 bst_test_install_t test_installers[] = {
186 client_tests_install,
187 NULL
188 };
189
main(void)190 int main(void)
191 {
192 bst_main();
193
194 return 0;
195 }
196