蓝牙用户请求事件(User Confirmation Request Event)调用流程

User Confirmation Request Event(用户确认请求事件):  协议中关于User Confirmation Request Event事件定义如下:

当主机发送配对请求,从机蓝牙控制器接受到请求数据,协议层经过数据处理,最后到btu_hci_msg_process函数,btu_hci_msg_process函数  事件类型为 BT_EVT_TO_BTU_HCI_EVT:// 控制发送给主机的EVENT事件 Part E: Host Controller Interface Functional --> HCI Commands and Events。然后到btu_hcif_process_event函数,函数主要处理协议定义的evets事件。

system\bt\stack\include\hcidefs.h中定义如下: 

#define HCI_USER_CONFIRMATION_REQUEST_EVT   0x33

system\bt\stack\btu\btu_hcif.c

/*******************************************************************************
**
** Function         btu_hcif_process_event
**
** Description      This function is called when an event is received from
**                  the Host Controller.
**
** Returns          void
**
*******************************************************************************/
void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
{
    UINT8   *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
    UINT8   hci_evt_code, hci_evt_len;
#if BLE_INCLUDED == TRUE
    UINT8   ble_sub_code;
#endif
    STREAM_TO_UINT8  (hci_evt_code, p);
    STREAM_TO_UINT8  (hci_evt_len, p);
	 HCI_TRACE_EVENT("btu_hcif_process_event(id=%d) hci_evt_len = %d)", hci_evt_code,  hci_evt_len);
    switch (hci_evt_code)
    {
        case HCI_INQUIRY_COMP_EVT:
            btu_hcif_inquiry_comp_evt (p);
            break;
        case HCI_INQUIRY_RESULT_EVT:
            btu_hcif_inquiry_result_evt (p);
            break;
        case HCI_INQUIRY_RSSI_RESULT_EVT:
            btu_hcif_inquiry_rssi_result_evt (p);
            break;
        case HCI_EXTENDED_INQUIRY_RESULT_EVT:
            btu_hcif_extended_inquiry_result_evt (p);
            break;
        case HCI_CONNECTION_COMP_EVT:
            btu_hcif_connection_comp_evt (p);
            break;
        case HCI_CONNECTION_REQUEST_EVT:
            btu_hcif_connection_request_evt (p);
            break;
        case HCI_DISCONNECTION_COMP_EVT:
            btu_hcif_disconnection_comp_evt (p);
            break;
        case HCI_AUTHENTICATION_COMP_EVT:
            btu_hcif_authentication_comp_evt (p);
            break;
        case HCI_RMT_NAME_REQUEST_COMP_EVT:
            btu_hcif_rmt_name_request_comp_evt (p, hci_evt_len);
            break;
        case HCI_ENCRYPTION_CHANGE_EVT:
            btu_hcif_encryption_change_evt (p);
            break;
#if BLE_INCLUDED == TRUE
        case HCI_ENCRYPTION_KEY_REFRESH_COMP_EVT:
            btu_hcif_encryption_key_refresh_cmpl_evt(p);
            break;
#endif
        case HCI_READ_RMT_FEATURES_COMP_EVT:
            btu_hcif_read_rmt_features_comp_evt (p);
            break;
        case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
            btu_hcif_read_rmt_ext_features_comp_evt (p);
            break;
        case HCI_READ_RMT_VERSION_COMP_EVT:
            btu_hcif_read_rmt_version_comp_evt (p);
            break;
        case HCI_QOS_SETUP_COMP_EVT:
            btu_hcif_qos_setup_comp_evt (p);
            break;
        case HCI_COMMAND_COMPLETE_EVT:
            LOG_ERROR(LOG_TAG, "%s should not have received a command complete event. "
                  "Someone didn't go through the hci transmit_command function.", __func__);
            break;
        case HCI_COMMAND_STATUS_EVT:
            LOG_ERROR(LOG_TAG, "%s should not have received a command status event. "
                  "Someone didn't go through the hci transmit_command function.", __func__);
            break;
        case HCI_HARDWARE_ERROR_EVT:
            btu_hcif_hardware_error_evt (p);
            break;
        case HCI_FLUSH_OCCURED_EVT:
            btu_hcif_flush_occured_evt ();
            break;
        case HCI_ROLE_CHANGE_EVT:
            btu_hcif_role_change_evt (p);
            break;
        case HCI_NUM_COMPL_DATA_PKTS_EVT:
            btu_hcif_num_compl_data_pkts_evt (p);
            break;
        case HCI_MODE_CHANGE_EVT:
            btu_hcif_mode_change_evt (p);
            break;
        case HCI_PIN_CODE_REQUEST_EVT:
            btu_hcif_pin_code_request_evt (p);
            break;
        case HCI_LINK_KEY_REQUEST_EVT:
            btu_hcif_link_key_request_evt (p);
            break;
        case HCI_LINK_KEY_NOTIFICATION_EVT:
            btu_hcif_link_key_notification_evt (p);
            break;
        case HCI_LOOPBACK_COMMAND_EVT:
            btu_hcif_loopback_command_evt ();
            break;
        case HCI_DATA_BUF_OVERFLOW_EVT:
            btu_hcif_data_buf_overflow_evt ();
            break;
        case HCI_MAX_SLOTS_CHANGED_EVT:
            btu_hcif_max_slots_changed_evt ();
            break;
        case HCI_READ_CLOCK_OFF_COMP_EVT:
            btu_hcif_read_clock_off_comp_evt (p);
            break;
        case HCI_CONN_PKT_TYPE_CHANGE_EVT:
            btu_hcif_conn_pkt_type_change_evt ();
            break;
        case HCI_QOS_VIOLATION_EVT:
            btu_hcif_qos_violation_evt (p);
            break;
        case HCI_PAGE_SCAN_MODE_CHANGE_EVT:
            btu_hcif_page_scan_mode_change_evt ();
            break;
        case HCI_PAGE_SCAN_REP_MODE_CHNG_EVT:
            btu_hcif_page_scan_rep_mode_chng_evt ();
            break;
        case HCI_ESCO_CONNECTION_COMP_EVT:
            btu_hcif_esco_connection_comp_evt (p);
            break;
        case HCI_ESCO_CONNECTION_CHANGED_EVT:
            btu_hcif_esco_connection_chg_evt (p);
            break;
#if (BTM_SSR_INCLUDED == TRUE)
        case HCI_SNIFF_SUB_RATE_EVT:
            btu_hcif_ssr_evt (p, hci_evt_len);
            break;
#endif  /* BTM_SSR_INCLUDED == TRUE */
        case HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT:
            btu_hcif_host_support_evt (p);
            break;
        case HCI_IO_CAPABILITY_REQUEST_EVT:
            btu_hcif_io_cap_request_evt (p);
            break;
        case HCI_IO_CAPABILITY_RESPONSE_EVT:
            btu_hcif_io_cap_response_evt (p);
            break;
        case HCI_USER_CONFIRMATION_REQUEST_EVT:
            btu_hcif_user_conf_request_evt (p);
            break;
        case HCI_USER_PASSKEY_REQUEST_EVT:
            btu_hcif_user_passkey_request_evt (p);
            break;
        case HCI_REMOTE_OOB_DATA_REQUEST_EVT:
            btu_hcif_rem_oob_request_evt (p);
            break;
        case HCI_SIMPLE_PAIRING_COMPLETE_EVT:
            btu_hcif_simple_pair_complete_evt (p);
            break;
        case HCI_USER_PASSKEY_NOTIFY_EVT:
            btu_hcif_user_passkey_notif_evt (p);
            break;
        case HCI_KEYPRESS_NOTIFY_EVT:
            btu_hcif_keypress_notif_evt (p);
            break;
#if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
        case HCI_ENHANCED_FLUSH_COMPLETE_EVT:
            btu_hcif_enhanced_flush_complete_evt ();
            break;
#endif

#if (BLE_INCLUDED == TRUE)
        case HCI_BLE_EVENT:
            STREAM_TO_UINT8  (ble_sub_code, p);

            HCI_TRACE_EVENT("BLE HCI(id=%d) event = 0x%02x)", hci_evt_code,  ble_sub_code);

            switch (ble_sub_code)
            {
                case HCI_BLE_ADV_PKT_RPT_EVT: /* result of inquiry */
                    btu_ble_process_adv_pkt(p);
                    break;
                case HCI_BLE_CONN_COMPLETE_EVT:
                    btu_ble_ll_conn_complete_evt(p, hci_evt_len);
                    break;
                case HCI_BLE_LL_CONN_PARAM_UPD_EVT:
                    btu_ble_ll_conn_param_upd_evt(p, hci_evt_len);
                    break;
                case HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT:
                    btu_ble_read_remote_feat_evt(p);
                    break;
                case HCI_BLE_LTK_REQ_EVT: /* received only at slave device */
                    btu_ble_proc_ltk_req(p);
                    break;
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
                case HCI_BLE_ENHANCED_CONN_COMPLETE_EVT:
                    btu_ble_proc_enhanced_conn_cmpl(p, hci_evt_len);
                    break;
#endif
#if (BLE_LLT_INCLUDED == TRUE)
               case HCI_BLE_RC_PARAM_REQ_EVT:
                    btu_ble_rc_param_req_evt(p);
                    break;
#endif
               case HCI_BLE_DATA_LENGTH_CHANGE_EVT:
                    btu_ble_data_length_change_evt(p, hci_evt_len);
                    break;
            }
            break;
#endif /* BLE_INCLUDED */
        case HCI_VENDOR_SPECIFIC_EVT:
                btm_vendor_specific_evt (p, hci_evt_len);
            break;
    }
#if HCI_RAW_CMD_INCLUDED == TRUE
    btm_hci_event (p, hci_evt_code , hci_evt_len);
#endif
}

