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

Commit b7e2facc authored by En-Shuo Hsu's avatar En-Shuo Hsu Committed by Automerger Merge Worker
Browse files

floss: Pass BluetoothAudioDevice as a dictionary am: 42f1d5fe am: 382b12de

parents 3cac092a 382b12de
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -188,6 +188,43 @@ macro_rules! impl_dbus_arg_enum {
    };
}

/// Implements `DBusArg` for a type which implements TryFrom and TryInto.
#[macro_export]
macro_rules! impl_dbus_arg_from_into {
    ($rust_type:ty, $dbus_type:ty) => {
        impl DBusArg for $rust_type {
            type DBusType = $dbus_type;
            fn from_dbus(
                data: $dbus_type,
                _conn: Option<Arc<SyncConnection>>,
                _remote: Option<dbus::strings::BusName<'static>>,
                _disconnect_watcher: Option<
                    Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
                >,
            ) -> Result<$rust_type, Box<dyn std::error::Error>> {
                match <$rust_type>::try_from(data) {
                    Err(e) => Err(Box::new(DBusArgError::new(String::from(format!(
                        "error converting {} to {}",
                        data,
                        stringify!($rust_type),
                    ))))),
                    Ok(result) => Ok(result),
                }
            }

            fn to_dbus(data: $rust_type) -> Result<$dbus_type, Box<dyn std::error::Error>> {
                match data.try_into() {
                    Err(e) => Err(Box::new(DBusArgError::new(String::from(format!(
                        "error converting {:?} to {}",
                        data,
                        stringify!($dbus_type)
                    ))))),
                    Ok(result) => Ok(result),
                }
            }
        }
    };
}
/// Marks a function to be implemented by dbus_projection macros.
#[macro_export]
macro_rules! dbus_generated {
+32 −12
Original line number Diff line number Diff line
use bt_topshim::profiles::a2dp::PresentationPosition;
use btstack::bluetooth_media::{IBluetoothMedia, IBluetoothMediaCallback};
use bt_topshim::profiles::a2dp::{A2dpCodecConfig, PresentationPosition};
use bt_topshim::profiles::hfp::HfpCodecCapability;
use btstack::bluetooth_media::{BluetoothAudioDevice, IBluetoothMedia, IBluetoothMediaCallback};
use btstack::RPCProxy;

use dbus::arg::RefArg;
use dbus::nonblock::SyncConnection;
use dbus::strings::Path;

use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter};

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

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

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

#[allow(dead_code)]
struct BluetoothMediaCallbackDBus {}

