wireless/bluetooth: decoupling bt_driver_s and bt_buf_s
Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
parent
6837d4e1ba
commit
6c69b12000
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user