You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
273 lines
10 KiB
273 lines
10 KiB
/*
|
|
* 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<uint8_t>(address_with_type.GetAddressType()));
|
|
legacy_address_with_type.type = BLE_ADDR_PUBLIC;
|
|
}
|
|
return legacy_address_with_type;
|
|
}
|
|
|
|
inline std::unique_ptr<bluetooth::packet::RawBuilder> MakeUniquePacket(
|
|
const uint8_t* data, size_t len, bool is_flushable) {
|
|
bluetooth::packet::RawBuilder builder;
|
|
std::vector<uint8_t> bytes(data, data + len);
|
|
auto payload = std::make_unique<bluetooth::packet::RawBuilder>();
|
|
payload->AddOctets(bytes);
|
|
payload->SetFlushable(is_flushable);
|
|
return payload;
|
|
}
|
|
|
|
inline BT_HDR* MakeLegacyBtHdrPacket(
|
|
std::unique_ptr<bluetooth::hci::PacketView<bluetooth::hci::kLittleEndian>>
|
|
packet,
|
|
const std::vector<uint8_t>& preamble) {
|
|
std::vector<uint8_t> packet_vector(packet->begin(), packet->end());
|
|
BT_HDR* buffer = static_cast<BT_HDR*>(
|
|
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<uint8_t>(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<tHCI_STATUS>(
|
|
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<tHCI_STATUS>(
|
|
hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES);
|
|
case hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF:
|
|
return static_cast<tHCI_STATUS>(
|
|
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<tHCI_STATUS>(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<tHCI_STATUS>(hci::ErrorCode::SCO_OFFSET_REJECTED);
|
|
case hci::ErrorCode::SCO_INTERVAL_REJECTED:
|
|
return static_cast<tHCI_STATUS>(hci::ErrorCode::SCO_INTERVAL_REJECTED);
|
|
case hci::ErrorCode::SCO_AIR_MODE_REJECTED:
|
|
return static_cast<tHCI_STATUS>(hci::ErrorCode::SCO_AIR_MODE_REJECTED);
|
|
case hci::ErrorCode::INVALID_LMP_OR_LL_PARAMETERS:
|
|
return static_cast<tHCI_STATUS>(
|
|
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<tHCI_STATUS>(
|
|
hci::ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER);
|
|
case hci::ErrorCode::ROLE_CHANGE_NOT_ALLOWED:
|
|
return static_cast<tHCI_STATUS>(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<tHCI_STATUS>(hci::ErrorCode::ROLE_SWITCH_FAILED);
|
|
case hci::ErrorCode::CONTROLLER_BUSY:
|
|
return static_cast<tHCI_STATUS>(hci::ErrorCode::CONTROLLER_BUSY);
|
|
case hci::ErrorCode::CONNECTION_FAILED_ESTABLISHMENT:
|
|
return static_cast<tHCI_STATUS>(
|
|
hci::ErrorCode::CONNECTION_FAILED_ESTABLISHMENT);
|
|
case hci::ErrorCode::STATUS_UNKNOWN:
|
|
return HCI_ERR_UNDEFINED;
|
|
default:
|
|
return static_cast<tHCI_REASON>(reason);
|
|
}
|
|
}
|
|
|
|
inline tHCI_MODE ToLegacyHciMode(const hci::Mode& mode) {
|
|
return static_cast<tHCI_MODE>(mode);
|
|
}
|
|
|
|
inline hci::DisconnectReason ToDisconnectReasonFromLegacy(
|
|
const tHCI_STATUS& reason) {
|
|
return static_cast<hci::DisconnectReason>(reason);
|
|
}
|
|
|
|
inline bool IsPacketFlushable(const BT_HDR* p_buf) {
|
|
ASSERT(p_buf != nullptr);
|
|
return ToPacketData<const HciDataPreamble>(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
|