Loading system/stack/gatt/att_protocol.cc +17 −13 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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); } /******************************************************************************* Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -513,13 +517,13 @@ 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_cmd = attp_build_read_multi_cmd(payload_size, p_msg->read_multi.num_handles, p_msg->read_multi.handles); break; Loading system/stack/gatt/gatt_api.cc +22 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading @@ -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); } /******************************************************************************/ Loading Loading @@ -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; Loading Loading @@ -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: Loading system/stack/gatt/gatt_auth.cc +2 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } /******************************************************************************* Loading system/stack/gatt/gatt_cl.cc +46 −26 Original line number Diff line number Diff line Loading @@ -22,10 +22,10 @@ * ******************************************************************************/ #include "bt_target.h" #include <string.h> #include "bt_common.h" #include "bt_target.h" #include "bt_utils.h" #include "gatt_int.h" #include "l2c_api.h" Loading Loading @@ -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; Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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 */ Loading @@ -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; } Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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 */ Loading Loading @@ -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<tGATT_CMD_Q>* 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; } Loading @@ -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); Loading @@ -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; } Loading @@ -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( Loading @@ -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) { Loading system/stack/gatt/gatt_db.cc +18 −17 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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) { Loading Loading
system/stack/gatt/att_protocol.cc +17 −13 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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); } /******************************************************************************* Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -513,13 +517,13 @@ 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_cmd = attp_build_read_multi_cmd(payload_size, p_msg->read_multi.num_handles, p_msg->read_multi.handles); break; Loading
system/stack/gatt/gatt_api.cc +22 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading @@ -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); } /******************************************************************************/ Loading Loading @@ -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; Loading Loading @@ -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: Loading
system/stack/gatt/gatt_auth.cc +2 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } /******************************************************************************* Loading
system/stack/gatt/gatt_cl.cc +46 −26 Original line number Diff line number Diff line Loading @@ -22,10 +22,10 @@ * ******************************************************************************/ #include "bt_target.h" #include <string.h> #include "bt_common.h" #include "bt_target.h" #include "bt_utils.h" #include "gatt_int.h" #include "l2c_api.h" Loading Loading @@ -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; Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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 */ Loading @@ -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; } Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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 */ Loading Loading @@ -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<tGATT_CMD_Q>* 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; } Loading @@ -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); Loading @@ -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; } Loading @@ -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( Loading @@ -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) { Loading
system/stack/gatt/gatt_db.cc +18 −17 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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) { Loading