blob: b1b9262e23543676f707161a3331d12d6eeffa30 [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "utils.h"
#include "gatt_utils.h"
#include <zephyr/sys/__assert.h>
#include <zephyr/bluetooth/hci.h>
static struct bt_conn *default_conn;
DEFINE_FLAG(flag_is_connected);
DEFINE_FLAG(flag_test_end);
void wait_connected(void)
{
UNSET_FLAG(flag_is_connected);
WAIT_FOR_FLAG(flag_is_connected);
printk("connected\n");
}
void wait_disconnected(void)
{
SET_FLAG(flag_is_connected);
WAIT_FOR_FLAG_UNSET(flag_is_connected);
printk("disconnected\n");
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
__ASSERT_NO_MSG(default_conn == conn);
bt_conn_unref(default_conn);
default_conn = NULL;
UNSET_FLAG(flag_is_connected);
gatt_clear_flags();
}
static void connected(struct bt_conn *conn, uint8_t err)
{
struct bt_conn_info info = { 0 };
int ret;
if (err != 0) {
return;
}
ret = bt_conn_get_info(conn, &info);
__ASSERT_NO_MSG(ret == 0);
if (info.role == BT_CONN_ROLE_PERIPHERAL) {
__ASSERT_NO_MSG(default_conn == NULL);
default_conn = bt_conn_ref(conn);
}
__ASSERT_NO_MSG(default_conn != NULL);
SET_FLAG(flag_is_connected);
}
DEFINE_FLAG(flag_encrypted);
void security_changed(struct bt_conn *conn, bt_security_t level,
enum bt_security_err err)
{
__ASSERT(err == 0, "Error setting security (err %u)\n", err);
printk("Encrypted\n");
SET_FLAG(flag_encrypted);
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
.security_changed = security_changed,
};
static void scan_connect_to_first_result_device_found(const bt_addr_le_t *addr, int8_t rssi,
uint8_t type, struct net_buf_simple *ad)
{
char addr_str[BT_ADDR_LE_STR_LEN];
int err;
/* We're only interested in connectable events */
if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
FAIL("Unexpected advertisement type.");
}
bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
printk("Got scan result, connecting.. dst %s, RSSI %d\n",
addr_str, rssi);
err = bt_le_scan_stop();
__ASSERT(!err, "Err bt_le_scan_stop %d", err);
err = bt_conn_le_create(addr,
BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
&default_conn);
__ASSERT(!err, "Err bt_conn_le_create %d", err);
}
void scan_connect_to_first_result(void)
{
int err;
printk("start scanner\n");
err = bt_le_scan_start(BT_LE_SCAN_PASSIVE,
scan_connect_to_first_result_device_found);
__ASSERT(!err, "Err bt_le_scan_start %d", err);
}
void advertise_connectable(void)
{
printk("start advertiser\n");
int err;
struct bt_le_adv_param param = {};
param.interval_min = 0x0020;
param.interval_max = 0x4000;
param.options |= BT_LE_ADV_OPT_ONE_TIME;
param.options |= BT_LE_ADV_OPT_CONNECTABLE;
err = bt_le_adv_start(&param, NULL, 0, NULL, 0);
__ASSERT(err == 0, "Advertising failed to start (err %d)\n", err);
}
void disconnect(struct bt_conn *conn)
{
int err;
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
__ASSERT(!err, "Failed to initate disconnection (err %d)", err);
printk("Waiting for disconnection...\n");
WAIT_FOR_FLAG_UNSET(flag_is_connected);
}
struct bt_conn *get_conn(void)
{
return default_conn;
}
DEFINE_FLAG(flag_pairing_complete);
static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
{
FAIL("Pairing failed (unexpected): reason %u", reason);
}
static void pairing_complete(struct bt_conn *conn, bool bonded)
{
__ASSERT(bonded, "Bonding failed\n");
printk("Paired\n");
SET_FLAG(flag_pairing_complete);
}
static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = {
.pairing_failed = pairing_failed,
.pairing_complete = pairing_complete,
};
void set_security(struct bt_conn *conn, bt_security_t sec)
{
int err;
UNSET_FLAG(flag_encrypted);
err = bt_conn_set_security(conn, sec);
__ASSERT(!err, "Err bt_conn_set_security %d", err);
WAIT_FOR_FLAG(flag_encrypted);
}
void wait_secured(void)
{
UNSET_FLAG(flag_encrypted);
WAIT_FOR_FLAG(flag_encrypted);
}
void bond(struct bt_conn *conn)
{
UNSET_FLAG(flag_pairing_complete);
int err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb);
__ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n");
set_security(conn, BT_SECURITY_L2);
WAIT_FOR_FLAG(flag_pairing_complete);
}
void wait_bonded(void)
{
UNSET_FLAG(flag_encrypted);
UNSET_FLAG(flag_pairing_complete);
int err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb);
__ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n");
WAIT_FOR_FLAG(flag_encrypted);
WAIT_FOR_FLAG(flag_pairing_complete);
}
struct bt_conn *connect_as_central(void)
{
struct bt_conn *conn;
scan_connect_to_first_result();
wait_connected();
conn = get_conn();
return conn;
}
struct bt_conn *connect_as_peripheral(void)
{
struct bt_conn *conn;
advertise_connectable();
wait_connected();
conn = get_conn();
return conn;
}