The full scan function is mainly used to provide BLE scan performance.
This is required for scenes with high scan performance requirements, such as BLE Mesh scenes.
+ config BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED
+ bool "BLE adv report flow control supported"
+ depends on (BTDM_CONTROLLER_MODE_BTDM || BTDM_CONTROLLER_MODE_BLE_ONLY)
+ default y
+ help
+ The function is mainly used to enable flow control for advertising reports. When it is enabled,
+ advertising reports will be discarded by the controller if the number of unprocessed advertising
+ reports exceeds the size of BLE adv report flow control.
+
+ config BLE_ADV_REPORT_FLOW_CONTROL_NUM
+ int "BLE adv report flow control number"
+ depends on BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED
+ range 50 1000
+ default 100
+ help
+ The number of unprocessed advertising report that Bluedroid can save.If you set
+ `BLE_ADV_REPORT_FLOW_CONTROL_NUM` to a small value, this may cause adv packets lost.
+ If you set `BLE_ADV_REPORT_FLOW_CONTROL_NUM` to a large value, Bluedroid may cache a
+ lot of adv packets and this may cause system memory run out. For example, if you set
+ it to 50, the maximum memory consumed by host is 35 * 50 bytes. Please set
+ `BLE_ADV_REPORT_FLOW_CONTROL_NUM` according to your system free memory and handle adv
+ packets as fast as possible, otherwise it will cause adv packets lost.
+
+ config BLE_ADV_REPORT_DISCARD_THRSHOLD
+ int "BLE adv lost event threshold value"
+ depends on BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED
+ range 1 1000
+ default 20
+ help
+ When adv report flow control is enabled, The ADV lost event will be generated when the number
+ of ADV packets lost in the controller reaches this threshold. It is better to set a larger value.
+ If you set `BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it
+ may cause adv packets lost more.
+
endmenu
menuconfig BLUEDROID_ENABLED
ESP_GAP_SEARCH_DISC_CMPL_EVT = 4, /*!< Discovery complete. */
ESP_GAP_SEARCH_DI_DISC_CMPL_EVT = 5, /*!< Discovery complete. */
ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT = 6, /*!< Search cancelled */
+ ESP_GAP_SEARCH_INQ_DISCARD_NUM_EVT = 7, /*!< The number of pkt discarded by flow control */
} esp_gap_search_evt_t;
/**
int num_resps; /*!< Scan result number */
uint8_t adv_data_len; /*!< Adv data length */
uint8_t scan_rsp_len; /*!< Scan response length */
+ uint32_t num_dis; /*!< The number of discard packets */
} scan_rst; /*!< Event parameter of ESP_GAP_BLE_SCAN_RESULT_EVT */
/**
* @brief ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT
#endif ///SMP_INCLUDED == TRUE
static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
static void bta_dm_observe_cmpl_cb(void *p_result);
+static void bta_dm_observe_discard_cb (uint32_t num_dis);
static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle);
extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8 *p_uuid128);
static void bta_dm_disable_timer_cback(TIMER_LIST_ENT *p_tle);
}
}
+/*******************************************************************************
+**
+** Function bta_dm_observe_discard_cb
+**
+** Description Callback for BLE Observe lost
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_observe_discard_cb (uint32_t num_dis)
+{
+ tBTA_DM_SEARCH data;
+
+ APPL_TRACE_DEBUG("bta_dm_observe_discard_cb");
+
+ data.inq_dis.num_dis = num_dis;
+ if (bta_dm_search_cb.p_scan_cback) {
+ bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_DISCARD_NUM_EVT, &data);
+ }
+}
+
#if (SMP_INCLUDED == TRUE)
/*******************************************************************************
**
bta_dm_search_cb.p_scan_cback = p_data->ble_scan.p_cback;
if ((status = BTM_BleScan(TRUE, p_data->ble_scan.duration,
- bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb)) != BTM_CMD_STARTED) {
+ bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb, bta_dm_observe_discard_cb)) != BTM_CMD_STARTED) {
APPL_TRACE_WARNING(" %s start scan failed. status=0x%x\n", __FUNCTION__, status);
}
}
} else {
bta_dm_search_cb.p_scan_cback = NULL;
- status = BTM_BleScan(FALSE, 0, NULL, NULL);
+ status = BTM_BleScan(FALSE, 0, NULL, NULL, NULL);
if (status != BTM_CMD_STARTED){
APPL_TRACE_WARNING(" %s stop scan failed, status=0x%x\n", __FUNCTION__, status);
#define BTA_DM_DISC_CMPL_EVT 4 /* Discovery complete. */
#define BTA_DM_DI_DISC_CMPL_EVT 5 /* Discovery complete. */
#define BTA_DM_SEARCH_CANCEL_CMPL_EVT 6 /* Search cancelled */
+#define BTA_DM_INQ_DISCARD_NUM_EVT 7 /* The number of inquiry discarded packets */
typedef UINT8 tBTA_DM_SEARCH_EVT;
UINT8 num_resps; /* Number of inquiry responses. */
} tBTA_DM_INQ_CMPL;
+/* Structure associated with BTA_DM_INQ_DISCARD_NUM_EVT */
+typedef struct {
+ UINT32 num_dis; /* The number of inquiry discarded packets. */
+} tBTA_DM_INQ_DISCARD;
+
/* Structure associated with BTA_DM_DI_DISC_CMPL_EVT */
typedef struct {
BD_ADDR bd_addr; /* BD address peer device. */
tBTA_DM_DISC_RES disc_res; /* Discovery result for a peer device. */
tBTA_DM_DISC_BLE_RES disc_ble_res; /* Discovery result for GATT based service */
tBTA_DM_DI_DISC_CMPL di_disc; /* DI discovery result for a peer device */
+ tBTA_DM_INQ_DISCARD inq_dis; /* the discarded packets information of inquiry */
} tBTA_DM_SEARCH;
/* Structure of search callback event and structures */
case BTA_DM_SEARCH_CANCEL_CMPL_EVT:
BTC_TRACE_DEBUG("BTA_DM_SEARCH_CANCEL_CMPL_EVT\n");
break;
+ case BTA_DM_INQ_DISCARD_NUM_EVT:
+ param.scan_rst.num_dis = p_data->inq_dis.num_dis;
+ break;
default:
BTC_TRACE_ERROR("%s : Unknown event 0x%x\n", __FUNCTION__, event);
return;
#define SMP_SLAVE_CON_PARAMS_UPD_ENABLE FALSE
#endif
+#ifndef CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED
+#define BLE_ADV_REPORT_FLOW_CONTROL FALSE
+#else
+#define BLE_ADV_REPORT_FLOW_CONTROL CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED
+#endif /* CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED */
+
+#ifndef CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM
+#define BLE_ADV_REPORT_FLOW_CONTROL_NUM 100
+#else
+#define BLE_ADV_REPORT_FLOW_CONTROL_NUM CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM
+#endif /* CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM */
+
+#ifndef CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD
+#define BLE_ADV_REPORT_DISCARD_THRSHOLD 20
+#else
+#define BLE_ADV_REPORT_DISCARD_THRSHOLD CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD
+#endif /* CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD */
+
#if (CONFIG_BT_ACL_CONNECTIONS)
#define MAX_ACL_CONNECTIONS CONFIG_BT_ACL_CONNECTIONS
#define GATT_MAX_PHY_CHANNEL CONFIG_BT_ACL_CONNECTIONS
response = AWAIT_COMMAND(packet_factory->make_set_c2h_flow_control(HCI_HOST_FLOW_CTRL_ACL_ON));
packet_parser->parse_generic_command_complete(response);
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
-
+#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
+ // Enable adv flow control
+ response = AWAIT_COMMAND(packet_factory->make_set_adv_report_flow_control(HCI_HOST_FLOW_CTRL_ADV_REPORT_ON, (uint16_t)BLE_ADV_REPORT_FLOW_CONTROL_NUM, (uint16_t)BLE_ADV_REPORT_DISCARD_THRSHOLD));
+ packet_parser->parse_generic_command_complete(response);
+#endif
// Tell the controller about our buffer sizes and buffer counts next
// TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10?
response = AWAIT_COMMAND(
typedef struct {
size_t buffer_size;
fixed_queue_t *rx_q;
+ uint16_t adv_free_num;
} hci_hal_env_t;
assert(max_buffer_count > 0);
hci_hal_env.buffer_size = buffer_size;
+ hci_hal_env.adv_free_num = 0;
hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
if (hci_hal_env.rx_q) {
{
assert(upper_callbacks != NULL);
callbacks = upper_callbacks;
-
+#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
hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, QUEUE_SIZE_MAX);
+#endif
xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_LEN, sizeof(BtTaskEvt_t));
xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, HCI_H4_TASK_PINNED_TO_CORE);
bool host_recv_adv_packet(BT_HDR *packet)
{
assert(packet);
- if(packet->data[0] == DATA_TYPE_EVENT && packet->data[1] == HCI_BLE_EVENT && packet->data[3] == HCI_BLE_ADV_PKT_RPT_EVT) {
- return true;
+ 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;
+ }
}
return false;
}
+#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
+
static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
{
uint8_t type, hdr_size;
osi_free(packet);
return;
}
+
+#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
+ hci_update_adv_report_flow_control(packet);
+#endif
+
#if SCAN_QUEUE_CONGEST_CHECK
if(BTU_check_queue_is_congest() && host_recv_adv_packet(packet)) {
HCI_TRACE_ERROR("BtuQueue is congested");
return;
}
#endif
-
packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
callbacks->packet_ready(packet);
}
wait_entry = fixed_queue_dequeue(queue);
- if(wait_entry->opcode == HCI_HOST_NUM_PACKETS_DONE){
+ if(wait_entry->opcode == HCI_HOST_NUM_PACKETS_DONE
+#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
+ || wait_entry->opcode == HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL
+#endif
+ ){
packet_fragmenter->fragment_and_dispatch(wait_entry->command);
osi_free(wait_entry->command);
osi_free(wait_entry);
return packet;
}
+static BT_HDR *make_set_adv_report_flow_control(uint8_t enable, uint16_t num, uint16_t lost_threshold)
+{
+ uint8_t *stream;
+ const uint8_t parameter_size = 1 + 2 + 2;
+ BT_HDR *packet = make_command(HCI_VENDOR_BLE_SET_ADV_FLOW_CONTROL, parameter_size, &stream);
+
+ UINT8_TO_STREAM(stream, enable);
+ UINT16_TO_STREAM(stream, num);
+ UINT16_TO_STREAM(stream, lost_threshold);
+ return packet;
+}
+
static BT_HDR *make_host_buffer_size(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count)
{
uint8_t *stream;
make_reset,
make_read_buffer_size,
make_set_c2h_flow_control,
+ make_set_adv_report_flow_control,
make_host_buffer_size,
make_read_local_version_info,
make_read_bd_addr,
BT_HDR *(*make_reset)(void);
BT_HDR *(*make_read_buffer_size)(void);
BT_HDR *(*make_set_c2h_flow_control)(uint8_t enable);
+ BT_HDR *(*make_set_adv_report_flow_control)(uint8_t enable, uint16_t num, uint16_t lost_threshold);
BT_HDR *(*make_host_buffer_size)(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count);
BT_HDR *(*make_read_local_version_info)(void);
BT_HDR *(*make_read_bd_addr)(void);
**
*******************************************************************************/
tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
- tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
+ tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb, tBTM_INQ_DIS_CB *p_discard_cb)
{
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS status = BTM_WRONG_MODE;
btm_cb.ble_ctr_cb.p_scan_results_cb = p_results_cb;
btm_cb.ble_ctr_cb.p_scan_cmpl_cb = p_cmpl_cb;
+ btm_cb.ble_ctr_cb.p_obs_discard_cb = p_discard_cb;
status = BTM_CMD_STARTED;
/* scan is not started */
}
}
+void btm_ble_process_adv_discard_evt(UINT8 *p)
+{
+#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
+ uint32_t num_dis = 0;
+ STREAM_TO_UINT32 (num_dis, p);
+ tBTM_INQ_DIS_CB *p_obs_discard_cb = btm_cb.ble_ctr_cb.p_obs_discard_cb;
+ if(p_obs_discard_cb) {
+ (p_obs_discard_cb)(num_dis);
+ }
+#endif
+}
/*******************************************************************************
**
** Function btm_ble_start_scan
/* observer callback and timer */
tBTM_INQ_RESULTS_CB *p_obs_results_cb;
tBTM_CMPL_CB *p_obs_cmpl_cb;
+ tBTM_INQ_DIS_CB *p_obs_discard_cb;
TIMER_LIST_ENT obs_timer_ent;
/* scan callback and timer */
void btm_ble_timeout(TIMER_LIST_ENT *p_tle);
void btm_ble_process_adv_pkt (UINT8 *p);
+void btm_ble_process_adv_discard_evt(UINT8 *p);
void btm_ble_proc_scan_rsp_rpt (UINT8 *p);
tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur, tBTM_CMPL_CB *p_cb);
BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda);
#if BLE_INCLUDED == TRUE
static void btu_ble_ll_conn_complete_evt (UINT8 *p, UINT16 evt_len);
static void btu_ble_process_adv_pkt (UINT8 *p);
+static void btu_ble_process_adv_dis(UINT8 *p);
static void btu_ble_read_remote_feat_evt (UINT8 *p);
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len);
static void btu_ble_ll_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle);
case HCI_BLE_ADV_PKT_RPT_EVT: /* result of inquiry */
btu_ble_process_adv_pkt(p);
break;
+ case HCI_BLE_ADV_DISCARD_REPORT_EVT:
+ btu_ble_process_adv_dis(p);
+ break;
case HCI_BLE_CONN_COMPLETE_EVT:
btu_ble_ll_conn_complete_evt(p, hci_evt_len);
break;
btm_ble_process_adv_pkt(p);
}
+static void btu_ble_process_adv_dis(UINT8 *p)
+{
+ btm_ble_process_adv_discard_evt(p);
+}
+
static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
{
btm_ble_conn_complete(p, evt_len, FALSE);
return TRUE;
}
+BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (1)) == NULL) {
+ return (FALSE);
+ }
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + 2;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL);
+ UINT8_TO_STREAM (pp, 2);
+ UINT16_TO_STREAM (pp, num);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return TRUE;
+}
+
#endif
*/
typedef void (tBTM_CMPL_CB) (void *p1);
+typedef void (tBTM_INQ_DIS_CB) (uint32_t num_dis);
+
/* VSC callback function for notifying an application that a synchronous
** BTM function is complete. The pointer contains the address of any returned data.
*/
UINT8 num_resp; /* Number of results from the current inquiry */
} tBTM_INQUIRY_CMPL;
-
/* Structure returned with remote name request */
typedef struct {
UINT16 status;
*******************************************************************************/
//extern
tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
- tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb);
+ tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb, tBTM_INQ_DIS_CB *p_discard_cb);
/*******************************************************************************
#define HCI_SUBCODE_BLE_EXTENDED_SCAN_PARAMS 0x06
#define HCI_SUBCODE_BLE_LONG_ADV 0x07
#define HCI_SUBCODE_BLE_DUPLICATE_EXCEPTIONAL_LIST 0x08
+#define HCI_SUBCODE_BLE_SET_ADV_FLOW_CONTROL 0x09
+#define HCI_SUBCODE_BLE_ADV_REPORT_FLOW_CONTROL 0x0A
#define HCI_SUBCODE_BLE_MAX 0x7F
//ESP BT subcode define
#define HCI_VENDOR_BLE_LONG_ADV_DATA HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_LONG_ADV)
/* BLE update duplicate scan exceptional list */
#define HCI_VENDOR_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_DUPLICATE_EXCEPTIONAL_LIST)
+#define HCI_VENDOR_BLE_SET_ADV_FLOW_CONTROL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_SET_ADV_FLOW_CONTROL)
+#define HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_ADV_REPORT_FLOW_CONTROL)
//ESP BT HCI CMD
/* subcode for multi adv feature */
#define HCI_BLE_DATA_LENGTH_CHANGE_EVT 0x07
#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT 0x0a
#define HCI_BLE_DIRECT_ADV_EVT 0x0b
+/* ESP vendor BLE Event sub code */
+#define HCI_BLE_ADV_DISCARD_REPORT_EVT 0XF0
/* Definitions for LE Channel Map */
#define HCI_BLE_CHNL_MAP_SIZE 5
#define HCI_HOST_FLOW_CTRL_SCO_ON 2
#define HCI_HOST_FLOW_CTRL_BOTH_ON 3
+#define HCI_HOST_FLOW_CTRL_ADV_REPORT_OFF 0
+#define HCI_HOST_FLOW_CTRL_ADV_REPORT_ON 1
+
+
BOOLEAN btsnd_hcic_write_auto_flush_tout(UINT16 handle,
UINT16 timeout); /* Write Retransmit Timout */
BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
UINT16 timeout);
+BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num);
+
#define HCIC_PARAM_SIZE_WRITE_AUTHENT_PAYLOAD_TOUT 4
#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_HANDLE_OFF 0
-Subproject commit 48ecf82c99f9e5d729e07c39a9d4c350a0f2f8e9
+Subproject commit a8aed8085d65e92f054d324137d03528409e4a41