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/l2cap/channel_manager.h"
16
17 #include <pw_assert/check.h>
18
19 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/a2dp_offload_manager.h"
22 #include "pw_bluetooth_sapphire/internal/host/l2cap/logical_link.h"
23
24 namespace bt::l2cap {
25
26 namespace {
27
28 constexpr const char* kInspectServicesNodeName = "services";
29 constexpr const char* kInspectServiceNodePrefix = "service_";
30 constexpr const char* kInspectLogicalLinksNodeName = "logical_links";
31 constexpr const char* kInspectLogicalLinkNodePrefix = "logical_link_";
32 constexpr const char* kInspectPsmPropertyName = "psm";
33
34 } // namespace
35
36 class ChannelManagerImpl final : public ChannelManager {
37 public:
38 using LinkErrorCallback = fit::closure;
39
40 ChannelManagerImpl(hci::AclDataChannel* acl_data_channel,
41 hci::CommandChannel* cmd_channel,
42 bool random_channel_ids,
43 pw::async::Dispatcher& dispatcher);
44 ~ChannelManagerImpl() override;
45
46 void AddACLConnection(
47 hci_spec::ConnectionHandle handle,
48 pw::bluetooth::emboss::ConnectionRole role,
49 l2cap::LinkErrorCallback link_error_callback,
50 l2cap::SecurityUpgradeCallback security_callback,
51 fit::callback<void(BrEdrFixedChannels)> fixed_channels_callback) override;
52
53 [[nodiscard]] LEFixedChannels AddLEConnection(
54 hci_spec::ConnectionHandle handle,
55 pw::bluetooth::emboss::ConnectionRole role,
56 LinkErrorCallback link_error_cb,
57 LEConnectionParameterUpdateCallback conn_param_cb,
58 SecurityUpgradeCallback security_cb) override;
59
60 void RemoveConnection(hci_spec::ConnectionHandle handle) override;
61
62 void AssignLinkSecurityProperties(hci_spec::ConnectionHandle handle,
63 sm::SecurityProperties security) override;
64
65 Channel::WeakPtr OpenFixedChannel(
66 hci_spec::ConnectionHandle connection_handle,
67 ChannelId channel_id) override;
68
69 void OpenL2capChannel(hci_spec::ConnectionHandle handle,
70 Psm psm,
71 ChannelParameters params,
72 ChannelCallback cb) override;
73
74 bool RegisterService(Psm psm,
75 ChannelParameters params,
76 ChannelCallback cb) override;
77 void UnregisterService(Psm psm) override;
78
79 void RequestConnectionParameterUpdate(
80 hci_spec::ConnectionHandle handle,
81 hci_spec::LEPreferredConnectionParameters params,
82 ConnectionParameterUpdateRequestCallback request_cb) override;
83
84 void AttachInspect(inspect::Node& parent, std::string name) override;
85
86 internal::LogicalLink::WeakPtr LogicalLinkForTesting(
87 hci_spec::ConnectionHandle handle) override;
88
89 private:
90 // Returns a handler for data packets received from the Bluetooth controller
91 // bound to this object.
92 hci::ACLPacketHandler MakeInboundDataHandler();
93
94 // Called when an ACL data packet is received from the controller. This method
95 // is responsible for routing the packet to the corresponding LogicalLink.
96 void OnACLDataReceived(hci::ACLDataPacketPtr data_packet);
97
98 // Called by the various Register functions. Returns a pointer to the newly
99 // added link.
100 internal::LogicalLink* RegisterInternal(
101 hci_spec::ConnectionHandle handle,
102 bt::LinkType ll_type,
103 pw::bluetooth::emboss::ConnectionRole role,
104 size_t max_payload_size);
105
106 // If a service (identified by |psm|) requested has been registered, return a
107 // ServiceInfo object containing preferred channel parameters and a callback
108 // that passes an inbound channel to the registrant. The callback may be
109 // called repeatedly to pass multiple channels for |psm|, but should not be
110 // stored because the service may be unregistered at a later time. Calls for
111 // unregistered services return null.
112 std::optional<ServiceInfo> QueryService(hci_spec::ConnectionHandle handle,
113 Psm psm);
114
115 pw::async::Dispatcher& pw_dispatcher_;
116
117 // Maximum sizes for data packet payloads from host to controller.
118 size_t max_acl_payload_size_;
119 size_t max_le_payload_size_;
120
121 hci::AclDataChannel* acl_data_channel_;
122 hci::CommandChannel* cmd_channel_;
123
124 std::unique_ptr<A2dpOffloadManager> a2dp_offload_manager_;
125
126 using LinkMap = std::unordered_map<hci_spec::ConnectionHandle,
127 std::unique_ptr<internal::LogicalLink>>;
128 LinkMap ll_map_;
129 inspect::Node ll_node_;
130
131 // Stores packets received on a connection handle before a link for it has
132 // been created.
133 using PendingPacketMap =
134 std::unordered_map<hci_spec::ConnectionHandle,
135 std::queue<hci::ACLDataPacketPtr>>;
136 PendingPacketMap pending_packets_;
137
138 // Store information required to create and forward channels for locally-
139 // hosted services.
140 struct ServiceData {
141 void AttachInspect(inspect::Node& parent);
142 ServiceInfo info;
143 Psm psm;
144 inspect::Node node;
145 inspect::StringProperty psm_property;
146 };
147 using ServiceMap = std::unordered_map<Psm, ServiceData>;
148 ServiceMap services_;
149 inspect::Node services_node_;
150 inspect::Node node_;
151
152 // Stored info on whether random channel ids are requested.
153 bool random_channel_ids_;
154
155 WeakSelf<ChannelManagerImpl> weak_self_;
156
157 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ChannelManagerImpl);
158 };
159
ChannelManagerImpl(hci::AclDataChannel * acl_data_channel,hci::CommandChannel * cmd_channel,bool random_channel_ids,pw::async::Dispatcher & dispatcher)160 ChannelManagerImpl::ChannelManagerImpl(hci::AclDataChannel* acl_data_channel,
161 hci::CommandChannel* cmd_channel,
162 bool random_channel_ids,
163 pw::async::Dispatcher& dispatcher)
164 : pw_dispatcher_(dispatcher),
165 acl_data_channel_(acl_data_channel),
166 cmd_channel_(cmd_channel),
167 a2dp_offload_manager_(
168 std::make_unique<A2dpOffloadManager>(cmd_channel_->AsWeakPtr())),
169 random_channel_ids_(random_channel_ids),
170 weak_self_(this) {
171 PW_CHECK(acl_data_channel_);
172 max_acl_payload_size_ = acl_data_channel_->GetBufferInfo().max_data_length();
173 max_le_payload_size_ = acl_data_channel_->GetLeBufferInfo().max_data_length();
174 acl_data_channel_->SetDataRxHandler(MakeInboundDataHandler());
175
176 bt_log(DEBUG, "l2cap", "initialized");
177 }
178
~ChannelManagerImpl()179 ChannelManagerImpl::~ChannelManagerImpl() {
180 bt_log(DEBUG, "l2cap", "shutting down");
181
182 // Explicitly shut down all links to force associated L2CAP channels to
183 // release their strong references.
184 for (auto& [handle, link] : ll_map_) {
185 link->Close();
186 }
187 }
188
MakeInboundDataHandler()189 hci::ACLPacketHandler ChannelManagerImpl::MakeInboundDataHandler() {
190 return [self = weak_self_.GetWeakPtr()](auto packet) {
191 if (self.is_alive()) {
192 self->OnACLDataReceived(std::move(packet));
193 }
194 };
195 }
196
AddACLConnection(hci_spec::ConnectionHandle handle,pw::bluetooth::emboss::ConnectionRole role,l2cap::LinkErrorCallback link_error_callback,l2cap::SecurityUpgradeCallback security_callback,fit::callback<void (BrEdrFixedChannels)> fixed_channels_callback)197 void ChannelManagerImpl::AddACLConnection(
198 hci_spec::ConnectionHandle handle,
199 pw::bluetooth::emboss::ConnectionRole role,
200 l2cap::LinkErrorCallback link_error_callback,
201 l2cap::SecurityUpgradeCallback security_callback,
202 fit::callback<void(BrEdrFixedChannels)> fixed_channels_callback) {
203 bt_log(DEBUG, "l2cap", "register ACL link (handle: %#.4x)", handle);
204
205 auto* ll =
206 RegisterInternal(handle, bt::LinkType::kACL, role, max_acl_payload_size_);
207 ll->set_error_callback(std::move(link_error_callback));
208 ll->set_security_upgrade_callback(std::move(security_callback));
209 ll->OpenFixedChannelAsync(
210 kSMPChannelId,
211 [cb = std::move(fixed_channels_callback)](Channel::WeakPtr smp) mutable {
212 cb(BrEdrFixedChannels{.smp = std::move(smp)});
213 });
214 }
215
AddLEConnection(hci_spec::ConnectionHandle handle,pw::bluetooth::emboss::ConnectionRole role,LinkErrorCallback link_error_cb,LEConnectionParameterUpdateCallback conn_param_cb,SecurityUpgradeCallback security_cb)216 ChannelManagerImpl::LEFixedChannels ChannelManagerImpl::AddLEConnection(
217 hci_spec::ConnectionHandle handle,
218 pw::bluetooth::emboss::ConnectionRole role,
219 LinkErrorCallback link_error_cb,
220 LEConnectionParameterUpdateCallback conn_param_cb,
221 SecurityUpgradeCallback security_cb) {
222 bt_log(DEBUG, "l2cap", "register LE link (handle: %#.4x)", handle);
223
224 auto* ll =
225 RegisterInternal(handle, bt::LinkType::kLE, role, max_le_payload_size_);
226 ll->set_error_callback(std::move(link_error_cb));
227 ll->set_security_upgrade_callback(std::move(security_cb));
228 ll->set_connection_parameter_update_callback(std::move(conn_param_cb));
229
230 Channel::WeakPtr att = OpenFixedChannel(handle, kATTChannelId);
231 Channel::WeakPtr smp = OpenFixedChannel(handle, kLESMPChannelId);
232 PW_CHECK(att.is_alive());
233 PW_CHECK(smp.is_alive());
234 return LEFixedChannels{.att = std::move(att), .smp = std::move(smp)};
235 }
236
RemoveConnection(hci_spec::ConnectionHandle handle)237 void ChannelManagerImpl::RemoveConnection(hci_spec::ConnectionHandle handle) {
238 bt_log(DEBUG, "l2cap", "unregister link (handle: %#.4x)", handle);
239
240 pending_packets_.erase(handle);
241 auto iter = ll_map_.find(handle);
242 if (iter == ll_map_.end()) {
243 bt_log(DEBUG,
244 "l2cap",
245 "attempt to unregister unknown link (handle: %#.4x)",
246 handle);
247 return;
248 }
249
250 // Explicitly shut down the link to force associated L2CAP channels to release
251 // their strong references.
252 iter->second->Close();
253 ll_map_.erase(iter);
254 }
255
AssignLinkSecurityProperties(hci_spec::ConnectionHandle handle,sm::SecurityProperties security)256 void ChannelManagerImpl::AssignLinkSecurityProperties(
257 hci_spec::ConnectionHandle handle, sm::SecurityProperties security) {
258 bt_log(DEBUG,
259 "l2cap",
260 "received new security properties (handle: %#.4x)",
261 handle);
262
263 auto iter = ll_map_.find(handle);
264 if (iter == ll_map_.end()) {
265 bt_log(DEBUG, "l2cap", "ignoring new security properties on unknown link");
266 return;
267 }
268
269 iter->second->AssignSecurityProperties(security);
270 }
271
OpenFixedChannel(hci_spec::ConnectionHandle handle,ChannelId channel_id)272 Channel::WeakPtr ChannelManagerImpl::OpenFixedChannel(
273 hci_spec::ConnectionHandle handle, ChannelId channel_id) {
274 auto iter = ll_map_.find(handle);
275 if (iter == ll_map_.end()) {
276 bt_log(ERROR,
277 "l2cap",
278 "cannot open fixed channel on unknown connection handle: %#.4x",
279 handle);
280 return Channel::WeakPtr();
281 }
282
283 return iter->second->OpenFixedChannel(channel_id);
284 }
285
OpenL2capChannel(hci_spec::ConnectionHandle handle,Psm psm,ChannelParameters params,ChannelCallback cb)286 void ChannelManagerImpl::OpenL2capChannel(hci_spec::ConnectionHandle handle,
287 Psm psm,
288 ChannelParameters params,
289 ChannelCallback cb) {
290 auto iter = ll_map_.find(handle);
291 if (iter == ll_map_.end()) {
292 bt_log(ERROR,
293 "l2cap",
294 "Cannot open channel on unknown connection handle: %#.4x",
295 handle);
296 cb(Channel::WeakPtr());
297 return;
298 }
299
300 iter->second->OpenChannel(psm, params, std::move(cb));
301 }
302
RegisterService(Psm psm,ChannelParameters params,ChannelCallback cb)303 bool ChannelManagerImpl::RegisterService(Psm psm,
304 ChannelParameters params,
305 ChannelCallback cb) {
306 // v5.0 Vol 3, Part A, Sec 4.2: PSMs shall be odd and the least significant
307 // bit of the most significant byte shall be zero
308 if (((psm & 0x0001) != 0x0001) || ((psm & 0x0100) != 0x0000)) {
309 return false;
310 }
311
312 auto iter = services_.find(psm);
313 if (iter != services_.end()) {
314 return false;
315 }
316
317 ServiceData service{.info = ServiceInfo(params, std::move(cb)),
318 .psm = psm,
319 .node = {},
320 .psm_property = {}};
321 service.AttachInspect(services_node_);
322 services_.emplace(psm, std::move(service));
323 return true;
324 }
325
UnregisterService(Psm psm)326 void ChannelManagerImpl::UnregisterService(Psm psm) { services_.erase(psm); }
327
RequestConnectionParameterUpdate(hci_spec::ConnectionHandle handle,hci_spec::LEPreferredConnectionParameters params,ConnectionParameterUpdateRequestCallback request_cb)328 void ChannelManagerImpl::RequestConnectionParameterUpdate(
329 hci_spec::ConnectionHandle handle,
330 hci_spec::LEPreferredConnectionParameters params,
331 ConnectionParameterUpdateRequestCallback request_cb) {
332 auto iter = ll_map_.find(handle);
333 if (iter == ll_map_.end()) {
334 bt_log(DEBUG,
335 "l2cap",
336 "ignoring Connection Parameter Update request on unknown link");
337 return;
338 }
339
340 iter->second->SendConnectionParameterUpdateRequest(params,
341 std::move(request_cb));
342 }
343
AttachInspect(inspect::Node & parent,std::string name)344 void ChannelManagerImpl::AttachInspect(inspect::Node& parent,
345 std::string name) {
346 if (!parent) {
347 return;
348 }
349
350 node_ = parent.CreateChild(name);
351
352 services_node_ = node_.CreateChild(kInspectServicesNodeName);
353 for (auto& [psm, service] : services_) {
354 service.AttachInspect(services_node_);
355 }
356
357 ll_node_ = node_.CreateChild(kInspectLogicalLinksNodeName);
358 for (auto& [_, ll] : ll_map_) {
359 ll->AttachInspect(ll_node_,
360 ll_node_.UniqueName(kInspectLogicalLinkNodePrefix));
361 }
362 }
363
LogicalLinkForTesting(hci_spec::ConnectionHandle handle)364 internal::LogicalLink::WeakPtr ChannelManagerImpl::LogicalLinkForTesting(
365 hci_spec::ConnectionHandle handle) {
366 auto iter = ll_map_.find(handle);
367 if (iter == ll_map_.end()) {
368 return internal::LogicalLink::WeakPtr();
369 }
370 return iter->second->GetWeakPtr();
371 }
372
373 // Called when an ACL data packet is received from the controller. This method
374 // is responsible for routing the packet to the corresponding LogicalLink.
OnACLDataReceived(hci::ACLDataPacketPtr packet)375 void ChannelManagerImpl::OnACLDataReceived(hci::ACLDataPacketPtr packet) {
376 auto handle = packet->connection_handle();
377 TRACE_DURATION(
378 "bluetooth", "ChannelManagerImpl::OnDataReceived", "handle", handle);
379
380 auto iter = ll_map_.find(handle);
381 PendingPacketMap::iterator pp_iter;
382
383 // If a LogicalLink does not exist, we set up a queue for its packets to be
384 // delivered when the LogicalLink gets created.
385 if (iter == ll_map_.end()) {
386 pp_iter =
387 pending_packets_.emplace(handle, std::queue<hci::ACLDataPacketPtr>())
388 .first;
389 } else {
390 // A logical link exists. |pp_iter| will be valid only if the drain task has
391 // not run yet (see ChannelManagerImpl::RegisterInternal()).
392 pp_iter = pending_packets_.find(handle);
393 }
394
395 if (pp_iter != pending_packets_.end()) {
396 packet->set_trace_id(TRACE_NONCE());
397 TRACE_FLOW_BEGIN("bluetooth",
398 "ChannelMaager::OnDataReceived queued",
399 packet->trace_id());
400 pp_iter->second.push(std::move(packet));
401 bt_log(TRACE, "l2cap", "queued rx packet on handle: %#.4x", handle);
402 return;
403 }
404
405 iter->second->HandleRxPacket(std::move(packet));
406 }
407
RegisterInternal(hci_spec::ConnectionHandle handle,bt::LinkType ll_type,pw::bluetooth::emboss::ConnectionRole role,size_t max_payload_size)408 internal::LogicalLink* ChannelManagerImpl::RegisterInternal(
409 hci_spec::ConnectionHandle handle,
410 bt::LinkType ll_type,
411 pw::bluetooth::emboss::ConnectionRole role,
412 size_t max_payload_size) {
413 TRACE_DURATION(
414 "bluetooth", "ChannelManagerImpl::RegisterInternal", "handle", handle);
415
416 // TODO(armansito): Return nullptr instead of asserting. Callers shouldn't
417 // assume this will succeed.
418 auto iter = ll_map_.find(handle);
419 PW_DCHECK(iter == ll_map_.end(),
420 "connection handle re-used! (handle=%#.4x)",
421 handle);
422
423 auto ll = std::make_unique<internal::LogicalLink>(
424 handle,
425 ll_type,
426 role,
427 max_payload_size,
428 fit::bind_member<&ChannelManagerImpl::QueryService>(this),
429 acl_data_channel_,
430 cmd_channel_,
431 random_channel_ids_,
432 *a2dp_offload_manager_,
433 pw_dispatcher_);
434
435 if (ll_node_) {
436 ll->AttachInspect(ll_node_,
437 ll_node_.UniqueName(kInspectLogicalLinkNodePrefix));
438 }
439
440 // Route all pending packets to the link.
441 auto pp_iter = pending_packets_.find(handle);
442 if (pp_iter != pending_packets_.end()) {
443 auto& packets = pp_iter->second;
444 while (!packets.empty()) {
445 auto packet = std::move(packets.front());
446 packets.pop();
447 TRACE_FLOW_END("bluetooth",
448 "ChannelManagerImpl::OnDataReceived queued",
449 packet->trace_id());
450 ll->HandleRxPacket(std::move(packet));
451 }
452 pending_packets_.erase(pp_iter);
453 }
454
455 auto* ll_raw = ll.get();
456 ll_map_[handle] = std::move(ll);
457
458 return ll_raw;
459 }
460
QueryService(hci_spec::ConnectionHandle,Psm psm)461 std::optional<ChannelManager::ServiceInfo> ChannelManagerImpl::QueryService(
462 hci_spec::ConnectionHandle, Psm psm) {
463 auto iter = services_.find(psm);
464 if (iter == services_.end()) {
465 return std::nullopt;
466 }
467
468 // |channel_cb| will be called in LogicalLink. Each callback in |services_|
469 // already trampolines to the appropriate dispatcher (passed to
470 // RegisterService).
471 return ServiceInfo(iter->second.info.channel_params,
472 iter->second.info.channel_cb.share());
473 }
474
AttachInspect(inspect::Node & parent)475 void ChannelManagerImpl::ServiceData::AttachInspect(inspect::Node& parent) {
476 if (!parent) {
477 return;
478 }
479 node = parent.CreateChild(parent.UniqueName(kInspectServiceNodePrefix));
480 psm_property = node.CreateString(kInspectPsmPropertyName, PsmToString(psm));
481 }
482
Create(hci::AclDataChannel * acl_data_channel,hci::CommandChannel * cmd_channel,bool random_channel_ids,pw::async::Dispatcher & dispatcher)483 std::unique_ptr<ChannelManager> ChannelManager::Create(
484 hci::AclDataChannel* acl_data_channel,
485 hci::CommandChannel* cmd_channel,
486 bool random_channel_ids,
487 pw::async::Dispatcher& dispatcher) {
488 return std::make_unique<ChannelManagerImpl>(
489 acl_data_channel, cmd_channel, random_channel_ids, dispatcher);
490 }
491
492 } // namespace bt::l2cap
493