mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(ble/bluedroid): fix GATT server lifecycle and callbacks
(cherry picked from commit 54a1e31916)
Co-authored-by: zhiweijian <zhiweijian@espressif.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
/*******************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user