Bluetooth: Add HCI driver API
This patch adds a basic HCI driver registration API along with a fiber to process data from the driver. A FIFO is used for receiving data from the driver and waking up the respective fiber. To open and set up the HCI transport for operation there's an open() callback passed to the HCI core. This function will be called as soon as an application initializes Bluetooth functionality through bt_init(). Change-Id: I780cca517a0dfc714f1ca35527e1c61e307345a0 Co-authored-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
64b117a9b1
commit
23a0df8b9b
2 changed files with 102 additions and 2 deletions
|
@ -104,4 +104,26 @@ size_t bt_buf_headroom(struct bt_buf *buf);
|
|||
/* Initialize Bluetooth. Must be the called before anything else. */
|
||||
int bt_init(void);
|
||||
|
||||
/* HCI driver API */
|
||||
|
||||
/* Receive data from the controller/HCI driver */
|
||||
void bt_recv(struct bt_buf *buf);
|
||||
|
||||
struct bt_driver {
|
||||
/* How much headroom is needed for HCI transport headers */
|
||||
size_t head_reserve;
|
||||
|
||||
/* Open the HCI transport */
|
||||
int (*open) (void);
|
||||
|
||||
/* Send data to HCI */
|
||||
int (*send) (struct bt_buf *buf);
|
||||
};
|
||||
|
||||
/* Register a new HCI driver to the Bluetooth stack */
|
||||
int bt_driver_register(struct bt_driver *drv);
|
||||
|
||||
/* Unregister a previously registered HCI driver */
|
||||
void bt_driver_unregister(struct bt_driver *drv);
|
||||
|
||||
#endif /* __BT_BLUETOOTH_H */
|
||||
|
|
|
@ -38,11 +38,24 @@
|
|||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
/* Stacks for the fibers */
|
||||
#define RX_STACK_SIZE 1024
|
||||
static char rx_fiber_stack[RX_STACK_SIZE];
|
||||
|
||||
/* Available (free) buffers queue */
|
||||
#define NUM_BUFS 5
|
||||
static struct bt_buf buffers[NUM_BUFS];
|
||||
static struct nano_fifo free_bufs;
|
||||
|
||||
/* State tracking for the local Bluetooth controller */
|
||||
static struct bt_dev {
|
||||
/* Queue for incoming HCI events & ACL data */
|
||||
struct nano_fifo rx_queue;
|
||||
|
||||
/* Registered HCI driver */
|
||||
struct bt_driver *drv;
|
||||
} dev;
|
||||
|
||||
struct bt_buf *bt_buf_get_reserve(size_t reserve_head)
|
||||
{
|
||||
struct bt_buf *buf;
|
||||
|
@ -104,7 +117,61 @@ size_t bt_buf_tailroom(struct bt_buf *buf)
|
|||
return BT_BUF_MAX_DATA - bt_buf_headroom(buf) - buf->len;
|
||||
}
|
||||
|
||||
static void init_free_queue(void)
|
||||
static void hci_receive_packet(struct bt_buf *buf)
|
||||
{
|
||||
BT_DBG("buf %p type %u\n", buf, buf->type);
|
||||
}
|
||||
|
||||
static void hci_rx_fiber(void)
|
||||
{
|
||||
struct bt_buf *buf;
|
||||
|
||||
BT_DBG("\n");
|
||||
|
||||
while (1) {
|
||||
buf = nano_fifo_get_wait(&dev.rx_queue);
|
||||
|
||||
hci_receive_packet(buf);
|
||||
bt_buf_put(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Interface to HCI driver layer */
|
||||
|
||||
void bt_recv(struct bt_buf *buf)
|
||||
{
|
||||
nano_fifo_put(&dev.rx_queue, buf);
|
||||
}
|
||||
|
||||
int bt_driver_register(struct bt_driver *drv)
|
||||
{
|
||||
if (dev.drv)
|
||||
return -EALREADY;
|
||||
|
||||
if (!drv->open || !drv->send)
|
||||
return -EINVAL;
|
||||
|
||||
dev.drv = drv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_driver_unregister(struct bt_driver *drv)
|
||||
{
|
||||
dev.drv = NULL;
|
||||
}
|
||||
|
||||
/* fibers, fifos and semaphores initialization */
|
||||
|
||||
static void rx_queue_init(void)
|
||||
{
|
||||
nano_fifo_init(&dev.rx_queue);
|
||||
|
||||
fiber_start(rx_fiber_stack, RX_STACK_SIZE,
|
||||
(nano_fiber_entry_t) hci_rx_fiber, 0, 0, 7, 0);
|
||||
}
|
||||
|
||||
static void free_queue_init(void)
|
||||
{
|
||||
nano_fifo_init(&free_bufs);
|
||||
|
||||
|
@ -114,7 +181,18 @@ static void init_free_queue(void)
|
|||
|
||||
int bt_init(void)
|
||||
{
|
||||
init_free_queue();
|
||||
struct bt_driver *drv = dev.drv;
|
||||
int err;
|
||||
|
||||
if (!drv)
|
||||
return -ENODEV;
|
||||
|
||||
free_queue_init();
|
||||
rx_queue_init();
|
||||
|
||||
err = drv->open();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue