/* * Copyright 2020 The Android Open Source Project * * 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. */ #pragma once #include "hci/address_with_type.h" #include "gd/common/init_flags.h" #include "gd/packet/raw_builder.h" #include "osi/include/allocator.h" #include "stack/include/bt_types.h" #include "stack/include/hci_error_code.h" #include "stack/include/hcidefs.h" #include "types/ble_address_with_type.h" #include "types/hci_role.h" namespace bluetooth { inline RawAddress ToRawAddress(const hci::Address& address) { RawAddress ret; ret.address[0] = address.address[5]; ret.address[1] = address.address[4]; ret.address[2] = address.address[3]; ret.address[3] = address.address[2]; ret.address[4] = address.address[1]; ret.address[5] = address.address[0]; return ret; } inline hci::Address ToGdAddress(const RawAddress& address) { hci::Address ret; ret.address[0] = address.address[5]; ret.address[1] = address.address[4]; ret.address[2] = address.address[3]; ret.address[3] = address.address[2]; ret.address[4] = address.address[1]; ret.address[5] = address.address[0]; return ret; } inline hci::AddressWithType ToAddressWithType( const RawAddress& legacy_address, const tBLE_ADDR_TYPE& legacy_type) { hci::Address address = ToGdAddress(legacy_address); hci::AddressType type; if (legacy_type == BLE_ADDR_PUBLIC) type = hci::AddressType::PUBLIC_DEVICE_ADDRESS; else if (legacy_type == BLE_ADDR_RANDOM) type = hci::AddressType::RANDOM_DEVICE_ADDRESS; else if (legacy_type == BLE_ADDR_PUBLIC_ID) type = hci::AddressType::PUBLIC_IDENTITY_ADDRESS; else if (legacy_type == BLE_ADDR_RANDOM_ID) type = hci::AddressType::RANDOM_IDENTITY_ADDRESS; else { LOG_ALWAYS_FATAL("Bad address type %02x", legacy_type); return hci::AddressWithType{address, hci::AddressType::PUBLIC_DEVICE_ADDRESS}; } return hci::AddressWithType{address, type}; } inline hci::AddressWithType ToAddressWithTypeFromLegacy( const tBLE_BD_ADDR& legacy_address_with_type) { return ToAddressWithType(legacy_address_with_type.bda, legacy_address_with_type.type); } inline tBLE_BD_ADDR ToLegacyAddressWithType( const hci::AddressWithType& address_with_type) { tBLE_BD_ADDR legacy_address_with_type; legacy_address_with_type.bda = ToRawAddress(address_with_type.GetAddress()); if (address_with_type.GetAddressType() == hci::AddressType::PUBLIC_DEVICE_ADDRESS) { legacy_address_with_type.type = BLE_ADDR_PUBLIC; } else if (address_with_type.GetAddressType() == hci::AddressType::RANDOM_DEVICE_ADDRESS) { legacy_address_with_type.type = BLE_ADDR_RANDOM; } else if (address_with_type.GetAddressType() == hci::AddressType::PUBLIC_IDENTITY_ADDRESS) { legacy_address_with_type.type = BLE_ADDR_PUBLIC_ID; } else if (address_with_type.GetAddressType() == hci::AddressType::RANDOM_IDENTITY_ADDRESS) { legacy_address_with_type.type = BLE_ADDR_RANDOM_ID; } else { LOG_ALWAYS_FATAL("%s Bad address type %02x", __func__, static_cast(address_with_type.GetAddressType())); legacy_address_with_type.type = BLE_ADDR_PUBLIC; } return legacy_address_with_type; } inline std::unique_ptr MakeUniquePacket( const uint8_t* data, size_t len, bool is_flushable) { bluetooth::packet::RawBuilder builder; std::vector bytes(data, data + len); auto payload = std::make_unique(); payload->AddOctets(bytes); payload->SetFlushable(is_flushable); return payload; } inline BT_HDR* MakeLegacyBtHdrPacket( std::unique_ptr> packet, const std::vector& preamble) { std::vector packet_vector(packet->begin(), packet->end()); BT_HDR* buffer = static_cast( osi_calloc(packet_vector.size() + preamble.size() + sizeof(BT_HDR))); std::copy(preamble.begin(), preamble.end(), buffer->data); std::copy(packet_vector.begin(), packet_vector.end(), buffer->data + preamble.size()); buffer->len = preamble.size() + packet_vector.size(); return buffer; } inline tHCI_ROLE ToLegacyRole(hci::Role role) { return to_hci_role(static_cast(role)); } inline hci::Role ToHciRole(const hci_role_t& role) { switch (role) { case HCI_ROLE_CENTRAL: return hci::Role::CENTRAL; case HCI_ROLE_PERIPHERAL: return hci::Role::PERIPHERAL; default: ASSERT_LOG(false, "Unable to determine legacy role:%u", role); } } inline tHCI_STATUS ToLegacyHciErrorCode(const hci::ErrorCode& reason) { switch (reason) { case hci::ErrorCode::SUCCESS: return HCI_SUCCESS; case hci::ErrorCode::UNKNOWN_HCI_COMMAND: return HCI_ERR_ILLEGAL_COMMAND; case hci::ErrorCode::UNKNOWN_CONNECTION: return HCI_ERR_NO_CONNECTION; case hci::ErrorCode::HARDWARE_FAILURE: return HCI_ERR_HW_FAILURE; case hci::ErrorCode::PAGE_TIMEOUT: return HCI_ERR_PAGE_TIMEOUT; case hci::ErrorCode::AUTHENTICATION_FAILURE: return HCI_ERR_AUTH_FAILURE; case hci::ErrorCode::PIN_OR_KEY_MISSING: return HCI_ERR_KEY_MISSING; case hci::ErrorCode::MEMORY_CAPACITY_EXCEEDED: return HCI_ERR_MEMORY_FULL; case hci::ErrorCode::CONNECTION_TIMEOUT: return HCI_ERR_CONNECTION_TOUT; case hci::ErrorCode::CONNECTION_LIMIT_EXCEEDED: return HCI_ERR_MAX_NUM_OF_CONNECTIONS; case hci::ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED: return HCI_ERR_MAX_NUM_OF_SCOS; case hci::ErrorCode::CONNECTION_ALREADY_EXISTS: return HCI_ERR_CONNECTION_EXISTS; case hci::ErrorCode::COMMAND_DISALLOWED: return HCI_ERR_COMMAND_DISALLOWED; case hci::ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES: return HCI_ERR_HOST_REJECT_RESOURCES; case hci::ErrorCode::CONNECTION_REJECTED_SECURITY_REASONS: return HCI_ERR_HOST_REJECT_SECURITY; case hci::ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR: return HCI_ERR_HOST_REJECT_DEVICE; case hci::ErrorCode::CONNECTION_ACCEPT_TIMEOUT: return HCI_ERR_HOST_TIMEOUT; case hci::ErrorCode::UNSUPORTED_FEATURE_OR_PARAMETER_VALUE: return static_cast( hci::ErrorCode::UNSUPORTED_FEATURE_OR_PARAMETER_VALUE); case hci::ErrorCode::INVALID_HCI_COMMAND_PARAMETERS: return HCI_ERR_ILLEGAL_PARAMETER_FMT; case hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION: return HCI_ERR_PEER_USER; case hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES: return static_cast( hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES); case hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF: return static_cast( hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF); case hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST: return HCI_ERR_CONN_CAUSE_LOCAL_HOST; case hci::ErrorCode::REPEATED_ATTEMPTS: return HCI_ERR_REPEATED_ATTEMPTS; case hci::ErrorCode::PAIRING_NOT_ALLOWED: return HCI_ERR_PAIRING_NOT_ALLOWED; case hci::ErrorCode::UNKNOWN_LMP_PDU: return static_cast(hci::ErrorCode::UNKNOWN_LMP_PDU); case hci::ErrorCode::UNSUPPORTED_REMOTE_OR_LMP_FEATURE: return HCI_ERR_UNSUPPORTED_REM_FEATURE; case hci::ErrorCode::SCO_OFFSET_REJECTED: return static_cast(hci::ErrorCode::SCO_OFFSET_REJECTED); case hci::ErrorCode::SCO_INTERVAL_REJECTED: return static_cast(hci::ErrorCode::SCO_INTERVAL_REJECTED); case hci::ErrorCode::SCO_AIR_MODE_REJECTED: return static_cast(hci::ErrorCode::SCO_AIR_MODE_REJECTED); case hci::ErrorCode::INVALID_LMP_OR_LL_PARAMETERS: return static_cast( hci::ErrorCode::INVALID_LMP_OR_LL_PARAMETERS); case hci::ErrorCode::UNSPECIFIED_ERROR: return HCI_ERR_UNSPECIFIED; case hci::ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER: return static_cast( hci::ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER); case hci::ErrorCode::ROLE_CHANGE_NOT_ALLOWED: return static_cast(hci::ErrorCode::ROLE_CHANGE_NOT_ALLOWED); case hci::ErrorCode::LINK_LAYER_COLLISION: return HCI_ERR_LMP_ERR_TRANS_COLLISION; case hci::ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE: return HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE; case hci::ErrorCode::ROLE_SWITCH_FAILED: return static_cast(hci::ErrorCode::ROLE_SWITCH_FAILED); case hci::ErrorCode::CONTROLLER_BUSY: return static_cast(hci::ErrorCode::CONTROLLER_BUSY); case hci::ErrorCode::CONNECTION_FAILED_ESTABLISHMENT: return static_cast( hci::ErrorCode::CONNECTION_FAILED_ESTABLISHMENT); case hci::ErrorCode::STATUS_UNKNOWN: return HCI_ERR_UNDEFINED; default: return static_cast(reason); } } inline tHCI_MODE ToLegacyHciMode(const hci::Mode& mode) { return static_cast(mode); } inline hci::DisconnectReason ToDisconnectReasonFromLegacy( const tHCI_STATUS& reason) { return static_cast(reason); } inline bool IsPacketFlushable(const BT_HDR* p_buf) { ASSERT(p_buf != nullptr); return ToPacketData(p_buf)->IsFlushable(); } namespace debug { inline void DumpBtHdr(const BT_HDR* p_buf, const char* token) { uint16_t len = p_buf->len; char buf[255]; const uint8_t* data = p_buf->data + p_buf->offset; int cnt = 0; while (len > 0) { memset(buf, 0, sizeof(buf)); char* pbuf = buf; pbuf += sprintf(pbuf, "len:%5u %5d: ", p_buf->len, cnt); for (int j = 0; j < 16; j++, --len, data++, cnt++) { if (len == 0) break; pbuf += sprintf(pbuf, "0x%02x ", *data); } LOG_DEBUG("%s %s", token, buf); } } } // namespace debug } // namespace bluetooth