component/bt: use the OSI utility "pkt_queue" to store ADV report packet in btu layer

This commit is contained in:
Karl Wang 2022-07-18 01:56:28 +08:00 committed by wangmengyang
parent 57336e0a0e
commit a075aa564f
9 changed files with 234 additions and 62 deletions

View File

@ -19,21 +19,23 @@
#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"
#include "osi/pkt_queue.h"
#include "esp_bt.h"
#include "stack/hcimsgs.h"
#if SOC_ESP_NIMBLE_CONTROLLER
#include "nimble/ble_hci_trans.h"
#endif
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
#include "l2c_int.h"
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
#include "stack/hcimsgs.h"
#if SOC_ESP_NIMBLE_CONTROLLER
#include "nimble/ble_hci_trans.h"
#endif
#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)
@ -57,8 +59,8 @@ static const uint16_t outbound_event_types[] = {
};
typedef struct {
size_t buffer_size;
fixed_queue_t *rx_q;
struct pkt_queue *adv_rpt_q;
uint16_t adv_free_num;
hci_hal_callbacks_t *callbacks;
osi_thread_t *hci_h4_thread;
@ -73,6 +75,7 @@ static const esp_vhci_host_callback_t vhci_host_cb;
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_hdl_rx_packet(BT_HDR *packet);
static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt);
static void hci_upstream_data_handler(void *arg);
static bool hci_upstream_data_post(uint32_t timeout);
@ -81,21 +84,16 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr
assert(upper_callbacks != NULL);
assert(task_thread != NULL);
size_t max_buffer_count;
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
max_buffer_count = 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
max_buffer_count = QUEUE_SIZE_MAX; // adv flow control num + ACL flow control num + hci cmd numeber
#endif
hci_hal_env.hci_h4_thread = task_thread;
hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks;
hci_hal_env.buffer_size = HCI_HAL_SERIAL_BUFFER_SIZE;
hci_hal_env.adv_free_num = 0;
hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
hci_hal_env.rx_q = fixed_queue_new(QUEUE_SIZE_MAX);
assert(hci_hal_env.rx_q != NULL);
hci_hal_env.adv_rpt_q = pkt_queue_create();
assert(hci_hal_env.adv_rpt_q != NULL);
struct osi_event *event = osi_event_create(hci_upstream_data_handler, NULL);
assert(event != NULL);
hci_hal_env.upstream_data_ready = event;
@ -109,6 +107,9 @@ static void hci_hal_env_deinit(void)
fixed_queue_free(hci_hal_env.rx_q, osi_free_func);
hci_hal_env.rx_q = NULL;
pkt_queue_destroy(hci_hal_env.adv_rpt_q, NULL);
hci_hal_env.adv_rpt_q = NULL;
osi_event_delete(hci_hal_env.upstream_data_ready);
hci_hal_env.upstream_data_ready = NULL;
@ -173,18 +174,31 @@ static uint16_t transmit_data(serial_data_type_t type,
// Internal functions
static void hci_upstream_data_handler(void *arg)
{
fixed_queue_t *queue = hci_hal_env.rx_q;
BT_HDR *packet;
fixed_queue_t *rx_q = hci_hal_env.rx_q;
struct pkt_queue *adv_rpt_q = hci_hal_env.adv_rpt_q;
size_t pkts_to_process;
size_t pkts_to_process = fixed_queue_length(queue);
for (size_t i = 0; i < pkts_to_process; i++) {
packet = fixed_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
if (packet != NULL) {
hci_hal_h4_hdl_rx_packet(packet);
do {
pkts_to_process = fixed_queue_length(rx_q);
for (size_t i = 0; i < pkts_to_process; i++) {
BT_HDR *packet = fixed_queue_dequeue(rx_q, 0);
if (packet != NULL) {
hci_hal_h4_hdl_rx_packet(packet);
}
}
}
} while (0);
if (!fixed_queue_is_empty(queue)) {
do {
pkts_to_process = pkt_queue_length(adv_rpt_q);
for (size_t i = 0; i < pkts_to_process; i++) {
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(adv_rpt_q);
if (linked_pkt != NULL) {
hci_hal_h4_hdl_rx_adv_rpt(linked_pkt);
}
}
} while (0);
if (!fixed_queue_is_empty(rx_q) || pkt_queue_length(adv_rpt_q) > 0) {
hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);
}
}
@ -210,13 +224,13 @@ static void hci_packet_complete(BT_HDR *packet){
}
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
bool host_recv_adv_packet(BT_HDR *packet)
bool host_recv_adv_packet(uint8_t *packet)
{
assert(packet);
if(packet->data[0] == DATA_TYPE_EVENT && packet->data[1] == HCI_BLE_EVENT) {
if(packet->data[3] == HCI_BLE_ADV_PKT_RPT_EVT
if(packet[0] == DATA_TYPE_EVENT && packet[1] == HCI_BLE_EVENT) {
if(packet[3] == HCI_BLE_ADV_PKT_RPT_EVT
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|| packet->data[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT
|| packet[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT
#endif
) {
return true;
@ -229,7 +243,8 @@ bool host_recv_adv_packet(BT_HDR *packet)
static void hci_update_adv_report_flow_control(BT_HDR *packet)
{
// this is adv packet
if(host_recv_adv_packet(packet)) {
uint8_t *data = packet->data + packet->offset;
if(host_recv_adv_packet(data)) {
// update adv free number
hci_hal_env.adv_free_num ++;
if (esp_vhci_host_check_send_available()){
@ -301,19 +316,61 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
return;
}
packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
hci_hal_env.callbacks->packet_ready(packet);
}
static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt)
{
uint8_t type;
uint8_t hdr_size;
uint16_t length;
uint8_t *stream = NULL;
if (!linked_pkt) {
return;
}
BT_HDR* packet = (BT_HDR *)linked_pkt->data;
stream = packet->data + packet->offset;
assert(host_recv_adv_packet(stream) == true);
STREAM_TO_UINT8(type, stream);
packet->offset++;
packet->len--;
hdr_size = preamble_sizes[type - 1];
if (packet->len < hdr_size) {
HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d",
type, packet->len, hdr_size);
osi_free(linked_pkt);
return;
}
stream += hdr_size - 1;
STREAM_TO_UINT8(length, stream);
if ((length + hdr_size) != packet->len) {
HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
"pkt_len=%d", type, hdr_size, length, packet->len);
osi_free(linked_pkt);
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)) {
if(BTU_check_queue_is_congest()) {
HCI_TRACE_DEBUG("BtuQueue is congested");
osi_free(packet);
osi_free(linked_pkt);
return;
}
#endif
packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
hci_hal_env.callbacks->packet_ready(packet);
hci_hal_env.callbacks->adv_rpt_ready(linked_pkt);
}
static void host_send_pkt_available_cb(void)
@ -326,25 +383,44 @@ static void host_send_pkt_available_cb(void)
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;
BT_HDR *pkt = NULL;
pkt_linked_item_t *linked_pkt = NULL;
size_t pkt_size;
if (hci_hal_env.rx_q == NULL) {
return 0;
}
pkt_size = BT_HDR_SIZE + len;
pkt = (BT_HDR *) osi_calloc(pkt_size);
bool is_adv_rpt = host_recv_adv_packet(data);
if (!pkt) {
HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
return -1;
if (!is_adv_rpt) {
pkt_size = BT_HDR_SIZE + len;
pkt = (BT_HDR *) osi_calloc(pkt_size);
if (!pkt) {
HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
assert(0);
}
pkt->offset = 0;
pkt->len = len;
pkt->layer_specific = 0;
memcpy(pkt->data, data, len);
fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT);
} else {
pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len;
linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size);
if (!linked_pkt) {
// TODO: handle the adv report flow control exception
return 0;
}
pkt = (BT_HDR *)linked_pkt->data;
pkt->offset = 0;
pkt->len = len;
pkt->layer_specific = 0;
memcpy(pkt->data, data, len);
pkt_queue_enqueue(hci_hal_env.adv_rpt_q, linked_pkt);
}
pkt->offset = 0;
pkt->len = len;
pkt->layer_specific = 0;
memcpy(pkt->data, data, len);
fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT);
hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);
BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);

View File

@ -102,6 +102,7 @@ static bool filter_incoming_event(BT_HDR *packet);
static serial_data_type_t event_to_data_type(uint16_t event);
static waiting_command_t *get_waiting_command(command_opcode_t opcode);
static void dispatch_reassembled(BT_HDR *packet);
static void dispatch_adv_report(pkt_linked_item_t *linked_pkt);
// Module lifecycle functions
int hci_start_up(void)
@ -421,6 +422,11 @@ static void hal_says_packet_ready(BT_HDR *packet)
}
}
static void hal_says_adv_rpt_ready(pkt_linked_item_t *linked_pkt)
{
dispatch_adv_report(linked_pkt);
}
// Returns true if the event was intercepted and should not proceed to
// higher layers. Also inspects an incoming event for interesting
// information, like how many commands are now able to be sent.
@ -518,6 +524,14 @@ static void dispatch_reassembled(BT_HDR *packet)
}
}
static void dispatch_adv_report(pkt_linked_item_t *linked_pkt)
{
// Events should already have been dispatched before this point
//Tell Up-layer received packet.
if (btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, linked_pkt, OSI_THREAD_MAX_TIMEOUT) == false) {
osi_free(linked_pkt);
}
}
// Misc internal functions
// TODO(zachoverflow): we seem to do this a couple places, like the HCI inject module. #centralize
@ -570,7 +584,8 @@ static void init_layer_interface(void)
}
static const hci_hal_callbacks_t hal_callbacks = {
hal_says_packet_ready
hal_says_packet_ready,
hal_says_adv_rpt_ready,
};
static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {

View File

@ -21,7 +21,7 @@
#include <stdbool.h>
#include <stdint.h>
#include "osi/pkt_queue.h"
#include "stack/bt_types.h"
#if SOC_ESP_NIMBLE_CONTROLLER
#include "os/os_mbuf.h"
@ -34,12 +34,14 @@ typedef enum {
} serial_data_type_t;
typedef void (*packet_ready_cb)(BT_HDR *packet);
typedef void (*adv_rpt_ready_cb)(pkt_linked_item_t *linked_pkt);
typedef struct {
// Called when the HAL detects inbound data.
// Data |type| may be ACL, SCO, or EVENT.
// Executes in the context of the thread supplied to |init|.
packet_ready_cb packet_ready;
adv_rpt_ready_cb adv_rpt_ready;
/*
// Called when the HAL detects inbound astronauts named Dave.

View File

@ -82,6 +82,7 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
tBLE_ADDR_TYPE *p_own_addr_type);
static void btm_ble_stop_observe(void);
static void btm_ble_stop_discover(void);
static void btm_adv_pkt_handler(void *arg);
uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb);
#define BTM_BLE_INQ_RESULT 0x01
@ -3455,6 +3456,41 @@ void btm_send_sel_conn_callback(BD_ADDR remote_bda, UINT8 evt_type, UINT8 *p_dat
}
}
static void btm_adv_pkt_handler(void *arg)
{
UINT8 hci_evt_code, hci_evt_len;
UINT8 ble_sub_code;
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
size_t pkts_to_process = pkt_queue_length(p_cb->adv_rpt_queue);
for (size_t i = 0; i < pkts_to_process; i++) {
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(p_cb->adv_rpt_queue);
assert(linked_pkt != NULL);
BT_HDR *packet = (BT_HDR *)linked_pkt->data;
uint8_t *p = packet->data + packet->offset;
STREAM_TO_UINT8 (hci_evt_code, p);
STREAM_TO_UINT8 (hci_evt_len, p);
STREAM_TO_UINT8 (ble_sub_code, p);
if (ble_sub_code == HCI_BLE_ADV_PKT_RPT_EVT) {
btm_ble_process_adv_pkt(p);
} else if (ble_sub_code == HCI_BLE_ADV_DISCARD_REPORT_EVT) {
btm_ble_process_adv_discard_evt(p);
} else {
assert (0);
}
osi_free(linked_pkt);
}
if (pkt_queue_length(p_cb->adv_rpt_queue) != 0) {
btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, NULL, OSI_THREAD_MAX_TIMEOUT);
}
UNUSED(hci_evt_code);
UNUSED(hci_evt_len);
}
/*******************************************************************************
**
** Function btm_ble_process_adv_pkt
@ -4414,6 +4450,13 @@ void btm_ble_init (void)
p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
p_cb->adv_rpt_queue = pkt_queue_create();
assert(p_cb->adv_rpt_queue != NULL);
p_cb->adv_rpt_ready = osi_event_create(btm_adv_pkt_handler, NULL);
assert(p_cb->adv_rpt_ready != NULL);
osi_event_bind(p_cb->adv_rpt_ready, btu_get_current_thread(), 0);
#if BLE_VND_INCLUDED == FALSE
btm_ble_adv_filter_init();
#endif
@ -4436,6 +4479,12 @@ void btm_ble_free (void)
fixed_queue_free(p_cb->conn_pending_q, osi_free_func);
pkt_queue_destroy(p_cb->adv_rpt_queue, NULL);
p_cb->adv_rpt_queue = NULL;
osi_event_delete(p_cb->adv_rpt_ready);
p_cb->adv_rpt_ready = NULL;
#if BTM_DYNAMIC_MEMORY == TRUE
osi_free(cmn_ble_gap_vsc_cb_ptr);
cmn_ble_gap_vsc_cb_ptr = NULL;
@ -4530,4 +4579,22 @@ BOOLEAN BTM_Ble_Authorization(BD_ADDR bd_addr, BOOLEAN authorize)
return FALSE;
}
bool btm_ble_adv_pkt_ready(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
osi_thread_post_event(p_cb->adv_rpt_ready, OSI_THREAD_MAX_TIMEOUT);
return true;
}
bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt)
{
if (pkt == NULL) {
return false;
}
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
pkt_queue_enqueue(p_cb->adv_rpt_queue, pkt);
return true;
}
#endif /* BLE_INCLUDED */

View File

@ -28,6 +28,8 @@
#include "common/bt_target.h"
#include "osi/fixed_queue.h"
#include "osi/pkt_queue.h"
#include "osi/thread.h"
#include "stack/hcidefs.h"
#include "stack/btm_ble_api.h"
#include "btm_int.h"
@ -341,6 +343,9 @@ typedef struct {
tBTM_CMPL_CB *p_scan_cmpl_cb;
TIMER_LIST_ENT scan_timer_ent;
struct pkt_queue *adv_rpt_queue;
struct osi_event *adv_rpt_ready;
/* background connection procedure cb value */
tBTM_BLE_CONN_TYPE bg_conn_type;
UINT32 scan_int;
@ -384,6 +389,8 @@ extern "C" {
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);
bool btm_ble_adv_pkt_ready(void);
bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt);
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);

View File

@ -124,8 +124,6 @@ static void btu_hcif_ssr_evt_dump (UINT8 *p, UINT16 evt_len);
#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);
@ -360,10 +358,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
switch (ble_sub_code) {
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);
case HCI_BLE_DIRECT_ADV_EVT:
// These three events are directed to another specialized processing path
HCI_TRACE_ERROR("Unexpected HCI BLE event = 0x%02x", ble_sub_code);
break;
case HCI_BLE_CONN_COMPLETE_EVT:
btu_ble_ll_conn_complete_evt(p, hci_evt_len);
@ -2015,18 +2013,6 @@ static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p)
}
#endif ///SMP_INCLUDED == TRUE
static void btu_ble_process_adv_pkt (UINT8 *p)
{
HCI_TRACE_DEBUG("btu_ble_process_adv_pkt\n");
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);

