blob: 915e61b9366bae982b5da052ed9a7a304ce321d4 [file] [log] [blame]
/**
* Copyright (c) 2024 Croxel, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gap.h>
static struct bt_conn *default_conn;
enum bt_sample_adv_evt {
BT_SAMPLE_EVT_CONNECTED,
BT_SAMPLE_EVT_DISCONNECTED,
BT_SAMPLE_EVT_MAX,
};
enum bt_sample_adv_st {
BT_SAMPLE_ST_ADV,
BT_SAMPLE_ST_CONNECTED,
};
static ATOMIC_DEFINE(evt_bitmask, BT_SAMPLE_EVT_MAX);
static volatile enum bt_sample_adv_st app_st = BT_SAMPLE_ST_ADV;
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_adv_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) {
return;
}
__ASSERT(!default_conn, "Attempting to override existing connection object!");
default_conn = bt_conn_ref(conn);
raise_evt(BT_SAMPLE_EVT_CONNECTED);
}
static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected (reason 0x%02X)\n", reason);
__ASSERT(conn == default_conn, "Unexpected disconnected callback");
bt_conn_unref(default_conn);
default_conn = NULL;
}
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 int start_advertising(struct bt_le_ext_adv *adv)
{
int err;
printk("Starting Extended Advertising\n");
err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
if (err) {
printk("Failed to start extended advertising (err %d)\n", err);
}
return err;
}
int main(void)
{
int err;
struct bt_le_ext_adv *adv;
printk("Starting Extended Advertising Demo\n");
/* Initialize the Bluetooth Subsystem */
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return err;
}
/* Create a non-connectable non-scannable advertising set */
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN_NAME, NULL, &adv);
if (err) {
printk("Failed to create advertising set (err %d)\n", err);
return err;
}
err = start_advertising(adv);
if (err) {
return err;
}
while (true) {
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_CONNECTED) &&
app_st == BT_SAMPLE_ST_ADV) {
printk("Connected state!\n");
app_st = BT_SAMPLE_ST_CONNECTED;
printk("Initiating disconnect within 5 seconds...\n");
k_sleep(K_SECONDS(5));
bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
} else if (atomic_test_and_clear_bit(evt_bitmask, BT_SAMPLE_EVT_DISCONNECTED) &&
app_st == BT_SAMPLE_ST_CONNECTED) {
printk("Disconnected state! Restarting advertising\n");
app_st = BT_SAMPLE_ST_ADV;
err = start_advertising(adv);
if (err) {
return err;
}
}
}
return err;
}