Bluetooth: Add RAW API interface to Bluetooth

HCI RAW channel API is intended to expose HCI interface to the remote
entity. The local Bluetooth controller gets owned by the remote entity
and host Bluetooth stack is not used. RAW API provides direct access
to packets which are sent and received by Bluetooth HCI drivers.

Change-Id: I4ba2b7ca2c2b0d6c5de6ef1f231d1c5b82125e09
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This commit is contained in:
Andrei Emeltchenko 2016-08-09 11:13:52 +03:00 committed by Johan Hedberg
commit 6ab1b9cdc4
5 changed files with 196 additions and 21 deletions

View file

@ -24,7 +24,7 @@ if BLUETOOTH
menu "Bluetooth Drivers"
if BLUETOOTH_STACK_HCI
if BLUETOOTH_STACK_HCI || BLUETOOTH_STACK_HCI_RAW
comment "Bluetooth HCI Driver Options"

View file

@ -0,0 +1,20 @@
/* hci_raw.h - Bluetooth HCI RAW channel handling */
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
int bt_send(struct net_buf *buf);
int bt_enable_raw(struct nano_fifo *rx_queue);

View file

@ -42,6 +42,12 @@ config BLUETOOTH_STACK_NBLE
help
Select the Bluetooth stack to use with Nordic BLE drivers.
config BLUETOOTH_STACK_HCI_RAW
bool "Bluetooth RAW HCI access to the controller"
help
This option allows to access Bluetooth controller
from the application with the RAW HCI protocol.
endchoice
comment "HCI Stack Configurations"
@ -62,7 +68,7 @@ config BLUETOOTH_LE
Currently it is mandatory whenever Bluetooth support
(CONFIG_BLUETOOTH) is enabled.
if BLUETOOTH_LE
if BLUETOOTH_LE || BLUETOOTH_STACK_HCI_RAW
config BLUETOOTH_HCI_CMD_COUNT
int "Number of HCI command buffers"
default 2
@ -100,7 +106,27 @@ config BLUETOOTH_MAX_EVT_LEN
for LE is the Command Complete for Read Local Supported
Commands. It is a 3 byte Command Complete header + 65 byte
return parameters = 68 bytes in total.
endif # BLUETOOTH_LE || BLUETOOTH_STACK_HCI_RAW
if (BLUETOOTH_LE && BLUETOOTH_CONN) || BLUETOOTH_STACK_HCI_RAW
config BLUETOOTH_ACL_IN_COUNT
int "Number of incoming ACL data buffers"
default 5
range 2 64
help
Number of buffers available for incoming ACL data.
config BLUETOOTH_L2CAP_IN_MTU
int "Maximum supported L2CAP MTU for incoming data"
default 65 if BLUETOOTH_SMP
default 23 if !BLUETOOTH_SMP
range 65 1300 if BLUETOOTH_SMP
range 23 1300 if !BLUETOOTH_SMP
help
Maximum size of each incoming L2CAP PDU.
endif # BLUETOOTH_LE && BLUETOOTH_CONN || BLUETOOTH_STACK_HCI_RAW
if BLUETOOTH_LE
config BLUETOOTH_RX_STACK_SIZE
int "Size of the receiving fiber stack"
default 1024
@ -134,22 +160,6 @@ config BLUETOOTH_CONN
default n
if BLUETOOTH_CONN
config BLUETOOTH_ACL_IN_COUNT
int "Number of incoming ACL data buffers"
default 5
range 2 64
help
Number of buffers available for incoming ACL data.
config BLUETOOTH_L2CAP_IN_MTU
int "Maximum supported L2CAP MTU for incoming data"
default 65 if BLUETOOTH_SMP
default 23 if !BLUETOOTH_SMP
range 65 1300 if BLUETOOTH_SMP
range 23 1300 if !BLUETOOTH_SMP
help
Maximum size of each incoming L2CAP PDU.
config BLUETOOTH_ATT_MTU
int "Attribute Protocol (ATT) channel MTU"
default 50 if BLUETOOTH_SMP # BLUETOOTH_L2CAP_IN_MTU is big enough

View file

@ -1,8 +1,11 @@
ccflags-y +=-I$(srctree)/include/drivers
obj-$(CONFIG_BLUETOOTH_STACK_HCI) = \
hci_core.o \
uuid.o
obj-$(CONFIG_BLUETOOTH_STACK_HCI) += \
uuid.o \
hci_core.o
obj-$(CONFIG_BLUETOOTH_STACK_HCI_RAW) += \
hci_raw.o
obj-$(CONFIG_BLUETOOTH_DEBUG) += log.o

142
net/bluetooth/hci_raw.c Normal file
View file

@ -0,0 +1,142 @@
/* hci_userchan.c - HCI user channel Bluetooth handling */
/*
* Copyright (c) 2015-2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <atomic.h>
#include <bluetooth/driver.h>
#include <bluetooth/log.h>
#include "monitor.h"
static struct nano_fifo *raw_rx;
/* ACL incoming buffers */
static struct nano_fifo avail_acl_in;
static NET_BUF_POOL(acl_in_pool, CONFIG_BLUETOOTH_ACL_IN_COUNT,
BT_BUF_ACL_IN_SIZE, &avail_acl_in, NULL,
sizeof(uint8_t));
/* HCI event buffers */
static struct nano_fifo avail_hci_evt;
static NET_BUF_POOL(hci_evt_pool, CONFIG_BLUETOOTH_HCI_EVT_COUNT,
BT_BUF_EVT_SIZE, &avail_hci_evt, NULL,
sizeof(uint8_t));
static struct bt_dev {
/* Registered HCI driver */
struct bt_driver *drv;
} bt_dev;
int bt_driver_register(struct bt_driver *drv)
{
if (bt_dev.drv) {
return -EALREADY;
}
if (!drv->open || !drv->send) {
return -EINVAL;
}
bt_dev.drv = drv;
BT_DBG("Registered %s", drv->name ? drv->name : "");
bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, drv->bus,
BT_ADDR_ANY, drv->name ? drv->name : "bt0");
return 0;
}
void bt_driver_unregister(struct bt_driver *drv)
{
bt_dev.drv = NULL;
}
struct net_buf *bt_buf_get_evt(uint8_t opcode)
{
struct net_buf *buf;
buf = net_buf_get(&avail_hci_evt, 0);
if (buf) {
bt_buf_set_type(buf, BT_BUF_EVT);
}
return buf;
}
struct net_buf *bt_buf_get_acl(void)
{
struct net_buf *buf;
buf = net_buf_get(&avail_acl_in, 0);
if (buf) {
bt_buf_set_type(buf, BT_BUF_ACL_IN);
}
return buf;
}
int bt_recv(struct net_buf *buf)
{
BT_DBG("buf %p len %u", buf, buf->len);
bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
/* Queue to RAW rx queue */
net_buf_put(raw_rx, buf);
return 0;
}
int bt_send(struct net_buf *buf)
{
BT_DBG("buf %p len %u", buf, buf->len);
bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
return bt_dev.drv->send(buf);
}
int bt_enable_raw(struct nano_fifo *rx_queue)
{
struct bt_driver *drv = bt_dev.drv;
int err;
BT_DBG("");
net_buf_pool_init(hci_evt_pool);
net_buf_pool_init(acl_in_pool);
raw_rx = rx_queue;
if (!bt_dev.drv) {
BT_ERR("No HCI driver registered");
return -ENODEV;
}
err = drv->open();
if (err) {
BT_ERR("HCI driver open failed (%d)", err);
return err;
}
BT_INFO("Bluetooth enabled in RAW mode");
return 0;
}