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