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

Commit e825f809 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I50fd0400,If772cc72,I6f6845d1,Ib6911767,I4c754fd6, ...

* changes:
  floss: Refactor callback registration
  floss: Client checks if manager is valid
  floss: Improve bonding procedure
  floss: ConnectAllEnabledProfiles now connects A2DP
  floss: Implement ConnectAllEnabledProfiles + Disconnect
  floss: Add bond remove and cancel to btclient
  floss: Implement GetConnectionState
  floss: Add support for BtConnectionCallbacks
  floss: Add floss enable/disable to btclient
  floss: Refactor DisconnectWatcher to take id
parents 3a031b4b 5876b981
Loading
Loading
Loading
Loading
+122 −16
Original line number Diff line number Diff line
use crate::ClientContext;
use crate::{console_yellow, print_info};
use bt_topshim::btif::BtSspVariant;
use bt_topshim::btif::{BtBondState, BtSspVariant};
use bt_topshim::profiles::gatt::GattStatus;
use btstack::bluetooth::{BluetoothDevice, IBluetoothCallback};
use btstack::bluetooth::{
    BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
};
use btstack::bluetooth_gatt::{BluetoothGattService, IBluetoothGattCallback, LePhy};
use btstack::RPCProxy;
use manager_service::iface_bluetooth_manager::IBluetoothManagerCallback;
@@ -37,11 +39,17 @@ impl IBluetoothManagerCallback for BtManagerCallback {
}

impl manager_service::RPCProxy for BtManagerCallback {
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
    }

    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

/// Callback container for adapter interface callbacks.
@@ -89,31 +97,123 @@ impl IBluetoothCallback for BtCallback {
        variant: BtSspVariant,
        passkey: u32,
    ) {
        if variant == BtSspVariant::PasskeyNotification {
        match variant {
            BtSspVariant::PasskeyNotification => {
                print_info!(
                "device {}{} would like to pair, enter passkey on remote device: {:06}",
                remote_device.address.to_string(),
                if remote_device.name.len() > 0 {
                    format!(" ({})", remote_device.name)
                } else {
                    String::from("")
                },
                    "Device [{}: {}] would like to pair, enter passkey on remote device: {:06}",
                    &remote_device.address,
                    &remote_device.name,
                    passkey
                );
            }
            BtSspVariant::Consent => {
                let rd = remote_device.clone();
                self.context.lock().unwrap().run_callback(Box::new(move |context| {
                    // Auto-confirm bonding attempts that were locally initiated.
                    // Ignore all other bonding attempts.
                    let bonding_device = context.lock().unwrap().bonding_attempt.as_ref().cloned();
                    match bonding_device {
                        Some(bd) => {
                            if bd.address == rd.address {
                                context
                                    .lock()
                                    .unwrap()
                                    .adapter_dbus
                                    .as_ref()
                                    .unwrap()
                                    .set_pairing_confirmation(rd.clone(), true);
                            }
                        }
                        None => (),
                    }
                }));
            }
            BtSspVariant::PasskeyEntry => {
                println!("Got PasskeyEntry but it is not supported...");
            }
            BtSspVariant::PasskeyConfirmation => {
                println!("Got PasskeyConfirmation but there's nothing to do...");
            }
        }
    }

    fn on_bond_state_changed(&self, status: u32, address: String, state: u32) {
        print_info!("Bonding state changed: [{}] state: {}, Status = {}", address, state, status);

        // Clear bonding attempt if bonding fails or succeeds
        match BtBondState::from(state) {
            BtBondState::NotBonded | BtBondState::Bonded => {
                let bonding_attempt =
                    self.context.lock().unwrap().bonding_attempt.as_ref().cloned();
                match bonding_attempt {
                    Some(bd) => {
                        if &address == &bd.address {
                            self.context.lock().unwrap().bonding_attempt = None;
                        }
                    }
                    None => (),
                }
            }
            BtBondState::Bonding => (),
        }

        // If bonded, we should also automatically connect all enabled profiles
        if BtBondState::Bonded == state.into() {
            self.context.lock().unwrap().connect_all_enabled_profiles(BluetoothDevice {
                address,
                name: String::from("Classic device"),
            });
        }
    }
}

impl RPCProxy for BtCallback {
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
    }

    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

pub(crate) struct BtConnectionCallback {
    objpath: String,
    _context: Arc<Mutex<ClientContext>>,
}

impl BtConnectionCallback {
    pub(crate) fn new(objpath: String, _context: Arc<Mutex<ClientContext>>) -> Self {
        Self { objpath, _context }
    }
}

