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

Commit c88f41ce authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi Committed by Gerrit Code Review
Browse files

Merge changes I4775379a,Idc9e8afd,Ifed930a9,I6d7a451b,I1ce49aa5

* changes:
  floss: Add BleScanner topshim
  floss: Update rustdocs in topshim + stack
  floss: Improve build.py for docs and test
  floss: Fix doctest in topshim macros
  floss: Add cxxcall and mutcxxcall macros
parents ae7b3607 907cd721
Loading
Loading
Loading
Loading
+24 −7
Original line number Diff line number Diff line
@@ -59,13 +59,14 @@ USE_DEFAULTS = {
}

VALID_TARGETS = [
    'all',  # All targets except test and clean
    'clean',  # Clean up output directory
    'docs',  # Build Rust docs
    'main',  # Build the main C++ codebase
    'prepare',  # Prepare the output directory (gn gen + rust setup)
    'tools',  # Build the host tools (i.e. packetgen)
    'rust',  # Build only the rust components + copy artifacts to output dir
    'main',  # Build the main C++ codebase
    'test',  # Run the unit tests
    'clean',  # Clean up output directory
    'all',  # All targets except test and clean
    'tools',  # Build the host tools (i.e. packetgen)
]

# TODO(b/190750167) - Host tests are disabled until we are full bazel build
@@ -413,6 +414,10 @@ class HostBuild():
        shutil.copy(
            os.path.join(self._gn_default_output(), 'bluetooth_packetgen'), os.path.join(self.env['CARGO_HOME'], 'bin'))

    def _target_docs(self):
        """Build the Rust docs."""
        self.run_command('docs', ['cargo', 'doc'], cwd=os.path.join(self.platform_dir, 'bt'), env=self.env)

    def _target_rust(self):
        """ Build rust artifacts in an already prepared environment.
        """
@@ -427,7 +432,11 @@ class HostBuild():
        """ Runs the host tests.
        """
        # Rust tests first
        self.run_command('test', ['cargo', 'test'], cwd=os.path.join(self.platform_dir, 'bt'), env=self.env)
        rust_test_cmd = ['cargo', 'test']
        if self.args.test_name:
            rust_test_cmd = rust_test_cmd + [self.args.test_name]

        self.run_command('test', rust_test_cmd, cwd=os.path.join(self.platform_dir, 'bt'), env=self.env)

        # Host tests second based on host test list
        for t in HOST_TESTS:
@@ -502,7 +511,7 @@ class HostBuild():
            pass

    def _target_all(self):
        """ Build all common targets (skipping test and clean).
        """ Build all common targets (skipping doc, test, and clean).
        """
        self._target_prepare()
        self._target_tools()
@@ -514,12 +523,19 @@ class HostBuild():
        """
        print('Building target ', self.target)

        # Validate that the target is valid
        if self.target not in VALID_TARGETS:
            print('Target {} is not valid. Must be in {}', self.target, VALID_TARGETS)
            return

        if self.target == 'prepare':
            self._target_prepare()
        elif self.target == 'tools':
            self._target_tools()
        elif self.target == 'rust':
            self._target_rust()
        elif self.target == 'docs':
            self._target_docs()
        elif self.target == 'main':
            self._target_main()
        elif self.target == 'test':
@@ -759,7 +775,8 @@ if __name__ == '__main__':
    parser.add_argument(
        '--no-strip', help='Skip stripping binaries during install.', default=False, action='store_true')
    parser.add_argument('--use', help='Set a specific use flag.')
    parser.add_argument('--notest', help="Don't compile test code.", default=False, action='store_true')
    parser.add_argument('--notest', help='Don\'t compile test code.', default=False, action='store_true')
    parser.add_argument('--test-name', help='Run test with this string in the name.', default=None)
    parser.add_argument('--target', help='Run specific build target')
    parser.add_argument('--sysroot', help='Set a specific sysroot path', default='/')
    parser.add_argument('--libdir', help='Libdir - default = usr/lib', default='usr/lib')
