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

Commit d4457849 authored by Sungsoo Lim's avatar Sungsoo Lim Committed by Gerrit Code Review
Browse files

Merge "Handle HCI setup ESCO connection failures"

parents ba3d80cb d91c0ab5
Loading
Loading
Loading
Loading
+70 −57
Original line number Diff line number Diff line
@@ -723,8 +723,8 @@ void btm_sco_conn_req(const RawAddress& bda, const DEV_CLASS& dev_class,
 * Returns          void
 *
 ******************************************************************************/
void btm_sco_connected(tHCI_STATUS hci_status, const RawAddress& bda,
                       uint16_t hci_handle, tBTM_ESCO_DATA* p_esco_data) {
void btm_sco_connected(const RawAddress& bda, uint16_t hci_handle,
                       tBTM_ESCO_DATA* p_esco_data) {
  tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
  uint16_t xx;
  bool spt = false;
@@ -734,7 +734,63 @@ void btm_sco_connected(tHCI_STATUS hci_status, const RawAddress& bda,
    if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
         (p->state == SCO_ST_W4_CONN_RSP)) &&
        (p->rem_bd_known) && (p->esco.data.bd_addr == bda)) {
      if (hci_status != HCI_SUCCESS) {
      BTM_LogHistory(
          kBtmLogTag, bda, "Connection created",
          base::StringPrintf("sco_idx:%hu handle:0x%04x ", xx, hci_handle));

      if (p->state == SCO_ST_LISTENING) spt = true;

      p->state = SCO_ST_CONNECTED;
      p->hci_handle = hci_handle;

      BTM_LogHistory(kBtmLogTag, bda, "Connection success",
                     base::StringPrintf("handle:0x%04x %s", hci_handle,
                                        (spt) ? "listener" : "initiator"));

      if (!btm_cb.sco_cb.esco_supported) {
        p->esco.data.link_type = BTM_LINK_TYPE_SCO;
        if (spt) {
          parms.packet_types = p->esco.setup.packet_types;
          /* Keep the other parameters the same for SCO */
          parms.max_latency_ms = p->esco.setup.max_latency_ms;
          parms.retransmission_effort = p->esco.setup.retransmission_effort;

          BTM_ChangeEScoLinkParms(xx, &parms);
        }
      } else {
        if (p_esco_data) p->esco.data = *p_esco_data;
      }

      (*p->p_conn_cb)(xx);

      bluetooth::audio::sco::open();

      return;
    }
  }
}

/*******************************************************************************
 *
 * Function         btm_sco_connection_failed
 *
 * Description      This function is called by BTIF when an (e)SCO connection
 *                  setup is failed.
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_sco_connection_failed(tHCI_STATUS hci_status, const RawAddress& bda,
                               uint16_t hci_handle,
                               tBTM_ESCO_DATA* p_esco_data) {
  tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
  uint16_t xx;

  for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
    if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
         (p->state == SCO_ST_W4_CONN_RSP)) &&
        (p->rem_bd_known) &&
        (p->esco.data.bd_addr == bda || bda == RawAddress::kEmpty)) {
      /* Report the error if originator, otherwise remain in Listen mode */
      if (p->is_orig) {
        LOG_DEBUG("SCO initiating connection failed handle:0x%04x reason:%s",
@@ -776,49 +832,6 @@ void btm_sco_connected(tHCI_STATUS hci_status, const RawAddress& bda,
      }
      return;
    }

      BTM_LogHistory(
          kBtmLogTag, bda, "Connection created",
          base::StringPrintf("sco_idx:%hu handle:0x%04x ", xx, hci_handle));

      if (p->state == SCO_ST_LISTENING) spt = true;

      p->state = SCO_ST_CONNECTED;
      p->hci_handle = hci_handle;

      if (hci_status == HCI_SUCCESS) {
        BTM_LogHistory(kBtmLogTag, bda, "Connection success",
                       base::StringPrintf("handle:0x%04x %s", hci_handle,
                                          (spt) ? "listener" : "initiator"));
      } else {
        BTM_LogHistory(
            kBtmLogTag, bda, "Connection failed",
            base::StringPrintf(
                "reason:%s",
                hci_reason_code_text(static_cast<tHCI_REASON>(hci_status))
                    .c_str()));
      }

      if (!btm_cb.sco_cb.esco_supported) {
        p->esco.data.link_type = BTM_LINK_TYPE_SCO;
        if (spt) {
          parms.packet_types = p->esco.setup.packet_types;
          /* Keep the other parameters the same for SCO */
          parms.max_latency_ms = p->esco.setup.max_latency_ms;
          parms.retransmission_effort = p->esco.setup.retransmission_effort;

          BTM_ChangeEScoLinkParms(xx, &parms);
        }
      } else {
        if (p_esco_data) p->esco.data = *p_esco_data;
      }

      (*p->p_conn_cb)(xx);

      bluetooth::audio::sco::open();

      return;
    }
  }
}

