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

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

Merge "Refactor topshim with bindgen and unsafe code"

parents cd544d26 1927afa4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ class HostBuild():
        self.env['CARGO_TARGET_DIR'] = self.output_dir
        self.env['CARGO_HOME'] = os.path.join(self.output_dir, 'cargo_home')
        self.env['RUSTFLAGS'] = self._generate_rustflags()
        self.env['CXX_ROOT_PATH'] = os.path.join(self.platform_dir, 'bt')

        # Configure some GN variables
        if self.use_board:
+33 −85
Original line number Diff line number Diff line
use bt_topshim::btif;
use bt_topshim::btif::{ffi, BluetoothCallbacks, BluetoothInterface};
use bt_topshim::btif::{BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface};
use bt_topshim::topstack;
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::TryFrom;
use std::env;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::mpsc;
use tokio::sync::mpsc::{Receiver, Sender};
@@ -14,126 +13,70 @@ use tokio::time::sleep;
// Required so that bt_shim is linked into the final image
extern crate bt_shim;

enum Callbacks {
    AdapterStateChanged(btif::BtState),
    AdapterPropertiesChanged(i32, i32, Vec<ffi::BtProperty>),
    RemoteDevicePropertiesChanged(i32, ffi::RustRawAddress, i32, Vec<ffi::BtProperty>),
    DeviceFound(i32, Vec<ffi::BtProperty>),
    DiscoveryStateChanged(btif::BtDiscoveryState),
}
struct Context {
    tx: Sender<Callbacks>,
    rx: Receiver<Callbacks>,
    callbacks: Arc<BluetoothCallbacks>,
    tx: Sender<BaseCallbacks>,
    rx: Receiver<BaseCallbacks>,
    dispatcher: Option<BaseCallbacksDispatcher>,
    intf: BluetoothInterface,
}

