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