栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android 11 BT配对流程[3]

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 11 BT配对流程[3]

前面讲到btm_sec_bond_by_transport 这个接口,继续---->



tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
                                      tBT_TRANSPORT transport, uint8_t pin_len,
                                      uint8_t* p_pin, uint32_t trusted_mask[]) {
........
# 判断controller是否ready !

  if (!controller_get_interface()->get_is_ready()) {
    BTM_TRACE_ERROR("%s controller module is not ready", __func__);
    return (BTM_NO_RESOURCES);
  }

  BTM_TRACE_DEBUG("before update sec_flags=0x%x", p_dev_rec->sec_flags);

# 已配对返回 !
  
  if (((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) &&
       transport == BT_TRANSPORT_BR_EDR &&
       (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) ||
      ((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) &&
       transport == BT_TRANSPORT_LE &&
       (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))) {
    BTM_TRACE_WARNING("BTM_SecBond -> Already Paired");
    return (BTM_SUCCESS);
  }

# 向Controller发送HCIC_PARAM_SIZE_DELETE_STORED_KEY 删除link key !

  
  if ((BTM_DeleteStoredlinkKey(&bd_addr, NULL)) != BTM_SUCCESS)
    return (BTM_NO_RESOURCES);

  
  if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0)) {
    btm_cb.pin_code_len = pin_len;
    p_dev_rec->pin_code_length = pin_len;
    memcpy(btm_cb.pin_code, p_pin, PIN_CODE_LEN);
  }

  btm_cb.pairing_bda = bd_addr;

  btm_cb.pairing_flags = BTM_PAIR_FLAGS_WE_STARTED_DD;

  p_dev_rec->security_required = BTM_SEC_OUT_AUTHENTICATE;
  p_dev_rec->is_originator = true;
  if (trusted_mask)
    BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);


  if (transport == BT_TRANSPORT_LE) {
    btm_ble_init_pseudo_addr(p_dev_rec, bd_addr);
    p_dev_rec->sec_flags &= ~BTM_SEC_LE_MASK;

    if (SMP_Pair(bd_addr) == SMP_STARTED) {
      btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
      p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
      btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
      return BTM_CMD_STARTED;
    }

    btm_cb.pairing_flags = 0;
    return (BTM_NO_RESOURCES);
  }

  p_dev_rec->sec_flags &=
      ~(BTM_SEC_link_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED |
        BTM_SEC_ROLE_SWITCHED | BTM_SEC_link_KEY_AUTHED);

# 判断是否支持简单安全配对SSP,以及对应的逻辑

  BTM_TRACE_DEBUG("after update sec_flags=0x%x", p_dev_rec->sec_flags);
  if (!controller_get_interface()->supports_simple_pairing()) {
    
    
    
    if (((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) ==
         BTM_COD_MAJOR_PERIPHERAL) &&
        (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD) &&
        (btm_cb.cfg.pin_type != HCI_PIN_TYPE_FIXED)) {
      btm_cb.pin_type_changed = true;
      btsnd_hcic_write_pin_type(HCI_PIN_TYPE_FIXED);
    }
  }


.......

  
  if (p && p->hci_handle != BTM_SEC_INVALID_HANDLE) {
    btm_sec_start_authentication(p_dev_rec);

    btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);

    
    l2cu_update_lcb_4_bonding(bd_addr, true);
    return (BTM_CMD_STARTED);
  }

  BTM_TRACE_DEBUG("sec mode: %d sm4:x%x", btm_cb.security_mode, p_dev_rec->sm4);
  if (!controller_get_interface()->supports_simple_pairing() ||
      (p_dev_rec->sm4 == BTM_SM4_KNOWN)) {
    if (btm_sec_check_prefetch_pin(p_dev_rec)) return (BTM_CMD_STARTED);
  }
  if ((btm_cb.security_mode == BTM_SEC_MODE_SP ||
       btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
       btm_cb.security_mode == BTM_SEC_MODE_SC) &&
      BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
    
    if ((p_dev_rec->sm4 & BTM_SM4_CONN_PEND) == 0) {
      
      btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
      status = BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
    } else {
      


      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);
  } else {

# 我这边看的是BR/EDR 流程,走到这里 !

    
    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);
  }

  return status;
}

