• 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/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