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

View File

@ -31,9 +31,13 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.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/net/bluetooth.h>
#include <nuttx/wireless/bluetooth/bt_driver.h>
#include <nuttx/wireless/bluetooth/bt_uart.h>
#include "up_internal.h" #include "up_internal.h"
#include "up_hcisocket_host.h" #include "up_hcisocket_host.h"
@ -42,99 +46,157 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* HCI data types as defined by Linux Kernel */ #define BLUETOOTH_RX_FRAMELEN 1024
#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
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
struct bthcisock_s
{
FAR struct bt_driver_s drv;
int id;
int fd;
sq_entry_t link;
};
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static int bthcisock_send(FAR const struct bt_driver_s *dev, static int bthcisock_send(FAR struct bt_driver_s *drv,
FAR struct bt_buf_s *buf); enum bt_buf_type_e type,
static int bthcisock_open(FAR const struct bt_driver_s *dev); 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 * Private Data
****************************************************************************/ ****************************************************************************/
static const struct bt_driver_s g_bt_hcisock = static sq_queue_t g_bthcisock_list;
{
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;
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
static int bthcisock_send(FAR const struct bt_driver_s *dev, static int bthcisock_send(FAR struct bt_driver_s *drv,
FAR struct bt_buf_s *buf) 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;
{ }
*pkt_type = HCI_COMMAND_PKT; else if (type == BT_ACL_OUT)
break; {
} *hdr = H4_ACL;
}
case BT_ACL_OUT: else if (type == BT_ISO_OUT)
{ {
*pkt_type = HCI_ACLDATA_PKT; *hdr = H4_ISO;
break; }
} else
{
default: return -EINVAL;
{
wlerr("Unexpected HCI packet type %d", buf->type);
return buf->len;
}
} }
if (bthcisock_host_send(bt_fd, buf->data, buf->len) < 0) ret = bthcisock_host_send(dev->fd, hdr, len + H4_HEADER_SIZE);
{
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); FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv;
if (fd < 0)
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; 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 * Public Functions
****************************************************************************/ ****************************************************************************/
@ -156,10 +218,22 @@ static int bthcisock_open(FAR const struct bt_driver_s *dev)
int bthcisock_register(int dev_id) 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; dev = bthcisock_alloc(dev_id);
return bt_netdev_register(&g_bt_hcisock); 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) int bthcisock_loop(void)
{ {
uint8_t type; FAR struct bthcisock_s *dev;
int len; 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 */ dev = container_of(entry, struct bthcisock_s, link);
if (bthcisock_host_avail(dev->fd))
return -EBADF;
}
if (read_buf == NULL)
{
/* 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"); bthcisock_receive(&dev->drv);
return -ENOMEM;
} }
} }
len = bthcisock_host_read(bt_fd, read_buf->data, return 0;
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;
} }

View File

@ -35,6 +35,7 @@
#include <nuttx/net/bluetooth.h> #include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bluetooth/bt_hci.h> #include <nuttx/wireless/bluetooth/bt_hci.h>
#include <nuttx/wireless/bluetooth/bt_null.h> #include <nuttx/wireless/bluetooth/bt_null.h>
#include <nuttx/wireless/bluetooth/bt_driver.h>
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * 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, static void btnull_format_bdaddr_rsp(FAR struct bt_buf_s *buf,
uint16_t opcode); uint16_t opcode);
static int btnull_open(FAR const struct bt_driver_s *dev); static int btnull_open(FAR struct bt_driver_s *dev);
static int btnull_send(FAR const struct bt_driver_s *dev, static int btnull_send(FAR struct bt_driver_s *dev,
FAR struct bt_buf_s *buf); enum bt_buf_type_e type,
FAR void *data, size_t len);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
static const struct bt_driver_s g_bt_null = static struct bt_driver_s g_bt_null =
{ {
0, /* head_reserve */ 0, /* head_reserve */
btnull_open, /* open */ btnull_open, /* open */
@ -180,16 +182,17 @@ static void btnull_format_buffersize_rsp(FAR struct bt_buf_s *buf,
buf->len = len; buf->len = len;
} }
static int btnull_send(FAR const struct bt_driver_s *dev, static int btnull_send(FAR struct bt_driver_s *dev,
FAR struct bt_buf_s *buf) 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? */ /* 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; FAR struct bt_buf_s *outbuf;
uint16_t opcode = hdr->opcode; 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"); 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; return OK;
} }

View File

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

View File

@ -94,7 +94,9 @@ struct btuart_upperhalf_s
/* Generic implementations of HCI UART methods */ /* Generic implementations of HCI UART methods */
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,
int btuart_open(FAR const 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 */ #endif /* __DRIVER_WIRELESS_BLUETOOTH_BT_UART_H */

View File

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

View File

@ -49,6 +49,13 @@
#include <nuttx/wireless/bluetooth/bt_buf.h> #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 * Public Types
****************************************************************************/ ****************************************************************************/
@ -61,12 +68,27 @@ struct bt_driver_s
/* Open the HCI transport */ /* 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 */ /* Send data to HCI */
CODE int (*send)(FAR const struct bt_driver_s *btdev, CODE int (*send)(FAR struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf); 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); int bt_netdev_register(FAR 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);
#endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_DRIVER_H */ #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[]) 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; int ret;
wlinfo("started\n"); 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) FAR struct bt_buf_s *buf)
{ {
int ret;
/* Send to driver */ /* Send to driver */
ret = btdev->send(btdev, buf); return btdev->send(btdev, buf->type, buf->data, buf->len);
/* TODO: Hook here to notify hci monitor */
return ret;
} }
/**************************************************************************** /****************************************************************************
@ -1514,7 +1508,7 @@ int bt_send(FAR const struct bt_driver_s *btdev,
int bt_initialize(void) 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; int ret;
wlinfo("btdev %p\n", btdev); 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); 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; g_btdev.btdev = NULL;
} }
/**************************************************************************** /****************************************************************************
* Name: bt_hci_receive * Name: bt_receive
* *
* Description: * Description:
* Called by the Bluetooth low-level driver when new data is received from * 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? */ int bt_receive(FAR struct bt_driver_s *btdev, enum bt_buf_type_e type,
FAR void *data, size_t len)
void bt_hci_receive(FAR struct bt_buf_s *buf)
{ {
FAR struct bt_hci_evt_hdr_s *hdr; FAR struct bt_hci_evt_hdr_s *hdr;
struct bt_buf_s *buf;
int ret; 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 /* Critical command complete/status events use the high priority work
* queue. * 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); wlerr("ERROR: Invalid buf type %u\n", buf->type);
bt_buf_release(buf); bt_buf_release(buf);
return; return -EINVAL;
} }
/* Command Complete/Status events use high priority messages. */ /* 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); wlerr("ERROR: Failed to schedule LPWORK: %d\n", ret);
} }
} }
return OK;
} }
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST #ifdef CONFIG_WIRELESS_BLUETOOTH_HOST

View File

@ -126,7 +126,7 @@ struct bt_dev_s
/* Registered HCI driver */ /* Registered HCI driver */
FAR const struct bt_driver_s *btdev; FAR struct bt_driver_s *btdev;
}; };
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST #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 * 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 * 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); FAR struct bt_buf_s *buf);
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST #ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
@ -465,4 +465,17 @@ void bt_hci_cb_register(FAR struct bt_hci_cb_s *cb);
#endif #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 */ #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 btnet_driver_s *priv;
FAR struct radio_driver_s *radio; 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_req_data = btnet_req_data; /* Enqueue frame for transmission */
radio->r_properties = btnet_properties; /* Return radio properties */ radio->r_properties = btnet_properties; /* Return radio properties */
btdev->receive = bt_receive;
/* Associate the driver in with the Bluetooth stack. /* Associate the driver in with the Bluetooth stack.
* *
* REVISIT: We will eventually need to remember which Bluetooth device * REVISIT: We will eventually need to remember which Bluetooth device