ashpd/backend/
usb.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4
5use crate::{
6    backend::{
7        request::{Request, RequestImpl},
8        MaybeAppID, MaybeWindowIdentifier, Result,
9    },
10    desktop::{request::Response, usb::UsbDevice, HandleToken},
11    zvariant::{DeserializeDict, OwnedObjectPath, SerializeDict, Type},
12    AppID, WindowIdentifierType,
13};
14
15#[derive(Debug, DeserializeDict, Type)]
16#[zvariant(signature = "dict")]
17pub struct AcquireDevicesOptions {}
18
19#[derive(Debug, SerializeDict, DeserializeDict, Type)]
20#[zvariant(signature = "dict")]
21pub struct AccessOptions {
22    writable: Option<bool>,
23}
24
25impl AccessOptions {
26    pub fn new(is_writable: bool) -> Self {
27        Self {
28            writable: Some(is_writable),
29        }
30    }
31
32    pub fn is_writable(&self) -> Option<bool> {
33        self.writable
34    }
35}
36
37#[async_trait]
38pub trait UsbImpl: RequestImpl {
39    #[doc(alias = "AcquireDevices")]
40    async fn acquire_devices(
41        &self,
42        token: HandleToken,
43        window_identifier: Option<WindowIdentifierType>,
44        app_id: Option<AppID>,
45        devices: Vec<(String, UsbDevice, AccessOptions)>,
46        options: AcquireDevicesOptions,
47    ) -> Result<Vec<(String, AccessOptions)>>;
48}
49
50pub(crate) struct UsbInterface {
51    imp: Arc<dyn UsbImpl>,
52    spawn: Arc<dyn futures_util::task::Spawn + Send + Sync>,
53    cnx: zbus::Connection,
54}
55
56impl UsbInterface {
57    pub fn new(
58        imp: Arc<dyn UsbImpl>,
59        cnx: zbus::Connection,
60        spawn: Arc<dyn futures_util::task::Spawn + Send + Sync>,
61    ) -> Self {
62        Self { imp, cnx, spawn }
63    }
64}
65
66#[zbus::interface(name = "org.freedesktop.impl.portal.Usb")]
67impl UsbInterface {
68    #[zbus(property(emits_changed_signal = "const"), name = "version")]
69    fn version(&self) -> u32 {
70        1
71    }
72
73    #[zbus(name = "AcquireDevices")]
74    #[zbus(out_args("response", "results"))]
75    async fn acquire_devices(
76        &self,
77        handle: OwnedObjectPath,
78        window_identifier: MaybeWindowIdentifier,
79        app_id: MaybeAppID,
80        devices: Vec<(String, UsbDevice, AccessOptions)>,
81        options: AcquireDevicesOptions,
82    ) -> Result<Response<Vec<(String, AccessOptions)>>> {
83        let imp = Arc::clone(&self.imp);
84
85        Request::spawn(
86            "Usb::AcquireDevices",
87            &self.cnx,
88            handle.clone(),
89            Arc::clone(&self.imp),
90            Arc::clone(&self.spawn),
91            async move {
92                imp.acquire_devices(
93                    HandleToken::try_from(&handle).unwrap(),
94                    window_identifier.inner(),
95                    app_id.inner(),
96                    devices,
97                    options,
98                )
99                .await
100            },
101        )
102        .await
103    }
104}