1#![no_std]
2#![allow(unsafe_op_in_unsafe_fn)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
5
6pub(crate) mod fmt;
8
9pub use embassy_usb_driver as driver;
10
11mod builder;
12pub mod class;
13pub mod control;
14pub mod descriptor;
15mod descriptor_reader;
16pub mod msos;
17pub mod types;
18
19mod config {
20 #![allow(unused)]
21 include!(concat!(env!("OUT_DIR"), "/config.rs"));
22}
23
24use embassy_futures::select::{Either, select};
25use heapless::Vec;
26
27pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder, UsbVersion};
28use crate::config::{MAX_HANDLER_COUNT, MAX_INTERFACE_COUNT};
29use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType};
30use crate::descriptor::{descriptor_type, lang_id};
31use crate::descriptor_reader::foreach_endpoint;
32use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event};
33use crate::types::{InterfaceNumber, StringIndex};
34
35#[repr(u8)]
39#[derive(PartialEq, Eq, Copy, Clone, Debug)]
40#[cfg_attr(feature = "defmt", derive(defmt::Format))]
41pub enum UsbDeviceState {
42 Unpowered,
44
45 Disabled,
47
48 Default,
50
51 Addressed,
53
54 Configured,
56}
57
58#[derive(PartialEq, Eq, Copy, Clone, Debug)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub enum RemoteWakeupError {
62 InvalidState,
64 Unsupported,
66}
67
68impl From<driver::Unsupported> for RemoteWakeupError {
69 fn from(_: driver::Unsupported) -> Self {
70 RemoteWakeupError::Unsupported
71 }
72}
73
74pub const CONFIGURATION_NONE: u8 = 0;
76
77pub const CONFIGURATION_VALUE: u8 = 1;
79
80const STRING_INDEX_MANUFACTURER: u8 = 1;
81const STRING_INDEX_PRODUCT: u8 = 2;
82const STRING_INDEX_SERIAL_NUMBER: u8 = 3;
83const STRING_INDEX_CUSTOM_START: u8 = 4;
84
85pub trait Handler {
90 fn enabled(&mut self, _enabled: bool) {}
92
93 fn reset(&mut self) {}
95
96 fn addressed(&mut self, _addr: u8) {}
98
99 fn configured(&mut self, _configured: bool) {}
101
102 fn suspended(&mut self, _suspended: bool) {}
104
105 fn remote_wakeup_enabled(&mut self, _enabled: bool) {}
107
108 fn set_alternate_setting(&mut self, iface: InterfaceNumber, alternate_setting: u8) {
110 let _ = iface;
111 let _ = alternate_setting;
112 }
113
114 fn control_out(&mut self, req: Request, data: &[u8]) -> Option<OutResponse> {
130 let _ = (req, data);
131 None
132 }
133
134 fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
152 let _ = (req, buf);
153 None
154 }
155
156 fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&str> {
158 let _ = (index, lang_id);
159 None
160 }
161}
162
163struct Interface {
164 current_alt_setting: u8,
165 num_alt_settings: u8,
166}
167
168#[derive(PartialEq, Eq, Copy, Clone, Debug)]
170#[cfg_attr(feature = "defmt", derive(defmt::Format))]
171pub struct UsbBufferReport {
172 pub config_descriptor_used: usize,
174 pub bos_descriptor_used: usize,
176 pub msos_descriptor_used: usize,
178 pub control_buffer_size: usize,
180}
181
182pub struct UsbDevice<'d, D: Driver<'d>> {
184 control_buf: &'d mut [u8],
185 control: D::ControlPipe,
186 inner: Inner<'d, D>,
187}
188
189struct Inner<'d, D: Driver<'d>> {
190 bus: D::Bus,
191
192 config: Config<'d>,
193 device_descriptor: [u8; 18],
194 device_qualifier_descriptor: [u8; 10],
195 config_descriptor: &'d [u8],
196 bos_descriptor: &'d [u8],
197 msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
198
199 device_state: UsbDeviceState,
200 suspended: bool,
201 remote_wakeup_enabled: bool,
202 self_powered: bool,
203
204 address: u8,
206 set_address_pending: bool,
210
211 interfaces: Vec<Interface, MAX_INTERFACE_COUNT>,
212 handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
213}
214
215impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
216 pub(crate) fn build(
217 driver: D,
218 config: Config<'d>,
219 handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
220 config_descriptor: &'d [u8],
221 bos_descriptor: &'d [u8],
222 msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
223 interfaces: Vec<Interface, MAX_INTERFACE_COUNT>,
224 control_buf: &'d mut [u8],
225 ) -> UsbDevice<'d, D> {
226 let (bus, control) = driver.start(config.max_packet_size_0 as u16);
229 let device_descriptor = descriptor::device_descriptor(&config);
230 let device_qualifier_descriptor = descriptor::device_qualifier_descriptor(&config);
231
232 Self {
233 control_buf,
234 control,
235 inner: Inner {
236 bus,
237 config,
238 device_descriptor,
239 device_qualifier_descriptor,
240 config_descriptor,
241 bos_descriptor,
242 msos_descriptor,
243
244 device_state: UsbDeviceState::Unpowered,
245 suspended: false,
246 remote_wakeup_enabled: false,
247 self_powered: false,
248 address: 0,
249 set_address_pending: false,
250 interfaces,
251 handlers,
252 },
253 }
254 }
255
256 pub fn buffer_usage(&self) -> UsbBufferReport {
260 UsbBufferReport {
261 config_descriptor_used: self.inner.config_descriptor.len(),
262 bos_descriptor_used: self.inner.bos_descriptor.len(),
263 msos_descriptor_used: self.inner.msos_descriptor.len(),
264 control_buffer_size: self.control_buf.len(),
265 }
266 }
267
268 pub async fn run(&mut self) -> ! {
275 loop {
276 self.run_until_suspend().await;
277 self.wait_resume().await;
278 }
279 }
280
281 pub async fn run_until_suspend(&mut self) {
288 while !self.inner.suspended {
289 let control_fut = self.control.setup();
290 let bus_fut = self.inner.bus.poll();
291 match select(bus_fut, control_fut).await {
292 Either::First(evt) => self.inner.handle_bus_event(evt).await,
293 Either::Second(req) => self.handle_control(req).await,
294 }
295 }
296 }
297
298 pub async fn disable(&mut self) {
300 if self.inner.device_state != UsbDeviceState::Disabled {
301 self.inner.bus.disable().await;
302 self.inner.device_state = UsbDeviceState::Disabled;
303 self.inner.suspended = false;
304 self.inner.remote_wakeup_enabled = false;
305
306 for h in &mut self.inner.handlers {
307 h.enabled(false);
308 }
309 }
310 }
311
312 pub async fn wait_resume(&mut self) {
316 while self.inner.suspended {
317 let evt = self.inner.bus.poll().await;
318 self.inner.handle_bus_event(evt).await;
319 }
320 }
321
322 pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> {
331 if self.inner.suspended && self.inner.remote_wakeup_enabled {
332 self.inner.bus.remote_wakeup().await?;
333 self.inner.suspended = false;
334
335 for h in &mut self.inner.handlers {
336 h.suspended(false);
337 }
338
339 Ok(())
340 } else {
341 Err(RemoteWakeupError::InvalidState)
342 }
343 }
344
345 async fn handle_control(&mut self, req: [u8; 8]) {
346 let req = Request::parse(&req);
347
348 trace!("control request: {:?}", req);
349
350 match req.direction {
351 Direction::In => self.handle_control_in(req).await,
352 Direction::Out => self.handle_control_out(req).await,
353 }
354 }
355
356 async fn handle_control_in(&mut self, req: Request) {
357 const DEVICE_DESCRIPTOR_LEN: usize = 18;
358
359 let mut resp_length = req.length as usize;
360 let max_packet_size = self.control.max_packet_size();
361
362 if self.inner.address == 0 && max_packet_size < DEVICE_DESCRIPTOR_LEN && max_packet_size < resp_length {
367 trace!("received control req while not addressed: capping response to 1 packet.");
368 resp_length = max_packet_size;
369 }
370
371 match self.inner.handle_control_in(req, self.control_buf) {
372 InResponse::Accepted(data) => {
373 let len = data.len().min(resp_length);
374 let need_zlp = len != resp_length && (len % max_packet_size) == 0;
375
376 let chunks = data[0..len]
377 .chunks(max_packet_size)
378 .chain(need_zlp.then(|| -> &[u8] { &[] }));
379
380 for (first, last, chunk) in first_last(chunks) {
381 match self.control.data_in(chunk, first, last).await {
382 Ok(()) => {}
383 Err(e) => {
384 warn!("control accept_in failed: {:?}", e);
385 return;
386 }
387 }
388 }
389 }
390 InResponse::Rejected => self.control.reject().await,
391 }
392 }
393
394 async fn handle_control_out(&mut self, req: Request) {
395 let req_length = req.length as usize;
396 let max_packet_size = self.control.max_packet_size();
397 let mut total = 0;
398
399 if req_length > self.control_buf.len() {
400 warn!(
401 "got CONTROL OUT with length {} higher than the control_buf len {}, rejecting.",
402 req_length,
403 self.control_buf.len()
404 );
405 self.control.reject().await;
406 return;
407 }
408
409 let chunks = self.control_buf[..req_length].chunks_mut(max_packet_size);
410 for (first, last, chunk) in first_last(chunks) {
411 let size = match self.control.data_out(chunk, first, last).await {
412 Ok(x) => x,
413 Err(e) => {
414 warn!("usb: failed to read CONTROL OUT data stage: {:?}", e);
415 return;
416 }
417 };
418 total += size;
419 if size < max_packet_size || total == req_length {
420 break;
421 }
422 }
423
424 let data = &self.control_buf[0..total];
425 #[cfg(feature = "defmt")]
426 trace!(" control out data: {:02x}", data);
427 #[cfg(not(feature = "defmt"))]
428 trace!(" control out data: {:02x?}", data);
429
430 match self.inner.handle_control_out(req, data) {
431 OutResponse::Accepted => {
432 if self.inner.set_address_pending {
433 self.control.accept_set_address(self.inner.address).await;
434 self.inner.set_address_pending = false;
435 } else {
436 self.control.accept().await;
437 }
438 }
439 OutResponse::Rejected => self.control.reject().await,
440 }
441 }
442}
443
444impl<'d, D: Driver<'d>> Inner<'d, D> {
445 async fn handle_bus_event(&mut self, evt: Event) {
446 match evt {
447 Event::Reset => {
448 trace!("usb: reset");
449 self.device_state = UsbDeviceState::Default;
450 self.suspended = false;
451 self.remote_wakeup_enabled = false;
452 self.address = 0;
453
454 for h in &mut self.handlers {
455 h.reset();
456 }
457
458 for (i, iface) in self.interfaces.iter_mut().enumerate() {
459 iface.current_alt_setting = 0;
460
461 for h in &mut self.handlers {
462 h.set_alternate_setting(InterfaceNumber::new(i as _), 0);
463 }
464 }
465 }
466 Event::Resume => {
467 trace!("usb: resume");
468 self.suspended = false;
469 for h in &mut self.handlers {
470 h.suspended(false);
471 }
472 }
473 Event::Suspend => {
474 trace!("usb: suspend");
475 self.suspended = true;
476 for h in &mut self.handlers {
477 h.suspended(true);
478 }
479 }
480 Event::PowerDetected => {
481 trace!("usb: power detected");
482 self.bus.enable().await;
483 self.device_state = UsbDeviceState::Default;
484
485 for h in &mut self.handlers {
486 h.enabled(true);
487 }
488 }
489 Event::PowerRemoved => {
490 trace!("usb: power removed");
491 self.bus.disable().await;
492 self.device_state = UsbDeviceState::Unpowered;
493
494 for h in &mut self.handlers {
495 h.enabled(false);
496 }
497 }
498 }
499 }
500
501 fn handle_control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
502 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
503 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
504
505 match (req.request_type, req.recipient) {
506 (RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
507 (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
508 self.remote_wakeup_enabled = false;
509 for h in &mut self.handlers {
510 h.remote_wakeup_enabled(false);
511 }
512 OutResponse::Accepted
513 }
514 (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
515 self.remote_wakeup_enabled = true;
516 for h in &mut self.handlers {
517 h.remote_wakeup_enabled(true);
518 }
519 OutResponse::Accepted
520 }
521 (Request::SET_ADDRESS, addr @ 1..=127) => {
522 self.address = addr as u8;
523 self.set_address_pending = true;
524 self.device_state = UsbDeviceState::Addressed;
525 for h in &mut self.handlers {
526 h.addressed(self.address);
527 }
528 OutResponse::Accepted
529 }
530 (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => {
531 debug!("SET_CONFIGURATION: configured");
532 self.device_state = UsbDeviceState::Configured;
533
534 foreach_endpoint(self.config_descriptor, |ep| {
536 let iface = &self.interfaces[ep.interface.0 as usize];
537 self.bus
538 .endpoint_set_enabled(ep.ep_address, iface.current_alt_setting == ep.interface_alt);
539 })
540 .unwrap();
541
542 for h in &mut self.handlers {
544 h.configured(true);
545 }
546
547 OutResponse::Accepted
548 }
549 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => {
550 if self.device_state != UsbDeviceState::Default {
551 debug!("SET_CONFIGURATION: unconfigured");
552 self.device_state = UsbDeviceState::Addressed;
553
554 foreach_endpoint(self.config_descriptor, |ep| {
556 self.bus.endpoint_set_enabled(ep.ep_address, false);
557 })
558 .unwrap();
559
560 for h in &mut self.handlers {
562 h.configured(false);
563 }
564 }
565 OutResponse::Accepted
566 }
567 _ => OutResponse::Rejected,
568 },
569 (RequestType::Standard, Recipient::Interface) => {
570 let iface_num = InterfaceNumber::new(req.index as _);
571 let Some(iface) = self.interfaces.get_mut(iface_num.0 as usize) else {
572 return OutResponse::Rejected;
573 };
574
575 match req.request {
576 Request::SET_INTERFACE => {
577 let new_altsetting = req.value as u8;
578
579 if new_altsetting >= iface.num_alt_settings {
580 warn!("SET_INTERFACE: trying to select alt setting out of range.");
581 return OutResponse::Rejected;
582 }
583
584 iface.current_alt_setting = new_altsetting;
585
586 foreach_endpoint(self.config_descriptor, |ep| {
588 if ep.interface == iface_num {
589 self.bus
590 .endpoint_set_enabled(ep.ep_address, iface.current_alt_setting == ep.interface_alt);
591 }
592 })
593 .unwrap();
594
595 for h in &mut self.handlers {
598 h.set_alternate_setting(iface_num, new_altsetting);
599 }
600 OutResponse::Accepted
601 }
602 _ => OutResponse::Rejected,
603 }
604 }
605 (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) {
606 (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
607 let ep_addr = ((req.index as u8) & 0x8f).into();
608 self.bus.endpoint_set_stalled(ep_addr, true);
609 OutResponse::Accepted
610 }
611 (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
612 let ep_addr = ((req.index as u8) & 0x8f).into();
613 self.bus.endpoint_set_stalled(ep_addr, false);
614 OutResponse::Accepted
615 }
616 _ => OutResponse::Rejected,
617 },
618 _ => self.handle_control_out_delegated(req, data),
619 }
620 }
621
622 fn handle_control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
623 match (req.request_type, req.recipient) {
624 (RequestType::Standard, Recipient::Device) => match req.request {
625 Request::GET_STATUS => {
626 let mut status: u16 = 0x0000;
627 if self.self_powered {
628 status |= 0x0001;
629 }
630 if self.remote_wakeup_enabled {
631 status |= 0x0002;
632 }
633 buf[..2].copy_from_slice(&status.to_le_bytes());
634 InResponse::Accepted(&buf[..2])
635 }
636 Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, buf),
637 Request::GET_CONFIGURATION => {
638 let status = match self.device_state {
639 UsbDeviceState::Configured => CONFIGURATION_VALUE,
640 _ => CONFIGURATION_NONE,
641 };
642 buf[0] = status;
643 InResponse::Accepted(&buf[..1])
644 }
645 _ => InResponse::Rejected,
646 },
647 (RequestType::Standard, Recipient::Interface) => {
648 let Some(iface) = self.interfaces.get_mut(req.index as usize) else {
649 return InResponse::Rejected;
650 };
651
652 match req.request {
653 Request::GET_STATUS => {
654 let status: u16 = 0;
655 buf[..2].copy_from_slice(&status.to_le_bytes());
656 InResponse::Accepted(&buf[..2])
657 }
658 Request::GET_INTERFACE => {
659 buf[0] = iface.current_alt_setting;
660 InResponse::Accepted(&buf[..1])
661 }
662 _ => self.handle_control_in_delegated(req, buf),
663 }
664 }
665 (RequestType::Standard, Recipient::Endpoint) => match req.request {
666 Request::GET_STATUS => {
667 let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into();
668 let mut status: u16 = 0x0000;
669 if self.bus.endpoint_is_stalled(ep_addr) {
670 status |= 0x0001;
671 }
672 buf[..2].copy_from_slice(&status.to_le_bytes());
673 InResponse::Accepted(&buf[..2])
674 }
675 _ => InResponse::Rejected,
676 },
677
678 (RequestType::Vendor, Recipient::Device) => {
679 if !self.msos_descriptor.is_empty()
680 && req.request == self.msos_descriptor.vendor_code()
681 && req.index == 7
682 {
683 InResponse::Accepted(self.msos_descriptor.descriptor())
685 } else {
686 self.handle_control_in_delegated(req, buf)
687 }
688 }
689 _ => self.handle_control_in_delegated(req, buf),
690 }
691 }
692
693 fn handle_control_out_delegated(&mut self, req: Request, data: &[u8]) -> OutResponse {
694 for h in &mut self.handlers {
695 if let Some(res) = h.control_out(req, data) {
696 return res;
697 }
698 }
699 OutResponse::Rejected
700 }
701
702 fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
703 unsafe fn extend_lifetime<'y>(r: InResponse<'_>) -> InResponse<'y> {
704 core::mem::transmute(r)
705 }
706
707 for h in &mut self.handlers {
708 if let Some(res) = h.control_in(req, buf) {
709 return unsafe { extend_lifetime(res) };
714 }
715 }
716 InResponse::Rejected
717 }
718
719 fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
720 let (dtype, index) = req.descriptor_type_index();
721
722 match dtype {
723 descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor),
724 descriptor_type::DEVICE => InResponse::Accepted(&self.device_descriptor),
725 descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor),
726 descriptor_type::STRING => {
727 if index == 0 {
728 buf[0] = 4; buf[1] = descriptor_type::STRING;
730 buf[2] = lang_id::ENGLISH_US as u8;
731 buf[3] = (lang_id::ENGLISH_US >> 8) as u8;
732 InResponse::Accepted(&buf[..4])
733 } else {
734 let s = match index {
735 STRING_INDEX_MANUFACTURER => self.config.manufacturer,
736 STRING_INDEX_PRODUCT => self.config.product,
737 STRING_INDEX_SERIAL_NUMBER => self.config.serial_number,
738 _ => {
739 let mut s = None;
740 for handler in &mut self.handlers {
741 let index = StringIndex::new(index);
742 let lang_id = req.index;
743 if let Some(res) = handler.get_string(index, lang_id) {
744 s = Some(res);
745 break;
746 }
747 }
748 s
749 }
750 };
751
752 if let Some(s) = s {
753 assert!(buf.len() >= 2, "control buffer too small");
754
755 buf[1] = descriptor_type::STRING;
756 let mut pos = 2;
757 for c in s.encode_utf16() {
758 assert!(pos + 2 < buf.len(), "control buffer too small");
759
760 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
761 pos += 2;
762 }
763
764 buf[0] = pos as u8;
765 InResponse::Accepted(&buf[..pos])
766 } else {
767 InResponse::Rejected
768 }
769 }
770 }
771 descriptor_type::DEVICE_QUALIFIER => InResponse::Accepted(&self.device_qualifier_descriptor),
772 _ => InResponse::Rejected,
773 }
774 }
775}
776
777fn first_last<T: Iterator>(iter: T) -> impl Iterator<Item = (bool, bool, T::Item)> {
778 let mut iter = iter.peekable();
779 let mut first = true;
780 core::iter::from_fn(move || {
781 let val = iter.next()?;
782 let is_first = first;
783 first = false;
784 let is_last = iter.peek().is_none();
785 Some((is_first, is_last, val))
786 })
787}