+3 −6
Original line number Diff line number Diff line
//! Fluoride/GD Bluetooth stack.
//! Floss Bluetooth stack.
//!
//! This crate provides the API implementation of the Fluoride/GD Bluetooth stack, independent of
//! any RPC projection.
//! This crate provides the API implementation of the Fluoride/GD Bluetooth
//! stack, independent of any RPC projection.

#[macro_use]
extern crate num_derive;
@@ -27,9 +27,6 @@ use bt_topshim::{
    },
};

/// Represents a Bluetooth address.
// TODO: Add support for LE random addresses.

#[derive(Clone, Debug)]
pub enum BluetoothCallbackType {
    Adapter,
+245 −6
Original line number Diff line number Diff line
@@ -16,13 +16,20 @@

#include "gd/rust/topshim/gatt/gatt_ble_scanner_shim.h"

#include <base/bind.h>
#include <base/callback.h>

#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>

#include "bind_helpers.h"
#include "gd/rust/topshim/common/utils.h"
#include "include/hardware/bt_common_types.h"
#include "rust/cxx.h"
#include "src/profiles/gatt.rs.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

namespace bluetooth {
@@ -31,12 +38,65 @@ namespace rust {

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

void BleScannerIntf::RegisterCallbacks() {
  // Register self as a callback handler. We will dispatch to Rust callbacks.
  scanner_intf_->RegisterCallbacks(this);
namespace internal {
ApcfCommand ConvertApcfFromRust(const RustApcfCommand& command) {
  RawAddress address = rusty::CopyFromRustAddress(command.address);

  // Copy vectors + arrays
  std::vector<uint8_t> name, data, data_mask;
  std::array<uint8_t, 16> irk;
  std::copy(command.name.begin(), command.name.end(), std::back_inserter(name));
  std::copy(command.data.begin(), command.data.end(), std::back_inserter(data));
  std::copy(command.data_mask.begin(), command.data_mask.end(), std::back_inserter(data_mask));
  std::copy(command.irk.begin(), command.irk.end(), std::begin(irk));

  ApcfCommand converted = {
      .type = command.type_,
      .address = address,
      .addr_type = command.addr_type,
      .uuid = bluetooth::Uuid::From128BitBE(command.uuid.uu),
      .uuid_mask = bluetooth::Uuid::From128BitBE(command.uuid_mask.uu),
      .name = name,
      .company = command.company,
      .company_mask = command.company_mask,
      .data = data,
      .data_mask = data_mask,
      .irk = irk,
  };

  return converted;
}

// ScanningCallbacks overrides
std::vector<ApcfCommand> ConvertApcfVec(const ::rust::Vec<RustApcfCommand>& rustvec) {
  std::vector<ApcfCommand> converted;

  for (const RustApcfCommand& command : rustvec) {
    converted.push_back(ConvertApcfFromRust(command));
  }

  return converted;
}

::btgatt_filt_param_setup_t ConvertRustFilterParam(const RustGattFilterParam& param) {
  ::btgatt_filt_param_setup_t converted = {
      .feat_seln = param.feat_seln,
      .list_logic_type = param.list_logic_type,
      .filt_logic_type = param.filt_logic_type,
      .rssi_high_thres = param.rssi_high_thres,
      .rssi_low_thres = param.rssi_low_thres,
      .dely_mode = param.delay_mode,
      .found_timeout = param.found_timeout,
      .lost_timeout = param.lost_timeout,
      .found_timeout_cnt = param.found_timeout_count,
      .num_of_tracking_entries = param.num_of_tracking_entries,
  };

  return converted;
}
}  // namespace internal

// ScanningCallbacks implementations

void BleScannerIntf::OnScannerRegistered(const bluetooth::Uuid app_uuid, uint8_t scannerId, uint8_t status) {
  rusty::gdscan_on_scanner_registered(reinterpret_cast<const signed char*>(&app_uuid), scannerId, status);
}
@@ -89,8 +149,8 @@ void BleScannerIntf::OnTrackAdvFoundLost(AdvertisingTrackInfo ati) {
      // .scan_response is copied below
  };

  std::copy(ati.adv_packet.begin(), ati.adv_packet.end(), std::back_inserter(rust_info.adv_packet));
  std::copy(ati.scan_response.begin(), ati.scan_response.end(), std::back_inserter(rust_info.scan_response));
  std::copy(rust_info.adv_packet.begin(), rust_info.adv_packet.end(), std::back_inserter(ati.adv_packet));
  std::copy(rust_info.scan_response.begin(), rust_info.scan_response.end(), std::back_inserter(ati.scan_response));

  rusty::gdscan_on_track_adv_found_lost(rust_info);
}
@@ -104,6 +164,185 @@ void BleScannerIntf::OnBatchScanThresholdCrossed(int client_if) {
  rusty::gdscan_on_batch_scan_threshold_crossed(client_if);
}

// BleScannerInterface implementations

void BleScannerIntf::RegisterScanner(RustUuid uuid) {
  bluetooth::Uuid converted = bluetooth::Uuid::From128BitBE(uuid.uu);
  scanner_intf_->RegisterScanner(
      converted, base::Bind(&BleScannerIntf::OnRegisterCallback, base::Unretained(this), uuid));
}

void BleScannerIntf::Unregister(uint8_t scanner_id) {
  scanner_intf_->Unregister(scanner_id);
}

void BleScannerIntf::Scan(bool start) {
  scanner_intf_->Scan(start);
}

void BleScannerIntf::ScanFilterParamSetup(
    uint8_t scanner_id, uint8_t action, uint8_t filter_index, RustGattFilterParam filter_param) {
  std::unique_ptr<::btgatt_filt_param_setup_t> converted =
      std::make_unique<::btgatt_filt_param_setup_t>(std::move(internal::ConvertRustFilterParam(filter_param)));

  scanner_intf_->ScanFilterParamSetup(
      scanner_id,
      action,
      filter_index,
      std::move(converted),
      base::Bind(&BleScannerIntf::OnFilterParamSetupCallback, base::Unretained(this), scanner_id));
}

void BleScannerIntf::ScanFilterAdd(uint8_t filter_index, ::rust::Vec<RustApcfCommand> filters) {
  auto converted = internal::ConvertApcfVec(filters);
  scanner_intf_->ScanFilterAdd(
      filter_index,
      converted,
      base::Bind(&BleScannerIntf::OnFilterConfigCallback, base::Unretained(this), filter_index));
}

void BleScannerIntf::ScanFilterClear(uint8_t filter_index) {
  scanner_intf_->ScanFilterClear(
      filter_index, base::Bind(&BleScannerIntf::OnFilterConfigCallback, base::Unretained(this), filter_index));
}

void BleScannerIntf::ScanFilterEnable(bool enable) {
  scanner_intf_->ScanFilterEnable(enable, base::Bind(&BleScannerIntf::OnEnableCallback, base::Unretained(this)));
}

void BleScannerIntf::SetScanParameters(uint8_t scanner_id, uint16_t scan_interval, uint16_t scan_window) {
  scanner_intf_->SetScanParameters(
      scanner_id,
      scan_interval,
      scan_window,
      base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), scanner_id));
}

void BleScannerIntf::BatchscanConfigStorage(
    uint8_t scanner_id,
    int32_t batch_scan_full_max,
    int32_t batch_scan_trunc_max,
    int32_t batch_scan_notify_threshold) {
  scanner_intf_->BatchscanConfigStorage(
      scanner_id,
      batch_scan_full_max,
      batch_scan_trunc_max,
      batch_scan_notify_threshold,
      base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), scanner_id));
}

