mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +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)
|
static void dispatch_reassembled(BT_HDR *packet)
|
||||||
{
|
{
|
||||||
// Events should already have been dispatched before this point
|
// Events should already have been dispatched before this point
|
||||||
//Tell Up-layer received packet.
|
// Tell Up-layer received packet.
|
||||||
if (btu_task_post(SIG_BTU_HCI_MSG, packet, OSI_THREAD_MAX_TIMEOUT) == false) {
|
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);
|
osi_free(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,6 +206,10 @@ bool BTU_StartUp(void)
|
|||||||
goto error_exit;
|
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) {
|
if (btu_task_post(SIG_BTU_START_UP, NULL, OSI_THREAD_MAX_TIMEOUT) == false) {
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
@@ -229,10 +233,19 @@ error_exit:;
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void BTU_ShutDown(void)
|
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
|
#if BTU_DYNAMIC_MEMORY
|
||||||
FREE_AND_RESET(btu_cb_ptr);
|
FREE_AND_RESET(btu_cb_ptr);
|
||||||
#endif
|
#endif
|
||||||
btu_task_shut_down();
|
|
||||||
|
|
||||||
hash_map_free(btu_general_alarm_hash_map);
|
hash_map_free(btu_general_alarm_hash_map);
|
||||||
osi_mutex_free(&btu_general_alarm_lock);
|
osi_mutex_free(&btu_general_alarm_lock);
|
||||||
@@ -243,11 +256,6 @@ void BTU_ShutDown(void)
|
|||||||
hash_map_free(btu_l2cap_alarm_hash_map);
|
hash_map_free(btu_l2cap_alarm_hash_map);
|
||||||
osi_mutex_free(&btu_l2cap_alarm_lock);
|
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_general_alarm_hash_map = NULL;
|
||||||
btu_oneshot_alarm_hash_map = NULL;
|
btu_oneshot_alarm_hash_map = NULL;
|
||||||
btu_l2cap_alarm_hash_map = NULL;
|
btu_l2cap_alarm_hash_map = NULL;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "btm_int.h"
|
#include "btm_int.h"
|
||||||
#include "stack/btu.h"
|
#include "stack/btu.h"
|
||||||
#include "osi/hash_map.h"
|
#include "osi/hash_map.h"
|
||||||
|
#include "osi/pkt_queue.h"
|
||||||
#include "stack/hcimsgs.h"
|
#include "stack/hcimsgs.h"
|
||||||
#include "l2c_int.h"
|
#include "l2c_int.h"
|
||||||
#include "osi/osi.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_l2cap_alarm_process(void *param);
|
||||||
static void btu_general_alarm_process(void *param);
|
static void btu_general_alarm_process(void *param);
|
||||||
static void btu_hci_msg_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)
|
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
|
||||||
static void btu_bta_alarm_process(void *param);
|
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)
|
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
|
||||||
static void btu_bta_alarm_process(void *param)
|
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;
|
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)
|
void btu_task_start_up(void *param)
|
||||||
{
|
{
|
||||||
UNUSED(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_TIMER (2) /* max # timer callbacks which may register */
|
||||||
#define BTU_MAX_REG_EVENT (6) /* max # event callbacks which may register */
|
#define BTU_MAX_REG_EVENT (6) /* max # event callbacks which may register */
|
||||||
#define BTU_DEFAULT_DATA_SIZE (0x2a0)
|
#define BTU_DEFAULT_DATA_SIZE (0x2a0)
|
||||||
|
#define BTU_ACL_QUEUE_BATCH_SIZE (12)
|
||||||
|
#define BTU_ACL_QUEUE_HIGH_WATERMARK (100)
|
||||||
|
|
||||||
#if (BLE_INCLUDED == TRUE)
|
#if (BLE_INCLUDED == TRUE)
|
||||||
#define BTU_DEFAULT_BLE_DATA_SIZE (27)
|
#define BTU_DEFAULT_BLE_DATA_SIZE (27)
|
||||||
@@ -234,6 +236,9 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
tBTU_TIMER_REG timer_reg[BTU_MAX_REG_TIMER];
|
tBTU_TIMER_REG timer_reg[BTU_MAX_REG_TIMER];
|
||||||
tBTU_EVENT_REG event_reg[BTU_MAX_REG_EVENT];
|
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 */
|
BOOLEAN reset_complete; /* TRUE after first ack from device received */
|
||||||
UINT8 trace_level; /* Trace level for HCI layer */
|
UINT8 trace_level; /* Trace level for HCI layer */
|
||||||
@@ -303,6 +308,10 @@ void btu_task_shut_down(void);
|
|||||||
UINT16 BTU_BleAclPktSize(void);
|
UINT16 BTU_BleAclPktSize(void);
|
||||||
|
|
||||||
bool btu_task_post(uint32_t sig, void *param, uint32_t timeout);
|
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);
|
int get_btu_work_queue_size(void);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user