Bluetooth: drivers: Convert userchan driver to new API

Convert the HCI User Channel driver to use the new HCI driver API.

Signed-off-by: Johan Hedberg <johan.hedberg@gmail.com>
This commit is contained in:
Johan Hedberg 2024-05-10 10:23:10 +03:00 committed by Anas Nashif
commit bb91aa0b7f
6 changed files with 63 additions and 42 deletions

View file

@ -22,10 +22,6 @@ config ETH_NATIVE_POSIX
endif # NETWORKING
config BT_USERCHAN
default y
depends on BT_HCI
if CONSOLE
config POSIX_ARCH_CONSOLE

View file

@ -22,10 +22,6 @@ config ETH_NATIVE_POSIX
endif # NETWORKING
config BT_USERCHAN
depends on BT_HCI
default y
if CONSOLE
config POSIX_ARCH_CONSOLE

View file

@ -24,6 +24,7 @@
zephyr,display = &sdl_dc;
zephyr,canbus = &can_loopback0;
zephyr,code-partition = &slot0_partition;
zephyr,bt-hci = &bt_hci_userchan;
};
aliases {
@ -218,4 +219,9 @@
#dma-cells = <1>;
stack-size = <4096>;
};
bt_hci_userchan: bt_hci_userchan {
compatible = "zephyr,bt-hci-userchan";
status = "okay";
};
};

View file

@ -85,6 +85,8 @@ config BT_SILABS_HCI
config BT_USERCHAN
bool "HCI User Channel based driver"
depends on BOARD_NATIVE_POSIX
default y
depends on DT_HAS_ZEPHYR_BT_HCI_USERCHAN_ENABLED
help
This driver provides access to the local Linux host's Bluetooth
adapter using a User Channel HCI socket to the Linux kernel. It

View file

@ -30,12 +30,20 @@
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/drivers/bluetooth/hci_driver.h>
#include <zephyr/drivers/bluetooth.h>
#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_driver);
#define DT_DRV_COMPAT zephyr_bt_hci_userchan
struct uc_data {
int fd;
bt_hci_recv_t recv;
};
#define BTPROTO_HCI 1
struct sockaddr_hci {
sa_family_t hci_family;
@ -50,8 +58,6 @@ static K_KERNEL_STACK_DEFINE(rx_thread_stack,
CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
static struct k_thread rx_thread_data;
static int uc_fd = -1;
static unsigned short bt_dev_index;
#define TCP_ADDR_BUFF_SIZE 16
@ -158,16 +164,18 @@ static int32_t hci_packet_complete(const uint8_t *buf, uint16_t buf_len)
return (int32_t)header_len + payload_len;
}
static bool uc_ready(void)
static bool uc_ready(int fd)
{
struct pollfd pollfd = { .fd = uc_fd, .events = POLLIN };
struct pollfd pollfd = { .fd = fd, .events = POLLIN };
return (poll(&pollfd, 1, 0) == 1);
}
static void rx_thread(void *p1, void *p2, void *p3)
{
ARG_UNUSED(p1);
const struct device *dev = p1;
struct uc_data *uc = dev->data;
ARG_UNUSED(p2);
ARG_UNUSED(p3);
@ -183,14 +191,14 @@ static void rx_thread(void *p1, void *p2, void *p3)
ssize_t len;
const uint8_t *frame_start = frame;
if (!uc_ready()) {
if (!uc_ready(uc->fd)) {
k_sleep(K_MSEC(1));
continue;
}
LOG_DBG("calling read()");
len = read(uc_fd, frame + frame_size, sizeof(frame) - frame_size);
len = read(uc->fd, frame + frame_size, sizeof(frame) - frame_size);
if (len < 0) {
if (errno == EINTR) {
k_yield();
@ -198,8 +206,8 @@ static void rx_thread(void *p1, void *p2, void *p3)
}
LOG_ERR("Reading socket failed, errno %d", errno);
close(uc_fd);
uc_fd = -1;
close(uc->fd);
uc->fd = -1;
return;
}
@ -256,18 +264,20 @@ static void rx_thread(void *p1, void *p2, void *p3)
LOG_DBG("Calling bt_recv(%p)", buf);
bt_recv(buf);
uc->recv(dev, buf);
}
k_yield();
}
}
static int uc_send(struct net_buf *buf)
static int uc_send(const struct device *dev, struct net_buf *buf)
{
struct uc_data *uc = dev->data;
LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
if (uc_fd < 0) {
if (uc->fd < 0) {
LOG_ERR("User channel not open");
return -EIO;
}
@ -290,7 +300,7 @@ static int uc_send(struct net_buf *buf)
return -EINVAL;
}
if (write(uc_fd, buf->data, buf->len) < 0) {
if (write(uc->fd, buf->data, buf->len) < 0) {
return -errno;
}
@ -350,25 +360,28 @@ static int user_chan_open(void)
return fd;
}
static int uc_open(void)
static int uc_open(const struct device *dev, bt_hci_recv_t recv)
{
struct uc_data *uc = dev->data;
if (hci_socket) {
LOG_DBG("hci%d", bt_dev_index);
} else {
LOG_DBG("hci %s:%d", ip_addr, port);
}
uc_fd = user_chan_open();
if (uc_fd < 0) {
return uc_fd;
uc->fd = user_chan_open();
if (uc->fd < 0) {
return uc->fd;
}
LOG_DBG("User Channel opened as fd %d", uc_fd);
uc->recv = recv;
LOG_DBG("User Channel opened as fd %d", uc->fd);
k_thread_create(&rx_thread_data, rx_thread_stack,
K_KERNEL_STACK_SIZEOF(rx_thread_stack),
rx_thread, NULL, NULL, NULL,
rx_thread, (void *)dev, NULL, NULL,
K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO),
0, K_NO_WAIT);
@ -377,22 +390,19 @@ static int uc_open(void)
return 0;
}
static const struct bt_hci_driver drv = {
.name = "HCI User Channel",
.bus = BT_HCI_DRIVER_BUS_UART,
.open = uc_open,
.send = uc_send,
static const struct bt_hci_driver_api uc_drv_api = {
.open = uc_open,
.send = uc_send,
};
static int bt_uc_init(void)
{
#define UC_DEVICE_INIT(inst) \
static struct uc_data uc_data_##inst = { \
.fd = -1, \
}; \
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &uc_data_##inst, NULL, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &uc_drv_api)
bt_hci_driver_register(&drv);
return 0;
}
SYS_INIT(bt_uc_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
DT_INST_FOREACH_STATUS_OKAY(UC_DEVICE_INIT)
static void cmd_bt_dev_found(char *argv, int offset)
{

View file

@ -0,0 +1,11 @@
description: Bluetooth HCI provided by a Linux HCI user channel socket
compatible: "zephyr,bt-hci-userchan"
include: bt-hci.yaml
properties:
bt-hci-name:
default: "HCI User Channel"
bt-hci-bus:
default: "BT_HCI_BUS_UART"