Skip to main content

embassy_usb/
lib.rs

1#![no_std]
2#![allow(unsafe_op_in_unsafe_fn)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
5
6// This mod MUST go first, so that the others see its macros.
7pub(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/// The global state of the USB device.
36///
37/// In general class traffic is only possible in the `Configured` state.
38#[repr(u8)]
39#[derive(PartialEq, Eq, Copy, Clone, Debug)]
40#[cfg_attr(feature = "defmt", derive(defmt::Format))]
41pub enum UsbDeviceState {
42    /// The USB device has no power.
43    Unpowered,
44
45    /// The USB device is disabled.
46    Disabled,
47
48    /// The USB device has just been enabled or reset.
49    Default,
50
51    /// The USB device has received an address from the host.
52    Addressed,
53
54    /// The USB device has been configured and is fully functional.
55    Configured,
56}
57
58/// Error returned by [`UsbDevice::remote_wakeup`].
59#[derive(PartialEq, Eq, Copy, Clone, Debug)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub enum RemoteWakeupError {
62    /// The USB device is not suspended, or remote wakeup was not enabled.
63    InvalidState,
64    /// The underlying driver doesn't support remote wakeup.
65    Unsupported,
66}
67
68impl From<driver::Unsupported> for RemoteWakeupError {
69    fn from(_: driver::Unsupported) -> Self {
70        RemoteWakeupError::Unsupported
71    }
72}
73
74/// The bConfiguration value for the not configured state.
75pub const CONFIGURATION_NONE: u8 = 0;
76
77/// The bConfiguration value for the single configuration supported by this device.
78pub 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
85/// Handler for device events and control requests.
86///
87/// All methods are optional callbacks that will be called by
88/// [`UsbDevice::run()`](crate::UsbDevice::run)
89pub trait Handler {
90    /// Called when the USB device has been enabled or disabled.
91    fn enabled(&mut self, _enabled: bool) {}
92
93    /// Called after a USB reset after the bus reset sequence is complete.
94    fn reset(&mut self) {}
95
96    /// Called when the host has set the address of the device to `addr`.
97    fn addressed(&mut self, _addr: u8) {}
98
99    /// Called when the host has enabled or disabled the configuration of the device.
100    fn configured(&mut self, _configured: bool) {}
101
102    /// Called when the bus has entered or exited the suspend state.
103    fn suspended(&mut self, _suspended: bool) {}
104
105    /// Called when remote wakeup feature is enabled or disabled.
106    fn remote_wakeup_enabled(&mut self, _enabled: bool) {}
107
108    /// Called when a "set alternate setting" control request is done on the interface.
109    fn set_alternate_setting(&mut self, iface: InterfaceNumber, alternate_setting: u8) {
110        let _ = iface;
111        let _ = alternate_setting;
112    }
113
114    /// Called when a control request is received with direction HostToDevice.
115    ///
116    /// # Arguments
117    ///
118    /// * `req` - The request from the SETUP packet.
119    /// * `data` - The data from the request.
120    ///
121    /// # Returns
122    ///
123    /// If you didn't handle this request (for example if it's for the wrong interface), return
124    /// `None`. In this case, the USB stack will continue calling the other handlers, to see
125    /// if another handles it.
126    ///
127    /// If you did, return `Some` with either `Accepted` or `Rejected`. This will make the USB stack
128    /// respond to the control request, and stop calling other handlers.
129    fn control_out(&mut self, req: Request, data: &[u8]) -> Option<OutResponse> {
130        let _ = (req, data);
131        None
132    }
133
134    /// Called when a control request is received with direction DeviceToHost.
135    ///
136    /// You should write the response somewhere (usually to `buf`, but you may use another buffer
137    /// owned by yourself, or a static buffer), then return `InResponse::Accepted(data)`.
138    ///
139    /// # Arguments
140    ///
141    /// * `req` - The request from the SETUP packet.
142    ///
143    /// # Returns
144    ///
145    /// If you didn't handle this request (for example if it's for the wrong interface), return
146    /// `None`. In this case, the USB stack will continue calling the other handlers, to see
147    /// if another handles it.
148    ///
149    /// If you did, return `Some` with either `Accepted` or `Rejected`. This will make the USB stack
150    /// respond to the control request, and stop calling other handlers.
151    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    /// Called when a GET_DESCRIPTOR STRING control request is received.
157    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/// A report of the used size of the runtime allocated buffers
169#[derive(PartialEq, Eq, Copy, Clone, Debug)]
170#[cfg_attr(feature = "defmt", derive(defmt::Format))]
171pub struct UsbBufferReport {
172    /// Number of config descriptor bytes used
173    pub config_descriptor_used: usize,
174    /// Number of bos descriptor bytes used
175    pub bos_descriptor_used: usize,
176    /// Number of msos descriptor bytes used
177    pub msos_descriptor_used: usize,
178    /// Size of the control buffer
179    pub control_buffer_size: usize,
180}
181
182/// Main struct for the USB device stack.
183pub 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    /// Our device address, or 0 if none.
205    address: u8,
206    /// SET_ADDRESS requests have special handling depending on the driver.
207    /// This flag indicates that requests must be handled by `ControlPipe::accept_set_address()`
208    /// instead of regular `accept()`.
209    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        // Start the USB bus.
227        // This prevent further allocation by consuming the driver.
228        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    /// Returns a report of the consumed buffers
257    ///
258    /// Useful for tuning buffer sizes for actual usage
259    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    /// Runs the `UsbDevice` forever.
269    ///
270    /// This future may leave the bus in an invalid state if it is dropped.
271    /// After dropping the future, [`UsbDevice::disable()`] should be called
272    /// before calling any other `UsbDevice` methods to fully reset the
273    /// peripheral.
274    pub async fn run(&mut self) -> ! {
275        loop {
276            self.run_until_suspend().await;
277            self.wait_resume().await;
278        }
279    }
280
281    /// Runs the `UsbDevice` until the bus is suspended.
282    ///
283    /// This future may leave the bus in an invalid state if it is dropped.
284    /// After dropping the future, [`UsbDevice::disable()`] should be called
285    /// before calling any other `UsbDevice` methods to fully reset the
286    /// peripheral.
287    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    /// Disables the USB peripheral.
299    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    /// Waits for a resume condition on the USB bus.
313    ///
314    /// This future is cancel-safe.
315    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    /// Initiates a device remote wakeup on the USB bus.
323    ///
324    /// If the bus is not suspended or remote wakeup is not enabled, an error
325    /// will be returned.
326    ///
327    /// This future may leave the bus in an inconsistent state if dropped.
328    /// After dropping the future, [`UsbDevice::disable()`] should be called
329    /// before calling any other `UsbDevice` methods to fully reset the peripheral.
330    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 we don't have an address yet, respond with max 1 packet.
363        // The host doesn't know our EP0 max packet size yet, and might assume
364        // a full-length packet is a short packet, thinking we're done sending data.
365        // See https://github.com/hathach/tinyusb/issues/184
366        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                    // Enable all endpoints of selected alt settings.
535                    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                    // Notify handlers.
543                    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                        // Disable all endpoints.
555                        foreach_endpoint(self.config_descriptor, |ep| {
556                            self.bus.endpoint_set_enabled(ep.ep_address, false);
557                        })
558                        .unwrap();
559
560                        // Notify handlers.
561                        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                        // Enable/disable EPs of this interface as needed.
587                        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                        // TODO check it is valid (not out of range)
596
597                        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                    // Index 7 retrieves the MS OS Descriptor Set
684                    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                // safety: the borrow checker isn't smart enough to know this pattern (returning a
710                // borrowed value from inside the loop) is sound. Workaround by unsafely extending lifetime.
711                // Also, Polonius (the WIP new borrow checker) does accept it.
712
713                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; // len
729                    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}