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

Commit 3c7ccd11 authored by Jeremy Wu's avatar Jeremy Wu
Browse files

Floss: implement csis_shim

This CL implements the topshim layer to bridge APIs between the native
stack and the Rust interface.

Bug: 317682584
Test: m Bluetooth
Flag: EXEMPT floss only changes
Change-Id: I27b8a5ad473dea05243a0710d4e3edb618f22da5
parent 355e96d4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ cc_library_static {
        "btav_sink/btav_sink_shim.cc",
        "btif/btif_shim.cc",
        "controller/controller_shim.cc",
        "csis/csis_shim.cc",
        "gatt/gatt_ble_advertiser_shim.cc",
        "gatt/gatt_ble_scanner_shim.cc",
        "gatt/gatt_shim.cc",
@@ -87,6 +88,7 @@ gensrcs {
        "src/controller.rs",
        "src/profiles/a2dp.rs",
        "src/profiles/avrcp.rs",
        "src/profiles/csis.rs",
        "src/profiles/gatt.rs",
        "src/profiles/hfp.rs",
        "src/profiles/le_audio.rs",
@@ -105,6 +107,7 @@ gensrcs {
        "src/controller.rs",
        "src/profiles/a2dp.rs",
        "src/profiles/avrcp.rs",
        "src/profiles/csis.rs",
        "src/profiles/gatt.rs",
        "src/profiles/hfp.rs",
        "src/profiles/le_audio.rs",
+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ cxxbridge_header("btif_bridge_header") {
    "src/metrics.rs",
    "src/profiles/a2dp.rs",
    "src/profiles/avrcp.rs",
    "src/profiles/csis.rs",
    "src/profiles/gatt.rs",
    "src/profiles/hfp.rs",
    "src/profiles/le_audio.rs",
@@ -43,6 +44,7 @@ cxxbridge_cc("btif_bridge_code") {
    "src/metrics.rs",
    "src/profiles/a2dp.rs",
    "src/profiles/avrcp.rs",
    "src/profiles/csis.rs",
    "src/profiles/gatt.rs",
    "src/profiles/hfp.rs",
    "src/profiles/le_audio.rs",
@@ -64,6 +66,7 @@ source_set("btif_cxx_bridge_code") {
    "btav_sink/btav_sink_shim.cc",
    "btif/btif_shim.cc",
    "controller/controller_shim.cc",
    "csis/csis_shim.cc",
    "gatt/gatt_ble_advertiser_shim.cc",
    "gatt/gatt_ble_scanner_shim.cc",
    "gatt/gatt_shim.cc",
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
 * to define the aliases in the topshim namespace.
 */

#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

namespace bluetooth {
@@ -32,6 +33,7 @@ namespace topshim {
namespace rust {

using RawAddress = ::RawAddress;
using Uuid = ::bluetooth::Uuid;

}  // namespace rust
}  // namespace topshim
+172 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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/csis/csis_shim.h"

#include <bluetooth/log.h>
#include <hardware/bluetooth.h>

#include <string>

#include "os/log.h"
#include "src/profiles/csis.rs.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

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

namespace bluetooth {
namespace topshim {
namespace rust {
namespace internal {

static CsisClientIntf* g_csis_if;

static BtCsisConnectionState to_rust_btcsis_connection_state(csis::ConnectionState state) {
  switch (state) {
    case csis::ConnectionState::DISCONNECTED:
      return BtCsisConnectionState::Disconnected;
    case csis::ConnectionState::CONNECTING:
      return BtCsisConnectionState::Connecting;
    case csis::ConnectionState::CONNECTED:
      return BtCsisConnectionState::Connected;
    case csis::ConnectionState::DISCONNECTING:
      return BtCsisConnectionState::Disconnecting;
    default:
      log::assert_that(false, "Unhandled enum value from C++");
  }
  return BtCsisConnectionState{};
}

static BtCsisGroupLockStatus to_rust_btcsis_group_lock_status(csis::CsisGroupLockStatus status) {
  switch (status) {
    case csis::CsisGroupLockStatus::SUCCESS:
      return BtCsisGroupLockStatus::Success;
    case csis::CsisGroupLockStatus::FAILED_INVALID_GROUP:
      return BtCsisGroupLockStatus::FailedInvalidGroup;
    case csis::CsisGroupLockStatus::FAILED_GROUP_EMPTY:
      return BtCsisGroupLockStatus::FailedGroupEmpty;
    case csis::CsisGroupLockStatus::FAILED_GROUP_NOT_CONNECTED:
      return BtCsisGroupLockStatus::FailedGroupNotConnected;
    case csis::CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER:
      return BtCsisGroupLockStatus::FailedLockedByOther;
    case csis::CsisGroupLockStatus::FAILED_OTHER_REASON:
      return BtCsisGroupLockStatus::FailedOtherReason;
    case csis::CsisGroupLockStatus::LOCKED_GROUP_MEMBER_LOST:
      return BtCsisGroupLockStatus::LockedGroupMemberLost;
    default:
      log::assert_that(false, "Unhandled enum value from C++");
  }
  return BtCsisGroupLockStatus{};
}

static void connection_state_cb(const RawAddress& addr, csis::ConnectionState state) {
  csis_connection_state_callback(addr, to_rust_btcsis_connection_state(state));
}

static void device_available_cb(
    const RawAddress& addr, int group_id, int group_size, int rank, const bluetooth::Uuid& uuid) {
  csis_device_available_callback(addr, group_id, group_size, rank, uuid);
}

static void set_member_available_cb(const RawAddress& addr, int group_id) {
  csis_set_member_available_callback(addr, group_id);
}

static void group_lock_changed_cb(int group_id, bool locked, csis::CsisGroupLockStatus status) {
  csis_group_lock_changed_callback(group_id, locked, to_rust_btcsis_group_lock_status(status));
}
}  // namespace internal

class DBusCsisClientCallbacks : public csis::CsisClientCallbacks {
 public:
  static csis::CsisClientCallbacks* GetInstance() {
    static auto instance = new DBusCsisClientCallbacks();
    return instance;
  }

  DBusCsisClientCallbacks(){};

  void OnConnectionState(const RawAddress& addr, csis::ConnectionState state) override {
    log::info("addr={}, state={}", ADDRESS_TO_LOGGABLE_CSTR(addr), static_cast<uint8_t>(state));
    topshim::rust::internal::connection_state_cb(addr, state);
  }

  void OnDeviceAvailable(
      const RawAddress& addr,
      int group_id,
      int group_size,
      int rank,
      const bluetooth::Uuid& uuid) override {
    log::info(
        "addr={}, group_id={}, group_size={}, rank={}",
        ADDRESS_TO_LOGGABLE_CSTR(addr),
        group_id,
        group_size,
        rank);
    topshim::rust::internal::device_available_cb(addr, group_id, group_size, rank, uuid);
  }

  void OnSetMemberAvailable(const RawAddress& addr, int group_id) {
    log::info("addr={}, group_id={}", ADDRESS_TO_LOGGABLE_CSTR(addr), group_id);
    topshim::rust::internal::set_member_available_cb(addr, group_id);
  }

  void OnGroupLockChanged(int group_id, bool locked, csis::CsisGroupLockStatus status) {
    topshim::rust::internal::group_lock_changed_cb(group_id, locked, status);
  }
};

std::unique_ptr<CsisClientIntf> GetCsisClientProfile(const unsigned char* btif) {
  if (internal::g_csis_if) std::abort();

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

  auto csis_if = std::make_unique<CsisClientIntf>(
      const_cast<csis::CsisClientInterface*>(reinterpret_cast<const csis::CsisClientInterface*>(
          btif_->get_profile_interface("csis_client"))));

  internal::g_csis_if = csis_if.get();

  return csis_if;
}

void CsisClientIntf::init(/*CsisClientCallbacks* callbacks*/) {
  return intf_->Init(DBusCsisClientCallbacks::GetInstance());
}

void CsisClientIntf::connect(RawAddress addr) {
  return intf_->Connect(addr);
}

void CsisClientIntf::disconnect(RawAddress addr) {
  return intf_->Disconnect(addr);
}

void CsisClientIntf::lock_group(int group_id, bool lock) {
  return intf_->LockGroup(group_id, lock);
}

void CsisClientIntf::remove_device(RawAddress addr) {
  return intf_->RemoveDevice(addr);
}

void CsisClientIntf::cleanup() {
  return intf_->Cleanup();
}
}  // namespace rust
}  // namespace topshim
}  // namespace bluetooth
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

#pragma once

#include <memory>

#include "include/hardware/bt_csis.h"
#include "rust/cxx.h"
#include "types/raw_address.h"

namespace bluetooth {
namespace topshim {
namespace rust {

class CsisClientIntf {
 public:
  CsisClientIntf(csis::CsisClientInterface* intf) : intf_(intf){};

  void init(/*CsisClientCallbacks* callbacks*/);
  void connect(RawAddress addr);
  void disconnect(RawAddress addr);
  void lock_group(int group_id, bool lock);
  void remove_device(RawAddress addr);
  void cleanup();

 private:
  csis::CsisClientInterface* intf_;
};

std::unique_ptr<CsisClientIntf> GetCsisClientProfile(const unsigned char* btif);

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