Parcourir la source

[esp-hosted][bt] add support for vhci device drivers and related configuration options

Evlers il y a 11 mois
Parent
commit
deeb4bfd45

+ 13 - 4
Kconfig

@@ -210,12 +210,21 @@ menuconfig RT_USING_ESP_HOSTED
 
             if ESP_HOSTED_BT_ENABLED
                 choice
-                    prompt "Select the stack type"
-                    default ESP_HOSTED_BT_NIMBLE_STACK
+                    prompt "Select hci interface"
+                    default ESP_HOSTED_BT_USING_VHCI_DEVICE_DRIVER
 
-                    config ESP_HOSTED_BT_NIMBLE_STACK
-                        bool "NimBLE"
+                    config ESP_HOSTED_BT_USING_VHCI_DEVICE_DRIVER
+                        bool "Using vhci device drivers"
+
+                    config ESP_HOSTED_BT_USING_NIMBLE_STACK
+                        bool "Using NimBLE hci drivers"
                 endchoice
+
+                if ESP_HOSTED_BT_USING_VHCI_DEVICE_DRIVER
+                    config ESP_HOSTED_VHCI_DEVICE_NAME
+                        string "The vhci device name"
+                        default "vhci"
+                endif
             endif
 
         menu "Wi-Fi Configure"

+ 12 - 2
SConscript

@@ -34,7 +34,6 @@ path += [cwd + '/esp-hosted/host/components/esp_wifi/include']
 path += [cwd + '/esp-hosted/host/components/esp_netif/include']
 
 # add host drivers source and header files
-src += Glob('esp-hosted/host/drivers/bt/*.c')
 src += Glob('esp-hosted/host/drivers/mempool/*.c')
 src += Glob('esp-hosted/host/drivers/rpc/core/*.c')
 src += Glob('esp-hosted/host/drivers/rpc/slaveif/*.c')
@@ -43,7 +42,6 @@ src += Glob('esp-hosted/host/drivers/serial/*.c')
 src += Glob('esp-hosted/host/drivers/transport/*.c')
 src += Glob('esp-hosted/host/drivers/transport/spi/*.c')
 src += Glob('esp-hosted/host/drivers/virtual_serial_if/*.c')
-path += [cwd + '/esp-hosted/host/drivers/bt']
 path += [cwd + '/esp-hosted/host/drivers/mempool']
 path += [cwd + '/esp-hosted/host/drivers/rpc/core']
 path += [cwd + '/esp-hosted/host/drivers/rpc/slaveif']
@@ -65,6 +63,18 @@ path += [cwd + '/porting/port/include']
 src += Glob('porting/ota/*.c')
 path += [cwd + '/porting/ota']
 
+# add bt source and header files
+if GetDepend(['ESP_HOSTED_BT_USING_VHCI_DEVICE_DRIVER']):
+    # add vhci device driver source and header files
+    src += Glob('porting/bt/*.c')
+    src += Glob('porting/bt/vhci/*.c')
+    path += [cwd + '/porting/bt/vhci']
+
+if GetDepend(['ESP_HOSTED_BT_USING_NIMBLE_STACK']):
+    # add nimble hci driver source and header files
+    src += Glob('esp-hosted/host/drivers/bt/*.c')
+path += [cwd + '/esp-hosted/host/drivers/bt']
+
 # add host wlan source files
 src += Glob('porting/wlan/*.c')
 

+ 27 - 23
esp-hosted/host/drivers/bt/vhci_drv.c

@@ -19,7 +19,8 @@
 #endif
 
 #include "esp_hosted_log.h"
-static const char TAG[] = "vhci_drv";
+
+#define TAG "vhci_drv"
 
 #if H_BT_HOST_ESP_NIMBLE
 struct hci_h4_sm hci_h4sm;
