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
+17 -12
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;
}
+75 -150
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);
goto errout_with_busy;
hdrlen = sizeof(struct bt_hci_evt_hdr_s);
}
if (buf == NULL)
else if (data[0] == H4_ACL)
{
/* 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);
hdrlen = sizeof(struct bt_hci_acl_hdr_s);
}
else
{
wlerr("ERROR: Unknown H4 type %u\n", data[0]);
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");
goto errout_with_buf;
wlwarn("WARNING: Unable to read H4 packet header: %ld\n",
(long)nread);
goto errout_with_busy;
}
remaining = hdrlen;
wlinfo("Need to get %u bytes\n", remaining);
hdr = (void *)(data + H4_HEADER_SIZE);
while (remaining > 0)
if (data[0] == H4_EVT)
{
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;
}
wlinfo("Received %ld bytes\n", (long)nread);
buf->len += nread;
remaining -= nread;
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;
}
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 */
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;
+4 -2
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 */