blob: a4773830fc312f4ede3d17478476c5ae9e59117d [file] [log] [blame]
/**
* Copyright (c) 2024 Croxel, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#define NAME_LEN 30
static struct bt_conn *default_conn;
bt_addr_le_t ext_addr;
enum bt_sample_scan_evt {
BT_SAMPLE_EVT_EXT_ADV_FOUND,
BT_SAMPLE_EVT_CONNECTED,
BT_SAMPLE_EVT_DISCONNECTED,
BT_SAMPLE_EVT_SCAN_DUE,
BT_SAMPLE_EVT_MAX,
};
enum bt_sample_scan_st {
BT_SAMPLE_ST_SCANNING,
BT_SAMPLE_ST_CONNECTING,
BT_SAMPLE_ST_CONNECTED,
BT_SAMPLE_ST_COOLDOWN,
};
static volatile enum bt_sample_scan_st app_st = BT_SAMPLE_ST_SCANNING;
static ATOMIC_DEFINE(evt_bitmask, BT_SAMPLE_EVT_MAX);
static struct k_poll_signal poll_sig = K_POLL_SIGNAL_INITIALIZER(poll_sig);
static struct k_poll_event poll_evt = K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
K_POLL_MODE_NOTIFY_ONLY, &poll_sig);
static void raise_evt(enum bt_sample_scan_evt evt)
{
(void)atomic_set_bit(evt_bitmask, evt);
k_poll_signal_raise(poll_evt.signal, 1);
}
static void connected_cb(struct bt_conn *conn, uint8_t err)
{
printk("Connected (err 0x%02X)\n", err);
if (err) {
bt_conn_unref(default_conn);
default_conn = NULL;
return;
}
raise_evt(BT_SAMPLE_EVT_CONNECTED);
}
static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
{
bt_conn_unref(default_conn);
default_conn = NULL;
printk("Disconnected (reason 0x%02X)\n", reason);
}
static void recycled_cb(void)
{
printk("Connection object available from previous conn. Disconnect is complete!\n");
raise_evt(BT_SAMPLE_EVT_DISCONNECTED);
}
BT_CONN_CB_DEFINE(conn_cb) = {
.connected = connected_cb,
.disconnected = disconnected_cb,
.recycled = recycled_cb,
};
static void scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf)
{
if (info->adv_type & BT_GAP_ADV_TYPE_EXT_ADV &&
info->adv_props & BT_GAP_ADV_PROP_EXT_ADV &&
info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) {
/* Attempt connection request for device with extended advertisements */
memcpy(&ext_addr, info->addr, sizeof(ext_addr));
raise_evt(BT_SAMPLE_EVT_EXT_ADV_FOUND);
}
}
static struct bt_le_scan_cb scan_callbacks = {
.recv = scan_recv,
};
static inline int attempt_connection(void)
{
int err;
printk("Stopping scan\n");
err = bt_le_scan_stop();
if (err) {
printk("Failed to stop scan: %d\n", err);
return err;
}
err = bt_conn_le_create(&ext_addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM_DEFAULT, &default_conn);
if (err) {
printk("Failed to establish conn: %d\n", err);
return err;
}
return 0;
}
static inline int start_scanning(void)
{
int err;
err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
if (err) {
printk("failed (err %d)\n", err);
}
return err;
}
int main(void)
{
int err;
printk("Starting Extended Advertising Demo [Scanner]\n");
/* Initialize the Bluetooth Subsystem */
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return 0;
}
bt_le_scan_cb_register(&scan_callbacks);
err = start_scanning();
if (err) {
return err;
}
while (true) {
(void)k_poll(&poll_evt, 1, K_FOREVER);
k_poll_signal_reset(poll_evt.signal);
poll_evt.state = K_POLL_STATE_NOT_READY;
/* Identify event and act upon if applicable */
if (atomic_test_and_clear_bit(evt_bitmask, BT_SAMPLE_EVT_EXT_ADV_FOUND) &&
app_st == BT_SAMPLE_ST_SCANNING) {
printk("Found extended advertisement packet!\n");
app_st = BT_SAMPLE_ST_CONNECTING;
err = attempt_connection();
if (err) {
return err;
}
} else if (atomic_test_and_clear_bit(evt_bitmask, BT_SAMPLE_EVT_CONNECTED) &&
(app_st == BT_SAMPLE_ST_CONNECTING)) {
printk("Connected state!\n");
app_st = BT_SAMPLE_ST_CONNECTED;
} else if (atomic_test_and_clear_bit(evt_bitmask, BT_SAMPLE_EVT_DISCONNECTED) &&
(app_st == BT_SAMPLE_ST_CONNECTED)) {
printk("Disconnected, cooldown for 5 seconds!\n");
app_st = BT_SAMPLE_ST_COOLDOWN;
/* Wait a few seconds before starting to re-scan again... */
k_sleep(K_SECONDS(5));
raise_evt(BT_SAMPLE_EVT_SCAN_DUE);
} else if (atomic_test_and_clear_bit(evt_bitmask, BT_SAMPLE_EVT_SCAN_DUE) &&
(app_st == BT_SAMPLE_ST_COOLDOWN)) {
printk("Starting to scan for extended adv\n");
app_st = BT_SAMPLE_ST_SCANNING;
err = start_scanning();
if (err) {
return err;
}
}
}
return 0;
}