wireless/bluetooth: decoupling bt_driver_s and bt_buf_s

Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
chao.an 2021-05-18 21:45:01 +08:00 committed by Matias N
parent 6837d4e1ba
commit 6c69b12000
10 changed files with 344 additions and 395 deletions

View File

@ -91,9 +91,10 @@ struct nrf52_sdc_dev_s
static void mpsl_assert_handler(const char *const file, const uint32_t line);
static void sdc_fault_handler(const char *file, const uint32_t line);
static int bt_open(FAR const struct bt_driver_s *btdev);
static int bt_hci_send(FAR const struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf);
static int bt_open(FAR struct bt_driver_s *btdev);
static int bt_hci_send(FAR struct bt_driver_s *btdev,
enum bt_buf_type_e type,
FAR void *data, size_t len);
static void on_hci(void);
static void on_hci_worker(void *arg);
@ -112,7 +113,7 @@ static void radio_handler(void);
* Private Data
****************************************************************************/
static const struct bt_driver_s g_bt_driver =
static struct bt_driver_s g_bt_driver =
{
.head_reserve = 0,
.open = bt_open,
@ -138,7 +139,7 @@ static struct nrf52_sdc_dev_s g_sdc_dev;
* Name: bt_open
****************************************************************************/
static int bt_open(FAR const struct bt_driver_s *btdev)
static int bt_open(FAR struct bt_driver_s *btdev)
{
return 0;
}
@ -147,61 +148,43 @@ static int bt_open(FAR const struct bt_driver_s *btdev)
* Name: bt_open
****************************************************************************/
static int bt_hci_send(FAR const struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf)
static int bt_hci_send(FAR struct bt_driver_s *btdev,
enum bt_buf_type_e type,
FAR void *data, size_t len)
{
int ret = OK;
int ret = -EIO;
/* Pass HCI CMD/DATA to SDC */
if (buf->type == BT_CMD)
if (type == BT_CMD || type == BT_ACL_OUT)
{
struct bt_hci_cmd_hdr_s *cmd = (struct bt_hci_cmd_hdr_s *)buf->data;
wlinfo("passing CMD %d to softdevice\n", cmd->opcode);
wlinfo("passing type %s to softdevice\n",
(type == BT_CMD) ? "CMD" : "ACL");
/* Ensure non-concurrent access to SDC operations */
nxsem_wait_uninterruptible(&g_sdc_dev.exclsem);
if (sdc_hci_cmd_put(buf->data) < 0)
if (type == BT_CMD)
{
wlerr("sdc_hci_cmd_put() failed\n");
ret = -EIO;
}
nxsem_post(&g_sdc_dev.exclsem);
work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
}
else if (buf->type == BT_ACL_OUT)
{
wlinfo("passing ACL to softdevice\n");
/* Ensure non-concurrent access to SDC operations */
nxsem_wait_uninterruptible(&g_sdc_dev.exclsem);
if (sdc_hci_data_put(buf->data) < 0)
{
wlerr("sdc_hci_data_put() failed\n");
ret = -EIO;
}
nxsem_post(&g_sdc_dev.exclsem);
work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
}
if (ret < 0)
{
wlerr("bt_hci_send() failed: %d\n", ret);
return ret;
ret = sdc_hci_cmd_put(data);
}
else
{
return buf->len;
ret = sdc_hci_data_put(data);
}
nxsem_post(&g_sdc_dev.exclsem);
if (ret >= 0)
{
ret = len;
work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
}
}
return ret;
}
/****************************************************************************
@ -261,12 +244,11 @@ static void on_hci_worker(void *arg)
static void on_hci(void)
{
struct bt_buf_s *outbuf;
bool check_again;
size_t len;
int ret;
bool check_again = true;
while (check_again)
do
{
check_again = false;
@ -302,13 +284,8 @@ static void on_hci(void)
}
#endif
outbuf = bt_buf_alloc(BT_EVT, NULL, BLUETOOTH_H4_HDRLEN);
bt_buf_extend(outbuf, len);
memcpy(outbuf->data, g_sdc_dev.msg_buffer, len);
bt_hci_receive(outbuf);
bt_netdev_receive(&g_bt_driver, BT_EVT,
g_sdc_dev.msg_buffer, len);
check_again = true;
}
@ -326,16 +303,12 @@ static void on_hci(void)
len = sizeof(*hdr) + hdr->len;
outbuf = bt_buf_alloc(BT_ACL_IN, NULL, BLUETOOTH_H4_HDRLEN);
bt_buf_extend(outbuf, len);
memcpy(outbuf->data, g_sdc_dev.msg_buffer, len);
bt_hci_receive(outbuf);
bt_netdev_receive(&g_bt_driver, BT_ACL_IN,
g_sdc_dev.msg_buffer, len);
check_again = true;
}
}
while (check_again);
}
/****************************************************************************

View File

@ -31,9 +31,13 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <queue.h>
#include <nuttx/wireless/bluetooth/bt_driver.h>
#include <nuttx/nuttx.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bluetooth/bt_driver.h>
#include <nuttx/wireless/bluetooth/bt_uart.h>
#include "up_internal.h"
#include "up_hcisocket_host.h"
@ -42,99 +46,157 @@
* Pre-processor Definitions
****************************************************************************/
/* HCI data types as defined by Linux Kernel */
#define HCI_COMMAND_PKT 0x01
#define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04
#define HCI_ISODATA_PKT 0x05
#define HCI_DIAG_PKT 0xf0
#define HCI_VENDOR_PKT 0xff
#define BLUETOOTH_RX_FRAMELEN 1024
/****************************************************************************
* Private Types
****************************************************************************/
struct bthcisock_s
{
FAR struct bt_driver_s drv;
int id;
int fd;
sq_entry_t link;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int bthcisock_send(FAR const struct bt_driver_s *dev,
FAR struct bt_buf_s *buf);
static int bthcisock_open(FAR const struct bt_driver_s *dev);
static int bthcisock_send(FAR struct bt_driver_s *drv,
enum bt_buf_type_e type,
FAR void *data, size_t len);
static int bthcisock_open(FAR struct bt_driver_s *drv);
static void bthcisock_close(FAR struct bt_driver_s *drv);
static int bthcisock_receive(FAR struct bt_driver_s *drv);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct bt_driver_s g_bt_hcisock =
{
0, /* head_reserve */
bthcisock_open, /* open */
bthcisock_send /* send */
};
static int bt_fd = -1; /* Host HCI socket fd */
static int host_dev_id = 0; /* Host HCI interface number */
/* Hold a receive frame buffer here. This allows us to not allocate and free
* on every socket read since most of the time there will be no data to
* actually process.
*/
struct bt_buf_s *read_buf = NULL;
static sq_queue_t g_bthcisock_list;
/****************************************************************************
* Private Functions
****************************************************************************/
static int bthcisock_send(FAR const struct bt_driver_s *dev,
FAR struct bt_buf_s *buf)
static int bthcisock_send(FAR struct bt_driver_s *drv,
enum bt_buf_type_e type,
FAR void *data, size_t len)
{
uint8_t *pkt_type = bt_buf_provide(buf, BLUETOOTH_H4_HDRLEN);
FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv;
FAR char *hdr = (FAR char *)data - drv->head_reserve;
int ret;
switch (buf->type)
if (type == BT_CMD)
{
case BT_CMD:
*hdr = H4_CMD;
}
else if (type == BT_ACL_OUT)
{
*pkt_type = HCI_COMMAND_PKT;
break;
*hdr = H4_ACL;
}
else if (type == BT_ISO_OUT)
{
*hdr = H4_ISO;
}
else
{
return -EINVAL;
}
case BT_ACL_OUT:
{
*pkt_type = HCI_ACLDATA_PKT;
break;
}
ret = bthcisock_host_send(dev->fd, hdr, len + H4_HEADER_SIZE);
default:
{
wlerr("Unexpected HCI packet type %d", buf->type);
return buf->len;
}
}
if (bthcisock_host_send(bt_fd, buf->data, buf->len) < 0)
{
return -1;
}
return buf->len;
return ret < 0 ? ret : len;
}
static int bthcisock_open(FAR const struct bt_driver_s *dev)
static void bthcisock_close(FAR struct bt_driver_s *drv)
{
int fd = bthcisock_host_open(host_dev_id);
if (fd < 0)
FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv;
bthcisock_host_close(dev->fd);
dev->fd = -1;
}
static int bthcisock_receive(FAR struct bt_driver_s *drv)
{
FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv;
char data[BLUETOOTH_RX_FRAMELEN];
enum bt_buf_type_e type;
int ret;
ret = bthcisock_host_read(dev->fd, data, sizeof(data));
if (ret <= 0)
{
return -1;
return ret;
}
bt_fd = fd;
if (data[0] == H4_EVT)
{
type = BT_EVT;
}
else if (data[0] == H4_ACL)
{
type = BT_ACL_IN;
}
else if (data[0] == H4_ISO)
{
type = BT_ISO_IN;
}
else
{
return -EINVAL;
}
return bt_netdev_receive(&dev->drv, type,
data + H4_HEADER_SIZE,
ret - H4_HEADER_SIZE);
}
static int bthcisock_open(FAR struct bt_driver_s *drv)
{
FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv;
int fd;
fd = bthcisock_host_open(dev->id);
if (fd < 0)
{
return fd;
}
dev->fd = fd;
return OK;
}
static FAR struct bthcisock_s *bthcisock_alloc(int dev_id)
{
/* Register the driver with the Bluetooth stack */
FAR struct bthcisock_s *dev;
FAR struct bt_driver_s *drv;
dev = (FAR struct bthcisock_s *)kmm_zalloc(sizeof(*dev));
if (dev == NULL)
{
return NULL;
}
dev->id = dev_id;
dev->fd = -1;
drv = &dev->drv;
drv->head_reserve = H4_HEADER_SIZE;
drv->open = bthcisock_open;
drv->send = bthcisock_send;
drv->close = bthcisock_close;
sq_addlast(&dev->link, &g_bthcisock_list);
return dev;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -156,10 +218,22 @@ static int bthcisock_open(FAR const struct bt_driver_s *dev)
int bthcisock_register(int dev_id)
{
/* Register the driver with the Bluetooth stack */
FAR struct bthcisock_s *dev;
int ret;
host_dev_id = dev_id;
return bt_netdev_register(&g_bt_hcisock);
dev = bthcisock_alloc(dev_id);
if (dev == NULL)
{
return -ENOMEM;
}
ret = bt_netdev_register(&dev->drv);
if (ret < 0)
{
kmm_free(dev);
}
return ret;
}
/****************************************************************************
@ -179,70 +253,17 @@ int bthcisock_register(int dev_id)
int bthcisock_loop(void)
{
uint8_t type;
int len;
FAR struct bthcisock_s *dev;
FAR sq_entry_t *entry;
if (bt_fd < 0)
for (entry = sq_peek(&g_bthcisock_list); entry; entry = sq_next(entry))
{
/* Internal socket has not yet been created */
return -EBADF;
}
if (read_buf == NULL)
dev = container_of(entry, struct bthcisock_s, link);
if (bthcisock_host_avail(dev->fd))
{
/* NOTE: This shared allocation only works because the allocation size
* is currently the same for all frame types. If this changes we will
* need to allocate for the largest frame or use an intermediate buffer
* to copy from
*/
read_buf = bt_buf_alloc(BT_DUMMY, NULL, 0);
if (read_buf == NULL)
{
wlerr("ERROR: Failed to allocate buffer\n");
return -ENOMEM;
bthcisock_receive(&dev->drv);
}
}
len = bthcisock_host_read(bt_fd, read_buf->data,
BLUETOOTH_MAX_FRAMELEN);
if (len < 0)
{
return OK;
}
type = *(uint8_t *)bt_buf_extend(read_buf, len);
bt_buf_consume(read_buf, BLUETOOTH_H4_HDRLEN);
switch (type)
{
case HCI_EVENT_PKT:
{
read_buf->type = BT_EVT;
break;
}
case HCI_ACLDATA_PKT:
{
read_buf->type = BT_ACL_IN;
break;
}
default:
{
wlerr("Unknown packet type %d\n", type);
return OK;
}
}
bt_hci_receive(read_buf);
/* Make sure to allocate a new buffer for the next read. Bluetooth
* stack will clean up the allocation of this buffer when it has been
* handled.
*/
read_buf = NULL;
return OK;
return 0;
}

