[bt][transport] Remove use of zx_packet_signal::count

Remove use of zx_packet_signal::count in CommandChannel, AclDataChannel,
and ScoDataChannel. This field is deprecated and hardcoded to 1 for
channel signals.

Bug: 50601
Test: fx test bt-host-transport-tests
Change-Id: I13f53119a5b40d2feb12a8fba44babd61eb3c7da
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/664386
Reviewed-by: Xo Wang <xow@google.com>
Commit-Queue: Ben Lawson <benlawson@google.com>
diff --git a/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc b/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc
index 31dd407..31dade1 100644
--- a/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc
+++ b/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc
@@ -7,6 +7,7 @@
 #include <endian.h>
 #include <lib/async/cpp/time.h>
 #include <lib/async/default.h>
+#include <lib/fit/defer.h>
 #include <lib/sys/inspect/cpp/component.h>
 #include <zircon/assert.h>
 #include <zircon/status.h>
@@ -874,33 +875,39 @@
   ZX_DEBUG_ASSERT(async_get_default_dispatcher() == io_dispatcher_);
   ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_READABLE);
 
-  for (size_t count = 0; count < signal->count; count++) {
-    TRACE_DURATION("bluetooth", "AclDataChannelImpl::OnChannelReady read packet");
-    if (!rx_callback_) {
-      continue;
+  // The wait needs to be restarted after every signal.
+  auto defer_wait = fit::defer([wait, dispatcher] {
+    zx_status_t status = wait->Begin(dispatcher);
+    if (status != ZX_OK) {
+      bt_log(ERROR, "hci", "wait error: %s", zx_status_get_string(status));
     }
-    // Allocate a buffer for the event. Since we don't know the size beforehand
-    // we allocate the largest possible buffer.
-    auto packet = ACLDataPacket::New(slab_allocators::kLargeACLDataPayloadSize);
-    if (!packet) {
-      bt_log(ERROR, "hci", "failed to allocate buffer received ACL data packet!");
-      return;
-    }
-    zx_status_t status = ReadAclDataPacketFromChannel(channel_, packet);
-    if (status == ZX_ERR_INVALID_ARGS) {
-      continue;
-    } else if (status != ZX_OK) {
-      return;
-    }
-    {
-      TRACE_DURATION("bluetooth", "AclDataChannelImpl->rx_callback_");
-      rx_callback_(std::move(packet));
-    }
+  });
+
+  if (!rx_callback_) {
+    return;
   }
 
-  status = wait->Begin(dispatcher);
+  // Allocate a buffer for the event. Since we don't know the size beforehand
+  // we allocate the largest possible buffer.
+  auto packet = ACLDataPacket::New(slab_allocators::kLargeACLDataPayloadSize);
+  if (!packet) {
+    bt_log(ERROR, "hci", "failed to allocate buffer received ACL data packet!");
+    defer_wait.cancel();
+    return;
+  }
+
+  status = ReadAclDataPacketFromChannel(channel_, packet);
+  if (status == ZX_ERR_INVALID_ARGS) {
+    return;
+  }
   if (status != ZX_OK) {
-    bt_log(ERROR, "hci", "wait error: %s", zx_status_get_string(status));
+    defer_wait.cancel();
+    return;
+  }
+
+  {
+    TRACE_DURATION("bluetooth", "AclDataChannelImpl->rx_callback_");
+    rx_callback_(std::move(packet));
   }
 }
 
diff --git a/pw_bluetooth_sapphire/host/transport/command_channel.cc b/pw_bluetooth_sapphire/host/transport/command_channel.cc
index f5c5e83..6858411 100644
--- a/pw_bluetooth_sapphire/host/transport/command_channel.cc
+++ b/pw_bluetooth_sapphire/host/transport/command_channel.cc
@@ -6,6 +6,7 @@
 
 #include <endian.h>
 #include <lib/async/default.h>
+#include <lib/fit/defer.h>
 #include <lib/trace/event.h>
 #include <zircon/assert.h>
 #include <zircon/status.h>
@@ -630,7 +631,7 @@
                                     zx_status_t status, const zx_packet_signal_t* signal) {
   ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_READABLE);
 
