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

Commit 07f88a80 authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi
Browse files

floss: Add socket manager implementation

Add IBluetoothSocketManager and wire it into the stack.

Bug: 233123287
Tag: #floss
Test: Manual tests on ChromeOS
Change-Id: I5c6660cffa49ac445daab2ca3d3cbc24804d112c
parent 90588f54
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -291,9 +291,9 @@ macro_rules! impl_dbus_arg_from_into {
                    Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
                >,
            ) -> Result<$rust_type, Box<dyn std::error::Error>> {
                match <$rust_type>::try_from(data) {
                match <$rust_type>::try_from(data.clone()) {
                    Err(e) => Err(Box::new(DBusArgError::new(String::from(format!(
                        "error converting {} to {}",
                        "error converting {:?} to {:?}",
                        data,
                        stringify!($rust_type),
                    ))))),
@@ -302,9 +302,9 @@ macro_rules! impl_dbus_arg_from_into {
            }

            fn to_dbus(data: $rust_type) -> Result<$dbus_type, Box<dyn std::error::Error>> {
                match data.try_into() {
                match data.clone().try_into() {
                    Err(e) => Err(Box::new(DBusArgError::new(String::from(format!(
                        "error converting {:?} to {}",
                        "error converting {:?} to {:?}",
                        data,
                        stringify!($dbus_type)
                    ))))),
+63 −3
Original line number Diff line number Diff line
extern crate bt_shim;

use bt_topshim::btif::{BtDeviceType, BtPropertyType, BtSspVariant, BtTransport, Uuid128Bit};
use bt_topshim::btif::{BtDeviceType, BtPropertyType, BtSspVariant, BtTransport, Uuid, Uuid128Bit};
use bt_topshim::profiles::socket::SocketType;

use btstack::bluetooth::{
    Bluetooth, BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
};
use btstack::socket_manager::{BluetoothSocketManager, IBluetoothSocketManager};
use btstack::suspend::{ISuspend, ISuspendCallback, Suspend, SuspendType};
use btstack::uuid::Profile;
use btstack::RPCProxy;
@@ -15,19 +17,35 @@ use dbus::strings::Path;
use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter};

use dbus_projection::DisconnectWatcher;
use dbus_projection::{dbus_generated, impl_dbus_arg_enum};
use dbus_projection::{dbus_generated, impl_dbus_arg_enum, impl_dbus_arg_from_into};

use num_traits::cast::{FromPrimitive, ToPrimitive};

use std::convert::{TryFrom, TryInto};
use std::sync::{Arc, Mutex};

use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust};

/// A mixin of the adapter and suspend interfaces. The naming of the fields in the mixin must match
// Represents Uuid as an array in D-Bus.
impl_dbus_arg_from_into!(Uuid, Vec<u8>);

impl RefArgToRust for Uuid {
    type RustType = Vec<u8>;

    fn ref_arg_to_rust(
        arg: &(dyn dbus::arg::RefArg + 'static),
        name: String,
    ) -> Result<Self::RustType, Box<dyn std::error::Error>> {
        <Vec<u8> as RefArgToRust>::ref_arg_to_rust(arg, name)
    }
}

/// A mixin of the several interfaces. The naming of the fields in the mixin must match
/// what is listed in the `generate_dbus_exporter` invocation.
pub struct BluetoothMixin {
    pub adapter: Arc<Mutex<Box<Bluetooth>>>,
    pub suspend: Arc<Mutex<Box<Suspend>>>,
    pub socket_mgr: Arc<Mutex<Box<BluetoothSocketManager>>>,
}

#[dbus_propmap(BluetoothDevice)]
@@ -322,6 +340,48 @@ impl IBluetooth for IBluetoothDBus {
    }
}

impl_dbus_arg_enum!(SocketType);

#[allow(dead_code)]
struct IBluetoothSocketManagerDBus {}

#[generate_dbus_exporter(
    export_socket_mgr_intf,
    "org.chromium.bluetooth.SocketManager",
    BluetoothMixin,
    socket_mgr
)]
impl IBluetoothSocketManager for IBluetoothSocketManagerDBus {
    #[dbus_method("ConnectSocket")]
    fn connect_socket(
        &mut self,
        device: BluetoothDevice,
        sock_type: SocketType,
        uuid: Option<Uuid>,
        port: i32,
        flags: i32,
    ) -> Option<std::fs::File> {
        dbus_generated!()
    }

    #[dbus_method("CreateSocketChannel")]
    fn create_socket_channel(
        &mut self,
        sock_type: SocketType,
        service_name: String,
        uuid: Option<Uuid>,
        port: i32,
        flags: i32,
    ) -> Option<std::fs::File> {
        dbus_generated!()
    }

    #[dbus_method("RequestMaximumTxDataLength")]
    fn request_maximum_tx_data_length(&mut self, device: BluetoothDevice) {
        dbus_generated!()
    }
}

impl_dbus_arg_enum!(SuspendType);

#[allow(dead_code)]
+9 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ use btstack::{
    bluetooth::{get_bt_dispatcher, Bluetooth, IBluetooth},
    bluetooth_gatt::BluetoothGatt,
    bluetooth_media::BluetoothMedia,
    socket_manager::BluetoothSocketManager,
    suspend::Suspend,
    Stack,
};
@@ -87,6 +88,7 @@ fn main() -> Result<(), Box<dyn Error>> {
        intf.clone(),
        bluetooth_media.clone(),
    ))));
    let bt_sock_mgr = Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(intf.clone()))));

    topstack::get_runtime().block_on(async {
        // Connect to D-Bus system bus.
@@ -148,6 +150,11 @@ fn main() -> Result<(), Box<dyn Error>> {
            &mut cr.lock().unwrap(),
            disconnect_watcher.clone(),
        );
        let socket_mgr_iface = iface_bluetooth::export_socket_mgr_intf(
            conn.clone(),
            &mut cr.lock().unwrap(),
            disconnect_watcher.clone(),
        );
        let suspend_iface = iface_bluetooth::export_suspend_dbus_intf(
            conn.clone(),
            &mut cr.lock().unwrap(),
@@ -171,11 +178,12 @@ fn main() -> Result<(), Box<dyn Error>> {
        let mixin = Box::new(iface_bluetooth::BluetoothMixin {
            adapter: bluetooth.clone(),
            suspend: suspend.clone(),
            socket_mgr: bt_sock_mgr.clone(),
        });

        cr.lock().unwrap().insert(
            make_object_name(adapter_index, "adapter"),
            &[adapter_iface, suspend_iface],
            &[adapter_iface, socket_mgr_iface, suspend_iface],
            mixin,
        );

+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ extern crate num_derive;
pub mod bluetooth;
pub mod bluetooth_gatt;
pub mod bluetooth_media;
pub mod socket_manager;
pub mod suspend;
pub mod uuid;

+173 −0
Original line number Diff line number Diff line
//! Implementation of the Socket API (IBluetoothSocketManager).

use crate::bluetooth::BluetoothDevice;
use crate::uuid::UuidHelper;
use bt_topshim::btif::{BluetoothInterface, RawAddress, Uuid};
use bt_topshim::profiles::socket::{BtSocket, SocketType};

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

pub trait IBluetoothSocketManager {
    /// Connects L2CAP or RFCOMM socket to remote device.
    ///
    /// # Args
    /// `device`: Remote device to connect with.
    /// `sock_type`: Type of socket to open.
    /// `uuid`: Optional service uuid for RFCOMM connections.
    /// `port`: Either channel (RFCOMM) or PSM (L2CAP).
    /// `flags`: Additional flags on the socket. Reserved for now.
    ///
    /// # Returns
    ///
    /// Optional file descriptor if the connection succeeds.
    fn connect_socket(
        &mut self,
        device: BluetoothDevice,
        sock_type: SocketType,
        uuid: Option<Uuid>,
        port: i32,
        flags: i32,
    ) -> Option<std::fs::File>;

    /// Listen to a RFCOMM UUID or L2CAP channel.
    ///
    /// # Args
    /// `sock_type`:
    /// `service_name`:
    /// `uuid`:
    /// `port`:
    /// `flags`:
    ///
    /// # Returns
    ///
    /// Optional file descriptor if listening socket was established successfully.
    fn create_socket_channel(
        &mut self,
        sock_type: SocketType,
        service_name: String,
        uuid: Option<Uuid>,
        port: i32,
        flags: i32,
    ) -> Option<std::fs::File>;

    /// Set the LE Data Length value for this connected peer to the maximum
    /// supported by this BT controller.
    ///
    /// # Args
    /// `device`: Connected remote device to apply this setting against.
    fn request_maximum_tx_data_length(&mut self, device: BluetoothDevice);
}

/// Implementation of the `IBluetoothSocketManager` api.
pub struct BluetoothSocketManager {
    sock: BtSocket,
}

impl BluetoothSocketManager {
    /// Constructs the IBluetooth implementation.
    pub fn new(intf: Arc<Mutex<BluetoothInterface>>) -> Self {
        let sock = BtSocket::new(&intf.lock().unwrap());
        BluetoothSocketManager { sock }
    }

    // TODO(abps) - We need to save information about who the caller is so that
    //              we can pipe it down to the lower levels. This needs to be
    //              provided by the projection layer and is currently missing.
    fn get_caller_uid(&self) -> i32 {
        0
    }
}

impl IBluetoothSocketManager for BluetoothSocketManager {
    fn connect_socket(
        &mut self,
        device: BluetoothDevice,
        sock_type: SocketType,
        uuid: Option<Uuid>,
        port: i32,
        flags: i32,
    ) -> Option<std::fs::File> {
        let addr = match RawAddress::from_string(device.address.clone()) {
            Some(r) => r,
            None => {
                warn!("Invalid address on connect to socket: {}", device.address);
                return None;
            }
        };

        let uu = match uuid {
            Some(v) => Some(v.uu.clone()),
            None => None,
        };

        let (status, result) =
            self.sock.connect(addr, sock_type.clone(), uu, port, flags, self.get_caller_uid());

        match result {
            Ok(fd) => Some(fd),
            Err(_) => {
                warn!(
                    "Failed to connect to socket at [{}]:{}, type={:?}, uuid={}. Status={:?}",
                    device.address,
                    port,
                    sock_type,
                    match uu {
                        Some(u) => UuidHelper::to_string(&u),
                        None => "".to_string(),
                    },
                    status
                );
                None
            }
        }
    }

    fn create_socket_channel(
        &mut self,
        sock_type: SocketType,
        service_name: String,
        uuid: Option<Uuid>,
        port: i32,
        flags: i32,
    ) -> Option<std::fs::File> {
        let uu = match uuid {
            Some(v) => Some(v.uu.clone()),
            None => None,
        };

        let (status, result) = self.sock.listen(
            sock_type.clone(),
            service_name.clone(),
            uu,
            port,
            flags,
            self.get_caller_uid(),
        );

        match result {
            Ok(fd) => Some(fd),
            Err(_) => {
                warn!(
                    "Failed to create socket channel on port {}, type {:?}, name={}, uuid={}. Status={:?}",
                    port, sock_type, service_name, match uu {
                        Some(u) => UuidHelper::to_string(&u),
                        None => "".to_string(),
                    }, status);
                None
            }
        }
    }

    fn request_maximum_tx_data_length(&mut self, device: BluetoothDevice) {
        let addr = match RawAddress::from_string(device.address.clone()) {
            Some(r) => r,
            None => {
                warn!("Invalid address requesting max tx data length: {}", device.address);
                return;
            }
        };

        self.sock.request_max_tx_data_length(addr);
    }
}
Loading