xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 <pw_bytes/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 EventPacket& 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   PW_DCHECK(transport_);
195   PW_CHECK(hci_);
196 
197   PW_DCHECK(bredr_buffer_info.IsAvailable() || le_buffer_info.IsAvailable());
198 
199   num_completed_packets_event_handler_id_ =
200       transport_->command_channel()->AddEventHandler(
201           hci_spec::kNumberOfCompletedPacketsEventCode,
202           fit::bind_member<
203               &AclDataChannelImpl::NumberOfCompletedPacketsCallback>(this));
204   PW_DCHECK(num_completed_packets_event_handler_id_);
205 
206   data_buffer_overflow_event_handler_id_ =
207       transport_->command_channel()->AddEventHandler(
208           hci_spec::kDataBufferOverflowEventCode,
209           fit::bind_member<&AclDataChannelImpl::DataBufferOverflowCallback>(
210               this));
211   PW_DCHECK(data_buffer_overflow_event_handler_id_);
212 
213   bt_log(DEBUG, "hci", "AclDataChannel initialized");
214 }
215 
~AclDataChannelImpl()216 AclDataChannelImpl::~AclDataChannelImpl() {
217   bt_log(INFO, "hci", "AclDataChannel shutting down");
218 
219   transport_->command_channel()->RemoveEventHandler(
220       num_completed_packets_event_handler_id_);
221   transport_->command_channel()->RemoveEventHandler(
222       data_buffer_overflow_event_handler_id_);
223 
224   hci_->SetReceiveAclFunction(nullptr);
225 }
226 
RegisterConnection(WeakPtr<ConnectionInterface> connection)227 void AclDataChannelImpl::RegisterConnection(
228     WeakPtr<ConnectionInterface> connection) {
229   bt_log(DEBUG,
230          "hci",
231          "ACL register connection (handle: %#.4x)",
232          connection->handle());
233   auto [_, inserted] =
234       registered_connections_.emplace(connection->handle(), connection);
235   PW_CHECK(inserted,
236            "connection with handle %#.4x already registered",
237            connection->handle());
238 
239   // Reset the round-robin iterators because they have been invalidated.
240   ResetRoundRobinIterators();
241 }
242 
UnregisterConnection(hci_spec::ConnectionHandle handle)243 void AclDataChannelImpl::UnregisterConnection(
244     hci_spec::ConnectionHandle handle) {
245   bt_log(DEBUG, "hci", "ACL unregister link (handle: %#.4x)", handle);
246   auto iter = registered_connections_.find(handle);
247   if (iter == registered_connections_.end()) {
248     bt_log(WARN,
249            "hci",
250            "attempt to unregister link that is not registered (handle: %#.4x)",
251            handle);
252     return;
253   }
254   registered_connections_.erase(iter);
255 
256   // Reset the round-robin iterators because they have been invalidated.
257   ResetRoundRobinIterators();
258 }
259 
IsBrEdrBufferShared() const260 bool AclDataChannelImpl::IsBrEdrBufferShared() const {
261   return !le_buffer_info_.IsAvailable();
262 }
263 
IncrementRoundRobinIterator(ConnectionMap::iterator & conn_iter,bt::LinkType connection_type)264 void AclDataChannelImpl::IncrementRoundRobinIterator(
265     ConnectionMap::iterator& conn_iter, bt::LinkType connection_type) {
266   // Only update iterator if |registered_connections_| is non-empty
267   if (conn_iter == registered_connections_.end()) {
268     bt_log(
269         DEBUG, "hci", "no registered connections, cannot increment iterator");
270     return;
271   }
272 
273   // Prevent infinite looping by tracking |original_conn_iter|
274   const ConnectionMap::iterator original_conn_iter = conn_iter;
275   do {
276     conn_iter++;
277     if (conn_iter == registered_connections_.end()) {
278       conn_iter = registered_connections_.begin();
279     }
280   } while (!IsBrEdrBufferShared() &&
281            conn_iter->second->type() != connection_type &&
282            conn_iter != original_conn_iter);
283 
284   // When buffer isn't shared, we must ensure |conn_iter| is assigned to a link
285   // of the same type.
286   if (!IsBrEdrBufferShared() && conn_iter->second->type() != connection_type) {
287     // There are no connections of |connection_type| in
288     // |registered_connections_|.
289     conn_iter = registered_connections_.end();
290   }
291 }
292 
IncrementPendingPacketsForLink(WeakPtr<ConnectionInterface> & connection)293 void AclDataChannelImpl::IncrementPendingPacketsForLink(
294     WeakPtr<ConnectionInterface>& connection) {
295   auto [iter, _] = pending_links_.try_emplace(
296       connection->handle(), PendingPacketData{connection->type()});
297   iter->second.count++;
298   IncrementPendingPacketsForLinkType(connection->type());
299 }
300 
SendPackets(ConnectionMap::iterator & current_link)301 void AclDataChannelImpl::SendPackets(ConnectionMap::iterator& current_link) {
302   PW_DCHECK(current_link != registered_connections_.end());
303   const ConnectionMap::iterator original_link = current_link;
304   const LinkType link_type = original_link->second->type();
305   size_t free_buffer_packets = GetNumFreePacketsForLinkType(link_type);
306   bool is_packet_queued = true;
307 
308   // Send packets as long as a link may have a packet queued and buffer space is
309   // available.
310   for (; free_buffer_packets != 0;
311        IncrementRoundRobinIterator(current_link, link_type)) {
312     if (current_link == original_link) {
313       if (!is_packet_queued) {
314         // All links are empty
315         break;
316       }
317       is_packet_queued = false;
318     }
319 
320     if (!current_link->second->HasAvailablePacket()) {
321       continue;
322     }
323 
324     // If there is an available packet, send and update packet counts
325     ACLDataPacketPtr packet = current_link->second->GetNextOutboundPacket();
326     PW_DCHECK(packet);
327     hci_->SendAclData(packet->view().data().subspan());
328 
329     is_packet_queued = true;
330     free_buffer_packets--;
331     IncrementPendingPacketsForLink(current_link->second);
332   }
333 }
334 
TrySendNextPackets()335 void AclDataChannelImpl::TrySendNextPackets() {
336   if (current_bredr_link_ != registered_connections_.end()) {
337     // If the BR/EDR buffer is shared, this will also send LE packets.
338     SendPackets(current_bredr_link_);
339   }
340 
341   if (!IsBrEdrBufferShared() &&
342       current_le_link_ != registered_connections_.end()) {
343     SendPackets(current_le_link_);
344   }
345 }
346 
OnOutboundPacketAvailable()347 void AclDataChannelImpl::OnOutboundPacketAvailable() { TrySendNextPackets(); }
348 
AttachInspect(inspect::Node & parent,const std::string & name)349 void AclDataChannelImpl::AttachInspect(inspect::Node& parent,
350                                        const std::string& name) {
351   node_ = parent.CreateChild(std::move(name));
352 
353   bredr_subnode_ = node_.CreateChild("bredr");
354   num_pending_bredr_packets_.AttachInspect(bredr_subnode_, "num_sent_packets");
355 
356   le_subnode_ = node_.CreateChild("le");
357   num_pending_le_packets_.AttachInspect(le_subnode_, "num_sent_packets");
358   le_subnode_shared_with_bredr_property_ =
359       le_subnode_.CreateBool("independent_from_bredr", !IsBrEdrBufferShared());
360 }
361 
SetDataRxHandler(ACLPacketHandler rx_callback)362 void AclDataChannelImpl::SetDataRxHandler(ACLPacketHandler rx_callback) {
363   PW_CHECK(rx_callback);
364   rx_callback_ = std::move(rx_callback);
365   hci_->SetReceiveAclFunction(
366       fit::bind_member<&AclDataChannelImpl::OnRxPacket>(this));
367 }
368 
ClearControllerPacketCount(hci_spec::ConnectionHandle handle)369 void AclDataChannelImpl::ClearControllerPacketCount(
370     hci_spec::ConnectionHandle handle) {
371   // Ensure link has already been unregistered. Otherwise, queued packets for
372   // this handle could be sent after clearing packet count, and the packet count
373   // could become corrupted.
374   PW_CHECK(registered_connections_.find(handle) ==
375            registered_connections_.end());
376 
377   bt_log(DEBUG, "hci", "clearing pending packets (handle: %#.4x)", handle);
378 
379   // subtract removed packets from sent packet counts, because controller does
380   // not send HCI Number of Completed Packets event for disconnected link
381   auto iter = pending_links_.find(handle);
382   if (iter == pending_links_.end()) {
383     bt_log(DEBUG,
384            "hci",
385            "no pending packets on connection (handle: %#.4x)",
386            handle);
387     return;
388   }
389 
390   const PendingPacketData& data = iter->second;
391   DecrementPendingPacketsForLinkType(data.ll_type, data.count);
392 
393   pending_links_.erase(iter);
394 
395   // Try sending the next batch of packets in case buffer space opened up.
396   TrySendNextPackets();
397 }
398 
GetBufferInfo() const399 const DataBufferInfo& AclDataChannelImpl::GetBufferInfo() const {
400   return bredr_buffer_info_;
401 }
402 
GetLeBufferInfo() const403 const DataBufferInfo& AclDataChannelImpl::GetLeBufferInfo() const {
404   return !IsBrEdrBufferShared() ? le_buffer_info_ : bredr_buffer_info_;
405 }
406 
RequestAclPriority(pw::bluetooth::AclPriority priority,hci_spec::ConnectionHandle handle,fit::callback<void (fit::result<fit::failed>)> callback)407 void AclDataChannelImpl::RequestAclPriority(
408     pw::bluetooth::AclPriority priority,
409     hci_spec::ConnectionHandle handle,
410     fit::callback<void(fit::result<fit::failed>)> callback) {
411   bt_log(TRACE, "hci", "sending ACL priority command");
412 
413   hci_->EncodeVendorCommand(
414       pw::bluetooth::SetAclPriorityCommandParameters{
415           .connection_handle = handle, .priority = priority},
416       [this, priority, request_cb = std::move(callback)](
417           pw::Result<pw::span<const std::byte>> encode_result) mutable {
418         if (!encode_result.ok()) {
419           bt_log(TRACE, "hci", "encoding ACL priority command failed");
420           request_cb(fit::failed());
421           return;
422         }
423 
424         DynamicByteBuffer encoded(
425             BufferView(encode_result->data(), encode_result->size()));
426         if (encoded.size() < sizeof(hci_spec::CommandHeader)) {
427           bt_log(TRACE,
428                  "hci",
429                  "encoded ACL priority command too small (size: %zu)",
430                  encoded.size());
431           request_cb(fit::failed());
432           return;
433         }
434 
435         hci_spec::OpCode op_code = pw::bytes::ConvertOrderFrom(
436             cpp20::endian::little,
437             encoded.ReadMember<&hci_spec::CommandHeader::opcode>());
438         auto packet =
439             CommandPacket::New<pw::bluetooth::emboss::GenericHciCommandWriter>(
440                 op_code, encoded.size());
441         auto packet_data = packet.mutable_data();
442         encoded.Copy(&packet_data);
443 
444         transport_->command_channel()->SendCommand(
445             std::move(packet),
446             [cb = std::move(request_cb), priority](
447                 auto, const hci::EventPacket& event) mutable {
448               if (HCI_IS_ERROR(event, WARN, "hci", "acl priority failed")) {
449                 cb(fit::failed());
450                 return;
451               }
452 
453               bt_log(DEBUG,
454                      "hci",
455                      "acl priority updated (priority: %#.8x)",
456                      static_cast<uint32_t>(priority));
457               cb(fit::ok());
458             });
459       });
460 }
461 
462 CommandChannel::EventCallbackResult
NumberOfCompletedPacketsCallback(const EventPacket & event)463 AclDataChannelImpl::NumberOfCompletedPacketsCallback(const EventPacket& event) {
464   if (event.size() <
465       pw::bluetooth::emboss::NumberOfCompletedPacketsEvent::MinSizeInBytes()) {
466     bt_log(ERROR,
467            "hci",
468            "Invalid HCI_Number_Of_Completed_Packets event received, ignoring");
469     return CommandChannel::EventCallbackResult::kContinue;
470   }
471   auto view = event.unchecked_view<
472       pw::bluetooth::emboss::NumberOfCompletedPacketsEventView>();
473   PW_CHECK(view.header().event_code_enum().Read() ==
474            pw::bluetooth::emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
475 
476   size_t handles_in_packet =
477       (event.size() -
478        pw::bluetooth::emboss::NumberOfCompletedPacketsEvent::MinSizeInBytes()) /
479       pw::bluetooth::emboss::NumberOfCompletedPacketsEventData::
480           IntrinsicSizeInBytes();
481   uint8_t expected_number_of_handles = view.num_handles().Read();
482   if (expected_number_of_handles != handles_in_packet) {
483     bt_log(WARN,
484            "hci",
485            "packets handle count (%d) doesn't match params size (%zu)",
486            expected_number_of_handles,
487            handles_in_packet);
488   }
489 
490   for (uint8_t i = 0; i < expected_number_of_handles && i < handles_in_packet;
491        ++i) {
492     uint16_t connection_handle = view.nocp_data()[i].connection_handle().Read();
493     uint16_t num_completed_packets =
494         view.nocp_data()[i].num_completed_packets().Read();
495     auto iter = pending_links_.find(connection_handle);
496     if (iter == pending_links_.end()) {
497       // This is expected if the completed packet is a SCO packet.
498       bt_log(TRACE,
499              "hci",
500              "controller reported completed packets for connection handle "
501              "without pending packets: "
502              "%#.4x",
503              connection_handle);
504       continue;
505     }
506 
507     if (iter->second.count < num_completed_packets) {
508       // TODO(fxbug.dev/42102535): This can be caused by the controller
509       // reusing the connection handle of a connection that just disconnected.
510       // We should somehow avoid sending the controller packets for a connection
511       // that has disconnected. AclDataChannel already dequeues such packets,
512       // but this is insufficient: packets can be queued in the channel to the
513       // transport driver, and possibly in the transport driver or USB/UART
514       // drivers.
515       bt_log(ERROR,
516              "hci",
517              "ACL packet tx count mismatch! (handle: %#.4x, expected: %zu, "
518              "actual : %u)",
519              connection_handle,
520              iter->second.count,
521              num_completed_packets);
522       // This should eventually result in convergence with the correct pending
523       // packet count. If it undercounts the true number of pending packets,
524       // this branch will be reached again when the controller sends an updated
525       // Number of Completed Packets event. However, AclDataChannel may overflow
526       // the controller's buffer in the meantime!
527       num_completed_packets = static_cast<uint16_t>(iter->second.count);
528     }
529 
530     iter->second.count -= num_completed_packets;
531     DecrementPendingPacketsForLinkType(iter->second.ll_type,
532                                        num_completed_packets);
533     if (!iter->second.count) {
534       pending_links_.erase(iter);
535     }
536   }
537 
538   TrySendNextPackets();
539 
540   return CommandChannel::EventCallbackResult::kContinue;
541 }
542 
GetNumFreePacketsForLinkType(LinkType link_type) const543 size_t AclDataChannelImpl::GetNumFreePacketsForLinkType(
544     LinkType link_type) const {
545   if (link_type == LinkType::kACL || IsBrEdrBufferShared()) {
546     PW_DCHECK(bredr_buffer_info_.max_num_packets() >=
547               *num_pending_bredr_packets_);
548     return bredr_buffer_info_.max_num_packets() - *num_pending_bredr_packets_;
549   } else if (link_type == LinkType::kLE) {
550     PW_DCHECK(le_buffer_info_.max_num_packets() >= *num_pending_le_packets_);
551     return le_buffer_info_.max_num_packets() - *num_pending_le_packets_;
552   }
553   return 0;
554 }
555 
DecrementPendingPacketsForLinkType(LinkType link_type,size_t count)556 void AclDataChannelImpl::DecrementPendingPacketsForLinkType(LinkType link_type,
557                                                             size_t count) {
558   if (link_type == LinkType::kACL || IsBrEdrBufferShared()) {
559     PW_DCHECK(*num_pending_bredr_packets_ >= count);
560     *num_pending_bredr_packets_.Mutable() -= count;
561   } else if (link_type == LinkType::kLE) {
562     PW_DCHECK(*num_pending_le_packets_ >= count);
563     *num_pending_le_packets_.Mutable() -= count;
564   }
565 }
566 
IncrementPendingPacketsForLinkType(LinkType link_type)567 void AclDataChannelImpl::IncrementPendingPacketsForLinkType(
568     LinkType link_type) {
569   if (link_type == LinkType::kACL || IsBrEdrBufferShared()) {
570     *num_pending_bredr_packets_.Mutable() += 1;
571     PW_DCHECK(*num_pending_bredr_packets_ <=
572               bredr_buffer_info_.max_num_packets());
573   } else if (link_type == LinkType::kLE) {
574     *num_pending_le_packets_.Mutable() += 1;
575     PW_DCHECK(*num_pending_le_packets_ <= le_buffer_info_.max_num_packets());
576   }
577 }
578 
OnRxPacket(pw::span<const std::byte> buffer)579 void AclDataChannelImpl::OnRxPacket(pw::span<const std::byte> buffer) {
580   PW_CHECK(rx_callback_);
581 
582   if (buffer.size() < sizeof(hci_spec::ACLDataHeader)) {
583     // TODO(fxbug.dev/42179582): Handle these types of errors by signaling
584     // Transport.
585     bt_log(ERROR,
586            "hci",
587            "malformed packet - expected at least %zu bytes, got %zu",
588            sizeof(hci_spec::ACLDataHeader),
589            buffer.size());
590     return;
591   }
592 
593   const size_t payload_size = buffer.size() - sizeof(hci_spec::ACLDataHeader);
594 
595   ACLDataPacketPtr packet =
596       ACLDataPacket::New(static_cast<uint16_t>(payload_size));
597   packet->mutable_view()->mutable_data().Write(
598       reinterpret_cast<const uint8_t*>(buffer.data()), buffer.size());
599   packet->InitializeFromBuffer();
600 
601   if (packet->view().header().data_total_length != payload_size) {
602     // TODO(fxbug.dev/42179582): Handle these types of errors by signaling
603     // Transport.
604     bt_log(ERROR,
605            "hci",
606            "malformed packet - payload size from header (%hu) does not match"
607            " received payload size: %zu",
608            packet->view().header().data_total_length,
609            payload_size);
610     return;
611   }
612 
613   {
614     TRACE_DURATION("bluetooth", "AclDataChannelImpl->rx_callback_");
615     rx_callback_(std::move(packet));
616   }
617 }
618 
619 CommandChannel::EventCallbackResult
DataBufferOverflowCallback(const EventPacket & event)620 AclDataChannelImpl::DataBufferOverflowCallback(const EventPacket& event) {
621   const auto params =
622       event.view<pw::bluetooth::emboss::DataBufferOverflowEventView>();
623 
624   // Internal buffer state must be invalid and no further transmissions are
625   // possible.
626   BT_PANIC("controller data buffer overflow event received (link type: %s)",
627            hci_spec::LinkTypeToString(params.ll_type().Read()));
628 
629   return CommandChannel::EventCallbackResult::kContinue;
630 }
631 
ResetRoundRobinIterators()632 void AclDataChannelImpl::ResetRoundRobinIterators() {
633   current_bredr_link_ = registered_connections_.begin();
634 
635   // If the BR/EDR buffer isn't shared, we need to do extra work to ensure
636   // |current_bredr_link_| is initialized to a link of BR/EDR type. The same
637   // applies for |current_le_link_|.
638   if (!IsBrEdrBufferShared()) {
639     current_le_link_ = registered_connections_.begin();
640 
641     IncrementRoundRobinIterator(current_bredr_link_, bt::LinkType::kACL);
642     IncrementRoundRobinIterator(current_le_link_, bt::LinkType::kLE);
643   }
644 }
645 
646 }  // namespace bt::hci
647