Skip to content

Commit

Permalink
Bluetooth: host: Add support for new-style HCI drivers
Browse files Browse the repository at this point in the history
Add support for HCI drivers which use the newly defined HCI driver API.
Since Zephyr (currently) only supports a single HCI driver instance,
boards are expected to indicate the instance using a new devicetree
chosen property `zephyr,bt_hci`.

In order to maintain compatibility with not-yet-converted drivers the
code has been placed behind `#if DT_HAS_CHOSEN(zephyr_bt_hci)`
conditionals.

Signed-off-by: Johan Hedberg <[email protected]>
  • Loading branch information
jhedberg committed May 5, 2024
1 parent 77f82b4 commit 856fe90
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 7 deletions.
2 changes: 0 additions & 2 deletions include/zephyr/drivers/bluetooth/hci_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ enum {
BT_QUIRK_NO_AUTO_DLE = BIT(1),
};

#define IS_BT_QUIRK_NO_AUTO_DLE(bt_dev) ((bt_dev)->drv->quirks & BT_QUIRK_NO_AUTO_DLE)

/**
* @brief Receive data from the controller/HCI driver.
*
Expand Down
73 changes: 71 additions & 2 deletions subsys/bluetooth/host/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/hci_vs.h>
#if DT_HAS_CHOSEN(zephyr_bt_hci)
#include <zephyr/drivers/bluetooth.h>
#else
#include <zephyr/drivers/bluetooth/hci_driver.h>
#endif
#include <zephyr/dt-bindings/bluetooth/hci.h>

#include "common/bt_str.h"
#include "common/assert.h"
Expand Down Expand Up @@ -85,6 +90,9 @@ struct bt_dev bt_dev = {
#if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
.appearance = CONFIG_BT_DEVICE_APPEARANCE,
#endif
#if DT_HAS_CHOSEN(zephyr_bt_hci)
.hci = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci)),
#endif
};

static bt_ready_cb_t ready_cb;
Expand Down Expand Up @@ -112,6 +120,20 @@ static struct cmd_data cmd_data[CONFIG_BT_BUF_CMD_TX_COUNT];
#define cmd(buf) (&cmd_data[net_buf_id(buf)])
#define acl(buf) ((struct acl_data *)net_buf_user_data(buf))

static uint32_t drv_quirks(void)
{
#if DT_HAS_CHOSEN(zephyr_bt_hci)
struct bt_hci_info info;

bt_hci_get_info(bt_dev.hci, &info);

return info.quirks;
#else
return bt_dev.drv->quirks;
#endif

}

void bt_hci_cmd_state_set_init(struct net_buf *buf,
struct bt_hci_cmd_state_set *state,
atomic_t *target, int bit, bool val)
Expand Down Expand Up @@ -1132,7 +1154,7 @@ static void conn_auto_initiate(struct bt_conn *conn)

if (IS_ENABLED(CONFIG_BT_AUTO_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features)) {
if (IS_BT_QUIRK_NO_AUTO_DLE(&bt_dev)) {
if ((drv_quirks() & BT_HCI_QUIRK_NO_AUTO_DLE)) {
uint16_t tx_octets, tx_time;

err = hci_le_read_max_data_len(&tx_octets, &tx_time);
Expand Down Expand Up @@ -3113,7 +3135,7 @@ static int common_init(void)
struct net_buf *rsp;
int err;

if (!(bt_dev.drv->quirks & BT_QUIRK_NO_RESET)) {
if (!(drv_quirks() & BT_HCI_QUIRK_NO_RESET)) {
/* Send HCI_RESET */
err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, &rsp);
if (err) {
Expand Down Expand Up @@ -3813,12 +3835,19 @@ static int hci_init(void)
}
#endif /* defined(CONFIG_BT_HCI_SET_PUBLIC_ADDR) */

#if DT_HAS_CHOSEN(zephyr_bt_hci)
err = bt_hci_setup(bt_dev.hci, &setup_params);
if (err && err != -ENOSYS) {
return err;
}
#else
if (bt_dev.drv->setup) {
err = bt_dev.drv->setup(&setup_params);
if (err) {
return err;
}
}
#endif
#endif /* defined(CONFIG_BT_HCI_SETUP) */

err = common_init();
Expand Down Expand Up @@ -3873,7 +3902,11 @@ int bt_send(struct net_buf *buf)
return bt_hci_ecc_send(buf);
}

#if DT_HAS_CHOSEN(zephyr_bt_hci)
return bt_hci_send(bt_dev.hci, buf);
#else
return bt_dev.drv->send(buf);
#endif
}

static const struct event_handler prio_events[] = {
Expand Down Expand Up @@ -3975,8 +4008,14 @@ static int bt_recv_unsafe(struct net_buf *buf)
}
}

