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

Commit f98f0cb7 authored by Sonny Sasaka's avatar Sonny Sasaka
Browse files

Floss: Add macro to generate D-Bus interface client

This adds macro to generate D-Bus client method calls. Callback param
type is not yet supported and can be written manually. Future work will
add support to it.

Bug: 200732080
Tag: #floss
Test: Build floss on Linux and test btclient manually

Change-Id: If14a35e335f2370fe60b074f82015a95a9101d2f
parent 55d949d6
Loading
Loading
Loading
Loading
+119 −94
Original line number Original line Diff line number Diff line
@@ -19,7 +19,9 @@ use dbus_crossroads::Crossroads;


use dbus_projection::{impl_dbus_arg_enum, DisconnectWatcher};
use dbus_projection::{impl_dbus_arg_enum, DisconnectWatcher};


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


use manager_service::iface_bluetooth_manager::{
use manager_service::iface_bluetooth_manager::{
    AdapterWithEnabled, IBluetoothManager, IBluetoothManagerCallback,
    AdapterWithEnabled, IBluetoothManager, IBluetoothManagerCallback,
@@ -41,6 +43,7 @@ impl_dbus_arg_enum!(BtSspVariant);
impl_dbus_arg_enum!(GattStatus);
impl_dbus_arg_enum!(GattStatus);
impl_dbus_arg_enum!(GattWriteType);
impl_dbus_arg_enum!(GattWriteType);
impl_dbus_arg_enum!(LePhy);
impl_dbus_arg_enum!(LePhy);
impl_dbus_arg_enum!(GattWriteRequestStatus);


// Represents Uuid128Bit as an array in D-Bus.
// Represents Uuid128Bit as an array in D-Bus.
impl DBusArg for Uuid128Bit {
impl DBusArg for Uuid128Bit {
@@ -237,7 +240,7 @@ impl BluetoothDBus {
    }
    }
}
}


// TODO(b/200732080): These are boilerplate codes, consider creating a macro to generate.
#[generate_dbus_interface_client]
impl IBluetooth for BluetoothDBus {
impl IBluetooth for BluetoothDBus {
    fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) {
    fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) {
        let path_string = callback.get_object_id();
        let path_string = callback.get_object_id();
@@ -270,8 +273,9 @@ impl IBluetooth for BluetoothDBus {
        self.client_proxy.method("RegisterConnectionCallback", (path,))
        self.client_proxy.method("RegisterConnectionCallback", (path,))
    }
    }


    #[dbus_method("UnregisterConnectionCallback")]
    fn unregister_connection_callback(&mut self, id: u32) -> bool {
    fn unregister_connection_callback(&mut self, id: u32) -> bool {
        self.client_proxy.method("UnregisterConnectionCallback", (id,))
        dbus_generated!()
    }
    }


    fn enable(&mut self) -> bool {
    fn enable(&mut self) -> bool {
@@ -284,136 +288,149 @@ impl IBluetooth for BluetoothDBus {
        true
        true
    }
    }


    #[dbus_method("GetAddress")]
    fn get_address(&self) -> String {
    fn get_address(&self) -> String {
        self.client_proxy.method("GetAddress", ())
        dbus_generated!()
    }
    }


    #[dbus_method("GetUuids")]
    fn get_uuids(&self) -> Vec<Uuid128Bit> {
    fn get_uuids(&self) -> Vec<Uuid128Bit> {
        let result: Vec<Vec<u8>> = self.client_proxy.method("GetUuids", ());
        dbus_generated!()
        <Vec<Uuid128Bit> as DBusArg>::from_dbus(result, None, None, None).unwrap()
    }
    }


    #[dbus_method("GetName")]
    fn get_name(&self) -> String {
    fn get_name(&self) -> String {
        self.client_proxy.method("GetName", ())
        dbus_generated!()
    }
    }


    #[dbus_method("SetName")]
    fn set_name(&self, name: String) -> bool {
    fn set_name(&self, name: String) -> bool {
        self.client_proxy.method("SetName", (name,))
        dbus_generated!()
    }
    }


    #[dbus_method("GetBluetoothClass")]
    fn get_bluetooth_class(&self) -> u32 {
    fn get_bluetooth_class(&self) -> u32 {
        self.client_proxy.method("GetBluetoothClass", ())
        dbus_generated!()
    }
    }


    #[dbus_method("SetBluetoothClass")]
    fn set_bluetooth_class(&self, cod: u32) -> bool {
    fn set_bluetooth_class(&self, cod: u32) -> bool {
        self.client_proxy.method("SetBluetoothClass", (cod,))
        dbus_generated!()
    }
    }


    #[dbus_method("GetDiscoverable")]
    fn get_discoverable(&self) -> bool {
    fn get_discoverable(&self) -> bool {
        self.client_proxy.method("GetDiscoverable", ())
        dbus_generated!()
    }
    }


    #[dbus_method("GetDiscoverableTimeout")]
    fn get_discoverable_timeout(&self) -> u32 {
    fn get_discoverable_timeout(&self) -> u32 {
        self.client_proxy.method("GetDiscoverableTimeout", ())
        dbus_generated!()
    }
    }


    #[dbus_method("SetDiscoverable")]
    fn set_discoverable(&self, mode: bool, duration: u32) -> bool {
    fn set_discoverable(&self, mode: bool, duration: u32) -> bool {
        self.client_proxy.method("SetDiscoverable", (mode, duration))
        dbus_generated!()
    }
    }


    #[dbus_method("IsMultiAdvertisementSupported")]
    fn is_multi_advertisement_supported(&self) -> bool {
    fn is_multi_advertisement_supported(&self) -> bool {
        self.client_proxy.method("IsMultiAdvertisementSupported", ())
        dbus_generated!()
    }
    }


    #[dbus_method("IsLeExtendedAdvertisingSupported")]
    fn is_le_extended_advertising_supported(&self) -> bool {
    fn is_le_extended_advertising_supported(&self) -> bool {
        self.client_proxy.method("IsLeExtendedAdvertisingSupported", ())
        dbus_generated!()
    }
    }


    #[dbus_method("StartDiscovery")]
    fn start_discovery(&self) -> bool {
    fn start_discovery(&self) -> bool {
        self.client_proxy.method("StartDiscovery", ())
        dbus_generated!()
    }
    }


    #[dbus_method("CancelDiscovery")]
    fn cancel_discovery(&self) -> bool {
    fn cancel_discovery(&self) -> bool {
        self.client_proxy.method("CancelDiscovery", ())
        dbus_generated!()
    }
    }


    #[dbus_method("IsDiscovering")]
    fn is_discovering(&self) -> bool {
    fn is_discovering(&self) -> bool {
        self.client_proxy.method("IsDiscovering", ())
        dbus_generated!()
    }
    }


    #[dbus_method("GetDiscoveryEndMillis")]
    fn get_discovery_end_millis(&self) -> u64 {
    fn get_discovery_end_millis(&self) -> u64 {
        self.client_proxy.method("GetDiscoveryEndMillis", ())
        dbus_generated!()
    }
    }


    #[dbus_method("CreateBond")]
    fn create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool {
    fn create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool {
        self.client_proxy.method(
        dbus_generated!()
            "CreateBond",
            (BluetoothDevice::to_dbus(device).unwrap(), BtTransport::to_dbus(transport).unwrap()),
        )
    }
    }


    #[dbus_method("CancelBondProcess")]
    fn cancel_bond_process(&self, device: BluetoothDevice) -> bool {
    fn cancel_bond_process(&self, device: BluetoothDevice) -> bool {
        self.client_proxy.method("CancelBondProcess", (BluetoothDevice::to_dbus(device).unwrap(),))
        dbus_generated!()
    }
    }


    #[dbus_method("RemoveBond")]
    fn remove_bond(&self, device: BluetoothDevice) -> bool {
    fn remove_bond(&self, device: BluetoothDevice) -> bool {
        self.client_proxy.method("RemoveBond", (BluetoothDevice::to_dbus(device).unwrap(),))
        dbus_generated!()
    }
    }


    #[dbus_method("GetBondedDevices")]
    fn get_bonded_devices(&self) -> Vec<BluetoothDevice> {
    fn get_bonded_devices(&self) -> Vec<BluetoothDevice> {
        let props: Vec<dbus::arg::PropMap> = self.client_proxy.method("GetBondedDevices", ());
        dbus_generated!()
        <Vec<BluetoothDevice> as DBusArg>::from_dbus(props, None, None, None).unwrap()
    }
    }


    #[dbus_method("GetBondState")]
    fn get_bond_state(&self, device: BluetoothDevice) -> u32 {
    fn get_bond_state(&self, device: BluetoothDevice) -> u32 {
        self.client_proxy.method("GetBondState", (BluetoothDevice::to_dbus(device).unwrap(),))
        dbus_generated!()
    }
    }


    #[dbus_method("SetPin")]
    fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool {
    fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool {
        self.client_proxy
        dbus_generated!()
            .method("SetPin", (BluetoothDevice::to_dbus(device).unwrap(), accept, pin_code))
    }
    }


    #[dbus_method("SetPasskey")]
    fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool {
    fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool {
        self.client_proxy
        dbus_generated!()
            .method("SetPasskey", (BluetoothDevice::to_dbus(device).unwrap(), accept, passkey))
    }
    }


    #[dbus_method("SetPairingConfirmation")]
    fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
    fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
        self.client_proxy
        dbus_generated!()
            .method("SetPairingConfirmation", (BluetoothDevice::to_dbus(device).unwrap(), accept))
    }
    }


    #[dbus_method("GetConnectionState")]
    fn get_connection_state(&self, device: BluetoothDevice) -> u32 {
    fn get_connection_state(&self, device: BluetoothDevice) -> u32 {
        self.client_proxy.method("GetConnectionState", (BluetoothDevice::to_dbus(device).unwrap(),))
        dbus_generated!()
    }
    }


    #[dbus_method("GetRemoteUuids")]
    fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
    fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
        let result: Vec<Vec<u8>> = self
        dbus_generated!()
            .client_proxy
            .method("GetRemoteUuids", (BluetoothDevice::to_dbus(device).unwrap(),));
        <Vec<Uuid128Bit> as DBusArg>::from_dbus(result, None, None, None).unwrap()
    }
    }


    #[dbus_method("FetchRemoteUuids")]
    fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool {
    fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool {
        self.client_proxy.method("FetchRemoteUuids", (BluetoothDevice::to_dbus(device).unwrap(),))
        dbus_generated!()
    }
    }


    #[dbus_method("SdpSearch")]
    fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
    fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
        self.client_proxy.method(
        dbus_generated!()
            "SdpSearch",
            (BluetoothDevice::to_dbus(device).unwrap(), Uuid128Bit::to_dbus(uuid).unwrap()),
        )
    }
    }


    #[dbus_method("ConnectAllEnabledProfiles")]
    fn connect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
    fn connect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
        self.client_proxy
        dbus_generated!()
            .method("ConnectAllEnabledProfiles", (BluetoothDevice::to_dbus(device).unwrap(),))
    }
    }


    #[dbus_method("DisconnectAllEnabledProfiles")]
    fn disconnect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
    fn disconnect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
        self.client_proxy
        dbus_generated!()
            .method("DisconnectAllEnabledProfiles", (BluetoothDevice::to_dbus(device).unwrap(),))
    }
    }
}
}


