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

Commit 0ccc3758 authored by Sonny Sasaka's avatar Sonny Sasaka Committed by Gerrit Code Review
Browse files

Merge changes I12391f4e,I3bdf0ea0,I10ff16d7,I58caec1f

* changes:
  Add D-Bus daemon binary
  Add `dbus_projection` crate
  Add the `btstack` crate
  Add topshim for bluetooth interface
parents 298711c2 bac6a529
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@

members = [
  "gd/rust/shim",
  "gd/rust/topshim",
  "gd/rust/linux/mgmt",
  "gd/rust/linux/adapter",
  "gd/rust/linux/service",
]
+2 −1
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ static_library("libbluetooth_gd") {
  include_dirs = [ "." ]
  configs += [ ":gd_defaults" ]
  deps = [
    "//bt/gd/rust/topshim:libbluetooth_topshim",
    "//bt/gd/rust/shim:libbluetooth_rust_interop",
    "//bt/gd:BluetoothGeneratedPackets_h",
    "//bt/gd/att:BluetoothAttSources",
    "//bt/gd/common:BluetoothCommonSources",
@@ -71,7 +73,6 @@ static_library("libbluetooth_gd") {
    "//bt/gd/hal:BluetoothHalSources_hci_host",
    "//bt/gd/l2cap:BluetoothL2capSources",
    "//bt/gd/neighbor:BluetoothNeighborSources",
    "//bt/gd/rust/shim:libbluetooth_rust_interop",
    "//bt/gd/security:BluetoothSecuritySources",
    "//bt/gd/shim:BluetoothShimSources",
    "//bt/gd/storage:BluetoothStorageSources",
+7 −1
Original line number Diff line number Diff line
@@ -20,12 +20,18 @@ edition = "2018"

[dependencies]
# BT dependencies
bt_topshim = { path = "../../topshim" }
bt_shim = { path = "../../shim" }

num-traits = "*"
num-derive = "*"
tokio = { version = "1.0", features = ['bytes', 'fs', 'io-util', 'libc', 'macros', 'memchr', 'mio', 'net', 'num_cpus', 'rt', 'rt-multi-thread', 'sync', 'time', 'tokio-macros'] }
tokio-stream = "0.1"

[build-dependencies]
pkg-config = "0.3"

[[bin]]
name = "bluetoothd"
path = "src/main.rs"
build = "build.rs"
+177 −0
Original line number Diff line number Diff line
use bt_topshim::btif;
use bt_topshim::btif::{ffi, BluetoothCallbacks, 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};
use tokio::time::sleep;

// DO NOT REMOVE
// 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>,
    intf: BluetoothInterface,
}

fn make_context(intf: BluetoothInterface) -> Context {
    let (tx, rx) = mpsc::channel::<Callbacks>(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 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;
            });
        }),
        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 };
}

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());

                if state == btif::BtState::On {
                    context.intf.get_adapter_properties();
                }
            }
            Callbacks::AdapterPropertiesChanged(status, _count, properties) => {
                if status != 0 {
                    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);
                }

                // 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);
                }

                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);
                }
            }
            Callbacks::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 {
                        print!(" Addr[{:?}]", p.val);
                    } else if proptype == btif::BtPropertyType::BdName {
                        print!(
                            " Name[{:?}]",
                            p.val.iter().map(|u| char::try_from(*u).unwrap()).collect::<String>()
                        );
                    }
                }

                println!("");
            }
            Callbacks::DiscoveryStateChanged(state) => {
                if state == btif::BtDiscoveryState::Started {
                    sleep(Duration::from_millis(5000)).await;
                    context.intf.cancel_discovery();

                    break 'main;
                }
            }
        }
    }
}

fn main() {
    println!("Bluetooth Adapter Daemon");

    // Drop the first arg (which is the binary name)
    let all_args: Vec<String> = env::args().collect();
    let args = all_args[1..].to_vec();

    let intf = BluetoothInterface::new();
    let mut context = make_context(intf);

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

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

        println!("Running mainloop now");
        mainloop(&mut context).await;

        println!("Disabling and exiting...");
        context.intf.disable();
    });
}
+7 −0
Original line number Diff line number Diff line
[package]
name = "dbus_projection"
version = "0.1.0"
edition = "2018"

[dependencies]
dbus = "0.9.2"
Loading