1#[cfg(keyos)]
5pub use atsama5d27::udphs::{EndpointDirection, EndpointType};
6use server::{CheckedConn, CheckedPermissions, MessageAllowed, MessageId as _};
7
8use super::messages::*;
9#[cfg(all(doc, not(keyos)))]
10pub use super::messages::{EndpointDirection, EndpointType};
11use crate::error::UsbError;
12
13#[macro_export]
14macro_rules! use_device_api {
15 () => {
16 mod usb_device_permissions {
17 use $crate::device::messages::*;
18 #[derive(Clone, Default, server::Permissions)]
19 #[server_name = "os/usbdev"]
20 pub struct UsbDevicePermissions;
21 }
22 type UsbDeviceEmulation =
23 $crate::device::api::UsbDeviceEmulation<usb_device_permissions::UsbDevicePermissions>;
24 type UsbEmulatedEndpoint =
25 $crate::device::api::UsbEmulatedEndpoint<usb_device_permissions::UsbDevicePermissions>;
26 type UsbInterfaceConfig<'a, const N: usize> = $crate::device::api::UsbInterfaceConfig<'a, N>;
27 type UsbRegisteredInterface =
28 $crate::device::api::UsbRegisteredInterface<usb_device_permissions::UsbDevicePermissions>;
29 };
30}
31
32#[derive(Default)]
33pub struct UsbDeviceEmulation<P: CheckedPermissions>(CheckedConn<P>);
34
35pub struct UsbInterfaceConfig<'a, const N: usize> {
36 interface_number: u8,
37 if_class: u8,
38 if_subclass: u8,
39 if_protocol: u8,
40 endpoints: &'a [EndpointProperties; N],
41 interface_functional_descriptors: &'a [u8],
42 associated_interface_count: u8,
43 capabilities: Vec<DeviceCapability>,
44 setup_responder: Option<Box<dyn FnOnce(xous::PID) -> Result<xous::CID, UsbError>>>,
45}
46
47impl<'a, const N: usize> UsbInterfaceConfig<'a, N> {
48 pub fn new(
49 interface_number: u8,
50 if_class: u8,
51 if_subclass: u8,
52 if_protocol: u8,
53 endpoints: &'a [EndpointProperties; N],
54 ) -> Self {
55 Self {
56 interface_number,
57 if_class,
58 if_subclass,
59 if_protocol,
60 endpoints,
61 interface_functional_descriptors: &[],
62 associated_interface_count: 0,
63 capabilities: Vec::new(),
64 setup_responder: None,
65 }
66 }
67
68 pub fn with_functional_descriptors(mut self, descriptors: &'a [u8]) -> Self {
69 self.interface_functional_descriptors = descriptors;
70 self
71 }
72
73 pub fn with_associated_interface_count(mut self, count: u8) -> Self {
74 self.associated_interface_count = count;
75 self
76 }
77
78 pub fn with_capability(
79 mut self,
80 cap_type: u8,
81 cap_subtype: u8,
82 cap_uuid: uuid::Uuid,
83 capability_functional_descriptors: &[u8],
84 ) -> Self {
85 self.capabilities.push(DeviceCapability {
86 cap_type,
87 cap_subtype,
88 cap_uuid: cap_uuid.to_bytes_le().to_vec(),
89 capability_functional_descriptors: capability_functional_descriptors.into(),
90 });
91 self
92 }
93
94 pub fn with_setup_responder<S>(mut self, setup_responder: Option<S>) -> Self
95 where
96 S: server::Server + server::BlockingArchiveHandler<SetupPacketCallback> + Send + 'static,
97 {
98 if let Some(setup_responder) = setup_responder {
99 self.setup_responder = Some(Box::new(move |pid| {
100 let cid = server::listen_and_connect(setup_responder, pid);
101 xous::allow_messages_on_connection(
102 pid,
103 cid,
104 SetupPacketCallback::ID..(SetupPacketCallback::ID + 1),
105 )?;
106 Ok(cid)
107 }));
108 }
109 self
110 }
111}
112
113impl<P: CheckedPermissions> UsbDeviceEmulation<P> {
114 pub fn register_interface<const N: usize>(
118 &mut self,
119 config: UsbInterfaceConfig<'_, N>,
120 ) -> Result<(UsbRegisteredInterface<P>, [UsbEmulatedEndpoint<P>; N]), UsbError>
121 where
122 P: MessageAllowed<RegisterInterface>,
123 {
124 let setup_responder = if let Some(connect) = config.setup_responder {
125 Some(connect(self.0.get_remote_pid())?)
126 } else {
127 None
128 };
129 let registered = self.0.send_blocking_archive(RegisterInterface {
130 interface_number: config.interface_number,
131 if_class: config.if_class,
132 if_subclass: config.if_subclass,
133 if_protocol: config.if_protocol,
134 endpoints: config.endpoints.into(),
135 interface_functional_descriptors: config.interface_functional_descriptors.into(),
136 associated_interface_count: config.associated_interface_count,
137 capabilities: config.capabilities,
138 setup_responder,
139 })?;
140 let interface =
141 UsbRegisteredInterface { connection: self.0.clone(), interface_number: config.interface_number };
142 let endpoints = core::array::from_fn(|i| UsbEmulatedEndpoint {
143 connection: self.0.clone(),
144 endpoint_number: registered.endpoints[i],
145 });
146 Ok((interface, endpoints))
147 }
148
149 pub fn wait_for_connection(&self) -> Result<(), UsbError>
151 where
152 P: MessageAllowed<WaitForConnection>,
153 {
154 self.0.try_send_blocking_scalar(WaitForConnection)?;
155 Ok(())
156 }
157
158 pub fn is_enabled(&self) -> Result<bool, UsbError>
159 where
160 P: MessageAllowed<IsDeviceEmulationEnabled>,
161 {
162 Ok(self.0.try_send_blocking_scalar(IsDeviceEmulationEnabled)?)
163 }
164
165 pub fn is_connected(&self) -> Result<bool, UsbError>
166 where
167 P: MessageAllowed<IsDeviceEmulationConnected>,
168 {
169 Ok(self.0.try_send_blocking_scalar(IsDeviceEmulationConnected)?)
170 }
171
172 pub fn is_cable_connected(&self) -> Result<bool, UsbError>
174 where
175 P: MessageAllowed<IsCableConnected>,
176 {
177 Ok(self.0.try_send_blocking_scalar(IsCableConnected)?)
178 }
179
180 pub fn is_device_mode(&self) -> Result<bool, UsbError>
182 where
183 P: MessageAllowed<IsDeviceMode>,
184 {
185 Ok(self.0.try_send_blocking_scalar(IsDeviceMode)?)
186 }
187
188 pub fn set_custom_vid_pid(&mut self, vid: Option<u16>, pid: Option<u16>)
189 where
190 P: MessageAllowed<SetVidPid>,
191 {
192 self.0.try_send_blocking_scalar(SetVidPid { vid, pid }).unwrap().unwrap();
193 }
194
195 pub fn reset_controller(&mut self)
196 where
197 P: MessageAllowed<ResetController>,
198 {
199 self.0.try_send_blocking_scalar(ResetController).unwrap().unwrap()
200 }
201}
202
203#[derive(Clone)]
204pub struct UsbRegisteredInterface<P: CheckedPermissions> {
205 connection: CheckedConn<P>,
206 interface_number: u8,
207}
208
209impl<P: CheckedPermissions> UsbRegisteredInterface<P> {
210 pub fn number(&self) -> u8 { self.interface_number }
211
212 pub fn set_enabled(&self, enabled: bool) -> Result<(), UsbError>
213 where
214 P: MessageAllowed<SetInterfaceEnabled>,
215 {
216 self.connection.try_send_blocking_scalar(SetInterfaceEnabled {
217 interface_number: self.interface_number,
218 enabled,
219 })??;
220 Ok(())
221 }
222}
223
224pub struct UsbEmulatedEndpoint<P: CheckedPermissions> {
225 connection: CheckedConn<P>,
226 endpoint_number: u8,
227}
228
229impl<P: CheckedPermissions> UsbEmulatedEndpoint<P> {
230 pub fn endpoint_number(&self) -> u8 { self.endpoint_number }
232
233 pub fn read_buf(&mut self, buf: xous::MemoryRange, length: u16) -> Result<usize, UsbError>
236 where
237 P: MessageAllowed<ReadEndpoint>,
238 {
239 self.connection.lend_mut(ReadEndpoint { buf, endpoint: self.endpoint_number, length })
240 }
241
242 pub fn write_buf(&mut self, buf: xous::MemoryRange, length: usize) -> Result<usize, UsbError>
251 where
252 P: MessageAllowed<WriteEndpoint>,
253 {
254 self.connection.lend_mut(WriteEndpoint { buf, endpoint: self.endpoint_number, length, zlp: false })
255 }
256
257 pub fn write_buf_zlp(&mut self, buf: xous::MemoryRange, length: usize) -> Result<usize, UsbError>
263 where
264 P: MessageAllowed<WriteEndpoint>,
265 {
266 self.connection.lend_mut(WriteEndpoint { buf, endpoint: self.endpoint_number, length, zlp: true })
267 }
268
269 pub fn set_stalled(&mut self, stalled: bool)
271 where
272 P: MessageAllowed<SetEndpointStalled>,
273 {
274 self.connection
275 .try_send_scalar(SetEndpointStalled { endpoint: self.endpoint_number, stalled })
276 .unwrap();
277 }
278}