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