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}