mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'feat/added_nonblocking_mode_for_hci_alloc_6.1' into 'release/v6.1'
fix(bt): fixed multiple CVE issues for Bluetooth Classic Controller See merge request espressif/esp-idf!52846
This commit is contained in:
@@ -239,6 +239,7 @@ extern int btdm_common_sched_bredr_on_sched_hw_list_done(void *param);
|
|||||||
extern int hci_tl_bredr_on_rx_cmd_c2h_num_pkt(void *param);
|
extern int hci_tl_bredr_on_rx_cmd_c2h_num_pkt(void *param);
|
||||||
extern int hci_tl_bredr_on_rx_cmd_set_c2h_flow_ctrl(void *param);
|
extern int hci_tl_bredr_on_rx_cmd_set_c2h_flow_ctrl(void *param);
|
||||||
extern int odm_afh_on_coex_wifi_channel_change(void *param);
|
extern int odm_afh_on_coex_wifi_channel_change(void *param);
|
||||||
|
extern int olc_acl_on_coex_schm_update(void *param);
|
||||||
extern int olc_intc_on_hal_exit_isr(void *param);
|
extern int olc_intc_on_hal_exit_isr(void *param);
|
||||||
extern int olc_sleep_on_sched_actual_time_get(void *param);
|
extern int olc_sleep_on_sched_actual_time_get(void *param);
|
||||||
extern int olc_sleep_on_sched_get_earlist_ticks(void *param);
|
extern int olc_sleep_on_sched_get_earlist_ticks(void *param);
|
||||||
@@ -406,11 +407,14 @@ const void * const _base_linear_broker_flash[] = BTDM_BROKER_NODE_DEF_FLASH(
|
|||||||
#endif /* UC_BT_CTRL_BLE_IS_ENABLE */
|
#endif /* UC_BT_CTRL_BLE_IS_ENABLE */
|
||||||
|
|
||||||
const void * const _btdm_coex_linear_broker_flash[] = BTDM_BROKER_NODE_DEF_FLASH(
|
const void * const _btdm_coex_linear_broker_flash[] = BTDM_BROKER_NODE_DEF_FLASH(
|
||||||
#if UC_BT_CTRL_BLE_IS_ENABLE
|
|
||||||
[1] = BTDM_BROKER_ENTRY_DEF_FLASH(
|
[1] = BTDM_BROKER_ENTRY_DEF_FLASH(
|
||||||
|
#if UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
brk_sym_coexHook_WcEp3uxRHd6HYgB0pn0L,
|
brk_sym_coexHook_WcEp3uxRHd6HYgB0pn0L,
|
||||||
),
|
|
||||||
#endif /* UC_BT_CTRL_BLE_IS_ENABLE */
|
#endif /* UC_BT_CTRL_BLE_IS_ENABLE */
|
||||||
|
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
|
||||||
|
olc_acl_on_coex_schm_update,
|
||||||
|
#endif /* UC_BT_CTRL_BR_EDR_IS_ENABLE */
|
||||||
|
),
|
||||||
[2] = BTDM_BROKER_ENTRY_DEF_FLASH(
|
[2] = BTDM_BROKER_ENTRY_DEF_FLASH(
|
||||||
#if UC_BT_CTRL_BLE_IS_ENABLE
|
#if UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
brk_sym_coexHook_wiWNhAUWlHyTZ7Z5ZC5Z,
|
brk_sym_coexHook_wiWNhAUWlHyTZ7Z5ZC5Z,
|
||||||
|
|||||||
Submodule components/bt/controller/lib_esp32h4/esp32h4-bt-lib updated: 00b5a98c1b...9358cd13cc
Submodule components/bt/controller/lib_esp32s31/esp32s31-bt-lib updated: 20e84f6ebe...849186e861
@@ -113,7 +113,7 @@
|
|||||||
#include "../../common/btdm_le.h"
|
#include "../../common/btdm_le.h"
|
||||||
#endif /* SOC_BLE_SUPPORTED */
|
#endif /* SOC_BLE_SUPPORTED */
|
||||||
|
|
||||||
#define BTDM_CONFIG_VERSION 0x20260127
|
#define BTDM_CONFIG_VERSION 0x20260911
|
||||||
#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5
|
#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5
|
||||||
|
|
||||||
/* Types definition
|
/* Types definition
|
||||||
@@ -124,15 +124,16 @@
|
|||||||
* @brief BTDM controller common configuration options
|
* @brief BTDM controller common configuration options
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version; /*!< Version number of the defined structure */
|
uint32_t version; /*!< Version number of the defined structure */
|
||||||
uint16_t task_stack_size; /*!< Size of Bluetooth controller task stack */
|
uint16_t task_stack_size; /*!< Size of Bluetooth controller task stack */
|
||||||
uint8_t task_prio; /*!< Priority of the Bluetooth controller task */
|
uint8_t task_prio; /*!< Priority of the Bluetooth controller task */
|
||||||
uint8_t task_run_cpu; /*!< CPU number on which the Bluetooth controller task runs */
|
uint8_t task_run_cpu; /*!< CPU number on which the Bluetooth controller task runs */
|
||||||
uint8_t hci_cmd_num; /*!< HCI command buffer number */
|
uint8_t hci_cmd_num; /*!< HCI command buffer number */
|
||||||
uint8_t sleep_en; /*!< Enable sleep functionality */
|
uint8_t nonblocking_cmd_buf; /*!< Non-blocking mode for command buffer allocation */
|
||||||
uint8_t version_num; /*!< Hardware version number of this chip */
|
uint8_t sleep_en; /*!< Enable sleep functionality */
|
||||||
uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */
|
uint8_t version_num; /*!< Hardware version number of this chip */
|
||||||
uint32_t magic; /*!< Magic number for configuration validation */
|
uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */
|
||||||
|
uint32_t magic; /*!< Magic number for configuration validation */
|
||||||
} esp_bt_ctrl_btdm_config_t;
|
} esp_bt_ctrl_btdm_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,38 +158,40 @@
|
|||||||
#endif // defined(CONFIG_BTDM_CTRL_MODE_BLE_ONLY)
|
#endif // defined(CONFIG_BTDM_CTRL_MODE_BLE_ONLY)
|
||||||
|
|
||||||
#if SOC_BT_CLASSIC_SUPPORTED
|
#if SOC_BT_CLASSIC_SUPPORTED
|
||||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() \
|
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() \
|
||||||
{ \
|
{ \
|
||||||
.ble = _BT_CTRL_LE_INIT_CONFIG_DEFAULT(), \
|
.ble = _BT_CTRL_LE_INIT_CONFIG_DEFAULT(), \
|
||||||
.bredr = _BT_CTRL_BREDR_INIT_CONFIG_DEFAULT(), \
|
.bredr = _BT_CTRL_BREDR_INIT_CONFIG_DEFAULT(), \
|
||||||
.btdm = \
|
.btdm = \
|
||||||
{ \
|
{ \
|
||||||
.version = BTDM_CONFIG_VERSION, \
|
.version = BTDM_CONFIG_VERSION, \
|
||||||
.task_stack_size = UC_BT_CTRL_TASK_STACK_SIZE, \
|
.task_stack_size = UC_BT_CTRL_TASK_STACK_SIZE, \
|
||||||
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||||
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
||||||
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
||||||
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
.nonblocking_cmd_buf = UC_BT_CTRL_NONBLOCK_CMD_BUF, \
|
||||||
.version_num = 0, \
|
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
||||||
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
.version_num = 0, \
|
||||||
.magic = BTDM_CONFIG_MAGIC_VALUE, \
|
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
||||||
}, \
|
.magic = BTDM_CONFIG_MAGIC_VALUE, \
|
||||||
|
}, \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() \
|
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() \
|
||||||
{ \
|
{ \
|
||||||
.ble = _BT_CTRL_LE_INIT_CONFIG_DEFAULT(), \
|
.ble = _BT_CTRL_LE_INIT_CONFIG_DEFAULT(), \
|
||||||
.btdm = \
|
.btdm = \
|
||||||
{ \
|
{ \
|
||||||
.version = BTDM_CONFIG_VERSION, \
|
.version = BTDM_CONFIG_VERSION, \
|
||||||
.task_stack_size = UC_BT_CTRL_TASK_STACK_SIZE, \
|
.task_stack_size = UC_BT_CTRL_TASK_STACK_SIZE, \
|
||||||
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||||
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
||||||
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
||||||
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
.nonblocking_cmd_buf = UC_BT_CTRL_NONBLOCK_CMD_BUF, \
|
||||||
.version_num = 0, \
|
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
||||||
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
.version_num = 0, \
|
||||||
.magic = BTDM_CONFIG_MAGIC_VALUE, \
|
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
||||||
|
.magic = BTDM_CONFIG_MAGIC_VALUE, \
|
||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
#endif // SOC_BT_CLASSIC_SUPPORTED
|
#endif // SOC_BT_CLASSIC_SUPPORTED
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ typedef struct {
|
|||||||
#include "../../common/btdm_le.h"
|
#include "../../common/btdm_le.h"
|
||||||
#endif /* SOC_BLE_SUPPORTED */
|
#endif /* SOC_BLE_SUPPORTED */
|
||||||
|
|
||||||
#define BTDM_CONFIG_VERSION 0x20260127
|
#define BTDM_CONFIG_VERSION 0x20260911
|
||||||
#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5
|
#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5
|
||||||
|
|
||||||
/* Types definition
|
/* Types definition
|
||||||
@@ -128,6 +128,7 @@ typedef struct {
|
|||||||
uint8_t task_prio; /*!< Priority of the Bluetooth controller task */
|
uint8_t task_prio; /*!< Priority of the Bluetooth controller task */
|
||||||
uint8_t task_run_cpu; /*!< CPU number on which the Bluetooth controller task runs */
|
uint8_t task_run_cpu; /*!< CPU number on which the Bluetooth controller task runs */
|
||||||
uint8_t hci_cmd_num; /*!< HCI command buffer number */
|
uint8_t hci_cmd_num; /*!< HCI command buffer number */
|
||||||
|
uint8_t nonblocking_cmd_buf; /*!< Non-blocking mode for command buffer allocation */
|
||||||
uint8_t sleep_en; /*!< Enable sleep functionality */
|
uint8_t sleep_en; /*!< Enable sleep functionality */
|
||||||
uint8_t version_num; /*!< Hardware version number of this chip */
|
uint8_t version_num; /*!< Hardware version number of this chip */
|
||||||
uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */
|
uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */
|
||||||
@@ -167,6 +168,7 @@ typedef struct {
|
|||||||
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||||
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
||||||
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
||||||
|
.nonblocking_cmd_buf = UC_BT_CTRL_NONBLOCK_CMD_BUF, \
|
||||||
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
||||||
.version_num = 0, \
|
.version_num = 0, \
|
||||||
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
||||||
@@ -184,6 +186,7 @@ typedef struct {
|
|||||||
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
.task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||||
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
.task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \
|
||||||
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
.hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \
|
||||||
|
.nonblocking_cmd_buf = UC_BT_CTRL_NONBLOCK_CMD_BUF, \
|
||||||
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
|
||||||
.version_num = 0, \
|
.version_num = 0, \
|
||||||
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
|
||||||
|
|||||||
@@ -295,6 +295,41 @@ static int bredr_psa_gen_keypair(bool p256, uint8_t *public_key, uint8_t *privat
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CVE-2018-5383: validate the peer's public key is a valid point on the curve
|
||||||
|
* before using it in the DH computation. PSA validates the point (rejects the
|
||||||
|
* point at infinity and out-of-range coordinates) when importing it as a public key.
|
||||||
|
*/
|
||||||
|
static int bredr_psa_validate_peer_pubkey(bool p256, const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y)
|
||||||
|
{
|
||||||
|
const size_t coord_len = p256 ? BREDR_P256_COORD_LEN : BREDR_P192_COORD_LEN;
|
||||||
|
const size_t pub_len = p256 ? BREDR_PUB_KEY_LEN_P256 : BREDR_PUB_KEY_LEN_P192;
|
||||||
|
|
||||||
|
uint8_t pk[BREDR_PUB_KEY_LEN_P256]; /* uncompressed: 0x04 || X || Y */
|
||||||
|
|
||||||
|
pk[0] = 0x04;
|
||||||
|
btdm_swap_buf(&pk[1], peer_pub_key_x, coord_len);
|
||||||
|
btdm_swap_buf(&pk[1 + coord_len], peer_pub_key_y, coord_len);
|
||||||
|
|
||||||
|
psa_key_attributes_t pub_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
psa_key_id_t pub_key_id = 0;
|
||||||
|
psa_status_t pub_status;
|
||||||
|
|
||||||
|
psa_set_key_type(&pub_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
|
||||||
|
psa_set_key_bits(&pub_attr, p256 ? 256 : 192);
|
||||||
|
psa_set_key_usage_flags(&pub_attr, 0);
|
||||||
|
|
||||||
|
pub_status = psa_import_key(&pub_attr, pk, pub_len, &pub_key_id);
|
||||||
|
psa_reset_key_attributes(&pub_attr);
|
||||||
|
if (pub_status != PSA_SUCCESS) {
|
||||||
|
ESP_LOGE(TAG_BREDR_CRYPTO, "invalid peer public key: psa_import_key failed: %d", (int)pub_status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_destroy_key(pub_key_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bredr_psa_gen_dhkey(bool p256, const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y,
|
static int bredr_psa_gen_dhkey(bool p256, const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y,
|
||||||
const uint8_t *our_priv_key, uint8_t *out_dhkey)
|
const uint8_t *our_priv_key, uint8_t *out_dhkey)
|
||||||
{
|
{
|
||||||
@@ -306,11 +341,18 @@ static int bredr_psa_gen_dhkey(bool p256, const uint8_t *peer_pub_key_x, const u
|
|||||||
uint8_t pk[65];
|
uint8_t pk[65];
|
||||||
uint8_t dh[32];
|
uint8_t dh[32];
|
||||||
|
|
||||||
btdm_swap_buf(priv, our_priv_key, priv_len);
|
/* Validate the peer's public key before using it in the DH computation. */
|
||||||
|
if (bredr_psa_validate_peer_pubkey(p256, peer_pub_key_x, peer_pub_key_y) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reconstruct the peer public key in uncompressed form (0x04 || X || Y). */
|
||||||
pk[0] = 0x04;
|
pk[0] = 0x04;
|
||||||
btdm_swap_buf(&pk[1], peer_pub_key_x, coord_len);
|
btdm_swap_buf(&pk[1], peer_pub_key_x, coord_len);
|
||||||
btdm_swap_buf(&pk[1 + coord_len], peer_pub_key_y, coord_len);
|
btdm_swap_buf(&pk[1 + coord_len], peer_pub_key_y, coord_len);
|
||||||
|
|
||||||
|
btdm_swap_buf(priv, our_priv_key, priv_len);
|
||||||
|
|
||||||
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
psa_key_id_t key_id = 0;
|
psa_key_id_t key_id = 0;
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ extern "C" {
|
|||||||
|
|
||||||
#define UC_BT_CTRL_TASK_STACK_SIZE CONFIG_BT_CTRL_TASK_STACK_SIZE
|
#define UC_BT_CTRL_TASK_STACK_SIZE CONFIG_BT_CTRL_TASK_STACK_SIZE
|
||||||
|
|
||||||
|
#ifdef CONFIG_BT_CTRL_NONBLOCK_CMD_BUF
|
||||||
|
#define UC_BT_CTRL_NONBLOCK_CMD_BUF CONFIG_BT_CTRL_NONBLOCK_CMD_BUF
|
||||||
|
#else
|
||||||
|
#define UC_BT_CTRL_NONBLOCK_CMD_BUF (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART
|
#ifdef CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART
|
||||||
#define UC_HCI_UART_EN CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART
|
#define UC_HCI_UART_EN CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -133,4 +133,12 @@ menu "Bluetooth controller HCI"
|
|||||||
Deprecated: this option is no longer used after HCI UART DMA
|
Deprecated: this option is no longer used after HCI UART DMA
|
||||||
switched to UHCI driver APIs, and will be removed in a future release.
|
switched to UHCI driver APIs, and will be removed in a future release.
|
||||||
|
|
||||||
|
config BT_CTRL_NONBLOCK_CMD_BUF
|
||||||
|
bool "Return NULL when no HCI command buffer is available instead of blocking"
|
||||||
|
default y if BT_CTRL_UART_HCI_DMA_MODE || BT_NIMBLE_ENABLED
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
By default, the API will block if no HCI command buffer is available.
|
||||||
|
It is recommended to enable this option when HCI Tx and Rx processing run within the same task.
|
||||||
|
Otherwise, the task may deadlock.
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@@ -45,6 +45,14 @@
|
|||||||
#define HCI_H4_SM_W4_HEADER 1
|
#define HCI_H4_SM_W4_HEADER 1
|
||||||
#define HCI_H4_SM_W4_PAYLOAD 2
|
#define HCI_H4_SM_W4_PAYLOAD 2
|
||||||
#define HCI_H4_SM_COMPLETED 3
|
#define HCI_H4_SM_COMPLETED 3
|
||||||
|
#define HCI_H4_SM_WAIT_RESET 4
|
||||||
|
|
||||||
|
/* Buffer allocation failed. The stream is still in sync, so the state machine
|
||||||
|
* is kept as is and the allocation is retried on the next pass.
|
||||||
|
*/
|
||||||
|
#define HCI_H4_ERR_MEM (-1)
|
||||||
|
/* The stream cannot be parsed anymore, the current packet has to be dropped. */
|
||||||
|
#define HCI_H4_ERR_SYNC_LOSS (-2)
|
||||||
|
|
||||||
#define TAG "HCI_H4"
|
#define TAG "HCI_H4"
|
||||||
|
|
||||||
@@ -78,7 +86,7 @@ hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type)
|
|||||||
#endif // (!CONFIG_BT_CONTROLLER_ENABLED)
|
#endif // (!CONFIG_BT_CONTROLLER_ENABLED)
|
||||||
default:
|
default:
|
||||||
/* !TODO: Sync loss. Need to wait for reset. */
|
/* !TODO: Sync loss. Need to wait for reset. */
|
||||||
return -1;
|
return HCI_H4_ERR_SYNC_LOSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -129,7 +137,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib)
|
|||||||
HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->cmd, 0, 0);
|
HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->cmd, 0, 0);
|
||||||
h4sm->pkt = h4sm->allocs->cmd();
|
h4sm->pkt = h4sm->allocs->cmd();
|
||||||
if (!h4sm->pkt) {
|
if (!h4sm->pkt) {
|
||||||
return -1;
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len);
|
memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len);
|
||||||
@@ -143,7 +151,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib)
|
|||||||
h4sm->exp_len = btdm_get_le16(&h4sm->hdr[2]) + 4;
|
h4sm->exp_len = btdm_get_le16(&h4sm->hdr[2]) + 4;
|
||||||
h4sm->pkt = h4sm->allocs->bredr_acl(conn_handle);
|
h4sm->pkt = h4sm->allocs->bredr_acl(conn_handle);
|
||||||
if (!h4sm->pkt) {
|
if (!h4sm->pkt) {
|
||||||
return -1;
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len);
|
memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len);
|
||||||
break;
|
break;
|
||||||
@@ -153,17 +161,20 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib)
|
|||||||
if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) {
|
if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) {
|
||||||
h4sm->om = h4sm->allocs->acl();
|
h4sm->om = h4sm->allocs->acl();
|
||||||
if (!h4sm->om) {
|
if (!h4sm->om) {
|
||||||
return -1;
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ble_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len)) {
|
if (ble_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len)) {
|
||||||
return -1;
|
/* Release the mbuf so that the retry starts from a clean state. */
|
||||||
|
h4sm->frees->acl(h4sm->om);
|
||||||
|
h4sm->om = NULL;
|
||||||
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
h4sm->exp_len = btdm_get_le16(&h4sm->hdr[2]) + 4;
|
h4sm->exp_len = btdm_get_le16(&h4sm->hdr[2]) + 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif // UC_BT_CTRL_BLE_IS_ENABLE
|
#endif // UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
return -1;
|
return HCI_H4_ERR_SYNC_LOSS;
|
||||||
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
|
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
|
||||||
case HCI_H4_SYNC:
|
case HCI_H4_SYNC:
|
||||||
conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK;
|
conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK;
|
||||||
@@ -214,7 +225,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib)
|
|||||||
} else {
|
} else {
|
||||||
h4sm->buf = h4sm->allocs->evt(0);
|
h4sm->buf = h4sm->allocs->evt(0);
|
||||||
if (!h4sm->buf) {
|
if (!h4sm->buf) {
|
||||||
return -1;
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,14 +241,14 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib)
|
|||||||
h4sm->exp_len = (btdm_get_le16(&h4sm->hdr[2]) & 0x3fff) + 4;
|
h4sm->exp_len = (btdm_get_le16(&h4sm->hdr[2]) & 0x3fff) + 4;
|
||||||
h4sm->buf = h4sm->allocs->iso(h4sm->exp_len);
|
h4sm->buf = h4sm->allocs->iso(h4sm->exp_len);
|
||||||
if (!h4sm->buf) {
|
if (!h4sm->buf) {
|
||||||
return -1;
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(h4sm->buf, h4sm->hdr, h4sm->len);
|
memcpy(h4sm->buf, h4sm->hdr, h4sm->len);
|
||||||
break;
|
break;
|
||||||
#endif // CONFIG_BT_LE_ISO_SUPPORT
|
#endif // CONFIG_BT_LE_ISO_SUPPORT
|
||||||
default:
|
default:
|
||||||
return -2;
|
return HCI_H4_ERR_SYNC_LOSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -288,13 +299,13 @@ hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm,
|
|||||||
len = BLE_MBUF_PKTLEN(h4sm->om) - mbuf_len;
|
len = BLE_MBUF_PKTLEN(h4sm->om) - mbuf_len;
|
||||||
h4sm->len += len;
|
h4sm->len += len;
|
||||||
hci_h4_ib_consume(ib, len);
|
hci_h4_ib_consume(ib, len);
|
||||||
return -1;
|
return HCI_H4_ERR_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // UC_BT_CTRL_BLE_IS_ENABLE
|
#endif // UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -2;
|
return HCI_H4_ERR_SYNC_LOSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4sm->len += len;
|
h4sm->len += len;
|
||||||
@@ -389,6 +400,67 @@ hci_h4_sm_completed(struct hci_h4_sm *h4sm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* H4 type + HCI Reset (opcode 0x0C03, plen 0). */
|
||||||
|
static const uint8_t s_hci_h4_reset_pattern[] = {HCI_H4_CMD, 0x03, 0x0C, 0x00};
|
||||||
|
|
||||||
|
static int
|
||||||
|
hci_h4_sm_dispatch_reset_cmd(struct hci_h4_sm *h4sm)
|
||||||
|
{
|
||||||
|
HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->cmd, 0, 0);
|
||||||
|
h4sm->pkt_type = HCI_H4_CMD;
|
||||||
|
h4sm->pkt = h4sm->allocs->cmd();
|
||||||
|
if (!h4sm->pkt) {
|
||||||
|
return HCI_H4_ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(h4sm->pkt->data, &s_hci_h4_reset_pattern[1], 3);
|
||||||
|
h4sm->len = 3;
|
||||||
|
hci_h4_sm_completed(h4sm);
|
||||||
|
h4sm->reset_match_idx = 0;
|
||||||
|
h4sm->state = HCI_H4_SM_W4_PKT_TYPE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hci_h4_sm_wait_for_reset(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Pattern already fully matched; retry delivery after a previous OOM. */
|
||||||
|
if (h4sm->reset_match_idx == sizeof(s_hci_h4_reset_pattern)) {
|
||||||
|
return hci_h4_sm_dispatch_reset_cmd(h4sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < ib->len; i++) {
|
||||||
|
if (ib->buf[i] == s_hci_h4_reset_pattern[h4sm->reset_match_idx]) {
|
||||||
|
h4sm->reset_match_idx++;
|
||||||
|
} else {
|
||||||
|
if (ib->buf[i] == s_hci_h4_reset_pattern[0]) {
|
||||||
|
h4sm->reset_match_idx = 1;
|
||||||
|
} else {
|
||||||
|
h4sm->reset_match_idx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (h4sm->reset_match_idx == sizeof(s_hci_h4_reset_pattern)) {
|
||||||
|
hci_h4_ib_consume(ib, i + 1);
|
||||||
|
rc = hci_h4_sm_dispatch_reset_cmd(h4sm);
|
||||||
|
if (rc == HCI_H4_ERR_MEM) {
|
||||||
|
/* Reset bytes are already consumed; keep idx at 4 and retry alloc. */
|
||||||
|
h4sm->state = HCI_H4_SM_WAIT_RESET;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h4sm->reset_match_idx) {
|
||||||
|
/* Need more data */
|
||||||
|
hci_h4_ib_consume(ib, ib->len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HCI_H4_ERR_SYNC_LOSS;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hci_h4_sm_free_buf(struct hci_h4_sm *h4sm)
|
hci_h4_sm_free_buf(struct hci_h4_sm *h4sm)
|
||||||
{
|
{
|
||||||
@@ -466,7 +538,8 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len)
|
|||||||
switch (h4sm->state) {
|
switch (h4sm->state) {
|
||||||
case HCI_H4_SM_W4_PKT_TYPE:
|
case HCI_H4_SM_W4_PKT_TYPE:
|
||||||
if (hci_h4_frame_start(h4sm, ib.buf[0]) < 0) {
|
if (hci_h4_frame_start(h4sm, ib.buf[0]) < 0) {
|
||||||
return -1;
|
rc = HCI_H4_ERR_SYNC_LOSS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hci_h4_ib_consume(&ib, 1);
|
hci_h4_ib_consume(&ib, 1);
|
||||||
@@ -492,27 +565,32 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len)
|
|||||||
hci_h4_sm_completed(h4sm);
|
hci_h4_sm_completed(h4sm);
|
||||||
h4sm->state = HCI_H4_SM_W4_PKT_TYPE;
|
h4sm->state = HCI_H4_SM_W4_PKT_TYPE;
|
||||||
break;
|
break;
|
||||||
|
case HCI_H4_SM_WAIT_RESET:
|
||||||
|
rc = hci_h4_sm_wait_for_reset(h4sm, &ib);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
rc = HCI_H4_ERR_SYNC_LOSS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc < 0) {
|
if ((rc < 0) && (rc != HCI_H4_ERR_MEM)) {
|
||||||
hci_h4_sm_free_buf(h4sm);
|
hci_h4_sm_free_buf(h4sm);
|
||||||
h4sm->state = HCI_H4_SM_W4_PKT_TYPE;
|
h4sm->reset_match_idx = 0;
|
||||||
return -1;
|
h4sm->state = HCI_H4_SM_WAIT_RESET;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate consumed bytes
|
/* Calculate consumed bytes
|
||||||
*
|
*
|
||||||
* Note: we should always consume some bytes unless there is an oom error.
|
* Note: we should always consume some bytes unless there is an oom error.
|
||||||
* It's also possible that we have an oom error but already consumed some
|
* On oom the state machine is left untouched so that the allocation is
|
||||||
* data, in such case just return success and error will be returned on next
|
* retried on the next pass, and the number of bytes actually taken from
|
||||||
* pass.
|
* `buf` is reported to let the caller resubmit the remaining data.
|
||||||
*/
|
*/
|
||||||
len = len - ib.len;
|
len = len - ib.len;
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
HCI_TRANS_ASSERT((rc < 0), rc, ib.len);
|
HCI_TRANS_ASSERT((rc == HCI_H4_ERR_MEM), rc, ib.len);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ typedef struct {
|
|||||||
uhci_transmit_buffer_info_t *tx_segments; /*!< Scratch array of UHCI TX segments for one multi-buffer transaction. */
|
uhci_transmit_buffer_info_t *tx_segments; /*!< Scratch array of UHCI TX segments for one multi-buffer transaction. */
|
||||||
volatile hci_trans_tx_state_t hci_tx_state; /*!< Only one HCI packet is in flight (tx-list entries cannot be mixed). */
|
volatile hci_trans_tx_state_t hci_tx_state; /*!< Only one HCI packet is in flight (tx-list entries cannot be mixed). */
|
||||||
volatile bool rx_copy_overflow; /*!< Set in ISR when rx_copy_ringbuf cannot accept a DMA slice. */
|
volatile bool rx_copy_overflow; /*!< Set in ISR when rx_copy_ringbuf cannot accept a DMA slice. */
|
||||||
|
uint8_t *rx_pending_item; /*!< Original xRingbufferReceive() pointer; held until H4 consumes the slice. */
|
||||||
|
uint8_t *rx_pending_data; /*!< Unparsed remainder of rx_pending_item (item + already consumed). */
|
||||||
|
size_t rx_pending_len; /*!< Bytes still to feed to hci_h4_sm_rx() from rx_pending_data. */
|
||||||
} hci_driver_uart_dma_env_t;
|
} hci_driver_uart_dma_env_t;
|
||||||
|
|
||||||
/* Max UHCI TX segments in one uhci_multi_buffer_transmit(); maps to max_transmit_buffer_count. */
|
/* Max UHCI TX segments in one uhci_multi_buffer_transmit(); maps to max_transmit_buffer_count. */
|
||||||
@@ -77,7 +80,6 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
#define HCI_UHCI_RX_DESC_MEM (UC_BT_CTRL_HCI_TRANS_RX_MEM_NUM * HCI_RX_DMA_RING_SIZE)
|
#define HCI_UHCI_RX_DESC_MEM (UC_BT_CTRL_HCI_TRANS_RX_MEM_NUM * HCI_RX_DMA_RING_SIZE)
|
||||||
#define HCI_RX_COPY_RINGBUF_SIZE HCI_RX_DMA_RING_SIZE
|
#define HCI_RX_COPY_RINGBUF_SIZE HCI_RX_DMA_RING_SIZE
|
||||||
|
|
||||||
static const char *TAG = "uart_dma";
|
static const char *TAG = "uart_dma";
|
||||||
static hci_driver_uart_dma_env_t s_hci_driver_uart_dma_env;
|
static hci_driver_uart_dma_env_t s_hci_driver_uart_dma_env;
|
||||||
static struct hci_h4_sm s_hci_driver_uart_h4_sm;
|
static struct hci_h4_sm s_hci_driver_uart_h4_sm;
|
||||||
@@ -85,6 +87,18 @@ static portMUX_TYPE s_hci_tx_state_mux = portMUX_INITIALIZER_UNLOCKED;
|
|||||||
|
|
||||||
static int hci_driver_uart_dma_tx_submit(void);
|
static int hci_driver_uart_dma_tx_submit(void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
hci_driver_uart_dma_rx_pending_clear(void)
|
||||||
|
{
|
||||||
|
if (s_hci_driver_uart_dma_env.rx_pending_item && s_hci_driver_uart_dma_env.rx_copy_ringbuf) {
|
||||||
|
vRingbufferReturnItem(s_hci_driver_uart_dma_env.rx_copy_ringbuf,
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_item);
|
||||||
|
}
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_item = NULL;
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_data = NULL;
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free the DMA ring, software RX ringbuf and TX segment scratch array.
|
* @brief Free the DMA ring, software RX ringbuf and TX segment scratch array.
|
||||||
*
|
*
|
||||||
@@ -94,6 +108,8 @@ static int hci_driver_uart_dma_tx_submit(void);
|
|||||||
static void
|
static void
|
||||||
hci_driver_uart_dma_memory_deinit(void)
|
hci_driver_uart_dma_memory_deinit(void)
|
||||||
{
|
{
|
||||||
|
hci_driver_uart_dma_rx_pending_clear();
|
||||||
|
|
||||||
if (s_hci_driver_uart_dma_env.rx_copy_ringbuf) {
|
if (s_hci_driver_uart_dma_env.rx_copy_ringbuf) {
|
||||||
vRingbufferDelete(s_hci_driver_uart_dma_env.rx_copy_ringbuf);
|
vRingbufferDelete(s_hci_driver_uart_dma_env.rx_copy_ringbuf);
|
||||||
s_hci_driver_uart_dma_env.rx_copy_ringbuf = NULL;
|
s_hci_driver_uart_dma_env.rx_copy_ringbuf = NULL;
|
||||||
@@ -423,18 +439,55 @@ hci_driver_uart_dma_h4_frame_cb(uint8_t pkt_type, void *data, int pkt_len, uint8
|
|||||||
return forward_cb(pkt_type, data, pkt_len, HCI_DRIVER_DIR_H2C, data_source);
|
return forward_cb(pkt_type, data, pkt_len, HCI_DRIVER_DIR_H2C, data_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Feed one H4 slice and either return the ringbuf item or hold the remainder.
|
||||||
|
*
|
||||||
|
* @return true if the caller may continue with the next ringbuf item.
|
||||||
|
* false if H4 consumed fewer bytes than offered (typically OOM); the
|
||||||
|
* unparsed tail is stored in rx_pending_* and must be retried
|
||||||
|
* on the next process_rx() entry.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
hci_driver_uart_dma_h4_feed(uint8_t *item, uint8_t *data, size_t item_size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "uart rx");
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(TAG, data, item_size, ESP_LOG_DEBUG);
|
||||||
|
ret = hci_h4_sm_rx(s_hci_driver_uart_dma_env.h4_sm, data, (uint16_t)item_size);
|
||||||
|
if (ret < 0) {
|
||||||
|
ESP_LOGW(TAG, "parse rx data error!\n");
|
||||||
|
#if UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
|
r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR);
|
||||||
|
#endif // #if UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
|
} else if ((size_t)ret < item_size) {
|
||||||
|
/* Keep the ringbuf item checked out so the unparsed bytes stay valid. */
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_item = item;
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_data = data + ret;
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_len = item_size - (size_t)ret;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vRingbufferReturnItem(s_hci_driver_uart_dma_env.rx_copy_ringbuf, item);
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_item = NULL;
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_data = NULL;
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_len = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Drain the software RX ringbuf into the H4 state machine.
|
* @brief Drain the software RX ringbuf into the H4 state machine.
|
||||||
*
|
*
|
||||||
* Timeout is 0: the process task is already woken by process_sem. Chunks may be
|
* Timeout is 0: the process task is already woken by process_sem. Chunks may be
|
||||||
* one DMA node or a short EOF tail; H4 concatenates them into HCI packets.
|
* one DMA node or a short EOF tail; H4 concatenates them into HCI packets.
|
||||||
|
* If H4 returns a partial consume, the remainder is retried first on the next call.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
hci_driver_uart_dma_process_rx(void)
|
hci_driver_uart_dma_process_rx(void)
|
||||||
{
|
{
|
||||||
size_t item_size;
|
size_t item_size;
|
||||||
uint8_t *rx_data;
|
uint8_t *rx_data;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (s_hci_driver_uart_dma_env.rx_copy_overflow) {
|
if (s_hci_driver_uart_dma_env.rx_copy_overflow) {
|
||||||
ESP_LOGE(TAG, "RX software ring buffer overflow, HCI stream may lose sync");
|
ESP_LOGE(TAG, "RX software ring buffer overflow, HCI stream may lose sync");
|
||||||
@@ -444,17 +497,17 @@ hci_driver_uart_dma_process_rx(void)
|
|||||||
#endif // #if UC_BT_CTRL_BLE_IS_ENABLE
|
#endif // #if UC_BT_CTRL_BLE_IS_ENABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_hci_driver_uart_dma_env.rx_pending_item) {
|
||||||
|
if (!hci_driver_uart_dma_h4_feed(s_hci_driver_uart_dma_env.rx_pending_item,
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_data,
|
||||||
|
s_hci_driver_uart_dma_env.rx_pending_len)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while ((rx_data = xRingbufferReceive(s_hci_driver_uart_dma_env.rx_copy_ringbuf, &item_size, 0)) != NULL) {
|
while ((rx_data = xRingbufferReceive(s_hci_driver_uart_dma_env.rx_copy_ringbuf, &item_size, 0)) != NULL) {
|
||||||
ESP_LOGD(TAG, "uart rx");
|
if (!hci_driver_uart_dma_h4_feed(rx_data, rx_data, item_size)) {
|
||||||
ESP_LOG_BUFFER_HEXDUMP(TAG, rx_data, item_size, ESP_LOG_DEBUG);
|
return;
|
||||||
ret = hci_h4_sm_rx(s_hci_driver_uart_dma_env.h4_sm, rx_data, (uint16_t)item_size);
|
|
||||||
/* Return the item before parsing the next slice so the ringbuf can accept more ISR copies. */
|
|
||||||
vRingbufferReturnItem(s_hci_driver_uart_dma_env.rx_copy_ringbuf, rx_data);
|
|
||||||
if (ret < 0) {
|
|
||||||
ESP_LOGW(TAG, "parse rx data error!\n");
|
|
||||||
#if UC_BT_CTRL_BLE_IS_ENABLE
|
|
||||||
r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR);
|
|
||||||
#endif // #if UC_BT_CTRL_BLE_IS_ENABLE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ struct hci_h4_sm {
|
|||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint8_t pkt_type;
|
uint8_t pkt_type;
|
||||||
uint8_t min_len;
|
uint8_t min_len;
|
||||||
|
uint8_t reset_match_idx;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint16_t exp_len;
|
uint16_t exp_len;
|
||||||
uint8_t hdr[4];
|
uint8_t hdr[4];
|
||||||
@@ -115,6 +116,17 @@ void hci_h4_sm_init(struct hci_h4_sm *h4sm,
|
|||||||
const struct hci_h4_frees *frees,
|
const struct hci_h4_frees *frees,
|
||||||
hci_h4_frame_cb *frame_cb);
|
hci_h4_frame_cb *frame_cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Feed received H4 data into the parser state machine.
|
||||||
|
*
|
||||||
|
* @return Number of bytes of `buf` that have been parsed, which may be less
|
||||||
|
* than `len` (0 included) when a buffer allocation failed. The
|
||||||
|
* unparsed data has to be submitted again, the allocation is retried
|
||||||
|
* on the next call.
|
||||||
|
* A negative value means the stream cannot be parsed anymore and the
|
||||||
|
* current packet has been dropped, the caller should report a sync
|
||||||
|
* loss.
|
||||||
|
*/
|
||||||
int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len);
|
int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len);
|
||||||
|
|
||||||
#endif /* _HCI_H4_H_ */
|
#endif /* _HCI_H4_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user