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