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