mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
change(bt/bluedroid): Refactored HCI ACL datapath
This commit is contained in:
@@ -581,8 +581,23 @@ intercepted:
|
||||
static void dispatch_reassembled(BT_HDR *packet)
|
||||
{
|
||||
// Events should already have been dispatched before this point
|
||||
//Tell Up-layer received packet.
|
||||
if (btu_task_post(SIG_BTU_HCI_MSG, packet, OSI_THREAD_MAX_TIMEOUT) == false) {
|
||||
// Tell Up-layer received packet.
|
||||
do {
|
||||
if ((packet->event & BT_EVT_MASK) == BT_EVT_TO_BTU_HCI_ACL) {
|
||||
if (btu_hci_acl_data_post(packet)) {
|
||||
packet = NULL;
|
||||
}
|
||||
// TODO: Use controller to host flow control
|
||||
break;
|
||||
}
|
||||
|
||||
if (btu_task_post(SIG_BTU_HCI_MSG, packet, OSI_THREAD_MAX_TIMEOUT)) {
|
||||
packet = NULL;
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (packet != NULL) {
|
||||
osi_free(packet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +206,10 @@ bool BTU_StartUp(void)
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (!btu_acl_queue_init()) {
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (btu_task_post(SIG_BTU_START_UP, NULL, OSI_THREAD_MAX_TIMEOUT) == false) {
|
||||
goto error_exit;
|
||||
}
|
||||
@@ -229,10 +233,19 @@ error_exit:;
|
||||
******************************************************************************/
|
||||
void BTU_ShutDown(void)
|
||||
{
|
||||
btu_acl_queue_close();
|
||||
|
||||
btu_task_shut_down();
|
||||
|
||||
if (btu_thread) {
|
||||
osi_thread_free(btu_thread);
|
||||
btu_thread = NULL;
|
||||
}
|
||||
|
||||
btu_acl_queue_deinit();
|
||||
#if BTU_DYNAMIC_MEMORY
|
||||
FREE_AND_RESET(btu_cb_ptr);
|
||||
#endif
|
||||
btu_task_shut_down();
|
||||
|
||||
hash_map_free(btu_general_alarm_hash_map);
|
||||
osi_mutex_free(&btu_general_alarm_lock);
|
||||
@@ -243,11 +256,6 @@ void BTU_ShutDown(void)
|
||||
hash_map_free(btu_l2cap_alarm_hash_map);
|
||||
osi_mutex_free(&btu_l2cap_alarm_lock);
|
||||
|
||||
if (btu_thread) {
|
||||
osi_thread_free(btu_thread);
|
||||
btu_thread = NULL;
|
||||
}
|
||||
|
||||
btu_general_alarm_hash_map = NULL;
|
||||
btu_oneshot_alarm_hash_map = NULL;
|
||||
btu_l2cap_alarm_hash_map = NULL;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "btm_int.h"
|
||||
#include "stack/btu.h"
|
||||
#include "osi/hash_map.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "l2c_int.h"
|
||||
#include "osi/osi.h"
|
||||
@@ -122,6 +123,25 @@ typedef void (tUSER_TIMEOUT_FUNC) (TIMER_LIST_ENT *p_tle);
|
||||
static void btu_l2cap_alarm_process(void *param);
|
||||
static void btu_general_alarm_process(void *param);
|
||||
static void btu_hci_msg_process(void *param);
|
||||
static void btu_hci_acl_data_handler(void *param);
|
||||
static bool btu_hci_acl_data_ready(uint32_t timeout);
|
||||
static void btu_acl_pkt_linked_free(pkt_linked_item_t *linked_pkt);
|
||||
|
||||
static void btu_acl_pkt_linked_free(pkt_linked_item_t *linked_pkt)
|
||||
{
|
||||
do {
|
||||
if (linked_pkt == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
BT_HDR *packet = NULL;
|
||||
memcpy(&packet, linked_pkt->data, sizeof(packet));
|
||||
if (packet != NULL) {
|
||||
osi_free(packet);
|
||||
}
|
||||
osi_free(linked_pkt);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
|
||||
static void btu_bta_alarm_process(void *param);
|
||||
@@ -197,6 +217,57 @@ static void btu_hci_msg_process(void *param)
|
||||
|
||||
}
|
||||
|
||||
static bool btu_hci_acl_data_ready(uint32_t timeout)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
do {
|
||||
if (btu_cb.acl_closing || btu_cb.acl_data_ready == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = osi_thread_post_event(btu_cb.acl_data_ready, timeout);
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void btu_hci_acl_data_handler(void *param)
|
||||
{
|
||||
UNUSED(param);
|
||||
struct pkt_queue *acl_pkt_queue = btu_cb.acl_pkt_queue;
|
||||
if (acl_pkt_queue == NULL || btu_cb.acl_closing) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pkts_to_process = pkt_queue_length(acl_pkt_queue);
|
||||
if (pkts_to_process > BTU_ACL_QUEUE_BATCH_SIZE) {
|
||||
pkts_to_process = BTU_ACL_QUEUE_BATCH_SIZE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pkts_to_process; i++) {
|
||||
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(acl_pkt_queue);
|
||||
if (linked_pkt == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
BT_HDR *packet = NULL;
|
||||
memcpy(&packet, linked_pkt->data, sizeof(packet));
|
||||
if (packet == NULL) {
|
||||
osi_free(linked_pkt);
|
||||
continue;
|
||||
}
|
||||
l2c_rcv_acl_data(packet);
|
||||
osi_free(linked_pkt);
|
||||
}
|
||||
|
||||
size_t pending = pkt_queue_length(acl_pkt_queue);
|
||||
if (pending != 0) {
|
||||
// Re-post from BTU thread itself must stay non-blocking to avoid deadlock on a full queue.
|
||||
btu_hci_acl_data_ready(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
|
||||
static void btu_bta_alarm_process(void *param)
|
||||
{
|
||||
@@ -263,6 +334,109 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout)
|
||||
return status;
|
||||
}
|
||||
|
||||
bool btu_acl_queue_init(void)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
btu_cb.acl_closing = FALSE;
|
||||
|
||||
do {
|
||||
btu_cb.acl_pkt_queue = pkt_queue_create();
|
||||
if (btu_cb.acl_pkt_queue == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
btu_cb.acl_data_ready = osi_event_create(btu_hci_acl_data_handler, NULL);
|
||||
if (btu_cb.acl_data_ready == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!osi_event_bind(btu_cb.acl_data_ready, btu_thread, 0)) {
|
||||
break;
|
||||
}
|
||||
status = true;
|
||||
} while (0);
|
||||
|
||||
if (status == false) {
|
||||
if (btu_cb.acl_data_ready != NULL) {
|
||||
osi_event_delete(btu_cb.acl_data_ready);
|
||||
btu_cb.acl_data_ready = NULL;
|
||||
}
|
||||
|
||||
if (btu_cb.acl_pkt_queue != NULL) {
|
||||
pkt_queue_destroy(btu_cb.acl_pkt_queue, NULL);
|
||||
btu_cb.acl_pkt_queue = NULL;
|
||||
}
|
||||
|
||||
btu_cb.acl_closing = TRUE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void btu_acl_queue_close(void)
|
||||
{
|
||||
#if BTU_DYNAMIC_MEMORY == TRUE
|
||||
if (!btu_cb_ptr) {
|
||||
return;
|
||||
}
|
||||
#endif /* BTU_DYNAMIC_MEMORY == FALSE */
|
||||
|
||||
btu_cb.acl_closing = TRUE;
|
||||
|
||||
if (btu_cb.acl_data_ready != NULL) {
|
||||
osi_event_delete(btu_cb.acl_data_ready);
|
||||
btu_cb.acl_data_ready = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void btu_acl_queue_deinit(void)
|
||||
{
|
||||
#if BTU_DYNAMIC_MEMORY == TRUE
|
||||
if (!btu_cb_ptr) {
|
||||
return;
|
||||
}
|
||||
#endif /* BTU_DYNAMIC_MEMORY == FALSE */
|
||||
|
||||
btu_cb.acl_closing = TRUE;
|
||||
|
||||
if (btu_cb.acl_pkt_queue != NULL) {
|
||||
pkt_queue_destroy(btu_cb.acl_pkt_queue, btu_acl_pkt_linked_free);
|
||||
btu_cb.acl_pkt_queue = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool btu_hci_acl_data_post(BT_HDR *packet)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
do {
|
||||
if (packet == NULL || btu_cb.acl_closing || btu_cb.acl_pkt_queue == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t acl_q_len = pkt_queue_length(btu_cb.acl_pkt_queue);
|
||||
if (acl_q_len >= BTU_ACL_QUEUE_HIGH_WATERMARK) {
|
||||
HCI_TRACE_WARNING("ACL queue high watermark (len=%u)", (unsigned)acl_q_len);
|
||||
break;
|
||||
}
|
||||
|
||||
pkt_linked_item_t *linked_pkt = (pkt_linked_item_t *)osi_malloc(BT_PKT_LINKED_HDR_SIZE + sizeof(packet));
|
||||
if (linked_pkt == NULL) {
|
||||
HCI_TRACE_WARNING("ACL queue malloc pkt failed");
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(linked_pkt->data, &packet, sizeof(packet));
|
||||
pkt_queue_enqueue(btu_cb.acl_pkt_queue, linked_pkt);
|
||||
|
||||
btu_hci_acl_data_ready(OSI_THREAD_MAX_TIMEOUT);
|
||||
status = true;
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void btu_task_start_up(void *param)
|
||||
{
|
||||
UNUSED(param);
|
||||
|
||||
@@ -206,6 +206,8 @@ typedef struct {
|
||||
#define BTU_MAX_REG_TIMER (2) /* max # timer callbacks which may register */
|
||||
#define BTU_MAX_REG_EVENT (6) /* max # event callbacks which may register */
|
||||
#define BTU_DEFAULT_DATA_SIZE (0x2a0)
|
||||
#define BTU_ACL_QUEUE_BATCH_SIZE (12)
|
||||
#define BTU_ACL_QUEUE_HIGH_WATERMARK (100)
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
#define BTU_DEFAULT_BLE_DATA_SIZE (27)
|
||||
@@ -234,6 +236,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
tBTU_TIMER_REG timer_reg[BTU_MAX_REG_TIMER];
|
||||
tBTU_EVENT_REG event_reg[BTU_MAX_REG_EVENT];
|
||||
struct pkt_queue *acl_pkt_queue;
|
||||
struct osi_event *acl_data_ready;
|
||||
BOOLEAN acl_closing;
|
||||
|
||||
BOOLEAN reset_complete; /* TRUE after first ack from device received */
|
||||
UINT8 trace_level; /* Trace level for HCI layer */
|
||||
@@ -303,6 +308,10 @@ void btu_task_shut_down(void);
|
||||
UINT16 BTU_BleAclPktSize(void);
|
||||
|
||||
bool btu_task_post(uint32_t sig, void *param, uint32_t timeout);
|
||||
bool btu_acl_queue_init(void);
|
||||
void btu_acl_queue_close(void);
|
||||
void btu_acl_queue_deinit(void);
|
||||
bool btu_hci_acl_data_post(BT_HDR *packet);
|
||||
|
||||
int get_btu_work_queue_size(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user