blob: 9aeb0cd6b5ecaeea4dc9f273335505147029112e [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "util.h"
#include <zircon/assert.h>
#include "garnet/drivers/bluetooth/lib/common/log.h"
namespace btlib {
using common::DeviceAddress;
namespace hci {
std::string HCIVersionToString(HCIVersion version) {
switch (version) {
case HCIVersion::k1_0b:
return "1.0b";
case HCIVersion::k1_1:
return "1.1";
case HCIVersion::k1_2:
return "1.2";
case HCIVersion::k2_0_EDR:
return "2.0 + EDR";
case HCIVersion::k2_1_EDR:
return "2.1 + EDR";
case HCIVersion::k3_0_HS:
return "3.0 + HS";
case HCIVersion::k4_0:
return "4.0";
case HCIVersion::k4_1:
return "4.1";
case HCIVersion::k4_2:
return "4.2";
case HCIVersion::k5_0:
return "5.0";
default:
break;
}
return "(unknown)";
}
// clang-format off
std::string StatusCodeToString(StatusCode code) {
switch (code) {
case kSuccess: return "success";
case kUnknownCommand: return "unknown command";
case kUnknownConnectionId: return "unknown connection ID";
case kHardwareFailure: return "hardware failure";
case kPageTimeout: return "page timeout";
case kAuthenticationFailure: return "authentication failure";
case kPinOrKeyMissing: return "pin or key missing";
case kMemoryCapacityExceeded: return "memory capacity exceeded";
case kConnectionTimeout: return "connection timeout";
case kConnectionLimitExceeded: return "connection limit exceeded";
case kSynchronousConnectionLimitExceeded: return "synchronous connection limit exceeded";
case kConnectionAlreadyExists: return "connection already exists";
case kCommandDisallowed: return "command disallowed";
case kConnectionRejectedLimitedResources: return "connection rejected: limited resources";
case kConnectionRejectedSecurity: return "connection rejected: security";
case kConnectionRejectedBadBdAddr: return "connection rejected: bad BD_ADDR";
case kConnectionAcceptTimeoutExceeded: return "connection accept timeout exceeded";
case kUnsupportedFeatureOrParameter: return "unsupported feature or parameter";
case kInvalidHCICommandParameters: return "invalid HCI command parameters";
case kRemoteUserTerminatedConnection: return "remote user terminated connection";
case kRemoteDeviceTerminatedConnectionLowResources: return "remote device terminated connection: low resources";
case kRemoteDeviceTerminatedConnectionPowerOff: return "remote device rerminated connection: power off";
case kConnectionTerminatedByLocalHost: return "connection terminated by local host";
case kRepeatedAttempts: return "repeated attempts";
case kPairingNotAllowed: return "pairing not allowed";
case kUnknownLMPPDU: return "unknown LMP PDU";
case kUnsupportedRemoteFeature: return "unsupported remote feature";
case kSCOOffsetRejected: return "SCO offset rejected";
case kSCOIntervalRejected: return "SCO interval rejected";
case kSCOAirModeRejected: return "SCO air mode rejected";
case kInvalidLMPOrLLParameters: return "invalid LMP or LL parameters";
case kUnspecifiedError: return "unspecified error";
case kUnsupportedLMPOrLLParameterValue: return "unsupported LMP or LL parameter value";
case kRoleChangeNotAllowed: return "role change not allowed";
case kLMPOrLLResponseTimeout: return "LMP or LL response timeout";
case kLMPErrorTransactionCollision: return "LMP error transaction collision";
case kLMPPDUNotAllowed: return "LMP PDU not allowed";
case kEncryptionModeNotAcceptable: return "encryption mode not acceptable";
case kLinkKeyCannotBeChanged: return "link key cannot be changed";
case kRequestedQoSNotSupported: return "requested QoS not supported";
case kInstantPassed: return "instant passed";
case kPairingWithUnitKeyNotSupported: return "pairing with unit key not supported";
case kDifferentTransactionCollision: return "different transaction collision";
case kQoSUnacceptableParameter: return "QoS unacceptable parameter";
case kQoSRejected: return "QoS rejected";
case kChannelClassificationNotSupported: return "channel classification not supported";
case kInsufficientSecurity: return "insufficient security";
case kParameterOutOfMandatoryRange: return "parameter out of mandatory range";
case kRoleSwitchPending: return "role switch pending";
case kReservedSlotViolation: return "reserved slot violation";
case kRoleSwitchFailed: return "role switch failed";
case kExtendedInquiryResponseTooLarge: return "extended inquiry response too large";
case kSecureSimplePairingNotSupportedByHost: return "secure simple pairing not supported by host";
case kHostBusyPairing: return "host busy pairing";
case kConnectionRejectedNoSuitableChannelFound: return "connection rejected: no suitable channel found";
case kControllerBusy: return "controller busy";
case kUnacceptableConnectionParameters: return "unacceptable connection parameters";
case kDirectedAdvertisingTimeout: return "directed advertising timeout";
case kConnectionTerminatedMICFailure: return "connection terminated: MIC failure";
case kConnectionFailedToBeEstablished: return "connection failed to be established";
case kMACConnectionFailed: return "MAC connection failed";
case kCoarseClockAdjustmentRejected: return "coarse clock adjustment rejected";
case kType0SubmapNotDefined: return "type 0 submap not defined";
case kUnknownAdvertisingIdentifier: return "unknown advertising identifier";
case kLimitReached: return "limit reached";
case kOperationCancelledByHost: return "operation cancelled by host";
default: break;
};
return "unknown status";
}
// clang-format on
bool DeviceAddressFromAdvReport(const LEAdvertisingReportData& report,
DeviceAddress* out_address,
bool* out_resolved) {
ZX_DEBUG_ASSERT(out_address);
ZX_DEBUG_ASSERT(out_resolved);
DeviceAddress::Type type;
switch (report.address_type) {
case LEAddressType::kPublicIdentity:
type = DeviceAddress::Type::kLEPublic;
*out_resolved = true;
break;
case LEAddressType::kPublic:
type = DeviceAddress::Type::kLEPublic;
*out_resolved = false;
break;
case LEAddressType::kRandomIdentity:
type = DeviceAddress::Type::kLERandom;
*out_resolved = true;
break;
case LEAddressType::kRandom:
type = DeviceAddress::Type::kLERandom;
*out_resolved = false;
break;
default:
bt_log(WARN, "hci", "invalid address type in advertising report: %#.2x",
static_cast<uint8_t>(report.address_type));
return false;
}
*out_address = DeviceAddress(type, report.address);
return true;
}
DeviceAddress::Type AddressTypeFromHCI(LEAddressType type) {
DeviceAddress::Type result;
switch (type) {
case LEAddressType::kPublic:
case LEAddressType::kPublicIdentity:
result = DeviceAddress::Type::kLEPublic;
break;
case LEAddressType::kRandom:
case LEAddressType::kRandomIdentity:
case LEAddressType::kRandomUnresolved:
result = DeviceAddress::Type::kLERandom;
break;
case LEAddressType::kAnonymous:
result = DeviceAddress::Type::kLEAnonymous;
break;
}
return result;
}
DeviceAddress::Type AddressTypeFromHCI(LEPeerAddressType type) {
DeviceAddress::Type result;
switch (type) {
case LEPeerAddressType::kPublic:
result = DeviceAddress::Type::kLEPublic;
break;
case LEPeerAddressType::kRandom:
result = DeviceAddress::Type::kLERandom;
break;
case LEPeerAddressType::kAnonymous:
result = DeviceAddress::Type::kLEAnonymous;
break;
}
return result;
}
LEAddressType AddressTypeToHCI(DeviceAddress::Type type) {
LEAddressType result = LEAddressType::kPublic;
switch (type) {
case DeviceAddress::Type::kLEPublic:
result = LEAddressType::kPublic;
break;
case DeviceAddress::Type::kLERandom:
result = LEAddressType::kRandom;
break;
case DeviceAddress::Type::kLEAnonymous:
result = LEAddressType::kAnonymous;
break;
default:
ZX_PANIC("invalid address type: %u", static_cast<unsigned int>(type));
break;
}
return result;
}
} // namespace hci
} // namespace btlib