OSDN Git Service

Fix for dual-mode devices advertising with a single address
authorJack He <siyuanh@google.com>
Thu, 16 Feb 2017 08:06:15 +0000 (03:06 -0500)
committerJack He <siyuanh@google.com>
Thu, 2 Mar 2017 18:49:34 +0000 (10:49 -0800)
* 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

stack/btm/btm_ble_gap.cc
stack/btm/btm_ble_int.h
stack/btm/btm_inq.cc
stack/btm/btm_int.h
stack/btm/btm_sec.cc

index 9f92d46..2f0f1d3 100644 (file)
@@ -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;
   }
index cf54297..0c8c689 100644 (file)
@@ -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);
 
index ec697b4..c259ee2 100644 (file)
@@ -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);
       }
index fcda0dc..583d3e3 100644 (file)
@@ -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);
 
index 3d7ac17..c79d8b9 100644 (file)
@@ -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);
   }
 
-  /* 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);
   }