@@ -449,20 +466,25 @@ impl BluetoothManagerDBus {
    }
    }
}
}


// TODO: These are boilerplate codes, consider creating a macro to generate.
#[generate_dbus_interface_client]
impl IBluetoothManager for BluetoothManagerDBus {
impl IBluetoothManager for BluetoothManagerDBus {
    #[dbus_method("Start")]
    fn start(&mut self, hci_interface: i32) {
    fn start(&mut self, hci_interface: i32) {
        self.client_proxy.method_noreturn("Start", (hci_interface,))
        dbus_generated!()
    }
    }


    #[dbus_method("Stop")]
    fn stop(&mut self, hci_interface: i32) {
    fn stop(&mut self, hci_interface: i32) {
        self.client_proxy.method_noreturn("Stop", (hci_interface,))
        dbus_generated!()
    }
    }


    #[dbus_method("GetAdapterEnabled")]
    fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool {
    fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool {
        self.client_proxy.method("GetAdapterEnabled", (hci_interface,))
        dbus_generated!()
    }
    }


    // `generate_dbus_interface_client` doesn't support callback types yet.
    // TODO(b/200732080): Support autogenerate code for callback types.
    fn register_callback(&mut self, callback: Box<dyn IBluetoothManagerCallback + Send>) {
    fn register_callback(&mut self, callback: Box<dyn IBluetoothManagerCallback + Send>) {
        let path_string = callback.get_object_id();
        let path_string = callback.get_object_id();
        let path = dbus::Path::new(path_string.clone()).unwrap();
        let path = dbus::Path::new(path_string.clone()).unwrap();
@@ -477,17 +499,19 @@ impl IBluetoothManager for BluetoothManagerDBus {
        self.client_proxy.method_noreturn("RegisterCallback", (path,))
        self.client_proxy.method_noreturn("RegisterCallback", (path,))
    }
    }


    #[dbus_method("GetFlossEnabled")]
    fn get_floss_enabled(&mut self) -> bool {
    fn get_floss_enabled(&mut self) -> bool {
        self.client_proxy.method("GetFlossEnabled", ())
        dbus_generated!()
    }
    }


    #[dbus_method("SetFlossEnabled")]
    fn set_floss_enabled(&mut self, enabled: bool) {
    fn set_floss_enabled(&mut self, enabled: bool) {
        self.client_proxy.method_noreturn("SetFlossEnabled", (enabled,))
        dbus_generated!()
    }
    }


    #[dbus_method("GetAvailableAdapters")]
    fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> {
    fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> {
        let props: Vec<dbus::arg::PropMap> = self.client_proxy.method("GetAvailableAdapters", ());
        dbus_generated!()
        <Vec<AdapterWithEnabled> as DBusArg>::from_dbus(props, None, None, None).unwrap()
    }
    }
}
}


@@ -541,7 +565,7 @@ impl BluetoothGattDBus {
    }
    }
}
}


