1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "bs_bt_utils.h"
8
9 BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 2, "CONFIG_BT_MAX_PAIRED is too small.");
10 BUILD_ASSERT(CONFIG_BT_ID_MAX >= 3, "CONFIG_BT_ID_MAX is too small.");
11
12 DEFINE_FLAG(flag_is_connected);
13 struct bt_conn *g_conn;
14
wait_connected(void)15 void wait_connected(void)
16 {
17 WAIT_FOR_FLAG(flag_is_connected);
18 }
19
wait_disconnected(void)20 void wait_disconnected(void)
21 {
22 WAIT_FOR_FLAG_UNSET(flag_is_connected);
23 }
24
disconnected(struct bt_conn * conn,uint8_t reason)25 static void disconnected(struct bt_conn *conn, uint8_t reason)
26 {
27 UNSET_FLAG(flag_is_connected);
28 }
29
30 BUILD_ASSERT(CONFIG_BT_MAX_CONN == 1, "This test assumes a single link.");
connected(struct bt_conn * conn,uint8_t err)31 static void connected(struct bt_conn *conn, uint8_t err)
32 {
33 TEST_ASSERT((!g_conn || (conn == g_conn)), "Unexpected new connection.");
34
35 if (!g_conn) {
36 g_conn = bt_conn_ref(conn);
37 }
38
39 if (err != 0) {
40 clear_g_conn();
41 return;
42 }
43
44 SET_FLAG(flag_is_connected);
45 }
46
47 BT_CONN_CB_DEFINE(conn_callbacks) = {
48 .connected = connected,
49 .disconnected = disconnected,
50 };
51
clear_g_conn(void)52 void clear_g_conn(void)
53 {
54 struct bt_conn *conn;
55
56 conn = g_conn;
57 g_conn = NULL;
58 TEST_ASSERT(conn, "Test error: No g_conn!");
59 bt_conn_unref(conn);
60 }
61
62 /* The following flags are raised by events and lowered by test code. */
63 DEFINE_FLAG(flag_pairing_complete);
64 DEFINE_FLAG(flag_pairing_failed);
65
pairing_failed(struct bt_conn * conn,enum bt_security_err reason)66 static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
67 {
68 SET_FLAG(flag_pairing_failed);
69 }
70
pairing_complete(struct bt_conn * conn,bool bonded)71 static void pairing_complete(struct bt_conn *conn, bool bonded)
72 {
73 SET_FLAG(flag_pairing_complete);
74 }
75
76 static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = {
77 .pairing_failed = pairing_failed,
78 .pairing_complete = pairing_complete,
79 };
80
bs_bt_utils_setup(void)81 void bs_bt_utils_setup(void)
82 {
83 int err;
84
85 err = bt_enable(NULL);
86 TEST_ASSERT(!err, "bt_enable failed.");
87 err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb);
88 TEST_ASSERT(!err, "bt_conn_auth_info_cb_register failed.");
89 }
90
scan_connect_to_first_result__device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)91 static void scan_connect_to_first_result__device_found(const bt_addr_le_t *addr, int8_t rssi,
92 uint8_t type, struct net_buf_simple *ad)
93 {
94 char addr_str[BT_ADDR_LE_STR_LEN];
95 int err;
96
97 if (g_conn != NULL) {
98 return;
99 }
100
101 /* We're only interested in connectable events */
102 if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
103 TEST_FAIL("Unexpected advertisement type.");
104 }
105
106 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
107 printk("Got scan result, connecting.. dst %s, RSSI %d", addr_str, rssi);
108
109 err = bt_le_scan_stop();
110 TEST_ASSERT(!err, "Err bt_le_scan_stop %d", err);
111
112 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn);
113 TEST_ASSERT(!err, "Err bt_conn_le_create %d", err);
114 }
115
scan_connect_to_first_result(void)116 void scan_connect_to_first_result(void)
117 {
118 int err;
119
120 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, scan_connect_to_first_result__device_found);
121 TEST_ASSERT(!err, "Err bt_le_scan_start %d", err);
122 }
123
disconnect(void)124 void disconnect(void)
125 {
126 int err;
127
128 err = bt_conn_disconnect(g_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
129 TEST_ASSERT(!err, "Err bt_conn_disconnect %d", err);
130 }
131
set_security(bt_security_t sec)132 void set_security(bt_security_t sec)
133 {
134 int err;
135
136 err = bt_conn_set_security(g_conn, sec);
137 TEST_ASSERT(!err, "Err bt_conn_set_security %d", err);
138 }
139
advertise_connectable(int id,bt_addr_le_t * directed_dst)140 void advertise_connectable(int id, bt_addr_le_t *directed_dst)
141 {
142 int err;
143 struct bt_le_adv_param param = {};
144
145 param.id = id;
146 param.interval_min = 0x0020;
147 param.interval_max = 0x4000;
148 param.options |= BT_LE_ADV_OPT_CONN;
149
150 if (directed_dst) {
151 param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
152 param.peer = directed_dst;
153 }
154
155 err = bt_le_adv_start(¶m, NULL, 0, NULL, 0);
156 TEST_ASSERT(err == 0, "Advertising failed to start (err %d)", err);
157 }
158