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

Commit b0540d2b authored by Venkata Jagadeesh Garaga's avatar Venkata Jagadeesh Garaga Committed by Andre Eisenbach
Browse files

Increase max remote ext feature pages to 3

Use Case: DUT unable to pair with Xbox HID device

Steps:
1. Turn on BT
2. Start Inquiry
3. Pair with device with three extended feature pages

Failure: Unable to pair with HID device

Root Cause: DUT not responding for btm_read_remote_ext_features_complete
as we are not supporting three extended pages. So Security procedure also
not getting started.

Fix: Increase max remote ext feature pages to three from
2 as some latest remotes supporting three extended pages.
As per spec we can support 255 extended pages.

Test: Pair with device with three extended feature pages

Bug: 32999575

Change-Id: I061c78a7aaa1ab58a2fc554d026305a0124eee77
parent cffd7112
Loading
Loading
Loading
Loading
+24 −35
Original line number Diff line number Diff line
@@ -255,7 +255,7 @@ void btm_acl_created(BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
         * setup */
        if ((p_dev_rec->num_read_pages) &&
            (p_dev_rec->num_read_pages <= (HCI_EXT_FEATURES_PAGE_MAX + 1))) {
          memcpy(p->peer_lmp_features, p_dev_rec->features,
          memcpy(p->peer_lmp_feature_pages, p_dev_rec->feature_pages,
                 (HCI_FEATURE_BYTES_PER_PAGE * p_dev_rec->num_read_pages));
          p->num_read_pages = p_dev_rec->num_read_pages;

@@ -926,7 +926,8 @@ void btm_process_remote_ext_features(tACL_CONN* p_acl_cb,
      BTM_TRACE_ERROR("%s: page=%d unexpected", __func__, page_idx);
      break;
    }
    memcpy(p_dev_rec->features[page_idx], p_acl_cb->peer_lmp_features[page_idx],
    memcpy(p_dev_rec->feature_pages[page_idx],
           p_acl_cb->peer_lmp_feature_pages[page_idx],
           HCI_FEATURE_BYTES_PER_PAGE);
  }

@@ -966,7 +967,8 @@ void btm_read_remote_features(uint16_t handle) {

  p_acl_cb = &btm_cb.acl_db[acl_idx];
  p_acl_cb->num_read_pages = 0;
  memset(p_acl_cb->peer_lmp_features, 0, sizeof(p_acl_cb->peer_lmp_features));
  memset(p_acl_cb->peer_lmp_feature_pages, 0,
         sizeof(p_acl_cb->peer_lmp_feature_pages));

  /* first send read remote supported features HCI command */
  /* because we don't know whether the remote support extended feature command
@@ -1028,26 +1030,22 @@ void btm_read_remote_features_complete(uint8_t* p) {
  p_acl_cb = &btm_cb.acl_db[acl_idx];

  /* Copy the received features page */
  STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0], p,
  STREAM_TO_ARRAY(p_acl_cb->peer_lmp_feature_pages[0], p,
                  HCI_FEATURE_BYTES_PER_PAGE);

  if ((HCI_LMP_EXTENDED_SUPPORTED(
          p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) &&
  if ((HCI_LMP_EXTENDED_SUPPORTED(p_acl_cb->peer_lmp_feature_pages[0])) &&
      (controller_get_interface()
           ->supports_reading_remote_extended_features())) {
    /* if the remote controller has extended features and local controller
    *supports
    ** HCI_Read_Remote_Extended_Features command then start reading these
    *feature starting
    ** with extended features page 1 */
       supports HCI_Read_Remote_Extended_Features command then start reading
       these feature starting with extended features page 1 */
    BTM_TRACE_DEBUG("Start reading remote extended features");
    btm_read_remote_ext_features(handle, HCI_EXT_FEATURES_PAGE_1);
    btm_read_remote_ext_features(handle, 1);
    return;
  }

  /* Remote controller has no extended features. Process remote controller
     supported features
     (features page HCI_EXT_FEATURES_PAGE_0). */
     supported features (features page 0). */
  btm_process_remote_ext_features(p_acl_cb, 1);

  /* Continue with HCI connection establishment */
@@ -1094,7 +1092,7 @@ void btm_read_remote_ext_features_complete(uint8_t* p) {
  p_acl_cb = &btm_cb.acl_db[acl_idx];

  /* Copy the received features page */
  STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[page_num], p,
  STREAM_TO_ARRAY(p_acl_cb->peer_lmp_feature_pages[page_num], p,
                  HCI_FEATURE_BYTES_PER_PAGE);

  /* If there is the next remote features page and
@@ -1185,8 +1183,7 @@ void btm_establish_continue(tACL_CONN* p_acl_cb) {
    evt_data.conn.p_bda = p_acl_cb->remote_addr;
    evt_data.conn.p_bdn = p_acl_cb->remote_name;
    evt_data.conn.p_dc = p_acl_cb->remote_dc;
    evt_data.conn.p_features =
        p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0];
    evt_data.conn.p_features = p_acl_cb->peer_lmp_feature_pages[0];
    evt_data.conn.handle = p_acl_cb->hci_handle;
    evt_data.conn.transport = p_acl_cb->transport;

@@ -1659,7 +1656,7 @@ uint8_t* BTM_ReadRemoteFeatures(BD_ADDR addr) {
    return (NULL);
  }

  return (p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]);
  return (p->peer_lmp_feature_pages[0]);
}

/*******************************************************************************
@@ -1683,7 +1680,7 @@ uint8_t* BTM_ReadRemoteExtendedFeatures(BD_ADDR addr, uint8_t page_number) {
    return NULL;
  }

  return (p->peer_lmp_features[page_number]);
  return (p->peer_lmp_feature_pages[page_number]);
}

/*******************************************************************************
@@ -1717,7 +1714,7 @@ uint8_t* BTM_ReadAllRemoteFeatures(BD_ADDR addr) {
    return (NULL);
  }

  return (p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]);
  return (p->peer_lmp_feature_pages[0]);
}

/*******************************************************************************
@@ -2378,43 +2375,35 @@ bool btm_acl_notif_conn_collision(BD_ADDR bda) {
 ******************************************************************************/
void btm_acl_chk_peer_pkt_type_support(tACL_CONN* p, uint16_t* p_pkt_type) {
  /* 3 and 5 slot packets? */
  if (!HCI_3_SLOT_PACKETS_SUPPORTED(
          p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
  if (!HCI_3_SLOT_PACKETS_SUPPORTED(p->peer_lmp_feature_pages[0]))
    *p_pkt_type &= ~(BTM_ACL_PKT_TYPES_MASK_DH3 + BTM_ACL_PKT_TYPES_MASK_DM3);

  if (!HCI_5_SLOT_PACKETS_SUPPORTED(
          p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
  if (!HCI_5_SLOT_PACKETS_SUPPORTED(p->peer_lmp_feature_pages[0]))
    *p_pkt_type &= ~(BTM_ACL_PKT_TYPES_MASK_DH5 + BTM_ACL_PKT_TYPES_MASK_DM5);

  /* 2 and 3 MPS support? */
  if (!HCI_EDR_ACL_2MPS_SUPPORTED(
          p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
  if (!HCI_EDR_ACL_2MPS_SUPPORTED(p->peer_lmp_feature_pages[0]))
    /* Not supported. Add 'not_supported' mask for all 2MPS packet types */
    *p_pkt_type |=
        (BTM_ACL_PKT_TYPES_MASK_NO_2_DH1 + BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
         BTM_ACL_PKT_TYPES_MASK_NO_2_DH5);

  if (!HCI_EDR_ACL_3MPS_SUPPORTED(
          p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
  if (!HCI_EDR_ACL_3MPS_SUPPORTED(p->peer_lmp_feature_pages[0]))
    /* Not supported. Add 'not_supported' mask for all 3MPS packet types */
    *p_pkt_type |=
        (BTM_ACL_PKT_TYPES_MASK_NO_3_DH1 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH3 +
         BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);

  /* EDR 3 and 5 slot support? */
  if (HCI_EDR_ACL_2MPS_SUPPORTED(
          p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]) ||
      HCI_EDR_ACL_3MPS_SUPPORTED(
          p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) {
    if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(
            p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
  if (HCI_EDR_ACL_2MPS_SUPPORTED(p->peer_lmp_feature_pages[0]) ||
      HCI_EDR_ACL_3MPS_SUPPORTED(p->peer_lmp_feature_pages[0])) {
    if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p->peer_lmp_feature_pages[0]))
      /* Not supported. Add 'not_supported' mask for all 3-slot EDR packet types
       */
      *p_pkt_type |=
          (BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH3);

    if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(
            p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
    if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p->peer_lmp_feature_pages[0]))
      /* Not supported. Add 'not_supported' mask for all 5-slot EDR packet types
       */
      *p_pkt_type |=
+6 −5
Original line number Diff line number Diff line
@@ -100,10 +100,11 @@ bool BTM_SecAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
  p_dev_rec->num_read_pages = 0;
  if (features) {
    bool found = false;
    memcpy(p_dev_rec->features, features, sizeof(p_dev_rec->features));
    memcpy(p_dev_rec->feature_pages, features,
           sizeof(p_dev_rec->feature_pages));
    for (int i = HCI_EXT_FEATURES_PAGE_MAX; !found && i >= 0; i--) {
      for (int j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++) {
        if (p_dev_rec->features[i][j] != 0) {
        if (p_dev_rec->feature_pages[i][j] != 0) {
          found = true;
          p_dev_rec->num_read_pages = i + 1;
          break;
@@ -111,7 +112,7 @@ bool BTM_SecAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
      }
    }
  } else {
    memset(p_dev_rec->features, 0, sizeof(p_dev_rec->features));
    memset(p_dev_rec->feature_pages, 0, sizeof(p_dev_rec->feature_pages));
  }

  BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
@@ -297,14 +298,14 @@ bool btm_dev_support_switch(BD_ADDR bd_addr) {
  p_dev_rec = btm_find_dev(bd_addr);
  if (p_dev_rec &&
      controller_get_interface()->supports_master_slave_role_switch()) {
    if (HCI_SWITCH_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0])) {
    if (HCI_SWITCH_SUPPORTED(p_dev_rec->feature_pages[0])) {
      BTM_TRACE_DEBUG("btm_dev_support_switch return true (feature found)");
      return (true);
    }

    /* If the feature field is all zero, we never received them */
    for (xx = 0; xx < BD_FEATURES_LEN; xx++) {
      if (p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0][xx] != 0x00) {
      if (p_dev_rec->feature_pages[0][xx] != 0x00) {
        feature_empty = false; /* at least one is != 0 */
        break;
      }
+2 −13
Original line number Diff line number Diff line
@@ -246,7 +246,7 @@ static void btm_decode_ext_features_page(uint8_t page_number,
  BTM_TRACE_DEBUG("btm_decode_ext_features_page page: %d", page_number);
  switch (page_number) {
    /* Extended (Legacy) Page 0 */
    case HCI_EXT_FEATURES_PAGE_0:
    case 0:

      /* Create ACL supported packet types mask */
      btm_cb.btm_acl_pkt_types_supported =
@@ -384,19 +384,8 @@ static void btm_decode_ext_features_page(uint8_t page_number,

      break;

    /* Extended Page 1 */
    case HCI_EXT_FEATURES_PAGE_1:
      /* Nothing to do for page 1 */
      break;

    /* Extended Page 2 */
    case HCI_EXT_FEATURES_PAGE_2:
      /* Nothing to do for page 2 */
      break;

    default:
      BTM_TRACE_ERROR("btm_decode_ext_features_page page=%d unknown",
                      page_number);
      BTM_TRACE_WARNING("%s: feature page %d ignored", __func__, page_number);
      break;
  }
}
+6 −7
Original line number Diff line number Diff line
@@ -47,8 +47,7 @@ typedef char tBTM_LOC_BD_NAME[BTM_MAX_LOC_BD_NAME_LEN + 1];
   HCI_PKT_TYPES_MASK_NO_2_DH5 | HCI_PKT_TYPES_MASK_NO_3_DH5)

#define BTM_EPR_AVAILABLE(p)                                            \
  ((HCI_ATOMIC_ENCRYPT_SUPPORTED(                                       \
        (p)->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]) &&             \
  ((HCI_ATOMIC_ENCRYPT_SUPPORTED((p)->peer_lmp_feature_pages[0]) &&     \
    HCI_ATOMIC_ENCRYPT_SUPPORTED(                                       \
        controller_get_interface()->get_features_classic(0)->as_array)) \
       ? true                                                           \
@@ -72,7 +71,7 @@ typedef struct {
  uint16_t lmp_subversion;
  uint16_t link_super_tout;
  BD_FEATURES
  peer_lmp_features[HCI_EXT_FEATURES_PAGE_MAX + 1]; /* Peer LMP Extended
  peer_lmp_feature_pages[HCI_EXT_FEATURES_PAGE_MAX + 1]; /* Peer LMP Extended
                                                            features mask table
                                                            for the device */
  uint8_t num_read_pages;
@@ -514,7 +513,7 @@ typedef struct {

  tBTM_BD_NAME sec_bd_name; /* User friendly name of the device. (may be
                               truncated to save space in dev_rec table) */
  BD_FEATURES features[HCI_EXT_FEATURES_PAGE_MAX +
  BD_FEATURES feature_pages[HCI_EXT_FEATURES_PAGE_MAX +
                            1]; /* Features supported by the device */
  uint8_t num_read_pages;

+2 −4
Original line number Diff line number Diff line
@@ -377,14 +377,12 @@ static tBTM_STATUS btm_send_connect_request(uint16_t acl_handle,
    xx = btm_handle_to_acl_index(acl_handle);
    if (xx < MAX_L2CAP_LINKS) {
      p_acl = &btm_cb.acl_db[xx];
      if (!HCI_EDR_ESCO_2MPS_SUPPORTED(
              p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) {
      if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) {
        BTM_TRACE_WARNING("BTM Remote does not support 2-EDR eSCO");
        temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_2_EV3 |
                           HCI_ESCO_PKT_TYPES_MASK_NO_2_EV5);
      }
      if (!HCI_EDR_ESCO_3MPS_SUPPORTED(
              p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) {
      if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) {
        BTM_TRACE_WARNING("BTM Remote does not support 3-EDR eSCO");
        temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_3_EV3 |
                           HCI_ESCO_PKT_TYPES_MASK_NO_3_EV5);
Loading