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

Commit 3dcce006 authored by En-Shuo Hsu's avatar En-Shuo Hsu
Browse files

floss: Fill in DBusHeadsetCallbacks for HFP SLC

Add implementation for some AT command callbacks.
 - The internal entry point for callbacks is bta_ag_at_hfp_cback()
 - Some AT commands are considered 'local' and is handled in bta_ag_cmd.cc
   with build time defined values
 - Otherwise by default AT commands are forwarded to application(i.e HFP shim)
   to be handled, and that's what this CL is for.

Bug: 195344366
Tag: #floss
Test: Build and check btmon
BYPASS_LONG_LINES_REASON: Bluetooth likes 120 char lines

Change-Id: I5b5439d5010b558facee2790d4eaede1365ba81d
parent 3e7d4887
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -115,6 +115,12 @@ config("target_defaults") {
    "TARGET_FLOSS",
    "EXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
    "FALLTHROUGH_INTENDED=[[clang::fallthrough]]",
    # TODO(b/214148074): Start with NB, should enable WB.
    "DISABLE_WBS=TRUE",
    # TODO(b/214149380): Start with no extra feature supported. Should enable
    # required features in the future.
    # This will be consumed by BTA_AgRegister and passed to HF through AT+BRSF.
    "BTIF_HF_FEATURES=0x00000000"
  ]

  # If not configured as a dynamic library, default to static library
