2016-09-26 13:37:39 +00:00
/******************************************************************************
*
* Copyright ( C ) 2014 Google , Inc .
*
* 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 <string.h>
2018-04-08 04:10:50 +00:00
# include "common/bt_defs.h"
# include "common/bt_trace.h"
# include "stack/bt_types.h"
# include "osi/fixed_queue.h"
# include "hci/hci_hal.h"
# include "hci/hci_internals.h"
# include "hci/hci_layer.h"
# include "osi/thread.h"
2017-12-07 13:48:27 +00:00
# include "esp_bt.h"
2018-11-01 09:33:44 +00:00
# include "stack/hcimsgs.h"
2016-09-26 13:37:39 +00:00
2018-06-21 03:41:42 +00:00
# if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
# include "l2c_int.h"
# endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
2018-09-14 09:24:25 +00:00
# include "stack/hcimsgs.h"
2018-06-21 03:41:42 +00:00
2016-09-26 13:37:39 +00:00
# define HCI_HAL_SERIAL_BUFFER_SIZE 1026
# define HCI_BLE_EVENT 0x3e
# define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
# define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
2018-07-02 02:59:51 +00:00
extern bool BTU_check_queue_is_congest ( void ) ;
2016-09-26 13:37:39 +00:00
static const uint8_t preamble_sizes [ ] = {
2016-11-24 18:10:15 +00:00
HCI_COMMAND_PREAMBLE_SIZE ,
HCI_ACL_PREAMBLE_SIZE ,
HCI_SCO_PREAMBLE_SIZE ,
HCI_EVENT_PREAMBLE_SIZE
2016-09-26 13:37:39 +00:00
} ;
static const uint16_t outbound_event_types [ ] = {
2016-11-24 18:10:15 +00:00
MSG_HC_TO_STACK_HCI_ERR ,
MSG_HC_TO_STACK_HCI_ACL ,
MSG_HC_TO_STACK_HCI_SCO ,
MSG_HC_TO_STACK_HCI_EVT
2016-09-26 13:37:39 +00:00
} ;
typedef struct {
2016-11-24 18:10:15 +00:00
size_t buffer_size ;
fixed_queue_t * rx_q ;
2019-03-01 13:59:55 +00:00
uint16_t adv_free_num ;
2016-09-26 13:37:39 +00:00
} hci_hal_env_t ;
static hci_hal_env_t hci_hal_env ;
static const hci_hal_t interface ;
static const hci_hal_callbacks_t * callbacks ;
2017-01-03 07:53:06 +00:00
static const esp_vhci_host_callback_t vhci_host_cb ;
2018-09-14 09:24:25 +00:00
static osi_thread_t * hci_h4_thread ;
2016-09-26 13:37:39 +00:00
static void host_send_pkt_available_cb ( void ) ;
static int host_recv_pkt_cb ( uint8_t * data , uint16_t len ) ;
static void hci_hal_h4_rx_handler ( void * arg ) ;
static void event_uart_has_bytes ( fixed_queue_t * queue ) ;
static void hci_hal_env_init (
size_t buffer_size ,
2016-11-24 18:10:15 +00:00
size_t max_buffer_count )
{
assert ( buffer_size > 0 ) ;
assert ( max_buffer_count > 0 ) ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
hci_hal_env . buffer_size = buffer_size ;
2019-03-01 13:59:55 +00:00
hci_hal_env . adv_free_num = 0 ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
hci_hal_env . rx_q = fixed_queue_new ( max_buffer_count ) ;
if ( hci_hal_env . rx_q ) {
fixed_queue_register_dequeue ( hci_hal_env . rx_q , event_uart_has_bytes ) ;
} else {
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " %s unable to create rx queue. \n " , __func__ ) ;
2016-11-24 18:10:15 +00:00
}
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
return ;
2016-09-26 13:37:39 +00:00
}
2016-11-24 18:10:15 +00:00
static void hci_hal_env_deinit ( void )
{
2018-08-15 02:40:51 +00:00
fixed_queue_free ( hci_hal_env . rx_q , osi_free_func ) ;
2018-07-17 07:46:56 +00:00
hci_hal_env . rx_q = NULL ;
2016-09-26 13:37:39 +00:00
}
2018-10-10 08:10:20 +00:00
static bool hal_open ( const hci_hal_callbacks_t * upper_callbacks , void * task_thread )
2016-11-05 11:57:53 +00:00
{
2016-11-24 18:10:15 +00:00
assert ( upper_callbacks ! = NULL ) ;
2018-10-10 08:10:20 +00:00
assert ( task_thread ! = NULL ) ;
2016-11-24 18:10:15 +00:00
callbacks = upper_callbacks ;
2019-03-01 13:59:55 +00:00
# if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
hci_hal_env_init ( HCI_HAL_SERIAL_BUFFER_SIZE , BLE_ADV_REPORT_FLOW_CONTROL_NUM + L2CAP_HOST_FC_ACL_BUFS + QUEUE_SIZE_MAX ) ; // adv flow control num + ACL flow control num + hci cmd numeber
# else
2018-07-02 02:59:51 +00:00
hci_hal_env_init ( HCI_HAL_SERIAL_BUFFER_SIZE , QUEUE_SIZE_MAX ) ;
2019-03-01 13:59:55 +00:00
# endif
2016-09-26 13:37:39 +00:00
2018-10-10 08:10:20 +00:00
hci_h4_thread = ( osi_thread_t * ) task_thread ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
//register vhci host cb
2018-06-15 13:40:51 +00:00
if ( esp_vhci_host_register_callback ( & vhci_host_cb ) ! = ESP_OK ) {
return false ;
}
2017-03-13 13:28:53 +00:00
2016-11-24 18:10:15 +00:00
return true ;
2016-09-26 13:37:39 +00:00
}
2016-11-24 18:10:15 +00:00
static void hal_close ( )
{
hci_hal_env_deinit ( ) ;
2018-09-14 09:24:25 +00:00
hci_h4_thread = NULL ;
2016-09-26 13:37:39 +00:00
}
/**
* Function : transmit_data - TX data to low - layer
* It is ported from Bluedroid source code , so it is not
* needed to use write ( ) to send data .
* TODO : Just use firmware API to send data .
*/
static uint16_t transmit_data ( serial_data_type_t type ,
uint8_t * data , uint16_t length )
{
2016-11-24 18:10:15 +00:00
uint8_t previous_byte ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
assert ( data ! = NULL ) ;
assert ( length > 0 ) ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
if ( type < DATA_TYPE_COMMAND | | type > DATA_TYPE_SCO ) {
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " %s invalid data type: %d " , __func__ , type ) ;
2016-11-24 18:10:15 +00:00
return 0 ;
}
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
// Write the signal byte right before the data
- - data ;
previous_byte = * data ;
* ( data ) = type ;
+ + length ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
BTTRC_DUMP_BUFFER ( " Transmit Pkt " , data , length ) ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
// TX Data to target
2017-01-03 07:53:06 +00:00
esp_vhci_host_send_packet ( data , length ) ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
// Be nice and restore the old value of that byte
* ( data ) = previous_byte ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
return length - 1 ;
2016-09-26 13:37:39 +00:00
}
// Internal functions
2016-11-05 11:57:53 +00:00
static void hci_hal_h4_rx_handler ( void * arg )
{
2018-09-14 09:24:25 +00:00
fixed_queue_process ( hci_hal_env . rx_q ) ;
2016-09-26 13:37:39 +00:00
}
2018-09-14 09:24:25 +00:00
bool hci_hal_h4_task_post ( osi_thread_blocking_t blocking )
2016-09-26 13:37:39 +00:00
{
2018-10-10 08:10:20 +00:00
return osi_thread_post ( hci_h4_thread , hci_hal_h4_rx_handler , NULL , 1 , blocking ) ;
2016-09-26 13:37:39 +00:00
}
2018-06-21 03:41:42 +00:00
# if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
static void hci_packet_complete ( BT_HDR * packet ) {
uint8_t type , num_handle ;
uint16_t handle ;
uint16_t handles [ MAX_L2CAP_LINKS + 4 ] ;
uint16_t num_packets [ MAX_L2CAP_LINKS + 4 ] ;
uint8_t * stream = packet - > data + packet - > offset ;
tL2C_LCB * p_lcb = NULL ;
STREAM_TO_UINT8 ( type , stream ) ;
if ( type = = DATA_TYPE_ACL /* || type == DATA_TYPE_SCO*/ ) {
STREAM_TO_UINT16 ( handle , stream ) ;
handle = handle & HCI_DATA_HANDLE_MASK ;
p_lcb = l2cu_find_lcb_by_handle ( handle ) ;
if ( p_lcb ) {
p_lcb - > completed_packets + + ;
}
if ( esp_vhci_host_check_send_available ( ) ) {
num_handle = l2cu_find_completed_packets ( handles , num_packets ) ;
if ( num_handle > 0 ) {
btsnd_hcic_host_num_xmitted_pkts ( num_handle , handles , num_packets ) ;
}
} else {
//Send HCI_Host_Number_of_Completed_Packets next time.
}
}
}
# endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
2018-07-02 02:59:51 +00:00
bool host_recv_adv_packet ( BT_HDR * packet )
{
assert ( packet ) ;
2019-03-01 13:59:55 +00:00
if ( packet - > data [ 0 ] = = DATA_TYPE_EVENT & & packet - > data [ 1 ] = = HCI_BLE_EVENT ) {
if ( packet - > data [ 3 ] = = HCI_BLE_ADV_PKT_RPT_EVT
# if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
| | packet - > data [ 3 ] = = HCI_BLE_ADV_DISCARD_REPORT_EVT
# endif
) {
return true ;
}
2018-07-02 02:59:51 +00:00
}
return false ;
}
2018-06-21 03:41:42 +00:00
2019-03-01 13:59:55 +00:00
# if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
static void hci_update_adv_report_flow_control ( BT_HDR * packet )
{
// this is adv packet
if ( host_recv_adv_packet ( packet ) ) {
// update adv free number
hci_hal_env . adv_free_num + + ;
if ( esp_vhci_host_check_send_available ( ) ) {
// send hci cmd
btsnd_hcic_ble_update_adv_report_flow_control ( hci_hal_env . adv_free_num ) ;
hci_hal_env . adv_free_num = 0 ;
} else {
//do nothing
}
}
}
# endif
2016-11-24 18:10:15 +00:00
static void hci_hal_h4_hdl_rx_packet ( BT_HDR * packet )
{
uint8_t type , hdr_size ;
uint16_t length ;
uint8_t * stream = packet - > data + packet - > offset ;
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
if ( ! packet ) {
return ;
}
2018-06-21 03:41:42 +00:00
# if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
hci_packet_complete ( packet ) ;
# endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
2016-11-24 18:10:15 +00:00
STREAM_TO_UINT8 ( type , stream ) ;
packet - > offset + + ;
packet - > len - - ;
if ( type = = HCI_BLE_EVENT ) {
2019-03-15 12:59:55 +00:00
# if (!CONFIG_BT_STACK_NO_LOG)
2017-04-20 11:18:05 +00:00
uint8_t len = 0 ;
2016-11-24 18:10:15 +00:00
STREAM_TO_UINT8 ( len , stream ) ;
2019-03-15 12:59:55 +00:00
# endif
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d \n " ,
2016-11-24 18:10:15 +00:00
packet - > len , len ) ;
2018-08-15 02:40:51 +00:00
osi_free ( packet ) ;
2016-11-24 18:10:15 +00:00
return ;
}
if ( type < DATA_TYPE_ACL | | type > DATA_TYPE_EVENT ) {
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " %s Unknown HCI message type. Dropping this byte 0x%x, "
2016-11-24 18:10:15 +00:00
" min %x, max %x \n " , __func__ , type ,
DATA_TYPE_ACL , DATA_TYPE_EVENT ) ;
2018-08-15 02:40:51 +00:00
osi_free ( packet ) ;
2016-11-24 18:10:15 +00:00
return ;
}
hdr_size = preamble_sizes [ type - 1 ] ;
if ( packet - > len < hdr_size ) {
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " Wrong packet length type=%d pkt_len=%d hdr_len=%d " ,
2016-11-24 18:10:15 +00:00
type , packet - > len , hdr_size ) ;
2018-08-15 02:40:51 +00:00
osi_free ( packet ) ;
2016-11-24 18:10:15 +00:00
return ;
}
if ( type = = DATA_TYPE_ACL ) {
stream + = hdr_size - 2 ;
STREAM_TO_UINT16 ( length , stream ) ;
} else {
stream + = hdr_size - 1 ;
STREAM_TO_UINT8 ( length , stream ) ;
}
2016-09-26 13:37:39 +00:00
2016-11-24 18:10:15 +00:00
if ( ( length + hdr_size ) ! = packet - > len ) {
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " Wrong packet length type=%d hdr_len=%d pd_len=%d "
2016-11-24 18:10:15 +00:00
" pkt_len=%d " , type , hdr_size , length , packet - > len ) ;
2018-08-15 02:40:51 +00:00
osi_free ( packet ) ;
2016-11-24 18:10:15 +00:00
return ;
}
2019-03-01 13:59:55 +00:00
# if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
hci_update_adv_report_flow_control ( packet ) ;
# endif
2018-07-02 02:59:51 +00:00
# if SCAN_QUEUE_CONGEST_CHECK
if ( BTU_check_queue_is_congest ( ) & & host_recv_adv_packet ( packet ) ) {
HCI_TRACE_ERROR ( " BtuQueue is congested " ) ;
2018-08-15 02:40:51 +00:00
osi_free ( packet ) ;
2018-07-02 02:59:51 +00:00
return ;
}
# endif
2016-11-24 18:10:15 +00:00
packet - > event = outbound_event_types [ PACKET_TYPE_TO_INDEX ( type ) ] ;
callbacks - > packet_ready ( packet ) ;
2016-09-26 13:37:39 +00:00
}
2016-11-24 18:10:15 +00:00
static void event_uart_has_bytes ( fixed_queue_t * queue )
{
BT_HDR * packet ;
while ( ! fixed_queue_is_empty ( queue ) ) {
packet = fixed_queue_dequeue ( queue ) ;
hci_hal_h4_hdl_rx_packet ( packet ) ;
}
2016-09-26 13:37:39 +00:00
}
2016-11-24 18:10:15 +00:00
static void host_send_pkt_available_cb ( void )
{
//Controller rx cache buffer is ready for receiving new host packet
//Just Call Host main thread task to process pending packets.
2018-09-14 09:24:25 +00:00
hci_host_task_post ( OSI_THREAD_BLOCKING ) ;
2016-09-26 13:37:39 +00:00
}
2016-11-24 18:10:15 +00:00
static int host_recv_pkt_cb ( uint8_t * data , uint16_t len )
{
//Target has packet to host, malloc new buffer for packet
BT_HDR * pkt ;
size_t pkt_size ;
2018-07-17 07:46:56 +00:00
if ( hci_hal_env . rx_q = = NULL ) {
return 0 ;
}
2016-11-24 18:10:15 +00:00
pkt_size = BT_HDR_SIZE + len ;
2018-08-15 02:40:51 +00:00
pkt = ( BT_HDR * ) osi_calloc ( pkt_size ) ;
//pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
2016-11-24 18:10:15 +00:00
if ( ! pkt ) {
2018-04-25 02:11:06 +00:00
HCI_TRACE_ERROR ( " %s couldn't aquire memory for inbound data buffer. \n " , __func__ ) ;
2016-11-24 18:10:15 +00:00
return - 1 ;
}
pkt - > offset = 0 ;
pkt - > len = len ;
pkt - > layer_specific = 0 ;
memcpy ( pkt - > data , data , len ) ;
fixed_queue_enqueue ( hci_hal_env . rx_q , pkt ) ;
2018-09-14 09:24:25 +00:00
hci_hal_h4_task_post ( OSI_THREAD_NON_BLOCKING ) ;
2016-11-24 18:10:15 +00:00
BTTRC_DUMP_BUFFER ( " Recv Pkt " , pkt - > data , len ) ;
return 0 ;
2016-09-26 13:37:39 +00:00
}
2017-01-03 07:53:06 +00:00
static const esp_vhci_host_callback_t vhci_host_cb = {
2016-11-24 18:10:15 +00:00
. notify_host_send_available = host_send_pkt_available_cb ,
. notify_host_recv = host_recv_pkt_cb ,
2016-09-26 13:37:39 +00:00
} ;
static const hci_hal_t interface = {
2016-11-24 18:10:15 +00:00
hal_open ,
hal_close ,
transmit_data ,
2016-09-26 13:37:39 +00:00
} ;
2016-11-24 18:10:15 +00:00
const hci_hal_t * hci_hal_h4_get_interface ( )
{
return & interface ;
2016-09-26 13:37:39 +00:00
}