Newer
Older
/******************************************************************************
*
* Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains functions that interface with the HCI transport. On
* the receive side, it routes events to the appropriate handler, e.g.
* L2CAP, ScoMgr. On the transmit side, it manages the command
* transmission.
*
******************************************************************************/
#include <base/functional/bind.h>
#include "common/metrics.h"
#include "device/include/controller.h"
#include "gd/common/init_flags.h"
#include "main/shim/hci_layer.h"
#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/ble_acl_interface.h"
#include "stack/include/ble_hci_link_interface.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/btm_iso_api.h"
#include "stack/include/btu.h"
#include "stack/include/dev_hci_link_interface.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/inq_hci_link_interface.h"
#include "stack/include/l2cap_hci_link_interface.h"
#include "stack/include/sco_hci_link_interface.h"
#include "stack/include/sec_hci_link_interface.h"
#include "stack/include/stack_metrics_logging.h"
#include "types/raw_address.h"
using bluetooth::hci::IsoManager;
bool BTM_BLE_IS_RESOLVE_BDA(const RawAddress& x); // TODO remove
void BTA_sys_signal_hw_error(); // TODO remove
void smp_cancel_start_encryption_attempt(); // TODO remove
void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason,
std::string comment); // TODO remove
/******************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
/******************************************************************************/
static void btu_hcif_inquiry_comp_evt(uint8_t* p);
static void btu_hcif_authentication_comp_evt(uint8_t* p);
static void btu_hcif_rmt_name_request_comp_evt(const uint8_t* p,
uint16_t evt_len);
static void btu_hcif_encryption_change_evt(uint8_t* p);
static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p,
uint8_t evt_len);
static void btu_hcif_command_complete_evt(BT_HDR* response, void* context);
static void btu_hcif_command_status_evt(uint8_t status, BT_HDR* command,
void* context);
static void btu_hcif_hardware_error_evt(uint8_t* p);
static void btu_hcif_mode_change_evt(uint8_t* p);
static void btu_hcif_link_key_notification_evt(const uint8_t* p);
static void btu_hcif_read_clock_off_comp_evt(uint8_t* p);
static void btu_hcif_esco_connection_comp_evt(const uint8_t* p);
static void btu_hcif_esco_connection_chg_evt(uint8_t* p);
/* Simple Pairing Events */
static void btu_hcif_io_cap_request_evt(const uint8_t* p);
static void btu_ble_ll_conn_param_upd_evt(uint8_t* p, uint16_t evt_len);
static void btu_ble_proc_ltk_req(uint8_t* p, uint16_t evt_len);
static void btu_hcif_encryption_key_refresh_cmpl_evt(uint8_t* p);
static void btu_ble_data_length_change_evt(uint8_t* p, uint16_t evt_len);
static void btu_ble_rc_param_req_evt(uint8_t* p, uint8_t len);
/**
* Log HCI event metrics that are not handled in special functions
* @param evt_code event code
* @param p_event pointer to event parameter, skipping paremter length
*/
void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event) {
uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
RawAddress bda = RawAddress::kEmpty;
switch (evt_code) {
case HCI_IO_CAPABILITY_REQUEST_EVT:
case HCI_IO_CAPABILITY_RESPONSE_EVT:
case HCI_LINK_KEY_REQUEST_EVT:
case HCI_LINK_KEY_NOTIFICATION_EVT:
case HCI_USER_PASSKEY_REQUEST_EVT:
case HCI_USER_PASSKEY_NOTIFY_EVT:
case HCI_USER_CONFIRMATION_REQUEST_EVT:
case HCI_KEYPRESS_NOTIFY_EVT:
case HCI_REMOTE_OOB_DATA_REQUEST_EVT:
STREAM_TO_BDADDR(bda, p_event);
log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason,
value);
break;
case HCI_SIMPLE_PAIRING_COMPLETE_EVT:
case HCI_RMT_NAME_REQUEST_COMP_EVT:
STREAM_TO_UINT8(status, p_event);
STREAM_TO_BDADDR(bda, p_event);
log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason,
value);
case HCI_AUTHENTICATION_COMP_EVT:
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
handle = HCID_GET_HANDLE(handle);
log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason,
value);
break;
case HCI_ENCRYPTION_CHANGE_EVT: {
uint8_t encryption_enabled;
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
STREAM_TO_UINT8(encryption_enabled, p_event);
log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason,
encryption_enabled);
break;
}
case HCI_ESCO_CONNECTION_COMP_EVT: {
uint8_t link_type;
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
STREAM_TO_BDADDR(bda, p_event);
STREAM_TO_UINT8(link_type, p_event);
handle = HCID_GET_HANDLE(handle);
log_link_layer_connection_event(
&bda, handle, android::bluetooth::DIRECTION_UNKNOWN, link_type, cmd,
evt_code, android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
break;
}
case HCI_ESCO_CONNECTION_CHANGED_EVT: {
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
handle = HCID_GET_HANDLE(handle);
log_link_layer_connection_event(
nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
android::bluetooth::LINK_TYPE_UNKNOWN, cmd, evt_code,
android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
break;
}
case HCI_CONNECTION_COMP_EVT: // EventCode::CONNECTION_COMPLETE
case HCI_CONNECTION_REQUEST_EVT: // EventCode::CONNECTION_REQUEST
case HCI_DISCONNECTION_COMP_EVT: // EventCode::DISCONNECTION_COMPLETE
default:
LOG_ERROR(
"Unexpectedly received event_code:0x%02x that should not be "
"handled here",
evt_code);
break;
/*******************************************************************************
*
* 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_t controller_id,
const BT_HDR* p_msg) {
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
uint8_t hci_evt_code, hci_evt_len;
STREAM_TO_UINT8(hci_evt_code, p);
STREAM_TO_UINT8(hci_evt_len, p);
// validate event size
if (hci_evt_len < hci_event_parameters_minimum_length[hci_evt_code]) {
HCI_TRACE_WARNING("%s: evt:0x%2X, malformed event of size %hhd", __func__,
hci_evt_code, hci_evt_len);
return;
}
btu_hcif_log_event_metrics(hci_evt_code, p);
switch (hci_evt_code) {
case HCI_INQUIRY_COMP_EVT:
btu_hcif_inquiry_comp_evt(p);
break;
case HCI_INQUIRY_RESULT_EVT:
btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_STANDARD);
break;
case HCI_INQUIRY_RSSI_RESULT_EVT:
btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_WITH_RSSI);
break;
case HCI_EXTENDED_INQUIRY_RESULT_EVT:
btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_EXTENDED);
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;
case HCI_ENCRYPTION_KEY_REFRESH_COMP_EVT:
btu_hcif_encryption_key_refresh_cmpl_evt(p);
break;
case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
btu_hcif_read_rmt_ext_features_comp_evt(p, hci_evt_len);
break;
case HCI_COMMAND_COMPLETE_EVT:
LOG_ERROR(
"%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(
"%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_MODE_CHANGE_EVT:
btu_hcif_mode_change_evt(p);
break;
case HCI_PIN_CODE_REQUEST_EVT:
break;
case HCI_LINK_KEY_REQUEST_EVT:
btm_sec_link_key_request(p);
break;
case HCI_LINK_KEY_NOTIFICATION_EVT:
btu_hcif_link_key_notification_evt(p);
break;
case HCI_READ_CLOCK_OFF_COMP_EVT:
btu_hcif_read_clock_off_comp_evt(p);
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;
case HCI_SNIFF_SUB_RATE_EVT:
btm_pm_proc_ssr_evt(p, hci_evt_len);
break;
case HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT:
btm_sec_rmt_host_support_feat_evt(p);
break;
case HCI_IO_CAPABILITY_REQUEST_EVT:
btu_hcif_io_cap_request_evt(p);
break;
case HCI_IO_CAPABILITY_RESPONSE_EVT:
break;
case HCI_USER_CONFIRMATION_REQUEST_EVT:
btm_proc_sp_req_evt(BTM_SP_CFM_REQ_EVT, p);
break;
case HCI_USER_PASSKEY_REQUEST_EVT:
btm_proc_sp_req_evt(BTM_SP_KEY_REQ_EVT, p);
break;
case HCI_REMOTE_OOB_DATA_REQUEST_EVT:
break;
case HCI_SIMPLE_PAIRING_COMPLETE_EVT:
break;
case HCI_USER_PASSKEY_NOTIFY_EVT:
btm_proc_sp_req_evt(BTM_SP_KEY_NOTIF_EVT, p);
case HCI_BLE_EVENT: {
STREAM_TO_UINT8(ble_sub_code, p);
uint8_t ble_evt_len = hci_evt_len - 1;
switch (ble_sub_code) {
case HCI_BLE_ADV_PKT_RPT_EVT: /* result of inquiry */
btm_ble_process_adv_pkt(ble_evt_len, p);
break;
case HCI_BLE_LL_CONN_PARAM_UPD_EVT:
btu_ble_ll_conn_param_upd_evt(p, ble_evt_len);
break;
case HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT:
btm_ble_read_remote_features_complete(p, ble_evt_len);
break;
case HCI_BLE_LTK_REQ_EVT: /* received only at peripheral device */
break;
case HCI_BLE_RC_PARAM_REQ_EVT:
btu_ble_rc_param_req_evt(p, ble_evt_len);
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
break;
case HCI_BLE_DATA_LENGTH_CHANGE_EVT:
btu_ble_data_length_change_evt(p, hci_evt_len);
break;
case HCI_BLE_PHY_UPDATE_COMPLETE_EVT:
btm_ble_process_phy_update_pkt(ble_evt_len, p);
break;
case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT:
btm_ble_process_ext_adv_pkt(hci_evt_len, p);
break;
case HCI_LE_ADVERTISING_SET_TERMINATED_EVT:
btm_le_on_advertising_set_terminated(p, hci_evt_len);
break;
case HCI_BLE_REQ_PEER_SCA_CPL_EVT:
btm_acl_process_sca_cmpl_pkt(ble_evt_len, p);
break;
case HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT:
btm_ble_process_periodic_adv_sync_est_evt(
ble_evt_len, const_cast<const uint8_t*>(p));
break;
case HCI_BLE_PERIODIC_ADV_REPORT_EVT:
btm_ble_process_periodic_adv_pkt(ble_evt_len,
const_cast<const uint8_t*>(p));
break;
case HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT:
btm_ble_process_periodic_adv_sync_lost_evt(ble_evt_len, p);
break;
case HCI_BLE_CIS_EST_EVT:
case HCI_BLE_CREATE_BIG_CPL_EVT:
case HCI_BLE_TERM_BIG_CPL_EVT:
case HCI_BLE_CIS_REQ_EVT:
case HCI_BLE_BIG_SYNC_EST_EVT:
case HCI_BLE_BIG_SYNC_LOST_EVT:
IsoManager::GetInstance()->HandleHciEvent(ble_sub_code, p,
ble_evt_len);
break;
case HCI_LE_PERIODIC_ADV_SYNC_TRANSFERE_RECEIVED_EVT:
btm_ble_periodic_adv_sync_tx_rcvd(p, hci_evt_len);
break;
case HCI_LE_BIGINFO_ADVERTISING_REPORT_EVT:
btm_ble_biginfo_adv_report_rcvd(p, hci_evt_len);
break;
// Events are now captured by gd/hci/le_acl_connection_interface.h
case HCI_BLE_CONN_COMPLETE_EVT: // SubeventCode::CONNECTION_COMPLETE
case HCI_BLE_ENHANCED_CONN_COMPLETE_EVT: // SubeventCode::ENHANCED_CONNECTION_COMPLETE
case HCI_LE_SUBRATE_CHANGE_EVT: // SubeventCode::LE_SUBRATE_CHANGE
default:
LOG_ERROR(
"Unexpectedly received LE sub_event_code:0x%02x that should not "
"be handled here",
ble_sub_code);
break;
btm_vendor_specific_evt(const_cast<const uint8_t*>(p), hci_evt_len);
// Events now captured by gd::hci_layer module
case HCI_NUM_COMPL_DATA_PKTS_EVT: // EventCode::NUMBER_OF_COMPLETED_PACKETS
case HCI_CONNECTION_COMP_EVT: // EventCode::CONNECTION_COMPLETE
case HCI_CONNECTION_REQUEST_EVT: // EventCode::CONNECTION_REQUEST
case HCI_READ_RMT_FEATURES_COMP_EVT: // EventCode::READ_REMOTE_SUPPORTED_FEATURES_COMPLETE
case HCI_READ_RMT_VERSION_COMP_EVT: // EventCode::READ_REMOTE_VERSION_INFORMATION_COMPLETE
case HCI_ROLE_CHANGE_EVT: // EventCode::ROLE_CHANGE
case HCI_DISCONNECTION_COMP_EVT: // EventCode::DISCONNECTION_COMPLETE
default:
LOG_ERROR(
"Unexpectedly received event_code:0x%02x that should not be "
"handled here",
hci_evt_code);
break;
}
static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
static uint16_t kUnknownBleEvt = android::bluetooth::hci::BLE_EVT_UNKNOWN;
uint16_t hci_event = android::bluetooth::hci::EVT_COMMAND_STATUS;
if (!is_cmd_status) {
hci_event = android::bluetooth::hci::EVT_UNKNOWN;
cmd_status = android::bluetooth::hci::STATUS_UNKNOWN;
}
RawAddress bd_addr;
uint16_t handle;
uint8_t reason;
switch (opcode) {
case HCI_CREATE_CONNECTION:
case HCI_CREATE_CONNECTION_CANCEL:
STREAM_TO_BDADDR(bd_addr, p_cmd);
log_link_layer_connection_event(
&bd_addr, bluetooth::common::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING,
android::bluetooth::LINK_TYPE_ACL, opcode, hci_event, kUnknownBleEvt,
cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
break;
case HCI_DISCONNECT:
STREAM_TO_UINT16(handle, p_cmd);
STREAM_TO_UINT8(reason, p_cmd);
log_link_layer_connection_event(
nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
kUnknownBleEvt, cmd_status, reason);
break;
case HCI_SETUP_ESCO_CONNECTION:
case HCI_ENH_SETUP_ESCO_CONNECTION:
STREAM_TO_UINT16(handle, p_cmd);
log_link_layer_connection_event(
nullptr, handle, android::bluetooth::DIRECTION_OUTGOING,
android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
break;
case HCI_ACCEPT_CONNECTION_REQUEST:
case HCI_ACCEPT_ESCO_CONNECTION:
case HCI_ENH_ACCEPT_ESCO_CONNECTION:
STREAM_TO_BDADDR(bd_addr, p_cmd);
log_link_layer_connection_event(
&bd_addr, bluetooth::common::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_INCOMING,
android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
break;
case HCI_REJECT_CONNECTION_REQUEST:
case HCI_REJECT_ESCO_CONNECTION:
STREAM_TO_BDADDR(bd_addr, p_cmd);
STREAM_TO_UINT8(reason, p_cmd);
log_link_layer_connection_event(
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
&bd_addr, bluetooth::common::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_INCOMING,
android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
kUnknownBleEvt, cmd_status, reason);
break;
// BLE Commands
case HCI_BLE_CREATE_LL_CONN: {
p_cmd += 2; // Skip LE_Scan_Interval
p_cmd += 2; // Skip LE_Scan_Window;
uint8_t initiator_filter_policy;
STREAM_TO_UINT8(initiator_filter_policy, p_cmd);
uint8_t peer_address_type;
STREAM_TO_UINT8(peer_address_type, p_cmd);
STREAM_TO_BDADDR(bd_addr, p_cmd);
// Peer address should not be used if initiator filter policy is not 0x00
const RawAddress* bd_addr_p = nullptr;
if (initiator_filter_policy == 0x00) {
bd_addr_p = &bd_addr;
if (peer_address_type == BLE_ADDR_PUBLIC_ID ||
peer_address_type == BLE_ADDR_RANDOM_ID) {
// if identity address is not matched, this address is invalid
if (!btm_identity_addr_to_random_pseudo(&bd_addr, &peer_address_type,
false)) {
bd_addr_p = nullptr;
}
}
}
if (initiator_filter_policy == 0x00 ||
(cmd_status != HCI_SUCCESS && !is_cmd_status)) {
// Selectively log to avoid log spam due to acceptlist connections:
// - When doing non-acceptlist connection
// - When there is an error in command status
log_link_layer_connection_event(
bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING,
android::bluetooth::LINK_TYPE_ACL, opcode, hci_event,
kUnknownBleEvt, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN);
}
break;
}
case HCI_LE_EXTENDED_CREATE_CONNECTION: {
uint8_t initiator_filter_policy;
STREAM_TO_UINT8(initiator_filter_policy, p_cmd);
p_cmd += 1; // Skip Own_Address_Type
uint8_t peer_addr_type;
STREAM_TO_UINT8(peer_addr_type, p_cmd);
STREAM_TO_BDADDR(bd_addr, p_cmd);
// Peer address should not be used if initiator filter policy is not 0x00
const RawAddress* bd_addr_p = nullptr;
if (initiator_filter_policy == 0x00) {
bd_addr_p = &bd_addr;
// if identity address is not matched, this should be a static address
btm_identity_addr_to_random_pseudo(&bd_addr, &peer_addr_type, false);
}
if (initiator_filter_policy == 0x00 ||
(cmd_status != HCI_SUCCESS && !is_cmd_status)) {
// Selectively log to avoid log spam due to acceptlist connections:
// - When doing non-acceptlist connection
// - When there is an error in command status
log_link_layer_connection_event(
bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING,
android::bluetooth::LINK_TYPE_ACL, opcode, hci_event,
kUnknownBleEvt, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN);
}
break;
}
case HCI_BLE_CREATE_CONN_CANCEL:
if (cmd_status != HCI_SUCCESS && !is_cmd_status) {
// Only log errors to prevent log spam due to acceptlist connections
log_link_layer_connection_event(
nullptr, bluetooth::common::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING,
android::bluetooth::LINK_TYPE_ACL, opcode, hci_event,
kUnknownBleEvt, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN);
}
break;
log_classic_pairing_event(RawAddress::kEmpty,
bluetooth::common::kUnknownConnectionHandle,
opcode, hci_event, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN, 0);
break;
case HCI_WRITE_SIMPLE_PAIRING_MODE: {
uint8_t simple_pairing_mode;
STREAM_TO_UINT8(simple_pairing_mode, p_cmd);
log_classic_pairing_event(
RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle,
opcode, hci_event, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN, simple_pairing_mode);
break;
}
case HCI_WRITE_SECURE_CONNS_SUPPORT: {
uint8_t secure_conn_host_support;
STREAM_TO_UINT8(secure_conn_host_support, p_cmd);
log_classic_pairing_event(
RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle,
opcode, hci_event, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN, secure_conn_host_support);
break;
}
case HCI_AUTHENTICATION_REQUESTED:
STREAM_TO_UINT16(handle, p_cmd);
log_classic_pairing_event(RawAddress::kEmpty, handle, opcode, hci_event,
cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN, 0);
break;
case HCI_SET_CONN_ENCRYPTION: {
STREAM_TO_UINT16(handle, p_cmd);
uint8_t encryption_enable;
STREAM_TO_UINT8(encryption_enable, p_cmd);
log_classic_pairing_event(
RawAddress::kEmpty, handle, opcode, hci_event, cmd_status,
android::bluetooth::hci::STATUS_UNKNOWN, encryption_enable);
break;
}
case HCI_DELETE_STORED_LINK_KEY: {
uint8_t delete_all_flag;
STREAM_TO_BDADDR(bd_addr, p_cmd);
STREAM_TO_UINT8(delete_all_flag, p_cmd);
log_classic_pairing_event(
bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode,
hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN,
delete_all_flag);
break;
}
case HCI_RMT_NAME_REQUEST:
case HCI_RMT_NAME_REQUEST_CANCEL:
case HCI_LINK_KEY_REQUEST_REPLY:
case HCI_LINK_KEY_REQUEST_NEG_REPLY:
case HCI_IO_CAPABILITY_REQUEST_REPLY:
case HCI_USER_CONF_REQUEST_REPLY:
case HCI_USER_CONF_VALUE_NEG_REPLY:
case HCI_USER_PASSKEY_REQ_REPLY:
case HCI_USER_PASSKEY_REQ_NEG_REPLY:
case HCI_REM_OOB_DATA_REQ_REPLY:
case HCI_REM_OOB_DATA_REQ_NEG_REPLY:
STREAM_TO_BDADDR(bd_addr, p_cmd);
log_classic_pairing_event(
bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode,
hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, 0);
break;
case HCI_IO_CAP_REQ_NEG_REPLY:
STREAM_TO_BDADDR(bd_addr, p_cmd);
STREAM_TO_UINT8(reason, p_cmd);
log_classic_pairing_event(bd_addr,
bluetooth::common::kUnknownConnectionHandle,
opcode, hci_event, cmd_status, reason, 0);
/*******************************************************************************
* Description This function is called to send commands to the Host
* Controller.
*
* Returns void
*
******************************************************************************/
void btu_hcif_send_cmd(UNUSED_ATTR uint8_t controller_id, const BT_HDR* p_buf) {
if (!p_buf) return;
uint16_t opcode;
const uint8_t* stream = p_buf->data + p_buf->offset;
void* vsc_callback = NULL;
STREAM_TO_UINT16(opcode, stream);
// Eww...horrible hackery here
/* If command was a VSC, then extract command_complete callback */
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);
bluetooth::shim::hci_layer_get_interface()->transmit_command(
p_buf, btu_hcif_command_complete_evt, btu_hcif_command_status_evt,
}
using hci_cmd_cb = base::OnceCallback<void(
uint8_t* /* return_parameters */, uint16_t /* return_parameters_length*/)>;
struct cmd_with_cb_data {
hci_cmd_cb cb;
base::Location posted_from;
};
void cmd_with_cb_data_init(cmd_with_cb_data* cb_wrapper) {
new (&cb_wrapper->cb) hci_cmd_cb;
new (&cb_wrapper->posted_from) Location;
}
void cmd_with_cb_data_cleanup(cmd_with_cb_data* cb_wrapper) {
cb_wrapper->cb.~hci_cmd_cb();
cb_wrapper->posted_from.~Location();
}
/**
* Log command complete events that is not handled individually in this file
* @param opcode opcode of the command
* @param p_return_params pointer to returned parameter after parameter length
* field
*/
static void btu_hcif_log_command_complete_metrics(
uint16_t opcode, const uint8_t* p_return_params) {
uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
uint16_t hci_event = android::bluetooth::hci::EVT_COMMAND_COMPLETE;
RawAddress bd_addr = RawAddress::kEmpty;
switch (opcode) {
case HCI_DELETE_STORED_LINK_KEY:
case HCI_READ_LOCAL_OOB_DATA:
case HCI_WRITE_SIMPLE_PAIRING_MODE:
case HCI_WRITE_SECURE_CONNS_SUPPORT:
STREAM_TO_UINT8(status, p_return_params);
log_classic_pairing_event(RawAddress::kEmpty,
bluetooth::common::kUnknownConnectionHandle,
opcode, hci_event, status, reason, 0);
case HCI_READ_ENCR_KEY_SIZE: {
uint16_t handle;
uint8_t key_size;
STREAM_TO_UINT8(status, p_return_params);
STREAM_TO_UINT16(handle, p_return_params);
STREAM_TO_UINT8(key_size, p_return_params);
log_classic_pairing_event(RawAddress::kEmpty, handle, opcode, hci_event,
status, reason, key_size);
case HCI_LINK_KEY_REQUEST_REPLY:
case HCI_LINK_KEY_REQUEST_NEG_REPLY:
case HCI_IO_CAPABILITY_REQUEST_REPLY:
case HCI_IO_CAP_REQ_NEG_REPLY:
case HCI_USER_CONF_REQUEST_REPLY:
case HCI_USER_CONF_VALUE_NEG_REPLY:
case HCI_USER_PASSKEY_REQ_REPLY:
case HCI_USER_PASSKEY_REQ_NEG_REPLY:
case HCI_REM_OOB_DATA_REQ_REPLY:
case HCI_REM_OOB_DATA_REQ_NEG_REPLY:
STREAM_TO_UINT8(status, p_return_params);
STREAM_TO_BDADDR(bd_addr, p_return_params);
log_classic_pairing_event(bd_addr,
bluetooth::common::kUnknownConnectionHandle,
opcode, hci_event, status, reason, 0);
static void btu_hcif_command_complete_evt_with_cb_on_task(BT_HDR* event,
void* context) {
// 2 for event header: event code (1) + parameter length (1)
// 1 for num_hci_pkt command credit
uint8_t* stream = event->data + event->offset + 3;
STREAM_TO_UINT16(opcode, stream);
btu_hcif_log_command_complete_metrics(opcode, stream);
cmd_with_cb_data* cb_wrapper = (cmd_with_cb_data*)context;
HCI_TRACE_DEBUG("command complete for: %s",
cb_wrapper->posted_from.ToString().c_str());
// 2 for event header: event code (1) + parameter length (1)
// 3 for command complete header: num_hci_pkt (1) + opcode (2)
uint16_t param_len = static_cast<uint16_t>(event->len - 5);
std::move(cb_wrapper->cb).Run(stream, param_len);
cmd_with_cb_data_cleanup(cb_wrapper);
osi_free(cb_wrapper);
static void btu_hcif_command_complete_evt_with_cb(BT_HDR* response,
void* context) {
do_in_main_thread(FROM_HERE,
base::Bind(btu_hcif_command_complete_evt_with_cb_on_task,
response, context));
static void btu_hcif_command_status_evt_with_cb_on_task(uint8_t status,
BT_HDR* event,
void* context) {
uint8_t* stream = event->data + event->offset;
STREAM_TO_UINT16(opcode, stream);
// stream + 1 to skip parameter length field
// No need to check length since stream is written by us
btu_hcif_log_command_metrics(opcode, stream + 1, status, true);
// report command status error
cmd_with_cb_data* cb_wrapper = (cmd_with_cb_data*)context;
HCI_TRACE_DEBUG("command status for: %s",
cb_wrapper->posted_from.ToString().c_str());
std::move(cb_wrapper->cb).Run(&status, sizeof(uint16_t));
cmd_with_cb_data_cleanup(cb_wrapper);
osi_free(cb_wrapper);
static void btu_hcif_command_status_evt_with_cb(uint8_t status, BT_HDR* command,
void* context) {
// Command is pending, we report only error.
if (!status) {
osi_free(command);
return;
}
FROM_HERE, base::Bind(btu_hcif_command_status_evt_with_cb_on_task, status,
command, context));
}
/* This function is called to send commands to the Host Controller. |cb| is
* called when command status event is called with error code, or when the
* command complete event is received. */
void btu_hcif_send_cmd_with_cb(const base::Location& posted_from,
uint16_t opcode, uint8_t* params,
uint8_t params_len, hci_cmd_cb cb) {
BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
uint8_t* pp = (uint8_t*)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + params_len;
p->offset = 0;
UINT16_TO_STREAM(pp, opcode);
UINT8_TO_STREAM(pp, params_len);
if (params) {
memcpy(pp, params, params_len);
}
btu_hcif_log_command_metrics(opcode, pp,
android::bluetooth::hci::STATUS_UNKNOWN, false);
cmd_with_cb_data* cb_wrapper =
(cmd_with_cb_data*)osi_malloc(sizeof(cmd_with_cb_data));
cmd_with_cb_data_init(cb_wrapper);
cb_wrapper->cb = std::move(cb);
bluetooth::shim::hci_layer_get_interface()->transmit_command(
btu_hcif_command_status_evt_with_cb, (void*)cb_wrapper);
/*******************************************************************************
*
* Function btu_hcif_inquiry_comp_evt
*
* Description Process event HCI_INQUIRY_COMP_EVT
*
* Returns void
*
******************************************************************************/
static void btu_hcif_inquiry_comp_evt(uint8_t* p) {
uint8_t status;
/* Tell inquiry processing that we are done */
btm_process_inq_complete(to_hci_status_code(status), BTM_BR_INQUIRY_MASK);
}
/*******************************************************************************
*
* Function btu_hcif_authentication_comp_evt
*
* Description Process event HCI_AUTHENTICATION_COMP_EVT
*
* Returns void
*
******************************************************************************/
static void btu_hcif_authentication_comp_evt(uint8_t* p) {
uint8_t status;
uint16_t handle;
STREAM_TO_UINT8(status, p);
STREAM_TO_UINT16(handle, p);
btm_sec_auth_complete(handle, static_cast<tHCI_STATUS>(status));
}
/*******************************************************************************
*
* Function btu_hcif_rmt_name_request_comp_evt
*
* Description Process event HCI_RMT_NAME_REQUEST_COMP_EVT
*
* Returns void
*
******************************************************************************/
static void btu_hcif_rmt_name_request_comp_evt(const uint8_t* p,
uint16_t evt_len) {
btm_process_remote_name(&bd_addr, p, evt_len, to_hci_status_code(status));
btm_sec_rmt_name_request_complete(&bd_addr, p, to_hci_status_code(status));
}
constexpr uint8_t MIN_KEY_SIZE = 7;
static void read_encryption_key_size_complete_after_encryption_change(uint8_t status, uint16_t handle,
uint8_t key_size) {
Jakub Pawlowski
committed
if (status == HCI_ERR_INSUFFCIENT_SECURITY) {
/* If remote device stop the encryption before we call "Read Encryption Key
* Size", we might receive Insufficient Security, which means that link is
* no longer encrypted. */
LOG(INFO) << __func__ << ": encryption stopped on link: " << loghex(handle);
return;
}
if (status != HCI_SUCCESS) {
LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
acl_disconnect_from_handle(handle, HCI_ERR_PEER_USER,
"stack::btu::btu_hcif::read_encryption_key_size_"
"complete_after_encryption_change Bad key size");
return;
}
if (key_size < MIN_KEY_SIZE) {
LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
<< " key_size: " << +key_size;
acl_disconnect_from_handle(
handle, HCI_ERR_HOST_REJECT_SECURITY,
"stack::btu::btu_hcif::read_encryption_key_size_complete_after_"
"encryption_change Key Too Short");
if (btm_sec_is_session_key_size_downgrade(handle, key_size)) {
LOG_ERROR(
"encryption key size lower than cached value, disconnecting. "
"handle: 0x%x attempted key size: %d",
handle, key_size);
acl_disconnect_from_handle(
handle, HCI_ERR_HOST_REJECT_SECURITY,
"stack::btu::btu_hcif::read_encryption_key_size_complete_after_"
"encryption_change Key Size Downgrade");
return;
}
btm_sec_update_session_key_size(handle, key_size);
// good key size - succeed
btm_acl_encrypt_change(handle, static_cast<tHCI_STATUS>(status),
1 /* enable */);
btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status),
1 /* enable */);
/*******************************************************************************
*
* Function btu_hcif_encryption_change_evt
*
* Description Process event HCI_ENCRYPTION_CHANGE_EVT
*
* Returns void
*
******************************************************************************/
static void btu_hcif_encryption_change_evt(uint8_t* p) {
uint8_t status;
uint16_t handle;
uint8_t encr_enable;
STREAM_TO_UINT8(status, p);
STREAM_TO_UINT16(handle, p);
STREAM_TO_UINT8(encr_enable, p);
if (status != HCI_SUCCESS || encr_enable == 0 ||
BTM_IsBleConnection(handle) ||
(bluetooth::common::init_flags::read_encryption_key_size_is_enabled() &&
!controller_get_interface()->supports_read_encryption_key_size()) ||
// Skip encryption key size check when using set_min_encryption_key_size
(bluetooth::common::init_flags::set_min_encryption_is_enabled() &&
controller_get_interface()->supports_set_min_encryption_key_size())) {
if (status == HCI_ERR_CONNECTION_TOUT) {
smp_cancel_start_encryption_attempt();
return;
}
btm_acl_encrypt_change(handle, static_cast<tHCI_STATUS>(status),
encr_enable);
btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status),
encr_enable);
btsnd_hcic_read_encryption_key_size(
handle,
base::Bind(&read_encryption_key_size_complete_after_encryption_change));
}
/*******************************************************************************
*
* Function btu_hcif_read_rmt_ext_features_comp_evt
*
* Description Process event HCI_READ_RMT_EXT_FEATURES_COMP_EVT
*
* Returns void
*
******************************************************************************/
static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p,
uint8_t evt_len) {
uint8_t* p_cur = p;
uint8_t status;
uint16_t handle;
STREAM_TO_UINT8(status, p_cur);
if (status == HCI_SUCCESS)
btm_read_remote_ext_features_complete_raw(p, evt_len);