+6 −1
Original line number Diff line number Diff line
@@ -53,13 +53,18 @@ cc_library_static {
        "hfp/hfp_shim.cc",
        "controller/controller_shim.cc",
    ],
    generated_headers: ["libbt_topshim_bridge_header", "cxx-bridge-header"],
    generated_headers: [
        "libbt_init_flags_bridge_header",
        "libbt_topshim_bridge_header",
        "cxx-bridge-header"
    ],
    generated_sources: ["libbt_topshim_bridge_code"],
    shared_libs: [
        "libchrome",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/gd",
        "packages/modules/Bluetooth/system/gd/rust/topshim",
        "packages/modules/Bluetooth/system/include",
        "packages/modules/Bluetooth/system/types",
+100 −58
Original line number Diff line number Diff line
@@ -17,38 +17,65 @@
#include "gd/rust/topshim/hfp/hfp_shim.h"

#include "btif/include/btif_hf.h"
#include "gd/os/log.h"
#include "include/hardware/bt_hf.h"
#include "src/profiles/hfp.rs.h"
#include "types/raw_address.h"

namespace rusty = ::bluetooth::topshim::rust;
namespace bluetooth::topshim::rust::internal {
static void connection_state_cb(bluetooth::headset::bthf_connection_state_t state, RawAddress* addr);
}  // namespace bluetooth::topshim::rust::internal

namespace bluetooth::headset {
class DBusHeadsetCallbacks : public Callbacks {
namespace bluetooth {
namespace topshim {
namespace rust {
namespace internal {
static HfpIntf* g_hfpif;

// TODO (b/204488136): Refactor to have a2dp, gatt and hfp share these helpers.
static RustRawAddress to_rust_address(const RawAddress& addr) {
  RustRawAddress raddr;
  std::copy(std::begin(addr.address), std::end(addr.address), std::begin(raddr.address));
  return raddr;
}

static RawAddress from_rust_address(const RustRawAddress& raddr) {
  RawAddress addr;
  addr.FromOctets(raddr.address.data());
  return addr;
}

static void connection_state_cb(bluetooth::headset::bthf_connection_state_t state, RawAddress* addr) {
  RustRawAddress raddr = to_rust_address(*addr);
  rusty::hfp_connection_state_callback(state, raddr);
}

}  // namespace internal

class DBusHeadsetCallbacks : public headset::Callbacks {
 public:
  static Callbacks* GetInstance() {
    static Callbacks* instance = new DBusHeadsetCallbacks();
  static Callbacks* GetInstance(headset::Interface* headset) {
    static Callbacks* instance = new DBusHeadsetCallbacks(headset);
    return instance;
  }

  void ConnectionStateCallback(bthf_connection_state_t state, RawAddress* bd_addr) override {
  DBusHeadsetCallbacks(headset::Interface* headset) : headset_(headset){};

  void ConnectionStateCallback(headset::bthf_connection_state_t state, RawAddress* bd_addr) override {
    LOG_WARN("ConnectionStateCallback from %s", bd_addr->ToString().c_str());
    topshim::rust::internal::connection_state_cb(state, bd_addr);
  }

  void AudioStateCallback([[maybe_unused]] bthf_audio_state_t state, [[maybe_unused]] RawAddress* bd_addr) override {}
  void AudioStateCallback(
      [[maybe_unused]] headset::bthf_audio_state_t state, [[maybe_unused]] RawAddress* bd_addr) override {}

  void VoiceRecognitionCallback([[maybe_unused]] bthf_vr_state_t state, [[maybe_unused]] RawAddress* bd_addr) override {
  }
  void VoiceRecognitionCallback(
      [[maybe_unused]] headset::bthf_vr_state_t state, [[maybe_unused]] RawAddress* bd_addr) override {}

  void AnswerCallCallback([[maybe_unused]] RawAddress* bd_addr) override {}

  void HangupCallCallback([[maybe_unused]] RawAddress* bd_addr) override {}

  void VolumeControlCallback(
      [[maybe_unused]] bthf_volume_type_t type,
      [[maybe_unused]] headset::bthf_volume_type_t type,
      [[maybe_unused]] int volume,
      [[maybe_unused]] RawAddress* bd_addr) override {}

@@ -56,68 +83,83 @@ class DBusHeadsetCallbacks : public Callbacks {

  void DtmfCmdCallback([[maybe_unused]] char tone, [[maybe_unused]] RawAddress* bd_addr) override {}

  void NoiseReductionCallback([[maybe_unused]] bthf_nrec_t nrec, [[maybe_unused]] RawAddress* bd_addr) override {}
  void NoiseReductionCallback(
      [[maybe_unused]] headset::bthf_nrec_t nrec, [[maybe_unused]] RawAddress* bd_addr) override {}

  void WbsCallback([[maybe_unused]] bthf_wbs_config_t wbs, [[maybe_unused]] RawAddress* bd_addr) override {}
  void WbsCallback([[maybe_unused]] headset::bthf_wbs_config_t wbs, [[maybe_unused]] RawAddress* bd_addr) override {}

  void AtChldCallback([[maybe_unused]] bthf_chld_type_t chld, [[maybe_unused]] RawAddress* bd_addr) override {}
  void AtChldCallback([[maybe_unused]] headset::bthf_chld_type_t chld, [[maybe_unused]] RawAddress* bd_addr) override {}

  void AtCnumCallback([[maybe_unused]] RawAddress* bd_addr) override {}

  void AtCindCallback([[maybe_unused]] RawAddress* bd_addr) override {}
  void AtCindCallback(RawAddress* bd_addr) override {
    /* This is required to setup the SLC, the format of the response should be
     * +CIND: <call>,<callsetup>,<service>,<signal>,<roam>,<battery>,<callheld>
     */
    LOG_WARN("Respond +CIND: 0,0,0,0,0,0,0 to AT+CIND? from %s", bd_addr->ToString().c_str());

    /* headset::Interface::CindResponse's parameters are similar but different
     * from the actual CIND response. It will construct the final response for
     * you based on the arguments you provide.
     * CindResponse(network_service_availability, active_call_num,
     *              held_call_num, callsetup_state, signal_strength,
     *              roam_state, battery_level, bd_addr);
     */
    headset_->CindResponse(0, 0, 0, headset::BTHF_CALL_STATE_IDLE, 0, 0, 0, bd_addr);
  }

  void AtCopsCallback([[maybe_unused]] RawAddress* bd_addr) override {}
  void AtCopsCallback(RawAddress* bd_addr) override {
    LOG_WARN("Respond +COPS: 0 to AT+COPS? from %s", bd_addr->ToString().c_str());
    headset_->CopsResponse("", bd_addr);
  }

  void AtClccCallback([[maybe_unused]] RawAddress* bd_addr) override {}
  void AtClccCallback(RawAddress* bd_addr) override {
    LOG_WARN("AT+CLCC from addr %s: Enhanced Call Status is not supported.", bd_addr->ToString().c_str());
    /*
    If we want to support the Enhanced Call Status feature, we need to use this
    callback to send response like "+CLCC: 0,0,0,0,0," with the following codes.
    headset_->ClccResponse(
        0,
        headset::BTHF_CALL_DIRECTION_OUTGOING,
        headset::BTHF_CALL_STATE_ACTIVE,
        headset::BTHF_CALL_TYPE_VOICE,
        headset::BTHF_CALL_MPTY_TYPE_SINGLE,
        NULL,
        headset::BTHF_CALL_ADDRTYPE_UNKNOWN,
        bd_addr);
    */
  }

  void UnknownAtCallback([[maybe_unused]] char* at_string, [[maybe_unused]] RawAddress* bd_addr) override {}
  void UnknownAtCallback(char* at_string, RawAddress* bd_addr) override {
    LOG_WARN("Reply Error to UnknownAtCallback:%s", at_string);
    headset_->AtResponse(headset::BTHF_AT_RESPONSE_ERROR, 0, bd_addr);
  }

  void KeyPressedCallback([[maybe_unused]] RawAddress* bd_addr) override {}

  void AtBindCallback([[maybe_unused]] char* at_string, [[maybe_unused]] RawAddress* bd_addr) override {}

  void AtBievCallback(
      [[maybe_unused]] bthf_hf_ind_type_t ind_id,
      [[maybe_unused]] int ind_value,
      [[maybe_unused]] RawAddress* bd_addr) override {}

  void AtBiaCallback(
      [[maybe_unused]] bool service,
      [[maybe_unused]] bool roam,
      [[maybe_unused]] bool signal,
      [[maybe_unused]] bool battery,
      [[maybe_unused]] RawAddress* bd_addr) override {}
};
}  // namespace bluetooth::headset

namespace bluetooth {
namespace topshim {
namespace rust {
namespace internal {
static HfpIntf* g_hfpif;

// TODO (b/204488136): Refactor to have a2dp, gatt and hfp share these helpers.
static RustRawAddress to_rust_address(const RawAddress& addr) {
  RustRawAddress raddr;
  std::copy(std::begin(addr.address), std::end(addr.address), std::begin(raddr.address));
  return raddr;
  void AtBindCallback(char* at_string, RawAddress* bd_addr) override {
    LOG_WARN(
        "AT+BIND %s from addr %s: Bluetooth HF Indicators is not supported.", at_string, bd_addr->ToString().c_str());
  }

static RawAddress from_rust_address(const RustRawAddress& raddr) {
  RawAddress addr;
  addr.FromOctets(raddr.address.data());
  return addr;
  void AtBievCallback(headset::bthf_hf_ind_type_t ind_id, int ind_value, RawAddress* bd_addr) override {
    LOG_WARN(
        "AT+BIEV=%d,%d from addr %s: Bluetooth HF Indicators is not supported.",
        ind_id,
        ind_value,
        bd_addr->ToString().c_str());
  }

static void connection_state_cb(bluetooth::headset::bthf_connection_state_t state, RawAddress* addr) {
  RustRawAddress raddr = to_rust_address(*addr);
  rusty::hfp_connection_state_callback(state, raddr);
  void AtBiaCallback(bool service, bool roam, bool signal, bool battery, RawAddress* bd_addr) override {
    LOG_WARN("AT+BIA=,,%d,%d,%d,%d,from addr %s", service, signal, roam, battery, bd_addr->ToString().c_str());
  }

}  // namespace internal
 private:
  headset::Interface* headset_;
};

int HfpIntf::init() {
  return intf_->Init(headset::DBusHeadsetCallbacks::GetInstance(), 1, false);
  return intf_->Init(DBusHeadsetCallbacks::GetInstance(intf_), 1, false);
}

int HfpIntf::connect(RustRawAddress bt_addr) {