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

Commit ce833a3c authored by Jack He's avatar Jack He
Browse files

Fix for dual-mode devices advertising with a single address

* BTM_ReadRemoteDeviceName checks if a device is connectable over LE before
  making a connection. However, when it is not connectable over LE, it could
  be connectable over BR/EDR.
* For Dual Mode device, the device type should be 0x3 and is not equal to
  BT_DEVICE_TYPE_BREDR, hence we cannot check equality to determine whether
  a device is BR/EDR, but need to AND them and check the result.
* btm_ble_read_remote_name() already checks if device is connectable in LE,
  and we do not need to do it in BTM_ReadRemoteDeviceName().
* This fix removes the check from BTM_ReadRemoteDeviceName
* This fix also adds error checking to return values of BTM_ReadRemoteDeviceName
* This fix moves inquiry database query to respective remote name
  request procedures, as the result of the query is used in those
  procedures instead of in BTM_ReadRemoteDeviceName()

Bug: 35348392
Test: make, pair with device that advertise on both LE and BR/EDR
Change-Id: I10d1aa9dd6e2447f9b9d40b1fea9370b5088a57d
parent 4485bd16
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1589,13 +1589,13 @@ void btm_ble_read_remote_name_cmpl(bool status, BD_ADDR bda, uint16_t length,
 * Returns          void
 *
 ******************************************************************************/
tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO* p_cur,
                                     tBTM_CMPL_CB* p_cb) {
tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_CMPL_CB* p_cb) {
  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;

  if (!controller_get_interface()->supports_ble()) return BTM_ERR_PROCESSING;

  if (p_cur && !ble_evt_type_is_connectable(p_cur->results.ble_evt_type)) {
  tINQ_DB_ENT* p_i = btm_inq_db_find(remote_bda);
  if (p_i && !ble_evt_type_is_connectable(p_i->inq_info.results.ble_evt_type)) {
    BTM_TRACE_DEBUG("name request to non-connectable device failed.");
    return BTM_ERR_PROCESSING;
  }
+0 −1
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ extern void btm_ble_process_adv_pkt(uint8_t len, uint8_t* p);
extern void btm_ble_process_ext_adv_pkt(uint8_t len, uint8_t* p);
extern void btm_ble_proc_scan_rsp_rpt(uint8_t* p);
extern tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda,
                                            tBTM_INQ_INFO* p_cur,
                                            tBTM_CMPL_CB* p_cb);
extern bool btm_ble_cancel_remote_name(BD_ADDR remote_bda);

+15 −32
Original line number Diff line number Diff line
@@ -953,32 +953,16 @@ tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
 ******************************************************************************/
tBTM_STATUS BTM_ReadRemoteDeviceName(BD_ADDR remote_bda, tBTM_CMPL_CB* p_cb,
                                     tBT_TRANSPORT transport) {
  tBTM_INQ_INFO* p_cur = NULL;
  tINQ_DB_ENT* p_i;

  BTM_TRACE_API("BTM_ReadRemoteDeviceName: bd addr [%02x%02x%02x%02x%02x%02x]",
  BTM_TRACE_API("%s: bd addr [%02x%02x%02x%02x%02x%02x]", __func__,
                remote_bda[0], remote_bda[1], remote_bda[2], remote_bda[3],
                remote_bda[4], remote_bda[5]);

  /* Use the remote device's clock offset if it is in the local inquiry database
   */
  p_i = btm_inq_db_find(remote_bda);
  if (p_i != NULL) {
    p_cur = &p_i->inq_info;
    if ((!ble_evt_type_is_connectable(p_cur->results.ble_evt_type)) &&
        (p_cur->results.device_type !=
         BT_DEVICE_TYPE_BREDR)) { /* Non-connectable LE device: do not request
                                     its name! */
      return BTM_ERR_PROCESSING;
    }
  }
  BTM_TRACE_API("no device found in inquiry db");

  /* Use LE transport when LE is the only available option */
  if (transport == BT_TRANSPORT_LE) {
    return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
  } else
    return (btm_initiate_rem_name(remote_bda, p_cur, BTM_RMT_NAME_EXT,
                                  BTM_EXT_RMT_NAME_TIMEOUT_MS, p_cb));
    return btm_ble_read_remote_name(remote_bda, p_cb);
  }
  /* Use classic transport for BR/EDR and Dual Mode devices */
  return btm_initiate_rem_name(remote_bda, BTM_RMT_NAME_EXT,
                               BTM_EXT_RMT_NAME_TIMEOUT_MS, p_cb);
}

/*******************************************************************************
@@ -2062,9 +2046,7 @@ void btm_process_cancel_complete(uint8_t status, uint8_t mode) {
 *                  called either by GAP or by the API call
 *                  BTM_ReadRemoteDeviceName.
 *
 * Input Params:    p_cur         - pointer to an inquiry result structure
 *                                  (NULL if nonexistent)
 *                  p_cb            - callback function called when
 * Input Params:    p_cb            - callback function called when
 *                                    BTM_CMD_STARTED is returned.
 *                                    A pointer to tBTM_REMOTE_DEV_NAME is
 *                                    passed to the callback.
@@ -2077,9 +2059,8 @@ void btm_process_cancel_complete(uint8_t status, uint8_t mode) {
 *                  BTM_WRONG_MODE if the device is not up.
 *
 ******************************************************************************/
tBTM_STATUS btm_initiate_rem_name(BD_ADDR remote_bda, tBTM_INQ_INFO* p_cur,
                                  uint8_t origin, period_ms_t timeout_ms,
                                  tBTM_CMPL_CB* p_cb) {
tBTM_STATUS btm_initiate_rem_name(BD_ADDR remote_bda, uint8_t origin,
                                  period_ms_t timeout_ms, tBTM_CMPL_CB* p_cb) {
  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;

  /*** Make sure the device is ready ***/
@@ -2106,13 +2087,15 @@ tBTM_STATUS btm_initiate_rem_name(BD_ADDR remote_bda, tBTM_INQ_INFO* p_cur,
                         btu_general_alarm_queue);

      /* If the database entry exists for the device, use its clock offset */
      if (p_cur) {
      tINQ_DB_ENT* p_i = btm_inq_db_find(remote_bda);
      if (p_i) {
        tBTM_INQ_INFO* p_cur = &p_i->inq_info;
        btsnd_hcic_rmt_name_req(
            remote_bda, p_cur->results.page_scan_rep_mode,
            p_cur->results.page_scan_mode,
            (uint16_t)(p_cur->results.clock_offset | BTM_CLOCK_OFFSET_VALID));
      } else /* Otherwise use defaults and mark the clock offset as invalid */
      {
      } else {
        /* Otherwise use defaults and mark the clock offset as invalid */
        btsnd_hcic_rmt_name_req(remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
                                HCI_MANDATARY_PAGE_SCAN_MODE, 0);
      }
+1 −2
Original line number Diff line number Diff line
@@ -49,8 +49,7 @@ extern void btm_init(void);
/* Internal functions provided by btm_inq.cc
 ******************************************
*/
extern tBTM_STATUS btm_initiate_rem_name(BD_ADDR remote_bda,
                                         tBTM_INQ_INFO* p_cur, uint8_t origin,
extern tBTM_STATUS btm_initiate_rem_name(BD_ADDR remote_bda, uint8_t origin,
                                         period_ms_t timeout_ms,
                                         tBTM_CMPL_CB* p_cb);

+32 −13
Original line number Diff line number Diff line
@@ -1078,21 +1078,24 @@ tBTM_STATUS btm_sec_bond_by_transport(BD_ADDR bd_addr, tBT_TRANSPORT transport,
       * -> RNR (to learn if peer is 2.1)
       * RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
      btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
      BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
      status = BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
    } else {
      /* We are accepting connection request from peer */
      btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);
      status = BTM_CMD_STARTED;
    }
    BTM_TRACE_DEBUG("State:%s sm4: 0x%x sec_state:%d",
                    btm_pair_state_descr(btm_cb.pairing_state), p_dev_rec->sm4,
                    p_dev_rec->sec_state);
    return BTM_CMD_STARTED;
  }

  } else {
    /* both local and peer are 2.1  */
    status = btm_sec_dd_create_conn(p_dev_rec);
  }

  if (status != BTM_CMD_STARTED) {
    BTM_TRACE_ERROR(
        "%s BTM_ReadRemoteDeviceName or btm_sec_dd_create_conn error: 0x%x",
        __func__, (int)status);
    btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
  }

@@ -3145,16 +3148,25 @@ void btm_sec_rmt_name_request_complete(uint8_t* p_bd_addr, uint8_t* p_bd_name,

          btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);

          if (btm_cb.api.p_auth_complete_callback)
          if (btm_cb.api.p_auth_complete_callback) {
            (*btm_cb.api.p_auth_complete_callback)(
                p_dev_rec->bd_addr, p_dev_rec->dev_class,
                p_dev_rec->sec_bd_name, HCI_ERR_MEMORY_FULL);
          }
        }
      }
      return;
    } else {
      BTM_TRACE_WARNING("%s: wrong BDA, retry with pairing BDA", __func__);
      BTM_ReadRemoteDeviceName(btm_cb.pairing_bda, NULL, BT_TRANSPORT_BR_EDR);
      if (BTM_ReadRemoteDeviceName(btm_cb.pairing_bda, NULL,
                                   BT_TRANSPORT_BR_EDR) != BTM_CMD_STARTED) {
        BTM_TRACE_ERROR("%s: failed to start remote name request", __func__);
        if (btm_cb.api.p_auth_complete_callback) {
          (*btm_cb.api.p_auth_complete_callback)(
              p_dev_rec->bd_addr, p_dev_rec->dev_class, p_dev_rec->sec_bd_name,
              HCI_ERR_MEMORY_FULL);
        }
      };
      return;
    }
  }
