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

Commit 012774b5 authored by Joseph Hwang's avatar Joseph Hwang
Browse files

gd/hci: enable erroneous data reporting in controller

This patch enables the erroneous data reporting when an adapter is
initialized if it is supported. This is useful in enhancing the
audio quality when the audio processing is done in the stack.

Bug: 270652267
Tag: #floss
Test: atest bluetooth_test_gd_unit
Test: Manual testing. Connect a brya host to a headphone and watch
the erroneous data reporting flag when using HFP. When walking
far from the host, some broken SCO data packets were observed in
the btsnoop log as below:

  > SCO Data RX: Handle 513 flags 0x01 dlen 60
  > SCO Data RX: Handle 513 flags 0x03 dlen 60

The meanings of the flags values above:
- 00: data received correctly
- 01: possibly invalid data
- 10: no data received. All data from the baseband are marked as
      lost data.
- 11: Data partially lost.

BYPASS_LONG_LINES_REASON: Bluetooth likes 120 lines

Change-Id: Iec480dcc399a832e05dd8e1d1da55e7a51cf532c
parent 07274981
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -179,6 +179,13 @@ struct Controller::impl {
          handler->BindOnceOn(this, &Controller::impl::le_set_host_feature_handler));
    }

    if (is_supported(OpCode::READ_DEFAULT_ERRONEOUS_DATA_REPORTING)) {
      hci_->EnqueueCommand(
          ReadDefaultErroneousDataReportingBuilder::Create(),
          handler->BindOnceOn(
              this, &Controller::impl::read_default_erroneous_data_reporting_handler));
    }

    // Skip vendor capabilities check if configured.
    if (os::GetSystemPropertyBool(
            kPropertyVendorCapabilitiesEnabled, kDefaultVendorCapabilitiesEnabled)) {
@@ -382,6 +389,62 @@ struct Controller::impl {
    ASSERT_LOG(status == ErrorCode::SUCCESS, "Status 0x%02hhx, %s", status, ErrorCodeText(status).c_str());
  }

  void read_default_erroneous_data_reporting_handler(CommandCompleteView view) {
    ASSERT(view.GetCommandOpCode() == OpCode::READ_DEFAULT_ERRONEOUS_DATA_REPORTING);
    auto complete_view = ReadDefaultErroneousDataReportingCompleteView::Create(view);
    // Check to see that the opcode was correct.
    // ASSERT(complete_view.IsValid()) is not used here to avoid process abort.
    // Some devices, such as mokey_go32, may claim to support it but do not
    // actually do so (b/277589118).
    if (!complete_view.IsValid()) {
      LOG_ERROR("invalid command complete view");
      return;
    }

    ErrorCode status = complete_view.GetStatus();
    // This is an optional feature to enhance audio quality. It is okay
    // to just return if the status is not SUCCESS.
    if (status != ErrorCode::SUCCESS) {
      LOG_ERROR("Unexpected status: %s", ErrorCodeText(status).c_str());
      return;
    }

    Enable erroneous_data_reporting = complete_view.GetErroneousDataReporting();
    LOG_INFO("erroneous data reporting: %hhu", erroneous_data_reporting);

    // Enable Erroneous Data Reporting if it is disabled and the write command is supported.
    if (erroneous_data_reporting == Enable::DISABLED &&
        is_supported(OpCode::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING)) {
      std::unique_ptr<WriteDefaultErroneousDataReportingBuilder> packet =
          WriteDefaultErroneousDataReportingBuilder::Create(Enable::ENABLED);
      hci_->EnqueueCommand(
          std::move(packet),
          module_.GetHandler()->BindOnceOn(
              this, &Controller::impl::write_default_erroneous_data_reporting_handler));
    }
  }

  void write_default_erroneous_data_reporting_handler(CommandCompleteView view) {
    ASSERT(view.GetCommandOpCode() == OpCode::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING);
    auto complete_view = WriteDefaultErroneousDataReportingCompleteView::Create(view);
    // Check to see that the opcode was correct.
    // ASSERT(complete_view.IsValid()) is not used here to avoid process abort.
    // Some devices, such as mokey_go32, may claim to support it but do not
    // actually do so (b/277589118).
    if (!complete_view.IsValid()) {
      LOG_ERROR("invalid command complete view");
      return;
    }

    ErrorCode status = complete_view.GetStatus();
    // This is an optional feature to enhance audio quality. It is okay
    // to just return if the status is not SUCCESS.
    if (status != ErrorCode::SUCCESS) {
      LOG_ERROR("Unexpected status: %s", ErrorCodeText(status).c_str());
      return;
    }
  }

  void le_read_local_supported_features_handler(CommandCompleteView view) {
    auto complete_view = LeReadLocalSupportedFeaturesCompleteView::Create(view);
    ASSERT(complete_view.IsValid());