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 6242e0244c)

Co-authored-by: zhiweijian <zhiweijian@espressif.com>
This commit is contained in:
Zhi Wei Jian
2026-03-31 14:29:24 +08:00
committed by zhiweijian
parent d3217033ab
commit 8f972e76ac
11 changed files with 163 additions and 109 deletions
@@ -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);
@@ -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;
@@ -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;
}
}
@@ -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;
@@ -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);
}
}
@@ -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 */
@@ -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;
}
}
}
@@ -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);
}
@@ -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 ||
@@ -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
@@ -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);