关注HCI_USER_CONFIRMATION_REQUEST_EVT事件,

        case HCI_USER_CONFIRMATION_REQUEST_EVT:
            btu_hcif_user_conf_request_evt (p);
            break;

 system\bt\stack\btu\btu_hcif.c

/*******************************************************************************
**
** Function         btu_hcif_user_conf_request_evt
**
** Description      Process event HCI_USER_CONFIRMATION_REQUEST_EVT
**
** Returns          void
**
*******************************************************************************/
static void btu_hcif_user_conf_request_evt (UINT8 *p)
{
    btm_proc_sp_req_evt(BTM_SP_CFM_REQ_EVT, p);
}

 event = BTM_SP_CFM_REQ_EVT

system\bt\stack\btm\btm_sec.c

/*******************************************************************************
**
** Function         btm_proc_sp_req_evt
**
** Description      This function is called to process/report
**                  HCI_USER_CONFIRMATION_REQUEST_EVT
**                  or HCI_USER_PASSKEY_REQUEST_EVT
**                  or HCI_USER_PASSKEY_NOTIFY_EVT
**
** Returns          void
**
*******************************************************************************/
void btm_proc_sp_req_evt (tBTM_SP_EVT event, UINT8 *p)
{
    tBTM_STATUS status = BTM_ERR_PROCESSING;
    tBTM_SP_EVT_DATA evt_data;
    UINT8               *p_bda = evt_data.cfm_req.bd_addr;
    tBTM_SEC_DEV_REC *p_dev_rec;

    /* All events start with bd_addr */
    STREAM_TO_BDADDR (p_bda, p);

    BTM_TRACE_EVENT ("btm_proc_sp_req_evt() BDA: %08x%04x event: 0x%x, State: %s",
                      (p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3], (p_bda[4] << 8) + p_bda[5],
                      event, btm_pair_state_descr(btm_cb.pairing_state));

    if ( ((p_dev_rec = btm_find_dev (p_bda)) != NULL)
         &&  (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
         &&  (memcmp (btm_cb.pairing_bda, p_bda, BD_ADDR_LEN) == 0) )
    {
        memcpy (evt_data.cfm_req.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
        memcpy (evt_data.cfm_req.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);

        strlcpy((char *)evt_data.cfm_req.bd_name, (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN);

        switch (event)
        {
            case BTM_SP_CFM_REQ_EVT:
                /* Numeric confirmation. Need user to conf the passkey */
                btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_NUMERIC_CONFIRM);

                /* The device record must be allocated in the "IO cap exchange" step */
                STREAM_TO_UINT32 (evt_data.cfm_req.num_val, p);

                evt_data.cfm_req.just_works = TRUE;

                /* process user confirm req in association with the auth_req param */
#if (BTM_LOCAL_IO_CAPS == BTM_IO_CAP_IO)
                if ( (p_dev_rec->rmt_io_caps == BTM_IO_CAP_IO)
                     &&  (btm_cb.devcb.loc_io_caps == BTM_IO_CAP_IO)
                     &&  ((p_dev_rec->rmt_auth_req & BTM_AUTH_SP_YES) || (btm_cb.devcb.loc_auth_req & BTM_AUTH_SP_YES)) )
                {
                    /* Both devices are DisplayYesNo and one or both devices want to authenticate
                       -> use authenticated link key */
                    evt_data.cfm_req.just_works = FALSE;
                }
#endif
                BTM_TRACE_DEBUG ("btm_proc_sp_req_evt()  just_works:%d, io loc:%d, rmt:%d, auth loc:%d, rmt:%d",
                                  evt_data.cfm_req.just_works, btm_cb.devcb.loc_io_caps, p_dev_rec->rmt_io_caps,
                                  btm_cb.devcb.loc_auth_req, p_dev_rec->rmt_auth_req);

                evt_data.cfm_req.loc_auth_req   = btm_cb.devcb.loc_auth_req;
                evt_data.cfm_req.rmt_auth_req   = p_dev_rec->rmt_auth_req;
                evt_data.cfm_req.loc_io_caps    = btm_cb.devcb.loc_io_caps;
                evt_data.cfm_req.rmt_io_caps    = p_dev_rec->rmt_io_caps;
                break;

            case BTM_SP_KEY_NOTIF_EVT:
                /* Passkey notification (other side is a keyboard) */
                STREAM_TO_UINT32 (evt_data.key_notif.passkey, p);

                BTM_TRACE_DEBUG ("BTM_SP_KEY_NOTIF_EVT:  passkey: %u", evt_data.key_notif.passkey);

                btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
                break;

#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
            case BTM_SP_KEY_REQ_EVT:
                /* HCI_USER_PASSKEY_REQUEST_EVT */
                btm_sec_change_pairing_state (BTM_PAIR_STATE_KEY_ENTRY);
                break;
#endif
        }

        if (btm_cb.api.p_sp_callback)
        {
            status = (*btm_cb.api.p_sp_callback) (event, (tBTM_SP_EVT_DATA *)&evt_data);
            if (status != BTM_NOT_AUTHORIZED)
            {
                return;
            }
            /* else BTM_NOT_AUTHORIZED means when the app wants to reject the req right now */
        }
        else if ( (event == BTM_SP_CFM_REQ_EVT) && (evt_data.cfm_req.just_works == TRUE) )
        {
            /* automatically reply with just works if no sp_cback */
            status = BTM_SUCCESS;
        }

        if (event == BTM_SP_CFM_REQ_EVT)
        {
            BTM_TRACE_DEBUG ("calling BTM_ConfirmReqReply with status: %d", status);
            BTM_ConfirmReqReply (status, p_bda);
        }
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
        else if (event == BTM_SP_KEY_REQ_EVT)
        {
            BTM_PasskeyReqReply(status, p_bda, 0);
        }
#endif
        return;
    }

    /* Something bad. we can only fail this connection */
    btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;

    if (BTM_SP_CFM_REQ_EVT == event)
    {
        btsnd_hcic_user_conf_reply (p_bda, FALSE);
    }
    else if (BTM_SP_KEY_NOTIF_EVT == event)
    {
        /* do nothing -> it very unlikely to happen.
        This event is most likely to be received by a HID host when it first connects to a HID device.
        Usually the Host initiated the connection in this case.
        On Mobile platforms, if there's a security process happening,
        the host probably can not initiate another connection.
        BTW (PC) is another story.  */
        if (NULL != (p_dev_rec = btm_find_dev (p_bda)) )
        {
            btm_sec_disconnect (p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE);
        }
    }
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
    else
    {
        btsnd_hcic_user_passkey_neg_reply(p_bda);
    }
#endif
}

 btm_cb.api.p_sp_callback   在 BTM_SecRegister函数中注册    btm_cb.api = *p_cb_info;

 BTM_SecRegister((tBTM_APPL_INFO*)&bta_security);  函数在bta_dm_enable 注册;

/*******************************************************************************
**
** Function         BTM_SecRegister
**
** Description      Application manager calls this function to register for
**                  security services.  There can be one and only one application
**                  saving link keys.  BTM allows only first registration.
**
** Returns          TRUE if registered OK, else FALSE
**
*******************************************************************************/
BOOLEAN BTM_SecRegister(tBTM_APPL_INFO *p_cb_info)
{
#if BLE_INCLUDED == TRUE
    BT_OCTET16      temp_value = {0};
#endif

    BTM_TRACE_EVENT("%s application registered", __func__);

#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
    LOG_INFO(LOG_TAG, "%s p_cb_info->p_le_callback == 0x%p", __func__, p_cb_info->p_le_callback);
    if (p_cb_info->p_le_callback)
    {
#if SMP_INCLUDED == TRUE
      BTM_TRACE_EVENT("%s SMP_Register( btm_proc_smp_cback )", __func__);
      SMP_Register(btm_proc_smp_cback);
#endif
      /* if no IR is loaded, need to regenerate all the keys */
      if (memcmp(btm_cb.devcb.id_keys.ir, &temp_value, sizeof(BT_OCTET16)) == 0)
      {
        btm_ble_reset_id();
      }
    }
    else
    {
      LOG_WARN(LOG_TAG, "%s p_cb_info->p_le_callback == NULL", __func__);
    }
#endif

    btm_cb.api = *p_cb_info;
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     LOG_INFO(LOG_TAG, "%s btm_cb.api.p_le_callback = 0x%p ", __func__, btm_cb.api.p_le_callback);
#endif
    BTM_TRACE_EVENT("%s application registered", __func__);
    return(TRUE);
}

system\bt\bta\dm\bta_dm_act.c

/* bta security callback */
const tBTM_APPL_INFO bta_security =
{
    &bta_dm_authorize_cback,
    &bta_dm_pin_cback,
    &bta_dm_new_link_key_cback,
    &bta_dm_authentication_complete_cback,
    &bta_dm_bond_cancel_complete_cback,
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
    &bta_dm_sp_cback
#else
    NULL
#endif
#if BLE_INCLUDED == TRUE
#if SMP_INCLUDED == TRUE
    ,&bta_dm_ble_smp_cback
#endif
    ,&bta_dm_ble_id_key_cback
#endif

};

 

/*******************************************************************************
**
** Function         bta_dm_sp_cback
**
** Description      simple pairing callback from BTM
**
** Returns          void
**
*******************************************************************************/
static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
{
    tBTM_STATUS status = BTM_CMD_STARTED;
    tBTA_DM_SEC sec_event;
    tBTA_DM_SEC_EVT pin_evt = BTA_DM_SP_KEY_NOTIF_EVT;

    APPL_TRACE_EVENT("bta_dm_sp_cback: %d", event);
    if (!bta_dm_cb.p_sec_cback)
        return BTM_NOT_AUTHORIZED;

    /* TODO_SP */
    switch(event)
    {
    case BTM_SP_IO_REQ_EVT:
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
        /* translate auth_req */
        bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
            &p_data->io_req.oob_data, &p_data->io_req.auth_req, p_data->io_req.is_orig);
#endif
        APPL_TRACE_EVENT("io mitm: %d oob_data:%d", p_data->io_req.auth_req, p_data->io_req.oob_data);
        break;
    case BTM_SP_IO_RSP_EVT:
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
        bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
                         p_data->io_rsp.oob_data, p_data->io_rsp.auth_req );
#endif
        break;

    case BTM_SP_CFM_REQ_EVT:
        pin_evt = BTA_DM_SP_CFM_REQ_EVT;
        bta_dm_cb.just_works = sec_event.cfm_req.just_works = p_data->cfm_req.just_works;
        sec_event.cfm_req.loc_auth_req = p_data->cfm_req.loc_auth_req;
        sec_event.cfm_req.rmt_auth_req = p_data->cfm_req.rmt_auth_req;
        sec_event.cfm_req.loc_io_caps = p_data->cfm_req.loc_io_caps;
        sec_event.cfm_req.rmt_io_caps = p_data->cfm_req.rmt_io_caps;

        /* continue to next case */
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
    /* Passkey entry mode, mobile device with output capability is very
        unlikely to receive key request, so skip this event */
    /*case BTM_SP_KEY_REQ_EVT: */
    case BTM_SP_KEY_NOTIF_EVT:
#endif
        bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;

        if(BTM_SP_CFM_REQ_EVT == event)
        {
          /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
             call remote name request using values from cfm_req */
          if(p_data->cfm_req.bd_name[0] == 0)
          {
              bta_dm_cb.pin_evt = pin_evt;
              bdcpy(bta_dm_cb.pin_bd_addr, p_data->cfm_req.bd_addr);
              bta_dm_cb.rmt_io_caps = sec_event.cfm_req.rmt_io_caps;
              bta_dm_cb.loc_io_caps = sec_event.cfm_req.loc_io_caps;
              bta_dm_cb.rmt_auth_req = sec_event.cfm_req.rmt_auth_req;
              bta_dm_cb.loc_auth_req = sec_event.cfm_req.loc_auth_req;

              BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->cfm_req.dev_class);
              if ((BTM_ReadRemoteDeviceName(p_data->cfm_req.bd_addr, bta_dm_pinname_cback,
                         BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
                  return BTM_CMD_STARTED;
              APPL_TRACE_WARNING(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
          }
          else
          {
              /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
                 copy these values into key_notif from cfm_req */
              bdcpy(sec_event.key_notif.bd_addr, p_data->cfm_req.bd_addr);
              BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->cfm_req.dev_class);
              strlcpy((char*)sec_event.key_notif.bd_name,
                      (char*)p_data->cfm_req.bd_name, BD_NAME_LEN);
           }
        }

        if (BTM_SP_KEY_NOTIF_EVT == event)
        {
            /* If the device name is not known, save bdaddr and devclass
               and initiate a name request with values from key_notif */
            if(p_data->key_notif.bd_name[0] == 0)
            {
                bta_dm_cb.pin_evt = pin_evt;
                /* Store the local and remote io caps */
                bta_dm_cb.loc_io_caps = sec_event.cfm_req.loc_io_caps;
                bta_dm_cb.rmt_io_caps = sec_event.cfm_req.rmt_io_caps;
                bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
                BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
                if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback,
                         BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
                return BTM_CMD_STARTED;
                APPL_TRACE_WARNING(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
            }
            else
            {
                bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
                BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
                strlcpy((char*)sec_event.key_notif.bd_name,
                        (char*)p_data->key_notif.bd_name, BD_NAME_LEN);
                sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
            }
        }

        bta_dm_cb.p_sec_cback(pin_evt, &sec_event);

        break;

    case BTM_SP_LOC_OOB_EVT:
        bta_dm_co_loc_oob((BOOLEAN)(p_data->loc_oob.status == BTM_SUCCESS),
            p_data->loc_oob.c, p_data->loc_oob.r);
        break;

    case BTM_SP_RMT_OOB_EVT:
        /* If the device name is not known, save bdaddr and devclass and initiate a name request */
        if (p_data->rmt_oob.bd_name[0] == 0)
        {
             bta_dm_cb.pin_evt = BTA_DM_SP_RMT_OOB_EVT;
             bdcpy(bta_dm_cb.pin_bd_addr, p_data->rmt_oob.bd_addr);
             BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->rmt_oob.dev_class);
             if ((BTM_ReadRemoteDeviceName(p_data->rmt_oob.bd_addr, bta_dm_pinname_cback,
                      BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
             return BTM_CMD_STARTED;
             APPL_TRACE_WARNING(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
        }

        bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
        BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
        strlcpy((char*)sec_event.rmt_oob.bd_name, (char*)p_data->rmt_oob.bd_name, BD_NAME_LEN);

        bta_dm_cb.p_sec_cback(BTA_DM_SP_RMT_OOB_EVT, &sec_event);

        bta_dm_co_rmt_oob(p_data->rmt_oob.bd_addr);
        break;

    case BTM_SP_COMPLT_EVT:
        /* do not report this event - handled by link_key_callback or auth_complete_callback */
        break;

    case BTM_SP_KEYPRESS_EVT:
        memcpy(&sec_event.key_press, &p_data->key_press, sizeof(tBTM_SP_KEYPRESS));
        bta_dm_cb.p_sec_cback(BTA_DM_SP_KEYPRESS_EVT, &sec_event);
        break;

    case BTM_SP_UPGRADE_EVT:
        bta_dm_co_lk_upgrade(p_data->upgrade.bd_addr, &p_data->upgrade.upgrade );
        break;

    default:
        status = BTM_NOT_AUTHORIZED;
        break;
    }
    APPL_TRACE_EVENT("dm status: %d", status);
    return status;
}

bta_dm_cb.p_sec_cback=bte_dm_evt

void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data)
{
    /* switch context to btif task context (copy full union size for convenience) */
    bt_status_t status = btif_transfer_context(btif_dm_upstreams_evt, (uint16_t)event,
                                (void*)p_data, sizeof(tBTA_DM_SEC), btif_dm_data_copy);

    /* catch any failed context transfers */
    ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}
/*******************************************************************************
**
** Function         btif_dm_upstreams_cback
**
** Description      Executes UPSTREAMS events in btif context
**
** Returns          void
**
*******************************************************************************/
static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
{
    tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param;
    tBTA_SERVICE_MASK service_mask;
    uint32_t i;
    bt_bdaddr_t bd_addr;

    BTIF_TRACE_EVENT("%s: ev: %s", __func__, dump_dm_event(event));

    switch (event)
    {
        case BTA_DM_ENABLE_EVT:
        {
             BD_NAME bdname;
             bt_status_t status;
             bt_property_t prop;
             prop.type = BT_PROPERTY_BDNAME;
             prop.len = BD_NAME_LEN + 1;
             prop.val = (void*)bdname;

             status = btif_storage_get_adapter_property(&prop);
             if (status == BT_STATUS_SUCCESS)
             {
                 /* A name exists in the storage. Make this the device name */
                 BTA_DmSetDeviceName((char*)prop.val);
             }
             else
             {
                 /* Storage does not have a name yet.
                  * Use the default name and write it to the chip
                  */
                 BTA_DmSetDeviceName(btif_get_default_local_name());
             }

#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
             /* Enable local privacy */
             BTA_DmBleConfigLocalPrivacy(BLE_LOCAL_PRIVACY_ENABLED);
#endif

             /* for each of the enabled services in the mask, trigger the profile
              * enable */
             service_mask = btif_get_enabled_services_mask();
             for (i=0; i <= BTA_MAX_SERVICE_ID; i++)
             {
                 if (service_mask &
                     (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i)))
                 {
                     btif_in_execute_service_request(i, TRUE);
                 }
             }
             /* clear control blocks */
             memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t));
             pairing_cb.bond_type = BOND_TYPE_PERSISTENT;

             /* This function will also trigger the adapter_properties_cb
             ** and bonded_devices_info_cb
             */
             btif_storage_load_bonded_devices();

             load_iot_devlist(IOT_DEV_CONF_FILE);

             btif_enable_bluetooth_evt(p_data->enable.status);
        }
        break;

        case BTA_DM_DISABLE_EVT:
            /* for each of the enabled services in the mask, trigger the profile
             * disable */
            service_mask = btif_get_enabled_services_mask();
            if (service_mask &
                (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(BTA_BLE_SERVICE_ID)))
            {
                btif_in_execute_service_request(BTA_BLE_SERVICE_ID, FALSE);
            }
            unload_iot_devlist();
            btif_disable_bluetooth_evt();
            break;

        case BTA_DM_PIN_REQ_EVT:
            btif_dm_pin_req_evt(&p_data->pin_req);
            break;

        case BTA_DM_AUTH_CMPL_EVT:
            btif_dm_auth_cmpl_evt(&p_data->auth_cmpl);
            break;

        case BTA_DM_BOND_CANCEL_CMPL_EVT:
            if (pairing_cb.state == BT_BOND_STATE_BONDING)
            {
                bdcpy(bd_addr.address, pairing_cb.bd_addr);
                btm_set_bond_type_dev(pairing_cb.bd_addr, BOND_TYPE_UNKNOWN);
                bond_state_changed(p_data->bond_cancel_cmpl.result, &bd_addr, BT_BOND_STATE_NONE);
                btif_dm_remove_bond(&bd_addr);
            }
            break;

        case BTA_DM_SP_CFM_REQ_EVT:
            btif_dm_ssp_cfm_req_evt(&p_data->cfm_req);
            break;
        case BTA_DM_SP_KEY_NOTIF_EVT:
            btif_dm_ssp_key_notif_evt(&p_data->key_notif);
            break;

        case BTA_DM_DEV_UNPAIRED_EVT:
            bdcpy(bd_addr.address, p_data->link_down.bd_addr);
            btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);

            /*special handling for HID devices */
            #if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE))
            btif_hh_remove_device(bd_addr);
            #endif
            btif_storage_remove_bonded_device(&bd_addr);
            bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_NONE);
            break;

        case BTA_DM_BUSY_LEVEL_EVT:
        {

            if (p_data->busy_level.level_flags & BTM_BL_INQUIRY_PAGING_MASK)
            {
                if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_STARTED)
                {
                       HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                                                BT_DISCOVERY_STARTED);
                       btif_dm_inquiry_in_progress = TRUE;
                }
                else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_CANCELLED)
                {
                       HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                                                BT_DISCOVERY_STOPPED);
                       btif_dm_inquiry_in_progress = FALSE;
                }
                else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_COMPLETE)
                {
                       btif_dm_inquiry_in_progress = FALSE;
                }
            }
        }break;

        case BTA_DM_LINK_UP_EVT:
            bdcpy(bd_addr.address, p_data->link_up.bd_addr);
            BTIF_TRACE_DEBUG("BTA_DM_LINK_UP_EVT. Sending BT_ACL_STATE_CONNECTED");

            if(p_data->link_up.link_type == BT_TRANSPORT_LE)
            {
                num_active_le_links++;
                BTIF_TRACE_DEBUG("num_active_le_links is %d ",
                    num_active_le_links);
            }

            if(p_data->link_up.link_type == BT_TRANSPORT_BR_EDR)
            {
                num_active_br_edr_links++;
                BTIF_TRACE_DEBUG("num_active_br_edr_links is %d ",
                    num_active_br_edr_links);
            }
            /* When tuchtones are enabled and 2 EDR HS are connected, if new
             * connection is initated, then tuch tones are send to both connected HS
             * over A2dp.Stream will be suspended after 3 secs and if remote has
             * initiated play in this duartion, multicast must not be enabled with
             * 3 ACL's, hence trigger a2dp suspend.
             * During active muisc streaming no new connection can happen, hence
             * We will get this only when multistreaming is happening due to tuchtones
             */
            if (btif_av_get_ongoing_multicast())
            {
                // trigger a2dp suspend
                btif_av_trigger_suspend();
            }

            btif_update_remote_version_property(&bd_addr);

            HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
                      &bd_addr, BT_ACL_STATE_CONNECTED);
            break;

        case BTA_DM_LINK_DOWN_EVT:
            bdcpy(bd_addr.address, p_data->link_down.bd_addr);

            btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);

            BTIF_TRACE_DEBUG("BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
            if (num_active_le_links > 0 &&
                p_data->link_down.link_type == BT_TRANSPORT_LE)
            {
                num_active_le_links--;
                BTIF_TRACE_DEBUG("num_active_le_links is %d ",num_active_le_links);
            }

            if (num_active_br_edr_links > 0 &&
                p_data->link_down.link_type == BT_TRANSPORT_BR_EDR)
            {
                num_active_br_edr_links--;
                BTIF_TRACE_DEBUG("num_active_br_edr_links is %d ",num_active_br_edr_links);
            }
            btif_av_move_idle(bd_addr);
            BTIF_TRACE_DEBUG("BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
            HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
                      &bd_addr, BT_ACL_STATE_DISCONNECTED);
            break;

        case BTA_DM_HW_ERROR_EVT:
            BTIF_TRACE_ERROR("Received H/W Error. ");
            /* Flush storage data */
            btif_config_flush();
            usleep(100000); /* 100milliseconds */
            /* Killing the process to force a restart as part of fault tolerance */
            kill(getpid(), SIGKILL);
            break;

#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
        case BTA_DM_BLE_KEY_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_KEY_EVT key_type=0x%02x ", p_data->ble_key.key_type);

            /* If this pairing is by-product of local initiated GATT client Read or Write,
            BTA would not have sent BTA_DM_BLE_SEC_REQ_EVT event and Bond state would not
            have setup properly. Setup pairing_cb and notify App about Bonding state now*/
            if (pairing_cb.state != BT_BOND_STATE_BONDING)
            {
                BTIF_TRACE_DEBUG("Bond state not sent to App so far.Notify the app now");
                bond_state_changed(BT_STATUS_SUCCESS, (bt_bdaddr_t*)p_data->ble_key.bd_addr,
                                   BT_BOND_STATE_BONDING);
            }
            else if (memcmp (pairing_cb.bd_addr, p_data->ble_key.bd_addr, BD_ADDR_LEN)!=0)
            {
                BTIF_TRACE_ERROR("BD mismatch discard BLE key_type=%d ",p_data->ble_key.key_type);
                break;
            }

            switch (p_data->ble_key.key_type)
            {
                case BTA_LE_KEY_PENC:
                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PENC");
                    pairing_cb.ble.is_penc_key_rcvd = TRUE;
                    pairing_cb.ble.penc_key = p_data->ble_key.p_key_value->penc_key;
                    break;

                case BTA_LE_KEY_PID:
                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PID");
                    pairing_cb.ble.is_pid_key_rcvd = TRUE;
                    pairing_cb.ble.pid_key = p_data->ble_key.p_key_value->pid_key;
                    break;

                case BTA_LE_KEY_PCSRK:
                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PCSRK");
                    pairing_cb.ble.is_pcsrk_key_rcvd = TRUE;
                    pairing_cb.ble.pcsrk_key = p_data->ble_key.p_key_value->pcsrk_key;
                    break;

                case BTA_LE_KEY_LENC:
                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LENC");
                    pairing_cb.ble.is_lenc_key_rcvd = TRUE;
                    pairing_cb.ble.lenc_key = p_data->ble_key.p_key_value->lenc_key;
                    break;

                case BTA_LE_KEY_LCSRK:
                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LCSRK");
                    pairing_cb.ble.is_lcsrk_key_rcvd = TRUE;
                    pairing_cb.ble.lcsrk_key = p_data->ble_key.p_key_value->lcsrk_key;
                    break;

                case BTA_LE_KEY_LID:
                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LID");
                    pairing_cb.ble.is_lidk_key_rcvd =  TRUE;
                    break;

                default:
                    BTIF_TRACE_ERROR("unknown BLE key type (0x%02x)", p_data->ble_key.key_type);
                    break;
            }
            break;
        case BTA_DM_BLE_SEC_REQ_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_SEC_REQ_EVT. ");
            btif_dm_ble_sec_req_evt(&p_data->ble_req);
            break;
        case BTA_DM_BLE_PASSKEY_NOTIF_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_NOTIF_EVT. ");
            btif_dm_ble_key_notif_evt(&p_data->key_notif);
            break;
        case BTA_DM_BLE_PASSKEY_REQ_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
            btif_dm_ble_passkey_req_evt(&p_data->pin_req);
            break;
        case BTA_DM_BLE_NC_REQ_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
            btif_dm_ble_key_nc_req_evt(&p_data->key_notif);
            break;
        case BTA_DM_BLE_OOB_REQ_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. ");
            btif_dm_ble_oob_req_evt(&p_data->rmt_oob);
            break;
        case BTA_DM_BLE_SC_OOB_REQ_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_SC_OOB_REQ_EVT. ");
            btif_dm_ble_sc_oob_req_evt(&p_data->rmt_oob);
            break;
        case BTA_DM_BLE_LOCAL_IR_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. ");
            ble_local_key_cb.is_id_keys_rcvd = TRUE;
            memcpy(&ble_local_key_cb.id_keys.irk[0],
                   &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
            memcpy(&ble_local_key_cb.id_keys.ir[0],
                   &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
            memcpy(&ble_local_key_cb.id_keys.dhk[0],
                   &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.irk[0],
                                            BTIF_DM_LE_LOCAL_KEY_IRK,
                                            BT_OCTET16_LEN);
            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.ir[0],
                                            BTIF_DM_LE_LOCAL_KEY_IR,
                                            BT_OCTET16_LEN);
            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.dhk[0],
                                            BTIF_DM_LE_LOCAL_KEY_DHK,
                                            BT_OCTET16_LEN);
            break;
        case BTA_DM_BLE_LOCAL_ER_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_ER_EVT. ");
            ble_local_key_cb.is_er_rcvd = TRUE;
            memcpy(&ble_local_key_cb.er[0], &p_data->ble_er[0], sizeof(BT_OCTET16));
            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.er[0],
                                            BTIF_DM_LE_LOCAL_KEY_ER,
                                            BT_OCTET16_LEN);
            break;

        case BTA_DM_BLE_AUTH_CMPL_EVT:
            BTIF_TRACE_DEBUG("BTA_DM_BLE_AUTH_CMPL_EVT. ");
            btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
            break;

        case BTA_DM_LE_FEATURES_READ:
        {
            tBTM_BLE_VSC_CB cmn_vsc_cb;
            bt_local_le_features_t local_le_features;
            char buf[512];
            bt_property_t prop;
            prop.type = BT_PROPERTY_LOCAL_LE_FEATURES;
            prop.val = (void*)buf;
            prop.len = sizeof(buf);

           /* LE features are not stored in storage. Should be retrived from stack */
            BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
            local_le_features.local_privacy_enabled = BTM_BleLocalPrivacyEnabled();

            prop.len = sizeof (bt_local_le_features_t);
            if (cmn_vsc_cb.filter_support == 1)
                local_le_features.max_adv_filter_supported = cmn_vsc_cb.max_filter;
             else
                local_le_features.max_adv_filter_supported = 0;
            local_le_features.max_adv_instance = cmn_vsc_cb.adv_inst_max;
            local_le_features.max_irk_list_size = cmn_vsc_cb.max_irk_list_sz;
            local_le_features.rpa_offload_supported = cmn_vsc_cb.rpa_offloading;
            local_le_features.activity_energy_info_supported = cmn_vsc_cb.energy_support;
            local_le_features.scan_result_storage_size = cmn_vsc_cb.tot_scan_results_strg;
            local_le_features.version_supported = cmn_vsc_cb.version_supported;
            local_le_features.total_trackable_advertisers =
                        cmn_vsc_cb.total_trackable_advertisers;

            local_le_features.extended_scan_support = cmn_vsc_cb.extended_scan_support > 0;
            local_le_features.debug_logging_supported = cmn_vsc_cb.debug_logging_supported > 0;

            memcpy(prop.val, &local_le_features, prop.len);
            HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, 1, &prop);
            break;
         }

        case BTA_DM_ENER_INFO_READ:
        {
            btif_activity_energy_info_cb_t *p_ener_data = (btif_activity_energy_info_cb_t*) p_param;
            bt_activity_energy_info energy_info;
            energy_info.status = p_ener_data->status;
            energy_info.ctrl_state = p_ener_data->ctrl_state;
            energy_info.rx_time = p_ener_data->rx_time;
            energy_info.tx_time = p_ener_data->tx_time;
            energy_info.idle_time = p_ener_data->idle_time;
            energy_info.energy_used = p_ener_data->energy_used;

            bt_uid_traffic_t* data = uid_set_read_and_clear(uid_set);
            HAL_CBACK(bt_hal_cbacks, energy_info_cb, &energy_info, data);
            osi_free(data);
            break;
        }
