mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
component/bt: allocate and use one static buffer for HCI adv flow control command
This commit is contained in:
parent
aaf1d3909d
commit
6c0c837378
@ -72,6 +72,8 @@ typedef struct {
|
||||
osi_alarm_t *adv_flow_monitor;
|
||||
int adv_credits;
|
||||
int adv_credits_to_release;
|
||||
pkt_linked_item_t *adv_fc_cmd_buf;
|
||||
bool cmd_buf_in_use;
|
||||
#endif
|
||||
hci_hal_callbacks_t *callbacks;
|
||||
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)
|
||||
static void hci_adv_flow_monitor(void *context);
|
||||
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt);
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
#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_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_to_release = 0;
|
||||
hci_hal_env.cmd_buf_in_use = false;
|
||||
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);
|
||||
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;
|
||||
|
||||
#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_free(hci_hal_env.adv_flow_monitor);
|
||||
hci_hal_env.adv_flow_monitor = NULL;
|
||||
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
|
||||
|
||||
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;
|
||||
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_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;
|
||||
}
|
||||
|
||||
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 credits_released = 0;
|
||||
if (hci_adv_credits_prep_to_release(num) >= HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE) {
|
||||
credits_released = hci_adv_credits_release();
|
||||
assert(credits_released >= 0);
|
||||
if (credits_released > 0) {
|
||||
// TODO: handle the exception that the command is discarded due to heap exhaustion
|
||||
btsnd_hcic_ble_update_adv_report_flow_control(credits_released);
|
||||
if (!hci_adv_flow_try_send_command(credits_released)) {
|
||||
hci_adv_credits_release_rollback(credits_released);
|
||||
}
|
||||
} else {
|
||||
assert (credits_released == 0);
|
||||
}
|
||||
}
|
||||
return credits_released;
|
||||
@ -338,8 +396,9 @@ int hci_adv_credits_force_release(uint16_t num)
|
||||
hci_adv_credits_prep_to_release(num);
|
||||
int credits_released = hci_adv_credits_release();
|
||||
if (credits_released > 0) {
|
||||
// TODO: handle the exception that the command is discarded due to heap exhaustion
|
||||
btsnd_hcic_ble_update_adv_report_flow_control(credits_released);
|
||||
if (!hci_adv_flow_try_send_command(credits_released)) {
|
||||
hci_adv_credits_release_rollback(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);
|
||||
|
||||
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
|
||||
// in case the upper layer didn't already
|
||||
command->event = MSG_STACK_TO_HC_HCI_CMD;
|
||||
|
||||
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode);
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
@ -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;
|
||||
|
||||
wait_entry = fixed_pkt_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
@ -49,6 +49,8 @@
|
||||
#define LOCAL_BR_EDR_CONTROLLER_ID 0
|
||||
|
||||
#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 /////
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
UINT8 *pp;
|
||||
|
||||
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)) == NULL) {
|
||||
return (FALSE);
|
||||
if (static_buf != NULL) {
|
||||
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);
|
||||
|
||||
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL;
|
||||
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);
|
||||
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL);
|
||||
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,
|
||||
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)
|
||||
BOOLEAN btsnd_hcic_ble_read_phy(UINT16 conn_handle);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user