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/transport/acl_data_channel.h"
16
17 #include <endian.h>
18
19 #include <iterator>
20
21 #include "lib/fit/function.h"
22 #include "pw_bluetooth/vendor.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
24 #include "pw_bluetooth_sapphire/internal/host/common/inspectable.h"
25 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
26 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
27 #include "pw_bluetooth_sapphire/internal/host/transport/acl_data_packet.h"
28 #include "pw_bluetooth_sapphire/internal/host/transport/link_type.h"
29 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
30
31 namespace bt::hci {
32
33 class AclDataChannelImpl final : public AclDataChannel {
34 public:
35 AclDataChannelImpl(Transport* transport,
36 pw::bluetooth::Controller* hci,
37 const DataBufferInfo& bredr_buffer_info,
38 const DataBufferInfo& le_buffer_info);
39 ~AclDataChannelImpl() override;
40
41 // AclDataChannel overrides:
42 void RegisterConnection(WeakPtr<ConnectionInterface> connection) override;
43 void UnregisterConnection(hci_spec::ConnectionHandle handle) override;
44 void OnOutboundPacketAvailable() override;
45 void AttachInspect(inspect::Node& parent, const std::string& name) override;
46 void SetDataRxHandler(ACLPacketHandler rx_callback) override;
47 void ClearControllerPacketCount(hci_spec::ConnectionHandle handle) override;
48 const DataBufferInfo& GetBufferInfo() const override;
49 const DataBufferInfo& GetLeBufferInfo() const override;
50 void RequestAclPriority(
51 pw::bluetooth::AclPriority priority,
52 hci_spec::ConnectionHandle handle,
53 fit::callback<void(fit::result<fit::failed>)> callback) override;
54
55 private:
56 using ConnectionMap = std::unordered_map<hci_spec::ConnectionHandle,
57 WeakPtr<ConnectionInterface>>;
58
59 struct PendingPacketData {
60 bt::LinkType ll_type = bt::LinkType::kACL;
61 size_t count = 0;
62 };
63
64 // Handler for the HCI Number of Completed Packets Event, used for
65 // packet-based data flow control.
66 CommandChannel::EventCallbackResult NumberOfCompletedPacketsCallback(
67 const EventPacket& event);
68
69 // Sends next queued packets over the ACL data channel while the controller
70 // has free buffer slots. If controller buffers are free and some links have
71 // queued packets, we round-robin iterate through links, sending a packet from
72 // each link with queued packets until the controller is full or we run out of
73 // packets.
74 void TrySendNextPackets();
75
76 // Returns the number of free controller buffer slots for packets of type
77 // |link_type|, taking shared buffers into account.
78 size_t GetNumFreePacketsForLinkType(LinkType link_type) const;
79
80 // Decreases the |link_type| pending packets count by |count|, taking shared
81 // buffers into account.
82 void DecrementPendingPacketsForLinkType(LinkType link_type, size_t count);
83
84 // Increments the pending packets count for links of type |link_type|, taking
85 // shared buffers into account.
86 void IncrementPendingPacketsForLinkType(LinkType link_type);
87
88 // Returns true if the LE data buffer is not available
89 bool IsBrEdrBufferShared() const;
90
91 // Called when a packet is received from the controller. Validates the packet
92 // and calls the client's RX callback.
93 void OnRxPacket(pw::span<const std::byte> packet);
94
95 // Increment connection iterators using round robin scheduling.
96 // If the BR/EDR buffer is shared, simply increment the iterator to the next
97 // connection. If the BR/EDR buffer isn't shared, increment the iterator to
98 // the next connection of type |connection_type|. No-op if |conn_iter| is
99 // |registered_connections_.end()|.
100 void IncrementRoundRobinIterator(ConnectionMap::iterator& conn_iter,
101 bt::LinkType connection_type);
102
103 // Increments count of pending packets that have been sent to the controller
104 // on |connection|.
105 void IncrementPendingPacketsForLink(WeakPtr<ConnectionInterface>& connection);
106
107 // Sends queued packets from links in a round-robin fashion, starting with
108 // |current_link|. |current_link| will be incremented to the next link that
109 // should send packets (according to the round-robin policy).
110 void SendPackets(ConnectionMap::iterator& current_link);
111
112 // Handler for HCI_Buffer_Overflow_event.
113 CommandChannel::EventCallbackResult DataBufferOverflowCallback(
114 const EmbossEventPacket& event);
115
116 void ResetRoundRobinIterators();
117
118 // Links this node to the inspect tree. Initialized as needed by
119 // AttachInspect.
120 inspect::Node node_;
121
122 // Contents of |node_|. Retained as members so that they last as long as a
123 // class instance.
124 inspect::Node le_subnode_;
125 inspect::BoolProperty le_subnode_shared_with_bredr_property_;
126 inspect::Node bredr_subnode_;
127
128 // The Transport object that owns this instance.
129 Transport* const transport_; // weak;
130
131 // Controller is owned by Transport and will outlive this object.
132 pw::bluetooth::Controller* const hci_;
133
134 // The event handler ID for the Number Of Completed Packets event.
135 CommandChannel::EventHandlerId num_completed_packets_event_handler_id_ = 0;
136
137 // The event handler ID for the Data Buffer Overflow event.
138 CommandChannel::EventHandlerId data_buffer_overflow_event_handler_id_ = 0;
139
140 // The current handler for incoming data.
141 ACLPacketHandler rx_callback_;
142
143 // BR/EDR data buffer information. This buffer will not be available on
144 // LE-only controllers.
145 const DataBufferInfo bredr_buffer_info_;
146
147 // LE data buffer information. This buffer will not be available on
148 // BR/EDR-only controllers (which we do not support) and MAY be available on
149 // dual-mode controllers. We maintain that if this buffer is not available,
150 // then the BR/EDR buffer MUST be available.
151 const DataBufferInfo le_buffer_info_;
152
153 // The current count of the number of ACL data packets that have been sent to
154 // the controller. |num_pending_le_packets_| is ignored if the controller uses
155 // one buffer for LE and BR/EDR.
156 UintInspectable<size_t> num_pending_bredr_packets_;
157 UintInspectable<size_t> num_pending_le_packets_;
158
159 // Stores per-connection information of unacknowledged packets sent to the
160 // controller. Entries are updated/removed on the HCI Number Of Completed
161 // Packets event and when a connection is unregistered (the controller does
162 // not acknowledge packets of disconnected links).
163 std::unordered_map<hci_spec::ConnectionHandle, PendingPacketData>
164 pending_links_;
165
166 // Stores connections registered by RegisterConnection().
167 ConnectionMap registered_connections_;
168
169 // Iterators used to round-robin through links for sending packets. When the
170 // BR/EDR buffer is shared with LE, |current_le_link_| is ignored
171 ConnectionMap::iterator current_bredr_link_ = registered_connections_.end();
172 ConnectionMap::iterator current_le_link_ = registered_connections_.end();
173
174 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AclDataChannelImpl);
175 };
176
Create(Transport * transport,pw::bluetooth::Controller * hci,const DataBufferInfo & bredr_buffer_info,const DataBufferInfo & le_buffer_info)177 std::unique_ptr<AclDataChannel> AclDataChannel::Create(
178 Transport* transport,
179 pw::bluetooth::Controller* hci,
180 const DataBufferInfo& bredr_buffer_info,
181 const DataBufferInfo& le_buffer_info) {
182 return std::make_unique<AclDataChannelImpl>(
183 transport, hci, bredr_buffer_info, le_buffer_info);
184 }
185
AclDataChannelImpl(Transport * transport,pw::bluetooth::Controller * hci,const DataBufferInfo & bredr_buffer_info,const DataBufferInfo & le_buffer_info)186 AclDataChannelImpl::AclDataChannelImpl(Transport* transport,
187 pw::bluetooth::Controller* hci,
188 const DataBufferInfo& bredr_buffer_info,
189 const DataBufferInfo& le_buffer_info)
190 : transport_(transport),
191 hci_(hci),
192 bredr_buffer_info_(bredr_buffer_info),
193 le_buffer_info_(le_buffer_info) {
194 BT_DEBUG_ASSERT(transport_);
195 BT_ASSERT(hci_);
196
197 BT_DEBUG_ASSERT(bredr_buffer_info.IsAvailable() ||
198 le_buffer_info.IsAvailable());
199
200 num_completed_packets_event_handler_id_ =
201 transport_->command_channel()->AddEventHandler(
202 hci_spec::kNumberOfCompletedPacketsEventCode,
203 fit::bind_member<
204 &AclDataChannelImpl::NumberOfCompletedPacketsCallback>(this));
205 BT_DEBUG_ASSERT(num_completed_packets_event_handler_id_);
206
207 data_buffer_overflow_event_handler_id_ =
208 transport_->command_channel()->AddEventHandler(
209 hci_spec::kDataBufferOverflowEventCode,
210 fit::bind_member<&AclDataChannelImpl::DataBufferOverflowCallback>(
211 this));
212 BT_DEBUG_ASSERT(data_buffer_overflow_event_handler_id_);
213
214 bt_log(DEBUG, "hci", "AclDataChannel initialized");
215 }
216
~AclDataChannelImpl()217 AclDataChannelImpl::~AclDataChannelImpl() {
218 bt_log(INFO, "hci", "AclDataChannel shutting down");
219
220 transport_->command_channel()->RemoveEventHandler(
221 num_completed_packets_event_handler_id_);
222 transport_->command_channel()->RemoveEventHandler(
223 data_buffer_overflow_event_handler_id_);
224
225 hci_->SetReceiveAclFunction(nullptr);
226 }
227
RegisterConnection(WeakPtr<ConnectionInterface> connection)228 void AclDataChannelImpl::RegisterConnection(
229 WeakPtr<ConnectionInterface> connection) {
230 bt_log(DEBUG,
231 "hci",
232 "ACL register connection (handle: %#.4x)",
233 connection->handle());
234 auto [_, inserted] =
235 registered_connections_.emplace(connection->handle(), connection);
236 BT_ASSERT_MSG(inserted,
237 "connection with handle %#.4x already registered",
238 connection->handle());
239
240 // Reset the round-robin iterators because they have been invalidated.
241 ResetRoundRobinIterators();
242 }
243
UnregisterConnection(hci_spec::ConnectionHandle handle)244 void AclDataChannelImpl::UnregisterConnection(
245 hci_spec::ConnectionHandle handle) {
246 bt_log(DEBUG, "hci", "ACL unregister link (handle: %#.4x)", handle);
247 auto iter = registered_connections_.find(handle);
248 if (iter == registered_connections_.end()) {
249 bt_log(WARN,
250 "hci",
251 "attempt to unregister link that is not registered (handle: %#.4x)",
252 handle);
253 return;
254 }
255 registered_connections_.erase(iter);
256
257 // Reset the round-robin iterators because they have been invalidated.
258 ResetRoundRobinIterators();
259 }
260
IsBrEdrBufferShared() const261 bool AclDataChannelImpl::IsBrEdrBufferShared() const {
262 return !le_buffer_info_.IsAvailable();
263 }
264
IncrementRoundRobinIterator(ConnectionMap::iterator & conn_iter,bt::LinkType connection_type)265 void AclDataChannelImpl::IncrementRoundRobinIterator(
266 ConnectionMap::iterator& conn_iter, bt::LinkType connection_type) {
267 // Only update iterator if |registered_connections_| is non-empty
268 if (conn_iter == registered_connections_.end()) {
269 bt_log(
270 DEBUG, "hci", "no registered connections, cannot increment iterator");
271 return;
272 }
273
274 // Prevent infinite looping by tracking |original_conn_iter|
275 const ConnectionMap::iterator original_conn_iter = conn_iter;
276 do {
277 conn_iter++;
278 if (conn_iter == registered_connections_.end()) {
279 conn_iter = registered_connections_.begin();
280 }
281 } while (!IsBrEdrBufferShared() &&
282 conn_iter->second->type() != connection_type &&
283 conn_iter != original_conn_iter);
284
285 // When buffer isn't shared, we must ensure |conn_iter| is assigned to a link
286 // of the same type.
287 if (!IsBrEdrBufferShared() && conn_iter->second->type() != connection_type) {
288 // There are no connections of |connection_type| in
289 // |registered_connections_|.
290 conn_iter = registered_connections_.end();
291 }
292 }
293
IncrementPendingPacketsForLink(WeakPtr<ConnectionInterface> & connection)294 void AclDataChannelImpl::IncrementPendingPacketsForLink(
295 WeakPtr<ConnectionInterface>& connection) {
296 auto [iter, _] = pending_links_.try_emplace(
297 connection->handle(), PendingPacketData{connection->type()});
298 iter->second.count++;
299 IncrementPendingPacketsForLinkType(connection->type());
300 }
301
SendPackets(ConnectionMap::iterator & current_link)302 void AclDataChannelImpl::SendPackets(ConnectionMap::iterator& current_link) {
303 BT_DEBUG_ASSERT(current_link != registered_connections_.end());
304 const ConnectionMap::iterator original_link = current_link;
305 const LinkType link_type = original_link->second->type();
306 size_t free_buffer_packets = GetNumFreePacketsForLinkType(link_type);
307 bool is_packet_queued = true;
308
309 // Send packets as long as a link may have a packet queued and buffer space is
310 // available.
311 for (; free_buffer_packets != 0;
312 IncrementRoundRobinIterator(current_link, link_type)) {
313 if (current_link == original_link) {
314 if (!is_packet_queued) {
315 // All links are empty
316 break;
317 }
318 is_packet_queued = false;
319 }
320
321 if (!current_link->second->HasAvailablePacket()) {
322 continue;
323 }
324
325 // If there is an available packet, send and update packet counts
326 ACLDataPacketPtr packet = current_link->second->GetNextOutboundPacket();
327 BT_DEBUG_ASSERT(packet);
328 hci_->SendAclData(packet->view().data().subspan());
329
330 is_packet_queued = true;
331 free_buffer_packets--;
332 IncrementPendingPacketsForLink(current_link->second);
333 }
334 }
335
TrySendNextPackets()336 void AclDataChannelImpl::TrySendNextPackets() {
337 if (current_bredr_link_ != registered_connections_.end()) {
338 // If the BR/EDR buffer is shared, this will also send LE packets.
339 SendPackets(current_bredr_link_);
340 }
341
342 if (!IsBrEdrBufferShared() &&
343 current_le_link_ != registered_connections_.end()) {
344 SendPackets(current_le_link_);
345 }
346 }
347
OnOutboundPacketAvailable()348 void AclDataChannelImpl::OnOutboundPacketAvailable() { TrySendNextPackets(); }
349
AttachInspect(inspect::Node & parent,const std::string & name)350 void AclDataChannelImpl::AttachInspect(inspect::Node& parent,
351 const std::string& name) {
352 node_ = parent.CreateChild(std::move(name));
353
354 bredr_subnode_ = node_.CreateChild("bredr");
355 num_pending_bredr_packets_.AttachInspect(bredr_subnode_, "num_sent_packets");
356
357 le_subnode_ = node_.CreateChild("le");
358 num_pending_le_packets_.AttachInspect(le_subnode_, "num_sent_packets");
359 le_subnode_shared_with_bredr_property_ =
360 le_subnode_.CreateBool("independent_from_bredr", !IsBrEdrBufferShared());
361 }
362
SetDataRxHandler(ACLPacketHandler rx_callback)363 void AclDataChannelImpl::SetDataRxHandler(ACLPacketHandler rx_callback) {
364 BT_ASSERT(rx_callback);
365 rx_callback_ = std::move(rx_callback);
366 hci_->SetReceiveAclFunction(
367 fit::bind_member<&AclDataChannelImpl::OnRxPacket>(this));
368 }
369
ClearControllerPacketCount(hci_spec::ConnectionHandle handle)370 void AclDataChannelImpl::ClearControllerPacketCount(
371 hci_spec::ConnectionHandle handle) {
372 // Ensure link has already been unregistered. Otherwise, queued packets for
373 // this handle could be sent after clearing packet count, and the packet count
374 // could become corrupted.
375 BT_ASSERT(registered_connections_.find(handle) ==
376 registered_connections_.end());
377
378 bt_log(DEBUG, "hci", "clearing pending packets (handle: %#.4x)", handle);
379
380 // subtract removed packets from sent packet counts, because controller does
381 // not send HCI Number of Completed Packets event for disconnected link
382 auto iter = pending_links_.find(handle);
383 if (iter == pending_links_.end()) {
384 bt_log(DEBUG,
385 "hci",
386 "no pending packets on connection (handle: %#.4x)",
387 handle);
388 return;
389 }
390
391 const PendingPacketData& data = iter->second;
392 DecrementPendingPacketsForLinkType(data.ll_type, data.count);
393
394 pending_links_.erase(iter);
395
396 // Try sending the next batch of packets in case buffer space opened up.
397 TrySendNextPackets();
398 }
399
GetBufferInfo() const400 const DataBufferInfo& AclDataChannelImpl::GetBufferInfo() const {
401 return bredr_buffer_info_;
402 }
403
GetLeBufferInfo() const404 const DataBufferInfo& AclDataChannelImpl::GetLeBufferInfo() const {
405 return !IsBrEdrBufferShared() ? le_buffer_info_ : bredr_buffer_info_;
406 }
407
RequestAclPriority(pw::bluetooth::AclPriority priority,hci_spec::ConnectionHandle handle,fit::callback<void (fit::result<fit::failed>)> callback)408 void AclDataChannelImpl::RequestAclPriority(
409 pw::bluetooth::AclPriority priority,
410 hci_spec::ConnectionHandle handle,
411 fit::callback<void(fit::result<fit::failed>)> callback) {
412 bt_log(TRACE, "hci", "sending ACL priority command");
413
414 hci_->EncodeVendorCommand(
415 pw::bluetooth::SetAclPriorityCommandParameters{
416 .connection_handle = handle, .priority = priority},
417 [this, priority, callback = std::move(callback)](
418 pw::Result<pw::span<const std::byte>> encode_result) mutable {
419 if (!encode_result.ok()) {
420 bt_log(TRACE, "hci", "encoding ACL priority command failed");
421 callback(fit::failed());
422 return;
423 }
424
425 DynamicByteBuffer encoded(
426 BufferView(encode_result->data(), encode_result->size()));
427 if (encoded.size() < sizeof(hci_spec::CommandHeader)) {
428 bt_log(TRACE,
429 "hci",
430 "encoded ACL priority command too small (size: %zu)",
431 encoded.size());
432 callback(fit::failed());
433 return;
434 }
435
436 hci_spec::OpCode op_code =
437 le16toh(encoded.ReadMember<&hci_spec::CommandHeader::opcode>());
438 auto packet = bt::hci::CommandPacket::New(
439 op_code, encoded.size() - sizeof(hci_spec::CommandHeader));
440 auto packet_view = packet->mutable_view()->mutable_data();
441 encoded.Copy(&packet_view);
442
443 transport_->command_channel()->SendCommand(
444 std::move(packet),
445 [cb = std::move(callback), priority](
446 auto id, const hci::EventPacket& event) mutable {
447 if (hci_is_error(event, WARN, "hci", "acl priority failed")) {
448 cb(fit::failed());
449 return;
450 }
451
452 bt_log(DEBUG,
453 "hci",
454 "acl priority updated (priority: %#.8x)",
455 static_cast<uint32_t>(priority));
456 cb(fit::ok());
457 });
458 });
459 }
460
461 CommandChannel::EventCallbackResult
NumberOfCompletedPacketsCallback(const EventPacket & event)462 AclDataChannelImpl::NumberOfCompletedPacketsCallback(const EventPacket& event) {
463 BT_DEBUG_ASSERT(event.event_code() ==
464 hci_spec::kNumberOfCompletedPacketsEventCode);
465 const auto& payload =
466 event.params<hci_spec::NumberOfCompletedPacketsEventParams>();
467
468 size_t handles_in_packet =
469 (event.view().payload_size() -
470 sizeof(hci_spec::NumberOfCompletedPacketsEventParams)) /
471 sizeof(hci_spec::NumberOfCompletedPacketsEventData);
472
473 if (payload.number_of_handles != handles_in_packet) {
474 bt_log(WARN,
475 "hci",
476 "packets handle count (%d) doesn't match params size (%zu)",
477 payload.number_of_handles,
478 handles_in_packet);
479 }
480
481 for (uint8_t i = 0; i < payload.number_of_handles && i < handles_in_packet;
482 ++i) {
483 const hci_spec::NumberOfCompletedPacketsEventData* data = payload.data + i;
484
485 auto iter = pending_links_.find(le16toh(data->connection_handle));
486 if (iter == pending_links_.end()) {
487 // This is expected if the completed packet is a SCO packet.
488 bt_log(TRACE,
489 "hci",
490 "controller reported completed packets for connection handle "
491 "without pending packets: "
492 "%#.4x",
493 data->connection_handle);
494 continue;
495 }
496
497 uint16_t comp_packets = le16toh(data->hc_num_of_completed_packets);
498
499 if (iter->second.count < comp_packets) {
500 // TODO(fxbug.dev/42102535): This can be caused by the controller reusing
501 // the connection handle of a connection that just disconnected. We should
502 // somehow avoid sending the controller packets for a connection that has
503 // disconnected. AclDataChannel already dequeues such packets, but this is
504 // insufficient: packets can be queued in the channel to the transport
505 // driver, and possibly in the transport driver or USB/UART drivers.
506 bt_log(ERROR,
507 "hci",
508 "ACL packet tx count mismatch! (handle: %#.4x, expected: %zu, "
509 "actual : %u)",
510 le16toh(data->connection_handle),
511 iter->second.count,
512 comp_packets);
513 // This should eventually result in convergence with the correct pending
514 // packet count. If it undercounts the true number of pending packets,
515 // this branch will be reached again when the controller sends an updated
516 // Number of Completed Packets event. However, AclDataChannel may overflow
517 // the controller's buffer in the meantime!
518 comp_packets = static_cast<uint16_t>(iter->second.count);
519 }
520
521 iter->second.count -= comp_packets;
522 DecrementPendingPacketsForLinkType(iter->second.ll_type, comp_packets);
523 if (!iter->second.count) {
524 pending_links_.erase(iter);
525 }
526 }
527
528 TrySendNextPackets();
529
530 return CommandChannel::EventCallbackResult::kContinue;
531 }
532
GetNumFreePacketsForLinkType(LinkType link_type) const533 size_t AclDataChannelImpl::GetNumFreePacketsForLinkType(
534 LinkType link_type) const {
535 if (link_type == LinkType::kACL || IsBrEdrBufferShared()) {
536 BT_DEBUG_ASSERT(bredr_buffer_info_.max_num_packets() >=
537 *num_pending_bredr_packets_);
538 return bredr_buffer_info_.max_num_packets() - *num_pending_bredr_packets_;
539 } else if (link_type == LinkType::kLE) {
540 BT_DEBUG_ASSERT(le_buffer_info_.max_num_packets() >=
541 *num_pending_le_packets_);
542 return le_buffer_info_.max_num_packets() - *num_pending_le_packets_;
543 }
544 return 0;
545 }
546
DecrementPendingPacketsForLinkType(LinkType link_type,size_t count)547 void AclDataChannelImpl::DecrementPendingPacketsForLinkType(LinkType link_type,
548 size_t count) {
549 if (link_type == LinkType::kACL || IsBrEdrBufferShared()) {
550 BT_DEBUG_ASSERT(*num_pending_bredr_packets_ >= count);
551 *num_pending_bredr_packets_.Mutable() -= count;
552 } else if (link_type == LinkType::kLE) {
553 BT_DEBUG_ASSERT(*num_pending_le_packets_ >= count);
554 *num_pending_le_packets_.Mutable() -= count;
555 }
556 }
557
IncrementPendingPacketsForLinkType(LinkType link_type)558 void AclDataChannelImpl::IncrementPendingPacketsForLinkType(
559 LinkType link_type) {
560 if (link_type == LinkType::kACL || IsBrEdrBufferShared()) {
561 *num_pending_bredr_packets_.Mutable() += 1;
562 BT_DEBUG_ASSERT(*num_pending_bredr_packets_ <=
563 bredr_buffer_info_.max_num_packets());
564 } else if (link_type == LinkType::kLE) {
565 *num_pending_le_packets_.Mutable() += 1;
566 BT_DEBUG_ASSERT(*num_pending_le_packets_ <=
567 le_buffer_info_.max_num_packets());
568 }
569 }
570
OnRxPacket(pw::span<const std::byte> buffer)571 void AclDataChannelImpl::OnRxPacket(pw::span<const std::byte> buffer) {
572 BT_ASSERT(rx_callback_);
573
574 if (buffer.size() < sizeof(hci_spec::ACLDataHeader)) {
575 // TODO(fxbug.dev/42179582): Handle these types of errors by signaling
576 // Transport.
577 bt_log(ERROR,
578 "hci",
579 "malformed packet - expected at least %zu bytes, got %zu",
580 sizeof(hci_spec::ACLDataHeader),
581 buffer.size());
582 return;
583 }
584
585 const size_t payload_size = buffer.size() - sizeof(hci_spec::ACLDataHeader);
586
587 ACLDataPacketPtr packet =
588 ACLDataPacket::New(static_cast<uint16_t>(payload_size));
589 packet->mutable_view()->mutable_data().Write(
590 reinterpret_cast<const uint8_t*>(buffer.data()), buffer.size());
591 packet->InitializeFromBuffer();
592
593 if (packet->view().header().data_total_length != payload_size) {
594 // TODO(fxbug.dev/42179582): Handle these types of errors by signaling
595 // Transport.
596 bt_log(ERROR,
597 "hci",
598 "malformed packet - payload size from header (%hu) does not match"
599 " received payload size: %zu",
600 packet->view().header().data_total_length,
601 payload_size);
602 return;
603 }
604
605 {
606 TRACE_DURATION("bluetooth", "AclDataChannelImpl->rx_callback_");
607 rx_callback_(std::move(packet));
608 }
609 }
610
611 CommandChannel::EventCallbackResult
DataBufferOverflowCallback(const EmbossEventPacket & event)612 AclDataChannelImpl::DataBufferOverflowCallback(const EmbossEventPacket& event) {
613 const auto params =
614 event.view<pw::bluetooth::emboss::DataBufferOverflowEventView>();
615
616 // Internal buffer state must be invalid and no further transmissions are
617 // possible.
618 BT_PANIC("controller data buffer overflow event received (link type: %s)",
619 hci_spec::LinkTypeToString(params.ll_type().Read()));
620
621 return CommandChannel::EventCallbackResult::kContinue;
622 }
623
ResetRoundRobinIterators()624 void AclDataChannelImpl::ResetRoundRobinIterators() {
625 current_bredr_link_ = registered_connections_.begin();
626
627 // If the BR/EDR buffer isn't shared, we need to do extra work to ensure
628 // |current_bredr_link_| is initialized to a link of BR/EDR type. The same
629 // applies for |current_le_link_|.
630 if (!IsBrEdrBufferShared()) {
631 current_le_link_ = registered_connections_.begin();
632
633 IncrementRoundRobinIterator(current_bredr_link_, bt::LinkType::kACL);
634 IncrementRoundRobinIterator(current_le_link_, bt::LinkType::kLE);
635 }
636 }
637
638 } // namespace bt::hci
639