#if DT_HAS_CHOSEN(zephyr_bt_hci)
int bt_hci_recv(const struct device *dev, struct net_buf *buf)
{
ARG_UNUSED(dev);
#else
int bt_recv(struct net_buf *buf)
{
#endif
int err;

k_sched_lock();
Expand All @@ -3986,6 +4025,8 @@ int bt_recv(struct net_buf *buf)
return err;
}

/* Old-style HCI driver registration */
#if !DT_HAS_CHOSEN(zephyr_bt_hci)
int bt_hci_driver_register(const struct bt_hci_driver *drv)
{
if (bt_dev.drv) {
Expand All @@ -4005,6 +4046,7 @@ int bt_hci_driver_register(const struct bt_hci_driver *drv)

return 0;
}
#endif /* !DT_HAS_CHOSEN(zephyr_bt_hci) */

void bt_finalize_init(void)
{
Expand Down Expand Up @@ -4126,10 +4168,22 @@ int bt_enable(bt_ready_cb_t cb)
{
int err;

#if DT_HAS_CHOSEN(zephyr_bt_hci)
struct bt_hci_info info;

if (!device_is_ready(bt_dev.hci)) {
LOG_ERR("HCI driver is not ready");
return -ENODEV;
}

bt_hci_get_info(bt_dev.hci, &info);
bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, info.bus, BT_ADDR_ANY, info.name);
#else
if (!bt_dev.drv) {
LOG_ERR("No HCI driver registered");
return -ENODEV;
}
#endif

atomic_clear_bit(bt_dev.flags, BT_DEV_DISABLE);

Expand Down Expand Up @@ -4178,7 +4232,11 @@ int bt_enable(bt_ready_cb_t cb)
k_thread_name_set(&bt_workq.thread, "BT RX WQ");
#endif

#if DT_HAS_CHOSEN(zephyr_bt_hci)
err = bt_hci_open(bt_dev.hci, bt_hci_recv);
#else
err = bt_dev.drv->open();
#endif
if (err) {
LOG_ERR("HCI driver open failed (%d)", err);
return err;
Expand All @@ -4198,6 +4256,7 @@ int bt_disable(void)
{
int err;

#if !DT_HAS_CHOSEN(zephyr_bt_hci)
if (!bt_dev.drv) {
LOG_ERR("No HCI driver registered");
return -ENODEV;
Expand All @@ -4206,6 +4265,7 @@ int bt_disable(void)
if (!bt_dev.drv->close) {
return -ENOTSUP;
}
#endif

if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_DISABLE)) {
return -EALREADY;
Expand All @@ -4214,7 +4274,16 @@ int bt_disable(void)
/* Clear BT_DEV_READY before disabling HCI link */
atomic_clear_bit(bt_dev.flags, BT_DEV_READY);

#if DT_HAS_CHOSEN(zephyr_bt_hci)
err = bt_hci_close(bt_dev.hci);
if (err == -ENOSYS) {
atomic_clear_bit(bt_dev.flags, BT_DEV_DISABLE);
atomic_set_bit(bt_dev.flags, BT_DEV_READY);
return -ENOTSUP;
}
#else
err = bt_dev.drv->close();
#endif
if (err) {
LOG_ERR("HCI driver close failed (%d)", err);

Expand Down
8 changes: 8 additions & 0 deletions subsys/bluetooth/host/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,12 @@ struct bt_dev {
/* Queue for outgoing HCI commands */
struct k_fifo cmd_tx_queue;

#if DT_HAS_CHOSEN(zephyr_bt_hci)
const struct device *hci;
#else
/* Registered HCI driver */
const struct bt_hci_driver *drv;
#endif

#if defined(CONFIG_BT_PRIVACY)
/* Local Identity Resolving Key */
Expand Down Expand Up @@ -439,6 +443,10 @@ extern sys_slist_t bt_auth_info_cbs;
enum bt_security_err bt_security_err_get(uint8_t hci_err);
#endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC */

#if DT_HAS_CHOSEN(zephyr_bt_hci)
int bt_hci_recv(const struct device *dev, struct net_buf *buf);
#endif

/* Data type to store state related with command to be updated
* when command completes successfully.
*/
Expand Down
20 changes: 20 additions & 0 deletions subsys/bluetooth/host/hci_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dh.h>

#include <zephyr/drivers/bluetooth.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/buf.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/hci.h>
#if !DT_HAS_CHOSEN(zephyr_bt_hci)
#include <zephyr/drivers/bluetooth/hci_driver.h>
#endif

#include "common/bt_str.h"

Expand Down Expand Up @@ -92,7 +96,11 @@ static void send_cmd_status(uint16_t opcode, uint8_t status)
evt->opcode = sys_cpu_to_le16(opcode);
evt->status = status;

#if DT_HAS_CHOSEN(zephyr_bt_hci)
bt_hci_recv(bt_dev.hci, buf);
#else
bt_recv(buf);
#endif
}

static uint8_t generate_keys(void)
Expand Down Expand Up @@ -154,7 +162,11 @@ static void emulate_le_p256_public_key_cmd(void)

atomic_clear_bit(flags, PENDING_PUB_KEY);

#if DT_HAS_CHOSEN(zephyr_bt_hci)
bt_hci_recv(bt_dev.hci, buf);
#else
bt_recv(buf);
#endif
}

static void emulate_le_generate_dhkey(void)
Expand Down Expand Up @@ -202,7 +214,11 @@ static void emulate_le_generate_dhkey(void)

atomic_clear_bit(flags, PENDING_DHKEY);

#if DT_HAS_CHOSEN(zephyr_bt_hci)
bt_hci_recv(bt_dev.hci, buf);
#else
bt_recv(buf);
#endif
}

static void ecc_process(struct k_work *work)
Expand Down Expand Up @@ -327,7 +343,11 @@ int bt_hci_ecc_send(struct net_buf *buf)
}
}

#if DT_HAS_CHOSEN(zephyr_bt_hci)
return bt_hci_send(bt_dev.hci, buf);
#else
return bt_dev.drv->send(buf);
#endif
}

void bt_hci_ecc_supported_commands(uint8_t *supported_commands)
Expand Down
42 changes: 39 additions & 3 deletions subsys/bluetooth/host/hci_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,15 @@ NET_BUF_POOL_FIXED_DEFINE(hci_iso_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
sizeof(struct bt_buf_data), NULL);
#endif /* CONFIG_BT_ISO */

struct bt_dev_raw bt_dev;
struct bt_dev_raw bt_dev = {
#if DT_HAS_CHOSEN(zephyr_bt_hci)
.hci = DT_CHOSEN(zephyr_bt_hci),
#endif
};
struct bt_hci_raw_cmd_ext *cmd_ext;
static size_t cmd_ext_size;

#if !DT_HAS_CHOSEN(zephyr_bt_hci)
int bt_hci_driver_register(const struct bt_hci_driver *drv)
{
if (bt_dev.drv) {
Expand All @@ -77,6 +82,7 @@ int bt_hci_driver_register(const struct bt_hci_driver *drv)

return 0;
}
#endif

struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout)
{
Expand Down Expand Up @@ -178,12 +184,19 @@ struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout,
}

struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout)
#endif
{
return bt_buf_get_rx(BT_BUF_EVT, timeout);
}