impl IBluetoothConnectionCallback for BtConnectionCallback {
    fn on_device_connected(&self, remote_device: BluetoothDevice) {
        print_info!("Connected: [{}]: {}", remote_device.address, remote_device.name);
    }

    fn on_device_disconnected(&self, remote_device: BluetoothDevice) {
        print_info!("Disconnected: [{}]: {}", remote_device.address, remote_device.name);
    }
}

impl RPCProxy for BtConnectionCallback {
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
    }

    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

pub(crate) struct BtGattCallback {
@@ -256,9 +356,15 @@ impl IBluetoothGattCallback for BtGattCallback {
}

impl RPCProxy for BtGattCallback {
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
    }

    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}
+160 −55
Original line number Diff line number Diff line
@@ -2,14 +2,13 @@ use std::collections::HashMap;
use std::fmt::{Display, Formatter, Result};
use std::sync::{Arc, Mutex};

use num_traits::cast::FromPrimitive;

use crate::callbacks::BtGattCallback;
use crate::ClientContext;
use crate::{console_red, console_yellow, print_error, print_info};
use bt_topshim::btif::Uuid128Bit;
use btstack::bluetooth::{BluetoothDevice, BluetoothTransport, IBluetooth};
use bt_topshim::btif::BtTransport;
use btstack::bluetooth::{BluetoothDevice, IBluetooth};
use btstack::bluetooth_gatt::IBluetoothGatt;
use btstack::uuid::UuidHelper;
use manager_service::iface_bluetooth_manager::IBluetoothManager;

const INDENT_CHAR: &str = " ";
@@ -49,20 +48,6 @@ impl<T: Display> Display for DisplayList<T> {
    }
}

struct DisplayUuid128Bit(Uuid128Bit);

// UUID128Bit should have a standard output display format
impl Display for DisplayUuid128Bit {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
            self.0[0], self.0[1], self.0[2], self.0[3],
            self.0[4], self.0[5],
            self.0[6], self.0[7],
            self.0[8], self.0[9],
            self.0[10], self.0[11], self.0[12], self.0[13], self.0[14], self.0[15])
    }
}

fn enforce_arg_len<F>(args: &Vec<String>, min_len: usize, msg: &str, mut action: F)
where
    F: FnMut(),
