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

Commit 34cae6f5 authored by Michael Sun's avatar Michael Sun
Browse files

floss: avrcp: connect bluetooth_media with uinput

Connect AVRCP connect/disconnect event to uinput to create and close
uinput device with the kernel. Then, route key event to uinput to have
AVRCP commands taking effect.

Explicitly connect to AVRCP profile with media interface through
topshim when connect/disconnect initiated by the host.

Bug: 240780817
Tag: #floss
Test: AVRCP is working!
Change-Id: I040a6d81882dfdca28216011f1872b13dd87b3b3
parent 4d31e5ca
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
bt_topshim = { path = "../../topshim" }
bt_shim = { path = "../../shim" }
bt_utils = { path = "../utils" }

btif_macros = { path = "btif_macros" }

+28 −3
Original line number Diff line number Diff line
@@ -11,8 +11,8 @@ use bt_topshim::profiles::hfp::{
    BthfAudioState, BthfConnectionState, Hfp, HfpCallbacks, HfpCallbacksDispatcher,
    HfpCodecCapability,
};

use bt_topshim::topstack;
use bt_utils::uinput::UInput;

use log::{info, warn};
use num_traits::cast::ToPrimitive;
@@ -146,6 +146,7 @@ pub struct BluetoothMedia {
    hfp_caps: HashMap<RawAddress, HfpCodecCapability>,
    device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>,
    absolute_volume: bool,
    uinput: UInput,
}

impl BluetoothMedia {
@@ -170,6 +171,7 @@ impl BluetoothMedia {
            hfp_caps: HashMap::new(),
            device_added_tasks: Arc::new(Mutex::new(HashMap::new())),
            absolute_volume: false,
            uinput: UInput::new(),
        }
    }

@@ -218,6 +220,11 @@ impl BluetoothMedia {
    pub fn dispatch_avrcp_callbacks(&mut self, cb: AvrcpCallbacks) {
        match cb {
            AvrcpCallbacks::AvrcpDeviceConnected(addr, supported) => {
                match self.uinput.create(self.adapter_get_remote_name(addr), addr.to_string()) {
                    Ok(()) => info!("uinput device created for: {}", addr.to_string()),
                    Err(e) => warn!("{}", e),
                }

                if self.absolute_volume == supported {
                    return;
                }
@@ -249,13 +256,20 @@ impl BluetoothMedia {
                    info!("[{}]: Device's avrcp connected before a2dp and hfp", addr.to_string());
                }
            }
            AvrcpCallbacks::AvrcpDeviceDisconnected(_addr) => {}
            AvrcpCallbacks::AvrcpDeviceDisconnected(addr) => {
                self.uinput.close(addr.to_string());
            }
            AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => {
                self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
                    callback.on_absolute_volume_changed(volume);
                });
            }
            AvrcpCallbacks::AvrcpSendKeyEvent(_key, _value) => {}
            AvrcpCallbacks::AvrcpSendKeyEvent(key, value) => {
                match self.uinput.send_key(key, value) {
                    Ok(()) => (),
                    Err(e) => warn!("{}", e),
                }
            }
        }
    }

@@ -580,6 +594,11 @@ impl IBluetoothMedia for BluetoothMedia {
            Some(hfp) => hfp.connect(addr),
            None => warn!("Uninitialized HFP to connect {}", address),
        };

        match self.avrcp.as_mut() {
            Some(avrcp) => avrcp.connect(addr),
            None => warn!("Uninitialized AVRCP to connect {}", address),
        };
    }

    fn cleanup(&mut self) -> bool {
@@ -599,6 +618,7 @@ impl IBluetoothMedia for BluetoothMedia {
            Some(a2dp) => a2dp.set_active_device(addr),
            None => warn!("Uninitialized A2DP to set active device"),
        }
        self.uinput.set_active_device(addr.to_string());
    }

    fn disconnect(&mut self, address: String) {
@@ -619,6 +639,11 @@ impl IBluetoothMedia for BluetoothMedia {
            Some(hfp) => hfp.disconnect(addr),
            None => warn!("Uninitialized HFP to disconnect {}", address),
        };

        match self.avrcp.as_mut() {
            Some(avrcp) => avrcp.disconnect(addr),
            None => warn!("Uninitialized AVRCP to disconnect {}", address),
        };
    }

    fn set_audio_config(
+16 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ pub mod ffi {

        fn init(self: Pin<&mut AvrcpIntf>);
        fn cleanup(self: Pin<&mut AvrcpIntf>);
        fn connect(self: Pin<&mut AvrcpIntf>, bt_addr: RustRawAddress) -> i32;
        fn disconnect(self: Pin<&mut AvrcpIntf>, bt_addr: RustRawAddress) -> i32;
        fn set_volume(self: Pin<&mut AvrcpIntf>, volume: i8);

    }
@@ -31,6 +33,12 @@ pub mod ffi {
    }
}

impl From<RawAddress> for ffi::RustRawAddress {
    fn from(addr: RawAddress) -> Self {
        ffi::RustRawAddress { address: addr.val }
    }
}

impl Into<RawAddress> for ffi::RustRawAddress {
    fn into(self) -> RawAddress {
        RawAddress { val: self.address }
@@ -116,6 +124,14 @@ impl Avrcp {
        true
    }

    pub fn connect(&mut self, addr: RawAddress) {
        self.internal.pin_mut().connect(addr.into());
    }

    pub fn disconnect(&mut self, addr: RawAddress) {
        self.internal.pin_mut().disconnect(addr.into());
    }

    pub fn set_volume(&mut self, volume: i8) {
        self.internal.pin_mut().set_volume(volume);
    }