void BleScannerIntf::BatchscanEnable(
    int32_t scan_mode, uint16_t scan_interval, uint16_t scan_window, int32_t addr_type, int32_t discard_rule) {
  scanner_intf_->BatchscanEnable(
      scan_mode,
      scan_interval,
      scan_window,
      addr_type,
      discard_rule,
      base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), 0));
}

void BleScannerIntf::BatchscanDisable() {
  scanner_intf_->BatchscanDisable(base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), 0));
}

void BleScannerIntf::BatchscanReadReports(uint8_t scanner_id, int32_t scan_mode) {
  scanner_intf_->BatchscanReadReports(scanner_id, scan_mode);
}

void BleScannerIntf::StartSync(uint8_t sid, RustRawAddress address, uint16_t skip, uint16_t timeout) {
  RawAddress converted = rusty::CopyFromRustAddress(address);
  scanner_intf_->StartSync(
      sid,
      converted,
      skip,
      timeout,
      base::Bind(&BleScannerIntf::OnStartSyncCb, base::Unretained(this)),
      base::Bind(&BleScannerIntf::OnSyncReportCb, base::Unretained(this)),
      base::Bind(&BleScannerIntf::OnSyncLostCb, base::Unretained(this)));
}

void BleScannerIntf::StopSync(uint16_t handle) {
  scanner_intf_->StopSync(handle);
}

