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

Commit 98d6eb92 authored by Hsin-Yu Chao's avatar Hsin-Yu Chao Committed by Hansong Zhang
Browse files

Create shared RawAddress in topshim

This change consolidates a few BT addr into just one
shared struct under btif.

- Move BDAddr to btif and rename it to RawAddress.
- Use the new RawAddress as the shared addr struct.
- Create FfiAddress in each topshim submodule and
convert between the shared RawAddress at ffi boundary.

Bug: 189497374
Tag: #floss
Test: Manual test with audio server changes

Change-Id: I8e445d3292241ddecb97cbeb169b468a397a9bff
parent 432fb372
Loading
Loading
Loading
Loading
+7 −12
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ use std::sync::Mutex;

use tokio::sync::mpsc::Sender;

use crate::{BDAddr, Message, RPCProxy};
use crate::{Message, RPCProxy};

/// Defines the adapter API.
pub trait IBluetooth {
@@ -68,7 +68,7 @@ impl BluetoothDevice {
        for prop in properties {
            match prop.prop_type {
                BtPropertyType::BdAddr => {
                    if let Some(addr) = BDAddr::from_byte_vec(&prop.val) {
                    if let Some(addr) = RawAddress::from_bytes(&prop.val) {
                        address = addr.to_string();
                    }
                }
@@ -111,7 +111,7 @@ pub struct Bluetooth {
    callbacks: Vec<(u32, Box<dyn IBluetoothCallback + Send>)>,
    callbacks_last_id: u32,
    tx: Sender<Message>,
    local_address: Option<BDAddr>,
    local_address: Option<RawAddress>,
    hh: Option<HidHost>,
}

@@ -140,7 +140,7 @@ impl Bluetooth {
    }

    fn update_local_address(&mut self, raw: &Vec<u8>) {
        self.local_address = BDAddr::from_byte_vec(raw);
        self.local_address = RawAddress::from_bytes(raw);

        self.for_all_callbacks(|callback| {
            callback.on_address_changed(self.local_address.unwrap().to_string());
@@ -252,12 +252,7 @@ impl BtifBluetoothCallbacks for Bluetooth {
        // TODO: We need a way to select the default agent.
        self.for_all_callbacks(|callback| {
            callback.on_ssp_request(
                BluetoothDevice {
                    address: BDAddr::from_byte_vec(&remote_addr.address.to_vec())
                        .unwrap()
                        .to_string(),
                    name: remote_name.clone(),
                },
                BluetoothDevice { address: remote_addr.to_string(), name: remote_name.clone() },
                cod,
                variant.clone(),
                passkey,
@@ -320,14 +315,14 @@ impl IBluetooth for Bluetooth {
    }

    fn create_bond(&self, device: BluetoothDevice, transport: BluetoothTransport) -> bool {
        let addr = BDAddr::from_string(device.address.clone());
        let addr = RawAddress::from_string(device.address.clone());

        if addr.is_none() {
            println!("address {} is not valid", device.address);
            return false;
        }

        let address = unsafe { RawAddress::new(&addr.unwrap().val) };
        let address = addr.unwrap();
        self.intf
            .lock()
            .unwrap()
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

use bt_topshim::btif::BluetoothInterface;
use bt_topshim::profiles::a2dp::{
    A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, BtavConnectionState, RawAddress,
    A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, BtavConnectionState,
};
use bt_topshim::topstack;

+0 −65
Original line number Diff line number Diff line
@@ -13,8 +13,6 @@ pub mod bluetooth_media;
use bt_topshim::btif::BaseCallbacks;
use bt_topshim::profiles::a2dp::A2dpCallbacks;

use std::convert::TryInto;
use std::fmt::{Debug, Formatter, Result};
use std::sync::{Arc, Mutex};

use tokio::sync::mpsc::channel;
@@ -25,69 +23,6 @@ use crate::bluetooth_media::BluetoothMedia;

/// Represents a Bluetooth address.
// TODO: Add support for LE random addresses.
#[derive(Copy, Clone)]
pub struct BDAddr {
    val: [u8; 6],
}

impl Debug for BDAddr {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        f.write_fmt(format_args!(
            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
            self.val[0], self.val[1], self.val[2], self.val[3], self.val[4], self.val[5]
        ))
    }
}

impl Default for BDAddr {
    fn default() -> Self {
        Self { val: [0; 6] }
    }
}

impl ToString for BDAddr {
    fn to_string(&self) -> String {
        String::from(format!(
            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
            self.val[0], self.val[1], self.val[2], self.val[3], self.val[4], self.val[5]
        ))
    }
}

impl BDAddr {
    /// Constructs a BDAddr from a vector of 6 bytes.
    pub fn from_byte_vec(raw_addr: &Vec<u8>) -> Option<BDAddr> {
        if let Ok(val) = raw_addr.clone().try_into() {
            return Some(BDAddr { val });
        }
        None
    }

    pub fn from_string<S: Into<String>>(addr: S) -> Option<BDAddr> {
        let addr: String = addr.into();
        let s = addr.split(':').collect::<Vec<&str>>();

        if s.len() != 6 {
            return None;
        }

        let mut raw: [u8; 6] = [0; 6];
        for i in 0..s.len() {
            raw[i] = match u8::from_str_radix(s[i], 16) {
                Ok(res) => res,
                Err(_) => {
                    return None;
                }
            };
        }

        Some(BDAddr { val: raw })
    }

    pub fn to_byte_arr(&self) -> [u8; 6] {
        self.val.clone()
    }
}

/// Message types that are sent to the stack main dispatch loop.
pub enum Message {
+147 −20
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
use crate::bindings::root as bindings;
use crate::topstack::get_dispatchers;
use num_traits::cast::{FromPrimitive, ToPrimitive};
use std::fmt::{Debug, Formatter, Result};
use std::sync::{Arc, Mutex};
use std::vec::Vec;
use topshim_macros::cb_variant;
@@ -262,7 +263,98 @@ mod ffi {
}

// Export the raw address type directly from the bindings
pub type RawAddress = bindings::RawAddress;
type FfiAddress = bindings::RawAddress;

/// A shared address structure that has the same representation as
/// bindings::RawAddress. Macros `deref_ffi_address` and `cast_to_ffi_address`
/// are used for transforming between bindings::RawAddress at ffi boundaries.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct RawAddress {
    pub val: [u8; 6],
}

impl Debug for RawAddress {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        f.write_fmt(format_args!(
            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
            self.val[0], self.val[1], self.val[2], self.val[3], self.val[4], self.val[5]
        ))
    }
}

impl Default for RawAddress {
    fn default() -> Self {
        Self { val: [0; 6] }
    }
}

impl ToString for RawAddress {
    fn to_string(&self) -> String {
        String::from(format!(
            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
            self.val[0], self.val[1], self.val[2], self.val[3], self.val[4], self.val[5]
        ))
    }
}

impl RawAddress {
    /// Constructs a RawAddress from a slice of 6 bytes.
    pub fn from_bytes(raw_addr: &[u8]) -> Option<RawAddress> {
        if raw_addr.len() != 6 {
            return None;
        }
        let mut raw: [u8; 6] = [0; 6];
        raw.copy_from_slice(raw_addr);
        return Some(RawAddress { val: raw });
    }

    pub fn from_string<S: Into<String>>(addr: S) -> Option<RawAddress> {
        let addr: String = addr.into();
        let s = addr.split(':').collect::<Vec<&str>>();

        if s.len() != 6 {
            return None;
        }

        let mut raw: [u8; 6] = [0; 6];
        for i in 0..s.len() {
            raw[i] = match u8::from_str_radix(s[i], 16) {
                Ok(res) => res,
                Err(_) => {
                    return None;
                }
            };
        }

        Some(RawAddress { val: raw })
    }

    pub fn to_byte_arr(&self) -> [u8; 6] {
        self.val.clone()
    }
}

#[macro_export]
macro_rules! deref_ffi_address {
    ($ffi_addr:ident) => {
        *($ffi_addr as *mut RawAddress)
    };
}

#[macro_export]
macro_rules! cast_to_ffi_address {
    ($raw_addr:expr) => {
        $raw_addr as *mut FfiAddress
    };
}

#[macro_export]
macro_rules! cast_to_const_ffi_address {
    ($raw_addr:expr) => {
        $raw_addr as *const FfiAddress
    };
}

#[derive(Debug)]
pub enum BaseCallbacks {
@@ -296,8 +388,8 @@ u32 -> BtStatus, i32, *mut bindings::bt_property_t, {
    let _2 = convert_properties(_1, _2);
});
cb_variant!(BaseCb, remote_device_properties_cb -> BaseCallbacks::RemoteDeviceProperties,
u32 -> BtStatus, *mut RawAddress -> RawAddress, i32, *mut bindings::bt_property_t, {
    let _1 = unsafe {*_1};
u32 -> BtStatus, *mut FfiAddress -> RawAddress, i32, *mut bindings::bt_property_t, {
    let _1 = unsafe { *(_1 as *const RawAddress) };
    let _3 = convert_properties(_2, _3);
});
cb_variant!(BaseCb, device_found_cb -> BaseCallbacks::DeviceFound,
@@ -307,22 +399,22 @@ i32, *mut bindings::bt_property_t, {
cb_variant!(BaseCb, discovery_state_cb -> BaseCallbacks::DiscoveryState,
    bindings::bt_discovery_state_t -> BtDiscoveryState);
cb_variant!(BaseCb, pin_request_cb -> BaseCallbacks::PinRequest,
*mut RawAddress, *mut bindings::bt_bdname_t, u32, bool, {
    let _0 = unsafe { *_0 };
*mut FfiAddress, *mut bindings::bt_bdname_t, u32, bool, {
    let _0 = unsafe { *(_0 as *const RawAddress)};
    let _1 = String::from(unsafe{*_1});
});
cb_variant!(BaseCb, ssp_request_cb -> BaseCallbacks::SspRequest,
*mut RawAddress, *mut bindings::bt_bdname_t, u32, bindings::bt_ssp_variant_t -> BtSspVariant, u32, {
    let _0 = unsafe {*_0};
*mut FfiAddress, *mut bindings::bt_bdname_t, u32, bindings::bt_ssp_variant_t -> BtSspVariant, u32, {
    let _0 = unsafe { *(_0 as *const RawAddress) };
    let _1 = String::from(unsafe{*_1});
});
cb_variant!(BaseCb, bond_state_cb -> BaseCallbacks::BondState,
u32 -> BtStatus, *mut RawAddress, bindings::bt_bond_state_t -> BtBondState, {
    let _1 = unsafe {*_1};
u32 -> BtStatus, *mut FfiAddress, bindings::bt_bond_state_t -> BtBondState, {
    let _1 = unsafe { *(_1 as *const RawAddress) };
});
cb_variant!(BaseCb, acl_state_cb -> BaseCallbacks::AclState,
u32 -> BtStatus, *mut RawAddress, bindings::bt_acl_state_t -> BtAclState, bindings::bt_hci_error_code_t -> BtHciErrorCode, {
    let _1 = unsafe { *_1 };
u32 -> BtStatus, *mut FfiAddress, bindings::bt_acl_state_t -> BtAclState, bindings::bt_hci_error_code_t -> BtHciErrorCode, {
    let _1 = unsafe { *(_1 as *const RawAddress) };
});

struct RawInterfaceWrapper {
@@ -440,7 +532,8 @@ impl BluetoothInterface {
    }

    pub fn get_remote_device_properties(&self, addr: &mut RawAddress) -> i32 {
        ccall!(self, get_remote_device_properties, addr)
        let ffi_addr = cast_to_ffi_address!(addr as *mut RawAddress);
        ccall!(self, get_remote_device_properties, ffi_addr)
    }

    pub fn get_remote_device_property(
@@ -449,12 +542,14 @@ impl BluetoothInterface {
        prop_type: BtPropertyType,
    ) -> i32 {
        let converted_type = bindings::bt_property_type_t::from(prop_type);
        ccall!(self, get_remote_device_property, addr, converted_type)
        let ffi_addr = cast_to_ffi_address!(addr as *mut RawAddress);
        ccall!(self, get_remote_device_property, ffi_addr, converted_type)
    }

    pub fn set_remote_device_property(&self, addr: &mut RawAddress, prop: BtProperty) -> i32 {
        let converted_prop = bindings::bt_property_t::from(prop);
        ccall!(self, set_remote_device_property, addr, &converted_prop)
        let ffi_addr = cast_to_ffi_address!(addr as *const RawAddress);
        ccall!(self, set_remote_device_property, ffi_addr, &converted_prop)
    }

    pub fn start_discovery(&self) -> i32 {
@@ -467,19 +562,23 @@ impl BluetoothInterface {

    pub fn create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i32 {
        let ctransport: i32 = transport.into();
        ccall!(self, create_bond, addr, ctransport)
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, create_bond, ffi_addr, ctransport)
    }

    pub fn remove_bond(&self, addr: &RawAddress) -> i32 {
        ccall!(self, remove_bond, addr)
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, remove_bond, ffi_addr)
    }

    pub fn cancel_bond(&self, addr: &RawAddress) -> i32 {
        ccall!(self, cancel_bond, addr)
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, cancel_bond, ffi_addr)
    }

    pub fn get_connection_state(&self, addr: &RawAddress) -> i32 {
        ccall!(self, get_connection_state, addr)
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, get_connection_state, ffi_addr)
    }

    pub fn pin_reply(
@@ -489,7 +588,8 @@ impl BluetoothInterface {
        pin_len: u8,
        pin_code: &mut BtPinCode,
    ) -> i32 {
        ccall!(self, pin_reply, addr, accept, pin_len, pin_code)
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, pin_reply, ffi_addr, accept, pin_len, pin_code)
    }

    pub fn ssp_reply(
@@ -500,7 +600,8 @@ impl BluetoothInterface {
        passkey: u32,
    ) -> i32 {
        let cvariant = bindings::bt_ssp_variant_t::from(variant);
        ccall!(self, ssp_reply, addr, cvariant, accept, passkey)
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, ssp_reply, ffi_addr, cvariant, accept, passkey)
    }

    pub(crate) fn get_profile_interface(
@@ -532,3 +633,29 @@ pub fn get_btinterface() -> Option<BluetoothInterface> {

    ret
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::mem;

    #[test]
    fn test_addr_size() {
        assert_eq!(mem::size_of::<RawAddress>(), mem::size_of::<FfiAddress>());
    }

    #[test]
    fn test_offset() {
        let r = RawAddress { val: [1, 2, 3, 4, 5, 6] };
        let f = FfiAddress { address: [1, 2, 3, 4, 5, 6] };
        assert_eq!(
            &f as *const _ as usize - &f.address as *const _ as usize,
            &r as *const _ as usize - &r.val as *const _ as usize
        );
    }

    #[test]
    fn test_alignment() {
        assert_eq!(std::mem::align_of::<RawAddress>(), std::mem::align_of::<FfiAddress>());
    }
}
+28 −42
Original line number Diff line number Diff line
use crate::btif::BluetoothInterface;
use crate::btif::{BluetoothInterface, RawAddress};
use crate::topstack::get_dispatchers;

use num_traits::cast::FromPrimitive;
@@ -110,7 +110,7 @@ bitflags! {

#[cxx::bridge(namespace = bluetooth::topshim::rust)]
pub mod ffi {
    #[derive(Debug)]
    #[derive(Debug, Copy, Clone)]
    pub struct RustRawAddress {
        address: [u8; 6],
    }
@@ -167,44 +167,18 @@ pub mod ffi {
    }
}

pub type RawAddress = ffi::RustRawAddress;
pub type FfiAddress = ffi::RustRawAddress;
pub type A2dpCodecConfig = ffi::A2dpCodecConfig;

// TODO(hychao): copied from BDAddr, need to move to a shared addr.
impl ToString for RawAddress {
    fn to_string(&self) -> String {
        String::from(format!(
            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
            self.address[0],
            self.address[1],
            self.address[2],
            self.address[3],
            self.address[4],
            self.address[5]
        ))
    }
}

impl RawAddress {
    pub fn from_string<S: Into<String>>(addr: S) -> Option<RawAddress> {
        let addr: String = addr.into();
        let s = addr.split(':').collect::<Vec<&str>>();

        if s.len() != 6 {
            return None;
        }

        let mut raw: [u8; 6] = [0; 6];
        for i in 0..s.len() {
            raw[i] = match u8::from_str_radix(s[i], 16) {
                Ok(res) => res,
                Err(_) => {
                    return None;
impl From<RawAddress> for FfiAddress {
    fn from(addr: RawAddress) -> Self {
        FfiAddress { address: addr.val }
    }
            };
}

        Some(RawAddress { address: raw })
impl Into<RawAddress> for FfiAddress {
    fn into(self) -> RawAddress {
        RawAddress { val: self.address }
    }
}

@@ -222,13 +196,25 @@ pub struct A2dpCallbacksDispatcher {

type A2dpCb = Arc<Mutex<A2dpCallbacksDispatcher>>;

cb_variant!(A2dpCb, connection_state_callback -> A2dpCallbacks::ConnectionState, RawAddress, u32 -> BtavConnectionState);
cb_variant!(A2dpCb, connection_state_callback -> A2dpCallbacks::ConnectionState,
FfiAddress -> RawAddress, u32 -> BtavConnectionState, {
    let _0 = _0.into();
});

cb_variant!(A2dpCb, audio_state_callback -> A2dpCallbacks::AudioState, RawAddress, u32 -> BtavAudioState);
cb_variant!(A2dpCb, audio_state_callback -> A2dpCallbacks::AudioState,
FfiAddress -> RawAddress, u32 -> BtavAudioState, {
    let _0 = _0.into();
});

cb_variant!(A2dpCb, mandatory_codec_preferred_callback -> A2dpCallbacks::MandatoryCodecPreferred, RawAddress);
cb_variant!(A2dpCb, mandatory_codec_preferred_callback -> A2dpCallbacks::MandatoryCodecPreferred,
FfiAddress -> RawAddress, {
    let _0 = _0.into();
});

cb_variant!(A2dpCb, audio_config_callback -> A2dpCallbacks::AudioConfig, RawAddress, A2dpCodecConfig, Vec<A2dpCodecConfig>, Vec<A2dpCodecConfig>);
cb_variant!(A2dpCb, audio_config_callback -> A2dpCallbacks::AudioConfig,
FfiAddress -> RawAddress, A2dpCodecConfig, Vec<A2dpCodecConfig>, Vec<A2dpCodecConfig>, {
    let _0 = _0.into();
});

pub struct A2dp {
    internal: cxx::UniquePtr<ffi::A2dpIntf>,
@@ -262,7 +248,7 @@ impl A2dp {
            eprintln!("Invalid device string {}", device);
            return;
        }
        self.internal.pin_mut().connect(addr.unwrap());
        self.internal.pin_mut().connect(addr.unwrap().into());
    }

    pub fn set_active_device(&mut self, device: String) {
@@ -271,7 +257,7 @@ impl A2dp {
            eprintln!("Invalid device string {}", device);
            return;
        }
        self.internal.pin_mut().set_active_device(addr.unwrap());
        self.internal.pin_mut().set_active_device(addr.unwrap().into());
    }

    pub fn disconnect(&mut self, device: String) {
@@ -280,7 +266,7 @@ impl A2dp {
            eprintln!("Invalid device string {}", device);
            return;
        }
        self.internal.pin_mut().disconnect(addr.unwrap());
        self.internal.pin_mut().disconnect(addr.unwrap().into());
    }

    pub fn start_session(&mut self) {
Loading