#endif

        case BTA_DM_AUTHORIZE_EVT:
        case BTA_DM_SIG_STRENGTH_EVT:
        case BTA_DM_SP_RMT_OOB_EVT:
        case BTA_DM_SP_KEYPRESS_EVT:
        case BTA_DM_ROLE_CHG_EVT:

        default:
            BTIF_TRACE_WARNING( "btif_dm_cback : unhandled event (%d)", event );
            break;
    }

    btif_dm_data_free(event, p_data);
}
       case BTA_DM_SP_CFM_REQ_EVT:
            btif_dm_ssp_cfm_req_evt(&p_data->cfm_req);
            break;
/*******************************************************************************
**
** Function         btif_dm_ssp_cfm_req_evt
**
** Description      Executes SSP confirm request event in btif context
**
** Returns          void
**
*******************************************************************************/
static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ *p_ssp_cfm_req)
{
    bt_bdaddr_t bd_addr;
    bt_bdname_t bd_name;
    UINT32 cod;
    BOOLEAN is_incoming = !(pairing_cb.state == BT_BOND_STATE_BONDING);
    int dev_type;

    BTIF_TRACE_DEBUG("%s", __FUNCTION__);

    /* Remote properties update */
	/*
		获取蓝牙类型,如果没有设置则默认为BT_DEVICE_TYPE_BREDR  
		#define BT_DEVICE_TYPE_BREDR   0x01
		#define BT_DEVICE_TYPE_BLE     0x02
		#define BT_DEVICE_TYPE_DUMO    0x03
	*/
    if (!btif_get_device_type(p_ssp_cfm_req->bd_addr, &dev_type))
    {
        dev_type = BT_DEVICE_TYPE_BREDR;
    }
    btif_update_remote_properties(p_ssp_cfm_req->bd_addr, p_ssp_cfm_req->bd_name,
                                  p_ssp_cfm_req->dev_class, (tBT_DEVICE_TYPE) dev_type);

    bdcpy(bd_addr.address, p_ssp_cfm_req->bd_addr);
    memcpy(bd_name.name, p_ssp_cfm_req->bd_name, BD_NAME_LEN);

    if (pairing_cb.state == BT_BOND_STATE_BONDING &&
        bdcmp(bd_addr.address, pairing_cb.bd_addr) != 0)
    {
        BTIF_TRACE_WARNING("%s(): already in bonding state, reject request", __FUNCTION__);
        btif_dm_ssp_reply(&bd_addr, BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 0, 0);
        return;
    }

    /* Set the pairing_cb based on the local & remote authentication requirements */
    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
	/*
		btif_dm_ssp_cfm_req_evt: just_works :0, loc_auth_req =3, rmt_auth_req =3
	*/
    BTIF_TRACE_EVENT("%s: just_works :%d, loc_auth_req =%d, rmt_auth_req =%d ",
        __FUNCTION__,p_ssp_cfm_req->just_works,p_ssp_cfm_req->loc_auth_req,
        p_ssp_cfm_req->rmt_auth_req);

    /* if just_works and bonding bit is not set treat this as temporary */
    if (p_ssp_cfm_req->just_works && !(p_ssp_cfm_req->loc_auth_req & BTM_AUTH_BONDS) &&
        !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS) &&
        !(check_cod((bt_bdaddr_t*)&p_ssp_cfm_req->bd_addr, COD_HID_POINTING)))
        pairing_cb.bond_type = BOND_TYPE_TEMPORARY;
    else
        pairing_cb.bond_type = BOND_TYPE_PERSISTENT;

    btm_set_bond_type_dev(p_ssp_cfm_req->bd_addr, pairing_cb.bond_type);

    pairing_cb.is_ssp = TRUE;

    /* If JustWorks auto-accept */
    if (p_ssp_cfm_req->just_works)
    {
        /* Pairing consent for JustWorks needed if:
         * 1. Incoming (non-temporary) pairing is detected AND
         * 2. local IO capabilities are DisplayYesNo AND
         * 3. remote IO capabiltiies are DisplayOnly or NoInputNoOutput;
         */
        if (is_incoming && pairing_cb.bond_type != BOND_TYPE_TEMPORARY &&
               ((p_ssp_cfm_req->loc_io_caps == HCI_IO_CAP_DISPLAY_YESNO) &&
                (p_ssp_cfm_req->rmt_io_caps == HCI_IO_CAP_DISPLAY_ONLY ||
                 p_ssp_cfm_req->rmt_io_caps == HCI_IO_CAP_NO_IO)))
        {
            BTIF_TRACE_EVENT("%s: User consent needed for incoming pairing request. loc_io_caps: %d, rmt_io_caps: %d",
                __FUNCTION__, p_ssp_cfm_req->loc_io_caps, p_ssp_cfm_req->rmt_io_caps);
        }
        else
        {
            BTIF_TRACE_EVENT("%s: Auto-accept JustWorks pairing", __FUNCTION__);
            btif_dm_ssp_reply(&bd_addr, BT_SSP_VARIANT_CONSENT, TRUE, 0);
            return;
        }
    }

    cod = devclass2uint(p_ssp_cfm_req->dev_class);

    if (cod == 0) {
        LOG_DEBUG(LOG_TAG, "%s cod is 0, set as unclassified", __func__);
        cod = COD_UNCLASSIFIED;
    }

    pairing_cb.sdp_attempts = 0;
	//通过调用JNI层回调函数,将数据反馈到上层
    HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name, cod,
                     (p_ssp_cfm_req->just_works ? BT_SSP_VARIANT_CONSENT : BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
                     p_ssp_cfm_req->num_val);
}

 HAL_CBACK(bt_hal_cbacks, ssp_request_cb )  回调给JNI层,JNI层对应的位置代码为:

packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
    jbyteArray addr = NULL;
    jbyteArray devname = NULL;
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }
    if (!bd_addr) {
        ALOGE("Address is null in %s", __FUNCTION__);
        return;
    }

    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (addr == NULL) goto Fail;
    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);

    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
    if (devname == NULL) goto Fail;
    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);

    if (sJniCallbacksObj) {
        callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
                                    (jint) pairing_variant, pass_key);
    }

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(addr);
    callbackEnv->DeleteLocalRef(devname);
    return;

Fail:
    if (addr) callbackEnv->DeleteLocalRef(addr);
    if (devname) callbackEnv->DeleteLocalRef(devname);

    ALOGE("Error while allocating in: %s", __FUNCTION__);
}

JAVA层:

packages\apps\Bluetooth\src\com\android\bluetooth\btservice\BondStateMachine.java

    void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant,
            int passkey) {
        //TODO(BT): Get wakelock and update name and cod
        BluetoothDevice bdDevice = mRemoteDevices.getDevice(address);
        if (bdDevice == null) {
            mRemoteDevices.addDeviceProperties(address);
        }
        infoLog("sspRequestCallback: " + address + " name: " + name + " cod: " +
                cod + " pairingVariant " + pairingVariant + " passkey: " + passkey);
        int variant;
        boolean displayPasskey = false;
        switch(pairingVariant) {

            case AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION :
                variant = BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION;
                displayPasskey = true;
            break;

            case AbstractionLayer.BT_SSP_VARIANT_CONSENT :
                variant = BluetoothDevice.PAIRING_VARIANT_CONSENT;
            break;

            case AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY :
                variant = BluetoothDevice.PAIRING_VARIANT_PASSKEY;
            break;

            case AbstractionLayer.BT_SSP_VARIANT_PASSKEY_NOTIFICATION :
                variant = BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY;
                displayPasskey = true;
            break;

            default:
                errorLog("SSP Pairing variant not present");
                return;
        }
        BluetoothDevice device = mRemoteDevices.getDevice(address);
        if (device == null) {
           warnLog("Device is not known for:" + Utils.getAddressStringFromByte(address));
           mRemoteDevices.addDeviceProperties(address);
           device = mRemoteDevices.getDevice(address);
        }

        Message msg = obtainMessage(SSP_REQUEST);
        msg.obj = device;
        if(displayPasskey)
            msg.arg1 = passkey;
        msg.arg2 = variant;
        sendMessage(msg);
    }

 

