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}