+15 −2
Original line number Diff line number Diff line
@@ -1138,7 +1138,12 @@ static void btu_hcif_esco_connection_comp_evt(const uint8_t* p) {
  handle = HCID_GET_HANDLE(handle);

  data.bd_addr = bda;
  btm_sco_connected(static_cast<tHCI_STATUS>(status), bda, handle, &data);
  if (status == HCI_SUCCESS) {
    btm_sco_connected(bda, handle, &data);
  } else {
    btm_sco_connection_failed(static_cast<tHCI_STATUS>(status), bda, handle,
                              &data);
  }
}

/*******************************************************************************
@@ -1393,7 +1398,9 @@ static void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status,
    case HCI_ENH_SETUP_ESCO_CONNECTION:
      if (status != HCI_SUCCESS) {
        STREAM_TO_UINT16(handle, p_cmd);
        // Determine if initial connection failed or is a change of setup
        RawAddress addr(RawAddress::kEmpty);
        btm_sco_connection_failed(static_cast<tHCI_STATUS>(status), addr,
                                  handle, nullptr);
      }
      break;

@@ -1436,6 +1443,12 @@ static void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status,
  }
}

void bluetooth::legacy::testing::btu_hcif_hdl_command_status(
    uint16_t opcode, uint8_t status, const uint8_t* p_cmd,
    void* p_vsc_status_cback) {
  ::btu_hcif_hdl_command_status(opcode, status, p_cmd, p_vsc_status_cback);
}

/*******************************************************************************
 *
 * Function         btu_hcif_command_status_evt
+5 −0
Original line number Diff line number Diff line
@@ -53,6 +53,11 @@ void btu_hcif_send_cmd_with_cb(const base::Location& posted_from,
                               uint16_t opcode, uint8_t* params,
                               uint8_t params_len,
                               base::OnceCallback<void(uint8_t*, uint16_t)> cb);
namespace bluetooth::legacy::testing {
void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status,
                                 const uint8_t* p_cmd,
                                 void* p_vsc_status_cback);
}  // namespace bluetooth::legacy::testing

/* Functions provided by btu_task.cc
 ***********************************
+6 −2
Original line number Diff line number Diff line
@@ -30,8 +30,12 @@ extern void btm_sco_chk_pend_unpark(tHCI_STATUS hci_status,
                                    uint16_t hci_handle);
extern void btm_sco_conn_req(const RawAddress& bda, const DEV_CLASS& dev_class,
                             uint8_t link_type);
extern void btm_sco_connected(tHCI_STATUS hci_status, const RawAddress& bda,
                              uint16_t hci_handle, tBTM_ESCO_DATA* p_esco_data);
extern void btm_sco_connected(const RawAddress& bda, uint16_t hci_handle,
                              tBTM_ESCO_DATA* p_esco_data);
extern void btm_sco_connection_failed(tHCI_STATUS hci_status,
                                      const RawAddress& bda,
                                      uint16_t hci_handle,
                                      tBTM_ESCO_DATA* p_esco_data);
extern bool btm_sco_removed(uint16_t hci_handle, tHCI_REASON reason);

void btm_sco_on_disconnected(uint16_t hci_handle, tHCI_REASON reason);
+19 −1
Original line number Diff line number Diff line
@@ -15,16 +15,34 @@
 */

#include <gtest/gtest.h>

#include <cstdint>
#include <map>
#include <string>

#include "stack/include/btu.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/hcidefs.h"

std::map<std::string, int> mock_function_count_map;

/* Function for test provided by btu_hcif.cc */
void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status,
                                 const uint8_t* p_cmd,
                                 void* p_vsc_status_cback);

void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {}

class StackBtuTest : public ::testing::Test {};
class StackBtuTest : public ::testing::Test {
 protected:
  void SetUp() override { mock_function_count_map.clear(); }
};

TEST_F(StackBtuTest, post_on_main) {}

TEST_F(StackBtuTest, btm_sco_connection_failed_called) {
  uint8_t p_cmd[10];  // garbage data for testing
  bluetooth::legacy::testing::btu_hcif_hdl_command_status(
      HCI_SETUP_ESCO_CONNECTION, HCI_ERR_UNSPECIFIED, p_cmd, nullptr);
  ASSERT_EQ(1, mock_function_count_map["btm_sco_connection_failed"]);
}
Loading