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(&param, NULL, 0, NULL, 0);
156 	TEST_ASSERT(err == 0, "Advertising failed to start (err %d)", err);
157 }
158