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

Commit b839f97b authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add topshim for A2DP source interface"

parents e50d671a b022a20f
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -23,20 +23,27 @@ config("rust_topshim_config") {
}

cxxbridge_header("btif_bridge_header") {
  sources = [ "src/btif.rs" ]
  sources = [
    "src/btif.rs",
    "src/profiles/a2dp.rs"
  ]
  all_dependent_configs = [ ":rust_topshim_config" ]
  deps = [":cxxlibheader"]
}

cxxbridge_cc("btif_bridge_code") {
  sources = [ "src/btif.rs" ]
  sources = [
    "src/btif.rs",
    "src/profiles/a2dp.rs"
  ]
  deps = [":btif_bridge_header"]
  configs = [ "//bt/gd:gd_defaults" ]
}

source_set("btif_cxx_bridge_code") {
  sources = [
    "btif/btif_shim.cc"
    "btif/btif_shim.cc",
    "btav/btav_shim.cc"
  ]

  deps = [":btif_bridge_header"]
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ num-derive = "*"
num-traits = "*"
tokio = { version = "*", features = ['bytes', 'fs', 'io-util', 'libc', 'macros', 'memchr', 'mio', 'net', 'num_cpus', 'rt', 'rt-multi-thread', 'sync', 'time', 'tokio-macros'] }
tokio-stream = "*"
bitflags ="*"

[build-dependencies]
bindgen = "0.57"
+163 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "gd/rust/topshim/btav/btav_shim.h"
#include "include/hardware/bluetooth.h"

#include "rust/cxx.h"
#include "src/profiles/a2dp.rs.h"

namespace bluetooth {
namespace topshim {
namespace rust {
namespace internal {
static A2dpIntf* g_a2dpif;

namespace rusty = ::bluetooth::topshim::rust;

static RustRawAddress to_rust_address(const RawAddress& address) {
  RustRawAddress raddr;
  std::copy(std::begin(address.address), std::end(address.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 A2dpCodecConfig to_rust_codec_config(const btav_a2dp_codec_config_t& config) {
  A2dpCodecConfig rconfig = {.codec_type = static_cast<uint8_t>(config.codec_type),
                             .codec_priority = config.codec_priority,
                             .sample_rate = static_cast<uint8_t>(config.sample_rate),
                             .bits_per_sample = static_cast<uint8_t>(config.bits_per_sample),
                             .channel_mode = static_cast<uint8_t>(config.channel_mode),
                             .codec_specific_1 = config.codec_specific_1,
                             .codec_specific_2 = config.codec_specific_2,
                             .codec_specific_3 = config.codec_specific_3,
                             .codec_specific_4 = config.codec_specific_4};
  return rconfig;
}

static btav_a2dp_codec_config_t from_rust_codec_config(const A2dpCodecConfig& rconfig) {
  btav_a2dp_codec_config_t config = {
      .codec_type = static_cast<btav_a2dp_codec_index_t>(rconfig.codec_type),
      .codec_priority = static_cast<btav_a2dp_codec_priority_t>(rconfig.codec_priority),
      .sample_rate = static_cast<btav_a2dp_codec_sample_rate_t>(rconfig.sample_rate),
      .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(rconfig.bits_per_sample),
      .channel_mode = static_cast<btav_a2dp_codec_channel_mode_t>(rconfig.channel_mode),
      .codec_specific_1 = rconfig.codec_specific_1,
      .codec_specific_2 = rconfig.codec_specific_2,
      .codec_specific_3 = rconfig.codec_specific_3,
      .codec_specific_4 = rconfig.codec_specific_4,
  };
  return config;
}

static ::rust::Vec<A2dpCodecConfig> to_rust_codec_config_vec(const std::vector<btav_a2dp_codec_config_t>& configs) {
  ::rust::Vec<A2dpCodecConfig> rconfigs;

  for (btav_a2dp_codec_config_t c : configs) {
    rconfigs.push_back(to_rust_codec_config(c));
  }
  return rconfigs;
}

static void connection_state_cb(const RawAddress& bd_addr, btav_connection_state_t state) {
  RustRawAddress addr = to_rust_address(bd_addr);
  rusty::connection_state_callback(addr, state);
}
static void audio_state_cb(const RawAddress& bd_addr, btav_audio_state_t state) {
  RustRawAddress addr = to_rust_address(bd_addr);
  rusty::audio_state_callback(addr, state);
}
static void audio_config_cb(
    const RawAddress& bd_addr,
    btav_a2dp_codec_config_t codec_config,
    std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
    std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities) {
  RustRawAddress addr = to_rust_address(bd_addr);
  A2dpCodecConfig cfg = to_rust_codec_config(codec_config);
  ::rust::Vec<A2dpCodecConfig> lcaps = to_rust_codec_config_vec(codecs_local_capabilities);
  ::rust::Vec<A2dpCodecConfig> scaps = to_rust_codec_config_vec(codecs_selectable_capabilities);
  rusty::audio_config_callback(addr, cfg, lcaps, scaps);
}
static bool mandatory_codec_preferred_cb(const RawAddress& bd_addr) {
  RustRawAddress addr = to_rust_address(bd_addr);
  rusty::mandatory_codec_preferred_callback(addr);
  return true;
}

btav_source_callbacks_t g_callbacks = {
    sizeof(btav_source_callbacks_t),
    connection_state_cb,
    audio_state_cb,
    audio_config_cb,
    mandatory_codec_preferred_cb,
};
}  // namespace internal

A2dpIntf::~A2dpIntf() {
  // TODO
}

std::unique_ptr<A2dpIntf> GetA2dpProfile(const unsigned char* btif) {
  if (internal::g_a2dpif) std::abort();

  const bt_interface_t* btif_ = reinterpret_cast<const bt_interface_t*>(btif);

  auto a2dpif = std::make_unique<A2dpIntf>(
      reinterpret_cast<const btav_source_interface_t*>(btif_->get_profile_interface("a2dp")));
  internal::g_a2dpif = a2dpif.get();
  return a2dpif;
}

int A2dpIntf::init() {
  std::vector<btav_a2dp_codec_config_t> a;
  std::vector<btav_a2dp_codec_config_t> b;

  return intf_->init(&internal::g_callbacks, 1, a, b);
}

int A2dpIntf::connect(RustRawAddress bt_addr) {
  RawAddress addr = internal::from_rust_address(bt_addr);
  return intf_->connect(addr);
}
int A2dpIntf::disconnect(RustRawAddress bt_addr) {
  RawAddress addr = internal::from_rust_address(bt_addr);
  return intf_->disconnect(addr);
}
int A2dpIntf::set_silence_device(RustRawAddress bt_addr, bool silent) {
  RawAddress addr = internal::from_rust_address(bt_addr);
  return intf_->set_silence_device(addr, silent);
}
int A2dpIntf::set_active_device(RustRawAddress bt_addr) {
  RawAddress addr = internal::from_rust_address(bt_addr);
  return intf_->set_active_device(addr);
}
int A2dpIntf::config_codec(RustRawAddress bt_addr, ::rust::Vec<A2dpCodecConfig> codec_preferences) {
  RawAddress addr = internal::from_rust_address(bt_addr);
  std::vector<btav_a2dp_codec_config_t> prefs;
  for (int i = 0; i < codec_preferences.size(); ++i) {
    prefs.push_back(internal::from_rust_codec_config(codec_preferences[i]));
  }
  return intf_->config_codec(addr, prefs);
}

}  // namespace rust
}  // namespace topshim
}  // namespace bluetooth
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef GD_RUST_TOPSHIM_BTAV_BTAV_SHIM_H
#define GD_RUST_TOPSHIM_BTAV_BTAV_SHIM_H

#include "include/hardware/bt_av.h"

#include "rust/cxx.h"

namespace bluetooth {
namespace topshim {
namespace rust {

struct A2dpCodecConfig;
struct RustRawAddress;

class A2dpIntf {
 public:
  A2dpIntf(const btav_source_interface_t* intf) : intf_(intf){};
  ~A2dpIntf();

  int init();
  int connect(RustRawAddress bt_addr);
  int disconnect(RustRawAddress bt_addr);
  int set_silence_device(RustRawAddress bt_addr, bool silent);
  int set_active_device(RustRawAddress bt_addr);
  int config_codec(RustRawAddress bt_addr, ::rust::Vec<A2dpCodecConfig> codec_preferences);
  void cleanup();

 private:
  const btav_source_interface_t* intf_;
};

std::unique_ptr<A2dpIntf> GetA2dpProfile(const unsigned char* btif);

}  // namespace rust
}  // namespace topshim
}  // namespace bluetooth

#endif  // GD_RUST_TOPSHIM_BTAV_BTAV_SHIM_H
+6 −0
Original line number Diff line number Diff line
@@ -235,12 +235,14 @@ pub type BtPinCode = bindings::bt_pin_code_t;

pub enum SupportedProfiles {
    HidHost,
    A2dp,
}

impl From<SupportedProfiles> for Vec<u8> {
    fn from(item: SupportedProfiles) -> Self {
        match item {
            SupportedProfiles::HidHost => "hidhost".bytes().collect::<Vec<u8>>(),
            SupportedProfiles::A2dp => "a2dp".bytes().collect::<Vec<u8>>(),
        }
    }
}
@@ -508,6 +510,10 @@ impl BluetoothInterface {
        let cprofile = Vec::<u8>::from(profile);
        ccall!(self, get_profile_interface, cprofile.as_slice().as_ptr() as *const i8)
    }

    pub(crate) fn as_raw_ptr(&self) -> *const u8 {
        self.internal.raw as *const u8
    }
}

pub fn get_btinterface() -> Option<BluetoothInterface> {
Loading