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

Commit cfc21525 authored by howardchung's avatar howardchung
Browse files

Floss: Wire avrcp ctrl interface to floss topshim

Wire avrcp_ctrl interface to upper layer for qualification purpose.

Bug: 264745185
Test: run AVRCP/CT/PTH/BV-01-C along with the top of this series
Tag: #floss

Change-Id: Ic0734dd89010f487ae89d752bbadf9cf2b992cc7
parent 4dd5ff6c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ rust_bindgen {
        "--allowlist-type=btsdp.*",
        "--allowlist-type=btsock_.*",
        "--allowlist-type=bthf_.*",
        "--allowlist-type=btrc_.*",
        "--allowlist-type=sock_connect_signal_t",
        "--enable-cxx-namespaces",
        "--opaque-type=std::.*",
+1 −0
Original line number Diff line number Diff line
@@ -9,5 +9,6 @@
#include "hardware/bt_gatt.h"
#include "hardware/bt_hf_client.h"
#include "hardware/bt_hh.h"
#include "hardware/bt_rc.h"
#include "hardware/bt_sdp.h"
#include "hardware/bt_sock.h"
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ fn main() {
        .size_t_is_usize(true)
        .blocklist_function("RawAddress_.*")
        .blocklist_function(".*Uuid_.*")
        .allowlist_type("(bt_|bthh_|btgatt_|btsdp|bluetooth_sdp|btsock_|bthf_).*")
        .allowlist_type("(bt_|bthh_|btgatt_|btsdp|bluetooth_sdp|btsock_|bthf_|btrc_).*")
        .allowlist_type("sock_connect_signal_t")
        .allowlist_function("(bt_|bthh_|btgatt_|btsdp).*")
        .allowlist_function("hal_util_.*")
+2 −0
Original line number Diff line number Diff line
@@ -705,6 +705,7 @@ pub enum SupportedProfiles {
    Sdp,
    Socket,
    HfClient,
    AvrcpCtrl,
}

impl From<SupportedProfiles> for Vec<u8> {
@@ -717,6 +718,7 @@ impl From<SupportedProfiles> for Vec<u8> {
            SupportedProfiles::Sdp => "sdp",
            SupportedProfiles::Socket => "socket",
            SupportedProfiles::HfClient => "handsfree_client",
            SupportedProfiles::AvrcpCtrl => "avrcp_ctrl",
        }
        .bytes()
        .chain("\0".bytes())
+110 −1
Original line number Diff line number Diff line
use crate::btif::{BluetoothInterface, BtStatus, RawAddress, ToggleableProfile};
use crate::btif::{BluetoothInterface, BtStatus, RawAddress, SupportedProfiles, ToggleableProfile};
use crate::topstack::get_dispatchers;

use std::sync::{Arc, Mutex};
use topshim_macros::{cb_variant, profile_enabled_or};

use crate::bindings::root as bindings;
use crate::ccall;
use crate::utils::LTCheckedPtrMut;

use log::warn;

#[derive(Debug, Default)]
@@ -23,6 +27,7 @@ pub mod ffi {

    unsafe extern "C++" {
        include!("btav/btav_shim.h");
        include!("btav_sink/btav_sink_shim.h");

        type AvrcpIntf;

@@ -196,3 +201,107 @@ impl Avrcp {
        );
    }
}

struct RawAvrcpCtrlWrapper {
    raw: *const bindings::btrc_ctrl_interface_t,
}

// Pointers unsafe due to ownership but this is a static pointer so Send is ok.
unsafe impl Send for RawAvrcpCtrlWrapper {}

pub struct AvrcpCtrl {
    internal: RawAvrcpCtrlWrapper,
    callbacks: Option<Box<bindings::btrc_ctrl_callbacks_t>>,
}

cb_variant!(AvrcpCtCb, avrcp_connection_state_cb -> AvrcpCtrlCallbacks::ConnectionState,
bool, bool, *const RawAddress, {
    let _2 = unsafe { *_2 };
});

cb_variant!(AvrcpCtCb, avrcp_getrcfeatures_cb -> AvrcpCtrlCallbacks::GetRCFeatures,
*const RawAddress, i32, {
    let _0 = unsafe { *_0 };
});

cb_variant!(AvrcpCtCb, avrcp_get_cover_art_psm_cb -> AvrcpCtrlCallbacks::GetCoverArtPsm,
*const RawAddress, u16, {
    let _0 = unsafe { *_0 };
});

cb_variant!(AvrcpCtCb, avrcp_passthrough_rsp_cb -> AvrcpCtrlCallbacks::PassthroughRsp,
*const RawAddress, i32, i32, {
    let _0 = unsafe { *_0 };
});

#[derive(Debug)]
pub enum AvrcpCtrlCallbacks {
    PassthroughRsp(RawAddress, i32, i32),
    ConnectionState(bool, bool, RawAddress),
    GetRCFeatures(RawAddress, i32),
    GetCoverArtPsm(RawAddress, u16),
}

pub struct AvrcpCtrlCallbacksDispatcher {
    pub dispatch: Box<dyn Fn(AvrcpCtrlCallbacks) + Send>,
}

type AvrcpCtCb = Arc<Mutex<AvrcpCtrlCallbacksDispatcher>>;

impl AvrcpCtrl {
    pub fn new(intf: &BluetoothInterface) -> AvrcpCtrl {
        let r = intf.get_profile_interface(SupportedProfiles::AvrcpCtrl);
        AvrcpCtrl {
            internal: RawAvrcpCtrlWrapper { raw: r as *const bindings::btrc_ctrl_interface_t },
            callbacks: None,
        }
    }

    pub fn initialize(&mut self, callbacks: AvrcpCtrlCallbacksDispatcher) -> bool {
        // Register dispatcher
        if get_dispatchers().lock().unwrap().set::<AvrcpCtCb>(Arc::new(Mutex::new(callbacks))) {
            panic!("Tried to set dispatcher for AvrcpCt Callbacks but it already existed");
        }

        let callbacks = Box::new(bindings::btrc_ctrl_callbacks_t {
            size: 21 * 8,
            passthrough_rsp_cb: Some(avrcp_passthrough_rsp_cb),
            groupnavigation_rsp_cb: None,
            connection_state_cb: Some(avrcp_connection_state_cb),
            getrcfeatures_cb: Some(avrcp_getrcfeatures_cb),
            setplayerappsetting_rsp_cb: None,
            playerapplicationsetting_cb: None,
            playerapplicationsetting_changed_cb: None,
            setabsvol_cmd_cb: None,
            registernotification_absvol_cb: None,
            track_changed_cb: None,
            play_position_changed_cb: None,
            play_status_changed_cb: None,
            get_folder_items_cb: None,
            change_folder_path_cb: None,
            set_browsed_player_cb: None,
            set_addressed_player_cb: None,
            addressed_player_changed_cb: None,
            now_playing_contents_changed_cb: None,
            available_player_changed_cb: None,
            get_cover_art_psm_cb: Some(avrcp_get_cover_art_psm_cb),
        });

        self.callbacks = Some(callbacks);

        let cb_ptr = LTCheckedPtrMut::from(self.callbacks.as_mut().unwrap());

        ccall!(self, init, cb_ptr.into());

        true
    }

    pub fn send_pass_through_cmd(
        &mut self,
        addr: RawAddress,
        key_code: u8,
        key_state: u8,
    ) -> BtStatus {
        ccall!(self, send_pass_through_cmd, &addr, key_code.into(), key_state.into()).into()
    }
}