Merge branch 'hci-controller-to-host-flow-control' into develop

This commit is contained in:
Matthias Ringwald 2017-04-01 15:46:41 +02:00
commit dcd578c4c7
5 changed files with 201 additions and 42 deletions

View File

@ -14,13 +14,13 @@ The configuration of BTstack is done both at compile time as well as at run time
- provided services
- packet handlers
In the following, we provide an overview of the configuration
that is necessary to setup BTstack. From the point when the run loop
In the following, we provide an overview of the configuration
that is necessary to setup BTstack. From the point when the run loop
is executed, the application runs as a finite
state machine, which processes events received from BTstack. BTstack
groups events logically and provides them via packet handlers.
groups events logically and provides them via packet handlers.
We provide their overview here. For the case that there is a need to inspect the data exchanged
between BTstack and the Bluetooth chipset, we describe how to configure
between BTstack and the Bluetooth chipset, we describe how to configure
packet logging mechanism. Finally, we provide an overview on power management in Bluetooth in general and how to save energy in BTstack.
@ -28,7 +28,7 @@ packet logging mechanism. Finally, we provide an overview on power management in
The file *btstack_config.h* contains three parts:
- \#define HAVE_* directives [listed here](#sec:haveDirectives). These directives describe available system properties, similar to config.h in a autoconf setup.
- \#define ENABLE_* directives [listed here](#sec:enableDirectives). These directives list enabled properties, most importantly ENABLE_CLASSIC and ENABLE_BLE.
- \#define ENABLE_* directives [listed here](#sec:enableDirectives). These directives list enabled properties, most importantly ENABLE_CLASSIC and ENABLE_BLE.
- other #define directives for BTstack configuration, most notably static memory, [see next section](#sec:memoryConfigurationHowTo).
<!-- a name "lst:platformConfiguration"></a-->
@ -79,6 +79,21 @@ ENBALE_LE_CENTRAL | Enable support for LE Central Role in HCI and Sec
ENABLE_LE_SECURE_CONNECTIONS | Enable LE Secure Connections using [mbed TLS library](https://tls.mbed.org)
ENABLE_LE_DATA_CHANNELS | Enable LE Data Channels in credit-based flow control mode
ENABLE_LE_SIGNED_WRITE | Enable LE Signed Writes in ATT/GATT
ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | Enable HCI Controller to Host Flow Control, see below
### HCI Controller to Host Flow Control
In general, BTstack relies on flow control of the HCI transport, either via Hardware CTS/RTS flow control for UART or regular USB flow control. If this is not possible, e.g on an SoC, BTstack can use HCI Controller to Host Flow Control by defining ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL. If enabled, the HCI Transport implementation must be able to buffer the specified packets. In addition, it also need to be able to buffer a few HCI Events. Using a low number of host buffers might result in less throughput.
Host buffer configuration for HCI Controller to Host Flow Control:
#define | Description
------------------|------------
HCI_HOST_ACL_PACKET_NUM | Max number of ACL packets
HCI_HOST_ACL_PACKET_LEN | Max size of HCI Host ACL packets
HCI_HOST_SCO_PACKET_NUM | Max number of ACL packets
HCI_HOST_SCO_PACKET_LEN | Max size of HCI Host SCO packets
### Memory configuration directives {#sec:memoryConfigurationHowTo}
@ -99,7 +114,7 @@ For each HCI connection, a buffer of size HCI_ACL_PAYLOAD_SIZE is reserved. For
<!-- a name "lst:memoryConfiguration"></a-->
<!-- -->
#define | Description
#define | Description
--------|------------
HCI_ACL_PAYLOAD_SIZE | Max size of HCI ACL payloads
MAX_NR_BNEP_CHANNELS | Max number of BNEP channels
@ -118,6 +133,7 @@ MAX_NR_SM_LOOKUP_ENTRIES | Max number of items in Security Manager lookup queue
MAX_NR_WHITELIST_ENTRIES | Max number of items in GAP LE Whitelist to connect to
MAX_NR_LE_DEVICE_DB_ENTRIES | Max number of items in LE Device DB
The memory is set up by calling *btstack_memory_init* function:
btstack_memory_init();
@ -178,7 +194,7 @@ various Bluetooth-related timeouts. They can also be used to handle
periodic events.
Data sources and timers are represented by the *btstack_data_source_t* and
*btstack_timer_source_t* structs respectively. Each of these structs contain
*btstack_timer_source_t* structs respectively. Each of these structs contain
at least a linked list node and a pointer to a callback function. All active timers
and data sources are kept in link lists. While the list of data sources
is unsorted, the timers are sorted by expiration timeout for efficient
@ -189,14 +205,14 @@ before its event handler callback is executed. If you need a periodic
timer, you can re-register the same timer source in the callback
function, as shown in Listing [PeriodicTimerHandler]. Note that BTstack
expects to get called periodically to keep its time, see Section
[on time abstraction](#sec:timeAbstractionPorting) for more on the
tick hardware abstraction.
[on time abstraction](#sec:timeAbstractionPorting) for more on the
tick hardware abstraction.
BTstack provides different run loop implementations that implement the *btstack_run_loop_t* interface:
- Embedded: the main implementation for embedded systems, especially without an RTOS.
- POSIX: implementation for POSIX systems based on the select() call.
- CoreFoundation: implementation for iOS and OS X applications
- CoreFoundation: implementation for iOS and OS X applications
- WICED: implementation for the Broadcom WICED SDK RTOS abstraction that wraps FreeRTOS or ThreadX.
- Windows: implementation for Windows based on Event objects and WaitForMultipleObjects() call.
@ -221,7 +237,7 @@ The complete Run loop API is provided [here](appendix/apis/#sec:runLoopAPIAppend
### Run loop embedded
In the embedded run loop implementation, data sources are constantly polled and
In the embedded run loop implementation, data sources are constantly polled and
the system is put to sleep if no IRQ happens during the poll of all data sources.
The complete run loop cycle looks like this: first, the callback
@ -235,7 +251,7 @@ Incoming data over the UART, USB, or timer ticks will generate an
interrupt and wake up the microcontroller. In order to avoid the
situation where a data source becomes ready just before the run loop
enters sleep mode, an interrupt-driven data source has to call the
*btstack_run_loop_embedded_trigger* function. The call to
*btstack_run_loop_embedded_trigger* function. The call to
*btstack_run_loop_embedded_trigger* sets an
internal flag that is checked in the critical section just before
entering sleep mode causing another run loop cycle.
@ -247,7 +263,7 @@ config file.
The data sources are standard File Descriptors. In the run loop execute implementation,
select() call is used to wait for file descriptors to become ready to read or write,
while waiting for the next timeout.
while waiting for the next timeout.
To enable the use of timers, make sure that you defined HAVE_POSIX_TIME in the config file.
@ -262,30 +278,30 @@ To enable the use of timers, make sure that you defined HAVE_POSIX_TIME in the c
### Run loop Windows
The data sources are Event objects. In the run loop implementation WaitForMultipleObjects() call
is all is used to wait for the Event object to become ready while waiting for the next timeout.
is all is used to wait for the Event object to become ready while waiting for the next timeout.
### Run loop WICED
WICED SDK API does not provide asynchronous read and write to the UART and no direct way to wait for
WICED SDK API does not provide asynchronous read and write to the UART and no direct way to wait for
one or more peripherals to become ready. Therefore, BTstack does not provide direct support for data sources.
Instead, the run loop provides a message queue that allows to schedule functions calls on its thread via
*btstack_run_loop_wiced_execute_code_on_main_thread()*.
*btstack_run_loop_wiced_execute_code_on_main_thread()*.
The HCI transport H4 implementation then uses two lightweight threads to do the
The HCI transport H4 implementation then uses two lightweight threads to do the
blocking read and write operations. When a read or write is complete on
the helper threads, a callback to BTstack is scheduled.
## HCI Transport configuration
The HCI initialization has to adapt BTstack to the used platform. The first
The HCI initialization has to adapt BTstack to the used platform. The first
call is to *hci_init()* and requires information about the HCI Transport to use.
The arguments are:
- *HCI Transport implementation*: On embedded systems, a Bluetooth
module can be connected via USB or an UART port. On embedded, BTstack implements HCI UART Transport Layer (H4) and H4 with eHCILL support, a lightweight low-power variant by Texas Instruments. For POSIX, there is an implementation for HCI H4, HCI H5 and H2 libUSB, and for WICED HCI H4 WICED.
These are accessed by linking the appropriate file, e.g.,
These are accessed by linking the appropriate file, e.g.,
[platform/embedded/hci_transport_h4_embedded.c]()
and then getting a pointer to HCI Transport implementation.
For more information on adapting HCI Transport to different
@ -302,8 +318,8 @@ The arguments are:
layer of BTstack will change the init baud rate to the main one
after the basic setup of the Bluetooth module. A baud rate change
has to be done in a coordinated way at both HCI and hardware level.
For example, on the CC256x, the HCI command to change the baud rate
is sent first, then it is necessary to wait for the confirmation event
For example, on the CC256x, the HCI command to change the baud rate
is sent first, then it is necessary to wait for the confirmation event
from the Bluetooth module. Only now, can the UART baud rate changed.
<!-- -->
@ -316,7 +332,7 @@ After these are ready, HCI is initialized like this:
In addition to these, most UART-based Bluetooth chipset require some
special logic for correct initialization that is not covered by the
special logic for correct initialization that is not covered by the
Bluetooth specification. In particular, this covers:
- setting the baudrate
@ -340,7 +356,7 @@ Finally, the HCI implementation requires some form of persistent storage for lin
during either legacy pairing or the Secure Simple Pairing (SSP). This commonly requires platform
specific code to access the MCUs EEPROM of Flash storage. For the
first steps, BTstack provides a (non) persistent store in memory.
For more see [here](porting/#sec:persistentStoragePorting).
For more see [here](porting/#sec:persistentStoragePorting).
<!-- -->
@ -376,7 +392,7 @@ functions, which in turn may send commands to the Bluetooth module. The
resulting events are delivered back to the application. Instead of
writing a single callback handler for each possible event (as it is done
in some other Bluetooth stacks), BTstack groups events logically and
provides them over a single generic interface. Appendix
provides them over a single generic interface. Appendix
[Events and Errors](generated/appendix/#sec:eventsAndErrorsAppendix)
summarizes the parameters and event
codes of L2CAP and RFCOMM events, as well as possible errors and the
@ -444,12 +460,12 @@ services for the HID Control and HID Interrupt PSMs using
*l2cap_register_service*. In this call, youll also specify
a packet handler to accept and receive keyboard data.
All events names have the form MODULE_EVENT_NAME now, e.g., *gap_event_advertising_report*.
All events names have the form MODULE_EVENT_NAME now, e.g., *gap_event_advertising_report*.
To facilitate working with
events and get rid of manually calculating offsets into packets, BTstack provides
auto-generated getters for all fields of all events in *src/hci_event.h*. All
functions are defined as static inline, so they are not wasting any program memory
if not used. If used, the memory footprint should be identical to accessing the
events and get rid of manually calculating offsets into packets, BTstack provides
auto-generated getters for all fields of all events in *src/hci_event.h*. All
functions are defined as static inline, so they are not wasting any program memory
if not used. If used, the memory footprint should be identical to accessing the
field directly via offsets into the packet. For example, to access fields address_type
and address from the *gap_event_advertising_report* event use following getters:
@ -469,31 +485,31 @@ For this, BTstack provides a configurable packet logging mechanism via hci_dump.
// formats: HCI_DUMP_BLUEZ, HCI_DUMP_PACKETLOGGER, HCI_DUMP_STDOUT
void hci_dump_open(const char *filename, hci_dump_format_t format);
On POSIX systems, you can call *hci_dump_open* with a path and *HCI_DUMP_BLUEZ*
On POSIX systems, you can call *hci_dump_open* with a path and *HCI_DUMP_BLUEZ*
or *HCI_DUMP_PACKETLOGGER* in the setup, i.e., before entering the run loop.
The resulting file can be analyzed with Wireshark
The resulting file can be analyzed with Wireshark
or the Apple's PacketLogger tool.
On embedded systems without a file system, you still can call *hci_dump_open(NULL, HCI_DUMP_STDOUT)*.
It will log all HCI packets to the console via printf.
If you capture the console output, incl. your own debug messages, you can use
If you capture the console output, incl. your own debug messages, you can use
the create_packet_log.py tool in the tools folder to convert a text output into a
PacketLogger file.
In addition to the HCI packets, you can also enable BTstack's debug information by adding
#define ENABLE_LOG_INFO
#define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
to the btstack_config.h and recompiling your application.
## Bluetooth Power Control {#sec:powerControl}
## Bluetooth Power Control {#sec:powerControl}
In most BTstack examples, the device is set to be discoverable and connectable. In this mode, even when there's no active connection, the Bluetooth Controller will periodically activate its receiver in order to listen for inquiries or connecting requests from another device.
The ability to be discoverable requires more energy than the ability to be connected. Being discoverable also announces the device to anybody in the area. Therefore, it is a good idea to pause listening for inquiries when not needed. Other devices that have your Bluetooth address can still connect to your device.
To enable/disable discoverability, you can call:
/**
* @brief Allows to control if device is discoverable. OFF by default.
*/
@ -514,7 +530,7 @@ For Bluetooth Low Energy, the radio is periodically used to broadcast advertisem
To enable/disable advertisements, you can call:
/**
/**
* @brief Enable/Disable Advertisements. OFF by default.
* @param enabled
*/
@ -523,13 +539,10 @@ To enable/disable advertisements, you can call:
If a Bluetooth Controller is neither discoverable nor connectable, it does not need to periodically turn on its radio and it only needs to respond to commands from the Host. In this case, the Bluetooth Controller is free to enter some kind of deep sleep where the power consumption is minimal.
Finally, if that's not sufficient for your application, you could request BTstack to shutdown the Bluetooth Controller. For this, the "on" and "off" functions in the btstack_control_t struct must be implemented. To shutdown the Bluetooth Controller, you can call:
/**
* @brief Requests the change of BTstack power mode.
*/
int hci_power_control(HCI_POWER_MODE mode);
with mode set to *HCI_POWER_OFF*. When needed later, Bluetooth can be started again via by calling it with mode *HCI_POWER_ON*, as seen in all examples.

104
src/hci.c
View File

@ -76,6 +76,20 @@
#include "hci_cmd.h"
#include "hci_dump.h"
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
#ifndef HCI_HOST_ACL_PACKET_NUM
#error "ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL requires to define HCI_HOST_ACL_PACKET_NUM"
#endif
#ifndef HCI_HOST_ACL_PACKET_LEN
#error "ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL requires to define HCI_HOST_ACL_PACKET_LEN"
#endif
#ifndef HCI_HOST_SCO_PACKET_NUM
#error "ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL requires to define HCI_HOST_SCO_PACKET_NUM"
#endif
#ifndef HCI_HOST_SCO_PACKET_LEN
#error "ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL requires to define HCI_HOST_SCO_PACKET_LEN"
#endif
#endif
#define HCI_CONNECTION_TIMEOUT_MS 10000
#define HCI_RESET_RESEND_TIMEOUT_MS 200
@ -401,8 +415,8 @@ static int hci_number_free_sco_slots(void){
}
#endif
// new functions replacing hci_can_send_packet_now[_using_packet_buffer]
int hci_can_send_command_packet_now(void){
// only used to send HCI Host Number Completed Packets
static int hci_can_send_comand_packet_transport(void){
if (hci_stack->hci_packet_buffer_reserved) return 0;
// check for async hci transport implementations
@ -411,7 +425,12 @@ int hci_can_send_command_packet_now(void){
return 0;
}
}
return 1;
}
// new functions replacing hci_can_send_packet_now[_using_packet_buffer]
int hci_can_send_command_packet_now(void){
if (hci_can_send_comand_packet_transport() == 0) return 0;
return hci_stack->num_cmd_packets > 0;
}
@ -687,6 +706,11 @@ static void acl_handler(uint8_t *packet, int size){
hci_connection_timestamp(conn);
#endif
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
hci_stack->host_completed_packets = 1;
conn->num_packets_completed++;
#endif
// handle different packet types
switch (acl_flags & 0x03) {
@ -1143,6 +1167,19 @@ static void hci_initializing_run(void){
hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_FEATURES;
hci_send_cmd(&hci_read_local_supported_features);
break;
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
case HCI_INIT_SET_CONTROLLER_TO_HOST_FLOW_CONTROL:
hci_stack->substate = HCI_INIT_W4_SET_CONTROLLER_TO_HOST_FLOW_CONTROL;
hci_send_cmd(&hci_set_controller_to_host_flow_control, 3); // ACL + SCO Flow Control
break;
case HCI_INIT_HOST_BUFFER_SIZE:
hci_stack->substate = HCI_INIT_W4_HOST_BUFFER_SIZE;
hci_send_cmd(&hci_host_buffer_size, HCI_HOST_ACL_PACKET_LEN, HCI_HOST_SCO_PACKET_LEN,
HCI_HOST_ACL_PACKET_NUM, HCI_HOST_SCO_PACKET_NUM);
break;
#endif
case HCI_INIT_SET_EVENT_MASK:
hci_stack->substate = HCI_INIT_W4_SET_EVENT_MASK;
if (hci_le_supported()){
@ -1152,6 +1189,7 @@ static void hci_initializing_run(void){
hci_send_cmd(&hci_set_event_mask,0xffffffff, 0x1FFFFFFF);
}
break;
#ifdef ENABLE_CLASSIC
case HCI_INIT_WRITE_SIMPLE_PAIRING_MODE:
hci_stack->substate = HCI_INIT_W4_WRITE_SIMPLE_PAIRING_MODE;
@ -2109,6 +2147,15 @@ static void event_handler(uint8_t *packet, int size){
static void sco_handler(uint8_t * packet, uint16_t size){
if (!hci_stack->sco_packet_handler) return;
hci_stack->sco_packet_handler(HCI_SCO_DATA_PACKET, 0, packet, size);
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
hci_con_handle_t con_handle = READ_SCO_CONNECTION_HANDLE(packet);
hci_connection_t *conn = hci_connection_for_handle(con_handle);
if (conn){
conn->num_packets_completed++;
hci_stack->host_completed_packets = 1;
hci_run();
}
#endif
}
#endif
@ -2600,6 +2647,50 @@ void gap_local_bd_addr(bd_addr_t address_buffer){
memcpy(address_buffer, hci_stack->local_bd_addr, 6);
}
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
static void hci_host_num_completed_packets(void){
// create packet manually as arrays are not supported and num_commands should not get reduced
hci_reserve_packet_buffer();
uint8_t * packet = hci_get_outgoing_packet_buffer();
uint16_t size = 0;
uint16_t num_handles = 0;
packet[size++] = 0x35;
packet[size++] = 0x0c;
size++; // skip param len
size++; // skip num handles
// add { handle, packets } entries
btstack_linked_item_t * it;
for (it = (btstack_linked_item_t *) hci_stack->connections; it ; it = it->next){
hci_connection_t * connection = (hci_connection_t *) it;
if (connection->num_packets_completed){
little_endian_store_16(packet, size, connection->con_handle);
size += 2;
little_endian_store_16(packet, size, connection->num_packets_completed);
size += 2;
//
num_handles++;
connection->num_packets_completed = 0;
}
}
packet[2] = size - 3;
packet[3] = num_handles;
hci_stack->host_completed_packets = 0;
hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, packet, size);
hci_stack->hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
// release packet buffer for synchronous transport implementations
if (hci_transport_synchronous()){
hci_stack->hci_packet_buffer_reserved = 0;
}
}
#endif
static void hci_run(void){
// log_info("hci_run: entered");
@ -2622,6 +2713,15 @@ static void hci_run(void){
}
}
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
// send host num completed packets next as they don't require num_cmd_packets > 0
if (!hci_can_send_comand_packet_transport()) return;
if (hci_stack->host_completed_packets){
hci_host_num_completed_packets();
return;
}
#endif
if (!hci_can_send_command_packet_now()) return;
// global/non-connection oriented commands

View File

@ -136,6 +136,7 @@ extern "C" {
// ACL Packet
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( little_endian_read_16(buffer,0) & 0x0fff)
#define READ_SCO_CONNECTION_HANDLE( buffer ) ( little_endian_read_16(buffer,0) & 0x0fff)
#define READ_ACL_FLAGS( buffer ) ( buffer[1] >> 4 )
#define READ_ACL_LENGTH( buffer ) (little_endian_read_16(buffer, 2))
@ -494,6 +495,10 @@ typedef struct {
uint8_t num_acl_packets_sent;
uint8_t num_sco_packets_sent;
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
uint8_t num_packets_completed;
#endif
// LE Connection parameter update
le_con_parameter_update_state_t le_con_parameter_update_state;
uint8_t le_con_param_update_identifier;
@ -552,8 +557,17 @@ typedef enum hci_init_state{
HCI_INIT_W4_READ_BUFFER_SIZE,
HCI_INIT_READ_LOCAL_SUPPORTED_FEATURES,
HCI_INIT_W4_READ_LOCAL_SUPPORTED_FEATURES,
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
HCI_INIT_SET_CONTROLLER_TO_HOST_FLOW_CONTROL,
HCI_INIT_W4_SET_CONTROLLER_TO_HOST_FLOW_CONTROL,
HCI_INIT_HOST_BUFFER_SIZE,
HCI_INIT_W4_HOST_BUFFER_SIZE,
#endif
HCI_INIT_SET_EVENT_MASK,
HCI_INIT_W4_SET_EVENT_MASK,
HCI_INIT_WRITE_SIMPLE_PAIRING_MODE,
HCI_INIT_W4_WRITE_SIMPLE_PAIRING_MODE,
HCI_INIT_WRITE_PAGE_TIMEOUT,
@ -731,6 +745,10 @@ typedef struct {
uint8_t decline_reason;
bd_addr_t decline_addr;
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
uint8_t host_completed_packets;
#endif
#ifdef ENABLE_BLE
uint8_t le_own_addr_type;
bd_addr_t le_random_address;

View File

@ -644,6 +644,15 @@ const hci_cmd_t hci_write_synchronous_flow_control_enable = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x2f), "1"
};
#ifdef ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
/**
* @param flow_control_enable - 0: off, 1: ACL only, 2: SCO only, 3: ACL + SCO
*/
const hci_cmd_t hci_set_controller_to_host_flow_control = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x31), "1"
};
/**
* @param host_acl_data_packet_length
* @param host_synchronous_data_packet_length
@ -654,6 +663,23 @@ const hci_cmd_t hci_host_buffer_size = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x33), "2122"
};
#if 0
//
// command sent manually sent by hci_host_num_completed_packets
//
/**
* @note only single handle supported by BTstack command generator
* @param number_of_handles must be 1
* @param connection_handle
* @param host_num_of_completed_packets for the given connection handle
*/
const hci_cmd_t hci_host_number_of_completed_packets = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x35), "1H2"
};
#endif
#endif
/**
* @param handle
*/

View File

@ -98,6 +98,7 @@ extern const hci_cmd_t hci_enhanced_accept_synchronous_connection;
extern const hci_cmd_t hci_enhanced_setup_synchronous_connection;
extern const hci_cmd_t hci_flush;
extern const hci_cmd_t hci_host_buffer_size;
// extern const hci_cmd_t hci_host_number_of_completed_packets;
extern const hci_cmd_t hci_inquiry;
extern const hci_cmd_t hci_inquiry_cancel;
extern const hci_cmd_t hci_io_capability_request_negative_reply;
@ -132,6 +133,7 @@ extern const hci_cmd_t hci_reset;
extern const hci_cmd_t hci_role_discovery;
extern const hci_cmd_t hci_set_connection_encryption;
extern const hci_cmd_t hci_set_event_mask;
extern const hci_cmd_t hci_set_controller_to_host_flow_control;
extern const hci_cmd_t hci_setup_synchronous_connection;
extern const hci_cmd_t hci_sniff_mode;
extern const hci_cmd_t hci_switch_role_command;