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

Commit bb433e24 authored by android-build-prod (mdb)'s avatar android-build-prod (mdb) Committed by Gerrit Code Review
Browse files

Merge changes from topics "bt-hfp-fix-connection-collision-handling",...

Merge changes from topics "bt-hfp-fix-connection-collision-handling", "bt-rfcomm-improve-logging-and-readability", "bt-rfcomm-add-end-to-end-unit-tests"

* changes:
  HFP: Fix connection colision handling
  RFCOMM: Improve logging and readability
  RFCOMM: Add unit tests for connection scenarios
parents 82bd8575 29687e21
Loading
Loading
Loading
Loading
+66 −45
Original line number Diff line number Diff line
@@ -174,17 +174,13 @@ void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
 *
 ******************************************************************************/
void bta_ag_start_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  RawAddress pending_bd_addr = {};

  /* store parameters */
  if (!data.IsEmpty()) {
  p_scb->peer_addr = data.api_open.bd_addr;
  p_scb->open_services = data.api_open.services;
  p_scb->cli_sec_mask = data.api_open.sec_mask;
  }

  /* Check if RFCOMM has any incoming connection to avoid collision. */
  if (PORT_IsOpening(pending_bd_addr)) {
  RawAddress pending_bd_addr = RawAddress::kEmpty;
  if (PORT_IsOpening(&pending_bd_addr)) {
    /* Let the incoming connection goes through.                        */
    /* Issue collision for this scb for now.                            */
    /* We will decide what to do when we find incoming connetion later. */
@@ -330,6 +326,7 @@ void bta_ag_open_fail(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
 *
 ******************************************************************************/
void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
  RawAddress peer_addr = p_scb->peer_addr;
  /* reinitialize stuff */
  p_scb->conn_handle = 0;
  p_scb->conn_service = 0;
@@ -346,7 +343,7 @@ void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
  bta_ag_start_servers(p_scb, p_scb->reg_services);

  /* call open cback w. failure */
  bta_ag_cback_open(p_scb, RawAddress::kEmpty, BTA_AG_FAIL_RFCOMM);
  bta_ag_cback_open(p_scb, peer_addr, BTA_AG_FAIL_RFCOMM);
}

/*******************************************************************************
@@ -502,56 +499,51 @@ void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
 *
 ******************************************************************************/
void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  uint16_t lcid;
  int i;
  tBTA_AG_SCB *ag_scb, *other_scb;
  RawAddress dev_addr = {};
  int status;

  APPL_TRACE_DEBUG("%s: serv_handle0 = %d serv_handle1 = %d", __func__,
                   p_scb->serv_handle[0], p_scb->serv_handle[1]);
  /* set role */
  p_scb->role = BTA_AG_ACP;

  APPL_TRACE_DEBUG("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
                   p_scb->serv_handle[0], p_scb->serv_handle[1]);

  /* get bd addr of peer */
  if (PORT_SUCCESS !=
      (status = PORT_CheckConnection(data.rfc.port_handle, dev_addr, &lcid))) {
    APPL_TRACE_DEBUG(
        "bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d",
        status);
  uint16_t lcid = 0;
  RawAddress dev_addr = RawAddress::kEmpty;
  int status = PORT_CheckConnection(data.rfc.port_handle, &dev_addr, &lcid);
  if (status != PORT_SUCCESS) {
    LOG(ERROR) << __func__ << ", PORT_CheckConnection returned " << status;
    return;
  }

  /* Collision Handling */
  for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_MAX_NUM_CLIENTS;
       i++, ag_scb++) {
    if (ag_scb->in_use && alarm_is_scheduled(ag_scb->collision_timer)) {
      alarm_cancel(ag_scb->collision_timer);

      if (dev_addr == ag_scb->peer_addr) {
        /* If incoming and outgoing device are same, nothing more to do. */
        /* Outgoing conn will be aborted because we have successful incoming
         * conn.  */
      } else {
        /* Resume outgoing connection. */
        other_scb = bta_ag_get_other_idle_scb(p_scb);
        if (other_scb) {
          other_scb->peer_addr = ag_scb->peer_addr;
          other_scb->open_services = ag_scb->open_services;
          other_scb->cli_sec_mask = ag_scb->cli_sec_mask;

          bta_ag_resume_open(other_scb);
        }
  for (tBTA_AG_SCB& ag_scb : bta_ag_cb.scb) {
    // Cancel any pending collision timers
    if (ag_scb.in_use && alarm_is_scheduled(ag_scb.collision_timer)) {
      alarm_cancel(ag_scb.collision_timer);
      if (dev_addr != ag_scb.peer_addr && p_scb != &ag_scb) {
        // Resume outgoing connection if incoming is not on the same device
        bta_ag_resume_open(&ag_scb);
      }

      break;
    }
    if (dev_addr == ag_scb.peer_addr && p_scb != &ag_scb) {
      // Fail the outgoing connection to clean up any upper layer states
      bta_ag_rfc_fail(&ag_scb, tBTA_AG_DATA::kEmpty);
      // If client port is opened, close it
      if (ag_scb.conn_handle > 0) {
        status = RFCOMM_RemoveConnection(ag_scb.conn_handle);
        if (status != PORT_SUCCESS) {
          LOG(WARNING) << __func__ << ": RFCOMM_RemoveConnection failed for "
                       << dev_addr << ", handle "
                       << std::to_string(ag_scb.conn_handle) << ", error "
                       << status;
        }
      }
    }
  }

  p_scb->peer_addr = dev_addr;

  /* determine connected service from port handle */
  for (i = 0; i < BTA_AG_NUM_IDX; i++) {
  for (uint8_t i = 0; i < BTA_AG_NUM_IDX; i++) {
    APPL_TRACE_DEBUG(
        "bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", i,
        p_scb->serv_handle[i], data.rfc.port_handle);
@@ -813,3 +805,32 @@ void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {

  (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
}

static void bta_ag_collision_timer_cback(void* data) {
  if (data == nullptr) {
    LOG(ERROR) << __func__ << ": data should never be null in a timer callback";
    return;
  }
  /* If the peer haven't opened AG connection     */
  /* we will restart opening process.             */
  bta_ag_resume_open(static_cast<tBTA_AG_SCB*>(data));
}

void bta_ag_handle_collision(tBTA_AG_SCB* p_scb,
                             UNUSED_ATTR const tBTA_AG_DATA& data) {
  /* Cancel SDP if it had been started. */
  if (p_scb->p_disc_db) {
    SDP_CancelServiceSearch(p_scb->p_disc_db);
    bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
  }

  /* reopen registered servers */
  /* Collision may be detected before or after we close servers. */
  if (bta_ag_is_server_closed(p_scb)) {
    bta_ag_start_servers(p_scb, p_scb->reg_services);
  }

  /* Start timer to han */
  alarm_set_on_mloop(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
                     bta_ag_collision_timer_cback, p_scb);
}
 No newline at end of file
+3 −1
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ enum {
  BTA_AG_DISC_FAIL_EVT,
  BTA_AG_RING_TIMEOUT_EVT,
  BTA_AG_SVC_TIMEOUT_EVT,
  BTA_AG_COLLISION_EVT,
  BTA_AG_MAX_EVT,
};

@@ -306,7 +307,6 @@ extern uint8_t bta_ag_service_to_idx(tBTA_SERVICE_MASK services);
extern uint16_t bta_ag_idx_by_bdaddr(const RawAddress* peer_addr);
extern bool bta_ag_other_scb_open(tBTA_AG_SCB* p_curr_scb);
extern bool bta_ag_scb_open(tBTA_AG_SCB* p_curr_scb);
extern tBTA_AG_SCB* bta_ag_get_other_idle_scb(tBTA_AG_SCB* p_curr_scb);
extern void bta_ag_sm_execute(tBTA_AG_SCB* p_scb, uint16_t event,
                              const tBTA_AG_DATA& data);
extern void bta_ag_sm_execute_by_handle(uint16_t handle, uint16_t event,
@@ -378,6 +378,8 @@ extern void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
extern void bta_ag_result(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
extern void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
extern void bta_ag_send_ring(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
extern void bta_ag_handle_collision(tBTA_AG_SCB* p_scb,
                                    const tBTA_AG_DATA& data);

/* Internal utility functions */
extern void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result);
+40 −85
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ enum {
  BTA_AG_RESULT,
  BTA_AG_SETCODEC,
  BTA_AG_SEND_RING,
  BTA_AG_HANDLE_COLLISION,
  BTA_AG_NUM_ACTIONS
};

@@ -133,6 +134,7 @@ static const char* bta_ag_evt_str(uint16_t event) {
    CASE_RETURN_STR(BTA_AG_DISC_FAIL_EVT)
    CASE_RETURN_STR(BTA_AG_RING_TIMEOUT_EVT)
    CASE_RETURN_STR(BTA_AG_SVC_TIMEOUT_EVT)
    CASE_RETURN_STR(BTA_AG_COLLISION_EVT)
    default:
      return "Unknown AG Event";
  }
@@ -160,7 +162,11 @@ const tBTA_AG_ACTION bta_ag_action[] = {
    bta_ag_sco_conn_close, bta_ag_sco_listen,    bta_ag_sco_open,
    bta_ag_sco_close,      bta_ag_sco_shutdown,  bta_ag_post_sco_open,
    bta_ag_post_sco_close, bta_ag_svc_conn_open, bta_ag_result,
    bta_ag_setcodec,       bta_ag_send_ring};
    bta_ag_setcodec,       bta_ag_send_ring,     bta_ag_handle_collision};

static_assert(sizeof(bta_ag_action) / sizeof(tBTA_AG_ACTION) ==
                  BTA_AG_NUM_ACTIONS,
              "bta_ag_action must handle all actions");

/* state table information */
#define BTA_AG_ACTIONS 2    /* number of actions */
@@ -189,7 +195,8 @@ const uint8_t bta_ag_st_init[][BTA_AG_NUM_COLS] = {
    /* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
    /* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
    /* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
    /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}};

/* state table for opening state */
const uint8_t bta_ag_st_opening[][BTA_AG_NUM_COLS] = {
@@ -216,7 +223,9 @@ const uint8_t bta_ag_st_opening[][BTA_AG_NUM_COLS] = {
    /* DISC_OK_EVT */ {BTA_AG_RFC_DO_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
    /* DISC_FAIL_EVT */ {BTA_AG_DISC_FAIL, BTA_AG_IGNORE, BTA_AG_INIT_ST},
    /* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}};
    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
    /* COLLISION_EVT */
    {BTA_AG_HANDLE_COLLISION, BTA_AG_IGNORE, BTA_AG_INIT_ST}};

/* state table for open state */
const uint8_t bta_ag_st_open[][BTA_AG_NUM_COLS] = {
@@ -243,7 +252,8 @@ const uint8_t bta_ag_st_open[][BTA_AG_NUM_COLS] = {
    /* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
    /* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
    /* RING_TOUT_EVT */ {BTA_AG_SEND_RING, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
    /* SVC_TOUT_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
    /* SVC_TOUT_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
    /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST}};

/* state table for closing state */
const uint8_t bta_ag_st_closing[][BTA_AG_NUM_COLS] = {
@@ -269,7 +279,19 @@ const uint8_t bta_ag_st_closing[][BTA_AG_NUM_COLS] = {
    /* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
    /* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
    /* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
    /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};

constexpr size_t BTA_AG_NUM_EVENTS =
    BTA_AG_MAX_EVT - BTA_SYS_EVT_START(BTA_ID_AG);
static_assert(sizeof(bta_ag_st_init) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
              "bta_ag_st_init must handle all AG events");
static_assert(sizeof(bta_ag_st_opening) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
              "bta_ag_st_opening must handle all AG events");
static_assert(sizeof(bta_ag_st_open) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
              "bta_ag_st_open must handle all AG events");
static_assert(sizeof(bta_ag_st_closing) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
              "bta_ag_st_closing must handle all AG events");

/* type for state table */
typedef const uint8_t (*tBTA_AG_ST_TBL)[BTA_AG_NUM_COLS];
@@ -494,52 +516,6 @@ bool bta_ag_scb_open(tBTA_AG_SCB* p_curr_scb) {
         p_curr_scb->state == BTA_AG_OPEN_ST;
}

/*******************************************************************************
 *
 * Function         bta_ag_get_other_idle_scb
 *
 * Description      Return other scb if it is in INIT st.
 *
 *
 * Returns          Pointer to other scb if INIT st, NULL otherwise.
 *
 ******************************************************************************/
tBTA_AG_SCB* bta_ag_get_other_idle_scb(tBTA_AG_SCB* p_curr_scb) {
  tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0];
  uint8_t xx;

  for (xx = 0; xx < BTA_AG_MAX_NUM_CLIENTS; xx++, p_scb++) {
    if (p_scb->in_use && (p_scb != p_curr_scb) &&
        (p_scb->state == BTA_AG_INIT_ST)) {
      return p_scb;
    }
  }

  /* no other scb found */
  APPL_TRACE_DEBUG("bta_ag_get_other_idle_scb: No idle AG scb");
  return nullptr;
}

/*******************************************************************************
 *
 * Function         bta_ag_collision_timer_cback
 *
 * Description      AG connection collision timer callback
 *
 *
 * Returns          void
 *
 ******************************************************************************/
static void bta_ag_collision_timer_cback(void* data) {
  tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;

  APPL_TRACE_DEBUG("%s", __func__);

  /* If the peer haven't opened AG connection     */
  /* we will restart opening process.             */
  bta_ag_resume_open(p_scb);
}

/*******************************************************************************
 *
 * Function         bta_ag_collision_cback
@@ -559,33 +535,16 @@ void bta_ag_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status, uint8_t id,

  if (p_scb && (p_scb->state == BTA_AG_OPENING_ST)) {
    if (id == BTA_ID_SYS) {
      LOG(WARNING) << __func__ << "AG found collision (ACL) for handle "
      LOG(WARNING) << __func__ << ": AG found collision (ACL) for handle "
                   << unsigned(handle) << " device " << peer_addr;
    } else if (id == BTA_ID_AG) {
      LOG(WARNING) << __func__ << "AG found collision (RFCOMM) for handle "
      LOG(WARNING) << __func__ << ": AG found collision (RFCOMM) for handle "
                   << unsigned(handle) << " device " << peer_addr;
    } else {
      LOG(WARNING) << __func__ << "AG found collision (UNKNOWN) for handle "
      LOG(WARNING) << __func__ << ": AG found collision (UNKNOWN) for handle "
                   << unsigned(handle) << " device " << peer_addr;
    }

    p_scb->state = BTA_AG_INIT_ST;

    /* Cancel SDP if it had been started. */
    if (p_scb->p_disc_db) {
      SDP_CancelServiceSearch(p_scb->p_disc_db);
      bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
    }

    /* reopen registered servers */
    /* Collision may be detected before or after we close servers. */
    if (bta_ag_is_server_closed(p_scb)) {
      bta_ag_start_servers(p_scb, p_scb->reg_services);
    }

    /* Start timer to han */
    alarm_set_on_mloop(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
                       bta_ag_collision_timer_cback, p_scb);
    bta_ag_sm_execute(p_scb, BTA_AG_COLLISION_EVT, tBTA_AG_DATA::kEmpty);
  }
}

@@ -600,20 +559,16 @@ void bta_ag_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status, uint8_t id,
 *
 ******************************************************************************/
void bta_ag_resume_open(tBTA_AG_SCB* p_scb) {
  if (p_scb) {
    APPL_TRACE_DEBUG("%s: handle=%d, bd_addr=%s", __func__,
                     bta_ag_scb_to_idx(p_scb),
                     p_scb->peer_addr.ToString().c_str());
    /* resume opening process.  */
  if (p_scb->state == BTA_AG_INIT_ST) {
      LOG(WARNING) << __func__
                   << ": handle=" << unsigned(bta_ag_scb_to_idx(p_scb))
                   << ", bd_addr=" << p_scb->peer_addr;
      p_scb->state = BTA_AG_OPENING_ST;
      bta_ag_start_open(p_scb, tBTA_AG_DATA::kEmpty);
    }
    LOG(INFO) << __func__ << ": Resume connection to " << p_scb->peer_addr
              << ", handle" << bta_ag_scb_to_idx(p_scb);
    tBTA_AG_DATA open_data = {.api_open.bd_addr = p_scb->peer_addr,
                              .api_open.services = p_scb->open_services,
                              .api_open.sec_mask = p_scb->cli_sec_mask};
    bta_ag_sm_execute(p_scb, BTA_AG_API_OPEN_EVT, open_data);
  } else {
    LOG(ERROR) << __func__ << ": null p_scb";
    VLOG(1) << __func__ << ": device " << p_scb->peer_addr
            << " is already in state " << std::to_string(p_scb->state);
  }
}

+5 −4
Original line number Diff line number Diff line
@@ -264,11 +264,12 @@ static uint8_t bta_av_get_scb_sep_type(tBTA_AV_SCB* p_scb,
 * Returns          void
 *
 ******************************************************************************/
static void bta_av_save_addr(tBTA_AV_SCB* p_scb, const RawAddress& b) {
static void bta_av_save_addr(tBTA_AV_SCB* p_scb, const RawAddress& bd_addr) {
  APPL_TRACE_DEBUG("%s: r:%d, s:%d", __func__, p_scb->recfg_sup,
                   p_scb->suspend_sup);
  if (p_scb->peer_addr != b) {
    APPL_TRACE_ERROR("%s: reset flags", __func__);
  if (p_scb->peer_addr != bd_addr) {
    LOG(INFO) << __func__ << ": reset flags old_addr=" << p_scb->peer_addr
              << ", new_addr=" << bd_addr;
    /* a new addr, reset the supported flags */
    p_scb->recfg_sup = true;
    p_scb->suspend_sup = true;
@@ -276,7 +277,7 @@ static void bta_av_save_addr(tBTA_AV_SCB* p_scb, const RawAddress& b) {

  /* do this copy anyway, just in case the first addr matches
   * the control block one by accident */
  p_scb->peer_addr = b;
  p_scb->peer_addr = bd_addr;
}

/*******************************************************************************
+7 −11
Original line number Diff line number Diff line
@@ -103,8 +103,8 @@ void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA* p_data) {
  }

  /* Check if RFCOMM has any incoming connection to avoid collision. */
  RawAddress pending_bd_addr;
  if (PORT_IsOpening(pending_bd_addr)) {
  RawAddress pending_bd_addr = RawAddress::kEmpty;
  if (PORT_IsOpening(&pending_bd_addr)) {
    /* Let the incoming connection goes through.                        */
    /* Issue collision for now.                                         */
    /* We will decide what to do when we find incoming connection later.*/
@@ -164,21 +164,17 @@ void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA* p_data) {
                     p_data->hdr.layer_specific);
    return;
  }

  uint16_t lcid;
  RawAddress dev_addr;
  int status;

  /* set role */
  client_cb->role = BTA_HF_CLIENT_ACP;

  APPL_TRACE_DEBUG("%s: conn_handle %d", __func__, client_cb->conn_handle);

  /* get bd addr of peer */
  if (PORT_SUCCESS != (status = PORT_CheckConnection(client_cb->conn_handle,
                                                     dev_addr, &lcid))) {
    APPL_TRACE_DEBUG("%s: error PORT_CheckConnection returned status %d",
                     __func__, status);
  uint16_t lcid = 0;
  RawAddress dev_addr = RawAddress::kEmpty;
  int status = PORT_CheckConnection(client_cb->conn_handle, &dev_addr, &lcid);
  if (status != PORT_SUCCESS) {
    LOG(ERROR) << __func__ << ": PORT_CheckConnection returned " << status;
  }

  /* Collision Handling */
Loading