// TODO: These are boilerplate codes, consider creating a macro to generate.
#[generate_dbus_interface_client]
impl IBluetoothGatt for BluetoothGattDBus {
impl IBluetoothGatt for BluetoothGattDBus {
    fn register_scanner(&self, _callback: Box<dyn IScannerCallback + Send>) {
    fn register_scanner(&self, _callback: Box<dyn IScannerCallback + Send>) {
        // TODO(b/200066804): implement
        // TODO(b/200066804): implement
@@ -578,10 +602,12 @@ impl IBluetoothGatt for BluetoothGattDBus {
        self.client_proxy.method_noreturn("RegisterClient", (app_uuid, path, eatt_support))
        self.client_proxy.method_noreturn("RegisterClient", (app_uuid, path, eatt_support))
    }
    }


    #[dbus_method("UnregisterClient")]
    fn unregister_client(&mut self, client_id: i32) {
    fn unregister_client(&mut self, client_id: i32) {
        self.client_proxy.method_noreturn("UnregisterClient", (client_id,))
        dbus_generated!()
    }
    }


    #[dbus_method("ClientConnect")]
    fn client_connect(
    fn client_connect(
        &self,
        &self,
        client_id: i32,
        client_id: i32,
@@ -591,16 +617,15 @@ impl IBluetoothGatt for BluetoothGattDBus {
        opportunistic: bool,
        opportunistic: bool,
        phy: i32,
        phy: i32,
    ) {
    ) {
        self.client_proxy.method_noreturn(
        dbus_generated!()
            "ClientConnect",
            (client_id, addr, is_direct, transport, opportunistic, phy),
        )
    }
    }


    #[dbus_method("ClientDisconnect")]
    fn client_disconnect(&self, client_id: i32, addr: String) {
    fn client_disconnect(&self, client_id: i32, addr: String) {
        self.client_proxy.method_noreturn("ClientDisconnect", (client_id, addr))
        dbus_generated!()
    }
    }


    #[dbus_method("ClientSetPreferredPhy")]
    fn client_set_preferred_phy(
    fn client_set_preferred_phy(
        &self,
        &self,
        client_id: i32,
        client_id: i32,
@@ -609,32 +634,35 @@ impl IBluetoothGatt for BluetoothGattDBus {
        rx_phy: LePhy,
        rx_phy: LePhy,
        phy_options: i32,
        phy_options: i32,
    ) {
    ) {
        self.client_proxy.method_noreturn(
        dbus_generated!()
            "ClientSetPreferredPhy",
            (client_id, addr, tx_phy.to_i32().unwrap(), rx_phy.to_i32().unwrap(), phy_options),
        )
    }
    }


    #[dbus_method("ClientReadPhy")]
    fn client_read_phy(&mut self, client_id: i32, addr: String) {
    fn client_read_phy(&mut self, client_id: i32, addr: String) {
        self.client_proxy.method_noreturn("ClientReadPhy", (client_id, addr))
        dbus_generated!()
    }
    }


    #[dbus_method("RefreshDevice")]
    fn refresh_device(&self, client_id: i32, addr: String) {
    fn refresh_device(&self, client_id: i32, addr: String) {
        self.client_proxy.method_noreturn("RefreshDevice", (client_id, addr))
        dbus_generated!()
    }
    }


    #[dbus_method("DiscoverServices")]
    fn discover_services(&self, client_id: i32, addr: String) {
    fn discover_services(&self, client_id: i32, addr: String) {
        self.client_proxy.method_noreturn("DiscoverServices", (client_id, addr))
        dbus_generated!()
    }
    }


    #[dbus_method("DiscoverServiceByUuid")]
    fn discover_service_by_uuid(&self, client_id: i32, addr: String, uuid: String) {
    fn discover_service_by_uuid(&self, client_id: i32, addr: String, uuid: String) {
        self.client_proxy.method_noreturn("DiscoverServiceByUuid", (client_id, addr, uuid))
        dbus_generated!()
    }
    }


    #[dbus_method("ReadCharacteristic")]
    fn read_characteristic(&self, client_id: i32, addr: String, handle: i32, auth_req: i32) {
    fn read_characteristic(&self, client_id: i32, addr: String, handle: i32, auth_req: i32) {
        self.client_proxy.method_noreturn("ReadCharacteristic", (client_id, addr, handle, auth_req))
        dbus_generated!()
    }
    }


    #[dbus_method("ReadUsingCharacteristicUuid")]
    fn read_using_characteristic_uuid(
    fn read_using_characteristic_uuid(
        &self,
        &self,
        client_id: i32,
        client_id: i32,
@@ -644,12 +672,10 @@ impl IBluetoothGatt for BluetoothGattDBus {
        end_handle: i32,
        end_handle: i32,
        auth_req: i32,
        auth_req: i32,
    ) {
    ) {
        self.client_proxy.method_noreturn(
        dbus_generated!()
            "ReadUsingCharacteristicUuid",
            (client_id, addr, uuid, start_handle, end_handle, auth_req),
        )
    }
    }


    #[dbus_method("WriteCharacteristic")]
    fn write_characteristic(
    fn write_characteristic(
        &self,
        &self,
        client_id: i32,
        client_id: i32,
@@ -659,17 +685,15 @@ impl IBluetoothGatt for BluetoothGattDBus {
        auth_req: i32,
        auth_req: i32,
        value: Vec<u8>,
        value: Vec<u8>,
    ) -> GattWriteRequestStatus {
    ) -> GattWriteRequestStatus {
        GattWriteRequestStatus::from_i32(self.client_proxy.method(
        dbus_generated!()
            "WriteCharacteristic",
            (client_id, addr, handle, write_type.to_i32().unwrap(), auth_req, value),
        ))
        .unwrap()
    }
    }


    #[dbus_method("ReadDescriptor")]
    fn read_descriptor(&self, client_id: i32, addr: String, handle: i32, auth_req: i32) {
    fn read_descriptor(&self, client_id: i32, addr: String, handle: i32, auth_req: i32) {
        self.client_proxy.method_noreturn("ReadDescriptor", (client_id, addr, handle, auth_req))
        dbus_generated!()
    }
    }


    #[dbus_method("WriteDescriptor")]
    fn write_descriptor(
    fn write_descriptor(
        &self,
        &self,
        client_id: i32,
        client_id: i32,
@@ -678,31 +702,35 @@ impl IBluetoothGatt for BluetoothGattDBus {
        auth_req: i32,
        auth_req: i32,
        value: Vec<u8>,
        value: Vec<u8>,
    ) {
    ) {
        self.client_proxy
        dbus_generated!()
            .method_noreturn("WriteDescriptor", (client_id, addr, handle, auth_req, value))
    }
    }


    #[dbus_method("RegisterForNotification")]
    fn register_for_notification(&self, client_id: i32, addr: String, handle: i32, enable: bool) {
    fn register_for_notification(&self, client_id: i32, addr: String, handle: i32, enable: bool) {
        self.client_proxy
        dbus_generated!()
            .method_noreturn("RegisterForNotification", (client_id, addr, handle, enable))
    }
    }


    #[dbus_method("BeginReliableWrite")]
    fn begin_reliable_write(&mut self, client_id: i32, addr: String) {
    fn begin_reliable_write(&mut self, client_id: i32, addr: String) {
        self.client_proxy.method_noreturn("BeginReliableWrite", (client_id, addr))
        dbus_generated!()
    }
    }


    #[dbus_method("EndReliableWrite")]
    fn end_reliable_write(&mut self, client_id: i32, addr: String, execute: bool) {
    fn end_reliable_write(&mut self, client_id: i32, addr: String, execute: bool) {
        self.client_proxy.method_noreturn("EndReliableWrite", (client_id, addr, execute))
        dbus_generated!()
    }
    }


    #[dbus_method("ReadRemoteRssi")]
    fn read_remote_rssi(&self, client_id: i32, addr: String) {
    fn read_remote_rssi(&self, client_id: i32, addr: String) {
        self.client_proxy.method_noreturn("ReadRemoteRssi", (client_id, addr))
        dbus_generated!()
    }
    }


    #[dbus_method("ConfigureMtu")]
    fn configure_mtu(&self, client_id: i32, addr: String, mtu: i32) {
    fn configure_mtu(&self, client_id: i32, addr: String, mtu: i32) {
        self.client_proxy.method_noreturn("ConfigureMtu", (client_id, addr, mtu))
        dbus_generated!()
    }
    }


    #[dbus_method("ConnectionParameterUpdate")]
    fn connection_parameter_update(
    fn connection_parameter_update(
        &self,
        &self,
        client_id: i32,
        client_id: i32,
@@ -714,10 +742,7 @@ impl IBluetoothGatt for BluetoothGattDBus {
        min_ce_len: u16,
        min_ce_len: u16,
        max_ce_len: u16,
        max_ce_len: u16,
    ) {
    ) {
        self.client_proxy.method_noreturn(
        dbus_generated!()
            "ConnectionParameterUpdate",
            (client_id, addr, min_interval, max_interval, latency, timeout, min_ce_len, max_ce_len),
        )
    }
    }
}
}


+135 −0
Original line number Original line Diff line number Diff line
@@ -207,6 +207,135 @@ pub fn generate_dbus_exporter(attr: TokenStream, item: TokenStream) -> TokenStre
    gen.into()
    gen.into()
}
}


/// Generates a client implementation of a D-Bus interface.
///
/// Example:
///   #[generate_dbus_interface_client()]
///
/// The impl containing #[dbus_method()] will contain a generated code to call the method via D-Bus.
#[proc_macro_attribute]
pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let ast: ItemImpl = syn::parse(item.clone()).unwrap();
    let trait_path = ast.trait_.unwrap().1;
    let struct_path = match *ast.self_ty {
        Type::Path(path) => path,
        _ => panic!("Struct path not available"),
    };

    let mut methods = quote! {};

    // Iterate on every methods of a trait impl
    for item in ast.items {
        if let ImplItem::Method(method) = item {
            // If the method is not marked with #[dbus_method], just copy the
            // original method body.
            if method.attrs.len() != 1 {
                methods = quote! {
                    #methods

                    #method
                };
                continue;
            }

            let attr = &method.attrs[0];
            if !attr.path.get_ident().unwrap().to_string().eq("dbus_method") {
                continue;
            }

            let sig = &method.sig;

            let dbus_method_name = if let Meta::List(meta_list) = attr.parse_meta().unwrap() {
                Some(meta_list.nested[0].clone())
            } else {
                None
            };

            if dbus_method_name.is_none() {
                continue;
            }

            let mut input_list = quote! {};

            // Iterate on every parameter of a method to build a tuple, e.g.
            // `(param1, param2, param3)`
            for input in &method.sig.inputs {
                if let FnArg::Typed(ref typed) = input {
                    let arg_type = &typed.ty;
                    if let Pat::Ident(pat_ident) = &*typed.pat {
                        let ident = pat_ident.ident.clone();

                        input_list = quote! {
                            #input_list
                            <#arg_type as DBusArg>::to_dbus(#ident).unwrap(),
                        };
                    }
                }
            }

            let mut output_as_dbus_arg = quote! {};
            if let ReturnType::Type(_, t) = &method.sig.output {
                output_as_dbus_arg = quote! {<#t as DBusArg>};
            }

            let input_tuple = quote! {
                (#input_list)
            };

            let body = match &method.sig.output {
                // Build the method call to `self.client_proxy`. `method` or `method_noreturn`
                // depends on whether there is a return from the function.
                ReturnType::Default => {
                    quote! {
                        self.client_proxy.method_noreturn(#dbus_method_name, #input_tuple)
                    }
                }
                _ => {
                    quote! {
                        let ret: #output_as_dbus_arg::DBusType = self.client_proxy.method(
                            #dbus_method_name,
                            #input_tuple,
                        );
                        #output_as_dbus_arg::from_dbus(ret, None, None, None).unwrap()
                    }
                }
            };

            // The method definition is its signature and the body.
            let generated_method = quote! {
                #sig {
                    #body
                }
            };

            // Assemble all the method definitions.
            methods = quote! {
                #methods

                #generated_method
            };
        }
    }

    let gen = quote! {
        impl #trait_path for #struct_path {
            #methods
        }
    };

    // TODO: Have a switch to turn on/off this debug.
    debug_output_to_file(
        &gen,
        std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap())
            .join(format!("out-{}.rs", struct_path.path.get_ident().unwrap()))
            .to_str()
            .unwrap()
            .to_string(),
    );

    gen.into()
}

fn copy_without_attributes(item: &TokenStream) -> TokenStream {
fn copy_without_attributes(item: &TokenStream) -> TokenStream {
    let mut ast: ItemStruct = syn::parse(item.clone()).unwrap();
    let mut ast: ItemStruct = syn::parse(item.clone()).unwrap();
    for field in &mut ast.fields {
    for field in &mut ast.fields {
@@ -365,7 +494,13 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {


    for item in ast.items {
    for item in ast.items {
        if let ImplItem::Method(method) = item {
        if let ImplItem::Method(method) = item {
            // If the method is not marked with #[dbus_method], just copy the
            // original method body.
            if method.attrs.len() != 1 {
            if method.attrs.len() != 1 {
                method_impls = quote! {
                    #method_impls
                    #method
                };
                continue;
                continue;
            }
            }