#[dbus_proxy_obj(BluetoothMediaCallback, "org.chromium.bluetooth.BluetoothMediaCallback")]
impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus {
    #[dbus_method("OnBluetoothAudioDeviceAdded")]
    fn on_bluetooth_audio_device_added(
        &self,
        addr: String,
#[dbus_propmap(A2dpCodecConfig)]
pub struct A2dpCodecConfigDBus {
    codec_type: i32,
    codec_priority: i32,
    sample_rate: i32,
    bits_per_sample: i32,
    channel_mode: i32,
        hfp_cap: i32,
    codec_specific_1: i64,
    codec_specific_2: i64,
    codec_specific_3: i64,
    codec_specific_4: i64,
}

#[dbus_propmap(BluetoothAudioDevice)]
pub struct BluetoothAudioDeviceDBus {
    address: String,
    name: String,
    ) {
    a2dp_caps: Vec<A2dpCodecConfig>,
    hfp_cap: HfpCodecCapability,
}

impl_dbus_arg_from_into!(HfpCodecCapability, i32);

#[dbus_proxy_obj(BluetoothMediaCallback, "org.chromium.bluetooth.BluetoothMediaCallback")]
impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus {
    #[dbus_method("OnBluetoothAudioDeviceAdded")]
    fn on_bluetooth_audio_device_added(&self, device: BluetoothAudioDevice) {
        dbus_generated!()
    }

+40 −36
Original line number Diff line number Diff line
@@ -3,8 +3,7 @@
use bt_topshim::btif::{BluetoothInterface, RawAddress};
use bt_topshim::profiles::a2dp::{
    A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
    A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, BtavConnectionState,
    PresentationPosition,
    A2dpCodecConfig, A2dpCodecSampleRate, BtavConnectionState, PresentationPosition,
};
use bt_topshim::profiles::avrcp::{Avrcp, AvrcpCallbacks, AvrcpCallbacksDispatcher};
use bt_topshim::profiles::hfp::{
@@ -63,15 +62,7 @@ pub trait IBluetoothMediaCallback {
    /// only be triggered once for a device and send an event to clients. If the
    /// device supports both HFP and A2DP, both should be ready when this is
    /// triggered.
    fn on_bluetooth_audio_device_added(
        &self,
        addr: String,
        sample_rate: i32,
        bits_per_sample: i32,
        channel_mode: i32,
        hfp_cap: i32,
        name: String,
    );
    fn on_bluetooth_audio_device_added(&self, device: BluetoothAudioDevice);

    ///
    fn on_bluetooth_audio_device_removed(&self, addr: String);
@@ -83,6 +74,25 @@ pub trait IBluetoothMediaCallback {
    fn on_absolute_volume_changed(&self, volume: i32);
}

/// Serializable device used in.
#[derive(Debug, Default, Clone)]
pub struct BluetoothAudioDevice {
    pub address: String,
    pub name: String,
    pub a2dp_caps: Vec<A2dpCodecConfig>,
    pub hfp_cap: HfpCodecCapability,
}

impl BluetoothAudioDevice {
    pub(crate) fn new(
        address: String,
        name: String,
        a2dp_caps: Vec<A2dpCodecConfig>,
        hfp_cap: HfpCodecCapability,
    ) -> BluetoothAudioDevice {
        BluetoothAudioDevice { address, name, a2dp_caps, hfp_cap }
    }
}
/// Actions that `BluetoothMedia` can take on behalf of the stack.
pub enum MediaActions {
    Connect(String),
@@ -254,22 +264,13 @@ impl BluetoothMedia {
            device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>,
            addr: RawAddress,
            callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>,
            cap: A2dpCodecConfig,
            hfp_cap: HfpCodecCapability,
            name: String,
            device: BluetoothAudioDevice,
            is_delayed: bool,
        ) -> bool {
            // Closure used to lock and trigger the device added callbacks.
            let trigger_device_added = || {
                for callback in &*callbacks.lock().unwrap() {
                    callback.1.on_bluetooth_audio_device_added(
                        addr.to_string(),
                        cap.sample_rate,
                        cap.bits_per_sample,
                        cap.channel_mode,
                        hfp_cap.bits(),
                        name.clone(),
                    );
                    callback.1.on_bluetooth_audio_device_added(device.clone());
                }
            };
            let mut guard = device_added_tasks.lock().unwrap();
@@ -304,26 +305,25 @@ impl BluetoothMedia {
            }
        }

        let cur_a2dp_cap = self.selectable_caps.get(&addr).and_then(|a2dp_caps| {
            a2dp_caps
                .iter()
                .find(|cap| A2dpCodecIndex::SrcSbc == A2dpCodecIndex::from(cap.codec_type))
        });
        let cur_a2dp_caps = self.selectable_caps.get(&addr);
        let cur_hfp_cap = self.hfp_caps.get(&addr);
        let name = self.adapter_get_remote_name(addr);
        match (cur_a2dp_cap, cur_hfp_cap) {
        match (cur_a2dp_caps, cur_hfp_cap) {
            (None, None) => warn!(
                "[{}]: Try to add a device without a2dp and hfp capability.",
                addr.to_string()
            ),
            (Some(cap), Some(hfp_cap)) => {
            (Some(caps), Some(hfp_cap)) => {
                dedup_added_cb(
                    self.device_added_tasks.clone(),
                    addr,
                    self.callbacks.clone(),
                    *cap,
                    BluetoothAudioDevice::new(
                        addr.to_string(),
                        name.clone(),
                        caps.to_vec(),
                        *hfp_cap,
                    name,
                    ),
                    false,
                );
            }
@@ -332,11 +332,15 @@ impl BluetoothMedia {
                if guard.get(&addr).is_none() {
                    let callbacks = self.callbacks.clone();
                    let device_added_tasks = self.device_added_tasks.clone();
                    let cap = cur_a2dp_cap.unwrap_or(&A2dpCodecConfig::default()).clone();
                    let hfp_cap = cur_hfp_cap.unwrap_or(&HfpCodecCapability::UNSUPPORTED).clone();
                    let device = BluetoothAudioDevice::new(
                        addr.to_string(),
                        name.clone(),
                        cur_a2dp_caps.unwrap_or(&Vec::new()).to_vec(),
                        *cur_hfp_cap.unwrap_or(&HfpCodecCapability::UNSUPPORTED),
                    );
                    let task = topstack::get_runtime().spawn(async move {
                        sleep(Duration::from_secs(DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC)).await;
                        if dedup_added_cb(device_added_tasks, addr, callbacks, cap, hfp_cap, name, true) {
                        if dedup_added_cb(device_added_tasks, addr, callbacks, device, true) {
                            warn!(
                                "[{}]: Add a device with only hfp or a2dp capability after timeout.",
                                addr.to_string()
+9 −9
Original line number Diff line number Diff line
@@ -135,15 +135,15 @@ pub mod ffi {

    #[derive(Debug, Copy, Clone)]
    pub struct A2dpCodecConfig {
        codec_type: i32,
        codec_priority: i32,
        sample_rate: i32,
        bits_per_sample: i32,
        channel_mode: i32,
        codec_specific_1: i64,
        codec_specific_2: i64,
        codec_specific_3: i64,
        codec_specific_4: i64,
        pub codec_type: i32,
        pub codec_priority: i32,
        pub sample_rate: i32,
        pub bits_per_sample: i32,
        pub channel_mode: i32,
        pub codec_specific_1: i64,
        pub codec_specific_2: i64,
        pub codec_specific_3: i64,
        pub codec_specific_4: i64,
    }

    #[derive(Debug, Default)]
+16 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ use crate::btif::{BluetoothInterface, RawAddress};
use crate::topstack::get_dispatchers;

use num_traits::cast::FromPrimitive;
use std::convert::{TryFrom, TryInto};
use std::sync::{Arc, Mutex};
use topshim_macros::cb_variant;

@@ -37,6 +38,7 @@ impl From<u32> for BthfAudioState {
}

bitflags! {
    #[derive(Default)]
    pub struct HfpCodecCapability: i32 {
        const UNSUPPORTED = 0b00;
        const CVSD = 0b01;
@@ -44,6 +46,20 @@ bitflags! {
    }
}

impl TryInto<i32> for HfpCodecCapability {
    type Error = ();
    fn try_into(self) -> Result<i32, Self::Error> {
        Ok(self.bits())
    }
}

impl TryFrom<i32> for HfpCodecCapability {
    type Error = ();
    fn try_from(val: i32) -> Result<Self, Self::Error> {
        Self::from_bits(val).ok_or(())
    }
}

#[cxx::bridge(namespace = bluetooth::topshim::rust)]
pub mod ffi {
    #[derive(Debug, Copy, Clone)]