From 8f972e76ac3c16d1e2a0b60938440a57801c40b6 Mon Sep 17 00:00:00 2001 From: Zhi Wei Jian Date: Wed, 25 Mar 2026 10:27:40 +0800 Subject: [PATCH] fix(ble/bluedroid): fix GATT protocol and database operation issues - Fix GATTC read by type length error and rsp pdu format check - Fix p_cur_handle update in gatts_db_read_attr_value_by_type - Fix len calculation error in calculate_database_info_size - Replace gatt_find_the_connected_bda with p_tcb_list iteration - Send cmd reject if cid is invalid - Fix param_len check in smp_rand_back - Remove duplicate uuid compare functions (cherry picked from commit 6242e0244c74d877712ee440d9a42ddf0c2cff21) Co-authored-by: zhiweijian --- .../bt/host/bluedroid/stack/gap/gap_ble.c | 18 ++- .../host/bluedroid/stack/gatt/att_protocol.c | 5 + .../bt/host/bluedroid/stack/gatt/gatt_api.c | 56 +++++----- .../bt/host/bluedroid/stack/gatt/gatt_auth.c | 2 + .../bt/host/bluedroid/stack/gatt/gatt_cl.c | 15 ++- .../bt/host/bluedroid/stack/gatt/gatt_db.c | 20 +++- .../bt/host/bluedroid/stack/gatt/gatt_main.c | 22 ++-- .../bt/host/bluedroid/stack/gatt/gatt_sr.c | 12 ++ .../host/bluedroid/stack/gatt/gatt_sr_hash.c | 15 ++- .../bt/host/bluedroid/stack/gatt/gatt_utils.c | 104 ++++++++---------- .../bluedroid/stack/gatt/include/gatt_int.h | 3 +- 11 files changed, 163 insertions(+), 109 deletions(-) diff --git a/components/bt/host/bluedroid/stack/gap/gap_ble.c b/components/bt/host/bluedroid/stack/gap/gap_ble.c index 154fcca0b03..823fadc9838 100644 --- a/components/bt/host/bluedroid/stack/gap/gap_ble.c +++ b/components/bt/host/bluedroid/stack/gap/gap_ble.c @@ -775,6 +775,7 @@ BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL { tGAP_CLCB *p_clcb; BOOLEAN started = FALSE; + BOOLEAN is_new_clcb = FALSE; if (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM) { return (started); @@ -785,6 +786,7 @@ BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL GAP_TRACE_ERROR("gap_ble_accept_cl_operation max connection reached"); return started; } + is_new_clcb = TRUE; } GAP_TRACE_EVENT ("%s() - BDA: %08x%04x cl_op_uuid: 0x%04x", @@ -798,11 +800,25 @@ BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL /* hold the link here */ if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, BT_TRANSPORT_LE, FALSE, FALSE, 0xFF, 0xFF)) { + if (is_new_clcb) { + gap_ble_dealloc_clcb(p_clcb); + } return started; } /* enqueue the request */ - gap_ble_enqueue_request(p_clcb, uuid, p_cback); + if (gap_ble_enqueue_request(p_clcb, uuid, p_cback) == FALSE) { + GAP_TRACE_ERROR("gap_ble_accept_cl_operation enqueue request failed"); + if (is_new_clcb) { + if (p_clcb->connected) { + GATT_Disconnect(p_clcb->conn_id); + } else { + GATT_CancelConnect(gap_cb.gatt_if, p_clcb->bda, TRUE); + } + gap_ble_dealloc_clcb(p_clcb); + } + return started; + } if (p_clcb->connected && p_clcb->cl_op_uuid == 0) { started = gap_ble_send_cl_read_request(p_clcb); diff --git a/components/bt/host/bluedroid/stack/gatt/att_protocol.c b/components/bt/host/bluedroid/stack/gatt/att_protocol.c index f2654f1a15b..686820071a8 100644 --- a/components/bt/host/bluedroid/stack/gatt/att_protocol.c +++ b/components/bt/host/bluedroid/stack/gatt/att_protocol.c @@ -166,6 +166,11 @@ BT_HDR *attp_build_read_by_type_value_cmd (UINT16 payload_size, tGATT_FIND_TYPE_ UINT8 *p; UINT16 len = p_value_type->value_len; + if (payload_size < GATT_DEF_BLE_MTU_SIZE) { + // never build packet smaller than default MTU size + return NULL; + } + if ((p_buf = (BT_HDR *)osi_malloc((UINT16)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET))) != NULL) { p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET; diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_api.c b/components/bt/host/bluedroid/stack/gatt/gatt_api.c index dfceedf049d..ddab5b986f8 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_api.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_api.c @@ -1029,6 +1029,12 @@ tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM p_clcb->s_handle = 0; /* copy multiple handles in CB */ p_read_multi = (tGATT_READ_MULTI *)osi_malloc(sizeof(tGATT_READ_MULTI)); + if (p_read_multi == NULL) { + GATT_TRACE_ERROR("GATTC_Read no resources for multiple read"); + status = GATT_NO_RESOURCES; + gatt_clcb_dealloc(p_clcb); + return status; + } p_clcb->p_attr_buf = (UINT8 *)p_read_multi; memcpy (p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI)); case GATT_READ_BY_HANDLE: @@ -1382,7 +1388,8 @@ void GATT_Deregister (tGATT_IF gatt_if) (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) { btu_stop_timer(&p_clcb->rsp_timer_ent); gatt_clcb_dealloc (p_clcb); - break; + // Removed break to ensure all CLCBs are cleaned up + // break; } } } @@ -1394,6 +1401,10 @@ void GATT_Deregister (tGATT_IF gatt_if) memset (p_reg, 0, sizeof(tGATT_REG)); } +void gatt_start_if_conn_cb(UINT8 tcb_idx, tBT_TRANSPORT transport, BD_ADDR bda) +{ + +} /******************************************************************************* ** @@ -1412,21 +1423,19 @@ void GATT_StartIf (tGATT_IF gatt_if) { tGATT_REG *p_reg; tGATT_TCB *p_tcb; - BD_ADDR bda; - UINT8 start_idx, found_idx; UINT16 conn_id; - tGATT_TRANSPORT transport ; + list_node_t *p_node = NULL; GATT_TRACE_API ("GATT_StartIf gatt_if=%d", gatt_if); if ((p_reg = gatt_get_regcb(gatt_if)) != NULL) { - start_idx = 0; - while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) { - p_tcb = gatt_find_tcb_by_addr(bda, transport); - if (p_reg->app_cb.p_conn_cb && p_tcb) { - conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if); - (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0, transport); + for (p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) { + p_tcb = list_node(p_node); + if (p_tcb->in_use && p_tcb->ch_state == GATT_CH_OPEN) { + if (p_reg->app_cb.p_conn_cb && p_tcb) { + conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if); + (*p_reg->app_cb.p_conn_cb)(gatt_if, p_tcb->peer_bda, conn_id, TRUE, 0, p_tcb->transport); + } } - start_idx = ++found_idx; } } } @@ -1593,11 +1602,10 @@ tGATT_STATUS GATT_Disconnect (UINT16 conn_id) *******************************************************************************/ tGATT_STATUS GATT_SendServiceChangeIndication (BD_ADDR bd_addr) { - UINT8 start_idx, found_idx; BOOLEAN srv_chg_ind_pending = FALSE; tGATT_TCB *p_tcb; - tBT_TRANSPORT transport; tGATT_STATUS status = GATT_NOT_FOUND; + list_node_t *p_node = NULL; if (gatt_cb.srv_chg_mode == GATTS_SEND_SERVICE_CHANGE_AUTO) { status = GATT_WRONG_STATE; @@ -1608,19 +1616,17 @@ tGATT_STATUS GATT_SendServiceChangeIndication (BD_ADDR bd_addr) if(bd_addr) { status = gatt_send_srv_chg_ind(bd_addr); } else { - start_idx = 0; - BD_ADDR addr; - while (gatt_find_the_connected_bda(start_idx, addr, &found_idx, &transport)) { - p_tcb = gatt_get_tcb_by_idx(found_idx); - srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb); - - if (!srv_chg_ind_pending) { - status = gatt_send_srv_chg_ind(addr); - } else { - status = GATT_BUSY; - GATT_TRACE_DEBUG("discard srv chg - already has one in the queue"); + for (p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) { + p_tcb = list_node(p_node); + if (p_tcb->in_use && p_tcb->ch_state == GATT_CH_OPEN) { + srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb); + if (!srv_chg_ind_pending) { + status = gatt_send_srv_chg_ind(p_tcb->peer_bda); + } else { + status = GATT_BUSY; + GATT_TRACE_DEBUG("discard srv chg - already has one in the queue"); + } } - start_idx = ++found_idx; } } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_auth.c b/components/bt/host/bluedroid/stack/gatt/gatt_auth.c index e205815fed4..0a033e1ae04 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_auth.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_auth.c @@ -80,6 +80,8 @@ static BOOLEAN gatt_sign_data (tGATT_CLCB *p_clcb) } osi_free(p_data); + } else { + gatt_end_operation(p_clcb, GATT_NO_RESOURCES, NULL); } return status; diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c index 1bdbfaec08c..98214f87973 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c @@ -449,7 +449,7 @@ void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UIN void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { - tGATT_DISC_RES result; + tGATT_DISC_RES result = {0}; UINT8 *p = p_data, uuid_len = 0, type; UNUSED(p_tcb); @@ -472,6 +472,10 @@ void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_c uuid_len = LEN_UUID_16; } else if (type == GATT_INFO_TYPE_PAIR_128) { uuid_len = LEN_UUID_128; + } else { + GATT_TRACE_ERROR("invalid Info Response PDU format: %d", type); + gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); + return; } while (len >= uuid_len + 2) { @@ -796,7 +800,7 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len - 1)) ) { /* this is an error case that server's response containing a value length which is larger than MTU-2 or value_len > message total length -1 */ - GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: Discard response op_code=%d vale_len=%d > (MTU-2=%d or msg_len-1=%d)", + GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: Discard response op_code=%d value_len=%d > (MTU-2=%d or msg_len-1=%d)", op_code, value_len, (p_tcb->payload_size - 2), (len - 1)); gatt_end_operation(p_clcb, GATT_ERROR, NULL); return; @@ -884,7 +888,8 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 } /* read by type */ else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE) { - p_clcb->counter = len - 2; + /* value_len is the length of current record's value; use it to avoid overread when multiple records present */ + p_clcb->counter = value_len; p_clcb->s_handle = handle; if ( p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) { p_clcb->op_subtype = GATT_READ_BY_HANDLE; @@ -916,7 +921,7 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 /* UUID not matching */ if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid)) { - len -= (value_len + 2); + len -= (value_len + handle_len); continue; /* skip the result, and look for next one */ } else if (p_clcb->operation == GATTC_OPTYPE_READ) /* UUID match for read characteristic value */ @@ -1000,7 +1005,7 @@ void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); } } else { /* exception, should not happen */ - GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %p ", offset, p_clcb->p_attr_buf); + GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %p ", offset, p_clcb->p_attr_buf ? p_clcb->p_attr_buf:0); gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf); } } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_db.c b/components/bt/host/bluedroid/stack/gatt/gatt_db.c index 6c578e678f1..73037155f27 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_db.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_db.c @@ -363,6 +363,7 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, if (p_attr->handle >= s_handle && gatt_uuid_compare(type, attr_uuid)) { if (*p_len <= 2) { + *p_cur_handle = p_attr->handle; status = GATT_NO_RESOURCES; break; } @@ -375,15 +376,19 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, need_rsp = TRUE; status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id, need_rsp); - + if (status != GATT_PENDING) { + *p_cur_handle = p_attr->handle; + } /* one callback at a time */ break; } else if (status == GATT_SUCCESS || status == GATT_STACK_RSP) { if (status == GATT_STACK_RSP){ need_rsp = FALSE; status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id, need_rsp); - if(status == GATT_BUSY) + if (status != GATT_STACK_RSP) { + *p_cur_handle = p_attr->handle; break; + } if (!have_send_request){ have_send_request = true; @@ -400,6 +405,7 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, *p_len -= (len + 2); } else { GATT_TRACE_WARNING("format mismatch"); + *p_cur_handle = p_attr->handle; status = GATT_NO_RESOURCES; break; } @@ -546,6 +552,7 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, if (attr_val != NULL) { if (!copy_extra_byte_in_db(p_db, (void **)&p_char_val->p_value, sizeof(tGATT_ATTR_VAL))) { + deallocate_attr_in_db(p_db, p_char_decl); deallocate_attr_in_db(p_db, p_char_val); return 0; } @@ -733,7 +740,7 @@ tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle, } p_cur = (tGATT_ATTR16 *) p_db->p_attr_list; - + BOOLEAN found = FALSE; while (p_cur != NULL) { if (p_cur->handle == attr_handle) { /* for characteristic should not be set, return GATT_NOT_FOUND */ @@ -758,13 +765,14 @@ tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle, } else{ memcpy(p_cur->p_value->attr_val.attr_val, value, length); p_cur->p_value->attr_val.attr_len = length; + found = TRUE; } break; } p_cur = p_cur->p_next; } - return GATT_SUCCESS; + return found ? GATT_SUCCESS : GATT_NOT_FOUND; } /******************************************************************************* @@ -1205,8 +1213,8 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION,handle %04x,perm %04x", handle, perm); } /* LE security mode 2 attribute */ - else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) - && (perm & GATT_WRITE_ALLOWED) == 0) { + else if ((perm & GATT_WRITE_SIGNED_PERM) && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) + && !(perm & (GATT_PERM_WRITE | GATT_PERM_WRITE_ENCRYPTED | GATT_PERM_WRITE_ENC_MITM))) { status = GATT_INSUF_AUTHENTICATION; GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required,handle %04x,perm %04x", handle, perm); } else { /* writable: must be char value declaration or char descriptors */ diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_main.c b/components/bt/host/bluedroid/stack/gatt/gatt_main.c index 30b2d468332..5d57534f6ca 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_main.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_main.c @@ -1174,27 +1174,25 @@ void gatt_init_srv_chg (void) #if (GATTS_INCLUDED == TRUE) void gatt_proc_srv_chg (void) { - UINT8 start_idx, found_idx; - BD_ADDR bda; BOOLEAN srv_chg_ind_pending = FALSE; tGATT_TCB *p_tcb; - tBT_TRANSPORT transport; + list_node_t *p_node = NULL; GATT_TRACE_DEBUG ("gatt_proc_srv_chg"); if (gatt_cb.cb_info.p_srv_chg_callback && gatt_cb.handle_of_h_r) { gatt_set_srv_chg(); - start_idx = 0; - while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) { - p_tcb = gatt_get_tcb_by_idx(found_idx); - srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb); - if (!srv_chg_ind_pending) { - gatt_send_srv_chg_ind(bda); - } else { - GATT_TRACE_DEBUG ("discard srv chg - already has one in the queue"); + for (p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) { + p_tcb = list_node(p_node); + if (p_tcb->in_use && p_tcb->ch_state == GATT_CH_OPEN) { + srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb); + if (!srv_chg_ind_pending) { + gatt_send_srv_chg_ind(p_tcb->peer_bda); + } else { + GATT_TRACE_DEBUG ("discard srv chg - already has one in the queue"); + } } - start_idx = ++found_idx; } } } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 118dad4cb3e..25bc51a02c9 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -166,6 +166,12 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, GATT_TRACE_DEBUG ("process_read_multi_rsp status=%d mtu=%d", status, mtu); + if (!p_msg) { + p_cmd->status = GATT_INVALID_PDU; + GATT_TRACE_ERROR("process_read_multi_rsp - invalid p_msg"); + return TRUE; + } + if (p_cmd->multi_rsp_q == NULL) { p_cmd->multi_rsp_q = fixed_queue_new(QUEUE_SIZE_MAX); } @@ -287,6 +293,12 @@ static BOOLEAN process_read_multi_var_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS sta GATT_TRACE_DEBUG ("process_read_multi_var rsp status=%d mtu=%d", status, mtu); + if (!p_msg) { + GATT_TRACE_ERROR("process_read_multi_var_rsp - invalid p_msg"); + p_cmd->status = GATT_INVALID_PDU; + return TRUE; + } + if (p_cmd->multi_rsp_q == NULL) { p_cmd->multi_rsp_q = fixed_queue_new(QUEUE_SIZE_MAX); } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c index d5a4b3a5e96..c7db69b6f59 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c @@ -56,6 +56,15 @@ static void attr_uuid_to_bt_uuid(void *p_attr, tBT_UUID *p_uuid) } } +static UINT8 get_uuid_stream_len(tBT_UUID uuid) +{ + // gatt_build_uuid_to_stream always converts 32-bit UUID to 128-bit UUID + if (uuid.len == LEN_UUID_32) { + return LEN_UUID_128; + } + return uuid.len; +} + static size_t calculate_database_info_size(void) { UINT8 i; @@ -71,17 +80,17 @@ static size_t calculate_database_info_size(void) if (p_attr->uuid == GATT_UUID_PRI_SERVICE || p_attr->uuid == GATT_UUID_SEC_SERVICE) { // Service declaration - len += 4 + p_attr->p_value->uuid.len; + len += 4 + get_uuid_stream_len(p_attr->p_value->uuid); } else if (p_attr->uuid == GATT_UUID_INCLUDE_SERVICE) { // Included service declaration - len += 8 + p_attr->p_value->incl_handle.service_type.len; + len += 8 + get_uuid_stream_len(p_attr->p_value->incl_handle.service_type); } else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) { tBT_UUID char_uuid = {0}; // Characteristic declaration p_attr = (tGATT_ATTR16 *)p_attr->p_next; attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid); // Increment 1 to fetch characteristic uuid from value declaration attribute - len += 7 + char_uuid.len; + len += 7 + get_uuid_stream_len(char_uuid); } else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION || p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG || p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG || diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c index 9d38c24292b..1b817a0053c 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c @@ -74,7 +74,7 @@ const char *const op_code_name[] = { "ATT_OP_CODE_MAX" }; -static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, +const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -216,11 +216,12 @@ tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tB list_t *list = fixed_queue_get_list(gatt_cb.pending_new_srv_start_q); for (const list_node_t *node = list_begin(list); node != list_end(list); node = list_next(node)) { - p_buf = (tGATTS_PENDING_NEW_SRV_START *)list_node(node); - tGATTS_HNDL_RANGE *p = p_buf->p_new_srv_start; + tGATTS_PENDING_NEW_SRV_START *p_temp = (tGATTS_PENDING_NEW_SRV_START *)list_node(node); + tGATTS_HNDL_RANGE *p = p_temp->p_new_srv_start; if (gatt_uuid_compare(*p_app_uuid128, p->app_uuid128) && gatt_uuid_compare (*p_svc_uuid, p->svc_uuid) && (svc_inst == p->svc_inst)) { + p_buf = p_temp; GATT_TRACE_DEBUG("gatt_sr_is_new_srv_chg: Yes"); break; } @@ -449,19 +450,17 @@ void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p) void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id) { tGATT_HDL_LIST_ELEM *p_elem = &gatt_cb.hdl_list[0]; + tGATT_HDL_LIST_INFO *p_list_info = &gatt_cb.hdl_list_info; UINT8 i; for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_elem ++) { if (memcmp(p_app_id, &p_elem->asgn_range.app_uuid128, sizeof(tBT_UUID)) == 0) { + /* Remove from linked list first */ + gatt_remove_an_item_from_list(p_list_info, p_elem); + /* Free attribute value buffers */ gatt_free_attr_value_buffer(p_elem); - while (!fixed_queue_is_empty(p_elem->svc_db.svc_buffer)) { - osi_free(fixed_queue_dequeue(p_elem->svc_db.svc_buffer, 0)); - } - fixed_queue_free(p_elem->svc_db.svc_buffer, NULL); - p_elem->svc_db.svc_buffer = NULL; - - p_elem->svc_db.mem_free = 0; - p_elem->svc_db.p_attr_list = p_elem->svc_db.p_free_mem = NULL; + /* Free the handle buffer completely (including svc_buffer and setting in_use = FALSE) */ + gatt_free_hdl_buffer(p_elem); } } } @@ -631,7 +630,17 @@ BOOLEAN gatt_remove_a_srv_from_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ p_remove->p_next->p_prev = p_remove->p_prev; p_remove->p_prev->p_next = p_remove->p_next; } - p_list->count--; + // If the list is now empty, update p_last to NULL + if(p_list->p_first == NULL) { + p_list->p_last = NULL; + } + if (p_list->count) { + p_list->count --; + } else { + GATT_TRACE_ERROR("Error: p_list->count is already zero"); + } + + gatt_update_last_pri_srv_info(p_list); return TRUE; @@ -722,46 +731,20 @@ BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIS p_remove->p_next->p_prev = p_remove->p_prev; p_remove->p_prev->p_next = p_remove->p_next; } - p_list->count--; + // If the list is now empty, update p_last to NULL + if (p_list->p_first == NULL) { + p_list->p_last = NULL; + } + + if(p_list->count > 0) { + p_list->count--; + } else { + GATT_TRACE_ERROR("Error: p_list->count is already zero"); + } return TRUE; } -/******************************************************************************* -** -** Function gatt_find_the_connected_bda -** -** Description This function find the connected bda -** -** Returns TRUE if found -** -*******************************************************************************/ -BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx, - tBT_TRANSPORT *p_transport) -{ - BOOLEAN found = FALSE; - GATT_TRACE_DEBUG("gatt_find_the_connected_bda start_idx=%d", start_idx); - tGATT_TCB *p_tcb = NULL; - list_node_t *p_node = NULL; - p_tcb = gatt_get_tcb_by_idx(start_idx); - if (p_tcb) { - for(p_node = list_get_node(gatt_cb.p_tcb_list, p_tcb); p_node; p_node = list_next(p_node)) { - p_tcb = list_node(p_node); - if (p_tcb->in_use && p_tcb->ch_state == GATT_CH_OPEN) { - memcpy( bda, p_tcb->peer_bda, BD_ADDR_LEN); - *p_found_idx = p_tcb->tcb_idx; - *p_transport = p_tcb->transport; - found = TRUE; - GATT_TRACE_DEBUG("gatt_find_the_connected_bda bda :%02x-%02x-%02x-%02x-%02x-%02x", - bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - break; - } - } - GATT_TRACE_DEBUG("gatt_find_the_connected_bda found=%d found_idx=%d", found, p_tcb->tcb_idx); - } - return found; -} - #if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** @@ -1736,14 +1719,18 @@ tGATT_CLCB *gatt_clcb_alloc (UINT16 conn_id) if (list_length(gatt_cb.p_clcb_list) < GATT_CL_MAX_LCB) { p_clcb = (tGATT_CLCB *)osi_malloc(sizeof(tGATT_CLCB)); if (p_clcb) { - list_append(gatt_cb.p_clcb_list, p_clcb); - memset(p_clcb, 0, sizeof(tGATT_CLCB)); - p_clcb->in_use = TRUE; - p_clcb->conn_id = conn_id; - //Add index of the clcb same as conn_id - p_clcb->clcb_idx = conn_id; - p_clcb->p_reg = p_reg; - p_clcb->p_tcb = p_tcb; + if (!list_append(gatt_cb.p_clcb_list, p_clcb)) { + osi_free(p_clcb); + GATT_TRACE_ERROR("gatt_clcb_alloc: could not add clcb to list"); + return NULL; + } + memset(p_clcb, 0, sizeof(tGATT_CLCB)); + p_clcb->in_use = TRUE; + p_clcb->conn_id = conn_id; + //Add index of the clcb same as conn_id + p_clcb->clcb_idx = conn_id; + p_clcb->p_reg = p_reg; + p_clcb->p_tcb = p_tcb; } } return p_clcb; @@ -1761,6 +1748,10 @@ tGATT_CLCB *gatt_clcb_alloc (UINT16 conn_id) void gatt_clcb_dealloc (tGATT_CLCB *p_clcb) { if (p_clcb && p_clcb->in_use) { + if (p_clcb->p_attr_buf) { + osi_free(p_clcb->p_attr_buf); + p_clcb->p_attr_buf = NULL; + } btu_free_timer(&p_clcb->rsp_timer_ent); memset(p_clcb, 0, sizeof(tGATT_CLCB)); list_remove(gatt_cb.p_clcb_list, p_clcb); @@ -2265,6 +2256,7 @@ void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_data) if (p_clcb->p_attr_buf) { osi_free(p_clcb->p_attr_buf); + p_clcb->p_attr_buf = NULL; } #if !CONFIG_BT_STACK_NO_LOG diff --git a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h index 4d5ea687764..76432c4f1b6 100644 --- a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h +++ b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h @@ -603,6 +603,8 @@ extern void gatt_set_err_rsp(BOOLEAN enable, UINT8 req_op_code, UINT8 err_status } #endif +extern const UINT8 base_uuid[LEN_UUID_128]; + /* internal functions */ extern void gatt_init (void); extern void gatt_free(void); @@ -658,7 +660,6 @@ extern tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid extern BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb); extern tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda); -extern BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx, tBT_TRANSPORT *p_transport); extern void gatt_set_srv_chg(void); extern void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr); extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start);