void BleScannerIntf::CancelCreateSync(uint8_t sid, RustRawAddress address) {
  RawAddress converted = rusty::CopyFromRustAddress(address);
  scanner_intf_->CancelCreateSync(sid, converted);
}

void BleScannerIntf::TransferSync(RustRawAddress address, uint16_t service_data, uint16_t sync_handle) {
  RawAddress converted = rusty::CopyFromRustAddress(address);
  scanner_intf_->TransferSync(
      converted, service_data, sync_handle, base::Bind(&BleScannerIntf::OnSyncTransferCb, base::Unretained(this)));
}

void BleScannerIntf::TransferSetInfo(RustRawAddress address, uint16_t service_data, uint8_t adv_handle) {
  RawAddress converted = rusty::CopyFromRustAddress(address);
  scanner_intf_->TransferSetInfo(
      converted, service_data, adv_handle, base::Bind(&BleScannerIntf::OnSyncTransferCb, base::Unretained(this)));
}

void BleScannerIntf::SyncTxParameters(RustRawAddress address, uint8_t mode, uint16_t skip, uint16_t timeout) {
  RawAddress converted = rusty::CopyFromRustAddress(address);
  scanner_intf_->SyncTxParameters(
      converted, mode, skip, timeout, base::Bind(&BleScannerIntf::OnStartSyncCb, base::Unretained(this)));
}

void BleScannerIntf::OnRegisterCallback(RustUuid uuid, uint8_t scanner_id, uint8_t btm_status) {
  rusty::gdscan_register_callback(uuid, scanner_id, btm_status);
}

void BleScannerIntf::OnStatusCallback(uint8_t scanner_id, uint8_t btm_status) {
  rusty::gdscan_status_callback(scanner_id, btm_status);
}

void BleScannerIntf::OnEnableCallback(uint8_t action, uint8_t btm_status) {
  rusty::gdscan_enable_callback(action, btm_status);
}

void BleScannerIntf::OnFilterParamSetupCallback(
    uint8_t scanner_id, uint8_t avbl_space, uint8_t action_type, uint8_t btm_status) {
  rusty::gdscan_filter_param_setup_callback(scanner_id, avbl_space, action_type, btm_status);
}

void BleScannerIntf::OnFilterConfigCallback(
    uint8_t filter_index, uint8_t filt_type, uint8_t avbl_space, uint8_t action, uint8_t btm_status) {
  rusty::gdscan_filter_config_callback(filter_index, filt_type, avbl_space, action, btm_status);
}

