firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
1use core::mem::MaybeUninit;
2use usb_device::bus::PollResult;
3use usb_device::class_prelude::{EndpointAddress, EndpointType};
4use usb_device::{UsbDirection, UsbError};
5use usb_device::endpoint::{IsochronousSynchronizationType, IsochronousUsageType};
6use crate::{syscall, SafeOption, SafeResult};
7use crate::syscall::SyscallNumber;
8
9#[repr(usize)]
10#[derive(Copy, Clone, Debug, Eq, PartialEq, strum::FromRepr)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub enum UsbSyscall {
13 UsbRet = 0,
14 SetHandler = 1,
15 ClearHandler = 2,
16 Init = 3,
17 Uninit = 4,
18 AllocEp = 5,
19 Enable = 6,
20 Reset = 7,
21 SetDeviceAddr = 8,
22 Write = 9,
23 Read = 10,
24 SetStalled = 11,
25 IsStalled = 12,
26 Poll = 13,
27}
28
29pub fn set_handler(f: extern "C" fn()) {
30 unsafe {
31 syscall!(
32 SyscallNumber::Usb,
33 in UsbSyscall::SetHandler,
34 in f,
35 );
36 }
37}
38
39pub fn clear_handler() {
40 unsafe {
41 syscall!(
42 SyscallNumber::Usb,
43 in UsbSyscall::ClearHandler,
44 )
45 }
46}
47
48#[repr(C)]
49#[derive(Copy, Clone, Debug, Eq, PartialEq)]
50#[cfg_attr(feature = "defmt", derive(defmt::Format))]
51pub enum SafePollResult {
52 None,
53 Reset,
54 Data {
55 ep_out: u16,
56 ep_in_complete: u16,
57 ep_setup: u16,
58 },
59 Suspend,
60 Resume,
61}
62
63impl From<SafePollResult> for PollResult {
64 fn from(value: SafePollResult) -> Self {
65 match value {
66 SafePollResult::None => PollResult::None,
67 SafePollResult::Reset => PollResult::Reset,
68 SafePollResult::Data { ep_out, ep_in_complete, ep_setup } => PollResult::Data { ep_out, ep_in_complete, ep_setup },
69 SafePollResult::Suspend => PollResult::Suspend,
70 SafePollResult::Resume => PollResult::Resume
71 }
72 }
73}
74
75impl From<PollResult> for SafePollResult {
76 fn from(value: PollResult) -> Self {
77 match value {
78 PollResult::None => SafePollResult::None,
79 PollResult::Reset => SafePollResult::Reset,
80 PollResult::Data { ep_out, ep_in_complete, ep_setup } => SafePollResult::Data { ep_out, ep_in_complete, ep_setup },
81 PollResult::Suspend => SafePollResult::Suspend,
82 PollResult::Resume => SafePollResult::Resume,
83 }
84 }
85}
86
87#[repr(C)]
88#[derive(Copy, Clone, Debug, Eq, PartialEq)]
89#[cfg_attr(feature = "defmt", derive(defmt::Format))]
90pub enum SafeUsbError {
91 WouldBlock,
92 ParseError,
93 BufferOverflow,
94 EndpointOverflow,
95 EndpointMemoryOverflow,
96 InvalidEndpoint,
97 Unsupported,
98 InvalidState,
99}
100
101impl From<SafeUsbError> for UsbError {
102 fn from(value: SafeUsbError) -> Self {
103 match value {
104 SafeUsbError::WouldBlock => UsbError::WouldBlock,
105 SafeUsbError::ParseError => UsbError::ParseError,
106 SafeUsbError::BufferOverflow => UsbError::BufferOverflow,
107 SafeUsbError::EndpointOverflow => UsbError::EndpointOverflow,
108 SafeUsbError::EndpointMemoryOverflow => UsbError::EndpointMemoryOverflow,
109 SafeUsbError::InvalidEndpoint => UsbError::InvalidEndpoint,
110 SafeUsbError::Unsupported => UsbError::Unsupported,
111 SafeUsbError::InvalidState => UsbError::InvalidState,
112 }
113 }
114}
115
116impl From<UsbError> for SafeUsbError {
117 fn from(value: UsbError) -> Self {
118 match value {
119 UsbError::WouldBlock => SafeUsbError::WouldBlock,
120 UsbError::ParseError => SafeUsbError::ParseError,
121 UsbError::BufferOverflow => SafeUsbError::BufferOverflow,
122 UsbError::EndpointOverflow => SafeUsbError::EndpointOverflow,
123 UsbError::EndpointMemoryOverflow => SafeUsbError::EndpointMemoryOverflow,
124 UsbError::InvalidEndpoint => SafeUsbError::InvalidEndpoint,
125 UsbError::Unsupported => SafeUsbError::Unsupported,
126 UsbError::InvalidState => SafeUsbError::InvalidState,
127 }
128 }
129}
130
131#[repr(C)]
132#[derive(Copy, Clone, Debug, Eq, PartialEq)]
133#[cfg_attr(feature = "defmt", derive(defmt::Format))]
134pub enum SafeIsochronousSynchronizationType {
135 NoSynchronization,
136 Asynchronous,
137 Adaptive,
138 Synchronous,
139}
140
141impl From<IsochronousSynchronizationType> for SafeIsochronousSynchronizationType {
142 fn from(value: IsochronousSynchronizationType) -> Self {
143 match value {
144 IsochronousSynchronizationType::NoSynchronization => SafeIsochronousSynchronizationType::NoSynchronization,
145 IsochronousSynchronizationType::Asynchronous => SafeIsochronousSynchronizationType::Asynchronous,
146 IsochronousSynchronizationType::Adaptive => SafeIsochronousSynchronizationType::Adaptive,
147 IsochronousSynchronizationType::Synchronous => SafeIsochronousSynchronizationType::Synchronous,
148 }
149 }
150}
151
152impl From<SafeIsochronousSynchronizationType> for IsochronousSynchronizationType {
153 fn from(value: SafeIsochronousSynchronizationType) -> Self {
154 match value {
155 SafeIsochronousSynchronizationType::NoSynchronization => IsochronousSynchronizationType::NoSynchronization,
156 SafeIsochronousSynchronizationType::Asynchronous => IsochronousSynchronizationType::Asynchronous,
157 SafeIsochronousSynchronizationType::Adaptive => IsochronousSynchronizationType::Adaptive,
158 SafeIsochronousSynchronizationType::Synchronous => IsochronousSynchronizationType::Synchronous,
159 }
160 }
161}
162
163#[repr(C)]
164#[derive(Copy, Clone, Debug, Eq, PartialEq)]
165#[cfg_attr(feature = "defmt", derive(defmt::Format))]
166pub enum SafeIsochronousUsageType {
167 Data,
168 Feedback,
169 ImplicitFeedbackData,
170}
171
172impl From<IsochronousUsageType> for SafeIsochronousUsageType {
173 fn from(value: IsochronousUsageType) -> Self {
174 match value {
175 IsochronousUsageType::Data => SafeIsochronousUsageType::Data,
176 IsochronousUsageType::Feedback => SafeIsochronousUsageType::Feedback,
177 IsochronousUsageType::ImplicitFeedbackData => SafeIsochronousUsageType::ImplicitFeedbackData,
178 }
179 }
180}
181
182impl From<SafeIsochronousUsageType> for IsochronousUsageType {
183 fn from(value: SafeIsochronousUsageType) -> Self {
184 match value {
185 SafeIsochronousUsageType::Data => IsochronousUsageType::Data,
186 SafeIsochronousUsageType::Feedback => IsochronousUsageType::Feedback,
187 SafeIsochronousUsageType::ImplicitFeedbackData => IsochronousUsageType::ImplicitFeedbackData,
188 }
189 }
190}
191
192#[repr(C)]
193#[derive(Copy, Clone, Debug, Eq, PartialEq)]
194#[cfg_attr(feature = "defmt", derive(defmt::Format))]
195pub enum SafeEndpointType {
196 Control,
197 Isochronous {
198 synchronization: SafeIsochronousSynchronizationType,
199 usage: SafeIsochronousUsageType,
200 },
201 Bulk,
202 Interrupt,
203}
204
205impl From<EndpointType> for SafeEndpointType {
206 fn from(value: EndpointType) -> Self {
207 match value {
208 EndpointType::Control => SafeEndpointType::Control,
209 EndpointType::Isochronous { synchronization, usage } => {
210 SafeEndpointType::Isochronous { synchronization: synchronization.into(), usage: usage.into() }
211 },
212 EndpointType::Bulk => SafeEndpointType::Bulk,
213 EndpointType::Interrupt => SafeEndpointType::Interrupt,
214 }
215 }
216}
217
218impl From<SafeEndpointType> for EndpointType {
219 fn from(value: SafeEndpointType) -> Self {
220 match value {
221 SafeEndpointType::Control => EndpointType::Control,
222 SafeEndpointType::Isochronous { synchronization, usage } => {
223 EndpointType::Isochronous { synchronization: synchronization.into(), usage: usage.into() }
224 },
225 SafeEndpointType::Bulk => EndpointType::Bulk,
226 SafeEndpointType::Interrupt => EndpointType::Interrupt,
227 }
228 }
229}
230
231#[repr(C)]
232#[derive(Copy, Clone, Debug, Eq, PartialEq)]
233#[cfg_attr(feature = "defmt", derive(defmt::Format))]
234pub struct UsbEpAllocArgs {
235 pub ep_dir: UsbDirection,
236 pub ep_addr: SafeOption<u8>,
237 pub ep_type: SafeEndpointType,
238 pub max_packet_size: u16,
239 pub interval: u8,
240}
241
242#[repr(C)]
243#[derive(Copy, Clone, Debug, Eq, PartialEq)]
244#[cfg_attr(feature = "defmt", derive(defmt::Format))]
245pub struct UsbWriteArgs {
246 pub ep_addr: u8,
247 pub len: usize,
248 pub buf: *const u8,
249 pub ptr: *mut SafeResult<usize, SafeUsbError>,
250}
251
252#[repr(C)]
253#[derive(Copy, Clone, Debug, Eq, PartialEq)]
254#[cfg_attr(feature = "defmt", derive(defmt::Format))]
255pub struct UsbReadArgs {
256 pub ep_addr: u8,
257 pub len: usize,
258 pub buf: *mut u8,
259 pub ptr: *mut SafeResult<usize, SafeUsbError>,
260}
261
262pub struct UsbBus {
263 _dummy: (),
264}
265
266impl UsbBus {
267 pub fn init() -> Self {
268 unsafe {
269 syscall!(
270 SyscallNumber::Usb,
271 in UsbSyscall::Init,
272 );
273 }
274
275 Self { _dummy: () }
276 }
277}
278
279impl Drop for UsbBus {
280 fn drop(&mut self) {
281 unsafe {
282 syscall!(
283 SyscallNumber::Usb,
284 in UsbSyscall::Uninit,
285 )
286 }
287 }
288}
289
290impl usb_device::bus::UsbBus for UsbBus {
291 fn alloc_ep(
292 &mut self,
293 ep_dir: UsbDirection,
294 ep_addr: Option<EndpointAddress>,
295 ep_type: EndpointType,
296 max_packet_size: u16,
297 interval: u8
298 ) -> usb_device::Result<EndpointAddress> {
299 let mut res: MaybeUninit<SafeResult<u8, SafeUsbError>> = MaybeUninit::uninit();
300 let res_ptr = res.as_mut_ptr();
301
302 let alloc_info = UsbEpAllocArgs {
303 ep_dir,
304 ep_addr: ep_addr.map(|v| v.into()).into(),
305 ep_type: ep_type.into(),
306 max_packet_size,
307 interval
308 };
309
310 unsafe {
311 syscall!(
312 SyscallNumber::Usb,
313 in UsbSyscall::AllocEp,
314 in &raw const alloc_info,
315 in res_ptr,
316 );
317
318 let res: Result<u8, SafeUsbError> = res.assume_init().into();
319 res.map(|v| v.into()).map_err(|e| e.into())
320 }
321 }
322
323 fn enable(&mut self) {
324 unsafe {
325 syscall!(
326 SyscallNumber::Usb,
327 in UsbSyscall::Enable,
328 );
329 }
330 }
331
332 fn reset(&self) {
333 unsafe {
334 syscall!(
335 SyscallNumber::Usb,
336 in UsbSyscall::Reset,
337 );
338 }
339 }
340
341 fn set_device_address(&self, addr: u8) {
342 unsafe {
343 syscall!(
344 SyscallNumber::Usb,
345 in UsbSyscall::SetDeviceAddr,
346 in addr,
347 );
348 }
349 }
350
351 fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> usb_device::Result<usize> {
352 let ep_addr: u8 = ep_addr.into();
353 let mut res: MaybeUninit<SafeResult<usize, SafeUsbError>> = MaybeUninit::uninit();
354 let ptr = res.as_mut_ptr();
355 let len = buf.len();
356 let buf = buf.as_ptr();
357
358 let args = UsbWriteArgs {
359 ep_addr,
360 len,
361 buf,
362 ptr,
363 };
364
365 unsafe {
366 syscall!(
367 SyscallNumber::Usb,
368 in UsbSyscall::Write,
369 in &raw const args,
370 );
371
372 let stdres: Result<usize, SafeUsbError> = res.assume_init().into();
373 stdres.map_err(|e| e.into())
374 }
375 }
376
377 fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> usb_device::Result<usize> {
378 let ep_addr: u8 = ep_addr.into();
379 let mut res: MaybeUninit<SafeResult<usize, SafeUsbError>> = MaybeUninit::uninit();
380 let ptr = res.as_mut_ptr();
381 let len = buf.len();
382 let buf = buf.as_mut_ptr();
383
384 let args = UsbReadArgs {
385 ep_addr,
386 len,
387 buf,
388 ptr,
389 };
390
391 unsafe {
392 syscall!(
393 SyscallNumber::Usb,
394 in UsbSyscall::Read,
395 in &raw const args,
396 );
397
398 let stdres: Result<usize, SafeUsbError> = res.assume_init().into();
399 stdres.map_err(|e| e.into())
400 }
401 }
402
403 fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
404 let ep_addr: u8 = ep_addr.into();
405 unsafe {
406 syscall!(
407 SyscallNumber::Usb,
408 in UsbSyscall::SetStalled,
409 in ep_addr,
410 in stalled,
411 )
412 }
413 }
414
415 fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
416 let ep_addr: u8 = ep_addr.into();
417
418 let mut stalled: usize;
419 unsafe {
420 syscall!(
421 SyscallNumber::Usb,
422 out stalled in UsbSyscall::IsStalled,
423 in ep_addr,
424 );
425 }
426
427 stalled != 0
428 }
429
430 fn suspend(&self) {
431 // not implemented in rp2040 usb-device implementation
432 }
433
434 fn resume(&self) {
435 // not implemented in rp2040 usb-device implementation
436 }
437
438 fn poll(&self) -> PollResult {
439 let mut spr: MaybeUninit<SafePollResult> = MaybeUninit::uninit();
440 let ptr = spr.as_mut_ptr();
441 unsafe {
442 syscall!(
443 SyscallNumber::Usb,
444 in UsbSyscall::Poll,
445 in ptr,
446 );
447
448 spr.assume_init().into()
449 }
450 }
451}