fn make_context(intf: BluetoothInterface) -> Context {
    let (tx, rx) = mpsc::channel::<Callbacks>(1);
    let (tx, rx) = mpsc::channel::<BaseCallbacks>(1);

    let (tx1, tx2, tx3, tx4, tx5) = (tx.clone(), tx.clone(), tx.clone(), tx.clone(), tx.clone());
    let cb = Arc::new(BluetoothCallbacks {
        adapter_state_changed: Box::new(move |state| {
    let tx1 = tx.clone();
    let dispatcher = btif::BaseCallbacksDispatcher {
        dispatch: Box::new(move |cb| {
            let txl = tx1.clone();
            topstack::get_runtime().spawn(async move {
                txl.send(Callbacks::AdapterStateChanged(state)).await;
            });
        }),
        adapter_properties_changed: Box::new(move |status, count, props| {
            let txl = tx2.clone();
            topstack::get_runtime().spawn(async move {
                txl.send(Callbacks::AdapterPropertiesChanged(status, count, props)).await;
            });
        }),
        remote_device_properties_changed: Box::new(move |status, address, count, props| {
            let txl = tx5.clone();
            topstack::get_runtime().spawn(async move {
                txl.send(Callbacks::RemoteDevicePropertiesChanged(status, address, count, props));
            });
        }),
        device_found: Box::new(move |count, props| {
            let txl = tx3.clone();
            topstack::get_runtime().spawn(async move {
                txl.send(Callbacks::DeviceFound(count, props)).await;
            });
        }),
        discovery_state_changed: Box::new(move |state| {
            let txl = tx4.clone();
            topstack::get_runtime().spawn(async move {
                txl.send(Callbacks::DiscoveryStateChanged(state)).await;
                txl.send(cb).await;
            });
        }),
        pin_request: Box::new(move |_address, _bdname, _cod, _min_16_digit| {
            println!("Pin request callback");
        }),
        ssp_request: Box::new(move |_address, _bdname, _cod, _variant, _passkey| {
            println!("Ssp request callback");
        }),
        bond_state_changed: Box::new(move |_status, _address, _state| {
            println!("Bond state changed");
        }),
        acl_state_changed: Box::new(move |_status, _address, _state, _hci_reason| {
            println!("Acl state changed");
        }),
    });
    };

    return Context { tx, rx, callbacks: cb, intf };
    return Context { tx, rx, dispatcher: Some(dispatcher), intf };
}

async fn mainloop(context: &mut Context) {
    'main: while let Some(cb) = context.rx.recv().await {
        match cb {
            Callbacks::AdapterStateChanged(state) => {
                println!("Adapter state changed to {}", state.to_i32().unwrap());
            BaseCallbacks::AdapterState(state) => {
                println!("Adapter state changed to {}", state.to_u32().unwrap());

                if state == btif::BtState::On {
                    context.intf.get_adapter_properties();
                }
            }
            Callbacks::AdapterPropertiesChanged(status, _count, properties) => {
                if status != 0 {
                    println!("Failed property change: {}", status);
            BaseCallbacks::AdapterProperties(status, _count, properties) => {
                if status != btif::BtStatus::Success {
                    println!("Failed property change: {:?}", status);
                }

                for p in properties {
                    let proptype = match btif::BtPropertyType::from_i32(p.prop_type) {
                        Some(x) => x,
                        None => btif::BtPropertyType::Unknown,
                    };
                    println!("Property {:?} is ({:?})", proptype, p.val);
                    println!("Property {:?} is ({:?})", p.prop_type, p.val);
                }

                // Scan for 5s and then cancel
                println!("Starting discovery");
                context.intf.start_discovery();
            }
            Callbacks::RemoteDevicePropertiesChanged(status, address, _count, properties) => {
                if status != 0 {
                    println!("Failed remote property change: {}", status);
            BaseCallbacks::RemoteDeviceProperties(status, address, _count, properties) => {
                if status != btif::BtStatus::Success {
                    println!("Failed remote property change: {:?}", status);
                }

                println!("Properties for {:?}", address.address);

                for p in properties {
                    let proptype = match btif::BtPropertyType::from_i32(p.prop_type) {
                        Some(x) => x,
                        None => btif::BtPropertyType::Unknown,
                    };
                    println!("Property {:?} is ({:?})", proptype, p.val);
                    println!("Property {:?} is ({:?})", p.prop_type, p.val);
                }
            }
            Callbacks::DeviceFound(_count, properties) => {
            BaseCallbacks::DeviceFound(_count, properties) => {
                print!("Device found: ");

                for p in properties {
                    let proptype = match btif::BtPropertyType::from_i32(p.prop_type) {
                        Some(x) => x,
                        None => btif::BtPropertyType::Unknown,
                    };

                    if proptype == btif::BtPropertyType::BdAddr {
                    if p.prop_type == btif::BtPropertyType::BdAddr {
                        print!(" Addr[{:?}]", p.val);
                    } else if proptype == btif::BtPropertyType::BdName {
                    } else if p.prop_type == btif::BtPropertyType::BdName {
                        print!(
                            " Name[{:?}]",
                            p.val.iter().map(|u| char::try_from(*u).unwrap()).collect::<String>()
@@ -143,7 +86,7 @@ async fn mainloop(context: &mut Context) {

                println!("");
            }
            Callbacks::DiscoveryStateChanged(state) => {
            BaseCallbacks::DiscoveryState(state) => {
                if state == btif::BtDiscoveryState::Started {
                    sleep(Duration::from_millis(5000)).await;
                    context.intf.cancel_discovery();
@@ -151,6 +94,7 @@ async fn mainloop(context: &mut Context) {
                    break 'main;
                }
            }
            _ => println!("{:?}", cb),
        }
    }
}
@@ -162,14 +106,18 @@ fn main() {
    let all_args: Vec<String> = env::args().collect();
    let args = all_args[1..].to_vec();

    let intf = BluetoothInterface::new();
    let intf = btif::get_btinterface().expect("Couldn't get bluetooth interface");
    let mut context = make_context(intf);

    topstack::get_runtime().block_on(async move {
        if !context.intf.initialize(context.callbacks.clone(), args) {
        if let Some(dispatcher) = context.dispatcher {
            if !context.intf.initialize(dispatcher, args) {
                panic!("Couldn't initialize bluetooth interface!");
            }

            context.dispatcher = None;
        }

        println!("Enabling...");
        context.intf.enable();

+4 −4
Original line number Diff line number Diff line
use bt_topshim::btif::BluetoothInterface;
use bt_topshim::btif::get_btinterface;
use bt_topshim::topstack;

use dbus::channel::MatchingReceiver;
@@ -12,7 +12,7 @@ use dbus_tokio::connection;

use futures::future;

use btstack::bluetooth::btif_bluetooth_callbacks;
use btstack::bluetooth::get_bt_dispatcher;
use btstack::bluetooth::Bluetooth;
use btstack::bluetooth_gatt::BluetoothGatt;
use btstack::Stack;
@@ -32,7 +32,7 @@ const OBJECT_BLUETOOTH_GATT: &str = "/org/chromium/bluetooth/gatt";
fn main() -> Result<(), Box<dyn Error>> {
    let (tx, rx) = Stack::create_channel();

    let intf = Arc::new(Mutex::new(BluetoothInterface::new()));
    let intf = Arc::new(Mutex::new(get_btinterface().unwrap()));
    let bluetooth = Arc::new(Mutex::new(Bluetooth::new(tx.clone(), intf.clone())));
    let bluetooth_gatt = Arc::new(Mutex::new(BluetoothGatt::new(intf.clone())));

@@ -59,7 +59,7 @@ fn main() -> Result<(), Box<dyn Error>> {
            }),
        )));

        intf.lock().unwrap().initialize(Arc::new(btif_bluetooth_callbacks(tx)), vec![]);
        intf.lock().unwrap().initialize(get_bt_dispatcher(tx), vec![]);

        // Run the stack main dispatch loop.
        topstack::get_runtime().spawn(Stack::dispatch(rx, bluetooth.clone()));
+19 −37
Original line number Diff line number Diff line
//! Anything related to the adapter API (IBluetooth).

use bt_topshim::btif::ffi;
use bt_topshim::btif::{BluetoothCallbacks, BluetoothInterface, BtState};
use bt_topshim::btif::{
    BaseCallbacksDispatcher, BluetoothInterface, BtProperty, BtPropertyType, BtState, BtStatus,
};
use bt_topshim::topstack;

use btif_macros::btif_callbacks_generator;
@@ -82,39 +83,26 @@ impl Bluetooth {
    }
}

#[btif_callbacks_generator(btif_bluetooth_callbacks, BluetoothCallbacks)]
pub(crate) trait BtifBluetoothCallbacks {
    #[stack_message(BluetoothAdapterStateChanged)]
    fn adapter_state_changed(&mut self, state: BtState);

    #[stack_message(BluetoothAdapterPropertiesChanged)]
    fn adapter_properties_changed(
        &mut self,
        status: i32,
        status: BtStatus,
        num_properties: i32,
        properties: Vec<ffi::BtProperty>,
        properties: Vec<BtProperty>,
    );
}

#[derive(FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
#[repr(i32)]
#[derive(Debug)]
enum PropertyType {
    BDName = 0x01,
    BDAddr,
    Uuids,
    ClassOfDevice,
    TypeOfDevice,
    ServiceRecord,
    AdapterScanMode,
    AdapterBondedDevices,
    AdapterDiscoverableTimeout,
    RemoteFriendlyName,
    RemoteRssi,
    RemoteVersionInfo,
    RemoteLocalLeFeatures,
    RemoteDynamicAudioBuffer = 0x10,
    Unknown = 0x100,
pub fn get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher {
    BaseCallbacksDispatcher {
        dispatch: Box::new(move |cb| {
            let txl = tx.clone();
            topstack::get_runtime().spawn(async move {
                txl.send(Message::Base(cb)).await;
            });
        }),
    }
}

impl BtifBluetoothCallbacks for Bluetooth {
@@ -131,23 +119,17 @@ impl BtifBluetoothCallbacks for Bluetooth {
    #[allow(unused_variables)]
    fn adapter_properties_changed(
        &mut self,
        status: i32,
        status: BtStatus,
        num_properties: i32,
        properties: Vec<ffi::BtProperty>,
        properties: Vec<BtProperty>,
    ) {
        if status != 0 {
        if status != BtStatus::Success {
            return;
        }

        for prop in properties {
            let prop_type = PropertyType::from_i32(prop.prop_type);

            if prop_type.is_none() {
                continue;
            }

            match prop_type.unwrap() {
                PropertyType::BDAddr => {
            match prop.prop_type {
                BtPropertyType::BdAddr => {
                    self.update_local_address(&prop.val);
                }
                _ => {}
+17 −14
Original line number Diff line number Diff line
@@ -9,8 +9,8 @@ extern crate num_derive;
pub mod bluetooth;
pub mod bluetooth_gatt;

use bt_topshim::btif::ffi;
use bt_topshim::btif::BtState;
use bt_topshim::btif::{BaseCallbacks, BaseCallbacksDispatcher};

use std::convert::TryInto;
use std::fmt::{Debug, Formatter, Result};
@@ -55,8 +55,7 @@ impl BDAddr {

/// Message types that are sent to the stack main dispatch loop.
pub enum Message {
    BluetoothAdapterStateChanged(BtState),
    BluetoothAdapterPropertiesChanged(i32, i32, Vec<ffi::BtProperty>),
    Base(BaseCallbacks),
    BluetoothCallbackDisconnected(u32),
}

@@ -80,11 +79,12 @@ impl Stack {
            }

            match m.unwrap() {
                Message::BluetoothAdapterStateChanged(state) => {
                Message::Base(b) => match b {
                    BaseCallbacks::AdapterState(state) => {
                        bluetooth.lock().unwrap().adapter_state_changed(state);
                    }

                Message::BluetoothAdapterPropertiesChanged(status, num_properties, properties) => {
                    BaseCallbacks::AdapterProperties(status, num_properties, properties) => {
                        bluetooth.lock().unwrap().adapter_properties_changed(
                            status,
                            num_properties,
@@ -92,6 +92,9 @@ impl Stack {
                        );
                    }

                    _ => println!("Unhandled callback arm {:?}", b),
                },

                Message::BluetoothCallbackDisconnected(id) => {
                    bluetooth.lock().unwrap().callback_disconnected(id);
                }
Loading