-  TRACE_DURATION("bluetooth", "CommandChannel::OnChannelReady", "signal->count", signal->count);
+  TRACE_DURATION("bluetooth", "CommandChannel::OnChannelReady");
 
   if (status != ZX_OK) {
     bt_log(DEBUG, "hci", "channel error: %s", zx_status_get_string(status));
@@ -643,35 +644,35 @@
   // TODO(armansito): We could first try to read into a small buffer and retry if the syscall
   // returns ZX_ERR_BUFFER_TOO_SMALL. Not sure if the second syscall would be worth it but
   // investigate.
-  for (size_t count = 0; count < signal->count; count++) {
-    std::unique_ptr<EventPacket> packet =
-        EventPacket::New(slab_allocators::kLargeControlPayloadSize);
-    if (!packet) {
-      bt_log(ERROR, "hci", "failed to allocate event packet!");
-      return;
-    }
-
-    zx_status_t status = ReadEventPacketFromChannel(channel_, packet);
-    if (status == ZX_ERR_INVALID_ARGS) {
-      continue;
-    }
-
-    if (status != ZX_OK) {
-      return;
-    }
-
-    if (packet->event_code() == hci_spec::kCommandStatusEventCode ||
-        packet->event_code() == hci_spec::kCommandCompleteEventCode) {
-      UpdateTransaction(std::move(packet));
-      TrySendQueuedCommands();
-    } else {
-      NotifyEventHandler(std::move(packet));
-    }
+  std::unique_ptr<EventPacket> packet = EventPacket::New(slab_allocators::kLargeControlPayloadSize);
+  if (!packet) {
+    bt_log(ERROR, "hci", "failed to allocate event packet!");
+    return;
   }
 
-  status = wait->Begin(dispatcher);
+  // The wait needs to be restarted after every signal.
+  auto defer_wait = fit::defer([wait, dispatcher] {
+    zx_status_t status = wait->Begin(dispatcher);
+    if (status != ZX_OK) {
+      bt_log(ERROR, "hci", "wait error: %s", zx_status_get_string(status));
+    }
+  });
+
+  status = ReadEventPacketFromChannel(channel_, packet);
+  if (status == ZX_ERR_INVALID_ARGS) {
+    return;
+  }
   if (status != ZX_OK) {
-    bt_log(DEBUG, "hci", "wait error: %s", zx_status_get_string(status));
+    defer_wait.cancel();
+    return;
+  }
+
+  if (packet->event_code() == hci_spec::kCommandStatusEventCode ||
+      packet->event_code() == hci_spec::kCommandCompleteEventCode) {
+    UpdateTransaction(std::move(packet));
+    TrySendQueuedCommands();
+  } else {
+    NotifyEventHandler(std::move(packet));
   }
 }
 
diff --git a/pw_bluetooth_sapphire/host/transport/sco_data_channel.cc b/pw_bluetooth_sapphire/host/transport/sco_data_channel.cc
index 9dfbc9d..4f7589a 100644
--- a/pw_bluetooth_sapphire/host/transport/sco_data_channel.cc
+++ b/pw_bluetooth_sapphire/host/transport/sco_data_channel.cc
@@ -5,6 +5,7 @@
 #include "sco_data_channel.h"
 
 #include <lib/async/default.h>
+#include <lib/fit/defer.h>
 #include <zircon/status.h>
 
 #include <fbl/ref_counted.h>
@@ -192,31 +193,33 @@
 
   ZX_ASSERT(signal->observed & ZX_CHANNEL_READABLE);
 
-  for (size_t count = 0; count < signal->count; count++) {
-    fitx::result<zx_status_t, std::unique_ptr<ScoDataPacket>> result = ReadPacketFromChannel();
-    if (result.is_error()) {
-      // Ignore malformed packets.
-      bt_log(ERROR, "hci", "ignoring packet due to read error: %s",
-             zx_status_get_string(result.error_value()));
-      continue;
+  // The wait needs to be restarted after every signal.
+  auto defer_wait = fit::defer([wait, dispatcher] {
+    zx_status_t status = wait->Begin(dispatcher);
+    if (status != ZX_OK) {
+      bt_log(ERROR, "hci", "wait error: %s", zx_status_get_string(status));
     }
-    auto conn_iter = connections_.find(letoh16(result.value()->connection_handle()));
-    if (conn_iter == connections_.end()) {
-      // Ignore inbound packets for connections that aren't registered. Unlike ACL, buffering data
-      // received before a connection is registered is unnecessary for SCO (it's realtime and
-      // not expected to be reliable).
-      bt_log(DEBUG, "hci", "ignoring inbound SCO packet for unregistered connection: %#.4x",
-             result.value()->connection_handle());
-      continue;
-    }
-    conn_iter->second.connection->ReceiveInboundPacket(std::move(result.value()));
+  });
+
+  fitx::result<zx_status_t, std::unique_ptr<ScoDataPacket>> result = ReadPacketFromChannel();
+  if (result.is_error()) {
+    // Ignore malformed packets.
+    bt_log(ERROR, "hci", "ignoring packet due to read error: %s",
+           zx_status_get_string(result.error_value()));
+    return;
   }
 
-  // The wait needs to be restarted after every signal.
-  status = wait->Begin(dispatcher);
-  if (status != ZX_OK) {
-    bt_log(ERROR, "hci", "wait error: %s", zx_status_get_string(status));
+  auto conn_iter = connections_.find(letoh16(result.value()->connection_handle()));
+  if (conn_iter == connections_.end()) {
+    // Ignore inbound packets for connections that aren't registered. Unlike ACL, buffering data
+    // received before a connection is registered is unnecessary for SCO (it's realtime and
+    // not expected to be reliable).
+    bt_log(DEBUG, "hci", "ignoring inbound SCO packet for unregistered connection: %#.4x",
+           result.value()->connection_handle());
+    return;
   }
+
+  conn_iter->second.connection->ReceiveInboundPacket(std::move(result.value()));
 }
 
 fitx::result<zx_status_t, std::unique_ptr<ScoDataPacket>>