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

Commit d6077220 authored by Sonny Sasaka's avatar Sonny Sasaka
Browse files

Add command line client

This adds the minimal command line client with Bluetooth stack embedded
into the client. Future work will add support for the Bluetooth stack
over D-Bus.

Bug: 188718349
Tag: #floss
Test: manual - Build floss on Linux, run btclient

Change-Id: If525ab7653b85d108b4eb3303fe5e1761a43f2c8
parent 33efa9a4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,4 +20,5 @@ members = [
  "gd/rust/topshim",
  "gd/rust/linux/mgmt",
  "gd/rust/linux/service",
  "gd/rust/linux/client",
]
+22 −0
Original line number Diff line number Diff line
[package]
name = "client"
version = "0.1.0"
edition = "2018"

[dependencies]
rustyline = "8.0"
bt_topshim = { path = "../../topshim" }
bt_shim = { path = "../../shim" }
btstack = { path = "../stack" }

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

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

[[bin]]
name = "btclient"
path = "src/main.rs"
build = "build.rs"
+27 −0
Original line number Diff line number Diff line
use pkg_config::Config;

fn main() {
    let target_dir = std::env::var_os("CARGO_TARGET_DIR").unwrap();

    // The main linking point with c++ code is the libbluetooth-static.a
    // These includes all the symbols built via C++ but doesn't include other
    // links (i.e. pkg-config)
    println!("cargo:rustc-link-lib=static=bluetooth-static");
    println!("cargo:rustc-link-search=native={}", target_dir.into_string().unwrap());

    // A few dynamic links
    println!("cargo:rustc-link-lib=dylib=flatbuffers");
    println!("cargo:rustc-link-lib=dylib=protobuf");
    println!("cargo:rustc-link-lib=dylib=resolv");

    // Clang requires -lc++ instead of -lstdc++
    println!("cargo:rustc-link-lib=c++");

    // A few more dependencies from pkg-config. These aren't included as part of
    // the libbluetooth-static.a
    Config::new().probe("libchrome").unwrap();
    Config::new().probe("libmodp_b64").unwrap();
    Config::new().probe("tinyxml2").unwrap();

    println!("cargo:rerun-if-changed=build.rs");
}
+53 −0
Original line number Diff line number Diff line
use btstack::bluetooth::{BluetoothDevice, BluetoothTransport, IBluetooth};

use num_traits::cast::FromPrimitive;

use std::sync::{Arc, Mutex};

use crate::console_yellow;
use crate::print_info;

/// Handles string command entered from command line.
pub struct CommandHandler {
    bluetooth: Arc<Mutex<dyn IBluetooth>>,
}

impl CommandHandler {
    pub fn new(bluetooth: Arc<Mutex<dyn IBluetooth>>) -> CommandHandler {
        CommandHandler { bluetooth }
    }

    pub fn cmd_enable(&self, _cmd: String) {
        self.bluetooth.lock().unwrap().enable();
    }

    pub fn cmd_disable(&self, _cmd: String) {
        self.bluetooth.lock().unwrap().disable();
    }

    pub fn cmd_get_address(&self, _cmd: String) {
        let addr = self.bluetooth.lock().unwrap().get_address();
        print_info!("Local address = {}", addr);
    }

    pub fn cmd_start_discovery(&self, _cmd: String) {
        self.bluetooth.lock().unwrap().start_discovery();
    }

    pub fn cmd_cancel_discovery(&self, _cmd: String) {
        self.bluetooth.lock().unwrap().cancel_discovery();
    }

    pub fn cmd_create_bond(&self, cmd: String) {
        let s = cmd.split(' ').collect::<Vec<&str>>();
        if s.len() < 2 {
            println!("usage: create_bond <addr>");
            return;
        }
        let device = BluetoothDevice { address: String::from(s[1]), name: String::from("") };
        self.bluetooth
            .lock()
            .unwrap()
            .create_bond(device, BluetoothTransport::from_i32(0).unwrap());
    }
}
+25 −0
Original line number Diff line number Diff line
//! Convenient functions to print messages to console.

#[macro_export]
macro_rules! console_blue {
    ( $text:expr ) => {
        format!("\x1b[1;34m{}\x1b[0m", $text).as_str()
    };
}

#[macro_export]
macro_rules! console_yellow {
    ( $text:expr ) => {
        format!("\x1b[1;33m{}\x1b[0m", $text).as_str()
    };
}

#[macro_export]
macro_rules! print_info {
    ( $($arg:tt)* ) => {
        {
            print!("{}: ", console_yellow!("btclient:info"));
            println!($($arg)*);
        }
    };
}
Loading