@@ -126,6 +111,13 @@ fn build_commands() -> HashMap<String, CommandOption> {
            function_pointer: CommandHandler::cmd_discovery,
        },
    );
    command_options.insert(
        String::from("floss"),
        CommandOption {
            description: String::from("Enable or disable Floss for dogfood."),
            function_pointer: CommandHandler::cmd_floss,
        },
    );
    command_options.insert(
        String::from("gatt"),
        CommandOption {
@@ -255,6 +247,11 @@ impl CommandHandler {
                self.context.lock().unwrap().manager_dbus.stop(default_adapter);
            }
            "show" => {
                if !self.context.lock().unwrap().manager_dbus.get_floss_enabled() {
                    println!("Floss is not enabled. First run, `floss enable`");
                    return;
                }

                let enabled = self.context.lock().unwrap().enabled;
                let address = match self.context.lock().unwrap().adapter_address.as_ref() {
                    Some(x) => x.clone(),
@@ -268,10 +265,7 @@ impl CommandHandler {
                print_info!(
                    "Uuids: {}",
                    DisplayList(
                        uuids
                            .iter()
                            .map(|&x| DisplayUuid128Bit(x))
                            .collect::<Vec<DisplayUuid128Bit>>()
                        uuids.iter().map(|&x| UuidHelper::to_string(&x)).collect::<Vec<String>>()
                    )
                );
            }
@@ -316,9 +310,48 @@ impl CommandHandler {
            return;
        }

        enforce_arg_len(args, 1, "bond <address>", || {
        enforce_arg_len(args, 2, "bond <add|remove|cancel> <address>", || match &args[0][0..] {
            "add" => {
                let device = BluetoothDevice {
                address: String::from(&args[0]),
                    address: String::from(&args[1]),
                    name: String::from("Classic Device"),
                };

                let bonding_attempt =
                    &self.context.lock().unwrap().bonding_attempt.as_ref().cloned();

                if bonding_attempt.is_some() {
                    print_info!(
                        "Already bonding [{}]. Cancel bonding first.",
                        bonding_attempt.as_ref().unwrap().address,
                    );
                    return;
                }

                let success = self
                    .context
                    .lock()
                    .unwrap()
                    .adapter_dbus
                    .as_ref()
                    .unwrap()
                    .create_bond(device.clone(), BtTransport::Auto);

                if success {
                    self.context.lock().unwrap().bonding_attempt = Some(device);
                }
            }
            "remove" => {
                let device = BluetoothDevice {
                    address: String::from(&args[1]),
                    name: String::from("Classic Device"),
                };

                self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().remove_bond(device);
            }
            "cancel" => {
                let device = BluetoothDevice {
                    address: String::from(&args[1]),
                    name: String::from("Classic Device"),
                };

@@ -328,7 +361,11 @@ impl CommandHandler {
                    .adapter_dbus
                    .as_ref()
                    .unwrap()
                .create_bond(device, BluetoothTransport::from_i32(0).unwrap());
                    .cancel_bond_process(device);
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

@@ -338,36 +375,104 @@ impl CommandHandler {
            return;
        }

        enforce_arg_len(args, 2, "device <info> <address>", || match &args[0][0..] {
            "info" => {
        enforce_arg_len(args, 2, "device <connect|disconnect|info> <address>", || {
            match &args[0][0..] {
                "connect" => {
                    let device = BluetoothDevice {
                        address: String::from(&args[1]),
                        name: String::from("Classic Device"),
                    };

                let uuids = self
                    let success = self
                        .context
                        .lock()
                        .unwrap()
                        .adapter_dbus
                        .as_ref()
                        .unwrap()
                    .get_remote_uuids(device.clone());
                        .connect_all_enabled_profiles(device.clone());

                    if success {
                        println!("Connecting to {}", &device.address);
                    } else {
                        println!("Can't connect to {}", &device.address);
                    }
                }
                "disconnect" => {
                    let device = BluetoothDevice {
                        address: String::from(&args[1]),
                        name: String::from("Classic Device"),
                    };

                    let success = self
                        .context
                        .lock()
                        .unwrap()
                        .adapter_dbus
                        .as_ref()
                        .unwrap()
                        .disconnect_all_enabled_profiles(device.clone());

                    if success {
                        println!("Disconnecting from {}", &device.address);
                    } else {
                        println!("Can't disconnect from {}", &device.address);
                    }
                }
                "info" => {
                    let device = BluetoothDevice {
                        address: String::from(&args[1]),
                        name: String::from("Classic Device"),
                    };

                    let (bonded, connected, uuids) = {
                        let ctx = self.context.lock().unwrap();
                        let adapter = ctx.adapter_dbus.as_ref().unwrap();

                        let bonded = adapter.get_bond_state(device.clone());
                        let connected = adapter.get_connection_state(device.clone());
                        let uuids = adapter.get_remote_uuids(device.clone());

                        (bonded, connected, uuids)
                    };

                    print_info!("Address: {}", &device.address);
                    print_info!("Bonded: {}", bonded);
                    print_info!("Connected: {}", connected);
                    print_info!(
                        "Uuids: {}",
                        DisplayList(
                            uuids
                                .iter()
                            .map(|&x| DisplayUuid128Bit(x))
                            .collect::<Vec<DisplayUuid128Bit>>()
                                .map(|&x| UuidHelper::to_string(&x))
                                .collect::<Vec<String>>()
                        )
                    );
                }
                _ => {
                    println!("Invalid argument '{}'", args[0]);
                }
            }
        });
    }

    fn cmd_floss(&mut self, args: &Vec<String>) {
        enforce_arg_len(args, 1, "floss <enable|disable>", || match &args[0][0..] {
            "enable" => {
                self.context.lock().unwrap().manager_dbus.set_floss_enabled(true);
            }
            "disable" => {
                self.context.lock().unwrap().manager_dbus.set_floss_enabled(false);
            }
            "show" => {
                print_info!(
                    "Floss enabled: {}",
                    self.context.lock().unwrap().manager_dbus.get_floss_enabled()
                );
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

+131 −22
Original line number Diff line number Diff line
//! D-Bus proxy implementations of the APIs.

use bt_topshim::btif::{BtSspVariant, Uuid128Bit};
use bt_topshim::btif::{BtSspVariant, BtTransport, Uuid128Bit};
use bt_topshim::profiles::gatt::GattStatus;

use btstack::bluetooth::{BluetoothDevice, BluetoothTransport, IBluetooth, IBluetoothCallback};
use btstack::bluetooth::{
    BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
};
use btstack::bluetooth_gatt::{
    BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService,
    GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback,
@@ -34,7 +36,7 @@ fn make_object_path(idx: i32, name: &str) -> dbus::Path {
    dbus::Path::new(format!("/org/chromium/bluetooth/hci{}/{}", idx, name)).unwrap()
}

impl_dbus_arg_enum!(BluetoothTransport);
impl_dbus_arg_enum!(BtTransport);
impl_dbus_arg_enum!(BtSspVariant);
impl_dbus_arg_enum!(GattStatus);
impl_dbus_arg_enum!(GattWriteType);
@@ -110,28 +112,34 @@ impl ClientDBusProxy {
        )
    }

    fn method<A: AppendAll, T: 'static + dbus::arg::Arg + for<'z> dbus::arg::Get<'z>>(
    /// Calls a method and returns the dbus result.
    fn method_withresult<A: AppendAll, T: 'static + dbus::arg::Arg + for<'z> dbus::arg::Get<'z>>(
        &self,
        member: &str,
        args: A,
    ) -> T {
    ) -> Result<(T,), dbus::Error> {
        let proxy = self.create_proxy();
        // We know that all APIs return immediately, so we can block on it for simplicity.
        let (ret,): (T,) = futures::executor::block_on(async {
        return futures::executor::block_on(async {
            proxy.method_call(self.interface.clone(), member, args).await
        })
        .unwrap();
        });
    }

    fn method<A: AppendAll, T: 'static + dbus::arg::Arg + for<'z> dbus::arg::Get<'z>>(
        &self,
        member: &str,
        args: A,
    ) -> T {
        let (ret,): (T,) = self.method_withresult(member, args).unwrap();
        return ret;
    }

    fn method_noreturn<A: AppendAll>(&self, member: &str, args: A) {
        let proxy = self.create_proxy();
        // We know that all APIs return immediately, so we can block on it for simplicity.
        let _: () = futures::executor::block_on(async {
            proxy.method_call(self.interface.clone(), member, args).await
        })
        .unwrap();
        // The real type should be Result<((),), _> since there is no return value. However, to
        // meet trait constraints, we just use bool and never unwrap the result. This calls the
        // method, waits for the response but doesn't actually attempt to parse the result (on
        // unwrap).
        let _: Result<(bool,), _> = self.method_withresult(member, args);
    }
}

@@ -140,10 +148,15 @@ struct IBluetoothCallbackDBus {}

impl btstack::RPCProxy for IBluetoothCallbackDBus {
    // Dummy implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

#[generate_dbus_exporter(
@@ -174,6 +187,34 @@ impl IBluetoothCallback for IBluetoothCallbackDBus {
    fn on_bond_state_changed(&self, status: u32, address: String, state: u32) {}
}

#[allow(dead_code)]
struct IBluetoothConnectionCallbackDBus {}

impl btstack::RPCProxy for IBluetoothConnectionCallbackDBus {
    // Dummy implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

#[generate_dbus_exporter(
    export_bluetooth_connection_callback_dbus_obj,
    "org.chromium.bluetooth.BluetoothConnectionCallback"
)]
impl IBluetoothConnectionCallback for IBluetoothConnectionCallbackDBus {
    #[dbus_method("OnDeviceConnected")]
    fn on_device_connected(&self, remote_device: BluetoothDevice) {}

    #[dbus_method("OnDeviceDisconencted")]
    fn on_device_disconnected(&self, remote_device: BluetoothDevice) {}
}

pub(crate) struct BluetoothDBus {
    client_proxy: ClientDBusProxy,
}
@@ -212,6 +253,27 @@ impl IBluetooth for BluetoothDBus {
        self.client_proxy.method_noreturn("RegisterCallback", (path,))
    }

    fn register_connection_callback(
        &mut self,
        callback: Box<dyn IBluetoothConnectionCallback + Send>,
    ) -> u32 {
        let path_string = callback.get_object_id();
        let path = dbus::Path::new(path_string.clone()).unwrap();
        export_bluetooth_connection_callback_dbus_obj(
            path_string,
            self.client_proxy.conn.clone(),
            &mut self.client_proxy.cr.lock().unwrap(),
            Arc::new(Mutex::new(callback)),
            Arc::new(Mutex::new(DisconnectWatcher::new())),
        );

        self.client_proxy.method("RegisterConnectionCallback", (path,))
    }

    fn unregister_connection_callback(&mut self, id: u32) -> bool {
        self.client_proxy.method("UnregisterConnectionCallback", (id,))
    }

    fn enable(&mut self) -> bool {
        // Not implemented by server
        true
@@ -255,13 +317,10 @@ impl IBluetooth for BluetoothDBus {
        self.client_proxy.method("GetDiscoveryEndMillis", ())
    }

    fn create_bond(&self, device: BluetoothDevice, transport: BluetoothTransport) -> bool {
    fn create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool {
        self.client_proxy.method(
            "CreateBond",
            (
                BluetoothDevice::to_dbus(device).unwrap(),
                BluetoothTransport::to_dbus(transport).unwrap(),
            ),
            (BluetoothDevice::to_dbus(device).unwrap(), BtTransport::to_dbus(transport).unwrap()),
        )
    }

@@ -282,6 +341,31 @@ impl IBluetooth for BluetoothDBus {
        self.client_proxy.method("GetBondState", (BluetoothDevice::to_dbus(device).unwrap(),))
    }

    fn set_pin(&self, device: BluetoothDevice, accept: bool, len: u32, pin_code: Vec<u8>) -> bool {
        self.client_proxy
            .method("SetPin", (BluetoothDevice::to_dbus(device).unwrap(), accept, len, pin_code))
    }

    fn set_passkey(
        &self,
        device: BluetoothDevice,
        accept: bool,
        len: u32,
        passkey: Vec<u8>,
    ) -> bool {
        self.client_proxy
            .method("SetPasskey", (BluetoothDevice::to_dbus(device).unwrap(), accept, len, passkey))
    }

    fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
        self.client_proxy
            .method("SetPairingConfirmation", (BluetoothDevice::to_dbus(device).unwrap(), accept))
    }

    fn get_connection_state(&self, device: BluetoothDevice) -> u32 {
        self.client_proxy.method("GetConnectionState", (BluetoothDevice::to_dbus(device).unwrap(),))
    }

    fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
        let result: Vec<Vec<u8>> = self
            .client_proxy
@@ -299,6 +383,16 @@ impl IBluetooth for BluetoothDBus {
            (BluetoothDevice::to_dbus(device).unwrap(), Uuid128Bit::to_dbus(uuid).unwrap()),
        )
    }

    fn connect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
        self.client_proxy
            .method("ConnectAllEnabledProfiles", (BluetoothDevice::to_dbus(device).unwrap(),))
    }

    fn disconnect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
        self.client_proxy
            .method("DisconnectAllEnabledProfiles", (BluetoothDevice::to_dbus(device).unwrap(),))
    }
}

#[dbus_propmap(AdapterWithEnabled)]
@@ -326,6 +420,11 @@ impl BluetoothManagerDBus {
            },
        }
    }

    pub(crate) fn is_valid(&self) -> bool {
        let result: Result<(bool,), _> = self.client_proxy.method_withresult("GetFlossEnabled", ());
        return result.is_ok();
    }
}

// TODO: These are boilerplate codes, consider creating a macro to generate.
@@ -375,10 +474,15 @@ struct IBluetoothManagerCallbackDBus {}

impl manager_service::RPCProxy for IBluetoothManagerCallbackDBus {
    // Placeholder implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

#[generate_dbus_exporter(
@@ -600,10 +704,15 @@ struct IBluetoothGattCallbackDBus {}

impl btstack::RPCProxy for IBluetoothGattCallbackDBus {
    // Placeholder implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
    fn unregister(&mut self, _id: u32) -> bool {
        false
    }
}

#[generate_dbus_exporter(
+70 −9

File changed.

Preview size limit exceeded, changes collapsed.

+8 −3
Original line number Diff line number Diff line
@@ -431,10 +431,11 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {
        #ori_item

        impl RPCProxy for #self_ty {
            fn register_disconnect(&mut self, _disconnect_callback: Box<dyn Fn() + Send>) {}
            fn register_disconnect(&mut self, _disconnect_callback: Box<dyn Fn(u32) + Send>) -> u32 { 0 }
            fn get_object_id(&self) -> String {
                String::from("")
            }
            fn unregister(&mut self, _id: u32) -> bool { false }
        }

        struct #struct_ident {
@@ -449,13 +450,17 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {
        }

        impl RPCProxy for #struct_ident {
            fn register_disconnect(&mut self, disconnect_callback: Box<dyn Fn() + Send>) {
                self.disconnect_watcher.lock().unwrap().add(self.remote.clone(), disconnect_callback);
            fn register_disconnect(&mut self, disconnect_callback: Box<dyn Fn(u32) + Send>) -> u32 {
                return self.disconnect_watcher.lock().unwrap().add(self.remote.clone(), disconnect_callback);
            }

            fn get_object_id(&self) -> String {
                self.objpath.to_string().clone()
            }

            fn unregister(&mut self, id: u32) -> bool {
                self.disconnect_watcher.lock().unwrap().remove(self.remote.clone(), id)
            }
        }

        impl DBusArg for Box<dyn #trait_ + Send> {
Loading