• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
16 
17 #include <endian.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
20 
21 #pragma clang diagnostic ignored "-Wswitch-enum"
22 
23 namespace bt::hci_spec {
24 
HCIVersionToString(pw::bluetooth::emboss::CoreSpecificationVersion version)25 std::string HCIVersionToString(
26     pw::bluetooth::emboss::CoreSpecificationVersion version) {
27   switch (version) {
28     case pw::bluetooth::emboss::CoreSpecificationVersion::V1_0B:
29       return "1.0b";
30     case pw::bluetooth::emboss::CoreSpecificationVersion::V1_1:
31       return "1.1";
32     case pw::bluetooth::emboss::CoreSpecificationVersion::V1_2:
33       return "1.2";
34     case pw::bluetooth::emboss::CoreSpecificationVersion::V2_0_EDR:
35       return "2.0 + EDR";
36     case pw::bluetooth::emboss::CoreSpecificationVersion::V2_1_EDR:
37       return "2.1 + EDR";
38     case pw::bluetooth::emboss::CoreSpecificationVersion::V3_0_HS:
39       return "3.0 + HS";
40     case pw::bluetooth::emboss::CoreSpecificationVersion::V4_0:
41       return "4.0";
42     case pw::bluetooth::emboss::CoreSpecificationVersion::V4_1:
43       return "4.1";
44     case pw::bluetooth::emboss::CoreSpecificationVersion::V4_2:
45       return "4.2";
46     case pw::bluetooth::emboss::CoreSpecificationVersion::V5_0:
47       return "5.0";
48     case pw::bluetooth::emboss::CoreSpecificationVersion::V5_1:
49       return "5.1";
50     case pw::bluetooth::emboss::CoreSpecificationVersion::V5_2:
51       return "5.2";
52     case pw::bluetooth::emboss::CoreSpecificationVersion::V5_3:
53       return "5.3";
54     case pw::bluetooth::emboss::CoreSpecificationVersion::V5_4:
55       return "5.4";
56     default:
57       break;
58   }
59   return "(unknown)";
60 }
61 
62 // clang-format off
StatusCodeToString(pw::bluetooth::emboss::StatusCode code)63 std::string StatusCodeToString(pw::bluetooth::emboss::StatusCode code) {
64   switch (code) {
65     case pw::bluetooth::emboss::StatusCode::SUCCESS: return "success";
66     case pw::bluetooth::emboss::StatusCode::UNKNOWN_COMMAND: return "unknown command";
67     case pw::bluetooth::emboss::StatusCode::UNKNOWN_CONNECTION_ID: return "unknown connection ID";
68     case pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE: return "hardware failure";
69     case pw::bluetooth::emboss::StatusCode::PAGE_TIMEOUT: return "page timeout";
70     case pw::bluetooth::emboss::StatusCode::AUTHENTICATION_FAILURE: return "authentication failure";
71     case pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING: return "pin or key missing";
72     case pw::bluetooth::emboss::StatusCode::MEMORY_CAPACITY_EXCEEDED: return "memory capacity exceeded";
73     case pw::bluetooth::emboss::StatusCode::CONNECTION_TIMEOUT: return "connection timeout";
74     case pw::bluetooth::emboss::StatusCode::CONNECTION_LIMIT_EXCEEDED: return "connection limit exceeded";
75     case pw::bluetooth::emboss::StatusCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED: return "synchronous connection limit exceeded";
76     case pw::bluetooth::emboss::StatusCode::CONNECTION_ALREADY_EXISTS: return "connection already exists";
77     case pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED: return "command disallowed";
78     case pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_LIMITED_RESOURCES: return "connection rejected: limited resources";
79     case pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_SECURITY: return "connection rejected: security";
80     case pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR: return "connection rejected: bad BD_ADDR";
81     case pw::bluetooth::emboss::StatusCode::CONNECTION_ACCEPT_TIMEOUT_EXCEEDED: return "connection accept timeout exceeded";
82     case pw::bluetooth::emboss::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER: return "unsupported feature or parameter";
83     case pw::bluetooth::emboss::StatusCode::INVALID_HCI_COMMAND_PARAMETERS: return "invalid HCI command parameters";
84     case pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION: return "remote user terminated connection";
85     case pw::bluetooth::emboss::StatusCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES: return "remote device terminated connection: low resources";
86     case pw::bluetooth::emboss::StatusCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF: return "remote device terminated connection: power off";
87     case pw::bluetooth::emboss::StatusCode::CONNECTION_TERMINATED_BY_LOCAL_HOST: return "connection terminated by local host";
88     case pw::bluetooth::emboss::StatusCode::REPEATED_ATTEMPTS: return "repeated attempts";
89     case pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED: return "pairing not allowed";
90     case pw::bluetooth::emboss::StatusCode::UNKNOWN_LMP_PDU: return "unpw::bluetooth::emboss::StatusCode::nown LMP PDU";
91     case pw::bluetooth::emboss::StatusCode::UNSUPPORTED_REMOTE_FEATURE: return "unsupported remote feature";
92     case pw::bluetooth::emboss::StatusCode::SCO_OFFSET_REJECTED: return "SCO offset rejected";
93     case pw::bluetooth::emboss::StatusCode::SCO_INTERVAL_REJECTED: return "SCO interval rejected";
94     case pw::bluetooth::emboss::StatusCode::SCO_AIRMODE_REJECTED: return "SCO air mode rejected";
95     case pw::bluetooth::emboss::StatusCode::INVALID_LMP_OR_LL_PARAMETERS: return "invalid LMP or LL parameters";
96     case pw::bluetooth::emboss::StatusCode::UNSPECIFIED_ERROR: return "unspecified error";
97     case pw::bluetooth::emboss::StatusCode::UNSUPPORTED_LMP_OR_LL_PARAMETER_VALUE: return "unsupported LMP or LL parameter value";
98     case pw::bluetooth::emboss::StatusCode::ROLE_CHANGE_NOT_ALLOWED: return "role change not allowed";
99     case pw::bluetooth::emboss::StatusCode::LMP_OR_LL_RESPONSE_TIMEOUT: return "LMP or LL response timeout";
100     case pw::bluetooth::emboss::StatusCode::LMP_ERROR_TRANSACTION_COLLISION: return "LMP error transaction collision";
101     case pw::bluetooth::emboss::StatusCode::LMP_PDU_NOT_ALLOWED: return "LMP PDU not allowed";
102     case pw::bluetooth::emboss::StatusCode::ENCRYPTION_MODE_NOT_ACCEPTABLE: return "encryption mode not acceptable";
103     case pw::bluetooth::emboss::StatusCode::LINK_KEY_CANNOT_BE_CHANGED: return "link key cannot be changed";
104     case pw::bluetooth::emboss::StatusCode::REQUESTED_QOS_NOT_SUPPORTED: return "requested QoS not supported";
105     case pw::bluetooth::emboss::StatusCode::INSTANT_PASSED: return "instant passed";
106     case pw::bluetooth::emboss::StatusCode::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED: return "pairing with unit key not supported";
107     case pw::bluetooth::emboss::StatusCode::DIFFERENT_TRANSACTION_COLLISION: return "different transaction collision";
108     case pw::bluetooth::emboss::StatusCode::QOS_UNACCEPTABLE_PARAMETER: return "QoS unacceptable parameter";
109     case pw::bluetooth::emboss::StatusCode::QOS_REJECTED: return "QoS rejected";
110     case pw::bluetooth::emboss::StatusCode::CHANNEL_CLASSIFICATION_NOT_SUPPORTED: return "channel classification not supported";
111     case pw::bluetooth::emboss::StatusCode::INSUFFICIENT_SECURITY: return "insufficient security";
112     case pw::bluetooth::emboss::StatusCode::PARAMETER_OUT_OF_MANDATORY_RANGE: return "parameter out of mandatory range";
113     case pw::bluetooth::emboss::StatusCode::ROLE_SWITCH_PENDING: return "role switch pending";
114     case pw::bluetooth::emboss::StatusCode::RESERVED_SLOT_VIOLATION: return "reserved slot violation";
115     case pw::bluetooth::emboss::StatusCode::ROLE_SWITCH_FAILED: return "role switch failed";
116     case pw::bluetooth::emboss::StatusCode::EXTENDED_INQUIRY_RESPONSE_TOO_LARGE: return "extended inquiry response too large";
117     case pw::bluetooth::emboss::StatusCode::SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST: return "secure simple pairing not supported by host";
118     case pw::bluetooth::emboss::StatusCode::HOST_BUSY_PAIRING: return "host busy pairing";
119     case pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_NO_SUITABLE_CHANNEL_FOUND: return "connection rejected: no suitable channel found";
120     case pw::bluetooth::emboss::StatusCode::CONTROLLER_BUSY: return "controller busy";
121     case pw::bluetooth::emboss::StatusCode::UNACCEPTABLE_CONNECTION_PARAMETERS: return "unacceptable connection parameters";
122     case pw::bluetooth::emboss::StatusCode::DIRECTED_ADVERTISING_TIMEOUT: return "directed advertising timeout";
123     case pw::bluetooth::emboss::StatusCode::CONNECTION_TERMINATED_MIC_FAILURE: return "connection terminated: MIC failure";
124     case pw::bluetooth::emboss::StatusCode::CONNECTION_FAILED_TO_BE_ESTABLISHED: return "connection failed to be established";
125     case pw::bluetooth::emboss::StatusCode::MAC_CONNECTION_FAILED: return "MAC connection failed";
126     case pw::bluetooth::emboss::StatusCode::COARSE_CLOCK_ADJUSTMENT_REJECTED: return "coarse clocpw::bluetooth::emboss::StatusCode:: adjustment rejected";
127     case pw::bluetooth::emboss::StatusCode::TYPE_0_SUBMAP_NOT_DEFINED: return "type 0 submap not defined";
128     case pw::bluetooth::emboss::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER: return "unknown advertising identifier";
129     case pw::bluetooth::emboss::StatusCode::LIMIT_REACHED: return "limit reached";
130     case pw::bluetooth::emboss::StatusCode::OPERATION_CANCELLED_BY_HOST: return "operation cancelled by host";
131     default: break;
132   };
133   return "unknown status";
134 }
135 // clang-format on
136 
LinkTypeToString(pw::bluetooth::emboss::LinkType link_type)137 const char* LinkTypeToString(pw::bluetooth::emboss::LinkType link_type) {
138   switch (link_type) {
139     case pw::bluetooth::emboss::LinkType::SCO:
140       return "SCO";
141     case pw::bluetooth::emboss::LinkType::ACL:
142       return "ACL";
143     case pw::bluetooth::emboss::LinkType::ESCO:
144       return "eSCO";
145     default:
146       return "<Unknown LinkType>";
147   };
148 }
149 
LinkKeyTypeToString(hci_spec::LinkKeyType key_type)150 const char* LinkKeyTypeToString(hci_spec::LinkKeyType key_type) {
151   switch (key_type) {
152     case hci_spec::LinkKeyType::kCombination:
153       return "kCombination";
154     case hci_spec::LinkKeyType::kLocalUnit:
155       return "kLocalUnit";
156     case hci_spec::LinkKeyType::kRemoteUnit:
157       return "kRemoteUnit";
158     case hci_spec::LinkKeyType::kDebugCombination:
159       return "kDebugCombination";
160     case hci_spec::LinkKeyType::kUnauthenticatedCombination192:
161       return "kUnauthenticatedCombination192";
162     case hci_spec::LinkKeyType::kAuthenticatedCombination192:
163       return "kAuthenticatedCombination192";
164     case hci_spec::LinkKeyType::kChangedCombination:
165       return "kChangedCombination";
166     case hci_spec::LinkKeyType::kUnauthenticatedCombination256:
167       return "kUnauthenticatedCombination256";
168     case hci_spec::LinkKeyType::kAuthenticatedCombination256:
169       return "kAuthenticatedCombination256";
170     default:
171       break;
172   }
173 
174   return "(Unknown)";
175 }
176 
ConnectionRoleToString(pw::bluetooth::emboss::ConnectionRole role)177 std::string ConnectionRoleToString(pw::bluetooth::emboss::ConnectionRole role) {
178   switch (role) {
179     case pw::bluetooth::emboss::ConnectionRole::CENTRAL:
180       return "central";
181     case pw::bluetooth::emboss::ConnectionRole::PERIPHERAL:
182       return "peripheral";
183     default:
184       return "<unknown role>";
185   }
186 }
187 
AdvertisingTypeToEventBits(pw::bluetooth::emboss::LEAdvertisingType type)188 std::optional<AdvertisingEventBits> AdvertisingTypeToEventBits(
189     pw::bluetooth::emboss::LEAdvertisingType type) {
190   // TODO(fxbug.dev/42161929): for backwards compatibility and because
191   // supporting extended advertising PDUs is a much larger project, we currently
192   // only support legacy PDUs. Without using legacy PDUs, non-Bluetooth 5
193   // devices will not be able to discover extended advertisements.
194   uint16_t adv_event_properties = kLEAdvEventPropBitUseLegacyPDUs;
195 
196   // Bluetooth Spec Volume 4, Part E, Section 7.8.53, Table 7.2 defines the
197   // mapping of legacy PDU types to the corresponding bits within
198   // adv_event_properties.
199   switch (type) {
200     case pw::bluetooth::emboss::LEAdvertisingType::
201         CONNECTABLE_AND_SCANNABLE_UNDIRECTED:
202       adv_event_properties |= kLEAdvEventPropBitConnectable;
203       adv_event_properties |= kLEAdvEventPropBitScannable;
204       break;
205     case pw::bluetooth::emboss::LEAdvertisingType::
206         CONNECTABLE_LOW_DUTY_CYCLE_DIRECTED:
207       adv_event_properties |= kLEAdvEventPropBitConnectable;
208       adv_event_properties |= kLEAdvEventPropBitDirected;
209       break;
210     case pw::bluetooth::emboss::LEAdvertisingType::
211         CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED:
212       adv_event_properties |= kLEAdvEventPropBitConnectable;
213       adv_event_properties |= kLEAdvEventPropBitDirected;
214       adv_event_properties |=
215           kLEAdvEventPropBitHighDutyCycleDirectedConnectable;
216       break;
217     case pw::bluetooth::emboss::LEAdvertisingType::SCANNABLE_UNDIRECTED:
218       adv_event_properties |= kLEAdvEventPropBitScannable;
219       break;
220     case pw::bluetooth::emboss::LEAdvertisingType::NOT_CONNECTABLE_UNDIRECTED:
221       // no extra bits to set
222       break;
223     default:
224       return std::nullopt;
225   }
226 
227   return adv_event_properties;
228 }
229 
230 }  // namespace bt::hci_spec
231