这个接口很长,后面有发现学到的细节继续补充

下面实现建立ACL连接【ACL(AsynchronousConnectionless),和另一种链路是SCO(Synchronous Connection Oriented)。SCO主要用于同步话音传送,ACL主要用于分组数据传送】

ACL细节参考ACL&SCO链路介绍

system/bt/stack/btm/btm_sec.cc



static tBTM_STATUS btm_sec_dd_create_conn(tBTM_SEC_DEV_REC* p_dev_rec) {

# Step1 找到一个lcb(link control block)
  tL2C_LCB* p_lcb =
      l2cu_find_lcb_by_bd_addr(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
  if (p_lcb && (p_lcb->link_state == LST_ConNECTED ||
                p_lcb->link_state == LST_CONNECTING)) {
    BTM_TRACE_WARNING("%s Connection already exists", __func__);
    btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);
    return BTM_CMD_STARTED;
  }

# Step2 确保l2cap lcb空闲

  
  if (!p_lcb && (p_lcb = l2cu_allocate_lcb(p_dev_rec->bd_addr, true,
                                           BT_TRANSPORT_BR_EDR)) == NULL) {
    LOG(WARNING) << "Security Manager: failed allocate LCB "
                 << p_dev_rec->bd_addr;

    return (BTM_NO_RESOURCES);
  }

  
  btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;

# Step3 通过HCI创建一个与经典蓝牙设备的ACL链接

  if (!l2cu_create_conn_br_edr(p_lcb)) {
    LOG(WARNING) << "Security Manager: failed create allocate LCB "
                 << p_dev_rec->bd_addr;

    l2cu_release_lcb(p_lcb);
    return (BTM_NO_RESOURCES);
  }

  btm_acl_update_busy_level(BTM_BLI_PAGE_EVT);

  VLOG(1) << "Security Manager: " << p_dev_rec->bd_addr;

  btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);

  return (BTM_CMD_STARTED);
}

system/bt/stack/l2cap/l2c_utils.cc
----------------------------------------------


bool l2cu_create_conn_br_edr(tL2C_LCB* p_lcb) {
  int xx;
  tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
  bool is_sco_active;

  
  for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_linkS;
       xx++, p_lcb_cur++) {
    if (p_lcb_cur == p_lcb) continue;

    if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
      

      
      is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);

      L2CAP_TRACE_API(
          "l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s",
          (is_sco_active) ? "true" : "false");

      if (is_sco_active)
        continue; 
      
      if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
        
        p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
        p_lcb->link_role = HCI_ROLE_MASTER;

        if (BTM_SwitchRole(p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) ==
            BTM_CMD_STARTED) {
          alarm_set_on_mloop(p_lcb->l2c_lcb_timer,
                             L2CAP_link_ROLE_SWITCH_TIMEOUT_MS,
                             l2c_lcb_timer_timeout, p_lcb);
          return (true);
        }
      }
    }
  }

  p_lcb->link_state = LST_CONNECTING;

  return (l2cu_create_conn_after_switch(p_lcb));
}





bool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb) {
  uint8_t allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
  tBTM_INQ_INFO* p_inq_info;
  uint8_t page_scan_rep_mode;
  uint8_t page_scan_mode;
  uint16_t clock_offset;
  uint8_t* p_features;
  uint16_t num_acl = BTM_GetNumAcllinks();
  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_lcb->remote_bd_addr);
  uint8_t no_hi_prio_chs = l2cu_get_num_hi_priority();

  p_features = BTM_ReadLocalFeatures();

  L2CAP_TRACE_DEBUG(
      "l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
      l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
  
  if (((!l2cb.disallow_switch && (num_acl < 3)) ||
       (p_lcb->is_bonding && (no_hi_prio_chs == 0))) &&
      HCI_SWITCH_SUPPORTED(p_features))
    allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
  else
    allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;

  p_lcb->link_state = LST_CONNECTING;

  
  p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr);
  if ((p_inq_info != NULL) &&
      (p_inq_info->results.inq_result_type & BTM_INQ_RESULT_BR)) {
    page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
    page_scan_mode = p_inq_info->results.page_scan_mode;
    clock_offset = (uint16_t)(p_inq_info->results.clock_offset);
  } else {
    
    page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
    page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;

    clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
  }
