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

Commit 9afbaff6 authored by Etienne Ruffieux's avatar Etienne Ruffieux
Browse files

Handle conflicts in avct browse

Conflicts were handled in avct control but not in browse,
this would result in control connected but browse rejecting
incoming connections continuously.

Adding the same conflict handling mechanism in browse as in
control.

Bug: 285621447
Tag: #stability
Test: m libbt-bta
Test: Manual connect/disconnect with AA device
Test: atest bt_host_test_bta
Change-Id: I68df2f87cb39baadb398decde87e61d886f148b8
parent 6ed74e04
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -696,7 +696,8 @@ tAVCT_BCB* avct_bcb_by_lcid(uint16_t lcid) {
  int idx;

  for (idx = 0; idx < AVCT_NUM_LINKS; idx++, p_bcb++) {
    if (p_bcb->allocated && (p_bcb->ch_lcid == lcid)) {
    if (p_bcb->allocated &&
        ((p_bcb->ch_lcid == lcid) || (p_bcb->conflict_lcid == lcid))) {
      return p_bcb;
    }
  }
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ typedef struct {
  uint8_t allocated;  /* 0, not allocated. index+1, otherwise. */
  uint8_t state;      /* The state machine state */
  uint8_t ch_state;   /* L2CAP channel state */
  uint16_t conflict_lcid; /* L2CAP channel LCID */
  BT_HDR* p_tx_msg; /* Message to be sent - in case the browsing channel is not
                       open when MsgReg is called */
  uint8_t ch_close; /* CCB index+1, if CCB initiated channel close */
+74 −13
Original line number Diff line number Diff line
@@ -64,6 +64,36 @@ const tL2CAP_APPL_INFO avct_l2c_br_appl = {avct_l2c_br_connect_ind_cback,
                                           NULL,
                                           NULL};

/*******************************************************************************
 *
 * Function         avct_l2c_br_is_passive
 *
 * Description      check is the CCB associated with the given BCB was created
 *                  as passive
 *
 * Returns          true, if the given CCB is created as AVCT_PASSIVE
 *
 ******************************************************************************/
static bool avct_l2c_br_is_passive(tAVCT_BCB* p_bcb) {
  bool is_passive = false;
  tAVCT_LCB* p_lcb;
  tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
  p_lcb = avct_lcb_by_bcb(p_bcb);
  int i;

  for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
      AVCT_TRACE_DEBUG("Is bcb associated ccb control passive :0x%x",
                       p_ccb->cc.control);
      if (p_ccb->cc.control & AVCT_PASSIVE) {
        is_passive = true;
        break;
      }
    }
  }
  return is_passive;
}

/*******************************************************************************
 *
 * Function         avct_l2c_br_connect_ind_cback
@@ -94,6 +124,16 @@ void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
      p_bcb->allocated = p_lcb->allocated; /* copy the index from lcb */

      result = L2CAP_CONN_OK;
    } else {
      if (!avct_l2c_br_is_passive(p_bcb) || (p_bcb->ch_state == AVCT_CH_OPEN)) {
        /* this BCB included CT role - reject */
        result = L2CAP_CONN_NO_RESOURCES;
      } else {
        /* add channel ID to conflict ID */
        p_bcb->conflict_lcid = p_bcb->ch_lcid;
        result = L2CAP_CONN_OK;
        AVCT_TRACE_DEBUG("Detected conflict_lcid:0x%x", p_bcb->conflict_lcid);
      }
    }
  }
  /* else no control channel yet, reject */
@@ -103,6 +143,7 @@ void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,

  /* If we reject the connection, send DisconnectReq */
  if (result != L2CAP_CONN_OK) {
    AVCT_TRACE_DEBUG("Connection rejected to lcid:0x%x", lcid);
    L2CA_DisconnectReq(lcid);
  }

@@ -117,11 +158,16 @@ void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
}

void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result) {
  tAVCT_BCB* p_lcb = avct_bcb_by_lcid(lcid);
  if (p_lcb == nullptr) return;
  tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
  if (p_bcb == nullptr) return;

  if (p_bcb->ch_state == AVCT_CH_CONN && p_bcb->conflict_lcid == lcid) {
    AVCT_TRACE_DEBUG("Reset conflict_lcid:0x%x", p_bcb->conflict_lcid);
    p_bcb->conflict_lcid = 0;
    return;
  }
  /* store result value */
  p_lcb->ch_result = result;
  p_bcb->ch_result = result;

  /* Send L2CAP disconnect req */
  avct_l2c_br_disconnect(lcid, 0);
@@ -138,20 +184,35 @@ void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result) {
 *
 ******************************************************************************/
void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result) {
  tAVCT_BCB* p_lcb;
  tAVCT_BCB* p_bcb;

  /* look up lcb for this channel */
  p_lcb = avct_bcb_by_lcid(lcid);
  if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CONN)) return;
  /* look up bcb for this channel */
  p_bcb = avct_bcb_by_lcid(lcid);

  if (result != L2CAP_CONN_OK) {
    LOG(ERROR) << __func__ << ": invoked with non OK status";
  if (p_bcb == NULL) {
    return;
  }

  /* result is successful */
  /* if in correct state */
  if (p_bcb->ch_state == AVCT_CH_CONN) {
    /* if result successful */
    if (result == L2CAP_CONN_OK) {
      /* set channel state */
  p_lcb->ch_state = AVCT_CH_CFG;
      p_bcb->ch_state = AVCT_CH_CFG;
    }
    /* else failure */
    else {
      AVCT_TRACE_ERROR("Invoked with non OK status");
    }
  } else if (p_bcb->conflict_lcid == lcid) {
    /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
    if (result == L2CAP_CONN_OK) {
      /* just in case the peer also accepts our connection - Send L2CAP
       * disconnect req */
      AVCT_TRACE_DEBUG("Disconnect conflict_lcid:0x%x", p_bcb->conflict_lcid);
      L2CA_DisconnectReq(lcid);
    }
    p_bcb->conflict_lcid = 0;
  }
}

/*******************************************************************************