void BleScannerIntf::OnStartSyncCb(
    uint8_t status,
    uint16_t sync_handle,
    uint8_t advertising_sid,
    uint8_t address_type,
    RawAddress address,
    uint8_t phy,
    uint16_t interval) {
  RustRawAddress converted = rusty::CopyToRustAddress(address);
  rusty::gdscan_start_sync_callback(status, sync_handle, advertising_sid, address_type, &converted, phy, interval);
}

void BleScannerIntf::OnSyncReportCb(
    uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data) {
  rusty::gdscan_sync_report_callback(sync_handle, tx_power, rssi, status, data.data(), data.size());
}

void BleScannerIntf::OnSyncLostCb(uint16_t sync_handle) {
  rusty::gdscan_sync_lost_callback(sync_handle);
}

void BleScannerIntf::OnSyncTransferCb(uint8_t status, RawAddress address) {
  RustRawAddress converted = rusty::CopyToRustAddress(address);
  rusty::gdscan_sync_transfer_callback(status, &converted);
}

void BleScannerIntf::RegisterCallbacks() {
  // Register self as a callback handler. We will dispatch to Rust callbacks.
  scanner_intf_->RegisterCallbacks(this);
}

// ScanningCallbacks overrides
std::unique_ptr<BleScannerIntf> GetBleScannerIntf(const unsigned char* gatt_intf) {
  return std::make_unique<BleScannerIntf>(reinterpret_cast<const btgatt_interface_t*>(gatt_intf)->scanner);
}
+104 −2
Original line number Diff line number Diff line
@@ -26,13 +26,16 @@ namespace bluetooth {
namespace topshim {
namespace rust {

struct RustApcfCommand;
struct RustGattFilterParam;
struct RustRawAddress;
struct RustUuid;

class BleScannerIntf : public ScanningCallbacks {
 public:
  BleScannerIntf(BleScannerInterface* scanner_intf) : scanner_intf_(scanner_intf){};
  ~BleScannerIntf() = default;

  void RegisterCallbacks();

  // ScanningCallbacks overrides
  void OnScannerRegistered(const bluetooth::Uuid app_uuid, uint8_t scannerId, uint8_t status) override;

@@ -57,7 +60,106 @@ class BleScannerIntf : public ScanningCallbacks {

  void OnBatchScanThresholdCrossed(int client_if) override;

  // Implementations of BleScannerInterface. These don't inherit from
  // BleScannerInterface because the Rust FFI boundary requires some clever
  // modifications.

  // Register a scanner for a Uuid. Response comes back via
  // |OnRegisterCallback|.
  void RegisterScanner(RustUuid uuid);

  // Unregister a scanner with a |scanner_id|.
  void Unregister(uint8_t scanner_id);

  // Start/Stop LE scanning.
  void Scan(bool start);

  // Setup scan filter parameters. Get responses via
  // |OnFilterParamSetupCallback|.
  void ScanFilterParamSetup(uint8_t scanner_id, uint8_t action, uint8_t filter_index, RustGattFilterParam filter_param);

  // Adds filters to given filter index. Gets responses via
  // |OnFilterConfigCallback|.
  void ScanFilterAdd(uint8_t filter_index, ::rust::Vec<RustApcfCommand> filters);

  // Clear scan filter conditions for a specific index.
  void ScanFilterClear(uint8_t filter_index);

  // Enable/disable scan filter. Gets responses via |OnEnableCallback|.
  void ScanFilterEnable(bool enable);

  // Sets the LE scan interval and window in units of N * 0.625 msec. The result
  // of this action is returned via |OnStatusCallback|.
  void SetScanParameters(uint8_t scanner_id, uint16_t scan_interval, uint16_t scan_window);

  // Configure the batchscan storage and get a response via |OnStatusCallback|.
  void BatchscanConfigStorage(
      uint8_t scanner_id,
      int32_t batch_scan_full_max,
      int32_t batch_scan_trunc_max,
      int32_t batch_scan_notify_threshold);

  // Enable batchscan. Gets responses via |OnStatusCallback| with scanner id
  // = 0 (since multiple scanners can be registered).
  void BatchscanEnable(
      int32_t scan_mode, uint16_t scan_interval, uint16_t scan_window, int32_t addr_type, int32_t discard_rule);

  // Disable batchscan. Gets responses via |OnStatusCallback| with a scanner id
  // = 0 (since multiple scanners can be registered).
  void BatchscanDisable();

  // Read out batchscan report for a specific scanner. Gets responses via
  // |ScanningCallbacks::OnBatchScanReports|.
  void BatchscanReadReports(uint8_t scanner_id, int32_t scan_mode);

  // Start periodic sync. Gets responses via |OnStartSyncCb|. Periodic reports
  // come via |OnSyncReportCb| and |OnSyncLostCb|.
  void StartSync(uint8_t sid, RustRawAddress address, uint16_t skip, uint16_t timeout);

  // Stop periodic sync.
  void StopSync(uint16_t handle);

  // Cancel creating a periodic sync.
  void CancelCreateSync(uint8_t sid, RustRawAddress address);

  // Transfer sync data to target address. Gets responses via
  // |OnSyncTransferCb|.
  void TransferSync(RustRawAddress address, uint16_t service_data, uint16_t sync_handle);

  // Transfer set info to target address. Gets responses via |OnSyncTransferCb|.
  void TransferSetInfo(RustRawAddress address, uint16_t service_data, uint8_t adv_handle);

  // Sync tx parameters to target address. Gets responses via |OnStartSyncCb|.
  void SyncTxParameters(RustRawAddress address, uint8_t mode, uint16_t skip, uint16_t timeout);

  // Register scanning callbacks to be dispatched to the Rust layer via static
  // methods.
  void RegisterCallbacks();

 private:
  // The callback functions below will get base::Bind to the apis that need it
  // and will call the same Rust function with all the parameters. Some of these
  // callbacks don't have all the parameters coming back in the original
  // callback and will need the values to be base::Bind at the callsite.

  void OnRegisterCallback(RustUuid uuid, uint8_t scanner_id, uint8_t btm_status);
  void OnStatusCallback(uint8_t scanner_id, uint8_t btm_status);
  void OnEnableCallback(uint8_t action, uint8_t btm_status);
  void OnFilterParamSetupCallback(uint8_t scanner_id, uint8_t avbl_space, uint8_t action_type, uint8_t btm_status);
  void OnFilterConfigCallback(
      uint8_t filt_index, uint8_t filt_type, uint8_t avbl_space, uint8_t action, uint8_t btm_status);
  void OnStartSyncCb(
      uint8_t status,
      uint16_t sync_handle,
      uint8_t advertising_sid,
      uint8_t address_type,
      RawAddress address,
      uint8_t phy,
      uint16_t interval);
  void OnSyncReportCb(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data);
  void OnSyncLostCb(uint16_t sync_handle);
  void OnSyncTransferCb(uint8_t status, RawAddress address);

  BleScannerInterface* scanner_intf_;
};

+10 −8
Original line number Diff line number Diff line
@@ -73,10 +73,12 @@ impl Parse for CbVariant {
/// Implement C function to convert callback into enum variant.
///
/// Expected syntax:
///     ```compile_fail
///     cb_variant(DispatcherType, function_name -> EnumType::Variant, args..., {
///         // Statements (maybe converting types)
///         // Args in order will be _0, _1, etc.
///     })
///     ```
///
/// args can do conversions inline as well. In order for conversions to work, the relevant
/// From<T> trait should also be implemented.
@@ -84,7 +86,7 @@ impl Parse for CbVariant {
/// Example:
///     u32 -> BtStatus (requires impl From<u32> for BtStatus)
///
///     To consume a value during conversion, you can use `Type -> _`. This is useful when you want
/// To consume a value during conversion, you can use "Type -> _". This is useful when you want
/// to convert a pointer + size into a single Vec (i.e. using ptr_to_vec).
///
/// Example:
Loading