# 发起连接
  btsnd_hcic_create_conn(
      p_lcb->remote_bd_addr, (HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1 |
                              HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3 |
                              HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5),
      page_scan_rep_mode, page_scan_mode, clock_offset, allow_switch);

  btm_acl_update_busy_level(BTM_BLI_PAGE_EVT);

# 设置定时器,l2c_lcb_timer_timeout进行超时处理;
  alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_link_CONNECT_TIMEOUT_MS,
                     l2c_lcb_timer_timeout, p_lcb);

  return (true);
}

void btsnd_hcic_create_conn(const RawAddress& dest, uint16_t packet_types,
                            uint8_t page_scan_rep_mode, uint8_t page_scan_mode,
                            uint16_t clock_offset, uint8_t allow_switch) {
  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
  uint8_t* pp = (uint8_t*)(p + 1);

#ifndef BT_10A
  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CREATE_CONN;
#else
  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CREATE_CONN - 1;
#endif
  p->offset = 0;

  UINT16_TO_STREAM(pp, HCI_CREATE_CONNECTION);
#ifndef BT_10A
  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CREATE_CONN);
#else
  UINT8_TO_STREAM(pp, (HCIC_PARAM_SIZE_CREATE_CONN - 1));
#endif
  BDADDR_TO_STREAM(pp, dest);
  UINT16_TO_STREAM(pp, packet_types);
  UINT8_TO_STREAM(pp, page_scan_rep_mode);
  UINT8_TO_STREAM(pp, page_scan_mode);
  UINT16_TO_STREAM(pp, clock_offset);
#if !defined(BT_10A)
  UINT8_TO_STREAM(pp, allow_switch);
#endif
  btm_acl_paging(p, dest);
}




void btm_acl_paging(BT_HDR* p, const RawAddress& bda) {
  tBTM_SEC_DEV_REC* p_dev_rec;

  VLOG(2) << __func__ << ":" << btm_cb.discing << " , paging:" << btm_cb.paging
          << " BDA: " << bda;

  if (btm_cb.discing) {
    btm_cb.paging = true;
    fixed_queue_enqueue(btm_cb.page_queue, p);
  } else {
    if (!BTM_ACL_IS_ConNECTED(bda)) {
      VLOG(1) << "connecting_bda: " << btm_cb.connecting_bda;
      if (btm_cb.paging && bda == btm_cb.connecting_bda) {
        fixed_queue_enqueue(btm_cb.page_queue, p);
      } else {
        p_dev_rec = btm_find_or_alloc_dev(bda);
        btm_cb.connecting_bda = p_dev_rec->bd_addr;
        memcpy(btm_cb.connecting_dc, p_dev_rec->dev_class, DEV_CLASS_LEN);

        btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
      }

      btm_cb.paging = true;
    } else 
    {
 # 发送了 HCIC_PARAM_SIZE_CREATE_CONN 命令
      btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
    }
  }
}




void btu_hcif_send_cmd(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_buf) {
  if (!p_buf) return;

  uint16_t opcode;
  uint8_t* stream = p_buf->data + p_buf->offset;
  void* vsc_callback = NULL;

  STREAM_TO_UINT16(opcode, stream);

  // Eww...horrible hackery here
  
  if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC ||
      (opcode == HCI_BLE_RAND) || (opcode == HCI_BLE_ENCRYPT)) {
    vsc_callback = *((void**)(p_buf + 1));
  }

  // Skip parameter length before logging
  stream++;
  btu_hcif_log_command_metrics(opcode, stream,
                               android::bluetooth::hci::STATUS_UNKNOWN, false);

# 通过HCI向controller发送指令
  hci_layer_get_interface()->transmit_command(
      p_buf, btu_hcif_command_complete_evt, btu_hcif_command_status_evt,
      vsc_callback);
}


transmit_comman发送机制参考[init_layer_interface]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/352081.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号