@@ -44,6 +45,7 @@ static int hci_uart_frame_cb(uint8_t pkt_type, void *data)
  */
 int hci_rx_handler(interface_buffer_handle_t *buf_handle)
 {
+	ESP_LOG_BUFFER_HEXDUMP(TAG " rx", buf_handle->payload, buf_handle->payload_len, ESP_LOG_DEBUG);
 #if H_BT_HOST_ESP_NIMBLE
 	hci_h4_sm_rx(&hci_h4sm, buf_handle->payload, buf_handle->payload_len);
 #endif /* H_BT_HOST_ESP_NIMBLE */
@@ -88,33 +90,35 @@ void ble_transport_ll_init(void)
 
 int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
 {
-	// TODO: zerocopy version
-
-	// calculate data length from the incoming data
-	int data_len = OS_MBUF_PKTLEN(om) + 1;
-
-	uint8_t * data = NULL;
 	int res;
+	struct os_mbuf *x = om;
 
-	data = g_h.funcs->_h_malloc(data_len);
-	if (!data) {
-		ESP_LOGE(TAG, "Tx %s: malloc failed", __func__);
-		res = ESP_FAIL;
-		goto exit;
-	}
+    while (x != NULL)
+    {
+		uint8_t *data = NULL;
+		int data_len = OS_MBUF_PKTLEN(x) + 1;
 
-	data[0] = HCI_H4_ACL;
-	res = ble_hs_mbuf_to_flat(om, &data[1], OS_MBUF_PKTLEN(om), NULL);
-	if (res) {
-		ESP_LOGE(TAG, "Tx: Error copying HCI_H4_ACL data %d", res);
-		res = ESP_FAIL;
-		goto exit;
-	}
+		data = g_h.funcs->_h_malloc(data_len);
+		if (!data) {
+			ESP_LOGE(TAG, "Tx %s: malloc failed", __func__);
+			res = ESP_FAIL;
+			goto exit;
+		}
+
+		data[0] = HCI_H4_ACL;
+		res = ble_hs_mbuf_to_flat(x, &data[1], OS_MBUF_PKTLEN(x), NULL);
+		if (res) {
+			ESP_LOGE(TAG, "Tx: Error copying HCI_H4_ACL data %d", res);
+			res = ESP_FAIL;
+			goto exit;
+		}
 
-	ESP_LOG_BUFFER_HEXDUMP(TAG, data, data_len, ESP_LOG_DEBUG);
+		ESP_LOG_BUFFER_HEXDUMP(TAG " tx", data, data_len, ESP_LOG_DEBUG);
 
-	res = esp_hosted_tx(ESP_HCI_IF, 0, data, data_len, H_BUFF_NO_ZEROCOPY, H_DEFLT_FREE_FUNC);
+		res = esp_hosted_tx(ESP_HCI_IF, 0, data, data_len, H_BUFF_NO_ZEROCOPY, H_DEFLT_FREE_FUNC);
 
+		x = SLIST_NEXT(x, om_next);
+	}
  exit:
 	os_mbuf_free_chain(om);
 
@@ -141,7 +145,7 @@ int ble_transport_to_ll_cmd_impl(void *buf)
 	data[0] = HCI_H4_CMD;
 	memcpy(&data[1], buf, buf_len - 1);
 
-	ESP_LOG_BUFFER_HEXDUMP(TAG, data, buf_len, ESP_LOG_DEBUG);
+	ESP_LOG_BUFFER_HEXDUMP(TAG " tx", data, buf_len, ESP_LOG_DEBUG);
 
 	res = esp_hosted_tx(ESP_HCI_IF, 0, data, buf_len, H_BUFF_NO_ZEROCOPY, H_DEFLT_FREE_FUNC);
 

+ 4 - 0
esp-hosted/host/utils/common.h

@@ -105,7 +105,11 @@ uint32_t hton_long (uint32_t x);
 typedef unsigned char   u_char;
 typedef unsigned long   u_long;
 
+
+#ifndef min
 int min(int x, int y);
+#endif
+
 #if 0
 void hard_delay(int x);
 int get_num_from_string(int *val, char *arg);

+ 34 - 0
porting/bt/vhci/drivers/vhci.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-01-19     Evlers       first version.
+ */
+
+#ifndef _VHCI_H_
+#define _VHCI_H_
+
+#include <rtdef.h>
+
+struct rt_vhci_ops
+{
+    rt_err_t (*init)(void);
+    rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);
+    rt_err_t  (*close)  (rt_device_t dev);
+    rt_ssize_t (*read)  (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
+    rt_ssize_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
+};
+
+typedef struct rt_vhci_device
+{
+    struct rt_device parent;
+    const struct rt_vhci_ops *ops;
+    rt_mutex_t lock;
+} rt_vhci_dev_t;
+
+rt_err_t rt_device_vhci_register(rt_vhci_dev_t *vhci, const char *name, rt_uint32_t flag, void *user_data);
+
+#endif /* _VHCI_H_ */

+ 150 - 0
porting/bt/vhci/vhci.c

@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-01-19     Evlers       first version.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <rtthread.h>
+#include <drivers/vhci.h>
+
+static rt_err_t rt_vhci_init(struct rt_device *dev)
+{
+    rt_vhci_dev_t *vhci_core;
+
+    RT_ASSERT(dev != RT_NULL);
+    vhci_core = (rt_vhci_dev_t *)dev;
+
+    if (vhci_core->ops->init)
+    {
+        vhci_core->lock = rt_mutex_create("vhci", RT_IPC_FLAG_FIFO);
+        return (vhci_core->ops->init());
+    }
+
+    return -RT_ENOSYS;
+}
+
+static rt_err_t rt_vhci_open(struct rt_device *dev, rt_uint16_t oflag)
+{
+    rt_vhci_dev_t *vhci_core;
+
+    RT_ASSERT(dev != RT_NULL);
+    vhci_core = (rt_vhci_dev_t *)dev;
+
+    if (vhci_core->ops->open)
+    {
+        rt_err_t ret;
+        rt_mutex_take(vhci_core->lock, RT_WAITING_FOREVER);
+        ret = (vhci_core->ops->open(dev, oflag));
+        rt_mutex_release(vhci_core->lock);
+        return ret;
+    }
+
+    return -RT_ENOSYS;
+}
+
+static rt_err_t rt_vhci_close(struct rt_device *dev)
+{
+    rt_vhci_dev_t *vhci_core;
+
+    RT_ASSERT(dev != RT_NULL);
+    vhci_core = (rt_vhci_dev_t *)dev;
+
+    if (vhci_core->ops->close)
+    {
+        rt_err_t ret;
+        rt_mutex_take(vhci_core->lock, RT_WAITING_FOREVER);
+        ret = (vhci_core->ops->close(dev));
+        rt_mutex_release(vhci_core->lock);
+        return ret;
+    }
+
+    return -RT_ENOSYS;
+}
+
+static rt_ssize_t rt_vhci_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    rt_vhci_dev_t *vhci_core;
+
+    RT_ASSERT(dev != RT_NULL);
+    vhci_core = (rt_vhci_dev_t *)dev;
+
+    if (vhci_core->ops->read)
+    {
+        rt_err_t ret;
+        rt_mutex_take(vhci_core->lock, RT_WAITING_FOREVER);
+        ret = (vhci_core->ops->read(dev, pos, buffer, size));
+        rt_mutex_release(vhci_core->lock);
+        return ret;
+    }
+
+    return -RT_ENOSYS;
+}
+
+static rt_ssize_t rt_vhci_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    rt_vhci_dev_t *vhci_core;
+
+    RT_ASSERT(dev != RT_NULL);
+    vhci_core = (rt_vhci_dev_t *)dev;
+
+    if (vhci_core->ops->write)
+    {
+        rt_err_t ret;
+        rt_mutex_take(vhci_core->lock, RT_WAITING_FOREVER);
+        ret = (vhci_core->ops->write(dev, pos, buffer, size));
+        rt_mutex_release(vhci_core->lock);
+        return ret;
+    }
+
+    return -RT_ENOSYS;
+}
+
+static rt_err_t rt_vhci_control(struct rt_device *dev, int cmd, void *args)
+{
+    return RT_EOK;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops vhci_core_ops =
+{
+    rt_vhci_init,
+    rt_vhci_open,
+    rt_vhci_close,
+    rt_vhci_read,
+    rt_vhci_write,
+    rt_vhci_control,
+};
+#endif /* RT_USING_DEVICE_OPS */
+
+rt_err_t rt_device_vhci_register(rt_vhci_dev_t *vhci, const char *name, rt_uint32_t flag, void *user_data)
+{
+    struct rt_device *device;
+    RT_ASSERT(vhci != RT_NULL);
+
+    device = &(vhci->parent);
+
+    device->type        = RT_Device_Class_Char;
+    device->rx_indicate = RT_NULL;
+    device->tx_complete = RT_NULL;
+
+#ifdef RT_USING_DEVICE_OPS
+    device->ops         = &vhci_core_ops;
+#else
+    device->init        = rt_vhci_init;
+    device->open        = rt_vhci_open;
+    device->close       = rt_vhci_close;
+    device->read        = rt_vhci_read;
+    device->write       = rt_vhci_write;
+    device->control     = rt_vhci_control;
+#endif /* RT_USING_DEVICE_OPS */
+    device->user_data   = user_data;
+
+    /* register a character device */
+    return rt_device_register(device, name, flag);
+}

+ 121 - 0
porting/bt/vhci_dev.c

@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006-2025 Evlers Developers
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2025-01-19   Evlers      first implementation
+ */
+
+#include <stdint.h>
+#include "rtthread.h"
+#include "rtdevice.h"
+#include "ipc/ringbuffer.h"
+#include "adapter.h"
+#include "os_wrapper.h"
+#include "transport_drv.h"
+#include "hci_drv.h"
+#include "esp_hosted_log.h"
+#include "drivers/vhci.h"
+
+static const char TAG[] = "vhci.dev";
+
+static struct rt_ringbuffer *vhci_rx_buffer = RT_NULL;
+
+void hci_drv_show_configuration(void)
+{
+	ESP_LOGI(TAG, "Host BT Support: Enabled");
+	ESP_LOGI(TAG, "BT Transport Type: vhci devices");
+}
+
+int hci_rx_handler(interface_buffer_handle_t *buf_handle)
+{
+    if (rt_ringbuffer_put(vhci_rx_buffer, buf_handle->payload, buf_handle->payload_len) != buf_handle->payload_len)
+    {
+        ESP_LOGE(TAG, "vhci_rx_buffer put failed");
+        return ESP_ERR_NO_MEM;
+    }
+	return ESP_OK;
+}
+
+static rt_err_t rt_vhci_init(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t rt_vhci_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    vhci_rx_buffer = rt_ringbuffer_create(1024);
+    if (vhci_rx_buffer == RT_NULL)
+    {
+        ESP_LOGE(TAG, "vhci_rx_buffer create failed");
+        return -RT_ERROR;
+    }
+    return RT_EOK;
+}
+
+static rt_err_t rt_vhci_close(rt_device_t dev)
+{
+    return RT_EOK;
+}
+
+static rt_ssize_t rt_vhci_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    rt_size_t read_size = 0;
+    rt_uint8_t *data = (rt_uint8_t *)buffer;
+    rt_size_t data_len = 0;
+
+    if (vhci_rx_buffer == RT_NULL)
+    {
+        ESP_LOGE(TAG, "vhci_rx_buffer is null");
+        return -RT_ERROR;
+    }
+
+    read_size = rt_ringbuffer_data_len(vhci_rx_buffer);
+    if (read_size == 0)
+    {
+        return 0;
+    }
+
+    data_len = read_size > size ? size : read_size;
+    rt_ringbuffer_get(vhci_rx_buffer, data, data_len);
+    return data_len;
+}
+
+static rt_ssize_t rt_vhci_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    uint8_t *data = g_h.funcs->_h_malloc(size);
+
+    if (!data)
+    {
+        ESP_LOGE(TAG, "Tx %s: malloc failed", __func__);
+        return -RT_ERROR;
+    }
+
+    memcpy(data, buffer, size);
+    if (esp_hosted_tx(ESP_HCI_IF, 0, data, size, H_BUFF_NO_ZEROCOPY, H_DEFLT_FREE_FUNC) != ESP_OK)
+    {
+        return -RT_ERROR;
+    }
+
+    return size;
+}
+
+static struct rt_vhci_ops vhci_ops =
+{
+    .init = rt_vhci_init,
+    .open = rt_vhci_open,
+    .close = rt_vhci_close,
+    .read = rt_vhci_read,
+    .write = rt_vhci_write
+};
+
+static rt_vhci_dev_t vhci_dev =
+{
+    .ops = &vhci_ops
+};
+
+void hci_drv_init(void)
+{
+    /* register virtual hci device */
+    rt_device_vhci_register(&vhci_dev, ESP_HOSTED_VHCI_DEVICE_NAME, RT_DEVICE_FLAG_RDWR, NULL);
+}

+ 2 - 1
porting/port/include/config_convert.h

@@ -77,7 +77,8 @@
 
 /* BT Configuration */
 #ifdef ESP_HOSTED_BT_ENABLED
-#ifdef ESP_HOSTED_BT_NIMBLE_STACK
+#define CONFIG_ESP_ENABLE_BT 1
+#ifdef ESP_HOSTED_BT_USING_NIMBLE_STACK
 #define CONFIG_BT_NIMBLE_ENABLED 1
 #endif
 #endif