#if DT_HAS_CHOSEN(zephyr_bt_hci)
int bt_hci_recv(const struct device *dev, struct net_buf *buf)
{
ARG_UNUSED(dev);
#else
int bt_recv(struct net_buf *buf)
{
#endif
LOG_DBG("buf %p len %u", buf, buf->len);

bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
Expand Down Expand Up @@ -228,7 +241,11 @@ static void bt_cmd_complete_ext(uint16_t op, uint8_t status)
cc = net_buf_add(buf, sizeof(*cc));
cc->status = status;

#if DT_HAS_CHOSEN(zephyr_bt_hci)
bt_hci_recv(bt_dev.hci, buf);
#else
bt_recv(buf);
#endif
}

static uint8_t bt_send_ext(struct net_buf *buf)
Expand Down Expand Up @@ -308,7 +325,11 @@ int bt_send(struct net_buf *buf)
return bt_hci_ecc_send(buf);
}

#if DT_HAS_CHOSEN(zephyr_bt_hci)
return bt_hci_send(bt_dev.hci, buf);
#else
return bt_dev.drv->send(buf);
#endif
}

int bt_hci_raw_set_mode(uint8_t mode)
Expand Down Expand Up @@ -346,19 +367,34 @@ void bt_hci_raw_cmd_ext_register(struct bt_hci_raw_cmd_ext *cmds, size_t size)

int bt_enable_raw(struct k_fifo *rx_queue)
{
const struct bt_hci_driver *drv = bt_dev.drv;
int err;

LOG_DBG("");

raw_rx = rx_queue;

if (!bt_dev.drv) {
#if DT_HAS_CHOSEN(zephyr_bt_hci)
struct bt_hci_info info;

if (!device_is_ready(bt_dev.hci)) {
LOG_ERR("HCI driver is not ready");
return -ENODEV;
}

bt_hci_get_info(bt_dev.hci, &info);
bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, info.bus, BT_ADDR_ANY, info.name);

err = bt_hci_open(bt_dev.hci, bt_recv);
#else
const struct bt_hci_driver *drv = bt_dev.drv;

if (!drv) {
LOG_ERR("No HCI driver registered");
return -ENODEV;
}

err = drv->open();
#endif
if (err) {
LOG_ERR("HCI driver open failed (%d)", err);
return err;
Expand Down
Loading

0 comments on commit 856fe90

Please sign in to comment.