Skip to main content

ashpd/backend/
usb.rs

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