1 // Copyright 2024 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 #pragma once
16
17 #include <fidl/fuchsia.bluetooth.bredr/cpp/fidl.h>
18 #include <fidl/fuchsia.bluetooth/cpp/fidl.h>
19 #include <fidl/fuchsia.hardware.bluetooth/cpp/fidl.h>
20 #include <fuchsia/bluetooth/gatt/cpp/fidl.h>
21 #include <fuchsia/bluetooth/gatt2/cpp/fidl.h>
22 #include <fuchsia/bluetooth/host/cpp/fidl.h>
23 #include <fuchsia/bluetooth/le/cpp/fidl.h>
24 #include <fuchsia/bluetooth/sys/cpp/fidl.h>
25 #include <lib/fidl/cpp/type_converter.h>
26 #include <lib/fpromise/result.h>
27
28 #include <optional>
29
30 #include "pw_bluetooth_sapphire/internal/host/common/advertising_data.h"
31 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
32 #include "pw_bluetooth_sapphire/internal/host/common/error.h"
33 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h"
34 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
35 #include "pw_bluetooth_sapphire/internal/host/gap/adapter.h"
36 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h"
37 #include "pw_bluetooth_sapphire/internal/host/gap/low_energy_advertising_manager.h"
38 #include "pw_bluetooth_sapphire/internal/host/gap/peer.h"
39 #include "pw_bluetooth_sapphire/internal/host/gap/types.h"
40 #include "pw_bluetooth_sapphire/internal/host/gatt/types.h"
41 #include "pw_bluetooth_sapphire/internal/host/iso/iso_common.h"
42
43 // Helpers for implementing the Bluetooth FIDL interfaces.
44
45 namespace bt::gap {
46
47 class DiscoveryFilter;
48
49 } // namespace bt::gap
50
51 namespace bthost::fidl_helpers {
52
53 namespace android_emb = pw::bluetooth::vendor::android_hci;
54
55 // TODO(fxbug.dev/42171179): Temporary logic for converting between the stack
56 // identifier type (integer) and FIDL identifier type (string). Remove these
57 // once all FIDL interfaces have been converted to use integer IDs.
58 std::optional<bt::PeerId> PeerIdFromString(const std::string& id);
59
60 // Functions for generating a FIDL bluetooth::Status
61
62 fuchsia::bluetooth::ErrorCode HostErrorToFidlDeprecated(
63 bt::HostError host_error);
64
65 fuchsia::bluetooth::Status NewFidlError(
66 fuchsia::bluetooth::ErrorCode error_code, const std::string& description);
67
68 template <typename ProtocolErrorCode>
69 fuchsia::bluetooth::Status ResultToFidlDeprecated(
70 const fit::result<bt::Error<ProtocolErrorCode>>& result,
71 std::string msg = "") {
72 fuchsia::bluetooth::Status fidl_status;
73 if (result.is_ok()) {
74 return fidl_status;
75 }
76
77 auto error = std::make_unique<fuchsia::bluetooth::Error>();
78 error->description = msg.empty() ? bt_str(result) : std::move(msg);
79 if (result.is_error()) {
80 result.error_value().Visit(
81 [&error](bt::HostError c) {
82 error->error_code = HostErrorToFidlDeprecated(c);
83 },
84 [&](ProtocolErrorCode c) {
85 if constexpr (bt::Error<
86 ProtocolErrorCode>::may_hold_protocol_error()) {
87 error->error_code = fuchsia::bluetooth::ErrorCode::PROTOCOL_ERROR;
88 error->protocol_error_code = static_cast<uint32_t>(c);
89 } else {
90 BT_PANIC("Protocol branch visited by bt::Error<NoProtocolError>");
91 }
92 });
93 }
94
95 fidl_status.error = std::move(error);
96 return fidl_status;
97 }
98
99 // Convert a bt::HostError to fuchsia.bluetooth.sys.Error. This function does
100 // only deals with bt::HostError types and does not support Bluetooth
101 // protocol-specific errors; to represent such errors use protocol-specific FIDL
102 // error types.
103 fuchsia::bluetooth::sys::Error HostErrorToFidl(bt::HostError error);
104
105 // Convert a bt::Error to fuchsia.bluetooth.sys.Error. This function does only
106 // deals with bt::HostError codes and does not support Bluetooth
107 // protocol-specific errors; to represent such errors use protocol-specific FIDL
108 // error types.
109 template <typename ProtocolErrorCode>
HostErrorToFidl(const bt::Error<ProtocolErrorCode> & error)110 fuchsia::bluetooth::sys::Error HostErrorToFidl(
111 const bt::Error<ProtocolErrorCode>& error) {
112 if (!error.is_host_error()) {
113 return fuchsia::bluetooth::sys::Error::FAILED;
114 }
115 return HostErrorToFidl(error.host_error());
116 }
117
118 // Convert any bt::Status to a fpromise::result that uses the
119 // fuchsia.bluetooth.sys library error codes.
120 template <typename ProtocolErrorCode>
ResultToFidl(const fit::result<bt::Error<ProtocolErrorCode>> & status)121 fpromise::result<void, fuchsia::bluetooth::sys::Error> ResultToFidl(
122 const fit::result<bt::Error<ProtocolErrorCode>>& status) {
123 if (status.is_ok()) {
124 return fpromise::ok();
125 } else {
126 return fpromise::error(HostErrorToFidl(std::move(status).error_value()));
127 }
128 }
129
130 // Convert a bt::att::Error to fuchsia.bluetooth.gatt.Error.
131 fuchsia::bluetooth::gatt::Error GattErrorToFidl(const bt::att::Error& error);
132
133 // Convert a bt::att::Error to fuchsia.bluetooth.gatt2.Error.
134 fuchsia::bluetooth::gatt2::Error AttErrorToGattFidlError(
135 const bt::att::Error& error);
136
137 // Convert a fuchsia::bluetooth::Uuid to bt::UUID for old HLCPP FIDL bindings
138 bt::UUID UuidFromFidl(const fuchsia::bluetooth::Uuid& input);
139 // Convert a bt::UUID to fuchsia::bluetooth::Uuid for old HLCPP FIDL bindings
140 fuchsia::bluetooth::Uuid UuidToFidl(const bt::UUID& uuid);
141
142 // Convert a fuchsia_bluetooth::Uuid to bt::UUID for new C++ FIDL bindings
143 bt::UUID NewUuidFromFidl(const fuchsia_bluetooth::Uuid& input);
144
145 // Functions that convert FIDL types to library objects.
146 bt::sm::IOCapability IoCapabilityFromFidl(
147 const fuchsia::bluetooth::sys::InputCapability,
148 const fuchsia::bluetooth::sys::OutputCapability);
149 std::optional<bt::gap::BrEdrSecurityMode> BrEdrSecurityModeFromFidl(
150 const fuchsia::bluetooth::sys::BrEdrSecurityMode mode);
151 bt::gap::LESecurityMode LeSecurityModeFromFidl(
152 const fuchsia::bluetooth::sys::LeSecurityMode mode);
153 std::optional<bt::sm::SecurityLevel> SecurityLevelFromFidl(
154 const fuchsia::bluetooth::sys::PairingSecurityLevel level);
155
156 // fuchsia.bluetooth.sys library helpers.
157 fuchsia::bluetooth::sys::TechnologyType TechnologyTypeToFidl(
158 bt::gap::TechnologyType type);
159 fuchsia::bluetooth::sys::HostInfo HostInfoToFidl(
160 const bt::gap::Adapter& adapter);
161 fuchsia::bluetooth::sys::Peer PeerToFidl(const bt::gap::Peer& peer);
162
163 // Functions to convert bonding data structures from FIDL.
164 std::optional<bt::DeviceAddress> AddressFromFidlBondingData(
165 const fuchsia::bluetooth::sys::BondingData& data);
166 bt::sm::PairingData LePairingDataFromFidl(
167 bt::DeviceAddress peer_address,
168 const fuchsia::bluetooth::sys::LeBondData& data);
169 std::optional<bt::sm::LTK> BredrKeyFromFidl(
170 const fuchsia::bluetooth::sys::BredrBondData& data);
171 std::vector<bt::UUID> BredrServicesFromFidl(
172 const fuchsia::bluetooth::sys::BredrBondData& data);
173
174 // Function to construct a bonding data structure for a peer.
175 fuchsia::bluetooth::sys::BondingData PeerToFidlBondingData(
176 const bt::gap::Adapter& adapter, const bt::gap::Peer& peer);
177
178 // Functions to construct FIDL LE library objects from library objects. Returns
179 // nullptr if the peer is not LE or if the peer's advertising data failed to
180 // parse.
181 fuchsia::bluetooth::le::RemoteDevicePtr NewLERemoteDevice(
182 const bt::gap::Peer& peer);
183
184 // Validates the contents of a ScanFilter.
185 bool IsScanFilterValid(const fuchsia::bluetooth::le::ScanFilter& fidl_filter);
186
187 // Populates a library DiscoveryFilter based on a FIDL ScanFilter. Returns false
188 // if |fidl_filter| contains any malformed data and leaves |out_filter|
189 // unmodified.
190 bool PopulateDiscoveryFilter(
191 const fuchsia::bluetooth::le::ScanFilter& fidl_filter,
192 bt::gap::DiscoveryFilter* out_filter);
193 bt::gap::DiscoveryFilter DiscoveryFilterFromFidl(
194 const fuchsia::bluetooth::le::Filter& fidl_filter);
195
196 // Converts the given |mode_hint| to a stack interval value.
197 bt::gap::AdvertisingInterval AdvertisingIntervalFromFidl(
198 fuchsia::bluetooth::le::AdvertisingModeHint mode_hint);
199
200 std::optional<bt::AdvertisingData> AdvertisingDataFromFidl(
201 const fuchsia::bluetooth::le::AdvertisingData& input);
202 fuchsia::bluetooth::le::AdvertisingData AdvertisingDataToFidl(
203 const bt::AdvertisingData& input);
204 fuchsia::bluetooth::le::AdvertisingDataDeprecated
205 AdvertisingDataToFidlDeprecated(const bt::AdvertisingData& input);
206 fuchsia::bluetooth::le::ScanData AdvertisingDataToFidlScanData(
207 const bt::AdvertisingData& input,
208 pw::chrono::SystemClock::time_point timestamp);
209
210 // Constructs a fuchsia.bluetooth.le Peer type from the stack representation.
211 fuchsia::bluetooth::le::Peer PeerToFidlLe(const bt::gap::Peer& peer);
212
213 // Functions that convert FIDL GATT types to library objects.
214 bt::gatt::ReliableMode ReliableModeFromFidl(
215 const fuchsia::bluetooth::gatt::WriteOptions& write_options);
216 // TODO(fxbug.dev/42141942): The 64 bit `fidl_gatt_id` can overflow the 16 bits
217 // of a bt:att::Handle that underlies Characteristic/DescriptorHandles when
218 // directly casted. Fix this.
219 bt::gatt::CharacteristicHandle CharacteristicHandleFromFidl(
220 uint64_t fidl_gatt_id);
221 bt::gatt::DescriptorHandle DescriptorHandleFromFidl(uint64_t fidl_gatt_id);
222
223 // Constructs a sdp::ServiceRecord from a FIDL ServiceDefinition |definition|
224 fpromise::result<bt::sdp::ServiceRecord, fuchsia::bluetooth::ErrorCode>
225 ServiceDefinitionToServiceRecord(
226 const fuchsia_bluetooth_bredr::ServiceDefinition& definition);
227
228 // Constructs a sdp::ServiceRecord from a FIDL ServiceDefinition |definition|
229 fpromise::result<bt::sdp::ServiceRecord, fuchsia::bluetooth::ErrorCode>
230 ServiceDefinitionToServiceRecord(
231 const fuchsia::bluetooth::bredr::ServiceDefinition& definition);
232
233 // Constructs a FIDL ServiceDefinition from a sdp::ServiceRecord
234 fpromise::result<fuchsia::bluetooth::bredr::ServiceDefinition,
235 fuchsia::bluetooth::ErrorCode>
236 ServiceRecordToServiceDefinition(const bt::sdp::ServiceRecord& record);
237
238 bt::gap::BrEdrSecurityRequirements FidlToBrEdrSecurityRequirements(
239 const fuchsia::bluetooth::ChannelParameters& fidl);
240
241 fpromise::result<bt::StaticPacket<
242 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>
243 FidlToScoParameters(
244 const fuchsia::bluetooth::bredr::ScoConnectionParameters& params);
245 fpromise::result<std::vector<bt::StaticPacket<
246 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>>
247 FidlToScoParametersVector(
248 const std::vector<fuchsia::bluetooth::bredr::ScoConnectionParameters>&
249 params);
250
251 // Returns true if |handle| is within the valid handle range.
252 bool IsFidlGattHandleValid(fuchsia::bluetooth::gatt2::Handle handle);
253 bool IsFidlGattServiceHandleValid(
254 fuchsia::bluetooth::gatt2::ServiceHandle handle);
255
256 fuchsia::bluetooth::bredr::RxPacketStatus ScoPacketStatusToFidl(
257 bt::hci_spec::SynchronousDataPacketStatusFlag status);
258
259 bt::att::ErrorCode Gatt2ErrorCodeFromFidl(
260 fuchsia::bluetooth::gatt2::Error error_code);
261
262 bt::att::AccessRequirements Gatt2AccessRequirementsFromFidl(
263 const fuchsia::bluetooth::gatt2::SecurityRequirements& reqs);
264
265 void FillInAttributePermissionsDefaults(
266 fuchsia::bluetooth::gatt2::AttributePermissions& reqs);
267
268 // Returns the bt-host representation of the FIDL descriptor, or nullptr if the
269 // conversion fails.
270 std::unique_ptr<bt::gatt::Descriptor> Gatt2DescriptorFromFidl(
271 const fuchsia::bluetooth::gatt2::Descriptor& fidl_desc);
272
273 // Returns the bt-host representation of the FIDL characteristc, or nullptr if
274 // the conversion fails.
275 std::unique_ptr<bt::gatt::Characteristic> Gatt2CharacteristicFromFidl(
276 const fuchsia::bluetooth::gatt2::Characteristic& fidl_chrc);
277
278 std::optional<android_emb::A2dpCodecType> FidlToCodecType(
279 const fuchsia::bluetooth::bredr::AudioOffloadFeatures& codec);
280
281 bt::StaticPacket<android_emb::A2dpScmsTEnableWriter> FidlToScmsTEnable(
282 bool scms_t_enable);
283
284 std::optional<android_emb::A2dpSamplingFrequency> FidlToSamplingFrequency(
285 fuchsia::bluetooth::bredr::AudioSamplingFrequency sampling_frequency);
286
287 std::optional<android_emb::A2dpBitsPerSample> FidlToBitsPerSample(
288 fuchsia::bluetooth::bredr::AudioBitsPerSample bits_per_sample);
289
290 std::optional<android_emb::A2dpChannelMode> FidlToChannelMode(
291 fuchsia::bluetooth::bredr::AudioChannelMode channel_mode);
292
293 bt::StaticPacket<android_emb::SbcCodecInformationWriter>
294 FidlToEncoderSettingsSbc(
295 const fuchsia::bluetooth::bredr::AudioEncoderSettings& encoder_settings,
296 fuchsia::bluetooth::bredr::AudioSamplingFrequency sampling_frequency,
297 fuchsia::bluetooth::bredr::AudioChannelMode channel_mode);
298
299 bt::StaticPacket<android_emb::AacCodecInformationWriter>
300 FidlToEncoderSettingsAac(
301 const fuchsia::bluetooth::bredr::AudioEncoderSettings& encoder_settings,
302 fuchsia::bluetooth::bredr::AudioSamplingFrequency sampling_frequency,
303 fuchsia::bluetooth::bredr::AudioChannelMode channel_mode);
304
305 // For old HLCPP FIDL bindings
306 std::optional<bt::sdp::DataElement> FidlToDataElement(
307 const fuchsia::bluetooth::bredr::DataElement& fidl);
308 // For new C++ FIDL bindings
309 std::optional<bt::sdp::DataElement> NewFidlToDataElement(
310 const fuchsia_bluetooth_bredr::DataElement& fidl);
311
312 const char* DataPathDirectionToString(
313 pw::bluetooth::emboss::DataPathDirection direction);
314
315 pw::bluetooth::emboss::DataPathDirection DataPathDirectionFromFidl(
316 const fuchsia::bluetooth::DataDirection& fidl_direction);
317
318 pw::bluetooth::emboss::CodingFormat CodingFormatFromFidl(
319 const fuchsia::bluetooth::AssignedCodingFormat& fidl_format);
320
321 bt::StaticPacket<pw::bluetooth::emboss::CodecIdWriter> CodecIdFromFidl(
322 const fuchsia::bluetooth::CodecId& fidl_codec_id);
323
324 pw::bluetooth::emboss::LogicalTransportType LogicalTransportTypeFromFidl(
325 const fuchsia::bluetooth::LogicalTransportType& fidl_transport_type);
326
327 pw::bluetooth::emboss::StatusCode FidlHciErrorToStatusCode(
328 fuchsia_hardware_bluetooth::HciError code);
329
330 fuchsia::bluetooth::le::CisEstablishedParameters CisEstablishedParametersToFidl(
331 const bt::iso::CisEstablishedParameters& params_in);
332
333 bt::DeviceAddress::Type FidlToDeviceAddressType(
334 fuchsia::bluetooth::AddressType addr_type);
335
336 } // namespace bthost::fidl_helpers
337
338 // fidl::TypeConverter specializations for ByteBuffer and friends.
339 template <>
340 struct fidl::TypeConverter<std::vector<uint8_t>, bt::ByteBuffer> {
341 static std::vector<uint8_t> Convert(const bt::ByteBuffer& from);
342 };
343