Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce3779b2 authored by Octavian Purdila's avatar Octavian Purdila
Browse files

RootCanal: better handling for Completed Number Of Packet events

Change the behavior with regard to Completed Number Of Packet events:
ignore the event mask and instead always send the events for ACL
packets and selectively send the events for SCO packets based on the
synchronous flow control status.

From Vol 4, Part E, section "7.7.19 Number Of Completed Packets
event":

  "While the Controller has HCI Data packets in its buffer, it shall
  keep sending the HCI_Number_Of_Completed_Packets event to the Host
  at least periodically, until it finally reports that all the pending
  ACL Data packets have been transmitted or flushed."

From Vol 4, Part E, section "7.3.37 Write Synchronous Flow Control
Enable command":

  "Synchronous Flow Control is disabled - No
  HCI_Number_Of_Completed_Packets events shall be sent from the
  Controller for synchronous Connection_Handles.

  Synchronous Flow Control is enabled -
  HCI_Number_Of_Completed_Packets events shall be sent from the
  Controller for synchronous Connection_Handles."

This fixes an issues where the Fitbit BLE stack timeouts when
connecting the Fitbit emulator to RootCanal / Android emulator due to
not being able to send more ACL packets since no "Number Of Completed
Packets" were received.

Bug: 209058202
Tag: #feature
Test: cert/run
Change-Id: Icb7f81d0779c0687ac16ab1b156c11a4d528db42
parent aa93b0df
Loading
Loading
Loading
Loading
+30 −5
Original line number Diff line number Diff line
@@ -294,6 +294,9 @@ DualModeController::DualModeController(const std::string& properties_filename, u
  SET_SUPPORTED(WRITE_CONNECTION_ACCEPT_TIMEOUT, WriteConnectionAcceptTimeout);
  SET_SUPPORTED(LE_SET_ADDRESS_RESOLUTION_ENABLE, LeSetAddressResolutionEnable);
  SET_SUPPORTED(LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, LeSetResovalablePrivateAddressTimeout);
  SET_SUPPORTED(READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE, ReadSynchronousFlowControlEnable);
  SET_SUPPORTED(WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, WriteSynchronousFlowControlEnable);

#undef SET_HANDLER
#undef SET_SUPPORTED
  properties_.SetSupportedCommands(supported_commands);
@@ -337,10 +340,8 @@ void DualModeController::HandleAcl(std::shared_ptr<std::vector<uint8_t>> packet)
    cp.connection_handle_ = handle;
    cp.host_num_of_completed_packets_ = kNumCommandPackets;
    completed_packets.push_back(cp);
    if (properties_.IsUnmasked(EventCode::NUMBER_OF_COMPLETED_PACKETS)) {
    send_event_(bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
        completed_packets));
    }
    return;
  }

@@ -360,7 +361,7 @@ void DualModeController::HandleSco(std::shared_ptr<std::vector<uint8_t>> packet)
    cp.connection_handle_ = handle;
    cp.host_num_of_completed_packets_ = kNumCommandPackets;
    completed_packets.push_back(cp);
    if (properties_.IsUnmasked(EventCode::NUMBER_OF_COMPLETED_PACKETS)) {
    if (properties_.GetSynchronousFlowControl()) {
      send_event_(bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
          completed_packets));
    }
@@ -1449,6 +1450,30 @@ void DualModeController::WriteScanEnable(CommandView command) {
  send_event_(std::move(packet));
}

void DualModeController::ReadSynchronousFlowControlEnable(CommandView command) {
  auto command_view = gd_hci::ReadSynchronousFlowControlEnableView::Create(
      gd_hci::DiscoveryCommandView::Create(command));
  ASSERT(command_view.IsValid());
  auto enabled = bluetooth::hci::Enable::DISABLED;
  if (properties_.GetSynchronousFlowControl()) {
    enabled = bluetooth::hci::Enable::ENABLED;
  }
  auto packet = bluetooth::hci::ReadSynchronousFlowControlEnableCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS, enabled);
  send_event_(std::move(packet));
}

void DualModeController::WriteSynchronousFlowControlEnable(CommandView command) {
  auto command_view = gd_hci::WriteSynchronousFlowControlEnableView::Create(
      gd_hci::DiscoveryCommandView::Create(command));
  ASSERT(command_view.IsValid());
  auto enabled = command_view.GetEnable() == bluetooth::hci::Enable::ENABLED;
  properties_.SetSynchronousFlowControl(enabled);
  auto packet = bluetooth::hci::WriteSynchronousFlowControlEnableCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS);
  send_event_(std::move(packet));
}

void DualModeController::SetEventFilter(CommandView command) {
  auto command_view = gd_hci::SetEventFilterView::Create(command);
  ASSERT(command_view.IsValid());
+6 −0
Original line number Diff line number Diff line
@@ -289,6 +289,12 @@ class DualModeController : public Device {
  // 7.3.28
  void WriteVoiceSetting(CommandView args);

  // 7.3.36
  void ReadSynchronousFlowControlEnable(CommandView args);

  // 7.3.37
  void WriteSynchronousFlowControlEnable(CommandView args);

  // 7.3.39
  void HostBufferSize(CommandView args);

+1 −3
Original line number Diff line number Diff line
@@ -164,9 +164,7 @@ ErrorCode LinkLayerController::SendAclToRemote(
    completed_packets.push_back(cp);
    auto packet = bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
        completed_packets);
    if (properties_.IsUnmasked(EventCode::NUMBER_OF_COMPLETED_PACKETS)) {
    send_event_(std::move(packet));
    }
  });

  auto acl_payload = acl_packet.GetPayload();
+9 −0
Original line number Diff line number Diff line
@@ -133,6 +133,14 @@ class DeviceProperties {
    return num_sco_data_packets_;
  }

  bool GetSynchronousFlowControl() const {
    return sco_flow_control_;
  }

  void SetSynchronousFlowControl(bool sco_flow_control) {
    sco_flow_control_ = sco_flow_control;
  }

  const Address& GetAddress() const {
    return address_;
  }
@@ -391,6 +399,7 @@ class DeviceProperties {
  uint8_t sco_data_packet_size_;
  uint16_t num_acl_data_packets_;
  uint16_t num_sco_data_packets_;
  bool sco_flow_control_{false};
  uint8_t version_;
  uint16_t revision_;
  uint8_t lmp_pal_version_;