From 6c69b12000e90ee97c0e6585b9e4820bd014cb89 Mon Sep 17 00:00:00 2001 From: "chao.an" Date: Tue, 18 May 2021 21:45:01 +0800 Subject: [PATCH] wireless/bluetooth: decoupling bt_driver_s and bt_buf_s Signed-off-by: chao.an --- arch/arm/src/nrf52/nrf52_sdc.c | 89 +++---- arch/sim/src/sim/up_hcisocket.c | 267 ++++++++++--------- drivers/wireless/bluetooth/bt_null.c | 29 +- drivers/wireless/bluetooth/bt_uart.c | 225 ++++++---------- drivers/wireless/bluetooth/bt_uart.h | 6 +- include/nuttx/net/bluetooth.h | 4 +- include/nuttx/wireless/bluetooth/bt_driver.h | 48 ++-- wireless/bluetooth/bt_hcicore.c | 46 ++-- wireless/bluetooth/bt_hcicore.h | 21 +- wireless/bluetooth/bt_netdev.c | 4 +- 10 files changed, 344 insertions(+), 395 deletions(-) diff --git a/arch/arm/src/nrf52/nrf52_sdc.c b/arch/arm/src/nrf52/nrf52_sdc.c index 7bc5579801..4ed107f449 100644 --- a/arch/arm/src/nrf52/nrf52_sdc.c +++ b/arch/arm/src/nrf52/nrf52_sdc.c @@ -91,9 +91,10 @@ struct nrf52_sdc_dev_s static void mpsl_assert_handler(const char *const file, const uint32_t line); static void sdc_fault_handler(const char *file, const uint32_t line); -static int bt_open(FAR const struct bt_driver_s *btdev); -static int bt_hci_send(FAR const struct bt_driver_s *btdev, - FAR struct bt_buf_s *buf); +static int bt_open(FAR struct bt_driver_s *btdev); +static int bt_hci_send(FAR struct bt_driver_s *btdev, + enum bt_buf_type_e type, + FAR void *data, size_t len); static void on_hci(void); static void on_hci_worker(void *arg); @@ -112,7 +113,7 @@ static void radio_handler(void); * Private Data ****************************************************************************/ -static const struct bt_driver_s g_bt_driver = +static struct bt_driver_s g_bt_driver = { .head_reserve = 0, .open = bt_open, @@ -138,7 +139,7 @@ static struct nrf52_sdc_dev_s g_sdc_dev; * Name: bt_open ****************************************************************************/ -static int bt_open(FAR const struct bt_driver_s *btdev) +static int bt_open(FAR struct bt_driver_s *btdev) { return 0; } @@ -147,61 +148,43 @@ static int bt_open(FAR const struct bt_driver_s *btdev) * Name: bt_open ****************************************************************************/ -static int bt_hci_send(FAR const struct bt_driver_s *btdev, - FAR struct bt_buf_s *buf) +static int bt_hci_send(FAR struct bt_driver_s *btdev, + enum bt_buf_type_e type, + FAR void *data, size_t len) { - int ret = OK; + int ret = -EIO; /* Pass HCI CMD/DATA to SDC */ - if (buf->type == BT_CMD) + if (type == BT_CMD || type == BT_ACL_OUT) { - struct bt_hci_cmd_hdr_s *cmd = (struct bt_hci_cmd_hdr_s *)buf->data; - - wlinfo("passing CMD %d to softdevice\n", cmd->opcode); + wlinfo("passing type %s to softdevice\n", + (type == BT_CMD) ? "CMD" : "ACL"); /* Ensure non-concurrent access to SDC operations */ nxsem_wait_uninterruptible(&g_sdc_dev.exclsem); - if (sdc_hci_cmd_put(buf->data) < 0) + if (type == BT_CMD) { - wlerr("sdc_hci_cmd_put() failed\n"); - ret = -EIO; + ret = sdc_hci_cmd_put(data); + } + else + { + ret = sdc_hci_data_put(data); } nxsem_post(&g_sdc_dev.exclsem); - work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0); - } - else if (buf->type == BT_ACL_OUT) - { - wlinfo("passing ACL to softdevice\n"); - - /* Ensure non-concurrent access to SDC operations */ - - nxsem_wait_uninterruptible(&g_sdc_dev.exclsem); - - if (sdc_hci_data_put(buf->data) < 0) + if (ret >= 0) { - wlerr("sdc_hci_data_put() failed\n"); - ret = -EIO; + ret = len; + + 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) - { - wlerr("bt_hci_send() failed: %d\n", ret); - return ret; - } - else - { - return buf->len; - } + return ret; } /**************************************************************************** @@ -261,12 +244,11 @@ static void on_hci_worker(void *arg) static void on_hci(void) { - struct bt_buf_s *outbuf; + bool check_again; size_t len; int ret; - bool check_again = true; - while (check_again) + do { check_again = false; @@ -302,13 +284,8 @@ static void on_hci(void) } #endif - outbuf = bt_buf_alloc(BT_EVT, NULL, BLUETOOTH_H4_HDRLEN); - bt_buf_extend(outbuf, len); - - memcpy(outbuf->data, g_sdc_dev.msg_buffer, len); - - bt_hci_receive(outbuf); - + bt_netdev_receive(&g_bt_driver, BT_EVT, + g_sdc_dev.msg_buffer, len); check_again = true; } @@ -326,16 +303,12 @@ static void on_hci(void) len = sizeof(*hdr) + hdr->len; - outbuf = bt_buf_alloc(BT_ACL_IN, NULL, BLUETOOTH_H4_HDRLEN); - bt_buf_extend(outbuf, len); - - memcpy(outbuf->data, g_sdc_dev.msg_buffer, len); - - bt_hci_receive(outbuf); - + bt_netdev_receive(&g_bt_driver, BT_ACL_IN, + g_sdc_dev.msg_buffer, len); check_again = true; } } + while (check_again); } /**************************************************************************** diff --git a/arch/sim/src/sim/up_hcisocket.c b/arch/sim/src/sim/up_hcisocket.c index fdfa6850b9..0fd130f352 100644 --- a/arch/sim/src/sim/up_hcisocket.c +++ b/arch/sim/src/sim/up_hcisocket.c @@ -31,9 +31,13 @@ #include #include #include +#include -#include +#include +#include #include +#include +#include #include "up_internal.h" #include "up_hcisocket_host.h" @@ -42,99 +46,157 @@ * Pre-processor Definitions ****************************************************************************/ -/* HCI data types as defined by Linux Kernel */ - -#define HCI_COMMAND_PKT 0x01 -#define HCI_ACLDATA_PKT 0x02 -#define HCI_SCODATA_PKT 0x03 -#define HCI_EVENT_PKT 0x04 -#define HCI_ISODATA_PKT 0x05 -#define HCI_DIAG_PKT 0xf0 -#define HCI_VENDOR_PKT 0xff +#define BLUETOOTH_RX_FRAMELEN 1024 /**************************************************************************** * Private Types ****************************************************************************/ +struct bthcisock_s +{ + FAR struct bt_driver_s drv; + int id; + int fd; + sq_entry_t link; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static int bthcisock_send(FAR const struct bt_driver_s *dev, - FAR struct bt_buf_s *buf); -static int bthcisock_open(FAR const struct bt_driver_s *dev); +static int bthcisock_send(FAR struct bt_driver_s *drv, + enum bt_buf_type_e type, + FAR void *data, size_t len); +static int bthcisock_open(FAR struct bt_driver_s *drv); +static void bthcisock_close(FAR struct bt_driver_s *drv); +static int bthcisock_receive(FAR struct bt_driver_s *drv); /**************************************************************************** * Private Data ****************************************************************************/ -static const struct bt_driver_s g_bt_hcisock = -{ - 0, /* head_reserve */ - bthcisock_open, /* open */ - bthcisock_send /* send */ -}; - -static int bt_fd = -1; /* Host HCI socket fd */ -static int host_dev_id = 0; /* Host HCI interface number */ - -/* Hold a receive frame buffer here. This allows us to not allocate and free - * on every socket read since most of the time there will be no data to - * actually process. - */ - -struct bt_buf_s *read_buf = NULL; +static sq_queue_t g_bthcisock_list; /**************************************************************************** * Private Functions ****************************************************************************/ -static int bthcisock_send(FAR const struct bt_driver_s *dev, - FAR struct bt_buf_s *buf) +static int bthcisock_send(FAR struct bt_driver_s *drv, + enum bt_buf_type_e type, + FAR void *data, size_t len) { - uint8_t *pkt_type = bt_buf_provide(buf, BLUETOOTH_H4_HDRLEN); + FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv; + FAR char *hdr = (FAR char *)data - drv->head_reserve; + int ret; - switch (buf->type) + if (type == BT_CMD) { - case BT_CMD: - { - *pkt_type = HCI_COMMAND_PKT; - break; - } - - case BT_ACL_OUT: - { - *pkt_type = HCI_ACLDATA_PKT; - break; - } - - default: - { - wlerr("Unexpected HCI packet type %d", buf->type); - return buf->len; - } + *hdr = H4_CMD; + } + else if (type == BT_ACL_OUT) + { + *hdr = H4_ACL; + } + else if (type == BT_ISO_OUT) + { + *hdr = H4_ISO; + } + else + { + return -EINVAL; } - if (bthcisock_host_send(bt_fd, buf->data, buf->len) < 0) - { - return -1; - } + ret = bthcisock_host_send(dev->fd, hdr, len + H4_HEADER_SIZE); - return buf->len; + return ret < 0 ? ret : len; } -static int bthcisock_open(FAR const struct bt_driver_s *dev) +static void bthcisock_close(FAR struct bt_driver_s *drv) { - int fd = bthcisock_host_open(host_dev_id); - if (fd < 0) + FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv; + + bthcisock_host_close(dev->fd); + dev->fd = -1; +} + +static int bthcisock_receive(FAR struct bt_driver_s *drv) +{ + FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv; + char data[BLUETOOTH_RX_FRAMELEN]; + enum bt_buf_type_e type; + int ret; + + ret = bthcisock_host_read(dev->fd, data, sizeof(data)); + if (ret <= 0) { - return -1; + return ret; } - bt_fd = fd; + if (data[0] == H4_EVT) + { + type = BT_EVT; + } + else if (data[0] == H4_ACL) + { + type = BT_ACL_IN; + } + else if (data[0] == H4_ISO) + { + type = BT_ISO_IN; + } + else + { + return -EINVAL; + } + + return bt_netdev_receive(&dev->drv, type, + data + H4_HEADER_SIZE, + ret - H4_HEADER_SIZE); +} + +static int bthcisock_open(FAR struct bt_driver_s *drv) +{ + FAR struct bthcisock_s *dev = (FAR struct bthcisock_s *)drv; + int fd; + + fd = bthcisock_host_open(dev->id); + + if (fd < 0) + { + return fd; + } + + dev->fd = fd; + return OK; } +static FAR struct bthcisock_s *bthcisock_alloc(int dev_id) +{ + /* Register the driver with the Bluetooth stack */ + + FAR struct bthcisock_s *dev; + FAR struct bt_driver_s *drv; + + dev = (FAR struct bthcisock_s *)kmm_zalloc(sizeof(*dev)); + if (dev == NULL) + { + return NULL; + } + + dev->id = dev_id; + dev->fd = -1; + drv = &dev->drv; + drv->head_reserve = H4_HEADER_SIZE; + drv->open = bthcisock_open; + drv->send = bthcisock_send; + drv->close = bthcisock_close; + + sq_addlast(&dev->link, &g_bthcisock_list); + + return dev; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -156,10 +218,22 @@ static int bthcisock_open(FAR const struct bt_driver_s *dev) int bthcisock_register(int dev_id) { - /* Register the driver with the Bluetooth stack */ + FAR struct bthcisock_s *dev; + int ret; - host_dev_id = dev_id; - return bt_netdev_register(&g_bt_hcisock); + dev = bthcisock_alloc(dev_id); + if (dev == NULL) + { + return -ENOMEM; + } + + ret = bt_netdev_register(&dev->drv); + if (ret < 0) + { + kmm_free(dev); + } + + return ret; } /**************************************************************************** @@ -179,70 +253,17 @@ int bthcisock_register(int dev_id) int bthcisock_loop(void) { - uint8_t type; - int len; + FAR struct bthcisock_s *dev; + FAR sq_entry_t *entry; - if (bt_fd < 0) + for (entry = sq_peek(&g_bthcisock_list); entry; entry = sq_next(entry)) { - /* Internal socket has not yet been created */ - - return -EBADF; - } - - if (read_buf == NULL) - { - /* 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) + dev = container_of(entry, struct bthcisock_s, link); + if (bthcisock_host_avail(dev->fd)) { - wlerr("ERROR: Failed to allocate buffer\n"); - return -ENOMEM; + bthcisock_receive(&dev->drv); } } - len = bthcisock_host_read(bt_fd, read_buf->data, - BLUETOOTH_MAX_FRAMELEN); - if (len < 0) - { - return OK; - } - - type = *(uint8_t *)bt_buf_extend(read_buf, len); - bt_buf_consume(read_buf, BLUETOOTH_H4_HDRLEN); - - switch (type) - { - case HCI_EVENT_PKT: - { - read_buf->type = BT_EVT; - break; - } - - case HCI_ACLDATA_PKT: - { - read_buf->type = BT_ACL_IN; - break; - } - - default: - { - wlerr("Unknown packet type %d\n", type); - return OK; - } - } - - bt_hci_receive(read_buf); - - /* Make sure to allocate a new buffer for the next read. Bluetooth - * stack will clean up the allocation of this buffer when it has been - * handled. - */ - - read_buf = NULL; - return OK; + return 0; } diff --git a/drivers/wireless/bluetooth/bt_null.c b/drivers/wireless/bluetooth/bt_null.c index 818bc7a29d..df8979613d 100644 --- a/drivers/wireless/bluetooth/bt_null.c +++ b/drivers/wireless/bluetooth/bt_null.c @@ -35,6 +35,7 @@ #include #include #include +#include /**************************************************************************** * 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; } diff --git a/drivers/wireless/bluetooth/bt_uart.c b/drivers/wireless/bluetooth/bt_uart.c index b75d3d45e3..b932251935 100644 --- a/drivers/wireless/bluetooth/bt_uart.c +++ b/drivers/wireless/bluetooth/bt_uart.c @@ -51,6 +51,8 @@ #include #include +#include + #include #include #include @@ -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; diff --git a/drivers/wireless/bluetooth/bt_uart.h b/drivers/wireless/bluetooth/bt_uart.h index 9f0277f885..4156bba02f 100644 --- a/drivers/wireless/bluetooth/bt_uart.h +++ b/drivers/wireless/bluetooth/bt_uart.h @@ -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 */ diff --git a/include/nuttx/net/bluetooth.h b/include/nuttx/net/bluetooth.h index cd526108a4..cd9d422c3e 100644 --- a/include/nuttx/net/bluetooth.h +++ b/include/nuttx/net/bluetooth.h @@ -29,8 +29,6 @@ #include #include -#ifdef CONFIG_NET_BLUETOOTH - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -61,6 +59,8 @@ #define BLUETOOTH_ADDRCOPY(d,s) memcpy((d),(s),BLUETOOTH_ADDRSIZE) #define BLUETOOTH_ADDRCMP(a,b) (memcmp((a),(b),BLUETOOTH_ADDRSIZE) == 0) +#ifdef CONFIG_NET_BLUETOOTH + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/include/nuttx/wireless/bluetooth/bt_driver.h b/include/nuttx/wireless/bluetooth/bt_driver.h index edb4ee51c1..3104ab5caa 100644 --- a/include/nuttx/wireless/bluetooth/bt_driver.h +++ b/include/nuttx/wireless/bluetooth/bt_driver.h @@ -49,6 +49,13 @@ #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define bt_netdev_receive(btdev, type, data, len) \ + (btdev)->receive(btdev, type, data, len) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -61,12 +68,27 @@ struct bt_driver_s /* Open the HCI transport */ - CODE int (*open)(FAR const struct bt_driver_s *btdev); + CODE int (*open)(FAR struct bt_driver_s *btdev); /* Send data to HCI */ - CODE int (*send)(FAR const struct bt_driver_s *btdev, - FAR struct bt_buf_s *buf); + CODE int (*send)(FAR struct bt_driver_s *btdev, + enum bt_buf_type_e type, + FAR void *data, size_t len); + + /* Close the HCI transport */ + + CODE void (*close)(FAR struct bt_driver_s *btdev); + + /* Filled by register function but called by bt_driver_s */ + + CODE int (*receive)(FAR struct bt_driver_s *btdev, + enum bt_buf_type_e type, + FAR void *data, size_t len); + + /* Filled by register function, shouldn't be touched by bt_driver_s */ + + FAR void *priv; }; /**************************************************************************** @@ -89,24 +111,6 @@ struct bt_driver_s * ****************************************************************************/ -int bt_netdev_register(FAR const struct bt_driver_s *btdev); - -/**************************************************************************** - * Name: bt_hci_receive - * - * Description: - * Called by the Bluetooth low-level driver when new data is received from - * the radio. This may be called from the low-level driver and is part of - * the driver interface - * - * Input Parameters: - * buf - An instance of the buffer structure providing the received frame. - * - * Returned Value: - * None - * - ****************************************************************************/ - -void bt_hci_receive(FAR struct bt_buf_s *buf); +int bt_netdev_register(FAR struct bt_driver_s *btdev); #endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_DRIVER_H */ diff --git a/wireless/bluetooth/bt_hcicore.c b/wireless/bluetooth/bt_hcicore.c index 1d14839e7b..e3f6488738 100644 --- a/wireless/bluetooth/bt_hcicore.c +++ b/wireless/bluetooth/bt_hcicore.c @@ -992,7 +992,7 @@ static void hci_event(FAR struct bt_buf_s *buf) static int hci_tx_kthread(int argc, FAR char *argv[]) { - FAR const struct bt_driver_s *btdev = g_btdev.btdev; + FAR struct bt_driver_s *btdev = g_btdev.btdev; int ret; wlinfo("started\n"); @@ -1487,18 +1487,12 @@ static void cmd_queue_init(void) * ****************************************************************************/ -int bt_send(FAR const struct bt_driver_s *btdev, +int bt_send(FAR struct bt_driver_s *btdev, FAR struct bt_buf_s *buf) { - int ret; - /* Send to driver */ - ret = btdev->send(btdev, buf); - - /* TODO: Hook here to notify hci monitor */ - - return ret; + return btdev->send(btdev, buf->type, buf->data, buf->len); } /**************************************************************************** @@ -1514,7 +1508,7 @@ int bt_send(FAR const struct bt_driver_s *btdev, int bt_initialize(void) { - FAR const struct bt_driver_s *btdev = g_btdev.btdev; + FAR struct bt_driver_s *btdev = g_btdev.btdev; int ret; wlinfo("btdev %p\n", btdev); @@ -1564,7 +1558,7 @@ int bt_initialize(void) * ****************************************************************************/ -int bt_driver_register(FAR const struct bt_driver_s *btdev) +int bt_driver_register(FAR struct bt_driver_s *btdev) { DEBUGASSERT(btdev != NULL && btdev->open != NULL && btdev->send != NULL); @@ -1595,13 +1589,13 @@ int bt_driver_register(FAR const struct bt_driver_s *btdev) * ****************************************************************************/ -void bt_driver_unregister(FAR const struct bt_driver_s *btdev) +void bt_driver_unregister(FAR struct bt_driver_s *btdev) { g_btdev.btdev = NULL; } /**************************************************************************** - * Name: bt_hci_receive + * Name: bt_receive * * Description: * Called by the Bluetooth low-level driver when new data is received from @@ -1621,26 +1615,34 @@ void bt_driver_unregister(FAR const struct bt_driver_s *btdev) * ****************************************************************************/ -/* TODO: rename to bt_receive? */ - -void bt_hci_receive(FAR struct bt_buf_s *buf) +int bt_receive(FAR struct bt_driver_s *btdev, enum bt_buf_type_e type, + FAR void *data, size_t len) { FAR struct bt_hci_evt_hdr_s *hdr; + struct bt_buf_s *buf; int ret; - wlinfo("buf %p len %u\n", buf, buf->len); + wlinfo("data %p len %zu\n", data, len); /* Critical command complete/status events use the high priority work * queue. */ - if (buf->type != BT_ACL_IN) + buf = bt_buf_alloc(type, NULL, 0); + if (buf == NULL) { - if (buf->type != BT_EVT) + return -ENOMEM; + } + + memcpy(bt_buf_extend(buf, len), data, len); + + if (type != BT_ACL_IN) + { + if (type != BT_EVT) { wlerr("ERROR: Invalid buf type %u\n", buf->type); bt_buf_release(buf); - return; + return -EINVAL; } /* Command Complete/Status events use high priority messages. */ @@ -1669,7 +1671,7 @@ void bt_hci_receive(FAR struct bt_buf_s *buf) } } - return; + return OK; } } @@ -1691,6 +1693,8 @@ void bt_hci_receive(FAR struct bt_buf_s *buf) wlerr("ERROR: Failed to schedule LPWORK: %d\n", ret); } } + + return OK; } #ifdef CONFIG_WIRELESS_BLUETOOTH_HOST diff --git a/wireless/bluetooth/bt_hcicore.h b/wireless/bluetooth/bt_hcicore.h index 19ee569ba8..0b0fdf2925 100644 --- a/wireless/bluetooth/bt_hcicore.h +++ b/wireless/bluetooth/bt_hcicore.h @@ -126,7 +126,7 @@ struct bt_dev_s /* Registered HCI driver */ - FAR const struct bt_driver_s *btdev; + FAR struct bt_driver_s *btdev; }; #ifdef CONFIG_WIRELESS_BLUETOOTH_HOST @@ -281,7 +281,7 @@ int bt_initialize(void); * ****************************************************************************/ -int bt_driver_register(FAR const struct bt_driver_s *btdev); +int bt_driver_register(FAR struct bt_driver_s *btdev); /**************************************************************************** * Name: bt_driver_unregister @@ -300,7 +300,7 @@ int bt_driver_register(FAR const struct bt_driver_s *btdev); * ****************************************************************************/ -void bt_driver_unregister(FAR const struct bt_driver_s *btdev); +void bt_driver_unregister(FAR struct bt_driver_s *btdev); /**************************************************************************** * Name: bt_send @@ -318,7 +318,7 @@ void bt_driver_unregister(FAR const struct bt_driver_s *btdev); * ****************************************************************************/ -int bt_send(FAR const struct bt_driver_s *btdev, +int bt_send(FAR struct bt_driver_s *btdev, FAR struct bt_buf_s *buf); #ifdef CONFIG_WIRELESS_BLUETOOTH_HOST @@ -465,4 +465,17 @@ void bt_hci_cb_register(FAR struct bt_hci_cb_s *cb); #endif +/**************************************************************************** + * Name: bt_receive + * + * Description: + * Called by the Bluetooth low-level driver when new data is received from + * the radio. This may be called from the low-level driver and is part of + * the driver interface + * + ****************************************************************************/ + +int bt_receive(FAR struct bt_driver_s *btdev, enum bt_buf_type_e type, + FAR void *data, size_t len); + #endif /* __WIRELESS_BLUETOOTH_BT_HDICORE_H */ diff --git a/wireless/bluetooth/bt_netdev.c b/wireless/bluetooth/bt_netdev.c index 82f455aa1a..9569c4bd80 100644 --- a/wireless/bluetooth/bt_netdev.c +++ b/wireless/bluetooth/bt_netdev.c @@ -1271,7 +1271,7 @@ static int btnet_properties(FAR struct radio_driver_s *netdev, * ****************************************************************************/ -int bt_netdev_register(FAR const struct bt_driver_s *btdev) +int bt_netdev_register(FAR struct bt_driver_s *btdev) { FAR struct btnet_driver_s *priv; FAR struct radio_driver_s *radio; @@ -1354,6 +1354,8 @@ int bt_netdev_register(FAR const struct bt_driver_s *btdev) radio->r_req_data = btnet_req_data; /* Enqueue frame for transmission */ radio->r_properties = btnet_properties; /* Return radio properties */ + btdev->receive = bt_receive; + /* Associate the driver in with the Bluetooth stack. * * REVISIT: We will eventually need to remember which Bluetooth device