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

Commit 21f7d9e7 authored by Zach Johnson's avatar Zach Johnson
Browse files

rusty-gd: implement controller shim

Bug: 171749953
Tag: #gd-refactor
Test: gd/cert/run --rhost
Change-Id: I847253d5b217295a8ae72e124b25a647dc0d96e1
parent 22761eca
Loading
Loading
Loading
Loading
+123 −32
Original line number Diff line number Diff line
@@ -15,11 +15,12 @@ use bt_packets::hci::{
use gddi::{module, provides, Stoppable};
use num_traits::ToPrimitive;
use std::convert::TryFrom;
use std::sync::Arc;

module! {
    controller_module,
    providers {
        ControllerExports => provide_controller,
        Arc<ControllerExports> => provide_controller,
    },
}

@@ -33,7 +34,7 @@ macro_rules! assert_success {
}

#[provides]
async fn provide_controller(mut hci: HciExports) -> ControllerExports {
async fn provide_controller(mut hci: HciExports) -> Arc<ControllerExports> {
    assert_success!(hci.send(LeSetEventMaskBuilder { le_event_mask: 0x0000000000021e7f }));
    assert_success!(hci.send(SetEventMaskBuilder { event_mask: 0x3dbfffffffffffff }));
    assert_success!(
@@ -54,7 +55,7 @@ async fn provide_controller(mut hci: HciExports) -> ControllerExports {
            .get_supported_commands(),
    };

    let lmp_features = read_lmp_features(&mut hci).await;
    let features = read_features(&mut hci).await;

    let buffer_size = assert_success!(hci.send(ReadBufferSizeBuilder {}));
    let acl_buffer_length = buffer_size.get_acl_data_packet_length();
@@ -86,8 +87,9 @@ async fn provide_controller(mut hci: HciExports) -> ControllerExports {
        le_buffer_length = acl_buffer_length;
    }

    let le_features =
        assert_success!(hci.send(LeReadLocalSupportedFeaturesBuilder {})).get_le_features();
    let le_features = SupportedLeFeatures::new(
        assert_success!(hci.send(LeReadLocalSupportedFeaturesBuilder {})).get_le_features(),
    );
    let le_supported_states =
        assert_success!(hci.send(LeReadSupportedStatesBuilder {})).get_le_states();
    let le_connect_list_size =
@@ -139,12 +141,12 @@ async fn provide_controller(mut hci: HciExports) -> ControllerExports {

    let address = assert_success!(hci.send(ReadBdAddrBuilder {})).get_bd_addr();

    ControllerExports {
    Arc::new(ControllerExports {
        name,
        address,
        version_info,
        commands,
        lmp_features,
        features,
        acl_buffer_length,
        acl_buffers,
        sco_buffer_length: buffer_size.get_synchronous_data_packet_length(),
@@ -162,10 +164,10 @@ async fn provide_controller(mut hci: HciExports) -> ControllerExports {
        le_max_advertising_data_length,
        le_supported_advertising_sets,
        le_periodic_advertiser_list_size,
    }
    })
}

async fn read_lmp_features(hci: &mut HciExports) -> Vec<u64> {
async fn read_features(hci: &mut HciExports) -> SupportedFeatures {
    let mut features = Vec::new();
    let mut page_number: u8 = 0;
    let mut max_page_number: u8 = 1;
@@ -176,34 +178,35 @@ async fn read_lmp_features(hci: &mut HciExports) -> Vec<u64> {
        page_number += 1;
    }

    features
    SupportedFeatures::new(features)
}

/// Controller interface
#[derive(Clone, Stoppable)]
#[allow(missing_docs)]
pub struct ControllerExports {
    name: String,
    address: Address,
    version_info: LocalVersionInformation,
    commands: SupportedCommands,
    lmp_features: Vec<u64>,
    acl_buffer_length: u16,
    acl_buffers: u16,
    sco_buffer_length: u8,
    sco_buffers: u16,
    le_buffer_length: u16,
    le_buffers: u8,
    iso_buffer_length: u16,
    iso_buffers: u8,
    le_features: u64,
    le_supported_states: u64,
    le_connect_list_size: u8,
    le_resolving_list_size: u8,
    le_max_data_length: LeMaximumDataLength,
    le_suggested_default_data_length: u16,
    le_max_advertising_data_length: u16,
    le_supported_advertising_sets: u8,
    le_periodic_advertiser_list_size: u8,
    pub name: String,
    pub address: Address,
    pub version_info: LocalVersionInformation,
    pub commands: SupportedCommands,
    pub features: SupportedFeatures,
    pub acl_buffer_length: u16,
    pub acl_buffers: u16,
    pub sco_buffer_length: u8,
    pub sco_buffers: u16,
    pub le_buffer_length: u16,
    pub le_buffers: u8,
    pub iso_buffer_length: u16,
    pub iso_buffers: u8,
    pub le_features: SupportedLeFeatures,
    pub le_supported_states: u64,
    pub le_connect_list_size: u8,
    pub le_resolving_list_size: u8,
    pub le_max_data_length: LeMaximumDataLength,
    pub le_suggested_default_data_length: u16,
    pub le_max_advertising_data_length: u16,
    pub le_supported_advertising_sets: u8,
    pub le_periodic_advertiser_list_size: u8,
}

/// Convenience struct for checking what commands are supported
@@ -233,6 +236,94 @@ impl SupportedCommands {
    }
}

macro_rules! supported_features {
    ($($id:ident => $page:literal : $bit:literal),*) => {
        /// Convenience struct for checking what features are supported
        #[derive(Clone)]
        #[allow(missing_docs)]
        pub struct SupportedFeatures {
            $(pub $id: bool,)*
        }

        impl SupportedFeatures {
            fn new(supported: Vec<u64>) -> Self {
                Self {
                    $($id: *supported.get($page).unwrap_or(&0) & (1 << $bit) != 0,)*
                }
            }
        }
    }
}

supported_features! {
    three_slot_packets => 0:0,
    five_slot_packets => 0:1,
    role_switch => 0:5,
    hold_mode => 0:6,
    sniff_mode => 0:7,
    park_mode => 0:8,
    sco => 0:11,
    hv2_packets => 0:12,
    hv3_packets => 0:13,
    classic_2m_phy => 0:25,
    classic_3m_phy => 0:26,
    interlaced_inquiry_scan => 0:28,
    rssi_with_inquiry_results => 0:30,
    ev3_packets => 0:31,
    ev4_packets => 0:32,
    ev5_packets => 0:33,
    ble => 0:38,
    three_slot_edr_packets => 0:39,
    five_slot_edr_packets => 0:40,
    sniff_subrating => 0:41,
    encryption_pause => 0:42,
    esco_2m_phy => 0:45,
    esco_3m_phy => 0:46,
    three_slot_esco_edr_packets => 0:47,
    extended_inquiry_response => 0:48,
    simultaneous_le_bredr => 0:49,
    simple_pairing => 0:51,
    non_flushable_pb => 0:54,
    secure_connections => 2:8
}

macro_rules! supported_le_features {
    ($($id:ident => $bit:literal),*) => {
        /// Convenience struct for checking what features are supported
        #[derive(Clone)]
        #[allow(missing_docs)]
        pub struct SupportedLeFeatures {
            $(pub $id: bool,)*
        }

        impl SupportedLeFeatures {
            fn new(supported: u64) -> Self {
                Self {
                    $($id: supported & (1 << $bit) != 0,)*
                }
            }
        }
    }
}

supported_le_features! {
    connection_parameter_request => 1,
    connection_parameters_request => 2,
    peripheral_initiated_feature_exchange => 3,
    packet_extension => 5,
    privacy => 6,
    ble_2m_phy => 8,
    ble_coded_phy => 11,
    extended_advertising => 12,
    periodic_advertising => 13,
    periodic_advertising_sync_transfer_sender => 24,
    periodic_advertising_sync_transfer_recipient => 25,
    connected_iso_stream_central => 28,
    connected_iso_stream_peripheral => 29,
    iso_broadcaster => 30,
    synchronized_receiver => 31
}

fn null_terminated_to_string(slice: &[u8]) -> String {
    let temp = std::str::from_utf8(slice).unwrap();
    temp[0..temp.find('\0').unwrap()].to_string()
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ pub mod error;
pub mod facade;

pub use bt_hci_custom_types::*;
pub use controller::ControllerExports;

use bt_common::time::Alarm;
use bt_hal::HalExports;
+22 −0
Original line number Diff line number Diff line
@@ -35,6 +35,9 @@ rust_ffi_static {
        "libnix",
        "liblog_rust",
    ],
    proc_macros: [
        "libpaste",
    ],
    static_libs: [
        "libbt_callbacks_cxx",
    ],
@@ -47,6 +50,7 @@ cc_library_static {
        "libbt_init_flags_bridge_header",
        "libbt_shim_bridge_header",
        "libbt_hci_bridge_header",
        "libbt_controller_bridge_header",
        "libbt_message_loop_thread_bridge_header",
        "cxx-bridge-header",
    ],
@@ -54,12 +58,14 @@ cc_library_static {
        "libbt_init_flags_bridge_code",
        "libbt_shim_bridge_code",
        "libbt_hci_bridge_code",
        "libbt_controller_bridge_code",
        "libbt_message_loop_thread_bridge_code",
    ],
    export_generated_headers: [
        "libbt_init_flags_bridge_header",
        "libbt_shim_bridge_header",
        "libbt_hci_bridge_header",
        "libbt_controller_bridge_header",
        "libbt_message_loop_thread_bridge_header",
        "cxx-bridge-header",
    ],
@@ -162,3 +168,19 @@ genrule {
    srcs: ["src/message_loop_thread.rs"],
    out: ["message_loop_thread.cc"],
}

genrule {
    name: "libbt_controller_bridge_header",
    tools: ["cxxbridge"],
    cmd: "$(location cxxbridge) $(in) --header > $(out)",
    srcs: ["src/controller.rs"],
    out: ["src/controller.rs.h"],
}

genrule {
    name: "libbt_controller_bridge_code",
    tools: ["cxxbridge"],
    cmd: "$(location cxxbridge) $(in) >> $(out)",
    srcs: ["src/controller.rs"],
    out: ["controller.cc"],
}
+213 −0
Original line number Diff line number Diff line
//! Controller shim

use bt_hci::ControllerExports;
use bt_packets::hci::OpCode;
use paste::paste;
use std::sync::Arc;

#[cxx::bridge(namespace = bluetooth::shim::rust)]
mod ffi {
    extern "Rust" {
        type Controller;

        fn controller_supports_simple_pairing(c: &Controller) -> bool;
        fn controller_supports_secure_connections(c: &Controller) -> bool;
        fn controller_supports_simultaneous_le_bredr(c: &Controller) -> bool;
        fn controller_supports_interlaced_inquiry_scan(c: &Controller) -> bool;
        fn controller_supports_rssi_with_inquiry_results(c: &Controller) -> bool;
        fn controller_supports_extended_inquiry_response(c: &Controller) -> bool;
        fn controller_supports_role_switch(c: &Controller) -> bool;
        fn controller_supports_three_slot_packets(c: &Controller) -> bool;
        fn controller_supports_five_slot_packets(c: &Controller) -> bool;
        fn controller_supports_classic_2m_phy(c: &Controller) -> bool;
        fn controller_supports_classic_3m_phy(c: &Controller) -> bool;
        fn controller_supports_three_slot_edr_packets(c: &Controller) -> bool;
        fn controller_supports_five_slot_edr_packets(c: &Controller) -> bool;
        fn controller_supports_sco(c: &Controller) -> bool;
        fn controller_supports_hv2_packets(c: &Controller) -> bool;
        fn controller_supports_hv3_packets(c: &Controller) -> bool;
        fn controller_supports_ev3_packets(c: &Controller) -> bool;
        fn controller_supports_ev4_packets(c: &Controller) -> bool;
        fn controller_supports_ev5_packets(c: &Controller) -> bool;
        fn controller_supports_esco_2m_phy(c: &Controller) -> bool;
        fn controller_supports_esco_3m_phy(c: &Controller) -> bool;
        fn controller_supports_three_slot_esco_edr_packets(c: &Controller) -> bool;
        fn controller_supports_hold_mode(c: &Controller) -> bool;
        fn controller_supports_sniff_mode(c: &Controller) -> bool;
        fn controller_supports_park_mode(c: &Controller) -> bool;
        fn controller_supports_non_flushable_pb(c: &Controller) -> bool;
        fn controller_supports_sniff_subrating(c: &Controller) -> bool;
        fn controller_supports_encryption_pause(c: &Controller) -> bool;
        fn controller_supports_ble(c: &Controller) -> bool;

        fn controller_supports_privacy(c: &Controller) -> bool;
        fn controller_supports_packet_extension(c: &Controller) -> bool;
        fn controller_supports_connection_parameters_request(c: &Controller) -> bool;
        fn controller_supports_ble_2m_phy(c: &Controller) -> bool;
        fn controller_supports_ble_coded_phy(c: &Controller) -> bool;
        fn controller_supports_extended_advertising(c: &Controller) -> bool;
        fn controller_supports_periodic_advertising(c: &Controller) -> bool;
        fn controller_supports_peripheral_initiated_feature_exchange(c: &Controller) -> bool;
        fn controller_supports_connection_parameter_request(c: &Controller) -> bool;
        fn controller_supports_periodic_advertising_sync_transfer_sender(c: &Controller) -> bool;
        fn controller_supports_periodic_advertising_sync_transfer_recipient(c: &Controller)
            -> bool;
        fn controller_supports_connected_iso_stream_central(c: &Controller) -> bool;
        fn controller_supports_connected_iso_stream_peripheral(c: &Controller) -> bool;
        fn controller_supports_iso_broadcaster(c: &Controller) -> bool;
        fn controller_supports_synchronized_receiver(c: &Controller) -> bool;

        fn controller_supports_reading_remote_extended_features(c: &Controller) -> bool;
        fn controller_supports_enhanced_setup_synchronous_connection(c: &Controller) -> bool;
        fn controller_supports_enhanced_accept_synchronous_connection(c: &Controller) -> bool;
        fn controller_supports_ble_set_privacy_mode(c: &Controller) -> bool;

        fn controller_get_acl_buffer_length(c: &Controller) -> u16;
        fn controller_get_le_buffer_length(c: &Controller) -> u16;
        fn controller_get_iso_buffer_length(c: &Controller) -> u16;
        fn controller_get_le_suggested_default_data_length(c: &Controller) -> u16;
        fn controller_get_le_maximum_tx_data_length(c: &Controller) -> u16;
        fn controller_get_le_max_advertising_data_length(c: &Controller) -> u16;
        fn controller_get_le_supported_advertising_sets(c: &Controller) -> u8;
        fn controller_get_le_periodic_advertiser_list_size(c: &Controller) -> u8;
        fn controller_get_acl_buffers(c: &Controller) -> u16;
        fn controller_get_le_buffers(c: &Controller) -> u8;
        fn controller_get_iso_buffers(c: &Controller) -> u8;
        fn controller_get_le_connect_list_size(c: &Controller) -> u8;
        fn controller_get_le_resolving_list_size(c: &Controller) -> u8;
        fn controller_get_le_supported_states(c: &Controller) -> u64;

        fn controller_get_address(c: &Controller) -> String;
    }
}

pub type Controller = Arc<ControllerExports>;

macro_rules! feature_getters {
    ($($id:ident),*) => {
        paste! {
            $(
                fn [<controller_supports_ $id>](c: &Controller) -> bool {
                    c.features.$id
                }
            )*
        }
    }
}

feature_getters! {
    simple_pairing,
    secure_connections,
    simultaneous_le_bredr,
    interlaced_inquiry_scan,
    rssi_with_inquiry_results,
    extended_inquiry_response,
    role_switch,
    three_slot_packets,
    five_slot_packets,
    classic_2m_phy,
    classic_3m_phy,
    three_slot_edr_packets,
    five_slot_edr_packets,
    sco,
    hv2_packets,
    hv3_packets,
    ev3_packets,
    ev4_packets,
    ev5_packets,
    esco_2m_phy,
    esco_3m_phy,
    three_slot_esco_edr_packets,
    hold_mode,
    sniff_mode,
    park_mode,
    non_flushable_pb,
    sniff_subrating,
    encryption_pause,
    ble
}

macro_rules! le_feature_getters {
    ($($id:ident),*) => {
        paste! {
            $(
                fn [<controller_supports_ $id>](c: &Controller) -> bool {
                    c.le_features.$id
                }
            )*
        }
    }
}

le_feature_getters! {
    privacy,
    packet_extension,
    connection_parameters_request,
    ble_2m_phy,
    ble_coded_phy,
    extended_advertising,
    periodic_advertising,
    peripheral_initiated_feature_exchange,
    connection_parameter_request,
    periodic_advertising_sync_transfer_sender,
    periodic_advertising_sync_transfer_recipient,
    connected_iso_stream_central,
    connected_iso_stream_peripheral,
    iso_broadcaster,
    synchronized_receiver
}

macro_rules! opcode_getters {
    ($($id:ident => $opcode:path),*) => {
        paste! {
            $(
                fn [<controller_supports_ $id>](c: &Controller) -> bool {
                    c.commands.is_supported($opcode)
                }
            )*
        }
    }
}

opcode_getters! {
    reading_remote_extended_features => OpCode::ReadRemoteSupportedFeatures,
    enhanced_setup_synchronous_connection => OpCode::EnhancedSetupSynchronousConnection,
    enhanced_accept_synchronous_connection => OpCode::EnhancedAcceptSynchronousConnection,
    ble_set_privacy_mode => OpCode::LeSetPrivacyMode
}

macro_rules! field_getters {
    ($($id:ident : $type:ty),*) => {
        paste! {
            $(
                fn [<controller_get_ $id>](c: &Controller) -> $type {
                    c.$id
                }
            )*
        }
    }
}

field_getters! {
    acl_buffer_length: u16,
    le_buffer_length: u16,
    iso_buffer_length: u16,
    le_suggested_default_data_length: u16,
    le_max_advertising_data_length: u16,
    le_supported_advertising_sets: u8,
    le_periodic_advertiser_list_size: u8,
    acl_buffers: u16,
    le_buffers: u8,
    iso_buffers: u8,
    le_connect_list_size: u8,
    le_resolving_list_size: u8,
    le_supported_states: u64
}

fn controller_get_le_maximum_tx_data_length(c: &Controller) -> u16 {
    c.le_max_data_length.supported_max_tx_octets
}

fn controller_get_address(c: &Controller) -> String {
    c.address.to_string()
}
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#[macro_use]
extern crate lazy_static;

mod controller;
mod hci;
mod init_flags;
mod message_loop_thread;
Loading