Skip to main content

embassy_usb_host/class/uac/
mod.rs

1//! USB Audio Class (UAC) handler module.
2//!
3//! This module provides functionality for interacting with USB Audio Class devices,
4//! including device registration, control requests, and audio streaming.
5//!
6//! # Overview
7//!
8//! The UAC handler supports:
9//! - Device enumeration and interface discovery
10//! - Control requests for audio parameters (volume, mute, sampling frequency, etc.)
11//! - Isochronous audio streaming with feedback
12//! - String descriptor retrieval
13//! - Range queries for supported parameter values
14//!
15//! See the [UAC specification](https://www.usb.org/sites/default/files/audio10.pdf) for more details.
16//!
17//! # Usage
18//!
19//! ```rust,ignore
20//! // Register a UAC device
21//! let handler = UacHandler::try_register(&bus, enum_info).await?;
22//!
23//! // Get current sampling frequency
24//! let freq = handler.get_sampling_freq(terminal_id).await?;
25//!
26//! // Start audio output stream. The callback is called repeatedly whenever the buffer is ready to be filled.
27//! let mut output = handler.output()?;
28//! output.output_stream(|buffer| {
29//!     // Fill buffer with audio data
30//! }).await?;
31//! ```
32
33#[allow(missing_docs)]
34pub mod codes;
35pub mod descriptors;
36
37use core::future::{Future, poll_fn};
38use core::pin::pin;
39use core::task::Poll;
40
41use aligned::{A4, Aligned};
42use embassy_time::{Duration, Instant, Timer};
43use embassy_usb::control::Request;
44use embassy_usb_driver::host::{HostError, PipeError, UsbHostAllocator, UsbPipe, pipe};
45use embassy_usb_driver::{Direction, EndpointInfo, EndpointType, Speed};
46use heapless::{String, Vec};
47
48use crate::control::{ControlType, Recipient, RequestType, SetupPacket};
49use crate::descriptor::DEFAULT_MAX_DESCRIPTOR_SIZE;
50use crate::handler::{EnumerationInfo, RegisterError};
51
52const MAX_RANGES: usize = 16;
53// 256 is the maximum buffer size that can be used to store a string
54const MAX_STRING_BUF_SIZE: usize = 255;
55// But because these are UTF-16 strings, we can only store 127 characters (first two bytes are part of the header)
56const MAX_STRING_LENGTH: usize = 127;
57
58/// Handler for USB Audio Class (UAC) devices, providing control and streaming functionality.
59///
60/// This struct manages the USB pipes and interface descriptors required to interact with
61/// a UAC device, including control, output, and feedback pipes.
62pub struct UacHandler<'d, A: UsbHostAllocator<'d>> {
63    /// Collection of audio interface descriptors parsed from the device configuration.
64    pub interface_collection: descriptors::AudioInterfaceCollection,
65    /// Control pipe for sending standard and class-specific requests.
66    pub control_channel: A::Pipe<pipe::Control, pipe::InOut>,
67    /// Output pipe for isochronous audio streaming (if available).
68    pub output_channel: Option<A::Pipe<pipe::Isochronous, pipe::Out>>,
69    /// Feedback pipe for isochronous feedback endpoint (if available).
70    pub feedback_channel: Option<A::Pipe<pipe::Isochronous, pipe::In>>,
71    input_terminal_id: u8,
72    output_interface_idx: usize,
73    speed: Speed,
74    _phantom: core::marker::PhantomData<&'d ()>,
75}
76
77/// Errors that can occur during UAC request handling.
78#[derive(Debug)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub enum RequestError {
81    /// The request failed due to a pipe error.
82    RequestFailed(PipeError),
83    /// The device was disconnected during the operation.
84    DeviceDisconnected,
85    /// The device returned an invalid or unexpected response.
86    InvalidResponse,
87    /// No supported interface was found on the device.
88    NoSupportedInterface,
89}
90
91impl<'d, A: UsbHostAllocator<'d>> UacHandler<'d, A> {
92    /// Attempts to register a UAC device and allocate necessary pipes.
93    ///
94    /// This method parses the device's configuration, finds a suitable streaming interface,
95    /// and allocates output and feedback pipes as needed.
96    ///
97    /// Returns a new [`UacHandler`] on success, or a [`RegisterError`] if registration fails.
98    pub async fn try_register(alloc: &A, enum_info: EnumerationInfo) -> Result<Self, RegisterError> {
99        // Steps taken:
100        // 1. Find the first streaming interface with an output endpoint
101        // 2. Connect it to its terminal to find the sampling frequency
102        // 3. Check its format type
103        // 4. Select the right alternate setting for the interface with a SET_INTERFACE request
104        // 5. Allocate up the output pipe and the corresponding feedback pipe, store on Self
105
106        let mut control_channel = alloc.alloc_pipe::<pipe::Control, pipe::InOut>(
107            enum_info.device_address,
108            &EndpointInfo {
109                addr: 0.into(),
110                ep_type: EndpointType::Control,
111                max_packet_size: (enum_info.device_desc.max_packet_size0 as u16)
112                    .min(enum_info.speed().max_packet_size()),
113                interval_ms: 0,
114            },
115            enum_info.split(),
116        )?;
117
118        let mut cfg_desc_buf = [0u8; DEFAULT_MAX_DESCRIPTOR_SIZE];
119        let configuration = enum_info
120            .active_config_or_set_default(&mut control_channel, &mut cfg_desc_buf)
121            .await?;
122
123        let interface_collection = match descriptors::AudioInterfaceCollection::try_from_configuration(&configuration) {
124            Ok(collection) => collection,
125            Err(e) => {
126                warn!("Failed to parse Audio Interface Collection: {:#?}", e);
127                return Err(RegisterError::NoSupportedInterface);
128            }
129        };
130        debug!("[UAC] Audio Interface Collection: {:#?}", interface_collection);
131
132        // Find the first streaming interface with an output endpoint
133        let output_interface_idx = interface_collection
134            .audio_streaming_interfaces
135            .iter()
136            .position(|i| {
137                i.endpoint_descriptor
138                    .map(|e| e.ep_dir() == Direction::Out)
139                    .unwrap_or(false)
140            })
141            .ok_or(RegisterError::NoSupportedInterface)?;
142        let output_interface = &interface_collection.audio_streaming_interfaces[output_interface_idx];
143
144        // Check to see that the terminal link id is valid
145        let input_terminal = interface_collection
146            .control_interface
147            .terminal_descriptors
148            .get(&output_interface.class_descriptor.terminal_link_id)
149            .ok_or(RegisterError::NoSupportedInterface)?;
150
151        debug!("[UAC] Input Terminal: {:#?}", input_terminal);
152
153        // Check to see that the format is PCM
154        if output_interface.class_descriptor.format != codes::format_type::Format::Type1(codes::format_type::Type1::PCM)
155        {
156            error!(
157                "[UAC] Only PCM format is supported, got {:?}",
158                output_interface.class_descriptor.format
159            );
160            return Err(RegisterError::NoSupportedInterface);
161        }
162
163        // Find the interface with the most endpoints
164        let streaming_interface = output_interface
165            .interface_descriptors
166            .iter()
167            .max_by_key(|i| i.num_endpoints)
168            .ok_or(RegisterError::NoSupportedInterface)?;
169
170        // Allocate the pipes
171        let mut output_channel = None;
172        let mut feedback_channel = None;
173        let input_terminal_id = output_interface.class_descriptor.terminal_link_id;
174        // Select the correct alternate setting
175        let packet = SetupPacket {
176            request_type: RequestType {
177                direction: Direction::Out,
178                control_type: ControlType::Standard,
179                recipient: Recipient::Interface,
180            },
181            request: Request::SET_INTERFACE,
182            value: streaming_interface.alternate_setting as u16,
183            index: streaming_interface.interface_number as u16,
184            length: 0,
185        };
186        control_channel
187            .control_out(&packet.to_bytes(), &mut [])
188            .await
189            .map_err(|e| RegisterError::HostError(HostError::PipeError(e)))?;
190        debug!(
191            "[UAC] Set output interface to alternate setting: {}",
192            streaming_interface.alternate_setting
193        );
194
195        if streaming_interface.num_endpoints > 0 {
196            output_channel = Some(alloc.alloc_pipe::<pipe::Isochronous, pipe::Out>(
197                enum_info.device_address,
198                &output_interface.endpoint_descriptor.unwrap().into(),
199                enum_info.split(),
200            )?);
201        }
202        if streaming_interface.num_endpoints > 1 {
203            if let Some(feedback_endpoint) = output_interface.feedback_endpoint_descriptor {
204                feedback_channel = Some(alloc.alloc_pipe::<pipe::Isochronous, pipe::In>(
205                    enum_info.device_address,
206                    &feedback_endpoint.into(),
207                    enum_info.split(),
208                )?);
209            }
210        }
211
212        Ok(Self {
213            interface_collection,
214            control_channel,
215            output_channel,
216            feedback_channel,
217            input_terminal_id,
218            output_interface_idx,
219            speed: enum_info.speed(),
220            _phantom: core::marker::PhantomData,
221        })
222    }
223
224    /// Returns a [`UacOut`] object for audio output streaming.
225    ///
226    /// Returns an error if the output or feedback pipe is not allocated or if the interface is unsupported.
227    pub async fn output(&mut self) -> Result<UacOut<'d, A>, RequestError> {
228        if self.output_channel.is_none() {
229            error!("[UAC] Output pipe not allocated");
230            return Err(RequestError::DeviceDisconnected);
231        }
232
233        let output_interface = self.output_interface();
234        let num_channels = output_interface.class_descriptor.num_channels;
235        let lock_delay = if let Some(desc) = &output_interface.audio_endpoint_descriptor {
236            if desc.lock_delay_units == 1 {
237                LockDelay::Milliseconds(desc.lock_delay)
238            } else if desc.lock_delay_units == 2 {
239                LockDelay::Samples(desc.lock_delay)
240            } else {
241                LockDelay::Samples(0)
242            }
243        } else {
244            LockDelay::Samples(0)
245        };
246        let bytes_per_sample = match output_interface.format_type_descriptor {
247            Some(descriptors::FormatTypeDescriptor::I(descriptors::FormatTypeI { subslot_size, .. })) => {
248                subslot_size as usize
249            }
250            _ => return Err(RequestError::NoSupportedInterface),
251        };
252        let max_bytes_per_packet = output_interface.endpoint_descriptor.unwrap().max_packet_size as usize;
253        // Get the sampling frequency
254        let mut num_retries = 3;
255        let sampling_freq = loop {
256            let sampling_freq = self.get_sampling_freq(self.input_terminal().clock_source_id()).await;
257            if let Err(e) = sampling_freq {
258                num_retries -= 1;
259                if num_retries == 0 {
260                    error!("[UAC] Failed to get sampling frequency after 3 retries: {:#?}", e);
261                    return Err(e);
262                }
263                Timer::after(Duration::from_millis(10)).await;
264                continue;
265            }
266            break sampling_freq.unwrap();
267        };
268        let samples_per_microframe = sampling_freq as f32
269            / match self.speed {
270                Speed::High => 8000.0,
271                _ => 1000.0,
272            };
273
274        Ok(UacOut::<'d, A> {
275            output_channel: self.output_channel.take().unwrap(),
276            feedback_channel: self.feedback_channel.take(),
277            speed: self.speed,
278            samples_per_microframe,
279            microframes_per_microsecond: 1.0 / (if self.speed == Speed::High { 125.0 } else { 1000.0 }),
280            send_start: Instant::from_ticks(0),
281            num_frames: 0,
282            last_feedback_time: Instant::from_ticks(0),
283            lock_delay,
284            num_channels,
285            bytes_per_sample,
286            max_bytes_per_packet,
287            _phantom: core::marker::PhantomData,
288        })
289    }
290
291    /// Returns a reference to the input terminal descriptor associated with this handler.
292    pub fn input_terminal(&self) -> &descriptors::TerminalDescriptor {
293        &self.interface_collection.control_interface.terminal_descriptors[&self.input_terminal_id]
294    }
295
296    /// Returns a reference to the output audio streaming interface descriptor.
297    pub fn output_interface(&self) -> &descriptors::AudioStreamingInterface {
298        &self.interface_collection.audio_streaming_interfaces[self.output_interface_idx]
299    }
300
301    /// Retrieves the current sampling frequency from the specified terminal entity.
302    ///
303    /// Returns the sampling frequency in Hz, or an error if the request fails.
304    pub async fn get_sampling_freq(&mut self, terminal_id: u8) -> Result<u32, RequestError> {
305        self.get_curr_entity3(
306            codes::control_selector::clock_source::SAMPLING_FREQ_CONTROL,
307            0,
308            terminal_id,
309            0,
310        )
311        .await
312    }
313
314    //-------------------------------------------------------
315    // MARK: Getters
316    // For the control interface
317
318    /// Retrieves the supported language ID from the device.
319    ///
320    /// Returns the language ID as a 16-bit value, or an error if the request fails.
321    pub async fn get_supported_language(&mut self) -> Result<u16, RequestError> {
322        let packet = SetupPacket {
323            request_type: RequestType {
324                direction: Direction::In,
325                control_type: ControlType::Standard,
326                recipient: Recipient::Device,
327            },
328            request: Request::GET_DESCRIPTOR,
329            value: 0x0300, // String descriptor at index 0x00
330            index: 0x00,
331            length: 4,
332        };
333
334        let mut buf = Aligned::<A4, _>([0; 4]);
335
336        self.control_channel
337            .control_in(&packet.to_bytes(), buf.as_mut_slice())
338            .await
339            .map_err(|e| RequestError::RequestFailed(e))?;
340
341        Ok(u16::from_le_bytes([buf[2], buf[3]]))
342    }
343
344    /// Retrieves a string descriptor from the device.
345    ///
346    /// # Arguments
347    /// * `index` - The string descriptor index
348    /// * `lang_id` - The language ID for the string
349    ///
350    /// Returns the string as a UTF-8 encoded string, or an error if the request fails.
351    pub async fn get_string(
352        &mut self,
353        index: crate::descriptor::StringIndex,
354        lang_id: u16,
355    ) -> Result<String<MAX_STRING_LENGTH>, RequestError> {
356        // First, get just the length
357        let packet = SetupPacket {
358            request_type: RequestType {
359                direction: Direction::In,
360                control_type: ControlType::Standard,
361                recipient: Recipient::Device,
362            },
363            request: Request::GET_DESCRIPTOR,
364            value: (0x03 << 8) | index as u16,
365            index: lang_id,
366            length: 2, // Just get the length byte and type byte
367        };
368
369        let mut length_buf = Aligned::<A4, _>([0; 2]);
370        self.control_channel
371            .control_in(&packet.to_bytes(), length_buf.as_mut_slice())
372            .await
373            .map_err(|e| RequestError::RequestFailed(e))?;
374
375        if length_buf[1] != 0x03 {
376            return Err(RequestError::InvalidResponse);
377        }
378
379        let total_length = length_buf[0] as u16;
380        if total_length == 0 || total_length > MAX_STRING_BUF_SIZE as u16 {
381            return Err(RequestError::InvalidResponse);
382        }
383
384        // Now get the full string with the correct length
385        let packet = SetupPacket {
386            request_type: RequestType {
387                direction: Direction::In,
388                control_type: ControlType::Standard,
389                recipient: Recipient::Device,
390            },
391            request: Request::GET_DESCRIPTOR,
392            value: (0x03 << 8) | index as u16,
393            index: lang_id,
394            length: total_length,
395        };
396
397        let mut buf = Aligned::<A4, _>([0; MAX_STRING_BUF_SIZE]);
398        self.control_channel
399            .control_in(&packet.to_bytes(), &mut buf.as_mut_slice()[..total_length as usize])
400            .await
401            .map_err(|e| RequestError::RequestFailed(e))?;
402
403        // Rest of the string parsing code...
404        let mut buf = &buf.as_mut_slice()[2..total_length as usize];
405        let mut str = String::new();
406        while buf.len() >= 2 {
407            let b = u16::from_le_bytes([buf[0], buf[1]]);
408            if b == 0 {
409                break;
410            }
411            if let Some(c) = char::from_u32(b as u32) {
412                str.push(c).unwrap(); // We know we won't exceed the buffer size
413            } else {
414                return Err(RequestError::InvalidResponse);
415            }
416            buf = &buf[2..];
417        }
418
419        Ok(str)
420    }
421
422    /// Retrieves a 1-byte current value from a UAC entity.
423    ///
424    /// # Arguments
425    /// * `control_selector` - The control selector (e.g., volume, mute)
426    /// * `channel` - The channel number (0 for master control)
427    /// * `entity` - The entity ID
428    /// * `interface` - The interface number
429    ///
430    /// Returns the current value as a u8, or an error if the request fails.
431    pub async fn get_curr_entity1(
432        &mut self,
433        control_selector: u16,
434        channel: u8,
435        entity: u8,
436        interface: u8,
437    ) -> Result<u8, RequestError> {
438        let packet = SetupPacket {
439            request_type: RequestType {
440                direction: Direction::In,
441                control_type: ControlType::Class,
442                recipient: Recipient::Interface,
443            },
444            request: codes::request_code::CUR,
445            value: (channel as u16) << 8 | control_selector as u16,
446            index: (entity as u16) << 8 | interface as u16,
447            length: 1,
448        };
449
450        let mut buf = Aligned::<A4, _>([0; 1]);
451
452        self.control_channel
453            .control_in(&packet.to_bytes(), buf.as_mut_slice())
454            .await
455            .map_err(|e| RequestError::RequestFailed(e))?;
456
457        Ok(buf[0])
458    }
459
460    /// Retrieves a 2-byte current value from a UAC entity.
461    ///
462    /// # Arguments
463    /// * `control_selector` - The control selector (e.g., volume, mute)
464    /// * `channel` - The channel number (0 for master control)
465    /// * `entity` - The entity ID
466    /// * `interface` - The interface number
467    ///
468    /// Returns the current value as a u16, or an error if the request fails.
469    pub async fn get_curr_entity2(
470        &mut self,
471        control_selector: u16,
472        channel: u8,
473        entity: u8,
474        interface: u8,
475    ) -> Result<u16, RequestError> {
476        let packet = SetupPacket {
477            request_type: RequestType {
478                direction: Direction::In,
479                control_type: ControlType::Class,
480                recipient: Recipient::Interface,
481            },
482            request: codes::request_code::CUR,
483            value: (channel as u16) << 8 | control_selector,
484            index: (entity as u16) << 8 | interface as u16,
485            length: 2,
486        };
487
488        let mut buf = Aligned::<A4, _>([0; 2]);
489
490        self.control_channel
491            .control_in(&packet.to_bytes(), buf.as_mut_slice())
492            .await
493            .map_err(|e| RequestError::RequestFailed(e))?;
494
495        Ok(u16::from_le_bytes([buf[0], buf[1]]))
496    }
497
498    /// Retrieves a 4-byte current value from a UAC entity.
499    ///
500    /// # Arguments
501    /// * `control_selector` - The control selector (e.g., sampling frequency)
502    /// * `channel` - The channel number (0 for master control)
503    /// * `entity` - The entity ID
504    /// * `interface` - The interface number
505    ///
506    /// Returns the current value as a u32, or an error if the request fails.
507    pub async fn get_curr_entity3(
508        &mut self,
509        control_selector: u16,
510        channel: u8,
511        entity: u8,
512        interface: u8,
513    ) -> Result<u32, RequestError> {
514        let packet = SetupPacket {
515            request_type: RequestType {
516                direction: Direction::In,
517                control_type: ControlType::Class,
518                recipient: Recipient::Interface,
519            },
520            request: codes::request_code::CUR,
521            value: (channel as u16) << 8 | control_selector,
522            index: (entity as u16) << 8 | interface as u16,
523            length: 4,
524        };
525
526        let mut buf = Aligned::<A4, _>([0; 4]);
527
528        self.control_channel
529            .control_in(&packet.to_bytes(), buf.as_mut_slice())
530            .await
531            .map_err(|e| RequestError::RequestFailed(e))?;
532
533        Ok(u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]))
534    }
535
536    /// Retrieves the range of supported 1-byte values from a UAC entity.
537    ///
538    /// # Arguments
539    /// * `control_selector` - The control selector (e.g., volume, mute)
540    /// * `channel` - The channel number (0 for master control)
541    /// * `entity` - The entity ID
542    /// * `interface` - The interface number
543    ///
544    /// Returns a [`Layout1ParameterBlock`] containing the supported ranges, or an error if the request fails.
545    pub async fn get_range_entity1(
546        &mut self,
547        control_selector: u16,
548        channel: u8,
549        entity: u8,
550        interface: u8,
551    ) -> Result<Layout1ParameterBlock, RequestError> {
552        let packet = SetupPacket {
553            request_type: RequestType {
554                direction: Direction::In,
555                control_type: ControlType::Class,
556                recipient: Recipient::Interface,
557            },
558            request: codes::request_code::RANGE,
559            value: (channel as u16) << 8 | control_selector,
560            index: (entity as u16) << 8 | interface as u16,
561            length: size_of::<Layout1ParameterBlock>() as u16,
562        };
563
564        let mut buf = Aligned::<A4, _>([0; size_of::<Layout1ParameterBlock>()]);
565
566        self.control_channel
567            .control_in(&packet.to_bytes(), buf.as_mut_slice())
568            .await
569            .map_err(|e| RequestError::RequestFailed(e))?;
570
571        let layout = Layout1ParameterBlock::try_from_bytes(buf.as_slice()).ok_or(RequestError::InvalidResponse)?;
572
573        Ok(layout)
574    }
575
576    /// Retrieves the range of supported 2-byte values from a UAC entity.
577    ///
578    /// # Arguments
579    /// * `control_selector` - The control selector (e.g., volume, mute)
580    /// * `channel` - The channel number (0 for master control)
581    /// * `entity` - The entity ID
582    /// * `interface` - The interface number
583    ///
584    /// Returns a [`Layout2ParameterBlock`] containing the supported ranges, or an error if the request fails.
585    pub async fn get_range_entity2(
586        &mut self,
587        control_selector: u16,
588        channel: u8,
589        entity: u8,
590        interface: u8,
591    ) -> Result<Layout2ParameterBlock, RequestError> {
592        let packet = SetupPacket {
593            request_type: RequestType {
594                direction: Direction::In,
595                control_type: ControlType::Class,
596                recipient: Recipient::Interface,
597            },
598            request: codes::request_code::RANGE,
599            value: (channel as u16) << 8 | control_selector,
600            index: (entity as u16) << 8 | interface as u16,
601            length: size_of::<Layout2ParameterBlock>() as u16,
602        };
603
604        let mut buf = Aligned::<A4, _>([0; size_of::<Layout2ParameterBlock>()]);
605
606        self.control_channel
607            .control_in(&packet.to_bytes(), buf.as_mut_slice())
608            .await
609            .map_err(|e| RequestError::RequestFailed(e))?;
610
611        let layout = Layout2ParameterBlock::try_from_bytes(buf.as_slice()).ok_or(RequestError::InvalidResponse)?;
612
613        Ok(layout)
614    }
615
616    /// Retrieves the range of supported 4-byte values from a UAC entity.
617    ///
618    /// # Arguments
619    /// * `control_selector` - The control selector (e.g., sampling frequency)
620    /// * `channel` - The channel number (0 for master control)
621    /// * `entity` - The entity ID
622    /// * `interface` - The interface number
623    ///
624    /// Returns a [`Layout3ParameterBlock`] containing the supported ranges, or an error if the request fails.
625    pub async fn get_range_entity3(
626        &mut self,
627        control_selector: u16,
628        channel: u8,
629        entity: u8,
630        interface: u8,
631    ) -> Result<Layout3ParameterBlock, RequestError> {
632        let packet = SetupPacket {
633            request_type: RequestType {
634                direction: Direction::In,
635                control_type: ControlType::Class,
636                recipient: Recipient::Interface,
637            },
638            request: codes::request_code::RANGE,
639            value: (channel as u16) << 8 | control_selector,
640            index: (entity as u16) << 8 | interface as u16,
641            length: size_of::<Layout3ParameterBlock>() as u16,
642        };
643
644        let mut buf = Aligned::<A4, _>([0; size_of::<Layout3ParameterBlock>()]);
645
646        self.control_channel
647            .control_in(&packet.to_bytes(), buf.as_mut_slice())
648            .await
649            .map_err(|e| RequestError::RequestFailed(e))?;
650
651        let layout = Layout3ParameterBlock::try_from_bytes(buf.as_slice()).ok_or(RequestError::InvalidResponse)?;
652
653        Ok(layout)
654    }
655}
656
657//-------------------------------------------------------
658// MARK: Output stream
659
660/// Represents an output audio stream to a USB Audio Class (UAC) device.
661///
662/// This struct manages the output and feedback pipes for isochronous audio streaming,
663/// as well as timing and format information required for correct streaming.
664pub struct UacOut<'d, A: UsbHostAllocator<'d>> {
665    /// Output pipe for isochronous audio streaming.
666    pub output_channel: A::Pipe<pipe::Isochronous, pipe::Out>,
667    /// Feedback pipe for isochronous feedback endpoint.
668    pub feedback_channel: Option<A::Pipe<pipe::Isochronous, pipe::In>>,
669    speed: Speed,
670    samples_per_microframe: f32,
671    microframes_per_microsecond: f32,
672    send_start: Instant,
673    num_frames: u64,
674    last_feedback_time: Instant,
675    lock_delay: LockDelay,
676    num_channels: u8,
677    bytes_per_sample: usize,
678    max_bytes_per_packet: usize,
679    _phantom: core::marker::PhantomData<&'d ()>,
680}
681
682enum LockDelay {
683    Milliseconds(u16),
684    Samples(u16),
685}
686
687impl<'d, A: UsbHostAllocator<'d>> UacOut<'d, A> {
688    /// Starts the output audio stream, invoking the provided callback to fill each packet.
689    ///
690    /// The callback is called repeatedly with a mutable buffer for each packet to be sent.
691    /// Returns an error if the stream cannot be started or if a USB error occurs.
692    pub async fn output_stream(
693        &mut self,
694        is_connected: impl Fn() -> bool,
695        callback: impl FnMut(&mut [u8]),
696    ) -> Result<(), RequestError> {
697        let mut output_stream_future = pin!(self.output_stream_inner(callback));
698
699        poll_fn(|cx| {
700            // Check USB connection status first
701            if !is_connected() {
702                return Poll::Ready(Err(RequestError::DeviceDisconnected));
703            }
704
705            match output_stream_future.as_mut().poll(cx) {
706                Poll::Ready(result) => Poll::Ready(result),
707                Poll::Pending => {
708                    cx.waker().wake_by_ref();
709                    Poll::Pending
710                }
711            }
712        })
713        .await
714    }
715
716    async fn output_stream_inner(&mut self, mut callback: impl FnMut(&mut [u8])) -> Result<(), RequestError> {
717        // First, update the sampling frequency
718        self.update_sampling_freq().await?;
719
720        let mut output_buffer = Aligned::<A4, _>([0; 1024]);
721        let lock_delay = self.lock_delay_samples();
722
723        // First, send the lock request
724        let data = &output_buffer.as_mut_slice()
725            [..(lock_delay as usize * self.bytes_per_sample).min(self.max_bytes_per_packet)]; // Should already be zeroed out
726        self.output_channel
727            .request_out(data, true)
728            .await
729            .map_err(|e| RequestError::RequestFailed(e))?;
730
731        debug!(
732            "[UAC] Lock request sent, starting stream with sampling frequency: {} samples/microframe",
733            self.samples_per_microframe
734        );
735
736        // Readjust the max bytes per packet to be a multiple of the frame size
737        let bytes_per_frame = self.bytes_per_sample * self.num_channels as usize;
738        let max_samples_per_packet = self.max_bytes_per_packet / bytes_per_frame;
739        trace!(
740            "[UAC] Max bytes per packet: {}; max samples per packet: {}",
741            self.max_bytes_per_packet, max_samples_per_packet
742        );
743        let mut sample_accumulator = 0.0;
744        loop {
745            // Does the sampling frequency need to be updated?
746            if self.feedback_channel.is_some() && self.last_feedback_time.elapsed() > Duration::from_millis(1) {
747                self.update_sampling_freq().await?;
748            }
749            let mut microframes_elapsed = self.microframes_elapsed_since_last_frame();
750
751            // Do we need to wait until the next frame?
752            if microframes_elapsed < 1.0 {
753                Timer::after(Duration::from_micros(
754                    ((1.0 - microframes_elapsed) / self.microframes_per_microsecond) as u64,
755                ))
756                .await;
757                microframes_elapsed = self.microframes_elapsed_since_last_frame();
758            }
759            let num_microframes_elapsed = microframes_elapsed as u64;
760
761            // Figure out how many samples to send
762            sample_accumulator += self.samples_per_microframe * num_microframes_elapsed as f32;
763            let samples_to_send = sample_accumulator as usize;
764            sample_accumulator -= samples_to_send as f32;
765            let mut bytes_to_send = samples_to_send * bytes_per_frame;
766            // trace!("[UAC] Bytes to send: {}", bytes_to_send);
767            // Chunk the data if it's too large
768            while bytes_to_send > 0 {
769                let num_bytes = self.max_bytes_per_packet.min(bytes_to_send);
770                // Fill the buffer with data
771                let data = &mut output_buffer.as_mut_slice()[..num_bytes];
772                data.fill(0);
773
774                callback(data);
775                bytes_to_send -= num_bytes;
776
777                // Send the data
778                let _len = self
779                    .output_channel
780                    .request_out(data, true)
781                    .await
782                    .map_err(|e| RequestError::RequestFailed(e))?;
783            }
784
785            self.num_frames += num_microframes_elapsed;
786        }
787    }
788
789    /// Updates the current sampling frequency by reading from the feedback endpoint.
790    ///
791    /// Returns an error if the feedback cannot be read or parsed.
792    pub async fn update_sampling_freq(&mut self) -> Result<(), RequestError> {
793        if self.feedback_channel.is_none() {
794            return Ok(());
795        }
796
797        let mut feedback_buffer = Aligned::<A4, _>([0; 4]);
798        let _ = self
799            .feedback_channel
800            .as_mut()
801            .unwrap()
802            .request_in(feedback_buffer.as_mut_slice())
803            .await
804            .map_err(|e| RequestError::RequestFailed(e))?;
805        if let Some(samples_per_microframe) = parse_feedback(self.speed, &feedback_buffer.as_slice()) {
806            self.samples_per_microframe = samples_per_microframe;
807            trace!("[UAC] Samples per microframe: {}", self.samples_per_microframe);
808        }
809        self.last_feedback_time = Instant::now();
810        Ok(())
811    }
812
813    fn microframes_elapsed_since_last_frame(&self) -> f32 {
814        if self.send_start == Instant::from_ticks(0) {
815            // We're at the start of the stream, so we want to send 1 microframe
816            1.0
817        } else {
818            (self.send_start.elapsed().as_micros() - (self.num_frames * self.microseconds_per_microframe())) as f32
819                * self.microframes_per_microsecond
820        }
821    }
822
823    fn microseconds_per_microframe(&self) -> u64 {
824        if self.speed == Speed::High { 125 } else { 1000 }
825    }
826
827    fn lock_delay_samples(&self) -> u16 {
828        match self.lock_delay {
829            LockDelay::Milliseconds(ms) => (ms as f32 * self.samples_per_frame()) as u16,
830            LockDelay::Samples(samples) => samples,
831        }
832    }
833
834    fn microframes_per_frame(&self) -> u16 {
835        if self.speed == Speed::High { 8 } else { 1 }
836    }
837
838    fn samples_per_frame(&self) -> f32 {
839        self.samples_per_microframe * self.microframes_per_frame() as f32
840    }
841}
842
843/// Parse USB feedback endpoint response into a floating point number.
844///
845/// Returns the number of samples per USB frame (full-speed) or microframe (high-speed),
846/// or `None` if the data is invalid or the speed is unsupported.
847pub fn parse_feedback(speed: Speed, data: &[u8]) -> Option<f32> {
848    match speed {
849        Speed::Low => None, // Low-speed doesn't support isochronous transfers.
850
851        Speed::High => {
852            if data.len() < 4 {
853                return None;
854            }
855
856            let fractional_part = u16::from_le_bytes([data[0], data[1]]);
857            let integer_part = u16::from_le_bytes([data[2], data[3]]);
858            // Convert fractional part to float (divide by 2^16 since it's a 16-bit fraction)
859            Some(integer_part as f32 + (fractional_part as f32 / 65536.0))
860        }
861
862        Speed::Full => {
863            if data.len() < 3 {
864                return None;
865            }
866
867            // USB 2.0 spec says 10.14 fixed point, left-justified in 24 bits
868            // So we take the 3 bytes and shift left by 2 bits to convert to 10.16-style format
869            let raw = ((data[2] as u32) << 16) | ((data[1] as u32) << 8) | data[0] as u32;
870            let shifted = raw << 2;
871
872            let fractional_part = (shifted & 0xFFFF) as u16;
873            let integer_part = (shifted >> 16) as u16;
874            // Convert fractional part to float (divide by 2^16 since it's a 16-bit fraction)
875            Some(integer_part as f32 + (fractional_part as f32 / 65536.0))
876        }
877    }
878}
879
880//-------------------------------------------------------
881// MARK: Response types
882// For the control interface
883
884/// Parameter block for range queries with 1-byte values.
885#[derive(Debug)]
886pub struct Layout1ParameterBlock {
887    /// List of supported value ranges.
888    pub ranges: Vec<Range1, MAX_RANGES>,
889}
890
891impl Layout1ParameterBlock {
892    /// Attempts to parse a [`Layout1ParameterBlock`] from a byte slice.
893    /// Returns [`Some`] if parsing is successful, or [`None`] if the data is invalid.
894    pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
895        if bytes.len() < 5 {
896            return None;
897        }
898        let num_ranges = u16::from_le_bytes([bytes[0], bytes[1]]);
899        if num_ranges > MAX_RANGES as u16 {
900            warn!(
901                "Number of ranges in Get Range response is greater than the maximum allowed: {}",
902                num_ranges
903            );
904            return None;
905        }
906        let mut ranges = Vec::new();
907        let mut bytes = &bytes[2..];
908        for _ in 0..num_ranges {
909            let range = Range1 {
910                min: bytes[0],
911                max: bytes[1],
912                step: bytes[2],
913            };
914            ranges.push(range).unwrap();
915            bytes = &bytes[3..];
916        }
917        Some(Self { ranges })
918    }
919}
920
921/// Parameter block for range queries with 2-byte values.
922#[derive(Debug)]
923pub struct Layout2ParameterBlock {
924    /// List of supported value ranges.
925    pub ranges: Vec<Range2, MAX_RANGES>,
926}
927
928impl Layout2ParameterBlock {
929    /// Attempts to parse a [`Layout2ParameterBlock`] from a byte slice.
930    /// Returns [`Some`] if parsing is successful, or [`None`] if the data is invalid.
931    pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
932        if bytes.len() < 8 {
933            return None;
934        }
935        let num_ranges = u16::from_le_bytes([bytes[0], bytes[1]]);
936        if num_ranges > MAX_RANGES as u16 {
937            warn!(
938                "Number of ranges in Get Range response is greater than the maximum allowed: {}",
939                num_ranges
940            );
941            return None;
942        }
943        let mut ranges = Vec::new();
944        let mut bytes = &bytes[2..];
945        for _ in 0..num_ranges {
946            let range = Range2 {
947                min: u16::from_le_bytes([bytes[0], bytes[1]]),
948                max: u16::from_le_bytes([bytes[2], bytes[3]]),
949                step: u16::from_le_bytes([bytes[4], bytes[5]]),
950            };
951            ranges.push(range).unwrap();
952            bytes = &bytes[6..];
953        }
954        Some(Self { ranges })
955    }
956}
957
958/// Parameter block for range queries with 4-byte values.
959#[derive(Debug)]
960pub struct Layout3ParameterBlock {
961    /// List of supported value ranges.
962    pub ranges: Vec<Range4, MAX_RANGES>,
963}
964
965impl Layout3ParameterBlock {
966    /// Attempts to parse a [`Layout3ParameterBlock`] from a byte slice.
967    /// Returns [`Some`] if parsing is successful, or [`None`] if the data is invalid.
968    pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
969        if bytes.len() < 14 {
970            return None;
971        }
972        let mut ranges = Vec::new();
973        let num_ranges = u16::from_le_bytes([bytes[0], bytes[1]]);
974        if num_ranges > MAX_RANGES as u16 {
975            warn!(
976                "Number of ranges in Get Range response is greater than the maximum allowed: {}",
977                num_ranges
978            );
979            return None;
980        }
981        let mut bytes = &bytes[2..];
982        for _ in 0..num_ranges {
983            let range = Range4 {
984                min: u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
985                max: u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
986                step: u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]),
987            };
988            ranges.push(range).unwrap();
989            bytes = &bytes[12..];
990        }
991        Some(Self { ranges })
992    }
993}
994
995/// Represents a range of 4-byte (u32) values.
996#[derive(Debug)]
997pub struct Range4 {
998    /// Minimum value in the range.
999    pub min: u32,
1000    /// Maximum value in the range.
1001    pub max: u32,
1002    /// Step size between values in the range.
1003    pub step: u32,
1004}
1005
1006/// Represents a range of 2-byte (u16) values.
1007#[derive(Debug)]
1008pub struct Range2 {
1009    /// Minimum value in the range.
1010    pub min: u16,
1011    /// Maximum value in the range.
1012    pub max: u16,
1013    /// Step size between values in the range.
1014    pub step: u16,
1015}
1016
1017/// Represents a range of 1-byte (u8) values.
1018#[derive(Debug)]
1019pub struct Range1 {
1020    /// Minimum value in the range.
1021    pub min: u8,
1022    /// Maximum value in the range.
1023    pub max: u8,
1024    /// Step size between values in the range.
1025    pub step: u8,
1026}