mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'bugfix/fix_bluedroid_ai_review_bugs_20260427_v5.4' into 'release/v5.4'
Bugfix/fix bluedroid ai review bugs 20260427 (5.4) See merge request espressif/esp-idf!49539
This commit is contained in:
@@ -347,7 +347,10 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg
|
||||
|
||||
memcpy(lmsg, msg, sizeof(btc_msg_t));
|
||||
if (arg) {
|
||||
memset(lmsg->arg, 0x00, arg_len); //important, avoid arg which have no length
|
||||
/* memcpy below covers exactly arg_len bytes, which is the full size of
|
||||
* the destination buffer (it was sized as sizeof(btc_msg_t) + arg_len),
|
||||
* so a prior memset would be redundant. Deep-copy callbacks must only
|
||||
* read fields that were written by the caller-supplied arg. */
|
||||
memcpy(lmsg->arg, arg, arg_len);
|
||||
if (copy_func) {
|
||||
copy_func(lmsg, lmsg->arg, arg);
|
||||
|
||||
@@ -2315,7 +2315,11 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
|
||||
}
|
||||
break;
|
||||
case BTA_GATTC_CLOSE_EVT:
|
||||
bta_gattc_clcb_dealloc_by_conn_id(p_data->close.conn_id);
|
||||
/* CLCB lifetime is owned by BTA: bta_gattc_close() deallocates the
|
||||
* CLCB right after invoking this synchronous callback. Calling
|
||||
* bta_gattc_clcb_dealloc_by_conn_id() here would be a redundant
|
||||
* double-dealloc (currently a no-op only because of NULL checks in
|
||||
* bta_gattc_clcb_dealloc()). Keep this branch as a pure notification. */
|
||||
BT_DBG("BTA_GATTC_CLOSE_EVT");
|
||||
break;
|
||||
case BTA_GATTC_CONNECT_EVT: {
|
||||
|
||||
@@ -34,7 +34,7 @@ esp_ble_cte_cb_t esp_ble_cte_get_callback(void)
|
||||
#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
|
||||
esp_err_t esp_ble_cte_set_connectionless_trans_params(esp_ble_cte_connless_trans_params_t *cte_trans_params)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -42,7 +42,15 @@ esp_err_t esp_ble_cte_set_connectionless_trans_params(esp_ble_cte_connless_trans
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if ((cte_trans_params == NULL) || (cte_trans_params->antenna_ids == NULL)) {
|
||||
if (cte_trans_params == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
/*
|
||||
* Per Core Spec, switching_pattern_len and Antenna_IDs is ignored when no switching pattern is used
|
||||
* For AoA CTE type, the transmitter does not
|
||||
* switch antenna, so Antenna_IDs may be omitted as well.
|
||||
*/
|
||||
if ((cte_trans_params->cte_type != ESP_BLE_CTE_TYPE_AOA) && (cte_trans_params->antenna_ids == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
// The controller has performed parameter checking, and the host will no longer verify the validity of these parameters repeatedly.
|
||||
@@ -72,15 +80,24 @@ esp_err_t esp_ble_cte_set_connectionless_trans_params(esp_ble_cte_connless_trans
|
||||
arg.cte_trans_params.cte_len = cte_trans_params->cte_len;
|
||||
arg.cte_trans_params.cte_type = cte_trans_params->cte_type;
|
||||
arg.cte_trans_params.cte_count = cte_trans_params->cte_count;
|
||||
arg.cte_trans_params.switching_pattern_len = cte_trans_params->switching_pattern_len;
|
||||
arg.cte_trans_params.antenna_ids = cte_trans_params->antenna_ids;
|
||||
/* For AoA CTE type, the transmitter does not switch antenna; normalize
|
||||
* switching_pattern_len and antenna_ids so the BTC layer does not perform
|
||||
* an unnecessary deep copy of data that the controller will ignore.
|
||||
*/
|
||||
if (cte_trans_params->cte_type != ESP_BLE_CTE_TYPE_AOA) {
|
||||
arg.cte_trans_params.switching_pattern_len = cte_trans_params->switching_pattern_len;
|
||||
arg.cte_trans_params.antenna_ids = cte_trans_params->antenna_ids;
|
||||
} else {
|
||||
arg.cte_trans_params.switching_pattern_len = 0;
|
||||
arg.cte_trans_params.antenna_ids = NULL;
|
||||
}
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), btc_ble_cte_arg_deep_copy, btc_ble_cte_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_cte_set_connectionless_trans_enable(esp_ble_cte_trans_enable_params_t *cte_trans_enable)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -108,7 +125,7 @@ esp_err_t esp_ble_cte_set_connectionless_trans_enable(esp_ble_cte_trans_enable_p
|
||||
|
||||
esp_err_t esp_ble_cte_set_connectionless_iq_sampling_enable(esp_ble_cte_iq_sampling_params_t *iq_sampling_en)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -169,7 +186,7 @@ esp_err_t esp_ble_cte_set_connectionless_iq_sampling_enable(esp_ble_cte_iq_sampl
|
||||
#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE)
|
||||
esp_err_t esp_ble_cte_set_connection_receive_params(esp_ble_cte_recv_params_params_t *cte_recv_params)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -221,7 +238,7 @@ esp_err_t esp_ble_cte_set_connection_receive_params(esp_ble_cte_recv_params_para
|
||||
|
||||
esp_err_t esp_ble_cte_set_connection_transmit_params(esp_ble_cte_conn_trans_params_t *cte_conn_trans_params)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -229,9 +246,19 @@ esp_err_t esp_ble_cte_set_connection_transmit_params(esp_ble_cte_conn_trans_para
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if ((cte_conn_trans_params == NULL) || (cte_conn_trans_params->antenna_ids == NULL)) {
|
||||
if (cte_conn_trans_params == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
/*
|
||||
* Per Core Spec, switching_pattern_len and Antenna_IDs is ignored when no switching pattern is used
|
||||
* For AoA CTE type, the transmitter does not
|
||||
* switch antenna, so Antenna_IDs may be omitted as well.
|
||||
*/
|
||||
if ((cte_conn_trans_params->cte_types & (ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_1US | ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_2US)) &&
|
||||
(cte_conn_trans_params->antenna_ids == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// The controller has performed parameter checking, and the host will no longer verify the validity of these parameters repeatedly.
|
||||
#if (0)
|
||||
if ((cte_conn_trans_params->switching_pattern_len < ESP_BLE_CTE_MIN_SWITCHING_PATTERN_LENGTH) ||
|
||||
@@ -251,15 +278,25 @@ esp_err_t esp_ble_cte_set_connection_transmit_params(esp_ble_cte_conn_trans_para
|
||||
|
||||
arg.cte_conn_trans_params.conn_handle = cte_conn_trans_params->conn_handle;
|
||||
arg.cte_conn_trans_params.cte_types = cte_conn_trans_params->cte_types;
|
||||
arg.cte_conn_trans_params.switching_pattern_len = cte_conn_trans_params->switching_pattern_len;
|
||||
arg.cte_conn_trans_params.antenna_ids = cte_conn_trans_params->antenna_ids;
|
||||
/* Antenna switching is only required for AoD CTE responses; when only AoA
|
||||
* is enabled, normalize switching_pattern_len and antenna_ids so the BTC
|
||||
* layer does not perform an unnecessary deep copy of data that the
|
||||
* controller will ignore.
|
||||
*/
|
||||
if (cte_conn_trans_params->cte_types & (ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_1US | ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_2US)) {
|
||||
arg.cte_conn_trans_params.switching_pattern_len = cte_conn_trans_params->switching_pattern_len;
|
||||
arg.cte_conn_trans_params.antenna_ids = cte_conn_trans_params->antenna_ids;
|
||||
} else {
|
||||
arg.cte_conn_trans_params.switching_pattern_len = 0;
|
||||
arg.cte_conn_trans_params.antenna_ids = NULL;
|
||||
}
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), btc_ble_cte_arg_deep_copy, btc_ble_cte_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_cte_connection_cte_request_enable(esp_ble_cte_req_en_params_t *cte_conn_req_en)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -302,7 +339,7 @@ esp_err_t esp_ble_cte_connection_cte_request_enable(esp_ble_cte_req_en_params_t
|
||||
|
||||
esp_err_t esp_ble_cte_connection_cte_response_enable(esp_ble_cte_rsp_en_params_t *cte_conn_rsp_en)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
btc_ble_cte_args_t arg;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
@@ -334,7 +371,7 @@ esp_err_t esp_ble_cte_connection_cte_response_enable(esp_ble_cte_rsp_en_params_t
|
||||
|
||||
esp_err_t esp_ble_cte_read_antenna_information(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -63,7 +63,8 @@ esp_err_t esp_ble_iso_create_big(esp_ble_iso_big_creat_params_t *big_creat_param
|
||||
if (big_creat_param->rtn > 0x1E) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if ((big_creat_param->phy != 0x01) && (big_creat_param->phy != 0x02) && (big_creat_param->phy != 0x04)) {
|
||||
/* phy is a bit field: bit0=1M, bit1=2M, bit2=Coded (HCI_LE_Create_BIG, Core Spec): at least one bit. */
|
||||
if ((big_creat_param->phy == 0) || (big_creat_param->phy & ~0x07)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (big_creat_param->packing > 0x01) {
|
||||
@@ -118,7 +119,9 @@ esp_err_t esp_ble_iso_create_big_test(esp_ble_iso_big_creat_test_params_t *big_c
|
||||
if (big_creat_test_param->max_pdu < 0x0001 || big_creat_test_param->max_pdu > 0x00FB) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if ((big_creat_test_param->phy != 0x01) && (big_creat_test_param->phy != 0x02) && (big_creat_test_param->phy != 0x04)) {
|
||||
/* HCI_LE_Create_BIG_Test (Core Spec): host shall set exactly one of 1M / 2M / Coded PHY. */
|
||||
if ((big_creat_test_param->phy != 0x01) && (big_creat_test_param->phy != 0x02) &&
|
||||
(big_creat_test_param->phy != 0x04)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (big_creat_test_param->framing > BLE_ISO_FRAMING_FRAMED_PDU_UNSEGMENTABLE_MODE) {
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "btc/btc_ble_storage.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
/* Hard upper bound to prevent excessive allocations in BTC/BTA layers. */
|
||||
#define ESP_GAP_BLE_EXT_ADV_DATA_MAX_LEN 1650U
|
||||
|
||||
esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
@@ -158,7 +161,22 @@ esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params)
|
||||
ESP_BLE_IS_VALID_PARAM(params->max_int, BLE_CONN_INT_MIN_HOST_CHECK, ESP_BLE_CONN_INT_MAX) &&
|
||||
ESP_BLE_IS_VALID_PARAM(params->timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) &&
|
||||
(params->latency <= ESP_BLE_CONN_LATENCY_MAX) &&
|
||||
((params->timeout * 10) >= ((1 + params->latency) * ((params->max_int * 5) >> 1))) && params->min_int <= params->max_int) {
|
||||
/*
|
||||
* Core Spec (Vol 6, Part B, Section 4.5.2):
|
||||
* supervision_timeout shall be strictly greater than
|
||||
* (1 + connSlaveLatency) * connIntervalMax * 2.
|
||||
*
|
||||
* Here:
|
||||
* - timeout is in 10 ms units
|
||||
* - max_int is in 1.25 ms units
|
||||
*
|
||||
* Convert both sides into 0.5 ms units to avoid truncation:
|
||||
* (timeout * 10 ms) -> timeout * 20 (0.5 ms units)
|
||||
* (max_int * 1.25 ms * 2) -> max_int * 5 (0.5 ms units)
|
||||
*/
|
||||
(((uint32_t)params->timeout * 20U) >
|
||||
((uint32_t)(1U + (uint32_t)params->latency) * (uint32_t)params->max_int * 5U)) &&
|
||||
(params->min_int <= params->max_int)) {
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
@@ -339,7 +357,7 @@ esp_err_t esp_ble_gap_update_whitelist(bool add_remove, esp_bd_addr_t remote_bda
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!remote_bda){
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
@@ -369,7 +387,7 @@ esp_err_t esp_ble_gap_clear_whitelist(void)
|
||||
esp_err_t esp_ble_gap_get_whitelist_size(uint16_t *length)
|
||||
{
|
||||
if (length == NULL) {
|
||||
return ESP_FAIL;
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_get_whitelist_size(length);
|
||||
@@ -397,7 +415,9 @@ esp_err_t esp_ble_gap_set_prefer_conn_params(esp_bd_addr_t bd_addr,
|
||||
ESP_BLE_IS_VALID_PARAM(max_conn_int, BLE_CONN_INT_MIN_HOST_CHECK, ESP_BLE_CONN_INT_MAX) &&
|
||||
ESP_BLE_IS_VALID_PARAM(supervision_tout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) &&
|
||||
(slave_latency <= ESP_BLE_CONN_LATENCY_MAX) &&
|
||||
((supervision_tout * 10) >= ((1 + slave_latency) * ((max_conn_int * 5) >> 1))) && min_conn_int <= max_conn_int) {
|
||||
(((uint32_t)supervision_tout * 20U) >
|
||||
((uint32_t)(1U + (uint32_t)slave_latency) * (uint32_t)max_conn_int * 5U)) &&
|
||||
(min_conn_int <= max_conn_int)) {
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
@@ -678,7 +698,7 @@ esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param_type,
|
||||
uint32_t passkey = 0;
|
||||
for(uint8_t i = 0; i < len; i++)
|
||||
{
|
||||
passkey += (((uint8_t *)value)[i]<<(8*i));
|
||||
passkey += ((uint32_t)((const uint8_t *)value)[i] << (8U * (uint32_t)i));
|
||||
}
|
||||
if(passkey > 999999) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -846,6 +866,15 @@ esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_lis
|
||||
*dev_num = dev_num_total;
|
||||
}
|
||||
|
||||
/*
|
||||
* The storage layer updates some fields using |= (e.g. key_mask). Ensure
|
||||
* the caller-provided list is zero-initialized to avoid propagating
|
||||
* uninitialized heap contents (including padding) back to the caller.
|
||||
*/
|
||||
if (*dev_num > 0) {
|
||||
memset(dev_list, 0, sizeof(*dev_list) * (size_t)(*dev_num));
|
||||
}
|
||||
|
||||
ret = btc_storage_get_bonded_ble_devices_list(dev_list, *dev_num);
|
||||
|
||||
return (ret == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
@@ -1293,6 +1322,10 @@ esp_err_t esp_ble_gap_config_ext_adv_data_raw(uint8_t instance, uint16_t length,
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (length > ESP_GAP_BLE_EXT_ADV_DATA_MAX_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
@@ -1319,6 +1352,10 @@ esp_err_t esp_ble_gap_config_ext_scan_rsp_data_raw(uint8_t instance, uint16_t le
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (length > ESP_GAP_BLE_EXT_ADV_DATA_MAX_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW;
|
||||
@@ -1454,6 +1491,10 @@ esp_err_t esp_ble_gap_config_periodic_adv_data_raw(uint8_t instance, uint16_t le
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (length > ESP_GAP_BLE_EXT_ADV_DATA_MAX_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
@@ -1751,7 +1792,8 @@ esp_err_t esp_ble_gap_prefer_ext_connect_params_set(esp_bd_addr_t addr,
|
||||
ESP_BLE_IS_VALID_PARAM(phy_1m_conn_params->interval_max, BLE_CONN_INT_MIN_HOST_CHECK, ESP_BLE_CONN_INT_MAX) &&
|
||||
ESP_BLE_IS_VALID_PARAM(phy_1m_conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) &&
|
||||
(phy_1m_conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) &&
|
||||
((phy_1m_conn_params->supervision_timeout * 10) >= ((1 + phy_1m_conn_params->latency) * ((phy_1m_conn_params->interval_max * 5) >> 1))) &&
|
||||
(((uint32_t)phy_1m_conn_params->supervision_timeout * 20U) >
|
||||
((uint32_t)(1U + (uint32_t)phy_1m_conn_params->latency) * (uint32_t)phy_1m_conn_params->interval_max * 5U)) &&
|
||||
(phy_1m_conn_params->interval_min <= phy_1m_conn_params->interval_max)) {
|
||||
|
||||
memcpy(&arg.set_ext_conn_params.phy_1m_conn_params, phy_1m_conn_params, sizeof(esp_ble_gap_conn_params_t));
|
||||
@@ -1775,7 +1817,8 @@ esp_err_t esp_ble_gap_prefer_ext_connect_params_set(esp_bd_addr_t addr,
|
||||
ESP_BLE_IS_VALID_PARAM(phy_2m_conn_params->interval_max, BLE_CONN_INT_MIN_HOST_CHECK, ESP_BLE_CONN_INT_MAX) &&
|
||||
ESP_BLE_IS_VALID_PARAM(phy_2m_conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) &&
|
||||
(phy_2m_conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) &&
|
||||
((phy_2m_conn_params->supervision_timeout * 10) >= ((1 + phy_2m_conn_params->latency) * ((phy_2m_conn_params->interval_max * 5) >> 1))) &&
|
||||
(((uint32_t)phy_2m_conn_params->supervision_timeout * 20U) >
|
||||
((uint32_t)(1U + (uint32_t)phy_2m_conn_params->latency) * (uint32_t)phy_2m_conn_params->interval_max * 5U)) &&
|
||||
(phy_2m_conn_params->interval_min <= phy_2m_conn_params->interval_max)) {
|
||||
|
||||
memcpy(&arg.set_ext_conn_params.phy_2m_conn_params, phy_2m_conn_params, sizeof(esp_ble_gap_conn_params_t));
|
||||
@@ -1799,7 +1842,8 @@ esp_err_t esp_ble_gap_prefer_ext_connect_params_set(esp_bd_addr_t addr,
|
||||
ESP_BLE_IS_VALID_PARAM(phy_coded_conn_params->interval_max, BLE_CONN_INT_MIN_HOST_CHECK, ESP_BLE_CONN_INT_MAX) &&
|
||||
ESP_BLE_IS_VALID_PARAM(phy_coded_conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) &&
|
||||
(phy_coded_conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) &&
|
||||
((phy_coded_conn_params->supervision_timeout * 10) >= ((1 + phy_coded_conn_params->latency) * ((phy_coded_conn_params->interval_max * 5) >> 1))) &&
|
||||
(((uint32_t)phy_coded_conn_params->supervision_timeout * 20U) >
|
||||
((uint32_t)(1U + (uint32_t)phy_coded_conn_params->latency) * (uint32_t)phy_coded_conn_params->interval_max * 5U)) &&
|
||||
(phy_coded_conn_params->interval_min <= phy_coded_conn_params->interval_max)) {
|
||||
|
||||
memcpy(&arg.set_ext_conn_params.phy_coded_conn_params, phy_coded_conn_params, sizeof(esp_ble_gap_conn_params_t));
|
||||
|
||||
@@ -397,7 +397,9 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id,
|
||||
esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid,
|
||||
esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (result == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
@@ -415,14 +417,16 @@ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if,
|
||||
esp_gattc_char_elem_t *result,
|
||||
uint16_t *count, uint16_t offset)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
|
||||
if (result == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
if ((start_handle == 0) && (end_handle == 0)) {
|
||||
if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) {
|
||||
*count = 0;
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
@@ -437,7 +441,9 @@ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if,
|
||||
esp_gattc_descr_elem_t *result,
|
||||
uint16_t *count, uint16_t offset)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (char_handle == 0) {
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
@@ -459,13 +465,15 @@ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if,
|
||||
esp_gattc_char_elem_t *result,
|
||||
uint16_t *count)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (result == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
if (start_handle == 0 && end_handle == 0) {
|
||||
if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) {
|
||||
*count = 0;
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
@@ -484,12 +492,19 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if,
|
||||
esp_gattc_descr_elem_t *result,
|
||||
uint16_t *count)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (result == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) {
|
||||
*count = 0;
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
return btc_ble_gattc_get_descr_by_uuid(conn_hdl, start_handle, end_handle, char_uuid, descr_uuid, result, count);
|
||||
}
|
||||
@@ -501,7 +516,9 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if,
|
||||
esp_gattc_descr_elem_t *result,
|
||||
uint16_t *count)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (result == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
@@ -524,13 +541,15 @@ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if,
|
||||
esp_gattc_incl_svc_elem_t *result,
|
||||
uint16_t *count)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (result == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
if (start_handle == 0 && end_handle == 0) {
|
||||
if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) {
|
||||
*count = 0;
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
@@ -547,13 +566,17 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if,
|
||||
uint16_t char_handle,
|
||||
uint16_t *count)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (count == NULL) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
if ((start_handle == 0 && end_handle == 0) && (type != ESP_GATT_DB_DESCRIPTOR)) {
|
||||
/* start_handle/end_handle are ignored for ESP_GATT_DB_DESCRIPTOR (see esp_gattc_api.h). */
|
||||
if (type != ESP_GATT_DB_DESCRIPTOR &&
|
||||
((start_handle == 0 && end_handle == 0) || start_handle > end_handle)) {
|
||||
*count = 0;
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
@@ -565,14 +588,16 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if,
|
||||
esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
|
||||
esp_gattc_db_elem_t *db, uint16_t *count)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
|
||||
if (db == NULL || count == NULL || *count == 0) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
if (start_handle == 0 && end_handle == 0) {
|
||||
if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) {
|
||||
*count = 0;
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
@@ -644,10 +669,14 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if,
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (start_handle == 0 || end_handle == 0) {
|
||||
if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) {
|
||||
return ESP_GATT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (start_handle == 0) {
|
||||
start_handle = 1;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_READ_BY_TYPE;
|
||||
@@ -670,7 +699,12 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if ((read_multi == NULL) || (read_multi->num_attr == 0) || (read_multi->num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) {
|
||||
if (read_multi == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint8_t num_attr = read_multi->num_attr;
|
||||
|
||||
if ((num_attr == 0) || (num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -689,10 +723,10 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if,
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_READ_MULTIPLE_CHAR;
|
||||
arg.read_multiple.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
arg.read_multiple.num_attr = read_multi->num_attr;
|
||||
arg.read_multiple.num_attr = num_attr;
|
||||
arg.read_multiple.auth_req = auth_req;
|
||||
|
||||
memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t)*read_multi->num_attr);
|
||||
memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t) * num_attr);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
@@ -707,7 +741,12 @@ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if ((read_multi == NULL) || (read_multi->num_attr == 0) || (read_multi->num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) {
|
||||
if (read_multi == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint8_t num_attr = read_multi->num_attr;
|
||||
|
||||
if ((num_attr == 0) || (num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -726,9 +765,9 @@ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if,
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_READ_MULTIPLE_VARIABLE_CHAR;
|
||||
arg.read_multiple.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
arg.read_multiple.num_attr = read_multi->num_attr;
|
||||
arg.read_multiple.num_attr = num_attr;
|
||||
arg.read_multiple.auth_req = auth_req;
|
||||
memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t)*read_multi->num_attr);
|
||||
memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t) * num_attr);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
@@ -829,6 +868,10 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if ((value_len > 0) && (value == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
@@ -873,6 +916,10 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if ((value_len > 0) && (value == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
@@ -915,6 +962,10 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if ((value_len > 0) && (value == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -384,7 +384,9 @@ esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, co
|
||||
|
||||
esp_gatt_status_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (length == NULL || value == NULL) {
|
||||
return ESP_GATT_INVALID_PDU;
|
||||
@@ -463,20 +465,44 @@ esp_err_t esp_ble_gatts_send_service_change_indication(esp_gatt_if_t gatts_if, e
|
||||
|
||||
static esp_err_t esp_ble_gatts_add_char_desc_param_check(esp_attr_value_t *char_val, esp_attr_control_t *control)
|
||||
{
|
||||
if ((control != NULL) && ((control->auto_rsp != ESP_GATT_AUTO_RSP) && (control->auto_rsp != ESP_GATT_RSP_BY_APP))){
|
||||
LOG_ERROR("Error in %s, line=%d, control->auto_rsp should be set to ESP_GATT_AUTO_RSP or ESP_GATT_RSP_BY_APP\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
if ((control != NULL) &&
|
||||
(control->auto_rsp != ESP_GATT_AUTO_RSP) &&
|
||||
(control->auto_rsp != ESP_GATT_RSP_BY_APP)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if ((control != NULL) && (control->auto_rsp == ESP_GATT_AUTO_RSP)){
|
||||
if (char_val == NULL){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
/* Validate attribute value regardless of auto_rsp to avoid deep-copy waste and leaks. */
|
||||
if (char_val != NULL) {
|
||||
bool invalid = false;
|
||||
|
||||
if (char_val->attr_max_len > ESP_GATT_MAX_ATTR_LEN) {
|
||||
invalid = true;
|
||||
}
|
||||
if (char_val->attr_len > ESP_GATT_MAX_ATTR_LEN) {
|
||||
invalid = true;
|
||||
}
|
||||
/* Always require attr_len <= attr_max_len to avoid leaks and wasteful allocations. */
|
||||
if (char_val->attr_len > char_val->attr_max_len) {
|
||||
invalid = true;
|
||||
}
|
||||
|
||||
if (invalid) {
|
||||
LOG_ERROR("%s bad attr len=%u/%u lim=%u",
|
||||
__func__,
|
||||
(unsigned)char_val->attr_len,
|
||||
(unsigned)char_val->attr_max_len,
|
||||
(unsigned)ESP_GATT_MAX_ATTR_LEN);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else if (char_val->attr_max_len == 0){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
if ((control != NULL) && (control->auto_rsp == ESP_GATT_AUTO_RSP)) {
|
||||
if (char_val == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* For stack auto response, attr_max_len must be non-zero. */
|
||||
if (char_val->attr_max_len == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ typedef enum {
|
||||
#define BLE_ISO_WORST_CASE_SCA_LEVEL_20_PPM (0x07)
|
||||
|
||||
#define BLE_ISO_PACKING_SEQUENTIAL (0x00)
|
||||
#define BLE_ISO_PACKING_INTERLEAVED (0x00)
|
||||
#define BLE_ISO_PACKING_INTERLEAVED (0x01)
|
||||
|
||||
#define BLE_ISO_FRAMING_UNFRAMED_PDU (0x00)
|
||||
#define BLE_ISO_FRAMING_FRAMED_PDU_SEGMENTABLE_MODE (0x01)
|
||||
|
||||
@@ -2532,7 +2532,6 @@ typedef union {
|
||||
*/
|
||||
struct ble_cs_read_local_supp_caps_evt {
|
||||
esp_bt_status_t status; /*!< Indicate channel sounding read local supported capabilities command successfully completed */
|
||||
uint16_t conn_handle; /*!< Connection Handle */
|
||||
uint8_t num_config_supported; /*!< Number of CS configurations supported per connection */
|
||||
uint16_t max_consecutive_proc_supported; /*!< 0x0000: Support for both a fixed number of consecutive CS procedures and for an indefinite number of CS procedures until termination
|
||||
0x0001 to 0xFFFF: Maximum number of consecutive CS procedures supported */
|
||||
@@ -3113,6 +3112,11 @@ esp_err_t esp_ble_gap_add_device_to_resolving_list(esp_bd_addr_t peer_addr, uint
|
||||
/**
|
||||
* @brief This function clears the random address for the application
|
||||
*
|
||||
* @note This function shall not be used when:
|
||||
* - Advertising is enabled,
|
||||
* - Scanning is enabled, or
|
||||
* - any LE connection exists / a create connection command is pending.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
|
||||
@@ -519,8 +519,12 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id,
|
||||
* 2. `esp_ble_gattc_cache_refresh` can be used to discover services again.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_FAIL: Failure
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_GATT_NOT_FOUND: No matching service was found in the local cache
|
||||
* - ESP_GATT_INVALID_OFFSET: `offset` is out of range of the matched services
|
||||
* - ESP_GATT_NO_RESOURCES: Failed to allocate memory for the UUID lookup
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid,
|
||||
esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset);
|
||||
@@ -538,13 +542,17 @@ esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t con
|
||||
*
|
||||
* @note
|
||||
* 1. This API does not trigger any event.
|
||||
* 2. `start_handle` must be greater than 0, and smaller than `end_handle`.
|
||||
* 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and
|
||||
* `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches
|
||||
* cached attributes from the beginning of the handle range.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No characteristic found in the given handle range
|
||||
* - ESP_GATT_INVALID_OFFSET: `offset` is out of range of the matched characteristics
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -568,10 +576,12 @@ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if,
|
||||
* 2. `char_handle` must be greater than 0.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `char_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No descriptor found under the given characteristic
|
||||
* - ESP_GATT_INVALID_OFFSET: `offset` is out of range of the matched descriptors
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -592,13 +602,16 @@ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if,
|
||||
*
|
||||
* @note
|
||||
* 1. This API does not trigger any event.
|
||||
* 2. `start_handle` must be greater than 0, and smaller than `end_handle`.
|
||||
* 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and
|
||||
* `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches
|
||||
* cached attributes from the beginning of the handle range.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No characteristic matching `char_uuid` found in the handle range
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -622,12 +635,16 @@ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if,
|
||||
*
|
||||
* @note
|
||||
* 1. This API does not trigger any event.
|
||||
* 2. `start_handle` must be greater than 0, and smaller than `end_handle`.
|
||||
* 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and
|
||||
* `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches
|
||||
* cached attributes from the beginning of the handle range.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No descriptor matching the given UUIDs found in the handle range
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -653,10 +670,11 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if,
|
||||
* 2. `char_handle` must be greater than 0.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `char_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No descriptor matching `descr_uuid` found under `char_handle`
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -678,12 +696,16 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if,
|
||||
*
|
||||
* @note
|
||||
* 1. This API does not trigger any event.
|
||||
* 2. `start_handle` must be greater than 0, and smaller than `end_handle`.
|
||||
* 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and
|
||||
* `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches
|
||||
* cached attributes from the beginning of the handle range.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No included service matching `incl_uuid` found in the handle range
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -707,13 +729,15 @@ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if,
|
||||
*
|
||||
* @note
|
||||
* 1. This API does not trigger any event.
|
||||
* 2. `start_handle` must be greater than 0, and smaller than `end_handle` if the `type` is not `ESP_GATT_DB_DESCRIPTOR`.
|
||||
* 2. If the `type` is not `ESP_GATT_DB_DESCRIPTOR`, `start_handle` must not be greater than
|
||||
* `end_handle`, and `start_handle` and `end_handle` must not both be 0. 0 is allowed for
|
||||
* `start_handle` alone and matches cached attributes from the beginning of the handle range.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle`, `end_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `count`
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
@@ -735,13 +759,16 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if,
|
||||
*
|
||||
* @note
|
||||
* 1. This API does not trigger any event.
|
||||
* 2. `start_handle` must be greater than 0, and smaller than `end_handle`.
|
||||
* 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and
|
||||
* `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches
|
||||
* cached attributes from the beginning of the handle range.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle`, `end_handle`
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `db` or NULL pointer to `count` or the count value is 0
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - ESP_GATT_NOT_FOUND: No GATT database element found in the given handle range
|
||||
*
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
|
||||
@@ -784,7 +811,9 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
|
||||
* @note
|
||||
* 1. This function triggers `ESP_GATTC_READ_CHAR_EVT`.
|
||||
* 2. This function should be called only after the connection has been established.
|
||||
* 3. `start_handle` must be greater than 0, and smaller than `end_handle`.
|
||||
* 3. `start_handle` must not be greater than `end_handle`, and `start_handle` and
|
||||
* `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and is
|
||||
* treated as 1 on air.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
|
||||
@@ -548,9 +548,11 @@ esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, co
|
||||
* 2. `attr_handle` must be greater than 0.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_GATT_OK: Success
|
||||
* - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled
|
||||
* - ESP_GATT_INVALID_PDU: NULL pointer to `length` or `value`
|
||||
* - ESP_GATT_INVALID_HANDLE: Invalid `attr_handle`
|
||||
* - ESP_FAIL: Failure due to other reasons
|
||||
* - Other `esp_gatt_status_t` values: Failure due to other reasons
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value);
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ void bta_gattc_disable(tBTA_GATTC_CB *p_cb)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
UINT8 i;
|
||||
tBT_UUID *p_app_uuid = &p_data->api_reg.app_uuid;
|
||||
tBTA_GATTC_INT_START_IF *p_buf;
|
||||
@@ -383,7 +383,7 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_
|
||||
UINT16 event = ((BT_HDR *)p_msg)->event;
|
||||
tBTA_GATTC_CLCB *p_clcb = NULL;
|
||||
tBTA_GATTC_RCB *p_clreg;
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
UNUSED(p_cb);
|
||||
|
||||
if (p_msg->api_cancel_conn.is_direct) {
|
||||
@@ -425,7 +425,7 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_
|
||||
void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTC_RCB *p_clreg;
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
UNUSED(p_cb);
|
||||
|
||||
p_clreg = bta_gattc_cl_get_regcb(p_msg->enc_cmpl.client_if);
|
||||
@@ -451,7 +451,7 @@ void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
UNUSED(p_data);
|
||||
|
||||
memset(&cb_data, 0, sizeof(cb_data));
|
||||
@@ -513,6 +513,8 @@ void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&gattc_data, 0, sizeof(gattc_data));
|
||||
|
||||
p_tcb = gatt_find_tcb_by_addr(p_data->api_conn.remote_bda, BT_TRANSPORT_LE);
|
||||
if(p_tcb) {
|
||||
found_app = gatt_find_specific_app_in_hold_link(p_tcb, p_clcb->p_rcb->client_if);
|
||||
@@ -584,6 +586,8 @@ void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg
|
||||
tBTA_GATTC_CLCB *p_clcb;
|
||||
tBTA_GATTC_DATA gattc_data;
|
||||
|
||||
memset(&gattc_data, 0, sizeof(gattc_data));
|
||||
|
||||
if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE)) {
|
||||
/* always call open to hold a connection */
|
||||
if (!GATT_Connect(p_data->client_if, p_data->remote_bda,
|
||||
@@ -634,8 +638,7 @@ void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg
|
||||
void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
|
||||
{
|
||||
tBTA_GATTC_RCB *p_clreg;
|
||||
tBTA_GATTC cb_data;
|
||||
|
||||
tBTA_GATTC cb_data = {0};
|
||||
memset(&cb_data, 0, sizeof(cb_data));
|
||||
cb_data.cancel_open.status = BTA_GATT_ERROR;
|
||||
cb_data.cancel_open.client_if = p_data->client_if;
|
||||
@@ -667,7 +670,7 @@ void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
UNUSED(p_data);
|
||||
|
||||
if ( p_clcb->p_rcb->p_cback ) {
|
||||
@@ -691,8 +694,7 @@ void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
|
||||
tBTA_GATTC cb_data = {0};
|
||||
if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE)) {
|
||||
bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CANCEL_OPEN_OK_EVT, p_data);
|
||||
} else {
|
||||
@@ -759,12 +761,18 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
bta_gattc_register_service_change_notify(p_clcb->bta_conn_id, p_clcb->bda);
|
||||
} else
|
||||
#endif
|
||||
{ /* cache is building */
|
||||
APPL_TRACE_DEBUG("%s cache not found, start discovery %u", __func__, bta_gattc_cb.auto_disc);
|
||||
{ /* cache miss or cache load failed */
|
||||
APPL_TRACE_DEBUG("%s cache not found, auto_disc=%u", __func__, bta_gattc_cb.auto_disc);
|
||||
if (bta_gattc_cb.auto_disc) {
|
||||
p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
|
||||
/* cache load failure, start discovery */
|
||||
bta_gattc_start_discover(p_clcb, NULL);
|
||||
} else {
|
||||
/* Auto discovery is disabled: roll the SRCB back to
|
||||
* SERV_IDLE so it is not stuck in SERV_LOAD. The app is
|
||||
* expected to drive service discovery explicitly via
|
||||
* BTA_GATTC_ServiceSearchRequest() once it is ready. */
|
||||
p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
|
||||
}
|
||||
}
|
||||
} else { /* cache is building */
|
||||
@@ -852,8 +860,7 @@ void bta_gattc_disconncback(tBTA_GATTC_RCB *p_rcb, tBTA_GATTC_DATA *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
|
||||
tBTA_GATTC cb_data = {0};
|
||||
if ( p_clcb->p_rcb->p_cback ) {
|
||||
memset(&cb_data, 0, sizeof(tBTA_GATTC));
|
||||
cb_data.close.client_if = p_clcb->p_rcb->client_if;
|
||||
@@ -883,8 +890,7 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
}
|
||||
tBTA_GATTC_CBACK *p_cback = p_clcb->p_rcb->p_cback;
|
||||
tBTA_GATTC_RCB *p_clreg = p_clcb->p_rcb;
|
||||
tBTA_GATTC cb_data;
|
||||
|
||||
tBTA_GATTC cb_data = {0};
|
||||
APPL_TRACE_DEBUG("bta_gattc_close conn_id=%d", p_clcb->bta_conn_id);
|
||||
|
||||
cb_data.close.client_if = p_clcb->p_rcb->client_if;
|
||||
@@ -908,9 +914,13 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
(* p_cback)(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC *)&cb_data);
|
||||
}
|
||||
|
||||
// Please note that BTA_GATTC_CLOSE_EVT will run in the BTC task.
|
||||
// because bta_gattc_deregister_cmpl did not execute as expected(this is a known issue),
|
||||
// we will run it again in bta_gattc_clcb_dealloc_by_conn_id.
|
||||
/*
|
||||
* Free the CLCB in the BTA task after the close callback has been copied to
|
||||
* BTC. This keeps the original close-callback semantics while avoiding BTC
|
||||
* task access to core stack control blocks without locking.
|
||||
*/
|
||||
bta_gattc_clcb_dealloc(p_clcb);
|
||||
|
||||
if (p_clreg->num_clcb == 0 && p_clreg->dereg_pending) {
|
||||
bta_gattc_deregister_cmpl(p_clreg);
|
||||
}
|
||||
@@ -1078,7 +1088,7 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
APPL_TRACE_ERROR("discovery on server failed");
|
||||
bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
|
||||
//discover service complete, trigger callback
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
cb_data.dis_cmpl.status = p_clcb->status;
|
||||
cb_data.dis_cmpl.conn_id = p_clcb->bta_conn_id;
|
||||
( *p_clcb->p_rcb->p_cback)(BTA_GATTC_DIS_SRVC_CMPL_EVT, &cb_data);
|
||||
@@ -1380,7 +1390,7 @@ void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
{
|
||||
UINT8 event;
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
tBTA_GATT_UNFMT read_value;
|
||||
|
||||
if (p_clcb->p_q_cmd == NULL) {
|
||||
@@ -1434,8 +1444,21 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
APPL_TRACE_ERROR("%s, p_data->p_cmpl is NULL", __func__);
|
||||
UINT16 handle = p_clcb->p_q_cmd->api_write.handle;
|
||||
tBTA_GATTC_EVT cmpl_evt = p_clcb->p_q_cmd->api_write.cmpl_evt;
|
||||
tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find(p_clcb->bda);
|
||||
bta_gattc_free_command_data(p_clcb);
|
||||
bta_gattc_pop_command_to_send(p_clcb);
|
||||
/* If this completion belongs to the internal service-change CCC write,
|
||||
* clear the in-progress flag and swallow the event so the application
|
||||
* does not see a spurious BTA_GATTC_WRITE_DESCR_EVT, and a future
|
||||
* bta_gattc_register_service_change_notify() can retry. */
|
||||
if (p_conn &&
|
||||
p_conn->write_remote_svc_change_ccc_in_progress &&
|
||||
p_conn->svc_change_descr_handle == handle) {
|
||||
p_conn->write_remote_svc_change_ccc_in_progress = FALSE;
|
||||
p_conn->write_remote_svc_change_ccc_done = FALSE;
|
||||
APPL_TRACE_ERROR("svc chg ccc: p_cmpl NULL");
|
||||
return;
|
||||
}
|
||||
cb_data.write.status = BTA_GATT_ERROR;
|
||||
cb_data.write.handle = handle;
|
||||
cb_data.write.conn_id = p_clcb->bta_conn_id;
|
||||
@@ -1452,7 +1475,7 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE) {
|
||||
// Check if the parameters are valid
|
||||
// should not happen, but just in case
|
||||
if (p_clcb->p_q_cmd->api_write.p_value == NULL) {
|
||||
if (p_clcb->p_q_cmd->api_write.p_value == NULL && p_clcb->p_q_cmd->api_write.len != 0) {
|
||||
APPL_TRACE_ERROR("%s, p_clcb->p_q_cmd->api_write.p_value is NULL", __func__);
|
||||
bta_gattc_free_command_data(p_clcb);
|
||||
bta_gattc_pop_command_to_send(p_clcb);
|
||||
@@ -1461,10 +1484,21 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
( *p_clcb->p_rcb->p_cback)(BTA_GATTC_PREP_WRITE_EVT, (tBTA_GATTC *)&cb_data);
|
||||
return;
|
||||
}
|
||||
// Should check the value received from the peer device is correct or not.
|
||||
if (memcmp(p_clcb->p_q_cmd->api_write.p_value, p_data->p_cmpl->att_value.value,
|
||||
p_data->p_cmpl->att_value.len) != 0) {
|
||||
cb_data.write.status = BTA_GATT_INVALID_PDU;
|
||||
/* Rsp value is one ATT chunk (<= MTU-5), not necessarily full api_write.len. */
|
||||
{
|
||||
UINT16 rsp_len = p_data->p_cmpl->att_value.len;
|
||||
UINT16 req_len = p_clcb->p_q_cmd->api_write.len;
|
||||
tGATT_VALUE *a = &p_data->p_cmpl->att_value;
|
||||
tBTA_GATTC_API_WRITE *w = &p_clcb->p_q_cmd->api_write;
|
||||
|
||||
if (a->handle != w->handle || a->offset != w->offset || rsp_len > req_len ||
|
||||
(req_len > 0 && rsp_len == 0) ||
|
||||
(rsp_len > 0 && w->p_value != NULL &&
|
||||
memcmp(w->p_value, a->value, rsp_len) != 0)) {
|
||||
APPL_TRACE_ERROR("%s prep_write rsp bad h %u/%u o %u/%u len %u/%u", __func__,
|
||||
a->handle, w->handle, a->offset, w->offset, rsp_len, req_len);
|
||||
cb_data.write.status = BTA_GATT_INVALID_PDU;
|
||||
}
|
||||
}
|
||||
|
||||
event = BTA_GATTC_PREP_WRITE_EVT;
|
||||
@@ -1475,12 +1509,17 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
bta_gattc_free_command_data(p_clcb);
|
||||
bta_gattc_pop_command_to_send(p_clcb);
|
||||
cb_data.write.conn_id = p_clcb->bta_conn_id;
|
||||
if (p_conn && p_conn->svc_change_descr_handle == cb_data.write.handle) {
|
||||
if(cb_data.write.status != BTA_GATT_OK) {
|
||||
if (p_conn &&
|
||||
p_conn->write_remote_svc_change_ccc_in_progress &&
|
||||
p_conn->svc_change_descr_handle == cb_data.write.handle) {
|
||||
p_conn->write_remote_svc_change_ccc_in_progress = FALSE;
|
||||
if (cb_data.write.status == BTA_GATT_OK) {
|
||||
p_conn->write_remote_svc_change_ccc_done = TRUE;
|
||||
} else {
|
||||
p_conn->write_remote_svc_change_ccc_done = FALSE;
|
||||
APPL_TRACE_ERROR("service change write ccc failed");
|
||||
}
|
||||
return;
|
||||
return; /* internal CCC write: don't forward to application */
|
||||
}
|
||||
/* write complete, callback */
|
||||
( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
|
||||
@@ -1497,7 +1536,7 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
//free the command data store in the queue.
|
||||
bta_gattc_free_command_data(p_clcb);
|
||||
bta_gattc_pop_command_to_send(p_clcb);
|
||||
@@ -1522,7 +1561,7 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
//free the command data store in the queue.
|
||||
bta_gattc_free_command_data(p_clcb);
|
||||
bta_gattc_pop_command_to_send(p_clcb);
|
||||
@@ -1650,7 +1689,7 @@ void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
tBTA_GATT_STATUS status = GATT_INTERNAL_ERROR;
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
APPL_TRACE_DEBUG("bta_gattc_search conn_id=%d", p_clcb->bta_conn_id);
|
||||
if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache) {
|
||||
status = BTA_GATT_OK;
|
||||
@@ -1782,7 +1821,7 @@ void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg)
|
||||
{
|
||||
tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
|
||||
tBTA_GATTC_IF client_if = p_clreg->client_if;
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
tBTA_GATTC_CBACK *p_cback = p_clreg->p_cback;
|
||||
|
||||
memset(&cb_data, 0, sizeof(tBTA_GATTC));
|
||||
@@ -1910,7 +1949,7 @@ static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_refresh.remote_bda);
|
||||
tBTA_GATTC_SERV *p_srvc_cb;
|
||||
tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
|
||||
BOOLEAN found = FALSE;
|
||||
UINT8 i;
|
||||
@@ -1918,6 +1957,14 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
|
||||
|
||||
APPL_TRACE_DEBUG("%s", __func__);
|
||||
|
||||
#if (GATTC_CACHE_NVS == TRUE)
|
||||
if (p_msg->api_refresh.erase_flash) {
|
||||
bta_gattc_cache_reset(p_msg->api_refresh.remote_bda);
|
||||
}
|
||||
#endif
|
||||
|
||||
p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_refresh.remote_bda);
|
||||
|
||||
if (p_srvc_cb != NULL) {
|
||||
/* try to find a CLCB */
|
||||
if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0) {
|
||||
@@ -2014,11 +2061,17 @@ void bta_gattc_process_api_cache_get_addr_list(tBTA_GATTC_CB *p_cb, tBTA_GATTC_D
|
||||
*******************************************************************************/
|
||||
void bta_gattc_process_api_cache_clean(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_clean.remote_bda);
|
||||
tBTA_GATTC_SERV *p_srvc_cb;
|
||||
UNUSED(p_cb);
|
||||
|
||||
APPL_TRACE_DEBUG("%s", __func__);
|
||||
|
||||
#if (GATTC_CACHE_NVS == TRUE)
|
||||
bta_gattc_cache_reset(p_msg->api_clean.remote_bda);
|
||||
#endif
|
||||
|
||||
p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_clean.remote_bda);
|
||||
|
||||
if (p_srvc_cb != NULL && p_srvc_cb->p_srvc_cache != NULL) {
|
||||
//mark it and delete the cache */
|
||||
list_free(p_srvc_cb->p_srvc_cache);
|
||||
@@ -2094,6 +2147,8 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
|
||||
tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find(p_clcb->bda);
|
||||
if(p_conn) {
|
||||
p_conn->write_remote_svc_change_ccc_done = FALSE;
|
||||
p_conn->write_remote_svc_change_ccc_in_progress = FALSE;
|
||||
p_conn->svc_change_descr_handle = 0;
|
||||
}
|
||||
bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
|
||||
}
|
||||
@@ -2300,7 +2355,7 @@ static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op,
|
||||
********************************************************************************/
|
||||
static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
tBTA_GATTC cb_data = {0};
|
||||
cb_data.congest.conn_id = conn_id;
|
||||
cb_data.congest.congested = congested;
|
||||
btc_gattc_congest_callback(&cb_data);
|
||||
@@ -2343,6 +2398,8 @@ void bta_gattc_init_clcb_conn(UINT8 cif, BD_ADDR remote_bda)
|
||||
tBTA_GATTC_DATA gattc_data;
|
||||
UINT16 conn_id;
|
||||
|
||||
memset(&gattc_data, 0, sizeof(gattc_data));
|
||||
|
||||
/* should always get the connection ID */
|
||||
if (GATT_GetConnIdIfConnected(cif, remote_bda, &conn_id, BTA_GATT_TRANSPORT_LE) == FALSE) {
|
||||
APPL_TRACE_ERROR("bta_gattc_init_clcb_conn ERROR: not a connected device");
|
||||
@@ -2414,7 +2471,8 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
|
||||
tBT_UUID gatt_service_change_uuid = {LEN_UUID_16, {GATT_UUID_GATT_SRV_CHGD}};
|
||||
tBT_UUID gatt_ccc_uuid = {LEN_UUID_16, {GATT_UUID_CHAR_CLIENT_CONFIG}};
|
||||
tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find_alloc(remote_bda);
|
||||
if(p_conn && p_conn->write_remote_svc_change_ccc_done) {
|
||||
if (p_conn && (p_conn->write_remote_svc_change_ccc_done ||
|
||||
p_conn->write_remote_svc_change_ccc_in_progress)) {
|
||||
return SERVICE_CHANGE_CCC_WRITTEN_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2481,17 +2539,26 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
|
||||
}
|
||||
|
||||
if (gatt_ccc_found == TRUE){
|
||||
if (p_conn) {
|
||||
/*
|
||||
* The in-progress flag is required so that bta_gattc_write_cmpl can
|
||||
* recognize this internal CCC write and avoid forwarding the response
|
||||
* to the application as a spurious BTA_GATTC_WRITE_DESCR_EVT. If the
|
||||
* connection tracking slot could not be obtained (e.g. conn_track is
|
||||
* full), skip the write entirely instead of issuing an untracked one.
|
||||
*/
|
||||
if (p_conn == NULL) {
|
||||
APPL_TRACE_ERROR("%s: no conn_track, skip ccc", __func__);
|
||||
result = SERVICE_CHANGE_WRITE_CCC_FAILED;
|
||||
} else {
|
||||
p_conn->svc_change_descr_handle = p_desc->handle;
|
||||
p_conn->write_remote_svc_change_ccc_done = TRUE;
|
||||
p_conn->write_remote_svc_change_ccc_in_progress = TRUE;
|
||||
result = SERVICE_CHANGE_CCC_WRITTEN_SUCCESS;
|
||||
uint16_t indicate_value = GATT_CLT_CONFIG_INDICATION;
|
||||
tBTA_GATT_UNFMT indicate_v;
|
||||
indicate_v.len = 2;
|
||||
indicate_v.p_value = (uint8_t *)&indicate_value;
|
||||
BTA_GATTC_WriteCharDescr (conn_id, p_desc->handle, BTA_GATTC_TYPE_WRITE, &indicate_v, BTA_GATT_AUTH_REQ_NONE);
|
||||
}
|
||||
result = SERVICE_CHANGE_CCC_WRITTEN_SUCCESS;
|
||||
uint16_t indicate_value = GATT_CLT_CONFIG_INDICATION;
|
||||
tBTA_GATT_UNFMT indicate_v;
|
||||
indicate_v.len = 2;
|
||||
indicate_v.p_value = (uint8_t *)&indicate_value;
|
||||
BTA_GATTC_WriteCharDescr (conn_id, p_desc->handle, BTA_GATTC_TYPE_WRITE, &indicate_v, BTA_GATT_AUTH_REQ_NONE);
|
||||
|
||||
}
|
||||
else if (gatt_service_change_found == TRUE) {
|
||||
/* Gatt service char found, but service change char ccc not found,
|
||||
|
||||
@@ -91,6 +91,7 @@ void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
|
||||
}
|
||||
|
||||
if ((p_buf = (tBTA_GATTC_API_REG *) osi_malloc(sizeof(tBTA_GATTC_API_REG))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(*p_buf));
|
||||
p_buf->hdr.event = BTA_GATTC_API_REG_EVT;
|
||||
if (p_app_uuid != NULL) {
|
||||
memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
|
||||
@@ -206,6 +207,7 @@ void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN i
|
||||
tBTA_GATTC_API_CANCEL_OPEN *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_GATTC_API_CANCEL_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_CANCEL_OPEN))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_GATTC_API_CANCEL_OPEN));
|
||||
p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT;
|
||||
|
||||
p_buf->client_if = client_if;
|
||||
@@ -780,6 +782,7 @@ void BTA_GATTC_PrepareWrite (UINT16 conn_id, UINT16 handle,
|
||||
p_buf->handle = handle;
|
||||
|
||||
p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
|
||||
p_buf->cmpl_evt = BTA_GATTC_PREP_WRITE_EVT;
|
||||
p_buf->offset = offset;
|
||||
p_buf->len = len;
|
||||
|
||||
@@ -827,6 +830,7 @@ void BTA_GATTC_PrepareWriteCharDescr (UINT16 conn_id, UINT16 handle,
|
||||
p_buf->auth_req = auth_req;
|
||||
p_buf->handle = handle;
|
||||
p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
|
||||
p_buf->cmpl_evt = BTA_GATTC_PREP_WRITE_EVT;
|
||||
p_buf->offset = offset;
|
||||
|
||||
if (p_data && p_data->len != 0) {
|
||||
@@ -1043,12 +1047,6 @@ tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
|
||||
*******************************************************************************/
|
||||
void BTA_GATTC_Refresh(BD_ADDR remote_bda, bool erase_flash)
|
||||
{
|
||||
#if(GATTC_CACHE_NVS == TRUE)
|
||||
if(erase_flash) {
|
||||
/* used to reset cache in application */
|
||||
bta_gattc_cache_reset(remote_bda);
|
||||
}
|
||||
#endif
|
||||
//If the registration callback is NULL, return
|
||||
if(bta_sys_is_register(BTA_ID_GATTC) == FALSE) {
|
||||
return;
|
||||
@@ -1056,8 +1054,10 @@ void BTA_GATTC_Refresh(BD_ADDR remote_bda, bool erase_flash)
|
||||
tBTA_GATTC_API_CACHE_REFRESH *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_GATTC_API_CACHE_REFRESH *) osi_malloc(sizeof(tBTA_GATTC_API_CACHE_REFRESH))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_GATTC_API_CACHE_REFRESH));
|
||||
p_buf->hdr.event = BTA_GATTC_API_REFRESH_EVT;
|
||||
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
|
||||
p_buf->erase_flash = erase_flash ? TRUE : FALSE;
|
||||
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
@@ -1106,11 +1106,6 @@ void BTA_GATTC_CacheGetAddrList(tBTA_GATTC_IF client_if)
|
||||
*******************************************************************************/
|
||||
void BTA_GATTC_Clean(BD_ADDR remote_bda)
|
||||
{
|
||||
#if(GATTC_CACHE_NVS == TRUE)
|
||||
/* used to reset cache in application */
|
||||
bta_gattc_cache_reset(remote_bda);
|
||||
#endif
|
||||
|
||||
tBTA_GATTC_API_CACHE_CLEAN *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_GATTC_API_CACHE_CLEAN *) osi_malloc(sizeof(tBTA_GATTC_API_CACHE_CLEAN))) != NULL) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,6 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifdef BT_SUPPORT_NVM
|
||||
#include <unistd.h>
|
||||
#endif /* BT_SUPPORT_NVM */
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "bta/bta_gattc_co.h"
|
||||
@@ -30,6 +27,8 @@
|
||||
#include "osi/list.h"
|
||||
#include "esp_err.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
|
||||
#if( defined BTA_GATT_INCLUDED ) && (GATTC_INCLUDED == TRUE)
|
||||
@@ -40,42 +39,6 @@
|
||||
#define MAX_DEVICE_IN_CACHE 50
|
||||
#define MAX_ADDR_LIST_CACHE_BUF 2048
|
||||
|
||||
#ifdef BT_SUPPORT_NVM
|
||||
static FILE *sCacheFD = 0;
|
||||
static void getFilename(char *buffer, BD_ADDR bda)
|
||||
{
|
||||
sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX
|
||||
, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
}
|
||||
|
||||
static void cacheClose(void)
|
||||
{
|
||||
if (sCacheFD != 0) {
|
||||
fclose(sCacheFD);
|
||||
sCacheFD = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool cacheOpen(BD_ADDR bda, bool to_save)
|
||||
{
|
||||
char fname[255] = {0};
|
||||
getFilename(fname, bda);
|
||||
|
||||
cacheClose();
|
||||
sCacheFD = fopen(fname, to_save ? "w" : "r");
|
||||
|
||||
return (sCacheFD != 0);
|
||||
}
|
||||
|
||||
static void cacheReset(BD_ADDR bda)
|
||||
{
|
||||
char fname[255] = {0};
|
||||
getFilename(fname, bda);
|
||||
unlink(fname);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const char *cache_key = "gattc_cache_key";
|
||||
static const char *cache_addr = "cache_addr_tab";
|
||||
|
||||
@@ -98,6 +61,60 @@ typedef struct {
|
||||
|
||||
static cache_env_t *cache_env = NULL;
|
||||
|
||||
/* Protect |cache_env|; exported callouts re-enter each other (e.g. cacheOpen -> find_addr).
|
||||
*
|
||||
* The mutex is created exactly once from bta_gattc_co_cache_addr_init() on the
|
||||
* BT host startup task before any other callout becomes reachable, so we do
|
||||
* NOT need any spinlock around the creation. The *Static variant places the
|
||||
* storage in .bss and avoids any allocation. */
|
||||
static StaticSemaphore_t s_cache_env_mutex_buf;
|
||||
static SemaphoreHandle_t s_cache_env_mutex = NULL;
|
||||
|
||||
/* Must be called from the BT host startup task (single-threaded context)
|
||||
* before any other cache_env_* user becomes reachable. Idempotent. */
|
||||
static void cache_env_mutex_init_once(void)
|
||||
{
|
||||
if (s_cache_env_mutex == NULL) {
|
||||
s_cache_env_mutex = xSemaphoreCreateRecursiveMutexStatic(&s_cache_env_mutex_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void cache_env_lock(void)
|
||||
{
|
||||
if (s_cache_env_mutex != NULL) {
|
||||
(void)xSemaphoreTakeRecursive(s_cache_env_mutex, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
static void cache_env_unlock(void)
|
||||
{
|
||||
if (s_cache_env_mutex != NULL) {
|
||||
xSemaphoreGiveRecursive(s_cache_env_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Format a per-device GATT cache NVS namespace name into |buffer|.
|
||||
*
|
||||
* Output layout: GATT_CACHE_PREFIX (5 chars: "gatt_") + sizeof(hash_key_t)*2
|
||||
* hex chars (currently 8) + NUL = 14 bytes total.
|
||||
*
|
||||
* Contract:
|
||||
* |buffer| MUST be at least NVS_KEY_NAME_MAX_SIZE (16) bytes, which is also
|
||||
* the NVS limit for a namespace name. Today's 14-byte output leaves only
|
||||
* 2 bytes of headroom -- if GATT_CACHE_PREFIX is ever lengthened or
|
||||
* sizeof(hash_key_t) is ever increased so that
|
||||
*
|
||||
* strlen(GATT_CACHE_PREFIX) + 2*sizeof(hash_key_t) + 1 > NVS_KEY_NAME_MAX_SIZE
|
||||
*
|
||||
* this sprintf() will silently overflow the caller's stack buffer AND
|
||||
* produce a namespace name that nvs_open() will reject. In that case
|
||||
* switch to snprintf(buffer, NVS_KEY_NAME_MAX_SIZE, ...) and propagate
|
||||
* the truncation as an error to callers.
|
||||
*
|
||||
* Callers (keep this list in sync if a new one is added):
|
||||
* - cacheOpen() [open by current hash]
|
||||
* - bta_gattc_co_cache_addr_save() [erase old namespace on hash change]
|
||||
*/
|
||||
static void getFilename(char *buffer, hash_key_t hash)
|
||||
{
|
||||
sprintf(buffer, "%s%02x%02x%02x%02x", GATT_CACHE_PREFIX,
|
||||
@@ -107,6 +124,9 @@ static void getFilename(char *buffer, hash_key_t hash)
|
||||
static void cacheClose(BD_ADDR bda)
|
||||
{
|
||||
UINT8 index = 0;
|
||||
if (cache_env == NULL) {
|
||||
return;
|
||||
}
|
||||
if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
|
||||
if (cache_env->cache_addr[index].is_open) {
|
||||
nvs_close(cache_env->cache_addr[index].cache_fp);
|
||||
@@ -117,8 +137,13 @@ static void cacheClose(BD_ADDR bda)
|
||||
|
||||
static bool cacheOpen(BD_ADDR bda, bool to_save, UINT8 *index)
|
||||
{
|
||||
if (cache_env == NULL) {
|
||||
return false;
|
||||
}
|
||||
UNUSED(to_save);
|
||||
char fname[255] = {0};
|
||||
/* NVS namespace name is limited to (NVS_KEY_NAME_MAX_SIZE - 1) characters.
|
||||
* getFilename() produces GATT_CACHE_PREFIX (5) + 8 hex chars + NUL = 14 bytes. */
|
||||
char fname[NVS_KEY_NAME_MAX_SIZE] = {0};
|
||||
UINT8 *assoc_addr = NULL;
|
||||
esp_err_t status = ESP_FAIL;
|
||||
hash_key_t hash_key = {0};
|
||||
@@ -141,8 +166,9 @@ static bool cacheOpen(BD_ADDR bda, bool to_save, UINT8 *index)
|
||||
|
||||
static void cacheReset(BD_ADDR bda, BOOLEAN update)
|
||||
{
|
||||
char fname[255] = {0};
|
||||
getFilename(fname, bda);
|
||||
if (cache_env == NULL) {
|
||||
return;
|
||||
}
|
||||
UINT8 index = 0;
|
||||
//cache_env->cache_addr
|
||||
if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
|
||||
@@ -153,18 +179,21 @@ static void cacheReset(BD_ADDR bda, BOOLEAN update)
|
||||
nvs_close(cache_env->cache_addr[index].cache_fp);
|
||||
cache_env->cache_addr[index].is_open = FALSE;
|
||||
} else {
|
||||
cacheOpen(bda, false, &index);
|
||||
if (index == INVALID_ADDR_NUM) {
|
||||
APPL_TRACE_ERROR("%s INVALID ADDR NUM", __func__);
|
||||
return;
|
||||
}
|
||||
/* The entry exists but is not currently held open in this session;
|
||||
* try to (re)open it best-effort so we can erase the on-flash blob.
|
||||
* The recursive cache_env lock is held throughout, so cacheOpen()'s
|
||||
* internal find_addr_in_cache(bda) cannot disagree with the outer
|
||||
* find above, i.e. *index will remain valid here. We deliberately
|
||||
* do NOT bail out on cacheOpen() failure: the entry must still be
|
||||
* removed from RAM to keep num_addr/cache_addr[] consistent and to
|
||||
* avoid OOB in callers. */
|
||||
(void)cacheOpen(bda, false, &index);
|
||||
if (cache_env->cache_addr[index].is_open) {
|
||||
nvs_erase_all(cache_env->cache_addr[index].cache_fp);
|
||||
nvs_close(cache_env->cache_addr[index].cache_fp);
|
||||
cache_env->cache_addr[index].is_open = FALSE;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s cacheOpen failed", __func__);
|
||||
return;
|
||||
APPL_TRACE_ERROR("%s: cacheOpen fail, evict RAM", __func__);
|
||||
}
|
||||
}
|
||||
if(cache_env->num_addr == 0) {
|
||||
@@ -180,6 +209,10 @@ static void cacheReset(BD_ADDR bda, BOOLEAN update)
|
||||
cache_env->cache_addr[index].assoc_addr = NULL;
|
||||
}
|
||||
|
||||
if (cache_env->num_addr > MAX_DEVICE_IN_CACHE) {
|
||||
APPL_TRACE_WARNING("%s: num_addr %u exceeds max, clamping", __func__, cache_env->num_addr);
|
||||
cache_env->num_addr = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
UINT8 num = cache_env->num_addr;
|
||||
//delete the server_bda in the addr_info list.
|
||||
for(UINT8 i = index; i < (num - 1); i++) {
|
||||
@@ -231,7 +264,6 @@ static void cacheReset(BD_ADDR bda, BOOLEAN update)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BT_SUPPORT_NVM */
|
||||
/*****************************************************************************
|
||||
** Function Declarations
|
||||
*****************************************************************************/
|
||||
@@ -253,13 +285,19 @@ static void cacheReset(BD_ADDR bda, BOOLEAN update)
|
||||
*******************************************************************************/
|
||||
tBTA_GATT_STATUS bta_gattc_co_cache_open(BD_ADDR server_bda, BOOLEAN to_save, UINT8 *index)
|
||||
{
|
||||
cache_env_lock();
|
||||
/* open NV cache and send call in */
|
||||
tBTA_GATT_STATUS status = BTA_GATT_OK;
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return BTA_GATT_ERROR;
|
||||
}
|
||||
if (!cacheOpen(server_bda, to_save, index)) {
|
||||
status = BTA_GATT_ERROR;
|
||||
}
|
||||
|
||||
APPL_TRACE_DEBUG("%s() - status=%d", __func__, status);
|
||||
cache_env_unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -280,11 +318,22 @@ tBTA_GATT_STATUS bta_gattc_co_cache_open(BD_ADDR server_bda, BOOLEAN to_save, UI
|
||||
*******************************************************************************/
|
||||
tBTA_GATT_STATUS bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR *attr, UINT8 index)
|
||||
{
|
||||
cache_env_lock();
|
||||
#if (!CONFIG_BT_STACK_NO_LOG)
|
||||
UINT16 num_attr = 0;
|
||||
#endif
|
||||
tBTA_GATT_STATUS status = BTA_GATT_ERROR;
|
||||
size_t length = 0;
|
||||
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return BTA_GATT_ERROR;
|
||||
}
|
||||
|
||||
if (index >= MAX_DEVICE_IN_CACHE) {
|
||||
cache_env_unlock();
|
||||
return BTA_GATT_ERROR;
|
||||
}
|
||||
// Read the size of memory space required for blob
|
||||
nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, NULL, &length);
|
||||
// Read previously saved blob if available
|
||||
@@ -296,18 +345,28 @@ tBTA_GATT_STATUS bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR *attr, UINT8 index)
|
||||
APPL_TRACE_DEBUG("%s() - read=%d, status=%d, err_code = %d",
|
||||
__func__, num_attr, status, err_code);
|
||||
|
||||
cache_env_unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t bta_gattc_get_cache_attr_length(UINT8 index)
|
||||
{
|
||||
cache_env_lock();
|
||||
size_t length = 0;
|
||||
if (index == INVALID_ADDR_NUM) {
|
||||
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (index == INVALID_ADDR_NUM || index >= MAX_DEVICE_IN_CACHE) {
|
||||
cache_env_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read the size of memory space required for blob
|
||||
nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, NULL, &length);
|
||||
cache_env_unlock();
|
||||
return length;
|
||||
}
|
||||
|
||||
@@ -330,6 +389,13 @@ size_t bta_gattc_get_cache_attr_length(UINT8 index)
|
||||
void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
|
||||
tBTA_GATTC_NV_ATTR *p_attr_list)
|
||||
{
|
||||
cache_env_lock();
|
||||
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
tBTA_GATT_STATUS status = BTA_GATT_OK;
|
||||
hash_key_t hash_key = {0};
|
||||
UINT8 index = INVALID_ADDR_NUM;
|
||||
@@ -350,6 +416,7 @@ void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
|
||||
(void) status;
|
||||
#endif
|
||||
APPL_TRACE_DEBUG("%s() wrote hash_key = %x%x%x%x, num_attr = %d, status = %d.", __func__, hash_key[0], hash_key[1], hash_key[2], hash_key[3], num_attr, status);
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -367,14 +434,14 @@ void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
|
||||
*******************************************************************************/
|
||||
void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
|
||||
{
|
||||
cache_env_lock();
|
||||
UNUSED(conn_id);
|
||||
//#ifdef BT_SUPPORT_NVM
|
||||
cacheClose(server_bda);
|
||||
//#endif /* BT_SUPPORT_NVM */
|
||||
/* close NV when server cache is done saving or loading,
|
||||
does not need to do anything for now on Insight */
|
||||
|
||||
BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -391,18 +458,22 @@ void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
|
||||
*******************************************************************************/
|
||||
void bta_gattc_co_cache_reset(BD_ADDR server_bda)
|
||||
{
|
||||
cache_env_lock();
|
||||
cacheReset(server_bda, TRUE);
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
void bta_gattc_co_cache_addr_init(void)
|
||||
{
|
||||
cache_env_mutex_init_once();
|
||||
cache_env_lock();
|
||||
nvs_handle_t fp;
|
||||
esp_err_t err_code;
|
||||
UINT8 num_addr;
|
||||
size_t length = MAX_ADDR_LIST_CACHE_BUF;
|
||||
UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
|
||||
if (p_buf == NULL) {
|
||||
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -410,6 +481,7 @@ void bta_gattc_co_cache_addr_init(void)
|
||||
if (cache_env == NULL) {
|
||||
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
osi_free(p_buf);
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -420,19 +492,53 @@ void bta_gattc_co_cache_addr_init(void)
|
||||
cache_env->is_open = TRUE;
|
||||
// Read previously saved blob if available
|
||||
if ((err_code = nvs_get_blob(fp, cache_key, p_buf, &length)) != ESP_OK) {
|
||||
if(err_code != ESP_ERR_NVS_NOT_FOUND) {
|
||||
if (err_code == ESP_ERR_NVS_NOT_FOUND) {
|
||||
length = 0;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s, Line = %d, nvs flash get blob data fail, err_code = 0x%x", __func__, __LINE__, err_code);
|
||||
osi_free(p_buf);
|
||||
if (cache_env->is_open) {
|
||||
nvs_close(cache_env->addr_fp);
|
||||
cache_env->is_open = FALSE;
|
||||
}
|
||||
osi_free(cache_env);
|
||||
cache_env = NULL;
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
const size_t rec_sz = sizeof(BD_ADDR) + sizeof(hash_key_t);
|
||||
if (length == 0) {
|
||||
cache_env->num_addr = 0;
|
||||
osi_free(p_buf);
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
num_addr = length / (sizeof(BD_ADDR) + sizeof(hash_key_t));
|
||||
cache_env->num_addr = num_addr;
|
||||
if ((length % rec_sz) != 0) {
|
||||
APPL_TRACE_ERROR("%s: bad blob len %zu", __func__, length);
|
||||
(void)nvs_erase_key(fp, cache_key);
|
||||
cache_env->num_addr = 0;
|
||||
osi_free(p_buf);
|
||||
if (cache_env->is_open) {
|
||||
nvs_close(cache_env->addr_fp);
|
||||
cache_env->is_open = FALSE;
|
||||
}
|
||||
osi_free(cache_env);
|
||||
cache_env = NULL;
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
size_t n_entries = length / rec_sz;
|
||||
const BOOLEAN truncated = (n_entries > (size_t)MAX_DEVICE_IN_CACHE) ? TRUE : FALSE;
|
||||
if (truncated) {
|
||||
APPL_TRACE_WARNING("%s: trunc %zu->%d", __func__, n_entries, MAX_DEVICE_IN_CACHE);
|
||||
n_entries = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
cache_env->num_addr = (UINT8)n_entries;
|
||||
//read the address from nvs flash to cache address list.
|
||||
for (UINT8 i = 0; i < num_addr; i++) {
|
||||
memcpy(cache_env->cache_addr[i].addr, p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), sizeof(BD_ADDR));
|
||||
memcpy(cache_env->cache_addr[i].hash_key,
|
||||
p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR), sizeof(hash_key_t));
|
||||
for (UINT8 i = 0; i < cache_env->num_addr; i++) {
|
||||
memcpy(cache_env->cache_addr[i].addr, p_buf + i * rec_sz, sizeof(BD_ADDR));
|
||||
memcpy(cache_env->cache_addr[i].hash_key, p_buf + i * rec_sz + sizeof(BD_ADDR), sizeof(hash_key_t));
|
||||
|
||||
APPL_TRACE_DEBUG("cache_addr[%x] = %x:%x:%x:%x:%x:%x", i, cache_env->cache_addr[i].addr[0], cache_env->cache_addr[i].addr[1], cache_env->cache_addr[i].addr[2],
|
||||
cache_env->cache_addr[i].addr[3], cache_env->cache_addr[i].addr[4], cache_env->cache_addr[i].addr[5]);
|
||||
@@ -440,21 +546,30 @@ void bta_gattc_co_cache_addr_init(void)
|
||||
cache_env->cache_addr[i].hash_key[2], cache_env->cache_addr[i].hash_key[3]);
|
||||
bta_gattc_co_cache_new_assoc_list(cache_env->cache_addr[i].addr, i);
|
||||
}
|
||||
if (truncated) {
|
||||
UINT16 out_len = (UINT16)(cache_env->num_addr * rec_sz);
|
||||
if (nvs_set_blob(fp, cache_key, p_buf, out_len) != ESP_OK) {
|
||||
APPL_TRACE_WARNING("%s: nvs trunc fail", __func__);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
|
||||
osi_free(p_buf);
|
||||
osi_free(cache_env);
|
||||
cache_env = NULL;
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
osi_free(p_buf);
|
||||
return;
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
void bta_gattc_co_cache_addr_deinit(void)
|
||||
{
|
||||
cache_env_lock();
|
||||
if(cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -463,112 +578,222 @@ void bta_gattc_co_cache_addr_deinit(void)
|
||||
if (!cache_env->is_open) {
|
||||
osi_free(cache_env);
|
||||
cache_env = NULL;
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
nvs_close(cache_env->addr_fp);
|
||||
cache_env->is_open = false;
|
||||
|
||||
for(UINT8 i = 0; i< cache_env->num_addr; i++) {
|
||||
UINT8 num = cache_env->num_addr;
|
||||
if (num > MAX_DEVICE_IN_CACHE) {
|
||||
num = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
for (UINT8 i = 0; i < num; i++) {
|
||||
cache_addr_info_t *addr_info = &cache_env->cache_addr[i];
|
||||
if(addr_info) {
|
||||
if (addr_info->is_open) {
|
||||
nvs_close(addr_info->cache_fp);
|
||||
addr_info->is_open = false;
|
||||
if(addr_info->assoc_addr) {
|
||||
list_free(addr_info->assoc_addr);
|
||||
}
|
||||
}
|
||||
if (addr_info->assoc_addr != NULL) {
|
||||
list_free(addr_info->assoc_addr);
|
||||
addr_info->assoc_addr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
osi_free(cache_env);
|
||||
cache_env = NULL;
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
UINT8 addr_index = 0;
|
||||
UINT8 num = cache_env->num_addr;
|
||||
if (num > MAX_DEVICE_IN_CACHE) {
|
||||
num = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
|
||||
for (addr_index = 0; addr_index < num; addr_index++) {
|
||||
for (addr_index = 0; addr_index < num; addr_index++, addr_info++) {
|
||||
if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
|
||||
cache_env_unlock();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT8 bta_gattc_co_find_addr_in_cache(BD_ADDR bda)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return INVALID_ADDR_NUM;
|
||||
}
|
||||
UINT8 addr_index = 0;
|
||||
UINT8 num = cache_env->num_addr;
|
||||
if (num > MAX_DEVICE_IN_CACHE) {
|
||||
num = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
|
||||
|
||||
for (addr_index = 0; addr_index < num; addr_index++, addr_info++) {
|
||||
if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
|
||||
cache_env_unlock();
|
||||
return addr_index;
|
||||
}
|
||||
}
|
||||
|
||||
cache_env_unlock();
|
||||
return INVALID_ADDR_NUM;
|
||||
}
|
||||
|
||||
UINT8 bta_gattc_co_find_hash_in_cache(hash_key_t hash_key)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return INVALID_ADDR_NUM;
|
||||
}
|
||||
UINT8 index = 0;
|
||||
UINT8 num = cache_env->num_addr;
|
||||
if (num > MAX_DEVICE_IN_CACHE) {
|
||||
num = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
|
||||
for (index = 0; index < num; index++) {
|
||||
for (index = 0; index < num; index++, addr_info++) {
|
||||
if (!memcmp(addr_info->hash_key, hash_key, sizeof(hash_key_t))) {
|
||||
cache_env_unlock();
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
cache_env_unlock();
|
||||
return INVALID_ADDR_NUM;
|
||||
}
|
||||
|
||||
UINT8 bta_gattc_co_get_addr_num(void)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cache_env->num_addr;
|
||||
if (cache_env->num_addr > MAX_DEVICE_IN_CACHE) {
|
||||
cache_env_unlock();
|
||||
return MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
UINT8 n = cache_env->num_addr;
|
||||
cache_env_unlock();
|
||||
return n;
|
||||
}
|
||||
|
||||
void bta_gattc_co_get_addr_list(BD_ADDR *addr_list)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL || addr_list == NULL) {
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
UINT8 num = cache_env->num_addr;
|
||||
if (num > MAX_DEVICE_IN_CACHE) {
|
||||
num = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
for (UINT8 i = 0; i < num; i++) {
|
||||
memcpy(addr_list[i], cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
|
||||
}
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, hash_key_t hash_key)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
esp_err_t err_code;
|
||||
UINT8 index = 0;
|
||||
UINT8 new_index = cache_env->num_addr;
|
||||
UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
|
||||
if (p_buf == NULL) {
|
||||
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cache_env->num_addr > MAX_DEVICE_IN_CACHE) {
|
||||
APPL_TRACE_WARNING("%s: num_addr %u exceeds max, clamping", __func__, cache_env->num_addr);
|
||||
cache_env->num_addr = MAX_DEVICE_IN_CACHE;
|
||||
}
|
||||
|
||||
// check the address list has the same address or not
|
||||
// for the same address, it's hash key may be change due to service change
|
||||
if ((index = bta_gattc_co_find_addr_in_cache(bd_addr)) != INVALID_ADDR_NUM) {
|
||||
APPL_TRACE_DEBUG("%s the bd_addr already in the cache list, index = %x", __func__, index);
|
||||
/* If the hash key changed (service change on the same peer), the
|
||||
* per-device NVS namespace is keyed by the OLD hash. Just overwriting
|
||||
* the in-RAM hash would leave cache_fp/is_open pointing at the old
|
||||
* namespace, so a subsequent cacheOpen() would short-circuit on
|
||||
* is_open==TRUE and the new attribute blob would be written into the
|
||||
* stale namespace. After reboot the addr table maps bd_addr to the
|
||||
* NEW hash and the load path would miss (and the old namespace is
|
||||
* orphaned in NVS). Erase the old namespace and clear is_open so
|
||||
* the next cacheOpen() reopens with the new hash-derived filename. */
|
||||
if (memcmp(cache_env->cache_addr[index].hash_key, hash_key, sizeof(hash_key_t)) != 0) {
|
||||
APPL_TRACE_WARNING("%s: hash chg "MACSTR" %02x%02x%02x%02x->%02x%02x%02x%02x, erase NVS",
|
||||
__func__, MAC2STR(bd_addr),
|
||||
cache_env->cache_addr[index].hash_key[0], cache_env->cache_addr[index].hash_key[1],
|
||||
cache_env->cache_addr[index].hash_key[2], cache_env->cache_addr[index].hash_key[3],
|
||||
hash_key[0], hash_key[1], hash_key[2], hash_key[3]);
|
||||
if (cache_env->cache_addr[index].is_open) {
|
||||
(void)nvs_erase_all(cache_env->cache_addr[index].cache_fp);
|
||||
nvs_close(cache_env->cache_addr[index].cache_fp);
|
||||
cache_env->cache_addr[index].is_open = FALSE;
|
||||
} else {
|
||||
/* Not currently held open in this session; transiently open
|
||||
* the old namespace just to erase its blob. Best-effort:
|
||||
* ignore failures so a missing/corrupt old namespace does
|
||||
* not block writing the new one. */
|
||||
char fname_old[NVS_KEY_NAME_MAX_SIZE] = {0};
|
||||
nvs_handle_t old_fp;
|
||||
getFilename(fname_old, cache_env->cache_addr[index].hash_key);
|
||||
if (nvs_open(fname_old, NVS_READWRITE, &old_fp) == ESP_OK) {
|
||||
(void)nvs_erase_all(old_fp);
|
||||
nvs_close(old_fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if the bd_addr already in the address list, update the hash key in it.
|
||||
memcpy(cache_env->cache_addr[index].addr, bd_addr, sizeof(BD_ADDR));
|
||||
memcpy(cache_env->cache_addr[index].hash_key, hash_key, sizeof(hash_key_t));
|
||||
} else {
|
||||
if (cache_env->num_addr >= MAX_DEVICE_IN_CACHE) {
|
||||
while (cache_env->num_addr >= MAX_DEVICE_IN_CACHE) {
|
||||
APPL_TRACE_WARNING("%s cache list full and remove the oldest addr info", __func__);
|
||||
UINT8 before = cache_env->num_addr;
|
||||
cacheReset(cache_env->cache_addr[0].addr, FALSE);
|
||||
if (cache_env->num_addr >= before) {
|
||||
APPL_TRACE_ERROR("%s: cache eviction failed", __func__);
|
||||
osi_free(p_buf);
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
new_index = cache_env->num_addr;
|
||||
assert(new_index < MAX_DEVICE_IN_CACHE);
|
||||
if (new_index >= MAX_DEVICE_IN_CACHE) {
|
||||
APPL_TRACE_ERROR("%s: invalid new_index %u", __func__, new_index);
|
||||
osi_free(p_buf);
|
||||
cache_env_unlock();
|
||||
return;
|
||||
}
|
||||
memcpy(cache_env->cache_addr[new_index].addr, bd_addr, sizeof(BD_ADDR));
|
||||
memcpy(cache_env->cache_addr[new_index].hash_key, hash_key, sizeof(hash_key_t));
|
||||
cache_env->num_addr++;
|
||||
@@ -603,22 +828,45 @@ void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, hash_key_t hash_key)
|
||||
|
||||
//free the buffer after used.
|
||||
osi_free(p_buf);
|
||||
return;
|
||||
cache_env_unlock();
|
||||
}
|
||||
|
||||
BOOLEAN bta_gattc_co_cache_new_assoc_list(BD_ADDR src_addr, UINT8 index)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (cache_env == NULL) {
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
UNUSED(src_addr);
|
||||
if (index >= MAX_DEVICE_IN_CACHE) {
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
cache_addr_info_t *addr_info = &cache_env->cache_addr[index];
|
||||
/* Idempotent: if a list already exists at this slot (e.g. caller invoked
|
||||
* us twice on the same index), free it first so we don't leak the prior
|
||||
* list_t. The current sole caller is bta_gattc_co_cache_addr_init() which
|
||||
* runs after a fresh memset, so this path is normally a no-op; the guard
|
||||
* just keeps the function safe to reuse. */
|
||||
if (addr_info->assoc_addr != NULL) {
|
||||
list_free(addr_info->assoc_addr);
|
||||
addr_info->assoc_addr = NULL;
|
||||
}
|
||||
addr_info->assoc_addr = list_new(osi_free_func);
|
||||
return (addr_info->assoc_addr != NULL ? TRUE : FALSE);
|
||||
BOOLEAN ok = (addr_info->assoc_addr != NULL ? TRUE : FALSE);
|
||||
cache_env_unlock();
|
||||
return ok;
|
||||
}
|
||||
|
||||
BOOLEAN bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_addr)
|
||||
{
|
||||
cache_env_lock();
|
||||
UINT8 addr_index = 0;
|
||||
cache_addr_info_t *addr_info;
|
||||
UINT8 *p_assoc_buf = osi_malloc(sizeof(BD_ADDR));
|
||||
if(!p_assoc_buf) {
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(p_assoc_buf, assoc_addr, sizeof(BD_ADDR));
|
||||
@@ -630,6 +878,7 @@ BOOLEAN bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_add
|
||||
if (addr_info->assoc_addr == NULL) {
|
||||
APPL_TRACE_ERROR("assoc_addr list creation failed");
|
||||
osi_free(p_assoc_buf);
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -638,6 +887,7 @@ BOOLEAN bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_add
|
||||
if (!memcmp(list_node(sn), assoc_addr, sizeof(BD_ADDR))) {
|
||||
APPL_TRACE_WARNING("Association already exists");
|
||||
osi_free(p_assoc_buf);
|
||||
cache_env_unlock();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -645,19 +895,23 @@ BOOLEAN bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_add
|
||||
if (!list_append(addr_info->assoc_addr, p_assoc_buf)) {
|
||||
APPL_TRACE_ERROR("Failed to append to assoc_addr list");
|
||||
osi_free(p_assoc_buf);
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
cache_env_unlock();
|
||||
return TRUE;
|
||||
} else {
|
||||
osi_free(p_assoc_buf);
|
||||
}
|
||||
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN bta_gattc_co_cache_remove_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_addr)
|
||||
{
|
||||
cache_env_lock();
|
||||
UINT8 addr_index = 0;
|
||||
cache_addr_info_t *addr_info;
|
||||
if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
|
||||
@@ -667,20 +921,34 @@ BOOLEAN bta_gattc_co_cache_remove_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_add
|
||||
sn != list_end(addr_info->assoc_addr); sn = list_next(sn)) {
|
||||
void *addr = list_node(sn);
|
||||
if (!memcmp(addr, assoc_addr, sizeof(BD_ADDR))) {
|
||||
return list_remove(addr_info->assoc_addr, addr);
|
||||
BOOLEAN removed = list_remove(addr_info->assoc_addr, addr);
|
||||
cache_env_unlock();
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
//return list_remove(addr_info->assoc_addr, assoc_addr);
|
||||
} else {
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT8* bta_gattc_co_cache_find_src_addr(BD_ADDR assoc_addr, UINT8 *index)
|
||||
{
|
||||
cache_env_lock();
|
||||
if (index == NULL) {
|
||||
cache_env_unlock();
|
||||
return NULL;
|
||||
}
|
||||
if (cache_env == NULL) {
|
||||
*index = INVALID_ADDR_NUM;
|
||||
cache_env_unlock();
|
||||
return NULL;
|
||||
}
|
||||
UINT8 num = (cache_env->num_addr > MAX_DEVICE_IN_CACHE) ? MAX_DEVICE_IN_CACHE : cache_env->num_addr;
|
||||
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
|
||||
UINT8 *addr_data;
|
||||
@@ -695,30 +963,37 @@ UINT8* bta_gattc_co_cache_find_src_addr(BD_ADDR assoc_addr, UINT8 *index)
|
||||
addr_data = (UINT8 *)list_node(node);
|
||||
if (!memcmp(addr_data, assoc_addr, sizeof(BD_ADDR))) {
|
||||
*index = i;
|
||||
return (UINT8 *)addr_info->addr;
|
||||
UINT8 *ret = (UINT8 *)addr_info->addr;
|
||||
cache_env_unlock();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
addr_info++;
|
||||
}
|
||||
|
||||
*index = INVALID_ADDR_NUM;
|
||||
cache_env_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOLEAN bta_gattc_co_cache_clear_assoc_addr(BD_ADDR src_addr)
|
||||
{
|
||||
cache_env_lock();
|
||||
UINT8 addr_index = 0;
|
||||
cache_addr_info_t *addr_info;
|
||||
if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
|
||||
addr_info = &cache_env->cache_addr[addr_index];
|
||||
if (addr_info->assoc_addr != NULL) {
|
||||
list_clear(addr_info->assoc_addr);
|
||||
cache_env_unlock();
|
||||
return TRUE;
|
||||
} else {
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cache_env_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -491,6 +491,12 @@ static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
|
||||
return "BTA_GATTC_API_READ_BY_TYPE_EVT";
|
||||
case BTA_GATTC_API_READ_MULTI_VAR_EVT:
|
||||
return "BTA_GATTC_API_READ_MULTI_VAR_EVT";
|
||||
case BTA_GATTC_ENC_CMPL_EVT:
|
||||
return "BTA_GATTC_ENC_CMPL_EVT";
|
||||
case BTA_GATTC_API_CACHE_ASSOC_EVT:
|
||||
return "BTA_GATTC_API_CACHE_ASSOC_EVT";
|
||||
case BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT:
|
||||
return "BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT";
|
||||
default:
|
||||
return "unknown GATTC event code";
|
||||
}
|
||||
@@ -541,7 +547,8 @@ uint8_t bta_gattc_cl_rcb_active_count(void)
|
||||
|
||||
for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i ++) {
|
||||
if (bta_gattc_cb.cl_rcb[i].in_use &&
|
||||
memcmp(bta_gattc_cb.cl_rcb[i].app_uuid.uu.uuid128, dm_gattc_uuid, 16)) {
|
||||
(bta_gattc_cb.cl_rcb[i].app_uuid.len != LEN_UUID_128 ||
|
||||
memcmp(bta_gattc_cb.cl_rcb[i].app_uuid.uu.uuid128, dm_gattc_uuid, LEN_UUID_128))) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +154,12 @@ tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_conn_id (UINT16 conn_id)
|
||||
tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
|
||||
UINT8 i;
|
||||
|
||||
if (conn_id == 0 || conn_id == GATT_INVALID_CONN_ID) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++) {
|
||||
if (p_clcb->in_use &&
|
||||
p_clcb->bta_conn_id == conn_id) {
|
||||
if (p_clcb->in_use && p_clcb->bta_conn_id == conn_id) {
|
||||
return p_clcb;
|
||||
}
|
||||
}
|
||||
@@ -342,7 +345,7 @@ tBTA_GATTC_SERV *bta_gattc_find_srvr_cache(BD_ADDR bda)
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++) {
|
||||
if (bdcmp(p_srcb->server_bda, bda) == 0) {
|
||||
if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0) {
|
||||
return p_srcb;
|
||||
}
|
||||
}
|
||||
@@ -387,7 +390,7 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda)
|
||||
if (!p_tcb->in_use) {
|
||||
found = TRUE;
|
||||
break;
|
||||
} else if (!p_tcb->connected) {
|
||||
} else if (!p_tcb->connected && p_tcb->num_clcb == 0) {
|
||||
p_recycle = p_tcb;
|
||||
}
|
||||
}
|
||||
@@ -417,6 +420,38 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda)
|
||||
return p_tcb;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Fixed-length prefix size of a GATTC API message in the heap buffer passed
|
||||
* to bta_gattc_enqueue. Must match osi_malloc sizes in bta_gattc_api.c.
|
||||
* Variable payloads (write value, search UUID) are copied separately.
|
||||
*
|
||||
******************************************************************************/
|
||||
static size_t bta_gattc_enqueue_api_fixed_size(UINT16 event)
|
||||
{
|
||||
switch (event) {
|
||||
case BTA_GATTC_API_READ_EVT:
|
||||
case BTA_GATTC_API_READ_BY_TYPE_EVT:
|
||||
return sizeof(tBTA_GATTC_API_READ);
|
||||
case BTA_GATTC_API_WRITE_EVT:
|
||||
return sizeof(tBTA_GATTC_API_WRITE);
|
||||
case BTA_GATTC_API_EXEC_EVT:
|
||||
return sizeof(tBTA_GATTC_API_EXEC);
|
||||
case BTA_GATTC_API_CFG_MTU_EVT:
|
||||
return sizeof(tBTA_GATTC_API_CFG_MTU);
|
||||
case BTA_GATTC_API_SEARCH_EVT:
|
||||
return sizeof(tBTA_GATTC_API_SEARCH);
|
||||
case BTA_GATTC_API_CONFIRM_EVT:
|
||||
return sizeof(tBTA_GATTC_API_CONFIRM);
|
||||
case BTA_GATTC_API_READ_MULTI_EVT:
|
||||
case BTA_GATTC_API_READ_MULTI_VAR_EVT:
|
||||
return sizeof(tBTA_GATTC_API_READ_MULTI);
|
||||
default:
|
||||
APPL_TRACE_ERROR("%s: unexpected event 0x%x", __func__, event);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOLEAN bta_gattc_has_prepare_command_in_queue(tBTA_GATTC_CLCB *p_clcb)
|
||||
{
|
||||
assert(p_clcb != NULL);
|
||||
@@ -485,14 +520,29 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
|
||||
if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) {
|
||||
len = p_data->api_write.len;
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len)) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA) + len);
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
|
||||
cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1);
|
||||
memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len);
|
||||
if (len > 0) {
|
||||
if (p_data->api_write.p_value == NULL) {
|
||||
APPL_TRACE_ERROR("%s(), write len=%u but p_value is NULL", __func__, len);
|
||||
return FALSE;
|
||||
}
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len)) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA) + len);
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_API_WRITE));
|
||||
cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1);
|
||||
memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len);
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
/* len == 0: no payload to copy; keep p_value NULL like BTA_GATTC_API_SEARCH_EVT without UUID */
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_API_WRITE));
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else if (p_data->hdr.event == BTA_GATTC_API_SEARCH_EVT) {
|
||||
/*
|
||||
@@ -547,7 +597,7 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(len)) != NULL) {
|
||||
memset(cmd_data, 0, len);
|
||||
/* Copy the structure */
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_API_SEARCH));
|
||||
/* Update pointer to point to the space after the structure */
|
||||
cmd_data->api_search.p_srvc_uuid = (tBT_UUID *)(cmd_data + 1);
|
||||
/* Copy the UUID data */
|
||||
@@ -561,16 +611,22 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
/* p_srvc_uuid is NULL, no extra space needed (search all services) */
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_API_SEARCH));
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
size_t copy_sz = bta_gattc_enqueue_api_fixed_size(p_data->hdr.event);
|
||||
if (copy_sz == 0) {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, unknown event for queue copy 0x%x.", __func__, __LINE__,
|
||||
p_data->hdr.event);
|
||||
return FALSE;
|
||||
}
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, copy_sz);
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
@@ -888,7 +944,10 @@ tBTA_GATTC_CONN *bta_gattc_conn_alloc(BD_ADDR remote_bda)
|
||||
#if BTA_GATT_DEBUG == TRUE
|
||||
APPL_TRACE_DEBUG("bta_gattc_conn_alloc: found conn_track[%d] available", i_conn);
|
||||
#endif
|
||||
p_conn->in_use = TRUE;
|
||||
p_conn->in_use = TRUE;
|
||||
p_conn->svc_change_descr_handle = 0;
|
||||
p_conn->write_remote_svc_change_ccc_in_progress = FALSE;
|
||||
p_conn->write_remote_svc_change_ccc_done = FALSE;
|
||||
bdcpy(p_conn->remote_bda, remote_bda);
|
||||
return p_conn;
|
||||
}
|
||||
@@ -956,6 +1015,9 @@ BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda)
|
||||
|
||||
if (p_conn != NULL) {
|
||||
p_conn->in_use = FALSE;
|
||||
p_conn->svc_change_descr_handle = 0;
|
||||
p_conn->write_remote_svc_change_ccc_in_progress = FALSE;
|
||||
p_conn->write_remote_svc_change_ccc_done = FALSE;
|
||||
memset(p_conn->remote_bda, 0, BD_ADDR_LEN);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -173,11 +173,12 @@ void bta_gatts_api_disable(tBTA_GATTS_CB *p_cb)
|
||||
void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_INT_START_IF *p_buf;
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
tBTA_GATT_STATUS status = BTA_GATT_OK;
|
||||
UINT8 i, first_unuse = 0xff;
|
||||
|
||||
memset(&cb_data, 0, sizeof(tBTA_GATTS));
|
||||
cb_data.reg_oper.server_if = BTA_GATTS_INVALID_IF;
|
||||
memcpy(&cb_data.reg_oper.uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
|
||||
|
||||
if (p_cb->enabled == FALSE) {
|
||||
bta_gatts_enable(p_cb);
|
||||
@@ -188,6 +189,7 @@ void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
if (gatt_uuid_compare(p_cb->rcb[i].app_uuid, p_msg->api_reg.app_uuid)) {
|
||||
APPL_TRACE_ERROR("application already registered.\n");
|
||||
status = BTA_GATT_DUP_REG;
|
||||
cb_data.reg_oper.server_if = p_cb->rcb[i].gatt_if;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -201,8 +203,6 @@ void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
}
|
||||
}
|
||||
|
||||
cb_data.reg_oper.server_if = BTA_GATTS_INVALID_IF;
|
||||
memcpy(&cb_data.reg_oper.uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
|
||||
if (first_unuse != 0xff) {
|
||||
APPL_TRACE_VERBOSE("register application first_unuse rcb_idx = %d", first_unuse);
|
||||
|
||||
@@ -274,7 +274,8 @@ void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
tBTA_GATT_STATUS status = BTA_GATT_ERROR;
|
||||
tBTA_GATTS_CBACK *p_cback = NULL;
|
||||
UINT8 i;
|
||||
tBTA_GATTS cb_data;
|
||||
UINT8 j;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
|
||||
cb_data.reg_oper.server_if = p_msg->api_dereg.server_if;
|
||||
cb_data.reg_oper.status = status;
|
||||
@@ -287,6 +288,12 @@ void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
/* deregister the app */
|
||||
GATT_Deregister(p_cb->rcb[i].gatt_if);
|
||||
|
||||
for (j = 0; j < BTA_GATTS_MAX_SRVC_NUM; j ++) {
|
||||
if (p_cb->srvc_cb[j].in_use && p_cb->srvc_cb[j].rcb_idx == i) {
|
||||
memset(&p_cb->srvc_cb[j], 0, sizeof(tBTA_GATTS_SRVC_CB));
|
||||
}
|
||||
}
|
||||
|
||||
/* reset cb */
|
||||
memset(&p_cb->rcb[i], 0, sizeof(tBTA_GATTS_RCB));
|
||||
cb_data.reg_oper.status = status;
|
||||
@@ -323,6 +330,16 @@ void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
APPL_TRACE_DEBUG("create service rcb_idx = %d", rcb_idx);
|
||||
|
||||
if (rcb_idx != BTA_GATTS_INVALID_APP) {
|
||||
/*
|
||||
* Populate callback data with the request context early so the app can
|
||||
* identify which create-service request failed even if resource
|
||||
* allocation fails before we call into GATT.
|
||||
*/
|
||||
cb_data.create.server_if = p_cb->rcb[rcb_idx].gatt_if;
|
||||
cb_data.create.is_primary = p_msg->api_create_svc.is_pri;
|
||||
memcpy(&cb_data.create.uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
|
||||
cb_data.create.svc_instance = p_msg->api_create_svc.inst;
|
||||
|
||||
if ((srvc_idx = bta_gatts_alloc_srvc_cb(p_cb, rcb_idx)) != BTA_GATTS_INVALID_APP) {
|
||||
/* create the service now */
|
||||
service_id = GATTS_CreateService (p_cb->rcb[rcb_idx].gatt_if,
|
||||
@@ -345,7 +362,7 @@ void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
|
||||
cb_data.create.server_if = p_cb->rcb[rcb_idx].gatt_if;
|
||||
} else {
|
||||
cb_data.status = BTA_GATT_ERROR;
|
||||
cb_data.create.server_if = p_cb->rcb[rcb_idx].gatt_if;
|
||||
memset(&p_cb->srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
|
||||
APPL_TRACE_ERROR("service creation failed.");
|
||||
}
|
||||
@@ -374,7 +391,7 @@ void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
UINT16 attr_id = 0;
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
|
||||
attr_id = GATTS_AddIncludeService(p_msg->api_add_incl_srvc.hdr.layer_specific,
|
||||
p_msg->api_add_incl_srvc.included_service_id);
|
||||
@@ -406,7 +423,7 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
UINT16 attr_id = 0;
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
|
||||
tGATT_ATTR_VAL *p_attr_val = NULL;
|
||||
tGATTS_ATTR_CONTROL *p_control = NULL;
|
||||
@@ -436,8 +453,9 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
} else {
|
||||
cb_data.add_result.status = BTA_GATT_ERROR;
|
||||
}
|
||||
if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){
|
||||
osi_free(p_attr_val->attr_val);
|
||||
if (p_msg->api_add_char.attr_val.attr_val != NULL) {
|
||||
osi_free(p_msg->api_add_char.attr_val.attr_val);
|
||||
p_msg->api_add_char.attr_val.attr_val = NULL;
|
||||
}
|
||||
|
||||
if (p_rcb->p_cback) {
|
||||
@@ -458,7 +476,7 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
UINT16 attr_id = 0;
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
tGATT_ATTR_VAL *p_attr_val = NULL;
|
||||
tGATTS_ATTR_CONTROL *p_control = NULL;
|
||||
|
||||
@@ -486,8 +504,9 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
} else {
|
||||
cb_data.add_result.status = BTA_GATT_ERROR;
|
||||
}
|
||||
if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){
|
||||
osi_free(p_attr_val->attr_val);
|
||||
if (p_msg->api_add_char_descr.attr_val.attr_val != NULL) {
|
||||
osi_free(p_msg->api_add_char_descr.attr_val.attr_val);
|
||||
p_msg->api_add_char_descr.attr_val.attr_val = NULL;
|
||||
}
|
||||
|
||||
if (p_rcb->p_cback) {
|
||||
@@ -509,7 +528,7 @@ void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
UINT16 service_id = p_srvc_cb->service_id;
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
tBTA_GATT_STATUS gatts_status;
|
||||
gatts_status = GATTS_SetAttributeValue(p_msg->api_set_val.hdr.layer_specific,
|
||||
p_msg->api_set_val.length,
|
||||
@@ -543,11 +562,27 @@ void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
|
||||
tGATT_STATUS bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value)
|
||||
{
|
||||
if (GATTS_GetAttributeValueInternal(attr_handle, length, value) == 0) {
|
||||
return 0;
|
||||
tGATT_STATUS status = GATTS_GetAttributeValueInternal(attr_handle, length, value);
|
||||
if (status == GATT_SUCCESS) {
|
||||
return GATT_SUCCESS;
|
||||
}
|
||||
|
||||
return GATTS_GetAttributeValue(attr_handle, length, value);
|
||||
/*
|
||||
* Only fall back to the service database when the handle is not part of
|
||||
* internal GAP/GATT services. For any other internal read error, preserve
|
||||
* the original status to avoid masking failures as "success with len=0".
|
||||
*/
|
||||
if (status != GATT_NOT_FOUND) {
|
||||
if (length) {
|
||||
*length = 0;
|
||||
}
|
||||
if (value) {
|
||||
*value = NULL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
return GATTS_GetAttributeValue(attr_handle, length, value);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -562,10 +597,10 @@ tGATT_STATUS bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8
|
||||
void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
|
||||
cb_data.srvc_oper.server_if = p_rcb->gatt_if;
|
||||
cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
|
||||
cb_data.srvc_oper.service_id = p_srvc_cb->service_id;
|
||||
|
||||
if (GATTS_DeleteService(p_rcb->gatt_if,
|
||||
&p_srvc_cb->service_uuid,
|
||||
@@ -574,6 +609,12 @@ void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
|
||||
} else {
|
||||
cb_data.srvc_oper.status = BTA_GATT_ERROR;
|
||||
/*
|
||||
* GATTS_DeleteService() only fails when the service (or app registration)
|
||||
* cannot be found in the stack. Keeping srvc_cb "in_use" would permanently
|
||||
* leak a slot and eventually prevent creating new services.
|
||||
*/
|
||||
memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
|
||||
}
|
||||
|
||||
if (p_rcb->p_cback) {
|
||||
@@ -593,10 +634,10 @@ void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
|
||||
cb_data.srvc_oper.server_if = p_rcb->gatt_if;
|
||||
cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
|
||||
cb_data.srvc_oper.service_id = p_srvc_cb->service_id;
|
||||
|
||||
if (GATTS_StartService(p_rcb->gatt_if,
|
||||
p_srvc_cb->service_id,
|
||||
@@ -624,7 +665,7 @@ void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_m
|
||||
void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
UNUSED(p_msg);
|
||||
|
||||
GATTS_StopService(p_srvc_cb->service_id);
|
||||
@@ -651,14 +692,65 @@ void bta_gatts_send_rsp (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
UNUSED(p_cb);
|
||||
|
||||
if (GATTS_SendRsp (p_msg->api_rsp.hdr.layer_specific,
|
||||
p_msg->api_rsp.trans_id,
|
||||
p_msg->api_rsp.status,
|
||||
(tGATTS_RSP *)p_msg->api_rsp.p_rsp) != GATT_SUCCESS) {
|
||||
APPL_TRACE_ERROR("Sending response failed\n");
|
||||
tGATT_STATUS ret = GATTS_SendRsp(p_msg->api_rsp.hdr.layer_specific,
|
||||
p_msg->api_rsp.trans_id,
|
||||
p_msg->api_rsp.status,
|
||||
(tGATTS_RSP *)p_msg->api_rsp.p_rsp);
|
||||
if (ret == GATT_CONGESTED) {
|
||||
APPL_TRACE_WARNING("%s: rsp ok but congested", __func__);
|
||||
} else if (ret != GATT_SUCCESS) {
|
||||
APPL_TRACE_ERROR("%s: send rsp fail 0x%02x", __func__, ret);
|
||||
}
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_gatts_send_conf_evt_to_app
|
||||
**
|
||||
** Description Build a BTA_GATTS_CONF_EVT and dispatch it to the application
|
||||
** via the supplied RCB callback. The RCB callback is
|
||||
** btc_gatts_inter_cb (registered by BTA_GATTS_AppRegister), which
|
||||
** internally posts to the BTC task via btc_transfer_context, so
|
||||
** delivery is asynchronous w.r.t. the BTA task.
|
||||
**
|
||||
** If |value| is non-NULL and |value_len| > 0, the buffer is
|
||||
** duplicated for the duration of the callback and freed before
|
||||
** this helper returns. On allocation failure the callback is
|
||||
** still dispatched with value=NULL/data_len=0 so the application
|
||||
** does not stall waiting for CONF_EVT.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void bta_gatts_send_conf_evt_to_app(tBTA_GATTS_RCB *p_rcb,
|
||||
UINT16 conn_id, UINT16 handle,
|
||||
tBTA_GATT_STATUS status,
|
||||
const UINT8 *value, UINT16 value_len)
|
||||
{
|
||||
if (p_rcb == NULL || p_rcb->p_cback == NULL) {
|
||||
return;
|
||||
}
|
||||
tBTA_GATTS cb_data = {0};
|
||||
cb_data.req_data.status = status;
|
||||
cb_data.req_data.conn_id = conn_id;
|
||||
cb_data.req_data.handle = handle;
|
||||
cb_data.req_data.value = NULL;
|
||||
cb_data.req_data.data_len = 0;
|
||||
if (value != NULL && value_len > 0) {
|
||||
cb_data.req_data.value = (uint8_t *)osi_malloc(value_len);
|
||||
if (cb_data.req_data.value != NULL) {
|
||||
memcpy(cb_data.req_data.value, value, value_len);
|
||||
cb_data.req_data.data_len = value_len;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s, malloc(%u) failed", __func__, (unsigned)value_len);
|
||||
}
|
||||
}
|
||||
(*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
|
||||
if (cb_data.req_data.value != NULL) {
|
||||
osi_free(cb_data.req_data.value);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_gatts_indicate_handle
|
||||
@@ -672,71 +764,108 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_SRVC_CB *p_srvc_cb;
|
||||
tBTA_GATTS_RCB *p_rcb = NULL;
|
||||
tBTA_GATTS_RCB *p_srvc_rcb = NULL;
|
||||
tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
|
||||
tGATT_IF gatt_if;
|
||||
BD_ADDR remote_bda;
|
||||
tBTA_TRANSPORT transport;
|
||||
tBTA_GATTS cb_data;
|
||||
|
||||
p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);
|
||||
|
||||
if (p_srvc_cb ) {
|
||||
p_srvc_rcb = &p_cb->rcb[p_srvc_cb->rcb_idx];
|
||||
|
||||
if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific,
|
||||
&gatt_if, remote_bda, &transport)) {
|
||||
p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
|
||||
|
||||
if (p_msg->api_indicate.need_confirm) {
|
||||
|
||||
status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
|
||||
p_msg->api_indicate.attr_id,
|
||||
p_msg->api_indicate.len,
|
||||
p_msg->api_indicate.value);
|
||||
if (p_rcb != p_srvc_rcb) {
|
||||
if (p_rcb == NULL) {
|
||||
APPL_TRACE_ERROR("%s: no RCB for gatt_if %d", __func__, gatt_if);
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s: if mismatch svc owner", __func__);
|
||||
}
|
||||
if (!p_msg->api_indicate.need_confirm) {
|
||||
l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTU_NUM, NULL);
|
||||
}
|
||||
status = BTA_GATT_ILLEGAL_PARAMETER;
|
||||
} else {
|
||||
l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTU_NUM, NULL);
|
||||
status = GATTS_HandleValueNotification (p_msg->api_indicate.hdr.layer_specific,
|
||||
p_msg->api_indicate.attr_id,
|
||||
p_msg->api_indicate.len,
|
||||
p_msg->api_indicate.value);
|
||||
}
|
||||
|
||||
if (p_msg->api_indicate.need_confirm) {
|
||||
|
||||
status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
|
||||
p_msg->api_indicate.attr_id,
|
||||
p_msg->api_indicate.len,
|
||||
p_msg->api_indicate.value);
|
||||
} else {
|
||||
l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTU_NUM, NULL);
|
||||
status = GATTS_HandleValueNotification (p_msg->api_indicate.hdr.layer_specific,
|
||||
p_msg->api_indicate.attr_id,
|
||||
p_msg->api_indicate.len,
|
||||
p_msg->api_indicate.value);
|
||||
}
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
/* if over BR_EDR, inform PM for mode change */
|
||||
if (transport == BTA_TRANSPORT_BR_EDR) {
|
||||
bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
|
||||
bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
|
||||
}
|
||||
/* if over BR_EDR, inform PM for mode change */
|
||||
if (transport == BTA_TRANSPORT_BR_EDR) {
|
||||
bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
|
||||
bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
|
||||
}
|
||||
#endif // #if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_ERROR("Unknown connection ID: %d fail sending notification",
|
||||
p_msg->api_indicate.hdr.layer_specific);
|
||||
if (!p_msg->api_indicate.need_confirm) {
|
||||
l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTU_NUM, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) &&
|
||||
p_rcb && p_cb->rcb[p_srvc_cb->rcb_idx].p_cback) {
|
||||
cb_data.req_data.status = status;
|
||||
cb_data.req_data.conn_id = p_msg->api_indicate.hdr.layer_specific;
|
||||
cb_data.req_data.value = NULL;
|
||||
cb_data.req_data.data_len = 0;
|
||||
cb_data.req_data.handle = p_msg->api_indicate.attr_id;
|
||||
|
||||
if (p_msg->api_indicate.len > 0) {
|
||||
cb_data.req_data.value = (uint8_t *) osi_malloc(p_msg->api_indicate.len);
|
||||
if (cb_data.req_data.value != NULL) {
|
||||
memset(cb_data.req_data.value, 0, p_msg->api_indicate.len);
|
||||
cb_data.req_data.data_len = p_msg->api_indicate.len;
|
||||
memcpy(cb_data.req_data.value, p_msg->api_indicate.value, p_msg->api_indicate.len);
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s, malloc failed", __func__);
|
||||
}
|
||||
}
|
||||
(*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
|
||||
if (cb_data.req_data.value != NULL) {
|
||||
osi_free(cb_data.req_data.value);
|
||||
cb_data.req_data.value = NULL;
|
||||
}
|
||||
if (status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) {
|
||||
/* BTA_GATTS_CONF_EVT must be delivered to the application that
|
||||
* initiated the indicate/notify, i.e. the owner of the connection
|
||||
* (p_rcb resolved from conn_id's gatt_if). Fall back to the
|
||||
* service-owning RCB only when the conn_id could not be resolved
|
||||
* (link already torn down) so the application does not stall
|
||||
* waiting for CONF_EVT. */
|
||||
tBTA_GATTS_RCB *p_target_rcb = (p_rcb != NULL) ? p_rcb : p_srvc_rcb;
|
||||
bta_gatts_send_conf_evt_to_app(p_target_rcb,
|
||||
p_msg->api_indicate.hdr.layer_specific,
|
||||
p_msg->api_indicate.attr_id,
|
||||
status,
|
||||
p_msg->api_indicate.value,
|
||||
p_msg->api_indicate.len);
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_ERROR("Not a registered service attribute ID: 0x%04x",
|
||||
p_msg->api_indicate.attr_id);
|
||||
if (!p_msg->api_indicate.need_confirm) {
|
||||
/* Notifications increment the BTU counter in BTA_GATTS_HandleValueIndication();
|
||||
* indications do not. So only balance the counter on the notification path. */
|
||||
l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTU_NUM, NULL);
|
||||
} else {
|
||||
/* Indication path: the application is waiting for BTA_GATTS_CONF_EVT to know
|
||||
* the request is finished. Make a best-effort attempt to deliver an error event
|
||||
* so the app does not stall. Do NOT touch the BTU counter here, since indications
|
||||
* never incremented it. */
|
||||
if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific,
|
||||
&gatt_if, remote_bda, &transport)) {
|
||||
p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
|
||||
if (p_rcb && p_rcb->p_cback) {
|
||||
bta_gatts_send_conf_evt_to_app(p_rcb,
|
||||
p_msg->api_indicate.hdr.layer_specific,
|
||||
p_msg->api_indicate.attr_id,
|
||||
BTA_GATT_ILLEGAL_PARAMETER,
|
||||
NULL, 0);
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s: no RCB if=%d, drop CONF", __func__, gatt_if);
|
||||
}
|
||||
} else {
|
||||
/* conn_id is invalid (e.g. link already torn down). We have no gatt_if, so we
|
||||
* cannot locate the owning RCB to deliver the callback. The application is
|
||||
* expected to clean up pending indications on BTA_GATTS_DISCONNECT_EVT. */
|
||||
APPL_TRACE_ERROR("%s: bad conn_id %d, drop CONF", __func__, p_msg->api_indicate.hdr.layer_specific);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,13 +1045,11 @@ static void bta_gatts_send_request_cback (UINT16 conn_id,
|
||||
UINT32 trans_id,
|
||||
tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data)
|
||||
{
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
tBTA_GATTS_RCB *p_rcb;
|
||||
tGATT_IF gatt_if;
|
||||
tBTA_GATT_TRANSPORT transport;
|
||||
|
||||
memset(&cb_data, 0 , sizeof(tBTA_GATTS));
|
||||
|
||||
if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda, &transport)) {
|
||||
p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
|
||||
|
||||
@@ -974,10 +1101,10 @@ static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
|
||||
gatt_if, conn_id, connected, reason);
|
||||
APPL_TRACE_DEBUG("bta_gatts_conn_cback bda :%02x-%02x-%02x-%02x-%02x-%02x ",
|
||||
bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
|
||||
/*
|
||||
bt_bdaddr_t bdaddr;
|
||||
bdcpy(bdaddr.address, bda);
|
||||
/*
|
||||
|
||||
if (connected)
|
||||
btif_debug_conn_state(bdaddr, BTIF_DEBUG_CONNECTED, GATT_CONN_UNKNOWN);
|
||||
else
|
||||
@@ -1033,7 +1160,7 @@ static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
|
||||
*******************************************************************************/
|
||||
static void bta_gatts_cong_cback (UINT16 conn_id, BOOLEAN congested)
|
||||
{
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATTS cb_data = {0};
|
||||
cb_data.congest.conn_id = conn_id;
|
||||
cb_data.congest.congested = congested;
|
||||
btc_congest_callback(&cb_data);
|
||||
|
||||
@@ -93,6 +93,7 @@ void BTA_GATTS_AppRegister(const tBT_UUID * p_app_uuid, tBTA_GATTS_CBACK *p_cbac
|
||||
}
|
||||
|
||||
if ((p_buf = (tBTA_GATTS_API_REG *) osi_malloc(sizeof(tBTA_GATTS_API_REG))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(*p_buf));
|
||||
p_buf->hdr.event = BTA_GATTS_API_REG_EVT;
|
||||
|
||||
if (p_app_uuid != NULL) {
|
||||
@@ -237,16 +238,23 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_u
|
||||
}
|
||||
|
||||
if(attr_val != NULL){
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
if(len != 0){
|
||||
p_buf->attr_val.attr_val = (uint8_t *)osi_malloc(len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, len);
|
||||
} else {
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
p_buf->attr_val.attr_max_len = 0;
|
||||
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
|
||||
if (attr_val->attr_max_len == 0) {
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
if (len != 0) {
|
||||
APPL_TRACE_WARNING("%s: max_len 0, drop len %u", __func__, len);
|
||||
}
|
||||
} else {
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
if(len != 0){
|
||||
p_buf->attr_val.attr_val = (uint8_t *)osi_malloc(len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, len);
|
||||
} else {
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
p_buf->attr_val.attr_max_len = 0;
|
||||
APPL_TRACE_ERROR("alloc fail %s", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,19 +307,27 @@ void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
|
||||
}
|
||||
|
||||
if(attr_val != NULL){
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
value_len = attr_val->attr_len;
|
||||
if (value_len != 0){
|
||||
p_buf->attr_val.attr_val = (uint8_t*)osi_malloc(value_len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, value_len);
|
||||
if (attr_val->attr_max_len == 0) {
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
value_len = attr_val->attr_len;
|
||||
if (value_len != 0) {
|
||||
APPL_TRACE_WARNING("%s: max_len 0, drop len %u", __func__, value_len);
|
||||
}
|
||||
else{
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
p_buf->attr_val.attr_max_len = 0;
|
||||
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
|
||||
} else {
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
value_len = attr_val->attr_len;
|
||||
if (value_len != 0){
|
||||
p_buf->attr_val.attr_val = (uint8_t*)osi_malloc(value_len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, value_len);
|
||||
}
|
||||
else{
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
p_buf->attr_val.attr_max_len = 0;
|
||||
APPL_TRACE_ERROR("alloc fail %s", __func__);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,8 +517,10 @@ void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
|
||||
memset(p_buf, 0, len);
|
||||
p_buf->hdr.event = BTA_GATTS_API_SET_ATTR_VAL_EVT;
|
||||
p_buf->hdr.layer_specific = attr_handle;
|
||||
p_buf->length = length;
|
||||
if(value != NULL){
|
||||
if (value == NULL) {
|
||||
p_buf->length = 0;
|
||||
} else {
|
||||
p_buf->length = length;
|
||||
if((p_buf->value = (UINT8 *)osi_malloc(length)) != NULL){
|
||||
memcpy(p_buf->value, value, length);
|
||||
} else {
|
||||
|
||||
@@ -132,6 +132,16 @@ BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
|
||||
if (p_srvc_cb != NULL) {
|
||||
bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
|
||||
} else {
|
||||
tBTA_GATTS_DATA *p_data = (tBTA_GATTS_DATA *)p_msg;
|
||||
if (p_msg->event == BTA_GATTS_API_ADD_CHAR_EVT &&
|
||||
p_data->api_add_char.attr_val.attr_val != NULL) {
|
||||
osi_free(p_data->api_add_char.attr_val.attr_val);
|
||||
p_data->api_add_char.attr_val.attr_val = NULL;
|
||||
} else if (p_msg->event == BTA_GATTS_API_ADD_DESCR_EVT &&
|
||||
p_data->api_add_char_descr.attr_val.attr_val != NULL) {
|
||||
osi_free(p_data->api_add_char_descr.attr_val.attr_val);
|
||||
p_data->api_add_char_descr.attr_val.attr_val = NULL;
|
||||
}
|
||||
APPL_TRACE_ERROR("service not created\n");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -211,6 +211,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BD_ADDR remote_bda;
|
||||
BOOLEAN erase_flash;
|
||||
} tBTA_GATTC_API_CACHE_REFRESH;
|
||||
|
||||
typedef struct {
|
||||
@@ -399,6 +400,8 @@ typedef struct {
|
||||
BOOLEAN in_use;
|
||||
BD_ADDR remote_bda;
|
||||
UINT16 svc_change_descr_handle;
|
||||
/* Tracks the in-flight internal write to the Service Changed CCC descriptor */
|
||||
BOOLEAN write_remote_svc_change_ccc_in_progress;
|
||||
BOOLEAN write_remote_svc_change_ccc_done;
|
||||
} tBTA_GATTC_CONN;
|
||||
|
||||
@@ -558,7 +561,7 @@ extern void bta_gattc_get_db_with_operation(UINT16 conn_id,
|
||||
extern void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, UINT16 *count);
|
||||
|
||||
extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
|
||||
extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
|
||||
extern tBTA_GATT_STATUS bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
|
||||
extern void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
|
||||
extern void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status);
|
||||
|
||||
|
||||
@@ -676,10 +676,17 @@ typedef union {
|
||||
add char : BTA_GATTS_ADD_CHAR_EVT
|
||||
add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
|
||||
tBAT_GATTS_ATTR_VAL_RESULT attr_val;
|
||||
tBTA_GATTS_REQ req_data;
|
||||
tBTA_GATTS_REQ req_data; /* BTA_GATTS_READ_EVT, BTA_GATTS_WRITE_EVT,
|
||||
BTA_GATTS_EXEC_WRITE_EVT, BTA_GATTS_MTU_EVT,
|
||||
BTA_GATTS_CONF_EVT (handle/value/data_len
|
||||
are carried here, not in `confirm`) */
|
||||
tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */
|
||||
tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */
|
||||
tBTA_GATTS_CONF confirm; /* BTA_GATTS_CONF_EVT callback data */
|
||||
tBTA_GATTS_CONF confirm; /* Deprecated: retained for source/ABI compatibility
|
||||
only. BTA_GATTS_CONF_EVT actually uses `req_data`
|
||||
because handle/value/data_len are required by the
|
||||
public API. Do NOT add new producers/consumers
|
||||
that read or write this member. */
|
||||
tBTA_GATTS_CLOSE close; /* BTA_GATTS_CLOSE_EVT callback data */
|
||||
tBTA_GATTS_OPEN open; /* BTA_GATTS_OPEN_EVT callback data */
|
||||
tBTA_GATTS_CANCEL_OPEN cancel_open; /* tBTA_GATTS_CANCEL_OPEN callback data */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -90,6 +90,17 @@ void btc_storage_save(void)
|
||||
}
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
static bool btc_storage_is_all_zeros(const void *buf, size_t len)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)buf;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (p[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bt_status_t _btc_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
|
||||
char *key,
|
||||
uint8_t key_type,
|
||||
@@ -158,33 +169,48 @@ static bt_status_t _btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
const char* name;
|
||||
const char *name;
|
||||
size_t expected_len;
|
||||
switch (key_type) {
|
||||
case BTM_LE_KEY_PENC:
|
||||
name = BTC_BLE_STORAGE_LE_KEY_PENC_STR;
|
||||
expected_len = sizeof(tBTM_LE_PENC_KEYS);
|
||||
break;
|
||||
case BTM_LE_KEY_PID:
|
||||
name = BTC_BLE_STORAGE_LE_KEY_PID_STR;
|
||||
expected_len = sizeof(tBTM_LE_PID_KEYS);
|
||||
break;
|
||||
case BTM_LE_KEY_PCSRK:
|
||||
name = BTC_BLE_STORAGE_LE_KEY_PCSRK_STR;
|
||||
expected_len = sizeof(tBTM_LE_PCSRK_KEYS);
|
||||
break;
|
||||
case BTM_LE_KEY_LENC:
|
||||
name = BTC_BLE_STORAGE_LE_KEY_LENC_STR;
|
||||
expected_len = sizeof(tBTM_LE_LENC_KEYS);
|
||||
break;
|
||||
case BTM_LE_KEY_LCSRK:
|
||||
name = BTC_BLE_STORAGE_LE_KEY_LCSRK_STR;
|
||||
expected_len = sizeof(tBTM_LE_LCSRK_KEYS);
|
||||
break;
|
||||
case BTM_LE_KEY_LID:
|
||||
name = BTC_BLE_STORAGE_LE_KEY_LID_STR;
|
||||
/* LID is a flag-only key; no payload is persisted. */
|
||||
name = BTC_BLE_STORAGE_LE_KEY_LID_STR;
|
||||
expected_len = 0;
|
||||
break;
|
||||
default:
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
size_t length = key_length;
|
||||
int ret = btc_config_get_bin(bdstr, name, (uint8_t *)key_value, &length);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
|
||||
if (key_length < 0 || (size_t)key_length < expected_len) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
|
||||
size_t length = (size_t)key_length;
|
||||
bool ret = btc_config_get_bin(bdstr, name, (uint8_t *)key_value, &length);
|
||||
if (!ret || length != expected_len) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
|
||||
@@ -237,17 +263,22 @@ static bt_status_t _btc_storage_remove_all_ble_keys(const char *name)
|
||||
void btc_storage_remove_unused_sections(uint8_t *cur_addr, tBTM_LE_PID_KEYS *del_pid_key)
|
||||
{
|
||||
bt_bdaddr_t bd_addr;
|
||||
uint32_t device_type = 0;
|
||||
|
||||
if (del_pid_key == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only use valid static address for de-duplication.
|
||||
if (btc_storage_is_all_zeros(del_pid_key->static_addr, sizeof(del_pid_key->static_addr))) {
|
||||
return;
|
||||
}
|
||||
|
||||
btc_config_lock();
|
||||
|
||||
const btc_config_section_iter_t *iter = btc_config_section_begin();
|
||||
|
||||
while (iter != btc_config_section_end()) {
|
||||
uint32_t device_type = 0;
|
||||
//store the next iter, if remove section, then will not loss the point
|
||||
|
||||
const char *section = btc_config_section_name(iter);
|
||||
@@ -276,13 +307,19 @@ void btc_storage_remove_unused_sections(uint8_t *cur_addr, tBTM_LE_PID_KEYS *del
|
||||
|
||||
char buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0};
|
||||
|
||||
if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PID, buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS) {
|
||||
size_t pid_len = sizeof(tBTM_LE_PID_KEYS);
|
||||
bool pid_ok = btc_config_get_bin(section, BTC_BLE_STORAGE_LE_KEY_PID_STR, (uint8_t *)buffer, &pid_len);
|
||||
|
||||
if (pid_ok && pid_len >= sizeof(tBTM_LE_PID_KEYS)) {
|
||||
|
||||
tBTM_LE_PID_KEYS *pid_key = (tBTM_LE_PID_KEYS *) buffer;
|
||||
|
||||
iter = btc_config_section_next(iter);
|
||||
|
||||
if (memcmp(del_pid_key->static_addr, pid_key->static_addr, 6) == 0 && memcmp(cur_addr, bd_addr.address, 6) != 0 && del_pid_key->addr_type == pid_key->addr_type) {
|
||||
if (del_pid_key->addr_type == pid_key->addr_type &&
|
||||
!btc_storage_is_all_zeros(pid_key->static_addr, sizeof(pid_key->static_addr)) &&
|
||||
memcmp(del_pid_key->static_addr, pid_key->static_addr, sizeof(pid_key->static_addr)) == 0 &&
|
||||
memcmp(cur_addr, bd_addr.address, sizeof(bd_addr.address)) != 0) {
|
||||
if (device_type == BT_DEVICE_TYPE_DUMO) {
|
||||
btc_config_set_int(section, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR);
|
||||
_btc_storage_remove_all_ble_keys(section);
|
||||
@@ -308,13 +345,13 @@ void btc_storage_delete_duplicate_ble_devices(void)
|
||||
char temp_buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0};
|
||||
tBTM_LE_PID_KEYS *pid_key;
|
||||
tBTM_LE_PID_KEYS *temp_pid_key;
|
||||
uint32_t device_type = 0;
|
||||
|
||||
bt_bdaddr_t temp_bd_addr;
|
||||
|
||||
btc_config_lock();
|
||||
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
|
||||
iter = btc_config_section_next(iter)) {
|
||||
uint32_t device_type = 0;
|
||||
const char *name = btc_config_section_name(iter);
|
||||
|
||||
if (!string_is_bdaddr(name) ||
|
||||
@@ -324,27 +361,36 @@ void btc_storage_delete_duplicate_ble_devices(void)
|
||||
}
|
||||
|
||||
string_to_bdaddr(name, &bd_addr);
|
||||
if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PID, buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS)
|
||||
size_t pid_len = sizeof(tBTM_LE_PID_KEYS);
|
||||
bool pid_ok = btc_config_get_bin(name, BTC_BLE_STORAGE_LE_KEY_PID_STR, (uint8_t *)buffer, &pid_len);
|
||||
if (pid_ok && pid_len >= sizeof(tBTM_LE_PID_KEYS))
|
||||
{
|
||||
pid_key = (tBTM_LE_PID_KEYS *) buffer;
|
||||
if (btc_storage_is_all_zeros(pid_key->static_addr, sizeof(pid_key->static_addr))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const btc_config_section_iter_t *temp_iter = btc_config_section_next(iter);
|
||||
while (temp_iter != NULL)
|
||||
{
|
||||
uint32_t temp_device_type = 0;
|
||||
const char *temp_name = btc_config_section_name(temp_iter);
|
||||
if (!string_is_bdaddr(temp_name) || !btc_config_get_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) ||
|
||||
((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
|
||||
if (!string_is_bdaddr(temp_name) || !btc_config_get_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&temp_device_type) ||
|
||||
((temp_device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
|
||||
temp_iter = btc_config_section_next(temp_iter);
|
||||
continue;
|
||||
}
|
||||
string_to_bdaddr(temp_name, &temp_bd_addr);
|
||||
if (_btc_storage_get_ble_bonding_key(&temp_bd_addr, BTM_LE_KEY_PID, temp_buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS)
|
||||
size_t temp_pid_len = sizeof(tBTM_LE_PID_KEYS);
|
||||
bool temp_pid_ok = btc_config_get_bin(temp_name, BTC_BLE_STORAGE_LE_KEY_PID_STR, (uint8_t *)temp_buffer, &temp_pid_len);
|
||||
if (temp_pid_ok && temp_pid_len >= sizeof(tBTM_LE_PID_KEYS))
|
||||
{
|
||||
temp_pid_key = (tBTM_LE_PID_KEYS *) temp_buffer;
|
||||
if (memcmp(pid_key->static_addr, temp_pid_key->static_addr, 6) == 0 && pid_key->addr_type == temp_pid_key->addr_type) {
|
||||
const char *temp_name = btc_config_section_name(temp_iter);
|
||||
if (pid_key->addr_type == temp_pid_key->addr_type &&
|
||||
!btc_storage_is_all_zeros(temp_pid_key->static_addr, sizeof(temp_pid_key->static_addr)) &&
|
||||
memcmp(pid_key->static_addr, temp_pid_key->static_addr, sizeof(pid_key->static_addr)) == 0) {
|
||||
temp_iter = btc_config_section_next(temp_iter);
|
||||
if (device_type == BT_DEVICE_TYPE_DUMO) {
|
||||
if (temp_device_type == BT_DEVICE_TYPE_DUMO) {
|
||||
btc_config_set_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR);
|
||||
_btc_storage_remove_all_ble_keys(temp_name);
|
||||
} else {
|
||||
@@ -484,9 +530,11 @@ static bt_status_t _btc_storage_get_ble_local_key(uint8_t key_type,
|
||||
}
|
||||
size_t length = key_length;
|
||||
|
||||
int ret = btc_config_get_bin(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, name, (uint8_t *)key_value, &length);
|
||||
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
bool ret = btc_config_get_bin(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, name, (uint8_t *)key_value, &length);
|
||||
if (!ret || length != (size_t)key_length) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bt_status_t btc_storage_get_ble_local_key(uint8_t key_type,
|
||||
@@ -905,8 +953,8 @@ static void _btc_read_le_key(const uint8_t key_type, const size_t key_len, bt_bd
|
||||
}
|
||||
bt_status_t _btc_storage_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add)
|
||||
{
|
||||
uint32_t device_type;
|
||||
int addr_type;
|
||||
uint32_t device_type = 0;
|
||||
int addr_type = BLE_ADDR_PUBLIC;
|
||||
bt_bdaddr_t bd_addr;
|
||||
BD_ADDR bta_bd_addr;
|
||||
bool device_added = false;
|
||||
@@ -1015,11 +1063,11 @@ bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev
|
||||
int btc_storage_get_num_ble_bond_devices(void)
|
||||
{
|
||||
int num_dev = 0;
|
||||
uint32_t device_type = 0;
|
||||
|
||||
btc_config_lock();
|
||||
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
|
||||
iter = btc_config_section_next(iter)) {
|
||||
uint32_t device_type = 0;
|
||||
const char *name = btc_config_section_name(iter);
|
||||
if (!string_is_bdaddr(name) ||
|
||||
!btc_config_get_int(name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) ||
|
||||
@@ -1037,18 +1085,30 @@ int btc_storage_get_num_ble_bond_devices(void)
|
||||
bt_status_t btc_storage_get_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
int ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t *)&len);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
bool ret;
|
||||
size_t length = len;
|
||||
|
||||
btc_config_lock();
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
|
||||
ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, &length);
|
||||
btc_config_unlock();
|
||||
|
||||
if (!ret || length != (size_t)len) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
|
||||
{
|
||||
int ret;
|
||||
bool ret;
|
||||
bdstr_t bdstr;
|
||||
btc_config_lock();
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
|
||||
ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t)len);
|
||||
if (ret) {
|
||||
_btc_storage_save();
|
||||
}
|
||||
btc_config_unlock();
|
||||
if (ret == false) {
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -1060,18 +1120,33 @@ bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8
|
||||
bt_status_t btc_storage_get_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
int ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t *)&len);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
bool ret;
|
||||
size_t length = len;
|
||||
|
||||
btc_config_lock();
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
|
||||
ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, &length);
|
||||
btc_config_unlock();
|
||||
|
||||
if (!ret || length != (size_t)len) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bt_status_t btc_storage_set_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
|
||||
{
|
||||
int ret;
|
||||
bool ret;
|
||||
bdstr_t bdstr;
|
||||
|
||||
btc_config_lock();
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
|
||||
ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t)len);
|
||||
if (ret) {
|
||||
_btc_storage_save();
|
||||
}
|
||||
btc_config_unlock();
|
||||
|
||||
if (ret == false) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
@@ -1084,9 +1159,11 @@ bt_status_t btc_storage_remove_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr)
|
||||
bool ret = true;
|
||||
bdstr_t bdstr;
|
||||
|
||||
btc_config_lock();
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
|
||||
ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR);
|
||||
btc_config_unlock();
|
||||
|
||||
if (ret == false) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
@@ -1099,9 +1176,11 @@ bt_status_t btc_storage_remove_gatt_db_hash(bt_bdaddr_t *remote_bd_addr)
|
||||
bool ret = true;
|
||||
bdstr_t bdstr;
|
||||
|
||||
btc_config_lock();
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
|
||||
ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR);
|
||||
btc_config_unlock();
|
||||
|
||||
if (ret == false) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
|
||||
@@ -277,6 +277,7 @@ bool btc_config_set_bin(const char *section, const char *key, const uint8_t *val
|
||||
|
||||
config_set_string(config, section, key, str, false);
|
||||
|
||||
memset(str, 0, length * 2 + 1);
|
||||
osi_free(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
|
||||
}
|
||||
|
||||
#if BLE_SMP_BOND_NVS_FLASH
|
||||
int addr_type;
|
||||
int addr_type = BLE_ADDR_PUBLIC;
|
||||
|
||||
if (btc_dm_cb.pairing_cb.ble.is_pid_key_rcvd) {
|
||||
// delete unused section in NVS
|
||||
|
||||
@@ -28,7 +28,7 @@ static void btc_ble_cte_callback(tBTM_BLE_CTE_EVENT event,
|
||||
{
|
||||
esp_ble_cte_cb_param_t param = {0};
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLE_CTE;
|
||||
|
||||
@@ -42,7 +42,7 @@ static void btc_ble_cte_callback(tBTM_BLE_CTE_EVENT event,
|
||||
break;
|
||||
case BTA_BLE_CTE_SET_TRANS_ENABLE_EVT:
|
||||
msg.act = ESP_BLE_CTE_SET_CONNLESS_TRANS_ENABLE_CMPL_EVT;
|
||||
param.set_trans_enable_cmpl.status = btc_btm_status_to_esp_status(params->cte_trans_params_cmpl.status);
|
||||
param.set_trans_enable_cmpl.status = btc_btm_status_to_esp_status(params->cte_trans_en_cmpl.status);
|
||||
break;
|
||||
case BTA_BLE_CTE_SET_IQ_SAMP_ENABLE_EVT:
|
||||
msg.act = ESP_BLE_CTE_SET_CONNLESS_IQ_SAMPLING_ENABLE_CMPL_EVT;
|
||||
@@ -100,6 +100,7 @@ static void btc_ble_cte_callback(tBTM_BLE_CTE_EVENT event,
|
||||
case BTA_BLE_CTE_CONN_IQ_REPORT_EVT:
|
||||
msg.act = ESP_BLE_CTE_CONN_IQ_REPORT_EVT;
|
||||
param.conn_iq_rpt.conn_handle = params->cte_conn_iq_rpt.conn_handle;
|
||||
param.conn_iq_rpt.rx_phy = params->cte_conn_iq_rpt.rx_phy;
|
||||
param.conn_iq_rpt.data_channel_idx = params->cte_conn_iq_rpt.data_channel_idx;
|
||||
param.conn_iq_rpt.rssi = params->cte_conn_iq_rpt.rssi;
|
||||
param.conn_iq_rpt.rssi_ant_id = params->cte_conn_iq_rpt.rssi_ant_id;
|
||||
@@ -163,6 +164,7 @@ void btc_ble_cte_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
dst->cte_trans_params.antenna_ids = NULL;
|
||||
}
|
||||
} else {
|
||||
dst->cte_trans_params.switching_pattern_len = 0;
|
||||
dst->cte_trans_params.antenna_ids = NULL;
|
||||
}
|
||||
break;
|
||||
@@ -177,6 +179,7 @@ void btc_ble_cte_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
} else {
|
||||
dst->cte_iq_sampling_en.switching_pattern_len = 0;
|
||||
dst->cte_iq_sampling_en.antenna_ids = NULL;
|
||||
}
|
||||
break;
|
||||
@@ -194,6 +197,7 @@ void btc_ble_cte_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
} else {
|
||||
dst->cte_recv_params.switching_pattern_len = 0;
|
||||
dst->cte_recv_params.antenna_ids = NULL;
|
||||
}
|
||||
break;
|
||||
@@ -208,6 +212,7 @@ void btc_ble_cte_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
} else {
|
||||
dst->cte_conn_trans_params.switching_pattern_len = 0;
|
||||
dst->cte_conn_trans_params.antenna_ids = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -490,7 +490,8 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params)
|
||||
tBLE_BD_ADDR peer_addr;
|
||||
esp_bt_status_t status = ESP_BT_STATUS_SUCCESS;
|
||||
if (!BLE_ISVALID_PARAM(ble_adv_params->adv_int_min, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX) ||
|
||||
!BLE_ISVALID_PARAM(ble_adv_params->adv_int_max, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX)) {
|
||||
!BLE_ISVALID_PARAM(ble_adv_params->adv_int_max, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX) ||
|
||||
ble_adv_params->adv_int_min > ble_adv_params->adv_int_max) {
|
||||
status = ESP_BT_STATUS_PARM_INVALID;
|
||||
BTC_TRACE_ERROR("Invalid advertisting interval parameters.\n");
|
||||
}
|
||||
@@ -563,7 +564,8 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params)
|
||||
BLE_ISVALID_PARAM(scan_params->own_addr_type, BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_RPA_RANDOM) &&
|
||||
BLE_ISVALID_PARAM(scan_params->scan_filter_policy, BLE_SCAN_FILTER_ALLOW_ALL, BLE_SCAN_FILTER_ALLOW_WLIST_RPA_DIR) &&
|
||||
BLE_ISVALID_PARAM(scan_params->scan_duplicate, BLE_SCAN_DUPLICATE_DISABLE, BLE_SCAN_DUPLICATE_MAX -1) &&
|
||||
(scan_params->scan_type == BTM_BLE_SCAN_MODE_ACTI || scan_params->scan_type == BTM_BLE_SCAN_MODE_PASS)) {
|
||||
(scan_params->scan_type == BTM_BLE_SCAN_MODE_ACTI || scan_params->scan_type == BTM_BLE_SCAN_MODE_PASS) &&
|
||||
scan_params->scan_window <= scan_params->scan_interval) {
|
||||
BTA_DmSetBleScanFilterParams(ESP_DEFAULT_GATT_IF, /*client_if*/
|
||||
scan_params->scan_interval,
|
||||
scan_params->scan_window,
|
||||
@@ -936,7 +938,7 @@ static void btc_read_ble_rssi_cmpl_callback(void *p_data)
|
||||
static void btc_ble_read_channel_map_callback(void *p_data)
|
||||
{
|
||||
tBTA_BLE_CH_MAP_RESULTS *result = (tBTA_BLE_CH_MAP_RESULTS *)p_data;
|
||||
esp_ble_gap_cb_param_t param;
|
||||
esp_ble_gap_cb_param_t param = {0};
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
@@ -1229,7 +1231,14 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
#if (BLE_50_EXTEND_SCAN_EN == TRUE)
|
||||
case BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT:
|
||||
msg.act = ESP_GAP_BLE_EXT_ADV_REPORT_EVT;
|
||||
memcpy(¶m.ext_adv_report.params, ¶ms->ext_adv_report, sizeof(esp_ble_gap_ext_adv_report_t));
|
||||
memcpy(¶m.ext_adv_report.params, ¶ms->ext_adv_report, sizeof(tBTM_BLE_EXT_ADV_REPORT));
|
||||
/* The source struct ends with a pointer (UINT8 *adv_data) while the destination
|
||||
* ends with a fixed array (uint8_t adv_data[251]). The memcpy above leaves the
|
||||
* raw pointer bytes at the start of adv_data[]. Clear it before copying the real
|
||||
* advertising payload to avoid leaking stale pointer bytes when adv_data is NULL
|
||||
* or adv_data_len is smaller than sizeof(void *). */
|
||||
memset(param.ext_adv_report.params.adv_data, 0,
|
||||
sizeof(param.ext_adv_report.params.adv_data));
|
||||
if (params->ext_adv_report.adv_data) {
|
||||
memcpy(param.ext_adv_report.params.adv_data,
|
||||
params->ext_adv_report.adv_data, params->ext_adv_report.adv_data_len);
|
||||
@@ -1483,7 +1492,6 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
case BTA_BLE_GAP_CS_READ_LOCAL_SUPP_CAPS_EVT:
|
||||
msg.act = ESP_GAP_BLE_CS_READ_LOCAL_SUPP_CAPS_EVT;
|
||||
param.cs_read_local_supp_caps.status = btc_btm_status_to_esp_status(params->cs_read_local_supp_caps.status);
|
||||
param.cs_read_local_supp_caps.conn_handle = params->cs_read_local_supp_caps.conn_handle;
|
||||
param.cs_read_local_supp_caps.num_config_supported = params->cs_read_local_supp_caps.num_config_supported;
|
||||
param.cs_read_local_supp_caps.max_consecutive_proc_supported = params->cs_read_local_supp_caps.max_consecutive_proc_supported;
|
||||
param.cs_read_local_supp_caps.num_ant_supported = params->cs_read_local_supp_caps.num_ant_supported;
|
||||
@@ -1648,12 +1656,12 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
void btc_dtm_tx_start_callback(void *p1)
|
||||
void btc_dtm_tx_start_callback(UINT8 *p1, UINT16 len)
|
||||
{
|
||||
UINT8 status;
|
||||
UINT8 *p;
|
||||
p = (UINT8*) p1;
|
||||
if (p1) {
|
||||
if (p1 && len >= 1) {
|
||||
STREAM_TO_UINT8(status, p);
|
||||
BTC_TRACE_DEBUG("DTM TX start, status 0x%x\n", status);
|
||||
esp_ble_gap_cb_param_t param;
|
||||
@@ -1675,13 +1683,13 @@ void btc_dtm_tx_start_callback(void *p1)
|
||||
}
|
||||
}
|
||||
|
||||
void btc_dtm_rx_start_callback(void *p1)
|
||||
void btc_dtm_rx_start_callback(UINT8 *p1, UINT16 len)
|
||||
{
|
||||
|
||||
UINT8 status;
|
||||
UINT8 *p;
|
||||
p = (UINT8*) p1;
|
||||
if (p1) {
|
||||
if (p1 && len >= 1) {
|
||||
STREAM_TO_UINT8(status, p);
|
||||
BTC_TRACE_DEBUG("DTM RX start, status 0x%x\n", status);
|
||||
esp_ble_gap_cb_param_t param;
|
||||
@@ -1705,13 +1713,13 @@ void btc_dtm_rx_start_callback(void *p1)
|
||||
#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
|
||||
#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
void btc_dtm_stop_callback(void *p1)
|
||||
void btc_dtm_stop_callback(UINT8 *p1, UINT16 len)
|
||||
{
|
||||
UINT8 status;
|
||||
UINT16 num_pkt;
|
||||
UINT8 *p;
|
||||
p = (UINT8*) p1;
|
||||
if (p1) {
|
||||
if (p1 && len >= 3) {
|
||||
STREAM_TO_UINT8(status, p);
|
||||
STREAM_TO_UINT16(num_pkt, p);
|
||||
BTC_TRACE_DEBUG("DTM stop, status 0x%x num_pkt %d\n", status, num_pkt);
|
||||
@@ -1876,6 +1884,13 @@ static void btc_ble_vendor_hci_event_callback(UINT8 subevt_code, UINT8 param_len
|
||||
btc_msg_t msg = {0};
|
||||
esp_ble_vendor_evt_param_t *evt_param = ¶m.vendor_hci_evt.param;
|
||||
bool copy_param = false;
|
||||
bool parse_ok = true;
|
||||
|
||||
if (param_len && params == NULL) {
|
||||
BTC_TRACE_WARNING("%s vendor evt NULL: sub=0x%02x len=%u",
|
||||
__func__, subevt_code, param_len);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
@@ -1887,6 +1902,12 @@ static void btc_ble_vendor_hci_event_callback(UINT8 subevt_code, UINT8 param_len
|
||||
switch (subevt_code) {
|
||||
case BLE_VENDOR_PDU_RECV_EVT:
|
||||
param.vendor_hci_evt.subevt_code = ESP_BLE_VENDOR_PDU_RECV_EVT;
|
||||
if (param_len < (UINT8)(1 + 1 + 1 + BD_ADDR_LEN)) {
|
||||
BTC_TRACE_WARNING("%s vendor trunc: sub=0x%02x len=%u<%u",
|
||||
__func__, subevt_code, param_len, (unsigned)(1 + 1 + 1 + BD_ADDR_LEN));
|
||||
parse_ok = false;
|
||||
break;
|
||||
}
|
||||
STREAM_TO_UINT8(evt_param->pdu_recv.type, params);
|
||||
STREAM_TO_UINT8(evt_param->pdu_recv.handle, params);
|
||||
STREAM_TO_UINT8(evt_param->pdu_recv.addr_type, params);
|
||||
@@ -1894,6 +1915,12 @@ static void btc_ble_vendor_hci_event_callback(UINT8 subevt_code, UINT8 param_len
|
||||
break;
|
||||
case BLE_VENDOR_CHMAP_UPDATE_EVT:
|
||||
param.vendor_hci_evt.subevt_code = ESP_BLE_VENDOR_CHAN_MAP_UPDATE_EVT;
|
||||
if (param_len < (UINT8)(1 + 2 + ESP_GAP_BLE_CHANNELS_LEN)) {
|
||||
BTC_TRACE_WARNING("%s vendor trunc: sub=0x%02x len=%u<%u",
|
||||
__func__, subevt_code, param_len, (unsigned)(1 + 2 + ESP_GAP_BLE_CHANNELS_LEN));
|
||||
parse_ok = false;
|
||||
break;
|
||||
}
|
||||
STREAM_TO_UINT8(evt_param->chan_map_update.status, params);
|
||||
STREAM_TO_UINT16(evt_param->chan_map_update.conn_handle, params);
|
||||
REVERSE_STREAM_TO_ARRAY(evt_param->chan_map_update.ch_map, params, ESP_GAP_BLE_CHANNELS_LEN);
|
||||
@@ -1907,6 +1934,17 @@ static void btc_ble_vendor_hci_event_callback(UINT8 subevt_code, UINT8 param_len
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parse_ok) {
|
||||
/* Malformed/truncated parameters: keep the mapped esp_ble_vendor_evt_t
|
||||
* already assigned in the switch (do NOT restore the raw HCI subevent
|
||||
* code, which is outside esp_ble_vendor_evt_t and would break the
|
||||
* public API contract). Zero the structured fields and suppress the
|
||||
* internal raw buffer so the callback delivers a deterministic event;
|
||||
* the truncation has already been logged above. */
|
||||
memset(evt_param, 0, sizeof(*evt_param));
|
||||
copy_param = false;
|
||||
}
|
||||
|
||||
if (copy_param) {
|
||||
param.vendor_hci_evt.param_len = param_len;
|
||||
param.vendor_hci_evt.param_buf = (param_len) ? params : NULL;
|
||||
@@ -2140,20 +2178,38 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *) p_dest;
|
||||
|
||||
if (src->cfg_adv_data.adv_data.p_manufacturer_data) {
|
||||
/* btc_transfer_context() does a shallow memcpy first; always null-out
|
||||
* pointer fields so deep_free() never frees non-owned memory on OOM. */
|
||||
dst->cfg_adv_data.adv_data.p_manufacturer_data = NULL;
|
||||
dst->cfg_adv_data.adv_data.p_service_data = NULL;
|
||||
dst->cfg_adv_data.adv_data.p_service_uuid = NULL;
|
||||
|
||||
if (src->cfg_adv_data.adv_data.p_manufacturer_data && src->cfg_adv_data.adv_data.manufacturer_len) {
|
||||
dst->cfg_adv_data.adv_data.p_manufacturer_data = osi_malloc(src->cfg_adv_data.adv_data.manufacturer_len);
|
||||
memcpy(dst->cfg_adv_data.adv_data.p_manufacturer_data, src->cfg_adv_data.adv_data.p_manufacturer_data,
|
||||
src->cfg_adv_data.adv_data.manufacturer_len);
|
||||
if (dst->cfg_adv_data.adv_data.p_manufacturer_data) {
|
||||
memcpy(dst->cfg_adv_data.adv_data.p_manufacturer_data, src->cfg_adv_data.adv_data.p_manufacturer_data,
|
||||
src->cfg_adv_data.adv_data.manufacturer_len);
|
||||
} else {
|
||||
BTC_TRACE_WARNING("%s no mem, manu drop %u", __func__, src->cfg_adv_data.adv_data.manufacturer_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (src->cfg_adv_data.adv_data.p_service_data) {
|
||||
if (src->cfg_adv_data.adv_data.p_service_data && src->cfg_adv_data.adv_data.service_data_len) {
|
||||
dst->cfg_adv_data.adv_data.p_service_data = osi_malloc(src->cfg_adv_data.adv_data.service_data_len);
|
||||
memcpy(dst->cfg_adv_data.adv_data.p_service_data, src->cfg_adv_data.adv_data.p_service_data, src->cfg_adv_data.adv_data.service_data_len);
|
||||
if (dst->cfg_adv_data.adv_data.p_service_data) {
|
||||
memcpy(dst->cfg_adv_data.adv_data.p_service_data, src->cfg_adv_data.adv_data.p_service_data, src->cfg_adv_data.adv_data.service_data_len);
|
||||
} else {
|
||||
BTC_TRACE_WARNING("%s no mem, svc_data drop %u", __func__, src->cfg_adv_data.adv_data.service_data_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (src->cfg_adv_data.adv_data.p_service_uuid) {
|
||||
if (src->cfg_adv_data.adv_data.p_service_uuid && src->cfg_adv_data.adv_data.service_uuid_len) {
|
||||
dst->cfg_adv_data.adv_data.p_service_uuid = osi_malloc(src->cfg_adv_data.adv_data.service_uuid_len);
|
||||
memcpy(dst->cfg_adv_data.adv_data.p_service_uuid, src->cfg_adv_data.adv_data.p_service_uuid, src->cfg_adv_data.adv_data.service_uuid_len);
|
||||
if (dst->cfg_adv_data.adv_data.p_service_uuid) {
|
||||
memcpy(dst->cfg_adv_data.adv_data.p_service_uuid, src->cfg_adv_data.adv_data.p_service_uuid, src->cfg_adv_data.adv_data.service_uuid_len);
|
||||
} else {
|
||||
BTC_TRACE_WARNING("%s no mem, svc_uuid drop %u", __func__, src->cfg_adv_data.adv_data.service_uuid_len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2161,10 +2217,13 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *) p_dest;
|
||||
|
||||
dst->cfg_adv_data_raw.raw_adv = NULL;
|
||||
dst->cfg_adv_data_raw.raw_adv_len = 0;
|
||||
if (src && src->cfg_adv_data_raw.raw_adv && src->cfg_adv_data_raw.raw_adv_len > 0) {
|
||||
dst->cfg_adv_data_raw.raw_adv = osi_malloc(src->cfg_adv_data_raw.raw_adv_len);
|
||||
if (dst->cfg_adv_data_raw.raw_adv) {
|
||||
memcpy(dst->cfg_adv_data_raw.raw_adv, src->cfg_adv_data_raw.raw_adv, src->cfg_adv_data_raw.raw_adv_len);
|
||||
dst->cfg_adv_data_raw.raw_adv_len = src->cfg_adv_data_raw.raw_adv_len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2173,10 +2232,13 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *) p_dest;
|
||||
|
||||
dst->cfg_scan_rsp_data_raw.raw_scan_rsp = NULL;
|
||||
dst->cfg_scan_rsp_data_raw.raw_scan_rsp_len = 0;
|
||||
if (src && src->cfg_scan_rsp_data_raw.raw_scan_rsp && src->cfg_scan_rsp_data_raw.raw_scan_rsp_len > 0) {
|
||||
dst->cfg_scan_rsp_data_raw.raw_scan_rsp = osi_malloc(src->cfg_scan_rsp_data_raw.raw_scan_rsp_len);
|
||||
if (dst->cfg_scan_rsp_data_raw.raw_scan_rsp) {
|
||||
memcpy(dst->cfg_scan_rsp_data_raw.raw_scan_rsp, src->cfg_scan_rsp_data_raw.raw_scan_rsp, src->cfg_scan_rsp_data_raw.raw_scan_rsp_len);
|
||||
dst->cfg_scan_rsp_data_raw.raw_scan_rsp_len = src->cfg_scan_rsp_data_raw.raw_scan_rsp_len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2187,6 +2249,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *) p_dest;
|
||||
uint8_t length = 0;
|
||||
dst->set_security_param.value = NULL;
|
||||
if (src->set_security_param.value) {
|
||||
length = dst->set_security_param.len;
|
||||
dst->set_security_param.value = osi_malloc(length);
|
||||
@@ -2194,6 +2257,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
memcpy(dst->set_security_param.value, src->set_security_param.value, length);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
dst->set_security_param.len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2202,6 +2266,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *) p_dest;
|
||||
uint8_t length = 0;
|
||||
dst->oob_req_reply.p_value = NULL;
|
||||
if (src->oob_req_reply.p_value) {
|
||||
length = dst->oob_req_reply.len;
|
||||
dst->oob_req_reply.p_value = osi_malloc(length);
|
||||
@@ -2209,6 +2274,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
memcpy(dst->oob_req_reply.p_value, src->oob_req_reply.p_value, length);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
dst->oob_req_reply.len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2216,6 +2282,8 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
case BTC_GAP_BLE_SC_OOB_REQ_REPLY_EVT: {
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *)p_dest;
|
||||
dst->sc_oob_req_reply.p_c = NULL;
|
||||
dst->sc_oob_req_reply.p_r = NULL;
|
||||
if (src->sc_oob_req_reply.p_c) {
|
||||
dst->sc_oob_req_reply.p_c = osi_malloc(BT_OCTET16_LEN);
|
||||
if (dst->sc_oob_req_reply.p_c) {
|
||||
@@ -2236,17 +2304,38 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
}
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
#if (BLE_50_EXTEND_ADV_EN == TRUE)
|
||||
case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW:
|
||||
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: {
|
||||
case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW: {
|
||||
btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src;
|
||||
btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest;
|
||||
uint16_t length = 0;
|
||||
|
||||
dst->ext_adv_cfg_data.data = NULL;
|
||||
dst->ext_adv_cfg_data.length = 0;
|
||||
if (src->ext_adv_cfg_data.data) {
|
||||
length = src->ext_adv_cfg_data.length;
|
||||
dst->ext_adv_cfg_data.data = osi_malloc(length);
|
||||
if (dst->ext_adv_cfg_data.data) {
|
||||
memcpy(dst->ext_adv_cfg_data.data, src->ext_adv_cfg_data.data, length);
|
||||
dst->ext_adv_cfg_data.length = length;
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: {
|
||||
btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src;
|
||||
btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest;
|
||||
uint16_t length = 0;
|
||||
|
||||
dst->cfg_scan_rsp.data = NULL;
|
||||
dst->cfg_scan_rsp.length = 0;
|
||||
if (src->cfg_scan_rsp.data) {
|
||||
length = src->cfg_scan_rsp.length;
|
||||
dst->cfg_scan_rsp.data = osi_malloc(length);
|
||||
if (dst->cfg_scan_rsp.data) {
|
||||
memcpy(dst->cfg_scan_rsp.data, src->cfg_scan_rsp.data, length);
|
||||
dst->cfg_scan_rsp.length = length;
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
@@ -2260,17 +2349,17 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest;
|
||||
uint16_t length = 0;
|
||||
|
||||
dst->periodic_adv_cfg_data.data = NULL;
|
||||
dst->periodic_adv_cfg_data.len = 0;
|
||||
if (src->periodic_adv_cfg_data.data) {
|
||||
length = src->periodic_adv_cfg_data.len;
|
||||
dst->periodic_adv_cfg_data.data = osi_malloc(length);
|
||||
if (dst->periodic_adv_cfg_data.data) {
|
||||
memcpy(dst->periodic_adv_cfg_data.data, src->periodic_adv_cfg_data.data, length);
|
||||
dst->periodic_adv_cfg_data.len = length;
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
} else {
|
||||
dst->periodic_adv_cfg_data.data = NULL;
|
||||
dst->periodic_adv_cfg_data.len = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2308,10 +2397,13 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: {
|
||||
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
|
||||
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *)p_dest;
|
||||
dst->vendor_cmd_send.p_param_buf = NULL;
|
||||
dst->vendor_cmd_send.param_len = 0;
|
||||
if (src->vendor_cmd_send.param_len) {
|
||||
dst->vendor_cmd_send.p_param_buf = osi_malloc(src->vendor_cmd_send.param_len);
|
||||
if (dst->vendor_cmd_send.p_param_buf) {
|
||||
memcpy(dst->vendor_cmd_send.p_param_buf, src->vendor_cmd_send.p_param_buf, src->vendor_cmd_send.param_len);
|
||||
dst->vendor_cmd_send.param_len = src->vendor_cmd_send.param_len;
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
@@ -2398,11 +2490,14 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
|
||||
switch (msg->act) {
|
||||
case ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT: {
|
||||
dst->vendor_cmd_cmpl.p_param_buf = NULL;
|
||||
dst->vendor_cmd_cmpl.param_len = 0;
|
||||
if (src->vendor_cmd_cmpl.param_len) {
|
||||
dst->vendor_cmd_cmpl.p_param_buf = osi_malloc(src->vendor_cmd_cmpl.param_len);
|
||||
if (dst->vendor_cmd_cmpl.p_param_buf) {
|
||||
memcpy(dst->vendor_cmd_cmpl.p_param_buf, src->vendor_cmd_cmpl.p_param_buf,
|
||||
src->vendor_cmd_cmpl.param_len);
|
||||
dst->vendor_cmd_cmpl.param_len = src->vendor_cmd_cmpl.param_len;
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s, malloc failed\n", __func__);
|
||||
}
|
||||
@@ -2410,11 +2505,14 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_VENDOR_HCI_EVT: {
|
||||
dst->vendor_hci_evt.param_buf = NULL;
|
||||
dst->vendor_hci_evt.param_len = 0;
|
||||
if (src->vendor_hci_evt.param_len) {
|
||||
dst->vendor_hci_evt.param_buf = osi_malloc(src->vendor_hci_evt.param_len);
|
||||
if (dst->vendor_hci_evt.param_buf) {
|
||||
memcpy(dst->vendor_hci_evt.param_buf, src->vendor_hci_evt.param_buf,
|
||||
src->vendor_hci_evt.param_len);
|
||||
dst->vendor_hci_evt.param_len = src->vendor_hci_evt.param_len;
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s, malloc failed\n", __func__);
|
||||
}
|
||||
@@ -2476,7 +2574,7 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s, pa_rsp_info, no enough memory.", __func__);
|
||||
BTC_TRACE_ERROR("%s, step_info, no enough memory.", __func__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2499,7 +2597,7 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s, pa_rsp_info, no enough memory.", __func__);
|
||||
BTC_TRACE_ERROR("%s, continue step_info, no enough memory.", __func__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2574,14 +2672,20 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg)
|
||||
}
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
#if (BLE_50_EXTEND_ADV_EN == TRUE)
|
||||
case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW:
|
||||
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: {
|
||||
case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW: {
|
||||
uint8_t *value = ((btc_ble_5_gap_args_t *)msg->arg)->ext_adv_cfg_data.data;
|
||||
if (value) {
|
||||
osi_free(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: {
|
||||
uint8_t *value = ((btc_ble_5_gap_args_t *)msg->arg)->cfg_scan_rsp.data;
|
||||
if (value) {
|
||||
osi_free(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE)
|
||||
#if (BLE_50_PERIODIC_ADV_EN == TRUE)
|
||||
case BTC_GAP_BLE_CFG_PERIODIC_ADV_DATA_RAW: {
|
||||
@@ -3033,9 +3137,9 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
|
||||
break;
|
||||
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW:
|
||||
BTC_TRACE_DEBUG("BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW");
|
||||
BTA_DmBleGapConfigExtAdvDataRaw(TRUE, arg_5->ext_adv_cfg_data.instance,
|
||||
arg_5->ext_adv_cfg_data.length,
|
||||
(const UINT8 *)arg_5->ext_adv_cfg_data.data);
|
||||
BTA_DmBleGapConfigExtAdvDataRaw(TRUE, arg_5->cfg_scan_rsp.instance,
|
||||
arg_5->cfg_scan_rsp.length,
|
||||
(const UINT8 *)arg_5->cfg_scan_rsp.data);
|
||||
break;
|
||||
case BTC_GAP_BLE_EXT_ADV_START: {
|
||||
BTC_TRACE_DEBUG("BTC_GAP_BLE_EXT_ADV_START");
|
||||
|
||||
@@ -203,7 +203,7 @@ static void btc_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
|
||||
|
||||
static void btc_gattc_app_register(btc_ble_gattc_args_t *arg)
|
||||
{
|
||||
tBT_UUID app_uuid;
|
||||
tBT_UUID app_uuid = {0};
|
||||
app_uuid.len = 2;
|
||||
app_uuid.uu.uuid16 = arg->app_reg.app_id;
|
||||
BTA_GATTC_AppRegister(&app_uuid, btc_gattc_cback);
|
||||
@@ -991,8 +991,6 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
case BTA_GATTC_CLOSE_EVT: {
|
||||
tBTA_GATTC_CLOSE *close = &arg->close;
|
||||
|
||||
// Free gattc clcb in BTC task to avoid race condition
|
||||
bta_gattc_clcb_dealloc_by_conn_id(close->conn_id);
|
||||
gattc_if = close->client_if;
|
||||
param.close.status = close->status;
|
||||
param.close.conn_id = BTC_GATT_GET_CONN_ID(close->conn_id);
|
||||
|
||||
@@ -244,7 +244,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
|
||||
{
|
||||
uint16_t uuid = 0;
|
||||
future_t *future_p;
|
||||
esp_ble_gatts_cb_param_t param;
|
||||
esp_ble_gatts_cb_param_t param = {0};
|
||||
param.add_attr_tab.status = ESP_GATT_OK;
|
||||
param.add_attr_tab.num_handle = max_nb_attr;
|
||||
|
||||
@@ -509,11 +509,43 @@ static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gat
|
||||
uint16_t uuid = 0;
|
||||
|
||||
for(int i = 0; i < max_nb_attr; i++) {
|
||||
if(gatts_attr_db[i].att_desc.uuid_length != ESP_UUID_LEN_16) {
|
||||
const esp_attr_desc_t *desc = &gatts_attr_db[i].att_desc;
|
||||
|
||||
/* Reject absurd attribute sizes regardless of row type. Mirrors the per-call
|
||||
* guard in esp_ble_gatts_add_char_desc_param_check() so that the attribute
|
||||
* table API enforces the same upper bound. */
|
||||
if (desc->max_length > ESP_GATT_MAX_ATTR_LEN ||
|
||||
desc->length > ESP_GATT_MAX_ATTR_LEN) {
|
||||
BTC_TRACE_ERROR("%s attr[%d] len %u/max %u>%u",
|
||||
__func__, i,
|
||||
(unsigned)desc->length,
|
||||
(unsigned)desc->max_length,
|
||||
(unsigned)ESP_GATT_MAX_ATTR_LEN);
|
||||
return ESP_GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
|
||||
/* When max_length is non-zero the row carries a stack-stored attribute
|
||||
* value: gatts_add_char_descr()/gatts_add_characteristic() will allocate
|
||||
* max_length bytes and memcpy length bytes into it. Reject length > max_length
|
||||
* here so the table API matches esp_ble_gatts_add_char_desc_param_check(),
|
||||
* fails fast with a clear error to the app, and also avoids the BTA-layer
|
||||
* out-of-bounds read in BTA_GATTS_AddCharDescriptor() when the caller's
|
||||
* source buffer is sized to max_length. Rows with max_length == 0 carry
|
||||
* declarations (service UUID, char property byte, include-service descriptor)
|
||||
* whose length is unrelated to max_length, so they are skipped. */
|
||||
if (desc->max_length != 0 && desc->length > desc->max_length) {
|
||||
BTC_TRACE_ERROR("%s attr[%d] len %u>max %u",
|
||||
__func__, i,
|
||||
(unsigned)desc->length,
|
||||
(unsigned)desc->max_length);
|
||||
return ESP_GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
|
||||
if(desc->uuid_length != ESP_UUID_LEN_16) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
|
||||
uuid = (desc->uuid_p[1] << 8) + (desc->uuid_p[0]);
|
||||
switch(uuid) {
|
||||
case ESP_GATT_UUID_PRI_SERVICE:
|
||||
case ESP_GATT_UUID_SEC_SERVICE:
|
||||
@@ -594,9 +626,56 @@ esp_gatt_status_t btc_gatts_show_local_database(void)
|
||||
return ESP_GATT_OK;
|
||||
}
|
||||
|
||||
/* BTA passes a pointer to the active tBTA_GATTS union member (often a small stack
|
||||
* object). Only copy that member's size — sizeof(tBTA_GATTS) would read past it. */
|
||||
static int btc_gatts_cb_event_param_len(tBTA_GATTS_EVT event)
|
||||
{
|
||||
switch (event) {
|
||||
case BTA_GATTS_REG_EVT:
|
||||
case BTA_GATTS_DEREG_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_REG_OPER);
|
||||
case BTA_GATTS_READ_EVT:
|
||||
case BTA_GATTS_WRITE_EVT:
|
||||
case BTA_GATTS_EXEC_WRITE_EVT:
|
||||
case BTA_GATTS_MTU_EVT:
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_REQ);
|
||||
case BTA_GATTS_CREATE_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_CREATE);
|
||||
case BTA_GATTS_ADD_INCL_SRVC_EVT:
|
||||
case BTA_GATTS_ADD_CHAR_EVT:
|
||||
case BTA_GATTS_ADD_CHAR_DESCR_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_ADD_RESULT);
|
||||
case BTA_GATTS_DELELTE_EVT:
|
||||
case BTA_GATTS_START_EVT:
|
||||
case BTA_GATTS_STOP_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_SRVC_OPER);
|
||||
case BTA_GATTS_SET_ATTR_VAL_EVT:
|
||||
return (int)sizeof(tBAT_GATTS_ATTR_VAL_RESULT);
|
||||
case BTA_GATTS_CONNECT_EVT:
|
||||
case BTA_GATTS_DISCONNECT_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_CONN);
|
||||
case BTA_GATTS_OPEN_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_OPEN);
|
||||
case BTA_GATTS_CANCEL_OPEN_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_CANCEL_OPEN);
|
||||
case BTA_GATTS_CLOSE_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_CLOSE);
|
||||
case BTA_GATTS_LISTEN_EVT:
|
||||
return (int)sizeof(tBTA_GATT_STATUS);
|
||||
case BTA_GATTS_CONGEST_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_CONGEST);
|
||||
case BTA_GATTS_SEND_SERVICE_CHANGE_EVT:
|
||||
return (int)sizeof(tBTA_GATTS_SERVICE_CHANGE);
|
||||
default:
|
||||
return (int)sizeof(tBTA_GATTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
uint16_t event = msg->act;
|
||||
int copy_len = btc_gatts_cb_event_param_len((tBTA_GATTS_EVT)event);
|
||||
|
||||
tBTA_GATTS *p_dest_data = (tBTA_GATTS *) p_dest;
|
||||
tBTA_GATTS *p_src_data = (tBTA_GATTS *) p_src;
|
||||
@@ -605,8 +684,7 @@ static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_sr
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy basic structure first
|
||||
memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
|
||||
memcpy(p_dest_data, p_src_data, (size_t)copy_len);
|
||||
|
||||
// Allocate buffer for request data if necessary
|
||||
switch (event) {
|
||||
@@ -622,6 +700,21 @@ static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_sr
|
||||
BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
|
||||
}
|
||||
break;
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
/* bta_gatts_indicate_handle frees req_data.value after returning from this
|
||||
* callback; duplicate the buffer so the queued BTC handler does not UAF. */
|
||||
if (p_src_data->req_data.value != NULL && p_src_data->req_data.data_len > 0) {
|
||||
p_dest_data->req_data.value = (uint8_t *)osi_malloc(p_src_data->req_data.data_len);
|
||||
if (p_dest_data->req_data.value != NULL) {
|
||||
memcpy(p_dest_data->req_data.value, p_src_data->req_data.value,
|
||||
p_src_data->req_data.data_len);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s CONF_EVT no mem", __func__);
|
||||
p_dest_data->req_data.value = NULL;
|
||||
p_dest_data->req_data.data_len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -643,6 +736,10 @@ static void btc_gatts_cb_param_copy_free(btc_msg_t *msg)
|
||||
}
|
||||
break;
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
if (p_data && p_data->req_data.value) {
|
||||
osi_free(p_data->req_data.value);
|
||||
p_data->req_data.value = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -709,7 +806,7 @@ static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
future_ready(btc_creat_tab_env.complete_future, result);
|
||||
return;
|
||||
}
|
||||
status = btc_transfer_context(&msg, p_data, sizeof(tBTA_GATTS),
|
||||
status = btc_transfer_context(&msg, p_data, btc_gatts_cb_event_param_len(event),
|
||||
btc_gatts_cb_param_copy_req, btc_gatts_cb_param_copy_free);
|
||||
|
||||
if (status != BT_STATUS_SUCCESS) {
|
||||
@@ -786,7 +883,7 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
arg->send_ind.value_len, arg->send_ind.value, arg->send_ind.need_confirm);
|
||||
break;
|
||||
case BTC_GATTS_ACT_SEND_RESPONSE: {
|
||||
esp_ble_gatts_cb_param_t param;
|
||||
esp_ble_gatts_cb_param_t param = {0};
|
||||
esp_gatt_rsp_t *p_rsp = arg->send_rsp.rsp;
|
||||
|
||||
if (p_rsp) {
|
||||
@@ -1099,7 +1196,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
|
||||
void btc_congest_callback(tBTA_GATTS *param)
|
||||
{
|
||||
esp_ble_gatts_cb_param_t esp_param;
|
||||
esp_ble_gatts_cb_param_t esp_param = {0};
|
||||
esp_gatt_if_t gatts_if = BTC_GATT_GET_GATT_IF(param->congest.conn_id);
|
||||
esp_param.congest.conn_id = BTC_GATT_GET_CONN_ID(param->congest.conn_id);
|
||||
esp_param.congest.congested = param->congest.congested;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -29,9 +29,10 @@ static void btc_ble_iso_callback(tBTM_BLE_ISO_EVENT event,
|
||||
{
|
||||
esp_ble_iso_cb_param_t param = {0};
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg;
|
||||
btc_msg_t msg = {0};
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_ISO_BLE;
|
||||
msg.act = ESP_BLE_ISO_EVT_MAX;
|
||||
|
||||
switch(event) {
|
||||
#if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE)
|
||||
@@ -208,6 +209,11 @@ static void btc_ble_iso_callback(tBTM_BLE_ISO_EVENT event,
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg.act == ESP_BLE_ISO_EVT_MAX) {
|
||||
BTC_TRACE_ERROR("%s unk ISO evt %d", __func__, event);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = btc_transfer_context(&msg, ¶m,
|
||||
sizeof(esp_ble_iso_cb_param_t), NULL, NULL);
|
||||
|
||||
@@ -341,13 +347,14 @@ void btc_iso_ble_call_handler(btc_msg_t *msg)
|
||||
(uint8_t *)&set_cig_params->cis_params[0]);
|
||||
break;
|
||||
}
|
||||
case BTC_ISO_ACT_SET_CIG_PARAMS_TEST:
|
||||
case BTC_ISO_ACT_SET_CIG_PARAMS_TEST: {
|
||||
struct set_cig_params_test_arg *set_cig_params_test = (struct set_cig_params_test_arg *)arg;
|
||||
BTA_DmBleIsoSetCigParamsTest(set_cig_params_test->cig_id, set_cig_params_test->sdu_int_c_to_p, set_cig_params_test->sdu_int_p_to_c,
|
||||
set_cig_params_test->ft_c_to_p, set_cig_params_test->ft_p_to_c, set_cig_params_test->iso_interval,
|
||||
set_cig_params_test->worse_case_SCA, set_cig_params_test->packing, set_cig_params_test->framing,
|
||||
set_cig_params_test->cis_cnt, (uint8_t *)&set_cig_params_test->cis_params_test[0]);
|
||||
break;
|
||||
}
|
||||
case BTC_ISO_ACT_CREATE_CIS: {
|
||||
struct creat_cis_arg * create_cis = (struct creat_cis_arg *)arg;
|
||||
BTA_DmBleIsoCreateCis(create_cis->cis_count, (uint8_t *)&create_cis->cis_hdls[0]);
|
||||
|
||||
@@ -17,6 +17,22 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* WARNING
|
||||
* ============================================================================
|
||||
* NOTE: The code in this file is for INTERNAL TEMPORARY TESTING ONLY.
|
||||
*
|
||||
* - DO NOT use it in any product code or user application.
|
||||
* - It is not part of the public/stable API and provides NO compatibility
|
||||
* guarantees of any kind (behavior, ABI, function signatures, side effects).
|
||||
* - It may be changed, refactored, or REMOVED at any time without notice.
|
||||
*
|
||||
* This file will be deleted in a future release. Any external dependency on
|
||||
* the symbols defined here is unsupported and will break.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "hci/ble_hci_iso.h"
|
||||
|
||||
@@ -2279,7 +2279,7 @@ void btm_acl_pkt_types_changed(UINT8 status, UINT16 handle, UINT16 pkt_types)
|
||||
tBTM_STATUS BTM_ReadChannelMap(BD_ADDR remote_bda)
|
||||
{
|
||||
tACL_CONN *p;
|
||||
tBTM_BLE_CH_MAP_RESULTS result;
|
||||
tBTM_BLE_CH_MAP_RESULTS result = {0};
|
||||
tBTM_BLE_LEGACY_GAP_CB_PARAMS cb_params;
|
||||
UINT8 status;
|
||||
|
||||
@@ -2322,7 +2322,7 @@ void BTM_BleGetWhiteListSize(uint16_t *length)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
if (p_cb->white_list_avail_size == 0) {
|
||||
BTM_TRACE_WARNING("%s Whitelist full.", __func__);
|
||||
BTM_TRACE_WARNING("%s Whitelist size is 0.", __func__);
|
||||
}
|
||||
*length = p_cb->white_list_avail_size;
|
||||
return;
|
||||
@@ -2356,7 +2356,7 @@ void BTM_BleGetPeriodicAdvListSize(uint8_t *size)
|
||||
*******************************************************************************/
|
||||
void btm_read_channel_map_complete(UINT8 *p)
|
||||
{
|
||||
tBTM_BLE_CH_MAP_RESULTS results;
|
||||
tBTM_BLE_CH_MAP_RESULTS results = {0};
|
||||
UINT16 handle;
|
||||
tACL_CONN *p_acl_cb = NULL;
|
||||
|
||||
|
||||
@@ -736,7 +736,7 @@ BOOLEAN BTM_ReadConnectedTransportAddress(BD_ADDR remote_bda, tBT_TRANSPORT tran
|
||||
** p_cmd_cmpl_cback - Command Complete callback
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback)
|
||||
{
|
||||
btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
|
||||
|
||||
@@ -758,7 +758,7 @@ void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
|
||||
UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
UINT8 packet_payload, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback)
|
||||
{
|
||||
btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
|
||||
if (btsnd_hcic_ble_transmitter_test(tx_freq, test_data_len, packet_payload) == FALSE) {
|
||||
@@ -776,7 +776,7 @@ void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
|
||||
** Parameter p_cmd_cmpl_cback - Command complete callback
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
void BTM_BleTestEnd(tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback)
|
||||
{
|
||||
btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
|
||||
|
||||
@@ -788,14 +788,14 @@ void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
/*******************************************************************************
|
||||
** Internal Functions
|
||||
*******************************************************************************/
|
||||
void btm_ble_test_command_complete(UINT8 *p)
|
||||
void btm_ble_test_command_complete(UINT8 *p, UINT16 len)
|
||||
{
|
||||
tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
|
||||
tBTM_DTM_CMD_CMPL_CBACK *p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
|
||||
|
||||
btm_cb.devcb.p_le_test_cmd_cmpl_cb = NULL;
|
||||
|
||||
if (p_cb) {
|
||||
(*p_cb)(p);
|
||||
(*p_cb)(p, len);
|
||||
}
|
||||
}
|
||||
#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
@@ -813,7 +813,7 @@ void btm_ble_test_command_complete(UINT8 *p)
|
||||
** p_cmd_cmpl_cback - Command Complete callback
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback)
|
||||
{
|
||||
btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
|
||||
|
||||
@@ -836,7 +836,7 @@ void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_inde
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
|
||||
UINT8 packet_payload, UINT8 phy, tBTM_CMPL_CB *p_cmd_cmpl_cback)
|
||||
UINT8 packet_payload, UINT8 phy, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback)
|
||||
{
|
||||
btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
|
||||
if (btsnd_hcic_ble_enhand_tx_test(tx_freq, test_data_len, packet_payload, phy) == FALSE) {
|
||||
|
||||
@@ -334,13 +334,13 @@ tBTM_STATUS BTM_BleConfigExtendedAdvDataRaw(BOOLEAN is_scan_rsp, UINT8 instance,
|
||||
}
|
||||
}
|
||||
if (!is_scan_rsp) {
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_data(instance, operation, 0, send_data_len, (data == NULL) ? NULL : &data[data_offset])) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("LE EA SetAdvData: cmd err=0x%x", err);
|
||||
status = BTM_HCI_ERROR | err;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_scan_rsp_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_scan_rsp_data(instance, operation, 0, send_data_len, (data == NULL) ? NULL : &data[data_offset])) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("LE EA SetScanRspData: cmd err=0x%x", err);
|
||||
status = BTM_HCI_ERROR | err;
|
||||
break;
|
||||
@@ -1900,7 +1900,6 @@ void btm_ble_cs_read_local_supp_caps_cmpl_evt(uint8_t *p)
|
||||
goto _error;
|
||||
}
|
||||
|
||||
STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.conn_handle, p);
|
||||
STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.num_config_supported, p);
|
||||
STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.max_consecutive_proc_supported, p);
|
||||
STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.num_ant_supported, p);
|
||||
@@ -2011,6 +2010,7 @@ void btm_ble_cs_read_remote_fae_table_cmd_status(UINT8 status)
|
||||
tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT cs_read_remote_fae_tab = {0};
|
||||
if (status != HCI_SUCCESS) {
|
||||
cs_read_remote_fae_tab.status = (status | BTM_HCI_ERROR);
|
||||
cs_read_remote_fae_tab.conn_handle = 0xFFFF;
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)&cs_read_remote_fae_tab);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1180,6 +1180,9 @@ void btm_ble_resolving_list_cleanup(void)
|
||||
{
|
||||
tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
|
||||
|
||||
p_q->q_next = 0;
|
||||
p_q->q_pending = 0;
|
||||
|
||||
if (p_q->resolve_q_random_pseudo) {
|
||||
osi_free(p_q->resolve_q_random_pseudo);
|
||||
p_q->resolve_q_random_pseudo = NULL;
|
||||
|
||||
@@ -120,13 +120,11 @@ void btm_dev_init (void)
|
||||
*******************************************************************************/
|
||||
static void btm_db_reset (void)
|
||||
{
|
||||
tBTM_CMPL_CB *p_cb;
|
||||
tBTM_STATUS status = BTM_DEV_RESET;
|
||||
|
||||
btm_inq_db_reset();
|
||||
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
if (btm_cb.devcb.p_rln_cmpl_cb) {
|
||||
tBTM_CMPL_CB *p_cb;
|
||||
p_cb = btm_cb.devcb.p_rln_cmpl_cb;
|
||||
btm_cb.devcb.p_rln_cmpl_cb = NULL;
|
||||
|
||||
@@ -137,12 +135,14 @@ static void btm_db_reset (void)
|
||||
#endif // (CLASSIC_BT_INCLUDED == TRUE)
|
||||
|
||||
if (btm_cb.devcb.p_rssi_cmpl_cb) {
|
||||
p_cb = btm_cb.devcb.p_rssi_cmpl_cb;
|
||||
btm_cb.devcb.p_rssi_cmpl_cb = NULL;
|
||||
tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_rssi_cmpl_cb;
|
||||
tBTM_RSSI_RESULTS results = {0};
|
||||
|
||||
if (p_cb) {
|
||||
(*p_cb)((tBTM_RSSI_RESULTS *) &status);
|
||||
}
|
||||
results.status = BTM_DEV_RESET;
|
||||
btm_cb.devcb.p_rssi_cmpl_cb = NULL;
|
||||
btu_stop_timer(&btm_cb.devcb.rssi_timer);
|
||||
|
||||
(*p_cb)(&results);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -444,7 +444,7 @@ void btm_ble_increment_sign_ctr(BD_ADDR bd_addr, BOOLEAN is_local );
|
||||
BOOLEAN btm_get_local_div (BD_ADDR bd_addr, UINT16 *p_div);
|
||||
BOOLEAN btm_ble_get_enc_key_type(BD_ADDR bd_addr, UINT8 *p_key_types);
|
||||
|
||||
void btm_ble_test_command_complete(UINT8 *p);
|
||||
void btm_ble_test_command_complete(UINT8 *p, UINT16 len);
|
||||
void btm_ble_rand_enc_complete (UINT8 *p, UINT16 op_code, tBTM_RAND_ENC_CB *p_enc_cplt_cback);
|
||||
|
||||
void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY_VALUE *p_keys, BOOLEAN pass_to_application);
|
||||
|
||||
@@ -291,8 +291,8 @@ DEV_CLASS dev_class; /* Local device class
|
||||
|
||||
TIMER_LIST_ENT ble_channels_timer;
|
||||
|
||||
tBTM_CMPL_CB *p_le_test_cmd_cmpl_cb; /* Callback function to be called when
|
||||
LE test mode command has been sent successfully */
|
||||
tBTM_DTM_CMD_CMPL_CBACK *p_le_test_cmd_cmpl_cb; /* Callback function to be called when
|
||||
LE test mode command has been sent successfully */
|
||||
|
||||
BD_ADDR read_tx_pwr_addr; /* read TX power target address */
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#include "stack/btu.h"
|
||||
|
||||
extern void btm_process_cancel_complete(UINT8 status, UINT8 mode);
|
||||
extern void btm_ble_test_command_complete(UINT8 *p);
|
||||
extern void btm_ble_test_command_complete(UINT8 *p, UINT16 len);
|
||||
|
||||
#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
|
||||
// BLE Channel Sounding parameter validation macros per BLE spec
|
||||
@@ -1331,11 +1331,17 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
|
||||
btm_ble_create_ll_conn_complete(*p);
|
||||
break;
|
||||
|
||||
#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
case HCI_BLE_TRANSMITTER_TEST:
|
||||
case HCI_BLE_RECEIVER_TEST:
|
||||
case HCI_BLE_TEST_END:
|
||||
/* Forward raw parameters + length; upper layers validate before parsing. */
|
||||
btm_ble_test_command_complete(p, evt_len);
|
||||
break;
|
||||
#else
|
||||
case HCI_BLE_TRANSMITTER_TEST:
|
||||
case HCI_BLE_RECEIVER_TEST:
|
||||
#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
case HCI_BLE_TEST_END:
|
||||
btm_ble_test_command_complete(p);
|
||||
break;
|
||||
#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE))
|
||||
case HCI_BLE_CREATE_CONN_CANCEL:
|
||||
@@ -1397,7 +1403,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
|
||||
#if (BLE_50_DTM_TEST_EN == TRUE)
|
||||
case HCI_BLE_ENH_RX_TEST:
|
||||
case HCI_BLE_ENH_TX_TEST:
|
||||
btm_ble_test_command_complete(p);
|
||||
btm_ble_test_command_complete(p, evt_len);
|
||||
break;
|
||||
#endif // #if (BLE_50_DTM_TEST_EN == TRUE)
|
||||
|
||||
|
||||
@@ -390,6 +390,18 @@ tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB *p_tcb, BT_HDR *p_toL2CAP)
|
||||
|
||||
|
||||
if (p_tcb->att_lcid == L2CAP_ATT_CID) {
|
||||
/* L2CA_SendFixedChnlData() silently drops (osi_free) the buffer when the
|
||||
* ATT fixed channel is already in cong_sent state, yet still returns
|
||||
* L2CAP_DW_CONGESTED. Without distinguishing this from the post-enqueue
|
||||
* congestion case, the upper layer would treat a dropped PDU as "sent"
|
||||
* and wait for a response that never arrives. Detect the drop path
|
||||
* up-front, release the buffer here and surface it as GATT_BUSY so that
|
||||
* callers go through their failure path instead. */
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) {
|
||||
GATT_TRACE_WARNING("ATT fixed channel already congested, drop PDU");
|
||||
osi_free(p_toL2CAP);
|
||||
return GATT_BUSY;
|
||||
}
|
||||
l2cap_ret = L2CA_SendFixedChnlData (L2CAP_ATT_CID, p_tcb->peer_bda, p_toL2CAP);
|
||||
} else {
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
@@ -403,6 +415,8 @@ tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB *p_tcb, BT_HDR *p_toL2CAP)
|
||||
GATT_TRACE_DEBUG("ATT failed to pass msg to L2CAP");
|
||||
return GATT_INTERNAL_ERROR;
|
||||
} else if (l2cap_ret == L2CAP_DW_CONGESTED) {
|
||||
/* Buffer was enqueued by L2CAP before congestion was reported;
|
||||
* L2CAP retains ownership of it. */
|
||||
GATT_TRACE_DEBUG("ATT congested, message accepted");
|
||||
return GATT_CONGESTED;
|
||||
}
|
||||
|
||||
@@ -1750,9 +1750,22 @@ tGATT_STATUS GATTS_HandleMultiValueNotification (UINT16 conn_id, tGATT_HLV *tupl
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
{
|
||||
UINT32 new_len = (UINT32)notif.len + 4U + (UINT32)p_hlv->length;
|
||||
if (new_len > (UINT32)GATT_MAX_ATTR_LEN) {
|
||||
GATT_TRACE_ERROR("%s: len %u>MAX_ATTR_LEN", __func__, (unsigned)new_len);
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
UINT16_TO_STREAM(p, p_hlv->handle); //handle
|
||||
UINT16_TO_STREAM(p, p_hlv->length); //length
|
||||
memcpy (p, p_hlv->value, p_hlv->length); //value
|
||||
if (p_hlv->length > 0) {
|
||||
if (p_hlv->value == NULL) {
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
memcpy (p, p_hlv->value, p_hlv->length); //value
|
||||
}
|
||||
GATT_TRACE_DEBUG("%s handle %x, length %u", __func__, p_hlv->handle, p_hlv->length);
|
||||
p += p_hlv->length;
|
||||
notif.len += 4 + p_hlv->length;
|
||||
|
||||
@@ -171,7 +171,7 @@ void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb, UINT8 s
|
||||
void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, tBTM_STATUS result)
|
||||
{
|
||||
tGATT_TCB *p_tcb;
|
||||
UINT8 sec_flag;
|
||||
UINT8 sec_flag = 0;
|
||||
BOOLEAN status = FALSE;
|
||||
UNUSED(p_ref_data);
|
||||
|
||||
@@ -185,9 +185,8 @@ void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_d
|
||||
if (p_buf != NULL) {
|
||||
if (result == BTM_SUCCESS) {
|
||||
if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM ) {
|
||||
BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport);
|
||||
|
||||
if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) {
|
||||
if (BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport) &&
|
||||
(sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)) {
|
||||
status = TRUE;
|
||||
}
|
||||
} else {
|
||||
@@ -305,7 +304,7 @@ tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB *p_tcb)
|
||||
tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB *p_clcb )
|
||||
{
|
||||
tGATT_SEC_ACTION act = GATT_SEC_OK;
|
||||
UINT8 sec_flag;
|
||||
UINT8 sec_flag = 0;
|
||||
tGATT_TCB *p_tcb = p_clcb->p_tcb;
|
||||
tGATT_AUTH_REQ auth_req = p_clcb->auth_req;
|
||||
BOOLEAN is_link_encrypted = FALSE;
|
||||
|
||||
@@ -1124,10 +1124,14 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
|
||||
if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED) {
|
||||
sent = TRUE;
|
||||
p_cmd->to_send = FALSE;
|
||||
if(p_cmd->p_cmd) {
|
||||
osi_free(p_cmd->p_cmd);
|
||||
p_cmd->p_cmd = NULL;
|
||||
}
|
||||
/* On GATT_SUCCESS / GATT_CONGESTED, L2CAP has taken ownership of
|
||||
* p_cmd->p_cmd (it was either accepted normally, or enqueued just
|
||||
* before the channel turned congested). The "already congested"
|
||||
* drop path inside L2CA_SendFixedChnlData() is filtered out earlier
|
||||
* by attp_send_msg_to_l2cap() and returned as GATT_BUSY, which
|
||||
* falls into the error branch below. So we must not free the
|
||||
* buffer here. */
|
||||
p_cmd->p_cmd = NULL;
|
||||
|
||||
/* dequeue the request if is write command or sign write */
|
||||
if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE) {
|
||||
@@ -1145,13 +1149,22 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
|
||||
gatt_end_operation(p_clcb, att_ret, NULL);
|
||||
}
|
||||
} else {
|
||||
GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
|
||||
GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error, status=%d", att_ret);
|
||||
/* attp_send_msg_to_l2cap() already freed p_cmd->p_cmd on failure */
|
||||
p_cmd->p_cmd = NULL;
|
||||
memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
|
||||
p_tcb->pending_cl_req ++;
|
||||
p_tcb->pending_cl_req %= GATT_CL_MAX_LCB;
|
||||
p_cmd->to_send = FALSE;
|
||||
/* Dequeue the failing command so pending_cl_req is advanced and the
|
||||
* associated p_clcb can be retrieved. */
|
||||
p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
|
||||
p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
|
||||
/* Notify the upper layer about the failure. Without this the
|
||||
* response timer is never armed (non-write ops) and the write
|
||||
* completion callback is never fired, leaving the application
|
||||
* stuck waiting for a callback that will never come. The p_clcb
|
||||
* would also leak. */
|
||||
if (p_clcb != NULL) {
|
||||
gatt_end_operation(p_clcb, att_ret, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -754,8 +754,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
|
||||
for (ll = 0; ll < p_tcb->sr_cmd.multi_req.num_handles; ll ++) {
|
||||
if ((p_msg = (tGATTS_RSP *)osi_malloc(sizeof(tGATTS_RSP))) != NULL) {
|
||||
memset(p_msg, 0, sizeof(tGATTS_RSP))
|
||||
;
|
||||
memset(p_msg, 0, sizeof(tGATTS_RSP));
|
||||
handle = p_tcb->sr_cmd.multi_req.handles[ll];
|
||||
i_rcb = gatt_sr_find_i_rcb_by_handle(handle);
|
||||
|
||||
@@ -1496,10 +1495,17 @@ void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 hand
|
||||
}
|
||||
}
|
||||
|
||||
/* sr_cmd enqueued at handle but no attribute branch ran (null DB/list or no exact handle). */
|
||||
if (trans_id != 0 && !is_need_prepare_write_rsp && !is_need_queue_data &&
|
||||
status == GATT_SUCCESS) {
|
||||
status = GATT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (is_need_queue_data){
|
||||
queue_data = (tGATT_PREPARE_WRITE_QUEUE_DATA *)osi_malloc(len + sizeof(tGATT_PREPARE_WRITE_QUEUE_DATA));
|
||||
if (queue_data == NULL){
|
||||
status = GATT_PREPARE_Q_FULL;
|
||||
is_need_prepare_write_rsp = FALSE;
|
||||
} else {
|
||||
queue_data->p_attr = p_attr_temp;
|
||||
queue_data->len = len;
|
||||
@@ -1509,7 +1515,16 @@ void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 hand
|
||||
if (prepare_record->queue == NULL) {
|
||||
prepare_record->queue = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
}
|
||||
fixed_queue_enqueue(prepare_record->queue, queue_data, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
if (prepare_record->queue == NULL ||
|
||||
fixed_queue_length(prepare_record->queue) >=
|
||||
fixed_queue_capacity(prepare_record->queue)) {
|
||||
osi_free(queue_data);
|
||||
queue_data = NULL;
|
||||
status = GATT_PREPARE_Q_FULL;
|
||||
is_need_prepare_write_rsp = FALSE;
|
||||
} else {
|
||||
fixed_queue_enqueue(prepare_record->queue, queue_data, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -690,6 +690,9 @@ BOOLEAN gatt_add_an_item_to_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELE
|
||||
p_new->p_prev = p_old->p_prev;
|
||||
p_new->p_next = p_old;
|
||||
|
||||
if (p_old->p_prev != NULL) {
|
||||
p_old->p_prev->p_next = p_new;
|
||||
}
|
||||
|
||||
p_old->p_prev = p_new;
|
||||
break;
|
||||
@@ -1231,6 +1234,10 @@ BOOLEAN gatt_parse_uuid_from_cmd(tBT_UUID *p_uuid_rec, UINT16 uuid_size, UINT8 *
|
||||
void gatt_start_rsp_timer(UINT16 clcb_idx)
|
||||
{
|
||||
tGATT_CLCB *p_clcb = gatt_clcb_find_by_idx(clcb_idx);
|
||||
if (p_clcb == NULL) {
|
||||
GATT_TRACE_ERROR("%s: no CLCB for clcb_idx=0x%x", __func__, clcb_idx);
|
||||
return;
|
||||
}
|
||||
p_clcb->rsp_timer_ent.param = (TIMER_PARAM_TYPE)p_clcb;
|
||||
btu_start_timer (&p_clcb->rsp_timer_ent, BTU_TTYPE_ATT_WAIT_FOR_RSP,
|
||||
GATT_WAIT_FOR_RSP_TOUT);
|
||||
@@ -2305,10 +2312,17 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
|
||||
UINT8 i;
|
||||
UINT16 conn_id;
|
||||
tGATT_REG *p_reg = NULL;
|
||||
|
||||
#if (GATTS_INCLUDED == TRUE)
|
||||
BD_ADDR bda_local;
|
||||
#endif
|
||||
|
||||
GATT_TRACE_DEBUG ("gatt_cleanup_upon_disc ");
|
||||
|
||||
#if (GATTS_INCLUDED == TRUE)
|
||||
/* Copy in case bda points into p_tcb->peer_bda, which is invalid after gatt_tcb_free. */
|
||||
memcpy(bda_local, bda, BD_ADDR_LEN);
|
||||
#endif
|
||||
|
||||
if ((p_tcb = gatt_find_tcb_by_addr(bda, transport)) != NULL) {
|
||||
GATT_TRACE_DEBUG ("found p_tcb ");
|
||||
gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
|
||||
@@ -2357,7 +2371,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
|
||||
BTM_Recovery_Pre_State();
|
||||
}
|
||||
#if (GATTS_INCLUDED == TRUE)
|
||||
gatt_delete_dev_from_srv_chg_clt_list(bda);
|
||||
gatt_delete_dev_from_srv_chg_clt_list(bda_local);
|
||||
#endif // (GATTS_INCLUDED == TRUE)
|
||||
}
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -3059,7 +3059,8 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_subevt_data(UINT8 adv_handle, UINT8 num_su
|
||||
{
|
||||
BT_HDR *p;
|
||||
UINT8 *pp;
|
||||
uint8_t param_len = 0;
|
||||
unsigned total_len;
|
||||
UINT8 param_len;
|
||||
|
||||
HCI_TRACE_DEBUG("hci set PA subevent data, adv_handle %d num_subevents_with_data %d", adv_handle, num_subevents_with_data);
|
||||
|
||||
@@ -3067,10 +3068,19 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_subevt_data(UINT8 adv_handle, UINT8 num_su
|
||||
HCI_TRACE_ERROR("%s error\n", __func__);
|
||||
return HCI_ERR_ILLEGAL_PARAMETER_FMT;
|
||||
}
|
||||
param_len += HCIC_PARAM_SIZE_SET_PA_SUBEVT_DATA_PARAMS_LEN;
|
||||
total_len = HCIC_PARAM_SIZE_SET_PA_SUBEVT_DATA_PARAMS_LEN;
|
||||
|
||||
for (UINT8 i = 0; i < num_subevents_with_data; i++)
|
||||
{
|
||||
if (subevent_params[i].subevent_data_len > sizeof(subevent_params[i].data)) {
|
||||
HCI_TRACE_ERROR("%s sub_data_len %u>%u", __func__,
|
||||
(unsigned)subevent_params[i].subevent_data_len,
|
||||
(unsigned)sizeof(subevent_params[i].data));
|
||||
return HCI_ERR_ILLEGAL_PARAMETER_FMT;
|
||||
}
|
||||
|
||||
unsigned add_len = 4u + (unsigned)subevent_params[i].subevent_data_len;
|
||||
|
||||
HCI_TRACE_DEBUG("subevent_params: subevent %d response_slot_start %d response_slot_count %d subevent_data_len %d",
|
||||
subevent_params[i].subevent, subevent_params[i].response_slot_start, subevent_params[i].response_slot_count,
|
||||
subevent_params[i].subevent_data_len);
|
||||
@@ -3079,9 +3089,17 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_subevt_data(UINT8 adv_handle, UINT8 num_su
|
||||
esp_log_buffer_hex_internal("data", subevent_params[i].data, subevent_params[i].subevent_data_len, ESP_LOG_DEBUG);
|
||||
}
|
||||
|
||||
param_len += (4 + subevent_params[i].subevent_data_len);
|
||||
/* Avoid unsigned wrap when add_len > HCI_COMMAND_SIZE. */
|
||||
if (total_len > (unsigned)HCI_COMMAND_SIZE ||
|
||||
add_len > (unsigned)HCI_COMMAND_SIZE - total_len) {
|
||||
HCI_TRACE_ERROR("%s total>HCI_CMD_SZ", __func__);
|
||||
return HCI_ERR_ILLEGAL_PARAMETER_FMT;
|
||||
}
|
||||
total_len += add_len;
|
||||
}
|
||||
|
||||
param_len = (UINT8)total_len;
|
||||
|
||||
HCIC_BLE_CMD_CREATED_U8(p, pp, param_len);
|
||||
|
||||
pp = (UINT8 *)(p + 1);
|
||||
@@ -3113,6 +3131,11 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_rsp_data(UINT16 sync_handle, UINT16 req_ev
|
||||
HCI_TRACE_DEBUG("hci set PA rsp data, sync_handle %d req_evt %d req_subevt %d rsp_subevt %d rsp_slot %d rsp_data_len %d",
|
||||
sync_handle, req_evt, req_subevt, rsp_subevt, rsp_slot, rsp_data_len);
|
||||
|
||||
if (rsp_data_len > HCIC_PA_RSP_DATA_PAYLOAD_MAX) {
|
||||
HCI_TRACE_ERROR("%s rsp_len %u>%u", __func__, rsp_data_len, HCIC_PA_RSP_DATA_PAYLOAD_MAX);
|
||||
return HCI_ERR_ILLEGAL_PARAMETER_FMT;
|
||||
}
|
||||
|
||||
HCIC_BLE_CMD_CREATED_U8(p, pp, HCIC_PARAM_SIZE_SET_PA_RESPONSE_DATA_PARAMS_LEN + rsp_data_len);
|
||||
|
||||
pp = (UINT8 *)(p + 1);
|
||||
@@ -3141,6 +3164,12 @@ UINT8 btsnd_hcic_ble_set_periodic_sync_subevt(UINT16 sync_handle, UINT16 periodi
|
||||
|
||||
HCI_TRACE_DEBUG("hci set PA sync subevent, sync_handle %d periodic_adv_properties %d num_subevents_to_sync %d",
|
||||
sync_handle, periodic_adv_properties, num_subevents_to_sync);
|
||||
|
||||
if (num_subevents_to_sync > HCIC_PA_SYNC_SUBEVT_NUM_MAX) {
|
||||
HCI_TRACE_ERROR("%s n_sync %u>%u", __func__, num_subevents_to_sync, HCIC_PA_SYNC_SUBEVT_NUM_MAX);
|
||||
return HCI_ERR_ILLEGAL_PARAMETER_FMT;
|
||||
}
|
||||
|
||||
for (UINT8 i = 0; i < num_subevents_to_sync; i++)
|
||||
{
|
||||
HCI_TRACE_DEBUG("subevt[%d] = %d", i, subevt[i]);
|
||||
|
||||
@@ -173,7 +173,14 @@ typedef void (tBTM_VSC_CMPL_CB) (tBTM_VSC_CMPL *p1);
|
||||
*/
|
||||
// typedef UINT8 (tBTM_FILTER_CB) (BD_ADDR bd_addr, DEV_CLASS dc);
|
||||
|
||||
typedef void (tBTM_DTM_CMD_CMPL_CBACK) (void *p1);
|
||||
/*
|
||||
* DTM (Direct Test Mode) command complete callback.
|
||||
*
|
||||
* The controller returns a variable-length parameter block depending on the
|
||||
* specific LE test command. Propagate the parameter length so upper layers can
|
||||
* validate before parsing and avoid OOB reads on malformed/truncated responses.
|
||||
*/
|
||||
typedef void (tBTM_DTM_CMD_CMPL_CBACK) (UINT8 *p, UINT16 len);
|
||||
|
||||
typedef void (tBTM_SET_RAND_ADDR_CBACK) (UINT8 status);
|
||||
|
||||
|
||||
@@ -1528,7 +1528,6 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
UINT8 status;
|
||||
UINT16 conn_handle;
|
||||
UINT8 num_config_supported;
|
||||
UINT16 max_consecutive_proc_supported;
|
||||
UINT8 num_ant_supported;
|
||||
@@ -2726,7 +2725,7 @@ void BTM_BleClearWhitelist(void);
|
||||
** p_cmd_cmpl_cback - Command Complete callback
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback);
|
||||
void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -2742,7 +2741,7 @@ void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback);
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
|
||||
UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback);
|
||||
UINT8 packet_payload, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@@ -2753,7 +2752,7 @@ void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
|
||||
** Parameter p_cmd_cmpl_cback - Command complete callback
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback);
|
||||
void BTM_BleTestEnd(tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@@ -3087,9 +3086,9 @@ tBTM_STATUS BTM_BleEnableMonitorAdv(UINT8 enable);
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
#if (BLE_50_DTM_TEST_EN == TRUE)
|
||||
void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_CMPL_CB *p_cmd_cmpl_cback);
|
||||
void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback);
|
||||
|
||||
void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, UINT8 packet_payload, UINT8 phy, tBTM_CMPL_CB *p_cmd_cmpl_cback);
|
||||
void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, UINT8 packet_payload, UINT8 phy, tBTM_DTM_CMD_CMPL_CBACK *p_cmd_cmpl_cback);
|
||||
#endif // #if (BLE_50_DTM_TEST_EN == TRUE)
|
||||
|
||||
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
|
||||
|
||||
@@ -1285,6 +1285,11 @@ typedef struct {
|
||||
#define HCIC_PARAM_SIZE_SET_PA_RESPONSE_DATA_PARAMS_LEN 8
|
||||
#define HCIC_PARAM_SIZE_SET_PA_SYNC_SUBEVT_PARAMS_LEN 5
|
||||
|
||||
/** Max rsp_data octets in LE Set Periodic Advertising Response Data (HCI command param total ≤ HCI_COMMAND_SIZE). */
|
||||
#define HCIC_PA_RSP_DATA_PAYLOAD_MAX (HCI_COMMAND_SIZE - HCIC_PARAM_SIZE_SET_PA_RESPONSE_DATA_PARAMS_LEN)
|
||||
/** Max Num_Subevents_To_Sync in LE Set Periodic Advertising Sync Subevents (BT Core Spec §7.8.127: 0x01–0x80). */
|
||||
#define HCIC_PA_SYNC_SUBEVT_NUM_MAX 128
|
||||
|
||||
#define HCIC_PARAM_SIZE_SET_PERIODIC_ADV_PARAMS_V2 12
|
||||
UINT8 btsnd_hcic_ble_set_periodic_adv_params_v2(UINT8 adv_handle, UINT16 interval_min, UINT16 interval_max,
|
||||
UINT16 propertics, UINT8 num_subevents, UINT8 subevent_interval,
|
||||
|
||||
Reference in New Issue
Block a user