Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f345194 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "gatt: Fix possible assert on GATT timeout while ACL disconnection"

parents 14f25639 bd9ed86f
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -436,12 +436,17 @@ static tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,

  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);
    if (gatt_cmd_enq(tcb, p_clcb, true, cmd_code, p_cmd)) {
      LOG_DEBUG("Enqueued ATT command %p conn_id=0x%04x, cid=%d", p_clcb,
                p_clcb->conn_id, p_clcb->cid);
      return GATT_CMD_STARTED;
    }

    LOG_ERROR("%s, cid 0x%02x already disconnected",
             ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), p_clcb->cid);
    return GATT_INTERNAL_ERROR;
  }

  LOG_DEBUG(
      "Sending ATT command to l2cap cid:0x%04x eatt_channels:%u transport:%s",
      p_clcb->cid, tcb.eatt, bt_transport_text(tcb.transport).c_str());
@@ -460,7 +465,12 @@ static tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
  LOG_DEBUG("Starting ATT response timer %p conn_id=0x%04x, cid=%d", p_clcb,
            p_clcb->conn_id, p_clcb->cid);
  gatt_start_rsp_timer(p_clcb);
  gatt_cmd_enq(tcb, p_clcb, false, cmd_code, NULL);
  if (!gatt_cmd_enq(tcb, p_clcb, false, cmd_code, NULL)) {
    LOG_ERROR("Could not queue sent request. %s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), p_clcb->cid);
    return GATT_INTERNAL_ERROR;
  }

  return att_ret;
}

+1 −1
Original line number Diff line number Diff line
@@ -650,7 +650,7 @@ void gatt_act_discovery(tGATT_CLCB* p_clcb);
void gatt_act_read(tGATT_CLCB* p_clcb, uint16_t offset);
void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act);
tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_opcode);
void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
bool gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
                  uint8_t op_code, BT_HDR* p_buf);
void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,
                                   uint8_t op_code, uint16_t len,
+27 −1
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
      return 0;
    }

    p_cmd = &channel->server_outstanding_cmd_;
  }

@@ -104,6 +110,11 @@ bool gatt_sr_cmd_empty(tGATT_TCB& tcb, uint16_t cid) {

  EattChannel* channel =
      EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
  if (channel == nullptr) {
    LOG_WARN("%s, cid 0x%02x already disconnected",
             ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
    return false;
  }

  return (channel->server_outstanding_cmd_.op_code == 0);
}
@@ -125,6 +136,11 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid) {
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
      return;
    }

    p_cmd = &channel->server_outstanding_cmd_;
  }
@@ -420,6 +436,11 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
  VLOG(1) << __func__;

  tGATT_READ_MULTI* multi_req = gatt_sr_get_read_multi(tcb, cid);
  if (multi_req == nullptr) {
    LOG_ERROR("Could not proceed request. %s, 0x%02x",
              ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
    return;
  }
  multi_req->num_handles = 0;
  multi_req->variable_len = (op_code == GATT_REQ_READ_MULTI_VAR);
  gatt_sr_get_sec_info(tcb.peer_bda, tcb.transport, &sec_flag, &key_size);
@@ -470,7 +491,12 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
    trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, multi_req->handles[0]);
    if (trans_id != 0) {
      tGATT_SR_CMD* sr_cmd_p = gatt_sr_get_cmd_by_cid(tcb, cid);

      if (sr_cmd_p == nullptr) {
        LOG_ERROR(
            "Could not send response on CID were request arrived. %s, 0x%02x",
            ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
        return;
      }
      gatt_sr_reset_cback_cnt(tcb,
                              cid); /* read multiple use multi_rsp_q's count*/

+47 −4
Original line number Diff line number Diff line
@@ -998,7 +998,11 @@ bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid) {

  EattChannel* channel =
      EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
  if (!channel) return false;
  if (channel == nullptr) {
    LOG_WARN("%s, cid 0x%02x already disconnected",
             ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
    return false;
  }

  return !channel->cl_cmd_q_.empty();
}
@@ -1138,6 +1142,11 @@ uint16_t gatt_tcb_get_payload_size(tGATT_TCB& tcb, uint16_t cid) {

  EattChannel* channel =
      EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
  if (channel == nullptr) {
    LOG_WARN("%s, cid 0x%02x already disconnected",
             ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
    return 0;
  }

  /* ATT MTU for EATT is min from tx and rx mtu*/
  return std::min<uint16_t>(channel->tx_mtu_, channel->rx_mtu_);
@@ -1197,6 +1206,8 @@ void gatt_clcb_invalidate(tGATT_TCB* p_tcb, const tGATT_CLCB* p_clcb) {
    EattChannel* channel = EattExtension::GetInstance()->FindEattChannelByCid(
        p_tcb->peer_bda, cid);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(p_tcb->peer_bda), cid);
      return;
    }
    cl_cmd_q_p = &channel->cl_cmd_q_;
@@ -1343,6 +1354,11 @@ void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb, uint16_t cid) {
    } else {
      EattChannel* channel =
          EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
      if (channel == nullptr) {
        LOG_WARN("%s, cid 0x%02x already disconnected",
                 ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
        return;
      }
      channel->server_outstanding_cmd_.cback_cnt[i] = 0;
    }
  }
@@ -1373,6 +1389,12 @@ tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid) {
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
      return nullptr;
    }

    sr_cmd_p = &channel->server_outstanding_cmd_;
  }

@@ -1389,6 +1411,11 @@ tGATT_READ_MULTI* gatt_sr_get_read_multi(tGATT_TCB& tcb, uint16_t cid) {
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
      return nullptr;
    }
    read_multi_p = &channel->server_outstanding_cmd_.multi_req;
  }

@@ -1414,6 +1441,11 @@ void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if,
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
      return;
    }
    sr_cmd_p = &channel->server_outstanding_cmd_;
  }

@@ -1508,7 +1540,7 @@ bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) {
}

/** Enqueue this command */
void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
bool gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
                  uint8_t op_code, BT_HDR* p_buf) {
  tGATT_CMD_Q cmd;
  cmd.to_send = to_send; /* waiting to be sent */
@@ -1522,9 +1554,15 @@ void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cmd.cid);
    CHECK(channel);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cmd.cid);
      return false;
    }
    channel->cl_cmd_q_.push_back(cmd);
  }

  return true;
}

/** dequeue the command in the client CCB command queue */
@@ -1536,7 +1574,12 @@ tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_op_code) {
  } else {
    EattChannel* channel =
        EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
    CHECK(channel);
    if (channel == nullptr) {
      LOG_WARN("%s, cid 0x%02x already disconnected",
               ADDRESS_TO_LOGGABLE_CSTR(tcb.peer_bda), cid);
      return nullptr;
    }

    cl_cmd_q_p = &channel->cl_cmd_q_;
  }