From: Ɓukasz Rymanowski Date: Fri, 1 May 2020 00:40:58 +0000 (+0200) Subject: stack/gatt: Extend calls with CID X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=7a496c86ba675e1023a5b84de686a823834896db;p=android-x86%2Fsystem-bt.git stack/gatt: Extend calls with CID This is preparation for EATT Tag: #feature Bug: 159786353 Sponsor: jpawlowski@ Test: atest net_test_stack Change-Id: Ie209b705f6cc458286e9566919280ed5e2de60c9 --- diff --git a/stack/gatt/att_protocol.cc b/stack/gatt/att_protocol.cc index 5d3d4a818..00ebe1f21 100644 --- a/stack/gatt/att_protocol.cc +++ b/stack/gatt/att_protocol.cc @@ -322,13 +322,14 @@ BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code, * Description Send message to L2CAP. * ******************************************************************************/ -tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, BT_HDR* p_toL2CAP) { +tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, uint16_t lcid, + BT_HDR* p_toL2CAP) { uint16_t l2cap_ret; - if (tcb.att_lcid == L2CAP_ATT_CID) - l2cap_ret = L2CA_SendFixedChnlData(L2CAP_ATT_CID, tcb.peer_bda, p_toL2CAP); + if (lcid == L2CAP_ATT_CID) + l2cap_ret = L2CA_SendFixedChnlData(lcid, tcb.peer_bda, p_toL2CAP); else - l2cap_ret = (uint16_t)L2CA_DataWrite(tcb.att_lcid, p_toL2CAP); + l2cap_ret = (uint16_t)L2CA_DataWrite(lcid, p_toL2CAP); if (l2cap_ret == L2CAP_DW_FAILED) { LOG(ERROR) << __func__ << ": failed to write data to L2CAP"; @@ -394,11 +395,11 @@ BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code, * * ******************************************************************************/ -tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) { +tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_msg) { if (p_msg == NULL) return GATT_NO_RESOURCES; p_msg->offset = L2CAP_MIN_OFFSET; - return attp_send_msg_to_l2cap(tcb, p_msg); + return attp_send_msg_to_l2cap(tcb, cid, p_msg); } /******************************************************************************* @@ -417,13 +418,14 @@ tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t cmd_code, BT_HDR* p_cmd) { cmd_code &= ~GATT_AUTH_SIGN_MASK; - if (!tcb.cl_cmd_q.empty() && cmd_code != GATT_HANDLE_VALUE_CONF) { + if (gatt_tcb_is_cid_busy(tcb, p_clcb->cid) && + cmd_code != GATT_HANDLE_VALUE_CONF) { gatt_cmd_enq(tcb, p_clcb, true, cmd_code, p_cmd); return GATT_CMD_STARTED; } /* no pending request or value confirmation */ - tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_cmd); + tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_clcb->cid, p_cmd); if (att_ret != GATT_CONGESTED && att_ret != GATT_SUCCESS) { return GATT_INTERNAL_ERROR; } @@ -458,6 +460,8 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, tGATT_CL_MSG* p_msg) { BT_HDR* p_cmd = NULL; uint16_t offset = 0, handle; + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, p_clcb->cid); + switch (op_code) { case GATT_REQ_MTU: if (p_msg->mtu > GATT_MAX_MTU_SIZE) return GATT_ILLEGAL_PARAMETER; @@ -504,7 +508,7 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, return GATT_ILLEGAL_PARAMETER; p_cmd = attp_build_value_cmd( - tcb.payload_size, op_code, p_msg->attr_value.handle, offset, + payload_size, op_code, p_msg->attr_value.handle, offset, p_msg->attr_value.len, p_msg->attr_value.value); break; @@ -513,14 +517,14 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, break; case GATT_REQ_FIND_TYPE_VALUE: - p_cmd = attp_build_read_by_type_value_cmd(tcb.payload_size, + p_cmd = attp_build_read_by_type_value_cmd(payload_size, &p_msg->find_type_value); break; case GATT_REQ_READ_MULTI: - p_cmd = attp_build_read_multi_cmd(tcb.payload_size, - p_msg->read_multi.num_handles, - p_msg->read_multi.handles); + p_cmd = + attp_build_read_multi_cmd(payload_size, p_msg->read_multi.num_handles, + p_msg->read_multi.handles); break; default: diff --git a/stack/gatt/gatt_api.cc b/stack/gatt/gatt_api.cc index fd025daba..8240e74d3 100644 --- a/stack/gatt/gatt_api.cc +++ b/stack/gatt/gatt_api.cc @@ -431,7 +431,11 @@ tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle, memcpy(indication.value, p_val, val_len); indication.auth_req = GATT_AUTH_REQ_NONE; - if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) { + uint16_t* indicate_handle_p = NULL; + uint16_t cid; + + if (!gatt_tcb_get_cid_available_for_indication(p_tcb, p_reg->eatt_support, + &indicate_handle_p, &cid)) { VLOG(1) << "Add a pending indication"; gatt_add_pending_ind(p_tcb, &indication); return GATT_SUCCESS; @@ -443,9 +447,9 @@ tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle, attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg); if (!p_msg) return GATT_NO_RESOURCES; - tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, p_msg); + tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, cid, p_msg); if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) { - p_tcb->indicate_handle = indication.handle; + *indicate_handle_p = indication.handle; gatt_start_conf_timer(p_tcb); } return cmd_status; @@ -494,10 +498,13 @@ tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id, tGATT_STATUS cmd_sent; tGATT_SR_MSG gatt_sr_msg; gatt_sr_msg.attr_value = notif; + + uint16_t cid = gatt_tcb_get_att_cid(*p_tcb); + BT_HDR* p_buf = attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg); if (p_buf != NULL) { - cmd_sent = attp_send_sr_msg(*p_tcb, p_buf); + cmd_sent = attp_send_sr_msg(*p_tcb, cid, p_buf); } else cmd_sent = GATT_NO_RESOURCES; return cmd_sent; @@ -519,7 +526,6 @@ tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id, ******************************************************************************/ tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id, tGATT_STATUS status, tGATTS_RSP* p_msg) { - tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER; tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id); uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id); tGATT_REG* p_reg = gatt_get_regcb(gatt_if); @@ -533,16 +539,17 @@ tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id, return (tGATT_STATUS)GATT_INVALID_CONN_ID; } - if (p_tcb->sr_cmd.trans_id != trans_id) { + tGATT_SR_CMD* sr_res_p = gatt_sr_get_cmd_by_trans_id(p_tcb, trans_id); + + if (!sr_res_p) { LOG(ERROR) << "conn_id=" << loghex(conn_id) - << " waiting for op_code=" << loghex(p_tcb->sr_cmd.op_code); + << " waiting for other op_code "; return (GATT_WRONG_STATE); } - /* Process App response */ - cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id, - p_tcb->sr_cmd.op_code, status, p_msg); - return cmd_sent; + /* Process App response */ + return gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id, sr_res_p->op_code, + status, p_msg, sr_res_p); } /******************************************************************************/ @@ -593,6 +600,8 @@ tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) { tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id); if (!p_clcb) return GATT_NO_RESOURCES; + /* For this request only ATT CID is valid */ + p_clcb->cid = L2CAP_ATT_CID; p_clcb->p_tcb->payload_size = mtu; p_clcb->operation = GATTC_OPTYPE_CONFIG; tGATT_CL_MSG gatt_cl_msg; @@ -709,7 +718,8 @@ tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type, p_clcb->op_subtype = type; p_clcb->auth_req = p_read->by_handle.auth_req; p_clcb->counter = 0; - p_clcb->read_req_current_mtu = p_tcb->payload_size; + p_clcb->read_req_current_mtu = + gatt_tcb_get_payload_size_tx(*p_tcb, p_clcb->cid); switch (type) { case GATT_READ_BY_TYPE: diff --git a/stack/gatt/gatt_auth.cc b/stack/gatt/gatt_auth.cc index f3cb56fe5..e932987d5 100644 --- a/stack/gatt/gatt_auth.cc +++ b/stack/gatt/gatt_auth.cc @@ -94,7 +94,7 @@ static bool gatt_sign_data(tGATT_CLCB* p_clcb) { * Returns * ******************************************************************************/ -void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf) { +void gatt_verify_signature(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) { uint16_t cmd_len; uint8_t op_code; uint8_t *p, *p_orig = (uint8_t*)(p_buf + 1) + p_buf->offset; @@ -116,7 +116,7 @@ void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf) { } STREAM_TO_UINT8(op_code, p_orig); - gatt_server_handle_client_req(tcb, op_code, (uint16_t)(p_buf->len - 1), + gatt_server_handle_client_req(tcb, cid, op_code, (uint16_t)(p_buf->len - 1), p_orig); } /******************************************************************************* diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc index be6eca371..6ad0b5ebc 100644 --- a/stack/gatt/gatt_cl.cc +++ b/stack/gatt/gatt_cl.cc @@ -22,10 +22,10 @@ * ******************************************************************************/ -#include "bt_target.h" - #include + #include "bt_common.h" +#include "bt_target.h" #include "bt_utils.h" #include "gatt_int.h" #include "l2c_api.h" @@ -213,6 +213,8 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) { CHECK(p_clcb->p_attr_buf); tGATT_VALUE& attr = *((tGATT_VALUE*)p_clcb->p_attr_buf); + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, p_clcb->cid); + switch (p_clcb->op_subtype) { case GATT_WRITE_NO_RSP: { p_clcb->s_handle = attr.handle; @@ -231,7 +233,7 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) { } case GATT_WRITE: { - if (attr.len <= (tcb.payload_size - GATT_HDR_SIZE)) { + if (attr.len <= (payload_size - GATT_HDR_SIZE)) { p_clcb->s_handle = attr.handle; uint8_t rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_WRITE, @@ -332,9 +334,10 @@ void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) { VLOG(1) << __func__ << StringPrintf(" type=0x%x", type); uint16_t to_send = p_attr->len - p_attr->offset; - if (to_send > (tcb.payload_size - + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, p_clcb->cid); + if (to_send > (payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = uint16_t offset bytes */ - to_send = tcb.payload_size - GATT_WRITE_LONG_HDR_SIZE; + to_send = payload_size - GATT_WRITE_LONG_HDR_SIZE; p_clcb->s_handle = p_attr->handle; @@ -716,8 +719,8 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, } STREAM_TO_UINT8(value_len, p); - - if ((value_len > (tcb.payload_size - 2)) || (value_len > (len - 1))) { + uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, p_clcb->cid); + if ((value_len > (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 */ @@ -725,7 +728,7 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, << StringPrintf( ": Discard response op_code=%d " "vale_len=%d > (MTU-2=%d or msg_len-1=%d)", - op_code, value_len, (tcb.payload_size - 2), (len - 1)); + op_code, value_len, (payload_size - 2), (len - 1)); gatt_end_operation(p_clcb, GATT_ERROR, NULL); return; } @@ -808,7 +811,7 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, p_clcb->op_subtype == GATT_READ_BY_TYPE) { p_clcb->counter = len - 2; p_clcb->s_handle = handle; - if (p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) { + if (p_clcb->counter == (payload_size - 4)) { p_clcb->op_subtype = GATT_READ_BY_HANDLE; if (!p_clcb->p_attr_buf) p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN); @@ -895,6 +898,8 @@ void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t offset = p_clcb->counter; uint8_t* p = p_data; + uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, p_clcb->cid); + if (p_clcb->operation == GATTC_OPTYPE_READ) { if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) { p_clcb->counter = len; @@ -915,12 +920,12 @@ void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, /* full packet for read or read blob rsp */ bool packet_is_full; - if (tcb.payload_size == p_clcb->read_req_current_mtu) { - packet_is_full = (len == (tcb.payload_size - 1)); + if (payload_size == p_clcb->read_req_current_mtu) { + packet_is_full = (len == (payload_size - 1)); } else { packet_is_full = (len == (p_clcb->read_req_current_mtu - 1) || - len == (tcb.payload_size - 1)); - p_clcb->read_req_current_mtu = tcb.payload_size; + len == (payload_size - 1)); + p_clcb->read_req_current_mtu = payload_size; } /* send next request if needed */ @@ -1026,14 +1031,24 @@ uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) { /** Find next command in queue and sent to server */ bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) { + std::queue* cl_cmd_q; + while (!tcb.cl_cmd_q.empty()) { - tGATT_CMD_Q& cmd = tcb.cl_cmd_q.front(); - if (!cmd.to_send || cmd.p_cmd == NULL) return false; + if (!tcb.cl_cmd_q.empty()) { + cl_cmd_q = &tcb.cl_cmd_q; + } + + tGATT_CMD_Q& cmd = cl_cmd_q->front(); + if (!cmd.to_send || cmd.p_cmd == NULL) { + return false; + } + + tGATT_STATUS att_ret; + att_ret = attp_send_msg_to_l2cap(tcb, cmd.cid, cmd.p_cmd); - tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, cmd.p_cmd); if (att_ret != GATT_SUCCESS && att_ret != GATT_CONGESTED) { LOG(ERROR) << __func__ << ": L2CAP sent error"; - tcb.cl_cmd_q.pop(); + cl_cmd_q->pop(); continue; } @@ -1043,7 +1058,7 @@ bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) { if (cmd.op_code == GATT_CMD_WRITE || cmd.op_code == GATT_SIGN_CMD_WRITE) { /* dequeue the request if is write command or sign write */ uint8_t rsp_code; - tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &rsp_code); + tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, cmd.cid, &rsp_code); /* send command complete callback here */ gatt_end_operation(p_clcb, att_ret, NULL); @@ -1062,13 +1077,18 @@ bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) { } /** This function is called to handle the server response to client */ -void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data) { +void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data) { + VLOG(1) << __func__ << " opcode: " << loghex(op_code); + + uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, cid); + if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF) { - if (len >= tcb.payload_size) { + if (len >= payload_size) { LOG(ERROR) << StringPrintf( "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1, - tcb.payload_size); + payload_size); return; } @@ -1077,7 +1097,7 @@ void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code, } uint8_t cmd_code = 0; - tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &cmd_code); + tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, cid, &cmd_code); uint8_t rsp_code = gatt_cmd_to_rsp_code(cmd_code); if (!p_clcb || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) { LOG(WARNING) << StringPrintf( @@ -1092,16 +1112,16 @@ void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code, return; } - alarm_cancel(p_clcb->gatt_rsp_timer_ent); + gatt_stop_rsp_timer(p_clcb); p_clcb->retry_count = 0; /* the size of the message may not be bigger than the local max PDU size*/ /* The message has to be smaller than the agreed MTU, len does not count * op_code */ - if (len >= tcb.payload_size) { + if (len >= payload_size) { LOG(ERROR) << StringPrintf( "%s: invalid response pkt size: %d, PDU size: %d", __func__, len + 1, - tcb.payload_size); + payload_size); gatt_end_operation(p_clcb, GATT_ERROR, NULL); } else { switch (op_code) { diff --git a/stack/gatt/gatt_db.cc b/stack/gatt/gatt_db.cc index 4807f94c2..c3385a23f 100644 --- a/stack/gatt/gatt_db.cc +++ b/stack/gatt/gatt_db.cc @@ -45,8 +45,8 @@ using bluetooth::Uuid; static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const Uuid& uuid, tGATT_PERM perm); static tGATT_STATUS gatts_send_app_read_request( - tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset, - uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type); + tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t handle, + uint16_t offset, uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type); /** * Initialize a memory space to be a service database. @@ -254,10 +254,10 @@ static tGATT_STATUS read_attr_value(tGATT_ATTR& attr16, uint16_t offset, * ******************************************************************************/ tGATT_STATUS gatts_db_read_attr_value_by_type( - tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp, - uint16_t s_handle, uint16_t e_handle, const Uuid& type, uint16_t* p_len, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id, - uint16_t* p_cur_handle) { + tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code, + BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle, const Uuid& type, + uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size, + uint32_t trans_id, uint16_t* p_cur_handle) { tGATT_STATUS status = GATT_NOT_FOUND; uint16_t len = 0; uint8_t* p = (uint8_t*)(p_rsp + 1) + p_rsp->len + L2CAP_MIN_OFFSET; @@ -276,8 +276,8 @@ tGATT_STATUS gatts_db_read_attr_value_by_type( &len, sec_flag, key_size); if (status == GATT_PENDING) { - status = gatts_send_app_read_request(tcb, op_code, attr.handle, 0, - trans_id, attr.gatt_type); + status = gatts_send_app_read_request(tcb, cid, op_code, attr.handle, + 0, trans_id, attr.gatt_type); /* one callback at a time */ break; @@ -442,9 +442,10 @@ tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) { * ******************************************************************************/ tGATT_STATUS gatts_read_attr_value_by_handle( - tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, - uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) { + tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code, + uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len, + uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size, + uint32_t trans_id) { tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); if (!p_attr) return GATT_NOT_FOUND; @@ -454,8 +455,8 @@ tGATT_STATUS gatts_read_attr_value_by_handle( mtu, p_len, sec_flag, key_size); if (status == GATT_PENDING) { - status = gatts_send_app_read_request(tcb, op_code, p_attr->handle, offset, - trans_id, p_attr->gatt_type); + status = gatts_send_app_read_request(tcb, cid, op_code, p_attr->handle, + offset, trans_id, p_attr->gatt_type); } return status; } @@ -678,14 +679,14 @@ static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const Uuid& uuid, * ******************************************************************************/ static tGATT_STATUS gatts_send_app_read_request( - tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset, - uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) { + tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t handle, + uint16_t offset, uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) { tGATT_SRV_LIST_ELEM& el = *gatt_sr_find_i_rcb_by_handle(handle); uint16_t conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if); if (trans_id == 0) { - trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle); - gatt_sr_update_cback_cnt(tcb, el.gatt_if, true, true); + trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, handle); + gatt_sr_update_cback_cnt(tcb, cid, el.gatt_if, true, true); } if (trans_id != 0) { diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h index ab8283932..6bdd97a9a 100644 --- a/stack/gatt/gatt_int.h +++ b/stack/gatt/gatt_int.h @@ -205,6 +205,7 @@ typedef struct { tGATT_CLCB* p_clcb; uint8_t op_code; bool to_send; + uint16_t cid; } tGATT_CMD_Q; #if GATT_MAX_SR_PROFILES <= 8 @@ -225,6 +226,7 @@ typedef struct { uint8_t op_code; uint8_t status; uint8_t cback_cnt[GATT_MAX_APPS]; + uint16_t cid; } tGATT_SR_CMD; #define GATT_CH_CLOSE 0 @@ -327,6 +329,7 @@ struct tGATT_CLCB { uint8_t retry_count; uint16_t read_req_current_mtu; /* This is the MTU value that the read was initiated with */ + uint16_t cid; }; typedef struct { @@ -414,7 +417,7 @@ extern bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, extern bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBT_TRANSPORT transport, uint8_t initiating_phys, tGATT_IF gatt_if); -extern void gatt_data_process(tGATT_TCB& p_tcb, BT_HDR* p_buf); +extern void gatt_data_process(tGATT_TCB& p_tcb, uint16_t cid, BT_HDR* p_buf); extern void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb, bool is_add, bool check_acl_link); @@ -439,8 +442,10 @@ extern tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, tGATT_CL_MSG* p_msg); extern BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code, tGATT_SR_MSG* p_msg); -extern tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg); -extern tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, BT_HDR* p_toL2CAP); +extern tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, + BT_HDR* p_msg); +extern tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, uint16_t cid, + BT_HDR* p_toL2CAP); /* utility functions */ extern uint8_t* gatt_dbg_op_name(uint8_t op_code); @@ -455,14 +460,15 @@ extern void gatt_sr_get_sec_info(const RawAddress& rem_bda, tBT_TRANSPORT transport, uint8_t* p_sec_flag, uint8_t* p_key_size); extern void gatt_start_rsp_timer(tGATT_CLCB* p_clcb); +extern void gatt_stop_rsp_timer(tGATT_CLCB* p_clcb); extern void gatt_start_conf_timer(tGATT_TCB* p_tcb); extern void gatt_rsp_timeout(void* data); extern void gatt_indication_confirmation_timeout(void* data); extern void gatt_ind_ack_timeout(void* data); extern void gatt_start_ind_ack_timer(tGATT_TCB& tcb); -extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code, - uint8_t op_code, uint16_t handle, - bool deq); +extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint16_t cid, + uint8_t err_code, uint8_t op_code, + uint16_t handle, bool deq); extern bool gatt_is_srv_chg_ind_pending(tGATT_TCB* p_tcb); extern tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list( @@ -494,30 +500,47 @@ extern std::list::iterator gatt_sr_find_i_rcb_by_handle( extern tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if, uint32_t trans_id, uint8_t op_code, tGATT_STATUS status, - tGATTS_RSP* p_msg); -extern void gatt_server_handle_client_req(tGATT_TCB& p_tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data); + tGATTS_RSP* p_msg, + tGATT_SR_CMD* sr_res_p); +extern void gatt_server_handle_client_req(tGATT_TCB& p_tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data); extern void gatt_sr_send_req_callback(uint16_t conn_id, uint32_t trans_id, uint8_t op_code, tGATTS_DATA* p_req_data); -extern uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint8_t op_code, - uint16_t handle); +extern uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t handle); extern bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda); extern void gatt_notify_phy_updated(uint8_t status, uint16_t handle, uint8_t tx_phy, uint8_t rx_phy); /* */ +extern bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid); + extern tGATT_REG* gatt_get_regcb(tGATT_IF gatt_if); extern bool gatt_is_clcb_allocated(uint16_t conn_id); extern tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id); + +extern bool gatt_tcb_get_cid_available_for_indication( + tGATT_TCB* p_tcb, bool eatt_support, uint16_t** indicate_handle_p, + uint16_t* cid_p); +extern bool gatt_tcb_find_indicate_handle(tGATT_TCB& tcb, uint16_t cid, + uint16_t* indicated_handle_p); +extern uint16_t gatt_tcb_get_att_cid(tGATT_TCB& tcb); +extern uint16_t gatt_tcb_get_payload_size_tx(tGATT_TCB& tcb, uint16_t cid); +extern uint16_t gatt_tcb_get_payload_size_rx(tGATT_TCB& tcb, uint16_t cid); extern void gatt_clcb_dealloc(tGATT_CLCB* p_clcb); extern void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& p_tcb); extern bool gatt_sr_is_cback_cnt_zero(tGATT_TCB& p_tcb); extern bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& p_tcb); -extern void gatt_sr_reset_cback_cnt(tGATT_TCB& p_tcb); +extern void gatt_sr_reset_cback_cnt(tGATT_TCB& p_tcb, uint16_t cid); extern void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb); -extern void gatt_sr_update_cback_cnt(tGATT_TCB& p_tcb, tGATT_IF gatt_if, - bool is_inc, bool is_reset_first); +extern tGATT_SR_CMD* gatt_sr_get_cmd_by_trans_id(tGATT_TCB* p_tcb, + uint32_t trans_id); +extern tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid); +extern void gatt_sr_update_cback_cnt(tGATT_TCB& p_tcb, uint16_t cid, + tGATT_IF gatt_if, bool is_inc, + bool is_reset_first); extern void gatt_sr_update_prep_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if, bool is_inc, bool is_reset_first); @@ -545,17 +568,19 @@ extern void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, extern void gatt_act_discovery(tGATT_CLCB* p_clcb); extern void gatt_act_read(tGATT_CLCB* p_clcb, uint16_t offset); extern void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act); -extern tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint8_t* p_opcode); +extern tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid, + uint8_t* p_opcode); extern void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send, uint8_t op_code, BT_HDR* p_buf); -extern void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data); +extern void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data); extern void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, tGATT_EXEC_FLAG flag); /* gatt_auth.cc */ extern bool gatt_security_check_start(tGATT_CLCB* p_clcb); -extern void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf); +extern void gatt_verify_signature(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf); extern tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB& tcb); extern tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb); extern void gatt_set_sec_act(tGATT_TCB* p_tcb, tGATT_SEC_ACTION sec_act); @@ -573,14 +598,14 @@ extern uint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm, extern uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm, const bluetooth::Uuid& dscp_uuid); extern tGATT_STATUS gatts_db_read_attr_value_by_type( - tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp, - uint16_t s_handle, uint16_t e_handle, const bluetooth::Uuid& type, - uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size, - uint32_t trans_id, uint16_t* p_cur_handle); + tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code, + BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle, + const bluetooth::Uuid& type, uint16_t* p_len, tGATT_SEC_FLAG sec_flag, + uint8_t key_size, uint32_t trans_id, uint16_t* p_cur_handle); extern tGATT_STATUS gatts_read_attr_value_by_handle( - tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, - uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id); + tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code, + uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len, + uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id); extern tGATT_STATUS gatts_write_attr_perm_check( tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, uint16_t offset, uint8_t* p_data, uint16_t len, tGATT_SEC_FLAG sec_flag, uint8_t key_size); diff --git a/stack/gatt/gatt_main.cc b/stack/gatt/gatt_main.cc index fff9f75f2..f524d41b1 100644 --- a/stack/gatt/gatt_main.cc +++ b/stack/gatt/gatt_main.cc @@ -543,7 +543,7 @@ static void gatt_le_data_ind(uint16_t chan, const RawAddress& bd_addr, LOG(WARNING) << "ATT - Ignored L2CAP data while in state: " << +gatt_get_ch_state(p_tcb); } else - gatt_data_process(*p_tcb, p_buf); + gatt_data_process(*p_tcb, L2CAP_ATT_CID, p_buf); } osi_free(p_buf); @@ -773,7 +773,7 @@ static void gatt_l2cif_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) { tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid); if (p_tcb && gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) { /* process the data */ - gatt_data_process(*p_tcb, p_buf); + gatt_data_process(*p_tcb, lcid, p_buf); } osi_free(p_buf); @@ -838,7 +838,7 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) { * Returns void * ******************************************************************************/ -void gatt_data_process(tGATT_TCB& tcb, BT_HDR* p_buf) { +void gatt_data_process(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) { uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset; uint8_t op_code, pseudo_op_code; @@ -858,18 +858,18 @@ void gatt_data_process(tGATT_TCB& tcb, BT_HDR* p_buf) { */ LOG(ERROR) << __func__ << ": ATT - Rcvd L2CAP data, unknown cmd: " << loghex(op_code); - gatt_send_error_rsp(tcb, GATT_REQ_NOT_SUPPORTED, op_code, 0, false); + gatt_send_error_rsp(tcb, cid, GATT_REQ_NOT_SUPPORTED, op_code, 0, false); return; } if (op_code == GATT_SIGN_CMD_WRITE) { - gatt_verify_signature(tcb, p_buf); + gatt_verify_signature(tcb, cid, p_buf); } else { /* message from client */ if ((op_code % 2) == 0) - gatt_server_handle_client_req(tcb, op_code, msg_len, p); + gatt_server_handle_client_req(tcb, cid, op_code, msg_len, p); else - gatt_client_handle_server_rsp(tcb, op_code, msg_len, p); + gatt_client_handle_server_rsp(tcb, cid, op_code, msg_len, p); } } diff --git a/stack/gatt/gatt_sr.cc b/stack/gatt/gatt_sr.cc index 6336adae6..0346b4096 100644 --- a/stack/gatt/gatt_sr.cc +++ b/stack/gatt/gatt_sr.cc @@ -21,7 +21,6 @@ * this file contains the GATT server functions * ******************************************************************************/ - #include "bt_target.h" #include "osi/include/osi.h" @@ -46,10 +45,14 @@ using bluetooth::Uuid; * Returns void * ******************************************************************************/ -uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint8_t op_code, uint16_t handle) { +uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, + uint16_t handle) { tGATT_SR_CMD* p_cmd = &tcb.sr_cmd; + uint32_t trans_id = 0; + p_cmd->cid = cid; + if ((p_cmd->op_code == 0) || (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */ { @@ -228,42 +231,44 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status, tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if, UNUSED_ATTR uint32_t trans_id, uint8_t op_code, tGATT_STATUS status, - tGATTS_RSP* p_msg) { + tGATTS_RSP* p_msg, + tGATT_SR_CMD* sr_res_p) { tGATT_STATUS ret_code = GATT_SUCCESS; + uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, sr_res_p->cid); VLOG(1) << __func__ << " gatt_if=" << +gatt_if; - gatt_sr_update_cback_cnt(tcb, gatt_if, false, false); + gatt_sr_update_cback_cnt(tcb, sr_res_p->cid, gatt_if, false, false); if (op_code == GATT_REQ_READ_MULTI) { /* If no error and still waiting, just return */ - if (!process_read_multi_rsp(&tcb.sr_cmd, status, p_msg, tcb.payload_size)) + if (!process_read_multi_rsp(sr_res_p, status, p_msg, payload_size)) return (GATT_SUCCESS); } else { if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS) gatt_sr_update_prep_cnt(tcb, gatt_if, true, false); if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS) - gatt_sr_reset_cback_cnt(tcb); + gatt_sr_reset_cback_cnt(tcb, sr_res_p->cid); - tcb.sr_cmd.status = status; + sr_res_p->status = status; if (gatt_sr_is_cback_cnt_zero(tcb) && status == GATT_SUCCESS) { - if (tcb.sr_cmd.p_rsp_msg == NULL) { - tcb.sr_cmd.p_rsp_msg = attp_build_sr_msg(tcb, (uint8_t)(op_code + 1), - (tGATT_SR_MSG*)p_msg); + if (sr_res_p->p_rsp_msg == NULL) { + sr_res_p->p_rsp_msg = attp_build_sr_msg(tcb, (uint8_t)(op_code + 1), + (tGATT_SR_MSG*)p_msg); } else { LOG(ERROR) << "Exception!!! already has respond message"; } } } if (gatt_sr_is_cback_cnt_zero(tcb)) { - if ((tcb.sr_cmd.status == GATT_SUCCESS) && (tcb.sr_cmd.p_rsp_msg)) { - ret_code = attp_send_sr_msg(tcb, tcb.sr_cmd.p_rsp_msg); - tcb.sr_cmd.p_rsp_msg = NULL; + if ((sr_res_p->status == GATT_SUCCESS) && (sr_res_p->p_rsp_msg)) { + ret_code = attp_send_sr_msg(tcb, sr_res_p->cid, sr_res_p->p_rsp_msg); + sr_res_p->p_rsp_msg = NULL; } else { - ret_code = - gatt_send_error_rsp(tcb, status, op_code, tcb.sr_cmd.handle, false); + ret_code = gatt_send_error_rsp(tcb, sr_res_p->cid, status, op_code, + sr_res_p->handle, false); } gatt_dequeue_sr_cmd(tcb); @@ -284,8 +289,8 @@ tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if, * Returns void * ******************************************************************************/ -void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, + uint16_t len, uint8_t* p_data) { uint8_t *p = p_data, flag, i = 0; uint32_t trans_id = 0; tGATT_IF gatt_if; @@ -297,7 +302,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, << "Conformance tst: forced err rspv for Execute Write: error status=" << +gatt_cb.err_status; - gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, + gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, false); return; @@ -307,7 +312,8 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, if (len < sizeof(flag)) { android_errorWriteLog(0x534e4554, "73172115"); LOG(ERROR) << __func__ << "invalid length"; - gatt_send_error_rsp(tcb, GATT_INVALID_PDU, GATT_REQ_EXEC_WRITE, 0, false); + gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, GATT_REQ_EXEC_WRITE, 0, + false); return; } @@ -318,7 +324,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, /* no prep write is queued */ if (!gatt_sr_is_prep_cnt_zero(tcb)) { - trans_id = gatt_sr_enqueue_cmd(tcb, op_code, 0); + trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, 0); gatt_sr_copy_prep_cnt_to_cback_cnt(tcb); for (i = 0; i < GATT_MAX_APPS; i++) { @@ -335,7 +341,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, } else /* nothing needs to be executed , send response now */ { LOG(ERROR) << "gatt_process_exec_write_req: no prepare write pending"; - gatt_send_error_rsp(tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false); + gatt_send_error_rsp(tcb, cid, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false); } } @@ -349,8 +355,8 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, * Returns void * ******************************************************************************/ -void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, + uint16_t len, uint8_t* p_data) { uint32_t trans_id; uint16_t handle = 0, ll = len; uint8_t* p = p_data; @@ -369,8 +375,8 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, STREAM_TO_UINT16(handle, p); - gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, - false); + gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, gatt_cb.req_op_code, + handle, false); return; } @@ -407,9 +413,12 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, if (err == GATT_SUCCESS) { trans_id = - gatt_sr_enqueue_cmd(tcb, op_code, tcb.sr_cmd.multi_req.handles[0]); + gatt_sr_enqueue_cmd(tcb, cid, op_code, tcb.sr_cmd.multi_req.handles[0]); if (trans_id != 0) { - gatt_sr_reset_cback_cnt(tcb); /* read multiple use multi_rsp_q's count*/ + tGATT_SR_CMD* sr_cmd_p = gatt_sr_get_cmd_by_cid(tcb, cid); + + gatt_sr_reset_cback_cnt(tcb, + cid); /* read multiple use multi_rsp_q's count*/ for (ll = 0; ll < tcb.sr_cmd.multi_req.num_handles; ll++) { tGATTS_RSP* p_msg = (tGATTS_RSP*)osi_calloc(sizeof(tGATTS_RSP)); @@ -418,13 +427,13 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, p_msg->attr_value.handle = handle; err = gatts_read_attr_value_by_handle( - tcb, it->p_db, op_code, handle, 0, p_msg->attr_value.value, + tcb, cid, it->p_db, op_code, handle, 0, p_msg->attr_value.value, &p_msg->attr_value.len, GATT_MAX_ATTR_LEN, sec_flag, key_size, trans_id); if (err == GATT_SUCCESS) { gatt_sr_process_app_rsp(tcb, it->gatt_if, trans_id, op_code, - GATT_SUCCESS, p_msg); + GATT_SUCCESS, p_msg, sr_cmd_p); } /* either not using or done using the buffer, release it now */ osi_free(p_msg); @@ -436,7 +445,7 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, /* in theroy BUSY is not possible(should already been checked), protected * check */ if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY) - gatt_send_error_rsp(tcb, err, op_code, handle, false); + gatt_send_error_rsp(tcb, cid, err, op_code, handle, false); } /******************************************************************************* @@ -450,13 +459,16 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, * ******************************************************************************/ static tGATT_STATUS gatt_build_primary_service_rsp( - BT_HDR* p_msg, tGATT_TCB& tcb, uint8_t op_code, uint16_t s_hdl, - uint16_t e_hdl, UNUSED_ATTR uint8_t* p_data, const Uuid& value) { + BT_HDR* p_msg, tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, + uint16_t s_hdl, uint16_t e_hdl, UNUSED_ATTR uint8_t* p_data, + const Uuid& value) { tGATT_STATUS status = GATT_NOT_FOUND; uint8_t handle_len = 4; uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) { if (el.s_hdl < s_hdl || el.s_hdl > e_hdl || el.type != GATT_UUID_PRI_SERVICE) { @@ -481,7 +493,7 @@ static tGATT_STATUS gatt_build_primary_service_rsp( } } - if (p_msg->len + p_msg->offset > tcb.payload_size || + if (p_msg->len + p_msg->offset > payload_size || handle_len != p_msg->offset) { break; } @@ -613,28 +625,30 @@ static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t& len, * Returns void * ******************************************************************************/ -void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data) { +void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data) { uint16_t s_hdl = 0, e_hdl = 0; Uuid uuid = Uuid::kEmpty; uint8_t reason = gatts_validate_packet_format(op_code, len, p_data, &uuid, s_hdl, e_hdl); if (reason != GATT_SUCCESS) { - gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false); return; } if (uuid != Uuid::From16Bit(GATT_UUID_PRI_SERVICE)) { if (op_code == GATT_REQ_READ_BY_GRP_TYPE) { - gatt_send_error_rsp(tcb, GATT_UNSUPPORT_GRP_TYPE, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, GATT_UNSUPPORT_GRP_TYPE, op_code, s_hdl, + false); VLOG(1) << StringPrintf("unexpected ReadByGrpType Group: %s", uuid.ToString().c_str()); return; } // we do not support ReadByTypeValue with any non-primamry_service type - gatt_send_error_rsp(tcb, GATT_NOT_FOUND, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, GATT_NOT_FOUND, op_code, s_hdl, false); VLOG(1) << StringPrintf("unexpected ReadByTypeValue type: %s", uuid.ToString().c_str()); return; @@ -644,22 +658,24 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code, Uuid value = Uuid::kEmpty; if (op_code == GATT_REQ_FIND_TYPE_VALUE) { if (!gatt_parse_uuid_from_cmd(&value, len, &p_data)) { - gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, s_hdl, false); } } + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + uint16_t msg_len = - (uint16_t)(sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET); + (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); - reason = gatt_build_primary_service_rsp(p_msg, tcb, op_code, s_hdl, e_hdl, - p_data, value); + reason = gatt_build_primary_service_rsp(p_msg, tcb, cid, op_code, s_hdl, + e_hdl, p_data, value); if (reason != GATT_SUCCESS) { osi_free(p_msg); - gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false); return; } - attp_send_sr_msg(tcb, p_msg); + attp_send_sr_msg(tcb, cid, p_msg); } /******************************************************************************* @@ -672,17 +688,19 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code, * Returns void * ******************************************************************************/ -static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data) { +static void gatts_process_find_info(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data) { uint16_t s_hdl = 0, e_hdl = 0; uint8_t reason = read_handles(len, p_data, s_hdl, e_hdl); if (reason != GATT_SUCCESS) { - gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false); return; } + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); uint16_t buf_len = - (uint16_t)(sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET); + (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(buf_len); reason = GATT_NOT_FOUND; @@ -691,7 +709,7 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code, *p++ = op_code + 1; p_msg->len = 2; - buf_len = tcb.payload_size - 2; + buf_len = payload_size - 2; for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) { if (el.s_hdl <= e_hdl && el.e_hdl >= s_hdl) { @@ -709,9 +727,9 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code, if (reason != GATT_SUCCESS) { osi_free(p_msg); - gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false); } else - attp_send_sr_msg(tcb, p_msg); + attp_send_sr_msg(tcb, cid, p_msg); } /******************************************************************************* @@ -724,17 +742,18 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code, * Returns void * ******************************************************************************/ -static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t len, +static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t cid, uint16_t len, uint8_t* p_data) { /* BR/EDR conenction, send error response */ - if (tcb.att_lcid != L2CAP_ATT_CID) { - gatt_send_error_rsp(tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, false); + if (cid != L2CAP_ATT_CID) { + gatt_send_error_rsp(tcb, cid, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, + false); return; } if (len < GATT_MTU_REQ_MIN_LEN) { LOG(ERROR) << "invalid MTU request PDU received."; - gatt_send_error_rsp(tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false); + gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false); return; } @@ -757,7 +776,7 @@ static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t len, tGATT_SR_MSG gatt_sr_msg; gatt_sr_msg.mtu = tcb.payload_size; BT_HDR* p_buf = attp_build_sr_msg(tcb, GATT_RSP_MTU, &gatt_sr_msg); - attp_send_sr_msg(tcb, p_buf); + attp_send_sr_msg(tcb, cid, p_buf); tGATTS_DATA gatts_data; gatts_data.mtu = tcb.payload_size; @@ -787,8 +806,9 @@ static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t len, * Returns void * ******************************************************************************/ -void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data) { +void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data) { Uuid uuid = Uuid::kEmpty; uint16_t s_hdl = 0, e_hdl = 0, err_hdl = 0; tGATT_STATUS reason = @@ -799,26 +819,28 @@ void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code, VLOG(1) << "Conformance tst: forced err rsp for ReadByType: error status=" << +gatt_cb.err_status; - gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, - false); + gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, gatt_cb.req_op_code, + s_hdl, false); return; } #endif if (reason != GATT_SUCCESS) { - gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false); return; } - size_t msg_len = sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET; + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + + size_t msg_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; *p++ = op_code + 1; /* reserve length byte */ p_msg->len = 2; - uint16_t buf_len = tcb.payload_size - 2; + uint16_t buf_len = payload_size - 2; reason = GATT_NOT_FOUND; for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) { @@ -827,8 +849,8 @@ void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code, gatt_sr_get_sec_info(tcb.peer_bda, tcb.transport, &sec_flag, &key_size); tGATT_STATUS ret = gatts_db_read_attr_value_by_type( - tcb, el.p_db, op_code, p_msg, s_hdl, e_hdl, uuid, &buf_len, sec_flag, - key_size, 0, &err_hdl); + tcb, cid, el.p_db, op_code, p_msg, s_hdl, e_hdl, uuid, &buf_len, + sec_flag, key_size, 0, &err_hdl); if (ret != GATT_NOT_FOUND) { reason = ret; if (ret == GATT_NO_RESOURCES) reason = GATT_SUCCESS; @@ -849,20 +871,21 @@ void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code, /* in theroy BUSY is not possible(should already been checked), protected * check */ if (reason != GATT_PENDING && reason != GATT_BUSY) - gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false); return; } - attp_send_sr_msg(tcb, p_msg); + attp_send_sr_msg(tcb, cid, p_msg); } /** * This function is called to process the write request from client. */ -static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, - uint16_t handle, uint8_t op_code, - uint16_t len, uint8_t* p_data, +static void gatts_process_write_req(tGATT_TCB& tcb, uint16_t cid, + tGATT_SRV_LIST_ELEM& el, uint16_t handle, + uint8_t op_code, uint16_t len, + uint8_t* p_data, bt_gatt_db_attribute_type_t gatt_type) { tGATTS_DATA sr_data; uint32_t trans_id; @@ -878,7 +901,7 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, LOG(ERROR) << __func__ << ": Prepare write request was invalid - missing offset, " "sending error response"; - gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, handle, false); + gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, handle, false); return; } sr_data.write_req.is_prep = true; @@ -911,7 +934,7 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, sec_flag, key_size); if (status == GATT_SUCCESS) { - trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle); + trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, handle); if (trans_id != 0) { conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if); @@ -941,7 +964,7 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, * check */ if (status != GATT_PENDING && status != GATT_BUSY && (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) { - gatt_send_error_rsp(tcb, status, op_code, handle, false); + gatt_send_error_rsp(tcb, cid, status, op_code, handle, false); } return; } @@ -949,10 +972,13 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, /** * This function is called to process the read request from client. */ -static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, - uint8_t op_code, uint16_t handle, - uint16_t len, uint8_t* p_data) { - size_t buf_len = sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET; +static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid, + tGATT_SRV_LIST_ELEM& el, uint8_t op_code, + uint16_t handle, uint16_t len, + uint8_t* p_data) { + uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + + size_t buf_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; uint16_t offset = 0; if (op_code == GATT_REQ_READ_BLOB && len < sizeof(uint16_t)) { @@ -960,7 +986,7 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, LOG(ERROR) << __func__ << ": packet length=" << len << " too short. min=" << sizeof(uint16_t); android_errorWriteWithInfoLog(0x534e4554, "73172115", -1, NULL, 0); - gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, 0, false); + gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, 0, false); return; } @@ -971,15 +997,15 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; *p++ = op_code + 1; p_msg->len = 1; - buf_len = tcb.payload_size - 1; + buf_len = payload_size - 1; uint8_t sec_flag, key_size; gatt_sr_get_sec_info(tcb.peer_bda, tcb.transport, &sec_flag, &key_size); uint16_t value_len = 0; tGATT_STATUS reason = gatts_read_attr_value_by_handle( - tcb, el.p_db, op_code, handle, offset, p, &value_len, (uint16_t)buf_len, - sec_flag, key_size, 0); + tcb, cid, el.p_db, op_code, handle, offset, p, &value_len, + (uint16_t)buf_len, sec_flag, key_size, 0); p_msg->len += value_len; if (reason != GATT_SUCCESS) { @@ -988,12 +1014,12 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, /* in theory BUSY is not possible(should already been checked), protected * check */ if (reason != GATT_PENDING && reason != GATT_BUSY) - gatt_send_error_rsp(tcb, reason, op_code, handle, false); + gatt_send_error_rsp(tcb, cid, reason, op_code, handle, false); return; } - attp_send_sr_msg(tcb, p_msg); + attp_send_sr_msg(tcb, cid, p_msg); } /******************************************************************************* @@ -1006,8 +1032,8 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el, * Returns void * ******************************************************************************/ -void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +void gatts_process_attribute_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, + uint16_t len, uint8_t* p_data) { uint16_t handle = 0; uint8_t* p = p_data; tGATT_STATUS status = GATT_INVALID_HANDLE; @@ -1026,8 +1052,8 @@ void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, VLOG(1) << "Conformance tst: forced err rsp: error status=" << +gatt_cb.err_status; - gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, - false); + gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, cid, gatt_cb.req_op_code, + handle, false); return; } @@ -1041,14 +1067,14 @@ void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, switch (op_code) { case GATT_REQ_READ: /* read char/char descriptor value */ case GATT_REQ_READ_BLOB: - gatts_process_read_req(tcb, el, op_code, handle, len, p); + gatts_process_read_req(tcb, cid, el, op_code, handle, len, p); break; case GATT_REQ_WRITE: /* write char/char descriptor value */ case GATT_CMD_WRITE: case GATT_SIGN_CMD_WRITE: case GATT_REQ_PREPARE_WRITE: - gatts_process_write_req(tcb, el, handle, op_code, len, p, + gatts_process_write_req(tcb, cid, el, handle, op_code, len, p, attr.gatt_type); break; default: @@ -1065,7 +1091,7 @@ void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len, if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE) - gatt_send_error_rsp(tcb, status, op_code, handle, false); + gatt_send_error_rsp(tcb, cid, status, op_code, handle, false); } /******************************************************************************* @@ -1152,16 +1178,16 @@ static bool gatts_proc_ind_ack(tGATT_TCB& tcb, uint16_t ack_handle) { * Returns void * ******************************************************************************/ -void gatts_process_value_conf(tGATT_TCB& tcb, uint8_t op_code) { - uint16_t handle = tcb.indicate_handle; +void gatts_process_value_conf(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code) { + uint16_t handle; - alarm_cancel(tcb.conf_timer); - if (!GATT_HANDLE_IS_VALID(handle)) { + if (gatt_tcb_find_indicate_handle(tcb, cid, &handle)) { LOG(ERROR) << "unexpected handle value confirmation"; return; } - tcb.indicate_handle = 0; + alarm_cancel(tcb.conf_timer); + bool continue_processing = gatts_proc_ind_ack(tcb, handle); if (continue_processing) { @@ -1169,7 +1195,7 @@ void gatts_process_value_conf(tGATT_TCB& tcb, uint8_t op_code) { gatts_data.handle = handle; for (auto& el : *gatt_cb.srv_list_info) { if (el.s_hdl <= handle && el.e_hdl >= handle) { - uint32_t trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle); + uint32_t trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, handle); uint16_t conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if); gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_CONF, &gatts_data); @@ -1179,38 +1205,41 @@ void gatts_process_value_conf(tGATT_TCB& tcb, uint8_t op_code) { } /** This function is called to handle the client requests to server */ -void gatt_server_handle_client_req(tGATT_TCB& tcb, uint8_t op_code, - uint16_t len, uint8_t* p_data) { +void gatt_server_handle_client_req(tGATT_TCB& tcb, uint16_t cid, + uint8_t op_code, uint16_t len, + uint8_t* p_data) { /* there is pending command, discard this one */ if (!gatt_sr_cmd_empty(tcb) && op_code != GATT_HANDLE_VALUE_CONF) return; /* the size of the message may not be bigger than the local max PDU size*/ /* The message has to be smaller than the agreed MTU, len does not include op * code */ - if (len >= tcb.payload_size) { + + uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, cid); + if (len >= payload_size) { LOG(ERROR) << StringPrintf("server receive invalid PDU size:%d pdu size:%d", - len + 1, tcb.payload_size); + len + 1, payload_size); /* for invalid request expecting response, send it now */ if (op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE && op_code != GATT_HANDLE_VALUE_CONF) { - gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, 0, false); + gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, 0, false); } /* otherwise, ignore the pkt */ } else { switch (op_code) { case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */ case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */ - gatts_process_primary_service_req(tcb, op_code, len, p_data); + gatts_process_primary_service_req(tcb, cid, op_code, len, p_data); break; case GATT_REQ_FIND_INFO: /* discover char descrptor */ - gatts_process_find_info(tcb, op_code, len, p_data); + gatts_process_find_info(tcb, cid, op_code, len, p_data); break; case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */ /* discover characteristic, discover char by UUID */ - gatts_process_read_by_type_req(tcb, op_code, len, p_data); + gatts_process_read_by_type_req(tcb, cid, op_code, len, p_data); break; case GATT_REQ_READ: /* read char/char descriptor value */ @@ -1219,23 +1248,23 @@ void gatt_server_handle_client_req(tGATT_TCB& tcb, uint8_t op_code, case GATT_CMD_WRITE: case GATT_SIGN_CMD_WRITE: case GATT_REQ_PREPARE_WRITE: - gatts_process_attribute_req(tcb, op_code, len, p_data); + gatts_process_attribute_req(tcb, cid, op_code, len, p_data); break; case GATT_HANDLE_VALUE_CONF: - gatts_process_value_conf(tcb, op_code); + gatts_process_value_conf(tcb, cid, op_code); break; case GATT_REQ_MTU: - gatts_process_mtu_req(tcb, len, p_data); + gatts_process_mtu_req(tcb, cid, len, p_data); break; case GATT_REQ_EXEC_WRITE: - gatt_process_exec_write_req(tcb, op_code, len, p_data); + gatt_process_exec_write_req(tcb, cid, op_code, len, p_data); break; case GATT_REQ_READ_MULTI: - gatt_process_read_multi_req(tcb, op_code, len, p_data); + gatt_process_read_multi_req(tcb, cid, op_code, len, p_data); break; default: diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc index f06369e68..c2184d0fd 100644 --- a/stack/gatt/gatt_utils.cc +++ b/stack/gatt/gatt_utils.cc @@ -537,6 +537,19 @@ void gatt_start_rsp_timer(tGATT_CLCB* p_clcb) { /******************************************************************************* * + * Function gatt_stop_rsp_timer + * + * Description Stops a GATT response timer. + * + * Returns void + * + ******************************************************************************/ +void gatt_stop_rsp_timer(tGATT_CLCB* p_clcb) { + alarm_cancel(p_clcb->gatt_rsp_timer_ent); +} + +/******************************************************************************* + * * Function gatt_start_conf_timer * * Description Start a wait_for_confirmation timer. @@ -585,7 +598,7 @@ void gatt_rsp_timeout(void* data) { p_clcb->retry_count < GATT_REQ_RETRY_LIMIT) { uint8_t rsp_code; LOG(WARNING) << __func__ << " retry discovery primary service"; - if (p_clcb != gatt_cmd_dequeue(*p_clcb->p_tcb, &rsp_code)) { + if (p_clcb != gatt_cmd_dequeue(*p_clcb->p_tcb, p_clcb->cid, &rsp_code)) { LOG(ERROR) << __func__ << " command queue out of sync, disconnect"; } else { p_clcb->retry_count++; @@ -732,7 +745,7 @@ void gatt_sr_send_req_callback(uint16_t conn_id, uint32_t trans_id, * Returns void * ******************************************************************************/ -tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code, +tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint16_t cid, uint8_t err_code, uint8_t op_code, uint16_t handle, bool deq) { tGATT_STATUS status; BT_HDR* p_buf; @@ -744,7 +757,7 @@ tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code, p_buf = attp_build_sr_msg(tcb, GATT_RSP_ERROR, &msg); if (p_buf != NULL) { - status = attp_send_sr_msg(tcb, p_buf); + status = attp_send_sr_msg(tcb, cid, p_buf); } else status = GATT_INSUF_RESOURCE; @@ -891,6 +904,19 @@ bool gatt_is_clcb_allocated(uint16_t conn_id) { /******************************************************************************* * + * Function gatt_tcb_is_cid_busy + * + * Description The function check if channel with given cid is busy + * + * Returns True when busy + * + ******************************************************************************/ + +bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid) { + return !tcb.cl_cmd_q.empty(); +} +/******************************************************************************* + * * Function gatt_clcb_alloc * * Description The function allocates a GATT connection link control block @@ -915,6 +941,7 @@ tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id) { p_clcb->conn_id = conn_id; p_clcb->p_reg = p_reg; p_clcb->p_tcb = p_tcb; + p_clcb->cid = gatt_tcb_get_att_cid(*p_tcb); break; } } @@ -924,6 +951,87 @@ tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id) { /******************************************************************************* * + * Function gatt_tcb_get_cid_available_for_indication + * + * Description This function checks if indication can be send + * + * Returns None + * + ******************************************************************************/ +bool gatt_tcb_get_cid_available_for_indication(tGATT_TCB* p_tcb, + bool eatt_support, + uint16_t** indicated_handle_p, + uint16_t* cid_p) { + if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) { + return false; + } + + *indicated_handle_p = &p_tcb->indicate_handle; + *cid_p = p_tcb->att_lcid; + return true; +} + +/******************************************************************************* + * + * Function gatt_tcb_find_indicate_handle + * + * Description This function checks if indication can be send + * + * Returns true when indication handle found, false otherwise + * + ******************************************************************************/ +bool gatt_tcb_find_indicate_handle(tGATT_TCB& tcb, uint16_t cid, + uint16_t* indicated_handle_p) { + if (cid == tcb.att_lcid) { + *indicated_handle_p = tcb.indicate_handle; + tcb.indicate_handle = 0; + return true; + } + + return false; +} + +/******************************************************************************* + * + * Function gatt_tcb_get_att_cid + * + * Description This function gets cid for the GATT operation + * + * Returns Available CID + * + ******************************************************************************/ + +uint16_t gatt_tcb_get_att_cid(tGATT_TCB& tcb) { return tcb.att_lcid; } + +/******************************************************************************* + * + * Function gatt_tcb_get_payload_size_tx + * + * Description This function gets payload size for the GATT operation + * + * Returns Payload size for sending data + * + ******************************************************************************/ +uint16_t gatt_tcb_get_payload_size_tx(tGATT_TCB& tcb, uint16_t cid) { + return tcb.payload_size; +} + +/******************************************************************************* + * + * Function gatt_tcb_get_payload_size_rx + * + * Description This function gets payload size for the GATT operation + * + * Returns Payload size for receiving data + * + ******************************************************************************/ + +uint16_t gatt_tcb_get_payload_size_rx(tGATT_TCB& tcb, uint16_t cid) { + return tcb.payload_size; +} + +/******************************************************************************* + * * Function gatt_clcb_dealloc * * Description The function de-allocates a GATT connection link control @@ -988,6 +1096,12 @@ void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& tcb) { } } +/* Get outstanding server command pointer by the transaction id */ +tGATT_SR_CMD* gatt_sr_get_cmd_by_trans_id(tGATT_TCB* p_tcb, uint32_t trans_id) { + if (p_tcb->sr_cmd.trans_id == trans_id) return &p_tcb->sr_cmd; + + return nullptr; +} /******************************************************************************* * * Function gatt_sr_is_cback_cnt_zero @@ -1033,9 +1147,11 @@ bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& tcb) { * Returns None * ******************************************************************************/ -void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb) { +void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb, uint16_t cid) { for (uint8_t i = 0; i < GATT_MAX_APPS; i++) { - tcb.sr_cmd.cback_cnt[i] = 0; + if (cid == tcb.att_lcid) { + tcb.sr_cmd.cback_cnt[i] = 0; + } } } @@ -1054,6 +1170,10 @@ void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb) { } } +/* Get pointer to server command on given cid */ +tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid) { + return &tcb.sr_cmd; +} /******************************************************************************* * * Function gatt_sr_update_cback_cnt @@ -1063,18 +1183,19 @@ void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb) { * Returns None * ******************************************************************************/ -void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if, bool is_inc, - bool is_reset_first) { +void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if, + bool is_inc, bool is_reset_first) { uint8_t idx = ((uint8_t)gatt_if) - 1; + tGATT_SR_CMD* sr_cmd_p = &tcb.sr_cmd; if (is_reset_first) { - gatt_sr_reset_cback_cnt(tcb); + gatt_sr_reset_cback_cnt(tcb, cid); } if (is_inc) { - tcb.sr_cmd.cback_cnt[idx]++; + sr_cmd_p->cback_cnt[idx]++; } else { - if (tcb.sr_cmd.cback_cnt[idx]) { - tcb.sr_cmd.cback_cnt[idx]--; + if (sr_cmd_p->cback_cnt[idx]) { + sr_cmd_p->cback_cnt[idx]--; } } } @@ -1134,23 +1255,22 @@ void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send, cmd.op_code = op_code; cmd.p_cmd = p_buf; cmd.p_clcb = p_clcb; - - if (!to_send) { - // TODO: WTF why do we clear the queue here ?! - tcb.cl_cmd_q = std::queue(); - } + cmd.cid = p_clcb->cid; tcb.cl_cmd_q.push(cmd); } /** dequeue the command in the client CCB command queue */ -tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint8_t* p_op_code) { - if (tcb.cl_cmd_q.empty()) return nullptr; +tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_op_code) { + std::queue* cl_cmd_q_p = &tcb.cl_cmd_q; - tGATT_CMD_Q cmd = tcb.cl_cmd_q.front(); + if (cl_cmd_q_p->empty()) return nullptr; + + tGATT_CMD_Q cmd = cl_cmd_q_p->front(); tGATT_CLCB* p_clcb = cmd.p_clcb; *p_op_code = cmd.op_code; - tcb.cl_cmd_q.pop(); + p_clcb->cid = cid; + cl_cmd_q_p->pop(); return p_clcb; } @@ -1227,7 +1347,7 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) { operation = p_clcb->operation; conn_id = p_clcb->conn_id; - alarm_cancel(p_clcb->gatt_rsp_timer_ent); + gatt_stop_rsp_timer(p_clcb); gatt_clcb_dealloc(p_clcb); @@ -1255,7 +1375,7 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, uint16_t reason, tGATT_CLCB* p_clcb = &gatt_cb.clcb[i]; if (!p_clcb->in_use || p_clcb->p_tcb != p_tcb) continue; - alarm_cancel(p_clcb->gatt_rsp_timer_ent); + gatt_stop_rsp_timer(p_clcb); VLOG(1) << "found p_clcb conn_id=" << +p_clcb->conn_id; if (p_clcb->operation == GATTC_OPTYPE_NONE) { gatt_clcb_dealloc(p_clcb); diff --git a/stack/test/gatt/gatt_sr_test.cc b/stack/test/gatt/gatt_sr_test.cc index a5fe4cd40..d50db2662 100644 --- a/stack/test/gatt/gatt_sr_test.cc +++ b/stack/test/gatt/gatt_sr_test.cc @@ -68,7 +68,9 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, tGATT_CL_MSG* p_msg) { return 0; } -tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) { return 0; } +tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_msg) { + return 0; +} uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr) { return 0; } bool BTM_GetSecurityFlagsByTransport(const RawAddress& bd_addr, uint8_t* p_sec_flags, @@ -79,10 +81,10 @@ void gatt_act_discovery(tGATT_CLCB* p_clcb) {} bool gatt_disconnect(tGATT_TCB* p_tcb) { return false; } tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* p_tcb) { return 0; } tGATT_STATUS gatts_db_read_attr_value_by_type( - tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp, - uint16_t s_handle, uint16_t e_handle, const Uuid& type, uint16_t* p_len, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id, - uint16_t* p_cur_handle) { + tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code, + BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle, const Uuid& type, + uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size, + uint32_t trans_id, uint16_t* p_cur_handle) { return 0; } void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state) {} @@ -98,9 +100,10 @@ tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long, return GATT_SUCCESS; } tGATT_STATUS gatts_read_attr_value_by_handle( - tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, - uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) { + tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code, + uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len, + uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size, + uint32_t trans_id) { return GATT_SUCCESS; } tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code, @@ -176,28 +179,32 @@ class GattSrTest : public AllocationTestHarness { }; TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, 0, - nullptr, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_REQ_PREPARE_WRITE, 0, nullptr, + kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_max_len_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, - MAX_UINT16, nullptr, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_REQ_PREPARE_WRITE, MAX_UINT16, nullptr, + kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_zero_len_max_data) { uint8_t max_mem[MAX_UINT16]; - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, 0, - max_mem, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_REQ_PREPARE_WRITE, 0, max_mem, + kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_typical) { uint8_t p_data[2] = {0x34, 0x12}; uint16_t length = static_cast(sizeof(p_data) / sizeof(p_data[0])); - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, length, - p_data, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_REQ_PREPARE_WRITE, length, p_data, + kGattCharacteristicType); CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1); CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if); @@ -212,20 +219,23 @@ TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_typical) { } TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, 0, nullptr, + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_SIGN_CMD_WRITE, 0, nullptr, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_max_len_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, MAX_UINT16, - nullptr, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_SIGN_CMD_WRITE, MAX_UINT16, nullptr, + kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_zero_len_max_data) { uint8_t max_mem[MAX_UINT16]; - gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, 0, max_mem, + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_SIGN_CMD_WRITE, 0, max_mem, kGattCharacteristicType); } @@ -235,8 +245,9 @@ TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_typical) { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01}; uint16_t length = static_cast(sizeof(p_data) / sizeof(p_data[0])); - gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, length, - p_data, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, + GATT_SIGN_CMD_WRITE, length, p_data, + kGattCharacteristicType); CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1); CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if); @@ -251,27 +262,27 @@ TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_typical) { } TEST_F(GattSrTest, gatts_process_write_req_command_write_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, 0, nullptr, - kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE, 0, + nullptr, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_command_write_max_len_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, MAX_UINT16, - nullptr, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE, + MAX_UINT16, nullptr, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_command_write_zero_len_max_data) { uint8_t max_mem[MAX_UINT16]; - gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, 0, max_mem, - kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE, 0, + max_mem, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_command_write_typical) { uint8_t p_data[16] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01}; uint16_t length = static_cast(sizeof(p_data) / sizeof(p_data[0])); - gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, length, p_data, - kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE, + length, p_data, kGattCharacteristicType); CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1); CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if); @@ -285,19 +296,19 @@ TEST_F(GattSrTest, gatts_process_write_req_command_write_typical) { } TEST_F(GattSrTest, gatts_process_write_req_request_write_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, 0, nullptr, - kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE, 0, + nullptr, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_request_write_max_len_no_data) { - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, MAX_UINT16, - nullptr, kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE, + MAX_UINT16, nullptr, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_request_write_zero_len_max_data) { uint8_t max_mem[MAX_UINT16]; - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, 0, max_mem, - kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE, 0, + max_mem, kGattCharacteristicType); } TEST_F(GattSrTest, gatts_process_write_req_request_write_typical) { @@ -305,8 +316,8 @@ TEST_F(GattSrTest, gatts_process_write_req_request_write_typical) { 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01}; uint16_t length = static_cast(sizeof(p_data) / sizeof(p_data[0])); - gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, length, p_data, - kGattCharacteristicType); + gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE, + length, p_data, kGattCharacteristicType); CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1); CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);