mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
component/bt: allocate and use one static buffer for HCI adv flow control command
This commit is contained in:
@@ -72,6 +72,8 @@ typedef struct {
|
|||||||
osi_alarm_t *adv_flow_monitor;
|
osi_alarm_t *adv_flow_monitor;
|
||||||
int adv_credits;
|
int adv_credits;
|
||||||
int adv_credits_to_release;
|
int adv_credits_to_release;
|
||||||
|
pkt_linked_item_t *adv_fc_cmd_buf;
|
||||||
|
bool cmd_buf_in_use;
|
||||||
#endif
|
#endif
|
||||||
hci_hal_callbacks_t *callbacks;
|
hci_hal_callbacks_t *callbacks;
|
||||||
osi_thread_t *hci_h4_thread;
|
osi_thread_t *hci_h4_thread;
|
||||||
@@ -92,6 +94,7 @@ static bool hci_upstream_data_post(uint32_t timeout);
|
|||||||
|
|
||||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
static void hci_adv_flow_monitor(void *context);
|
static void hci_adv_flow_monitor(void *context);
|
||||||
|
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thread_t *task_thread)
|
static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thread_t *task_thread)
|
||||||
@@ -103,10 +106,13 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr
|
|||||||
hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks;
|
hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks;
|
||||||
|
|
||||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
hci_hal_env.adv_fc_cmd_buf = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL));
|
||||||
|
assert(hci_hal_env.adv_fc_cmd_buf != NULL);
|
||||||
osi_mutex_new(&hci_hal_env.adv_flow_lock);
|
osi_mutex_new(&hci_hal_env.adv_flow_lock);
|
||||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
hci_hal_env.adv_credits = BLE_ADV_REPORT_FLOW_CONTROL_NUM;
|
hci_hal_env.adv_credits = BLE_ADV_REPORT_FLOW_CONTROL_NUM;
|
||||||
hci_hal_env.adv_credits_to_release = 0;
|
hci_hal_env.adv_credits_to_release = 0;
|
||||||
|
hci_hal_env.cmd_buf_in_use = false;
|
||||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||||
hci_hal_env.adv_flow_monitor = osi_alarm_new("adv_fc_mon", hci_adv_flow_monitor, NULL, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
|
hci_hal_env.adv_flow_monitor = osi_alarm_new("adv_fc_mon", hci_adv_flow_monitor, NULL, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
|
||||||
assert (hci_hal_env.adv_flow_monitor != NULL);
|
assert (hci_hal_env.adv_flow_monitor != NULL);
|
||||||
@@ -138,10 +144,13 @@ static void hci_hal_env_deinit(void)
|
|||||||
hci_hal_env.upstream_data_ready = NULL;
|
hci_hal_env.upstream_data_ready = NULL;
|
||||||
|
|
||||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||||
|
hci_hal_env.cmd_buf_in_use = true;
|
||||||
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
||||||
osi_alarm_free(hci_hal_env.adv_flow_monitor);
|
osi_alarm_free(hci_hal_env.adv_flow_monitor);
|
||||||
hci_hal_env.adv_flow_monitor = NULL;
|
hci_hal_env.adv_flow_monitor = NULL;
|
||||||
osi_mutex_free(&hci_hal_env.adv_flow_lock);
|
osi_mutex_free(&hci_hal_env.adv_flow_lock);
|
||||||
|
osi_free(hci_hal_env.adv_fc_cmd_buf);
|
||||||
|
hci_hal_env.adv_fc_cmd_buf = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hci_hal_env.hci_h4_thread = NULL;
|
hci_hal_env.hci_h4_thread = NULL;
|
||||||
@@ -296,7 +305,7 @@ int hci_adv_credits_prep_to_release(uint16_t num)
|
|||||||
hci_hal_env.adv_credits_to_release = credits_to_release;
|
hci_hal_env.adv_credits_to_release = credits_to_release;
|
||||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||||
|
|
||||||
if (credits_to_release == num) {
|
if (credits_to_release == num && num != 0) {
|
||||||
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
||||||
osi_alarm_set(hci_hal_env.adv_flow_monitor, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
|
osi_alarm_set(hci_hal_env.adv_flow_monitor, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
|
||||||
}
|
}
|
||||||
@@ -319,15 +328,64 @@ static int hci_adv_credits_release(void)
|
|||||||
return credits_released;
|
return credits_released;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hci_adv_credits_release_rollback(uint16_t num)
|
||||||
|
{
|
||||||
|
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
|
hci_hal_env.adv_credits -= num;
|
||||||
|
hci_hal_env.adv_credits_to_release += num;
|
||||||
|
assert(hci_hal_env.adv_credits >=0);
|
||||||
|
assert(hci_hal_env.adv_credits_to_release <= BLE_ADV_REPORT_FLOW_CONTROL_NUM);
|
||||||
|
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt)
|
||||||
|
{
|
||||||
|
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
|
hci_hal_env.cmd_buf_in_use = false;
|
||||||
|
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||||
|
hci_adv_credits_try_release(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hci_adv_flow_try_send_command(uint16_t credits_released)
|
||||||
|
{
|
||||||
|
bool sent = false;
|
||||||
|
bool use_static_buffer = false;
|
||||||
|
|
||||||
|
/* first try using static buffer, then dynamic buffer */
|
||||||
|
if (!hci_hal_env.cmd_buf_in_use) {
|
||||||
|
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
|
if (!hci_hal_env.cmd_buf_in_use) {
|
||||||
|
hci_hal_env.cmd_buf_in_use = true;
|
||||||
|
use_static_buffer = true;
|
||||||
|
}
|
||||||
|
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_static_buffer) {
|
||||||
|
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(hci_hal_env.adv_fc_cmd_buf->data);
|
||||||
|
BT_HDR *static_buffer = &metadata->command;
|
||||||
|
metadata->command_free_cb = hci_adv_flow_cmd_free_cb;
|
||||||
|
sent = btsnd_hcic_ble_update_adv_report_flow_control(credits_released, static_buffer);
|
||||||
|
} else {
|
||||||
|
sent = btsnd_hcic_ble_update_adv_report_flow_control(credits_released, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
int hci_adv_credits_try_release(uint16_t num)
|
int hci_adv_credits_try_release(uint16_t num)
|
||||||
{
|
{
|
||||||
int credits_released = 0;
|
int credits_released = 0;
|
||||||
if (hci_adv_credits_prep_to_release(num) >= HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE) {
|
if (hci_adv_credits_prep_to_release(num) >= HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE) {
|
||||||
credits_released = hci_adv_credits_release();
|
credits_released = hci_adv_credits_release();
|
||||||
assert(credits_released >= 0);
|
|
||||||
if (credits_released > 0) {
|
if (credits_released > 0) {
|
||||||
// TODO: handle the exception that the command is discarded due to heap exhaustion
|
if (!hci_adv_flow_try_send_command(credits_released)) {
|
||||||
btsnd_hcic_ble_update_adv_report_flow_control(credits_released);
|
hci_adv_credits_release_rollback(credits_released);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert (credits_released == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return credits_released;
|
return credits_released;
|
||||||
@@ -338,8 +396,9 @@ int hci_adv_credits_force_release(uint16_t num)
|
|||||||
hci_adv_credits_prep_to_release(num);
|
hci_adv_credits_prep_to_release(num);
|
||||||
int credits_released = hci_adv_credits_release();
|
int credits_released = hci_adv_credits_release();
|
||||||
if (credits_released > 0) {
|
if (credits_released > 0) {
|
||||||
// TODO: handle the exception that the command is discarded due to heap exhaustion
|
if (!hci_adv_flow_try_send_command(credits_released)) {
|
||||||
btsnd_hcic_ble_update_adv_report_flow_control(credits_released);
|
hci_adv_credits_release_rollback(credits_released);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return credits_released;
|
return credits_released;
|
||||||
|
@@ -242,9 +242,12 @@ static void transmit_command(
|
|||||||
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
||||||
|
|
||||||
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||||
|
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_QUEUED;
|
||||||
|
|
||||||
// Store the command message type in the event field
|
// Store the command message type in the event field
|
||||||
// in case the upper layer didn't already
|
// in case the upper layer didn't already
|
||||||
command->event = MSG_STACK_TO_HC_HCI_CMD;
|
command->event = MSG_STACK_TO_HC_HCI_CMD;
|
||||||
|
|
||||||
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode);
|
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode);
|
||||||
BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);
|
BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);
|
||||||
|
|
||||||
@@ -259,7 +262,7 @@ static future_t *transmit_command_futured(BT_HDR *command)
|
|||||||
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
||||||
|
|
||||||
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||||
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_FUTURE;
|
metadata->flags_vnd |= (HCI_CMD_MSG_F_VND_QUEUED | HCI_CMD_MSG_F_VND_FUTURE);
|
||||||
|
|
||||||
future_t *future = future_new();
|
future_t *future = future_new();
|
||||||
|
|
||||||
@@ -294,8 +297,10 @@ static void event_command_ready(fixed_pkt_queue_t *queue)
|
|||||||
command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
|
command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
|
||||||
|
|
||||||
wait_entry = fixed_pkt_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
|
wait_entry = fixed_pkt_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||||
|
|
||||||
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
||||||
|
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_SENT;
|
||||||
|
metadata->flags_vnd &= ~HCI_CMD_MSG_F_VND_QUEUED;
|
||||||
|
|
||||||
if (metadata->flags_src & HCI_CMD_MSG_F_SRC_NOACK) {
|
if (metadata->flags_src & HCI_CMD_MSG_F_SRC_NOACK) {
|
||||||
packet_fragmenter->fragment_and_dispatch(&metadata->command);
|
packet_fragmenter->fragment_and_dispatch(&metadata->command);
|
||||||
hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func;
|
hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func;
|
||||||
|
@@ -49,6 +49,8 @@
|
|||||||
#define LOCAL_BR_EDR_CONTROLLER_ID 0
|
#define LOCAL_BR_EDR_CONTROLLER_ID 0
|
||||||
|
|
||||||
#define HCI_CMD_MSG_F_VND_FUTURE (0x01)
|
#define HCI_CMD_MSG_F_VND_FUTURE (0x01)
|
||||||
|
#define HCI_CMD_MSG_F_VND_QUEUED (0x02)
|
||||||
|
#define HCI_CMD_MSG_F_VND_SENT (0x04)
|
||||||
///// END LEGACY DEFINITIONS /////
|
///// END LEGACY DEFINITIONS /////
|
||||||
|
|
||||||
typedef struct hci_hal_t hci_hal_t;
|
typedef struct hci_hal_t hci_hal_t;
|
||||||
|
@@ -1028,23 +1028,31 @@ BOOLEAN btsnd_hcic_ble_set_data_length(UINT16 conn_handle, UINT16 tx_octets, UIN
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num)
|
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num, BT_HDR *static_buf)
|
||||||
{
|
{
|
||||||
BT_HDR *p;
|
BT_HDR *p;
|
||||||
UINT8 *pp;
|
UINT8 *pp;
|
||||||
|
|
||||||
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)) == NULL) {
|
if (static_buf != NULL) {
|
||||||
return (FALSE);
|
p = static_buf;
|
||||||
|
} else {
|
||||||
|
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)) == NULL) {
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
|
||||||
|
metadata->flags_src = HCI_CMD_MSG_F_SRC_NOACK;
|
||||||
|
if (static_buf == p) {
|
||||||
|
assert(metadata->command_free_cb != NULL);
|
||||||
|
}
|
||||||
|
p->layer_specific = HCI_CMD_BUF_TYPE_METADATA;
|
||||||
|
|
||||||
pp = (UINT8 *)(p + 1);
|
pp = (UINT8 *)(p + 1);
|
||||||
|
|
||||||
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL;
|
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL;
|
||||||
p->offset = 0;
|
p->offset = 0;
|
||||||
|
|
||||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
|
|
||||||
metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK;
|
|
||||||
|
|
||||||
UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL);
|
UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL);
|
||||||
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL);
|
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL);
|
||||||
UINT16_TO_STREAM (pp, num);
|
UINT16_TO_STREAM (pp, num);
|
||||||
|
@@ -939,7 +939,7 @@ BOOLEAN btsnd_hcic_read_authenticated_payload_tout(UINT16 handle);
|
|||||||
BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
|
BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
|
||||||
UINT16 timeout);
|
UINT16 timeout);
|
||||||
|
|
||||||
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num);
|
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num, BT_HDR *static_buf);
|
||||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||||
BOOLEAN btsnd_hcic_ble_read_phy(UINT16 conn_handle);
|
BOOLEAN btsnd_hcic_ble_read_phy(UINT16 conn_handle);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user