BLE蓝牙绑定和密码配对流程及代码详解: 一、蓝牙绑定流程 在 BLE 蓝牙设备连接时,需要进行绑定操作,以确保设备间通信的安全性。蓝牙绑定流程如下: 1. 从主设备中发出绑定请求。 2. 从设备接收到绑定请求并回复同意绑定。 3. 主设备生成随机数并加密发送到从设备。 4. 从设备使用预设的加密算法对接收到的随机数进行解密,并将加密后的结果发送给主设备。 5. 主设备对接收到的加密结果进行校验,若校验通过,表示绑定成功。 二、密码配对流程 在 BLE 蓝牙设备连接时,需要进行密码配对操作,以确保设备间通信的安全性。密码配对流程如下: 1. 从主设备中发出密码配对请求。 2. 从设备接收到密码配对请求并回复同意配对。 3. 主设备生成随机数并加密发送到从设备。 4. 从设备使用预设的加密算法对接收到的随机数进行解密,并将加密后的结果发送给主设备。 5. 主设备对接收到的加密结果进行校验,若校验通过,表示配对成功。 三、代码实现 下面是使用 Android BLE API 实现蓝牙绑定和密码配对的示例代码: ```java // 绑定流程 private void startBonding(BluetoothDevice device) { device.createBond(); } // 密码配对流程 private void startPairing(BluetoothDevice device) { device.setPairingConfirmation(true); } @Override public void onBondStateChanged(BluetoothDevice device, int state) { switch (state) { case BluetoothDevice.BOND_BONDING: Log.d(TAG, "正在绑定设备:" + device.getName()); break; case BluetoothDevice.BOND_BONDED: Log.d(TAG, "已绑定设备:" + device.getName()); break; case BluetoothDevice.BOND_NONE: Log.d(TAG, "未绑定设备:" + device.getName()); break; } } @Override public void onPairingRequest(BluetoothDevice device, int mode) { switch (mode) { case BluetoothDevice.PAIRING_VARIANT_PIN: Log.d(TAG, "需要输入 PIN 码"); // 输入 PIN 码 device.setPin(mPin.getBytes()); break; case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION: Log.d(TAG, "需要确认 Passkey"); // 确认 Passkey device.setPairingConfirmation(true); break; case BluetoothDevice.PAIRING_VARIANT_CONSENT: Log.d(TAG, "需要确认配对"); // 确认配对 startPairing(device); break; case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY: case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN: Log.d(TAG, "显示 Passkey 或 PIN 码"); break; default: Log.e(TAG, "未知的配对模式:" + mode); break; } } ``` 以上代码仅供参考,实际实现可能会因为硬件设备和蓝牙协议版本的不同而有所差异。在实际开发中,还需要注意蓝牙设备的连接状态和信号强度等信息,并根据需要进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值