forked from espressif/esp-idf
fix(ble scan): Malloc fail will lead to stop receive adv packets
This commit is contained in:
@@ -30,6 +30,15 @@ typedef enum {
|
|||||||
ESP_BLUEDROID_STATUS_ENABLED /*!< Bluetooth initialized and enabled */
|
ESP_BLUEDROID_STATUS_ENABLED /*!< Bluetooth initialized and enabled */
|
||||||
} esp_bluedroid_status_t;
|
} esp_bluedroid_status_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ADV_PKT = 0,
|
||||||
|
OTHER_PKT = 1
|
||||||
|
} hci_recv_pkt_type_t;
|
||||||
|
|
||||||
|
typedef void (* hci_recv_fail_cb_t)(hci_recv_pkt_type_t type, uint16_t pkt_len, uint32_t free_heap_size);
|
||||||
|
|
||||||
|
extern esp_err_t esp_bt_register_hci_recv_fail_callback(hci_recv_fail_cb_t callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get bluetooth stack status
|
* @brief Get bluetooth stack status
|
||||||
*
|
*
|
||||||
|
@@ -26,18 +26,28 @@
|
|||||||
#include "osi/thread.h"
|
#include "osi/thread.h"
|
||||||
#include "esp_bt.h"
|
#include "esp_bt.h"
|
||||||
#include "stack/hcimsgs.h"
|
#include "stack/hcimsgs.h"
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
#include "osi/mutex.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
|
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
|
||||||
#include "l2c_int.h"
|
#include "l2c_int.h"
|
||||||
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
|
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
|
||||||
#include "stack/hcimsgs.h"
|
#include "stack/hcimsgs.h"
|
||||||
|
|
||||||
|
#define HCI_RECV_HEAP_MONITOR_SIZE (5120) // 5k buffer
|
||||||
#define HCI_HAL_SERIAL_BUFFER_SIZE 1026
|
#define HCI_HAL_SERIAL_BUFFER_SIZE 1026
|
||||||
#define HCI_BLE_EVENT 0x3e
|
#define HCI_BLE_EVENT 0x3e
|
||||||
#define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
|
#define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
|
||||||
#define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
|
#define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
|
||||||
extern bool BTU_check_queue_is_congest(void);
|
extern bool BTU_check_queue_is_congest(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ADV_PKT = 0,
|
||||||
|
OTHER_PKT = 1
|
||||||
|
} hci_recv_pkt_type_t;
|
||||||
|
|
||||||
|
typedef void (* hci_recv_fail_cb_t)(hci_recv_pkt_type_t type, uint16_t pkt_len, uint32_t free_heap_size);
|
||||||
|
|
||||||
static const uint8_t preamble_sizes[] = {
|
static const uint8_t preamble_sizes[] = {
|
||||||
HCI_COMMAND_PREAMBLE_SIZE,
|
HCI_COMMAND_PREAMBLE_SIZE,
|
||||||
@@ -65,6 +75,11 @@ static const hci_hal_t interface;
|
|||||||
static const hci_hal_callbacks_t *callbacks;
|
static const hci_hal_callbacks_t *callbacks;
|
||||||
static const esp_vhci_host_callback_t vhci_host_cb;
|
static const esp_vhci_host_callback_t vhci_host_cb;
|
||||||
static osi_thread_t *hci_h4_thread;
|
static osi_thread_t *hci_h4_thread;
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
static osi_mutex_t adv_flow_lock;
|
||||||
|
static esp_timer_handle_t monitor_timer = NULL;
|
||||||
|
#endif
|
||||||
|
static hci_recv_fail_cb_t hci_recv_fail_cb = NULL;
|
||||||
|
|
||||||
static void host_send_pkt_available_cb(void);
|
static void host_send_pkt_available_cb(void);
|
||||||
static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
|
static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
|
||||||
@@ -72,11 +87,30 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
|
|||||||
static void hci_hal_h4_rx_handler(void *arg);
|
static void hci_hal_h4_rx_handler(void *arg);
|
||||||
static void event_uart_has_bytes(fixed_queue_t *queue);
|
static void event_uart_has_bytes(fixed_queue_t *queue);
|
||||||
|
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
static void monitor_timer_cb(void* arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_bt_register_hci_recv_fail_callback(hci_recv_fail_cb_t callback)
|
||||||
|
{
|
||||||
|
if (callback) {
|
||||||
|
hci_recv_fail_cb = callback;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
static void hci_hal_env_init(
|
static void hci_hal_env_init(
|
||||||
size_t buffer_size,
|
size_t buffer_size,
|
||||||
size_t max_buffer_count)
|
size_t max_buffer_count)
|
||||||
{
|
{
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
const esp_timer_create_args_t monitor_timer_args = {
|
||||||
|
.callback = &monitor_timer_cb,
|
||||||
|
.name = "monitor_timer"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
assert(buffer_size > 0);
|
assert(buffer_size > 0);
|
||||||
assert(max_buffer_count > 0);
|
assert(max_buffer_count > 0);
|
||||||
|
|
||||||
@@ -90,6 +124,13 @@ static void hci_hal_env_init(
|
|||||||
HCI_TRACE_ERROR("%s unable to create rx queue.\n", __func__);
|
HCI_TRACE_ERROR("%s unable to create rx queue.\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
osi_mutex_new(&adv_flow_lock);
|
||||||
|
esp_timer_create(&monitor_timer_args, &monitor_timer);
|
||||||
|
assert(monitor_timer);
|
||||||
|
esp_timer_start_periodic(monitor_timer, 5000000);
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +138,15 @@ static void hci_hal_env_deinit(void)
|
|||||||
{
|
{
|
||||||
fixed_queue_free(hci_hal_env.rx_q, osi_free_func);
|
fixed_queue_free(hci_hal_env.rx_q, osi_free_func);
|
||||||
hci_hal_env.rx_q = NULL;
|
hci_hal_env.rx_q = NULL;
|
||||||
|
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
osi_mutex_free(&adv_flow_lock);
|
||||||
|
if (monitor_timer) {
|
||||||
|
esp_timer_stop(monitor_timer);
|
||||||
|
esp_timer_delete(monitor_timer);
|
||||||
|
monitor_timer = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hal_open(const hci_hal_callbacks_t *upper_callbacks, void *task_thread)
|
static bool hal_open(const hci_hal_callbacks_t *upper_callbacks, void *task_thread)
|
||||||
@@ -205,13 +255,12 @@ static void hci_packet_complete(BT_HDR *packet){
|
|||||||
}
|
}
|
||||||
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
|
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
|
||||||
|
|
||||||
bool host_recv_adv_packet(BT_HDR *packet)
|
bool host_recv_adv_packet(uint8_t *data)
|
||||||
{
|
{
|
||||||
assert(packet);
|
if(data[0] == DATA_TYPE_EVENT && data[1] == HCI_BLE_EVENT) {
|
||||||
if(packet->data[0] == DATA_TYPE_EVENT && packet->data[1] == HCI_BLE_EVENT) {
|
if(data[3] == HCI_BLE_ADV_PKT_RPT_EVT || (data[3] == HCI_BLE_DIRECT_ADV_EVT)
|
||||||
if(packet->data[3] == HCI_BLE_ADV_PKT_RPT_EVT
|
|
||||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|| packet->data[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT
|
|| (data[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
@@ -221,21 +270,37 @@ bool host_recv_adv_packet(BT_HDR *packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
static void hci_update_adv_report_flow_control(BT_HDR *packet)
|
static void hci_update_adv_report_flow_control(bool need_add)
|
||||||
{
|
{
|
||||||
// this is adv packet
|
uint16_t temp_adv_free_num;
|
||||||
if(host_recv_adv_packet(packet)) {
|
|
||||||
|
osi_mutex_lock(&adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
|
if (need_add) {
|
||||||
// update adv free number
|
// update adv free number
|
||||||
hci_hal_env.adv_free_num ++;
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
temp_adv_free_num = hci_hal_env.adv_free_num;
|
||||||
|
osi_mutex_unlock(&adv_flow_lock);
|
||||||
|
|
||||||
|
if ((temp_adv_free_num > 0) && (esp_vhci_host_check_send_available())){
|
||||||
|
// send hci cmd
|
||||||
|
if (btsnd_hcic_ble_update_adv_report_flow_control(temp_adv_free_num)) {
|
||||||
|
// update adv free number
|
||||||
|
osi_mutex_lock(&adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
|
hci_hal_env.adv_free_num -= temp_adv_free_num;
|
||||||
|
osi_mutex_unlock(&adv_flow_lock);
|
||||||
|
} else {
|
||||||
|
HCI_TRACE_ERROR("Send Adv Flow HCI command fail");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void monitor_timer_cb(void* arg)
|
||||||
|
{
|
||||||
|
hci_update_adv_report_flow_control(false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -296,11 +361,13 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
hci_update_adv_report_flow_control(packet);
|
if (host_recv_adv_packet(packet->data)) {
|
||||||
|
hci_update_adv_report_flow_control(true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SCAN_QUEUE_CONGEST_CHECK
|
#if SCAN_QUEUE_CONGEST_CHECK
|
||||||
if(BTU_check_queue_is_congest() && host_recv_adv_packet(packet)) {
|
if(BTU_check_queue_is_congest() && host_recv_adv_packet(packet->data)) {
|
||||||
HCI_TRACE_DEBUG("BtuQueue is congested");
|
HCI_TRACE_DEBUG("BtuQueue is congested");
|
||||||
osi_free(packet);
|
osi_free(packet);
|
||||||
return;
|
return;
|
||||||
@@ -336,13 +403,20 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine whether it is a broadcase packet, if so, check the free heap size.
|
||||||
|
if (host_recv_adv_packet(data)) {
|
||||||
|
if (esp_get_free_heap_size() < HCI_RECV_HEAP_MONITOR_SIZE) {
|
||||||
|
goto hci_recv_fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pkt_size = BT_HDR_SIZE + len;
|
pkt_size = BT_HDR_SIZE + len;
|
||||||
pkt = (BT_HDR *) osi_calloc(pkt_size);
|
pkt = (BT_HDR *) osi_calloc(pkt_size);
|
||||||
//pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
|
|
||||||
if (!pkt) {
|
if (!pkt) {
|
||||||
HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
|
HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
|
||||||
return -1;
|
goto hci_recv_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->offset = 0;
|
pkt->offset = 0;
|
||||||
pkt->len = len;
|
pkt->len = len;
|
||||||
pkt->layer_specific = 0;
|
pkt->layer_specific = 0;
|
||||||
@@ -353,6 +427,23 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
|
|||||||
|
|
||||||
BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
|
BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hci_recv_fail:
|
||||||
|
|
||||||
|
if (host_recv_adv_packet(data)) {
|
||||||
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
hci_update_adv_report_flow_control(true);
|
||||||
|
#endif
|
||||||
|
if (hci_recv_fail_cb) {
|
||||||
|
hci_recv_fail_cb(ADV_PKT, len, esp_get_free_heap_size());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hci_recv_fail_cb) {
|
||||||
|
hci_recv_fail_cb(OTHER_PKT, len, esp_get_free_heap_size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user