@@ -4315,8 +4327,12 @@ void btm_sec_connected(uint8_t* bda, uint16_t handle, uint8_t status,
                               btu_general_alarm_queue);
          } else {
            btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
            BTM_ReadRemoteDeviceName(p_dev_rec->bd_addr, NULL,
                                     BT_TRANSPORT_BR_EDR);
            if (BTM_ReadRemoteDeviceName(p_dev_rec->bd_addr, NULL,
                                         BT_TRANSPORT_BR_EDR) !=
                BTM_CMD_STARTED) {
              BTM_TRACE_ERROR("%s cannot read remote name", __func__);
              btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
            }
          }
#if (BTM_DISC_DURING_RS == TRUE)
          p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
@@ -4353,7 +4369,11 @@ void btm_sec_connected(uint8_t* bda, uint16_t handle, uint8_t status,
      if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
        /* Try again: RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
        btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
        BTM_ReadRemoteDeviceName(bda, NULL, BT_TRANSPORT_BR_EDR);
        if (BTM_ReadRemoteDeviceName(bda, NULL, BT_TRANSPORT_BR_EDR) !=
            BTM_CMD_STARTED) {
          BTM_TRACE_ERROR("%s cannot read remote name", __func__);
          btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
        }
        return;
      }

@@ -5289,11 +5309,10 @@ static bool btm_sec_start_get_name(tBTM_SEC_DEV_REC* p_dev_rec) {

  p_dev_rec->sec_state = BTM_SEC_STATE_GETTING_NAME;

  /* Device should be connected, no need to provide correct page params */
  /* 0 and NULL are as timeout and callback params because they are not used in
   * security get name case */
  if ((btm_initiate_rem_name(p_dev_rec->bd_addr, NULL, BTM_RMT_NAME_SEC, 0,
                             NULL)) != BTM_CMD_STARTED) {
  if ((btm_initiate_rem_name(p_dev_rec->bd_addr, BTM_RMT_NAME_SEC, 0, NULL)) !=
      BTM_CMD_STARTED) {
    p_dev_rec->sec_state = tempstate;
    return (false);
  }