mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
wireless/bluetooth: add BT/BLE dual mode bridge driver
Change-Id: I692228fda27df1a4249f11474ff50a1049becf4b Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include <nuttx/timers/oneshot.h>
|
||||
#include <nuttx/wireless/pktradio.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_driver.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_uart_bridge.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_null.h>
|
||||
#include <nuttx/wireless/ieee802154/ieee802154_loopback.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
@@ -354,6 +355,17 @@ int sim_bringup(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BLUETOOTH_UART_BRIDGE
|
||||
/* Register the Bluetooth BT/BLE dual mode bridge driver */
|
||||
|
||||
ret = bt_uart_bridge_register("/dev/ttyHCI0",
|
||||
"/dev/ttyBT", "/dev/ttyBLE");
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: bt_uart_bridge_register() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SIM_I2CBUS
|
||||
/* Initialize the i2c master bus device */
|
||||
|
||||
|
||||
@@ -57,6 +57,13 @@ config BLUETOOTH_UART_DUMP
|
||||
|
||||
endif # BLUETOOTH_UART
|
||||
|
||||
config BLUETOOTH_UART_BRIDGE
|
||||
bool "Bluetooth BT/BLE Dual Mode UART Bridge Driver"
|
||||
select MM_CIRCBUF
|
||||
default n
|
||||
---help---
|
||||
Enable Bluetooth BT/BLE Dual Mode UART Bridge Driver.
|
||||
|
||||
config BLUETOOTH_NULL
|
||||
bool "NULL Bluetooth device"
|
||||
default n
|
||||
|
||||
@@ -55,6 +55,11 @@ CSRCS += bt_uart_bcm4343x.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BLUETOOTH_UART_BRIDGE),y)
|
||||
CSRCS += bt_uart_bridge.c
|
||||
CSRCS += bt_uart_filter.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BLUETOOTH_NULL),y)
|
||||
CSRCS += bt_null.c
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,433 @@
|
||||
/****************************************************************************
|
||||
* drivers/wireless/bluetooth/bt_uart_bridge.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/mm/circbuf.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_uart.h>
|
||||
|
||||
#include "bt_uart_filter.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define HCI_RECVBUF_SIZE 2048
|
||||
#define HCI_SENDBUF_SIZE 1024
|
||||
#define HCI_NPOLLWAITERS 2
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
union bt_hci_hdr_u
|
||||
{
|
||||
struct bt_hci_cmd_hdr_s cmd;
|
||||
struct bt_hci_acl_hdr_s acl;
|
||||
struct bt_hci_iso_hdr_s iso;
|
||||
struct bt_hci_evt_hdr_s evt;
|
||||
};
|
||||
|
||||
struct bt_uart_bridge_device_s
|
||||
{
|
||||
FAR struct bt_uart_bridge_s *bridge;
|
||||
|
||||
struct bt_uart_filter_s filter;
|
||||
|
||||
struct circbuf_s recvbuf;
|
||||
sem_t recvlock;
|
||||
uint8_t sendbuf[HCI_SENDBUF_SIZE];
|
||||
size_t sendlen;
|
||||
};
|
||||
|
||||
struct bt_uart_bridge_s
|
||||
{
|
||||
struct bt_uart_bridge_device_s device[BT_UART_FILTER_TYPE_COUNT];
|
||||
|
||||
sem_t recvlock;
|
||||
sem_t sendlock;
|
||||
|
||||
struct file filep;
|
||||
uint8_t tmpbuf[HCI_RECVBUF_SIZE];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int bt_uart_bridge_open (FAR struct file *filep);
|
||||
static int bt_uart_bridge_close (FAR struct file *filep);
|
||||
static ssize_t bt_uart_bridge_read (FAR struct file *filep,
|
||||
FAR char *buffer, size_t buflen);
|
||||
static ssize_t bt_uart_bridge_write (FAR struct file *filep,
|
||||
FAR const char *buffer, size_t buflen);
|
||||
static int bt_uart_bridge_ioctl (FAR struct file *filep,
|
||||
int cmd, unsigned long arg);
|
||||
static int bt_uart_bridge_poll (FAR struct file *filep,
|
||||
FAR struct pollfd *fds, bool setup);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_hcibridge_ops =
|
||||
{
|
||||
.open = bt_uart_bridge_open,
|
||||
.close = bt_uart_bridge_close,
|
||||
.read = bt_uart_bridge_read,
|
||||
.write = bt_uart_bridge_write,
|
||||
.ioctl = bt_uart_bridge_ioctl,
|
||||
.poll = bt_uart_bridge_poll
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t
|
||||
bt_uart_circbuf_read(FAR struct bt_uart_bridge_device_s *device,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&device->recvlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = circbuf_read(&device->recvbuf, buffer, buflen);
|
||||
|
||||
nxsem_post(&device->recvlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bt_uart_circbuf_write(FAR struct bt_uart_bridge_device_s *device,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&device->recvlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (circbuf_space(&device->recvbuf) >= buflen)
|
||||
{
|
||||
ret = circbuf_write(&device->recvbuf, buffer, buflen);
|
||||
}
|
||||
|
||||
nxsem_post(&device->recvlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bt_uart_bridge_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bt_uart_bridge_device_s *device = inode->i_private;
|
||||
|
||||
if (filep->f_inode->i_crefs == 0)
|
||||
{
|
||||
device->sendlen = 0;
|
||||
circbuf_reset(&device->recvbuf);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int bt_uart_bridge_close(FAR struct file *filep)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
static ssize_t bt_uart_bridge_read(FAR struct file *filep,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bt_uart_bridge_device_s *device = inode->i_private;
|
||||
FAR struct bt_uart_bridge_s *bridge = device->bridge;
|
||||
FAR struct bt_uart_bridge_device_s *iterator;
|
||||
int recvlen;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = bt_uart_circbuf_read(device, buffer, buflen);
|
||||
if (ret != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&bridge->recvlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (circbuf_is_empty(&device->recvbuf))
|
||||
{
|
||||
recvlen = file_read(&bridge->filep,
|
||||
bridge->tmpbuf, HCI_RECVBUF_SIZE);
|
||||
if (recvlen < 0)
|
||||
{
|
||||
nxsem_post(&bridge->recvlock);
|
||||
return recvlen;
|
||||
}
|
||||
|
||||
for (i = 0; i < BT_UART_FILTER_TYPE_COUNT; i++)
|
||||
{
|
||||
iterator = &bridge->device[i];
|
||||
if (bt_uart_filter_forward_recv(&iterator->filter,
|
||||
bridge->tmpbuf, recvlen))
|
||||
{
|
||||
bt_uart_circbuf_write(iterator, bridge->tmpbuf, recvlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&bridge->recvlock);
|
||||
|
||||
return bt_uart_circbuf_read(device, buffer, buflen);
|
||||
}
|
||||
|
||||
static ssize_t bt_uart_bridge_write(FAR struct file *filep,
|
||||
FAR const char *buffer, size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bt_uart_bridge_device_s *device = inode->i_private;
|
||||
FAR struct bt_uart_bridge_s *bridge = device->bridge;
|
||||
FAR union bt_hci_hdr_u *hdr;
|
||||
size_t pktlen;
|
||||
size_t hdrlen;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&bridge->sendlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (device->sendlen + buflen > HCI_SENDBUF_SIZE)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(device->sendbuf + device->sendlen, buffer, buflen);
|
||||
device->sendlen += buflen;
|
||||
|
||||
hdr = (FAR union bt_hci_hdr_u *)(device->sendbuf + 1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (device->sendbuf[0])
|
||||
{
|
||||
case H4_CMD:
|
||||
hdrlen = sizeof(struct bt_hci_cmd_hdr_s);
|
||||
pktlen = hdr->cmd.param_len;
|
||||
break;
|
||||
case H4_ACL:
|
||||
hdrlen = sizeof(struct bt_hci_acl_hdr_s);
|
||||
pktlen = hdr->acl.len;
|
||||
break;
|
||||
case H4_ISO:
|
||||
hdrlen = sizeof(struct bt_hci_iso_hdr_s);
|
||||
pktlen = hdr->iso.len;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Reassembly is incomplete ? */
|
||||
|
||||
hdrlen += H4_HEADER_SIZE;
|
||||
|
||||
if (device->sendlen < hdrlen)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
pktlen += hdrlen;
|
||||
if (device->sendlen < pktlen)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Got the full packet, check and send out */
|
||||
|
||||
if (bt_uart_filter_forward_send(&device->filter,
|
||||
device->sendbuf, pktlen))
|
||||
{
|
||||
ret = file_write(&bridge->filep, device->sendbuf, pktlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
device->sendlen -= pktlen;
|
||||
if (device->sendlen == 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
memmove(device->sendbuf, device->sendbuf + pktlen, device->sendlen);
|
||||
}
|
||||
|
||||
err:
|
||||
device->sendlen = 0;
|
||||
out:
|
||||
nxsem_post(&bridge->sendlock);
|
||||
return ret < 0 ? ret : buflen;
|
||||
}
|
||||
|
||||
static int bt_uart_bridge_ioctl(FAR struct file *filep,
|
||||
int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bt_uart_bridge_device_s *device = inode->i_private;
|
||||
FAR struct bt_uart_bridge_s *bridge = device->bridge;
|
||||
|
||||
return file_ioctl(&bridge->filep, cmd, arg);
|
||||
}
|
||||
|
||||
static int bt_uart_bridge_poll(FAR struct file *filep,
|
||||
FAR struct pollfd *fds, bool setup)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bt_uart_bridge_device_s *device = inode->i_private;
|
||||
FAR struct bt_uart_bridge_s *bridge = device->bridge;
|
||||
int ret;
|
||||
|
||||
ret = file_poll(&bridge->filep, fds, setup);
|
||||
if (setup && ret >= 0 && !circbuf_is_empty(&device->recvbuf))
|
||||
{
|
||||
fds->revents |= POLLIN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int bt_uart_bridge_register(const char *hciname,
|
||||
const char *btname, const char *blename)
|
||||
{
|
||||
FAR struct bt_uart_bridge_device_s *device;
|
||||
FAR struct bt_uart_bridge_s *bridge;
|
||||
int i = 0;
|
||||
int ret;
|
||||
FAR const char *bridges[] =
|
||||
{
|
||||
btname,
|
||||
blename
|
||||
};
|
||||
|
||||
if (!hciname || (!btname && !blename))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bridge = (FAR struct bt_uart_bridge_s *)
|
||||
kmm_zalloc(sizeof(struct bt_uart_bridge_s));
|
||||
if (bridge == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nxsem_init(&bridge->recvlock, 0, 1);
|
||||
nxsem_init(&bridge->sendlock, 0, 1);
|
||||
|
||||
ret = file_open(&bridge->filep, hciname, O_RDWR);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_file;
|
||||
}
|
||||
|
||||
for (i = 0; i < BT_UART_FILTER_TYPE_COUNT; i++)
|
||||
{
|
||||
if (!bridges[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
device = &bridge->device[i];
|
||||
|
||||
device->bridge = bridge;
|
||||
bt_uart_filter_init(&device->filter, i);
|
||||
nxsem_init(&device->recvlock, 0, 1);
|
||||
|
||||
ret = circbuf_init(&device->recvbuf, NULL, HCI_RECVBUF_SIZE);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_circbuf;
|
||||
}
|
||||
|
||||
ret = register_driver(bridges[i], &g_hcibridge_ops, 0666, device);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_device;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
for (; i >= 0; i--)
|
||||
{
|
||||
if (!bridges[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
device = &bridge->device[i];
|
||||
unregister_driver(bridges[i]);
|
||||
err_device:
|
||||
circbuf_uninit(&device->recvbuf);
|
||||
err_circbuf:
|
||||
nxsem_destroy(&device->recvlock);
|
||||
}
|
||||
|
||||
file_close(&bridge->filep);
|
||||
|
||||
err_file:
|
||||
nxsem_destroy(&bridge->recvlock);
|
||||
nxsem_destroy(&bridge->sendlock);
|
||||
|
||||
kmm_free(bridge);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/****************************************************************************
|
||||
* drivers/wireless/bluetooth/bt_uart_filter.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_uart.h>
|
||||
|
||||
#include "bt_uart_filter.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const uint8_t g_bt_uart_filter_bt_evt_table[] =
|
||||
{
|
||||
BT_HCI_EVT_INQUIRY_COMPLETE,
|
||||
BT_HCI_EVT_CONN_COMPLETE,
|
||||
BT_HCI_EVT_CONN_REQUEST,
|
||||
BT_HCI_EVT_AUTH_COMPLETE,
|
||||
BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE,
|
||||
BT_HCI_EVT_REMOTE_FEATURES,
|
||||
BT_HCI_EVT_ROLE_CHANGE,
|
||||
BT_HCI_EVT_PIN_CODE_REQ,
|
||||
BT_HCI_EVT_LINK_KEY_NOTIFY,
|
||||
BT_HCI_EVT_LINK_KEY_REQ,
|
||||
BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI,
|
||||
BT_HCI_EVT_REMOTE_EXT_FEATURES,
|
||||
BT_HCI_EVT_SYNC_CONN_COMPLETE,
|
||||
BT_HCI_EVT_EXTENDED_INQUIRY_RESULT,
|
||||
BT_HCI_EVT_IO_CAPA_RESP,
|
||||
BT_HCI_EVT_IO_CAPA_REQ,
|
||||
BT_HCI_EVT_SSP_COMPLETE,
|
||||
BT_HCI_EVT_USER_CONFIRM_REQ,
|
||||
BT_HCI_EVT_USER_PASSKEY_REQ,
|
||||
BT_HCI_EVT_USER_PASSKEY_NOTIFY,
|
||||
BT_HCI_EVT_PAGE_SCAN_REP_MODE_CHNG,
|
||||
BT_HCI_EVT_CONN_PKT_TYPE_CHANGE,
|
||||
BT_HCI_EVT_READ_CLOCK_OFF_COMP,
|
||||
BT_HCI_EVT_MAX_SLOTS_CHANGED,
|
||||
BT_HCI_EVT_MODE_CHANGE,
|
||||
BT_HCI_EVT_QOS_SETUP_COMP,
|
||||
BT_HCI_EVT_LINK_SUPER_TOUT_CHANGED,
|
||||
};
|
||||
|
||||
static const uint8_t g_bt_uart_filter_ble_evt_table[] =
|
||||
{
|
||||
BT_HCI_EVT_LE_META_EVENT,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static bool bt_uart_filter_set_handle(FAR struct bt_uart_filter_s *filter,
|
||||
int old, int new)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BT_UART_FILTER_CONN_COUNT; i++)
|
||||
{
|
||||
if (filter->handle[i] == old)
|
||||
{
|
||||
filter->handle[i] = new & 0xfff;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bt_uart_filter_alloc_handle(FAR struct bt_uart_filter_s *filter,
|
||||
int handle)
|
||||
{
|
||||
return bt_uart_filter_set_handle(filter, 0, handle);
|
||||
}
|
||||
|
||||
static bool bt_uart_filter_free_handle(FAR struct bt_uart_filter_s *filter,
|
||||
int handle)
|
||||
{
|
||||
return bt_uart_filter_set_handle(filter, handle, 0);
|
||||
}
|
||||
|
||||
static bool bt_uart_filter_has_handle(FAR struct bt_uart_filter_s *filter,
|
||||
int handle)
|
||||
{
|
||||
return bt_uart_filter_set_handle(filter, handle, handle);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
bool bt_uart_filter_forward_recv(FAR struct bt_uart_filter_s *filter,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
FAR const uint8_t *evt_table;
|
||||
int size;
|
||||
int i;
|
||||
|
||||
if (buffer[0] == H4_EVT)
|
||||
{
|
||||
if (filter->type == BT_UART_FILTER_TYPE_BLE)
|
||||
{
|
||||
evt_table = g_bt_uart_filter_bt_evt_table;
|
||||
size = sizeof(g_bt_uart_filter_bt_evt_table);
|
||||
}
|
||||
else
|
||||
{
|
||||
evt_table = g_bt_uart_filter_ble_evt_table;
|
||||
size = sizeof(g_bt_uart_filter_ble_evt_table);
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (buffer[1] == evt_table[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (buffer[1])
|
||||
{
|
||||
case BT_HCI_EVT_LE_META_EVENT:
|
||||
if (buffer[3] == BT_HCI_EVT_LE_CONN_COMPLETE)
|
||||
{
|
||||
FAR struct bt_hci_evt_le_conn_complete_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[4];
|
||||
if (evt->status == 0)
|
||||
{
|
||||
return bt_uart_filter_alloc_handle(filter, evt->handle);
|
||||
}
|
||||
}
|
||||
else if (buffer[3] == BT_HCI_EVT_LE_ENH_CONN_COMPLETE)
|
||||
{
|
||||
FAR struct bt_hci_evt_le_enh_conn_complete_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[4];
|
||||
if (evt->status == 0)
|
||||
{
|
||||
return bt_uart_filter_alloc_handle(filter, evt->handle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BT_HCI_EVT_CONN_COMPLETE:
|
||||
{
|
||||
FAR struct bt_hci_evt_conn_complete_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[3];
|
||||
if (evt->status == 0)
|
||||
{
|
||||
return bt_uart_filter_alloc_handle(filter, evt->handle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
|
||||
{
|
||||
FAR struct bt_hci_evt_num_completed_packets_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[3];
|
||||
return bt_uart_filter_has_handle(filter, evt->h[0].handle);
|
||||
}
|
||||
break;
|
||||
case BT_HCI_EVT_REMOTE_VERSION_INFO:
|
||||
{
|
||||
FAR struct bt_hci_evt_remote_version_info_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[3];
|
||||
return bt_uart_filter_has_handle(filter, evt->handle);
|
||||
}
|
||||
break;
|
||||
case BT_HCI_EVT_ENCRYPT_CHANGE:
|
||||
{
|
||||
FAR struct bt_hci_evt_encrypt_change_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[3];
|
||||
return bt_uart_filter_has_handle(filter, evt->handle);
|
||||
}
|
||||
break;
|
||||
case BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE:
|
||||
{
|
||||
FAR struct bt_hci_evt_encrypt_key_refresh_complete_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[3];
|
||||
return bt_uart_filter_has_handle(filter, evt->handle);
|
||||
}
|
||||
break;
|
||||
case BT_HCI_EVT_DISCONN_COMPLETE:
|
||||
{
|
||||
FAR struct bt_hci_evt_disconn_complete_s *evt;
|
||||
|
||||
evt = (FAR void *)&buffer[3];
|
||||
return bt_uart_filter_free_handle(filter, evt->handle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (buffer[0] == H4_ACL)
|
||||
{
|
||||
FAR struct bt_hci_acl_hdr_s *acl = (FAR void *)&buffer[1];
|
||||
|
||||
return bt_uart_filter_has_handle(filter, acl->handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bt_uart_filter_forward_send(FAR struct bt_uart_filter_s *filter,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
uint16_t opcode;
|
||||
|
||||
if (buffer[0] == H4_CMD)
|
||||
{
|
||||
opcode = buffer[2] << 8 | buffer[1];
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case BT_HCI_OP_SET_EVENT_MASK:
|
||||
{
|
||||
/* Override the all event bits roughly to avoid the
|
||||
* bt/ble host specific mask deliver to controller.
|
||||
*/
|
||||
|
||||
memset(&buffer[4], 0xff, 7);
|
||||
buffer[11] = 0x3f;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void bt_uart_filter_init(FAR struct bt_uart_filter_s *filter, int type)
|
||||
{
|
||||
memset(filter->handle, 0, sizeof(filter->handle));
|
||||
filter->type = type;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
* drivers/wireless/bluetooth/bt_uart_filter.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVER_WIRELESS_BLUETOOTH_BT_UART_FILTER_H
|
||||
#define __DRIVER_WIRELESS_BLUETOOTH_BT_UART_FILTER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define BT_UART_FILTER_CONN_COUNT 4
|
||||
|
||||
#define BT_UART_FILTER_TYPE_BT 0
|
||||
#define BT_UART_FILTER_TYPE_BLE 1
|
||||
#define BT_UART_FILTER_TYPE_COUNT 2
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct bt_uart_filter_s
|
||||
{
|
||||
int type;
|
||||
uint16_t handle[BT_UART_FILTER_CONN_COUNT];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
void bt_uart_filter_init(FAR struct bt_uart_filter_s *filter, int type);
|
||||
bool bt_uart_filter_forward_send(FAR struct bt_uart_filter_s *filter,
|
||||
FAR char *buffer, size_t buflen);
|
||||
bool bt_uart_filter_forward_recv(FAR struct bt_uart_filter_s *filter,
|
||||
FAR char *buffer, size_t buflen);
|
||||
|
||||
#endif /* __DRIVER_WIRELESS_BLUETOOTH_BT_UART_FILTER_H */
|
||||
@@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/wireless/bluetooth/bt_uart_bridge.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_UART_BRIDGE_H
|
||||
#define __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_UART_BRIDGE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bt_uart_bridge_register
|
||||
*
|
||||
* Description:
|
||||
* Register the Bluetooth BT/BLE dual mode UART bridge driver
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bt_uart_bridge_register(FAR const char *hciname,
|
||||
FAR const char *btname, FAR const char *blename);
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_UART_BRIDGE_H */
|
||||
Reference in New Issue
Block a user