View File

@ -35,6 +35,7 @@
#include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bluetooth/bt_hci.h>
#include <nuttx/wireless/bluetooth/bt_null.h>
#include <nuttx/wireless/bluetooth/bt_driver.h>
/****************************************************************************
* Private Function Prototypes
@ -45,15 +46,16 @@ static void btnull_format_cmdcomplete(FAR struct bt_buf_s *buf,
static void btnull_format_bdaddr_rsp(FAR struct bt_buf_s *buf,
uint16_t opcode);
static int btnull_open(FAR const struct bt_driver_s *dev);
static int btnull_send(FAR const struct bt_driver_s *dev,
FAR struct bt_buf_s *buf);
static int btnull_open(FAR struct bt_driver_s *dev);
static int btnull_send(FAR struct bt_driver_s *dev,
enum bt_buf_type_e type,
FAR void *data, size_t len);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct bt_driver_s g_bt_null =
static struct bt_driver_s g_bt_null =
{
0, /* head_reserve */
btnull_open, /* open */
@ -180,16 +182,17 @@ static void btnull_format_buffersize_rsp(FAR struct bt_buf_s *buf,
buf->len = len;
}
static int btnull_send(FAR const struct bt_driver_s *dev,
FAR struct bt_buf_s *buf)
static int btnull_send(FAR struct bt_driver_s *dev,
enum bt_buf_type_e type,
FAR void *data, size_t len)
{
wlinfo("Bit bucket: length %d\n", (int)buf->len);
wlinfo("Bit bucket: length %zu\n", len);
/* Is the Bluetooth stack waiting for an event? */
if (buf->type == BT_CMD)
if (type == BT_CMD)
{
FAR struct bt_hci_cmd_hdr_s *hdr = (FAR void *)buf->data;
FAR struct bt_hci_cmd_hdr_s *hdr = data;
FAR struct bt_buf_s *outbuf;
uint16_t opcode = hdr->opcode;
@ -224,13 +227,15 @@ static int btnull_send(FAR const struct bt_driver_s *dev,
wlinfo("Send CMD complete event\n");
bt_hci_receive(outbuf);
bt_netdev_receive(dev, outbuf->type,
outbuf->data, outbuf->len);
bt_buf_release(outbuf);
}
return buf->len;
return len;
}
static int btnull_open(FAR const struct bt_driver_s *dev)
static int btnull_open(FAR struct bt_driver_s *dev)
{
return OK;
}

View File

@ -51,6 +51,8 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bluetooth/bt_core.h>
#include <nuttx/wireless/bluetooth/bt_hci.h>
#include <nuttx/wireless/bluetooth/bt_driver.h>
@ -106,99 +108,29 @@ static ssize_t btuart_read(FAR struct btuart_upperhalf_s *upper,
return ntotal;
}
static FAR struct bt_buf_s *
btuart_evt_recv(FAR struct btuart_upperhalf_s *upper,
FAR unsigned int *hdrlen)
{
FAR struct bt_buf_s *buf;
struct bt_hci_evt_hdr_s hdr;
ssize_t nread;
/* We can ignore the return value since we pass buflen == minread */
nread = btuart_read(upper, (FAR uint8_t *)&hdr,
sizeof(struct bt_hci_evt_hdr_s),
sizeof(struct bt_hci_evt_hdr_s));
if (nread != sizeof(struct bt_hci_evt_hdr_s))
{
wlerr("ERROR: btuart_read returned %ld\n", (long)nread);
return NULL;
}
buf = bt_buf_alloc(BT_EVT, NULL, 0);
if (buf != NULL)
{
memcpy(bt_buf_extend(buf, sizeof(struct bt_hci_evt_hdr_s)), &hdr,
sizeof(struct bt_hci_evt_hdr_s));
}
else
{
wlerr("ERROR: No available event buffers!\n");
}
*hdrlen = hdr.len;
wlinfo("hdrlen %u\n", hdr.len);
return buf;
}
static FAR struct bt_buf_s *
btuart_acl_recv(FAR struct btuart_upperhalf_s *upper,
FAR unsigned int *hdrlen)
{
FAR struct bt_buf_s *buf;
struct bt_hci_acl_hdr_s hdr;
ssize_t nread;
/* We can ignore the return value since we pass buflen == minread */
nread = btuart_read(upper, (FAR uint8_t *)&hdr,
sizeof(struct bt_hci_acl_hdr_s),
sizeof(struct bt_hci_acl_hdr_s));
if (nread != sizeof(struct bt_hci_acl_hdr_s))
{
wlerr("ERROR: btuart_read returned %ld\n", (long)nread);
return NULL;
}
buf = bt_buf_alloc(BT_ACL_IN, NULL, 0);
if (buf != NULL)
{
memcpy(bt_buf_extend(buf, sizeof(struct bt_hci_acl_hdr_s)), &hdr,
sizeof(struct bt_hci_acl_hdr_s));
}
else
{
wlerr("ERROR: No available ACL buffers!\n");
}
*hdrlen = BT_LE162HOST(hdr.len);
wlinfo("hdrlen %u\n", *hdrlen);
return buf;
}
static void btuart_rxwork(FAR void *arg)
{
FAR struct btuart_upperhalf_s *upper;
FAR const struct btuart_lowerhalf_s *lower;
FAR struct bt_buf_s *buf;
uint8_t data[BLUETOOTH_MAX_FRAMELEN];
enum bt_buf_type_e type;
unsigned int hdrlen;
int remaining;
unsigned int pktlen;
ssize_t nread;
uint8_t type;
union
{
struct bt_hci_evt_hdr_s evt;
struct bt_hci_acl_hdr_s acl;
}
*hdr;
upper = (FAR struct btuart_upperhalf_s *)arg;
DEBUGASSERT(upper != NULL && upper->lower != NULL);
lower = upper->lower;
/* Beginning of a new packet.
* Read the first byte to get the packet type.
*/
nread = btuart_read(upper, &type, 1, 0);
nread = btuart_read(upper, data, H4_HEADER_SIZE, 0);
if (nread != 1)
{
wlwarn("WARNING: Unable to read H4 packet type: %ld\n",
@ -206,65 +138,64 @@ static void btuart_rxwork(FAR void *arg)
goto errout_with_busy;
}
switch (type)
if (data[0] == H4_EVT)
{
case H4_EVT:
buf = btuart_evt_recv(upper, &hdrlen);
break;
case H4_ACL:
buf = btuart_acl_recv(upper, &hdrlen);
break;
default:
wlerr("ERROR: Unknown H4 type %u\n", type);
hdrlen = sizeof(struct bt_hci_evt_hdr_s);
}
else if (data[0] == H4_ACL)
{
hdrlen = sizeof(struct bt_hci_acl_hdr_s);
}
else
{
wlerr("ERROR: Unknown H4 type %u\n", data[0]);
goto errout_with_busy;
}
if (buf == NULL)
nread = btuart_read(upper, data + H4_HEADER_SIZE,
hdrlen, hdrlen);
if (nread != hdrlen)
{
/* Failed to allocate a buffer. Drain the Rx data and fail the read. */
nread = lower->rxdrain(lower);
wlwarn("WARNING: Discarded %ld bytes\n", (long)nread);
wlwarn("WARNING: Unable to read H4 packet header: %ld\n",
(long)nread);
goto errout_with_busy;
}
else if (hdrlen > bt_buf_tailroom(buf))
hdr = (void *)(data + H4_HEADER_SIZE);
if (data[0] == H4_EVT)
{
wlerr("ERROR: Not enough space in buffer\n");
goto errout_with_buf;
pktlen = hdr->evt.len;
type = BT_EVT;
}
else if (data[0] == H4_ACL)
{
pktlen = hdr->acl.len;
type = BT_ACL_IN;
}
else
{
wlerr("ERROR: Unknown H4 type %u\n", data[0]);
goto errout_with_busy;
}
remaining = hdrlen;
wlinfo("Need to get %u bytes\n", remaining);
while (remaining > 0)
nread = btuart_read(upper, data + H4_HEADER_SIZE + hdrlen,
pktlen, pktlen);
if (nread != pktlen)
{
nread = btuart_read(upper, bt_buf_tail(buf), remaining, 0);
if (nread < 0)
{
wlerr("ERROR: Read returned error %d\n", (int)nread);
goto errout_with_buf;
wlwarn("WARNING: Unable to read H4 packet: %ld\n",
(long)nread);
goto errout_with_busy;
}
wlinfo("Received %ld bytes\n", (long)nread);
buf->len += nread;
remaining -= nread;
}
wlinfo("Full packet received\n");
/* Pass buffer to the stack */
BT_DUMP("Received", buf->data, buf->len);
BT_DUMP("Received", data, H4_HEADER_SIZE + hdrlen + pktlen);
upper->busy = false;
bt_hci_receive(buf);
bt_netdev_receive(&upper->dev, type, data + H4_HEADER_SIZE,
hdrlen + pktlen);
return;
errout_with_buf:
bt_buf_release(buf);
errout_with_busy:
upper->busy = false;
}
@ -293,51 +224,45 @@ static void btuart_rxcallback(FAR const struct btuart_lowerhalf_s *lower,
* Public Functions
****************************************************************************/
int btuart_send(FAR const struct bt_driver_s *dev, FAR struct bt_buf_s *buf)
int btuart_send(FAR struct bt_driver_s *dev,
enum bt_buf_type_e type,
FAR void *data, size_t len)
{
FAR uint8_t *hdr = (FAR uint8_t *)data - dev->head_reserve;
FAR struct btuart_upperhalf_s *upper;
FAR const struct btuart_lowerhalf_s *lower;
FAR uint8_t *type;
ssize_t ntotal = 0;
upper = (FAR struct btuart_upperhalf_s *)dev;
DEBUGASSERT(upper != NULL && upper->lower != NULL);
lower = upper->lower;
if (bt_buf_headroom(buf) < H4_HEADER_SIZE)
if (type == BT_CMD)
{
*hdr = H4_CMD;
}
else if (type == BT_ACL_OUT)
{
*hdr = H4_ACL;
}
else if (type == BT_ISO_OUT)
{
*hdr = H4_ISO;
}
else
{
wlerr("Not enough headroom in buffer\n");
return -EINVAL;
}
type = bt_buf_provide(buf, H4_HEADER_SIZE);
len += H4_HEADER_SIZE;
switch (buf->type)
{
case BT_CMD:
*type = H4_CMD;
break;
BT_DUMP("Sending", hdr, len);
case BT_ACL_OUT:
*type = H4_ACL;
break;
case BT_EVT:
*type = H4_EVT;
break;
default:
wlerr("Unknown buf type %u\n", buf->type);
return -EINVAL;
}
BT_DUMP("Sending", buf->data, buf->len);
while (ntotal < buf->len)
while (ntotal < len)
{
ssize_t nwritten;
nwritten = lower->write(lower, buf->data + ntotal, buf->len - ntotal);
nwritten = lower->write(lower, hdr + ntotal, len - ntotal);
if (nwritten >= 0)
{
ntotal += nwritten;
@ -351,7 +276,7 @@ int btuart_send(FAR const struct bt_driver_s *dev, FAR struct bt_buf_s *buf)
return OK;
}
int btuart_open(FAR const struct bt_driver_s *dev)
int btuart_open(FAR struct bt_driver_s *dev)
{
FAR struct btuart_upperhalf_s *upper;
FAR const struct btuart_lowerhalf_s *lower;

View File

@ -94,7 +94,9 @@ struct btuart_upperhalf_s
/* Generic implementations of HCI UART methods */
int btuart_send(FAR const struct bt_driver_s *dev, FAR struct bt_buf_s *buf);
int btuart_open(FAR const struct bt_driver_s *dev);
int btuart_send(FAR struct bt_driver_s *dev,
enum bt_buf_type_e type,
FAR void *data, size_t len);
int btuart_open(FAR struct bt_driver_s *dev);
#endif /* __DRIVER_WIRELESS_BLUETOOTH_BT_UART_H */

View File

@ -29,8 +29,6 @@
#include <string.h>
#include <nuttx/wireless/bluetooth/bt_hci.h>
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -61,6 +59,8 @@
#define BLUETOOTH_ADDRCOPY(d,s) memcpy((d),(s),BLUETOOTH_ADDRSIZE)
#define BLUETOOTH_ADDRCMP(a,b) (memcmp((a),(b),BLUETOOTH_ADDRSIZE) == 0)
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Public Types
****************************************************************************/

View File

@ -49,6 +49,13 @@
#include <nuttx/wireless/bluetooth/bt_buf.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define bt_netdev_receive(btdev, type, data, len) \
(btdev)->receive(btdev, type, data, len)
/****************************************************************************
* Public Types
****************************************************************************/
@ -61,12 +68,27 @@ struct bt_driver_s
/* Open the HCI transport */
CODE int (*open)(FAR const struct bt_driver_s *btdev);
CODE int (*open)(FAR struct bt_driver_s *btdev);
/* Send data to HCI */
CODE int (*send)(FAR const struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf);
CODE int (*send)(FAR struct bt_driver_s *btdev,
enum bt_buf_type_e type,
FAR void *data, size_t len);
/* Close the HCI transport */
CODE void (*close)(FAR struct bt_driver_s *btdev);
/* Filled by register function but called by bt_driver_s */
CODE int (*receive)(FAR struct bt_driver_s *btdev,
enum bt_buf_type_e type,
FAR void *data, size_t len);
/* Filled by register function, shouldn't be touched by bt_driver_s */
FAR void *priv;
};
/****************************************************************************
@ -89,24 +111,6 @@ struct bt_driver_s
*
****************************************************************************/
int bt_netdev_register(FAR const struct bt_driver_s *btdev);
/****************************************************************************
* Name: bt_hci_receive
*
* Description:
* Called by the Bluetooth low-level driver when new data is received from
* the radio. This may be called from the low-level driver and is part of
* the driver interface
*
* Input Parameters:
* buf - An instance of the buffer structure providing the received frame.
*
* Returned Value:
* None
*
****************************************************************************/
void bt_hci_receive(FAR struct bt_buf_s *buf);
int bt_netdev_register(FAR struct bt_driver_s *btdev);
#endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_DRIVER_H */

View File

@ -992,7 +992,7 @@ static void hci_event(FAR struct bt_buf_s *buf)
static int hci_tx_kthread(int argc, FAR char *argv[])
{
FAR const struct bt_driver_s *btdev = g_btdev.btdev;
FAR struct bt_driver_s *btdev = g_btdev.btdev;
int ret;
wlinfo("started\n");
@ -1487,18 +1487,12 @@ static void cmd_queue_init(void)
*
****************************************************************************/
int bt_send(FAR const struct bt_driver_s *btdev,
int bt_send(FAR struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf)
{
int ret;
/* Send to driver */
ret = btdev->send(btdev, buf);
/* TODO: Hook here to notify hci monitor */
return ret;
return btdev->send(btdev, buf->type, buf->data, buf->len);
}
/****************************************************************************
@ -1514,7 +1508,7 @@ int bt_send(FAR const struct bt_driver_s *btdev,
int bt_initialize(void)
{
FAR const struct bt_driver_s *btdev = g_btdev.btdev;
FAR struct bt_driver_s *btdev = g_btdev.btdev;
int ret;
wlinfo("btdev %p\n", btdev);
@ -1564,7 +1558,7 @@ int bt_initialize(void)
*
****************************************************************************/
int bt_driver_register(FAR const struct bt_driver_s *btdev)
int bt_driver_register(FAR struct bt_driver_s *btdev)
{
DEBUGASSERT(btdev != NULL && btdev->open != NULL && btdev->send != NULL);
@ -1595,13 +1589,13 @@ int bt_driver_register(FAR const struct bt_driver_s *btdev)
*
****************************************************************************/
void bt_driver_unregister(FAR const struct bt_driver_s *btdev)
void bt_driver_unregister(FAR struct bt_driver_s *btdev)
{
g_btdev.btdev = NULL;
}
/****************************************************************************
* Name: bt_hci_receive
* Name: bt_receive
*
* Description:
* Called by the Bluetooth low-level driver when new data is received from
@ -1621,26 +1615,34 @@ void bt_driver_unregister(FAR const struct bt_driver_s *btdev)
*
****************************************************************************/
/* TODO: rename to bt_receive? */
void bt_hci_receive(FAR struct bt_buf_s *buf)
int bt_receive(FAR struct bt_driver_s *btdev, enum bt_buf_type_e type,
FAR void *data, size_t len)
{
FAR struct bt_hci_evt_hdr_s *hdr;
struct bt_buf_s *buf;
int ret;
wlinfo("buf %p len %u\n", buf, buf->len);
wlinfo("data %p len %zu\n", data, len);
/* Critical command complete/status events use the high priority work
* queue.
*/
if (buf->type != BT_ACL_IN)
buf = bt_buf_alloc(type, NULL, 0);
if (buf == NULL)
{
if (buf->type != BT_EVT)
return -ENOMEM;
}
memcpy(bt_buf_extend(buf, len), data, len);
if (type != BT_ACL_IN)
{
if (type != BT_EVT)
{
wlerr("ERROR: Invalid buf type %u\n", buf->type);
bt_buf_release(buf);
return;
return -EINVAL;
}
/* Command Complete/Status events use high priority messages. */
@ -1669,7 +1671,7 @@ void bt_hci_receive(FAR struct bt_buf_s *buf)
}
}
return;
return OK;
}
}
@ -1691,6 +1693,8 @@ void bt_hci_receive(FAR struct bt_buf_s *buf)
wlerr("ERROR: Failed to schedule LPWORK: %d\n", ret);
}
}
return OK;
}
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST

View File

@ -126,7 +126,7 @@ struct bt_dev_s
/* Registered HCI driver */
FAR const struct bt_driver_s *btdev;
FAR struct bt_driver_s *btdev;
};
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
@ -281,7 +281,7 @@ int bt_initialize(void);
*
****************************************************************************/
int bt_driver_register(FAR const struct bt_driver_s *btdev);
int bt_driver_register(FAR struct bt_driver_s *btdev);
/****************************************************************************
* Name: bt_driver_unregister
@ -300,7 +300,7 @@ int bt_driver_register(FAR const struct bt_driver_s *btdev);
*
****************************************************************************/
void bt_driver_unregister(FAR const struct bt_driver_s *btdev);
void bt_driver_unregister(FAR struct bt_driver_s *btdev);
/****************************************************************************
* Name: bt_send
@ -318,7 +318,7 @@ void bt_driver_unregister(FAR const struct bt_driver_s *btdev);
*
****************************************************************************/
int bt_send(FAR const struct bt_driver_s *btdev,
int bt_send(FAR struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf);
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
@ -465,4 +465,17 @@ void bt_hci_cb_register(FAR struct bt_hci_cb_s *cb);
#endif
/****************************************************************************
* Name: bt_receive
*
* Description:
* Called by the Bluetooth low-level driver when new data is received from
* the radio. This may be called from the low-level driver and is part of
* the driver interface
*
****************************************************************************/
int bt_receive(FAR struct bt_driver_s *btdev, enum bt_buf_type_e type,
FAR void *data, size_t len);
#endif /* __WIRELESS_BLUETOOTH_BT_HDICORE_H */

View File

@ -1271,7 +1271,7 @@ static int btnet_properties(FAR struct radio_driver_s *netdev,
*
****************************************************************************/
int bt_netdev_register(FAR const struct bt_driver_s *btdev)
int bt_netdev_register(FAR struct bt_driver_s *btdev)
{
FAR struct btnet_driver_s *priv;
FAR struct radio_driver_s *radio;
@ -1354,6 +1354,8 @@ int bt_netdev_register(FAR const struct bt_driver_s *btdev)
radio->r_req_data = btnet_req_data; /* Enqueue frame for transmission */
radio->r_properties = btnet_properties; /* Return radio properties */
btdev->receive = bt_receive;
/* Associate the driver in with the Bluetooth stack.
*
* REVISIT: We will eventually need to remember which Bluetooth device