mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 14:27:37 +08:00
wireless/bluetooth: decoupling bt_driver_s and bt_buf_s
Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user