View File

@ -269,3 +269,8 @@ int get_btu_work_queue_size(void)
{
return osi_thread_queue_wait_size(btu_thread, 0);
}
osi_thread_t *btu_get_current_thread(void)
{
return btu_thread;
}

View File

@ -227,6 +227,18 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout)
case SIG_BTU_HCI_MSG:
status = osi_thread_post(btu_thread, btu_hci_msg_process, param, 0, timeout);
break;
case SIG_BTU_HCI_ADV_RPT_MSG:
#if BLE_INCLUDED == TRUE
if (param != NULL) {
btm_ble_adv_pkt_post(param);
}
btm_ble_adv_pkt_ready();
status = true;
#else
osi_free(param);
status = false;
#endif
break;
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
case SIG_BTU_BTA_MSG:
status = osi_thread_post(btu_thread, bta_sys_event, param, 0, timeout);

View File

@ -175,6 +175,7 @@ typedef enum {
SIG_BTU_GENERAL_ALARM,
SIG_BTU_ONESHOT_ALARM,
SIG_BTU_L2CAP_ALARM,
SIG_BTU_HCI_ADV_RPT_MSG,
SIG_BTU_NUM,
} SIG_BTU_t;
@ -297,6 +298,7 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout);
int get_btu_work_queue_size(void);
osi_thread_t *btu_get_current_thread(void);
/*
#ifdef __cplusplus
}