readme, doc comments, clippies

This commit is contained in:
2026-05-17 22:53:33 -07:00
parent 719d4391b8
commit 2b39987ef5
4 changed files with 117 additions and 10 deletions
+6
View File
@@ -27,3 +27,9 @@ embedded-io = "0.7.1"
modular-bitfield = "0.13.1"
num-traits = { version = "0.2.19", default-features = false }
usb-device.workspace = true
[profile.release]
opt-level = "z"
lto = true
debug = true
codegen-units = 1
+45
View File
@@ -0,0 +1,45 @@
# usbd-uac2
USB Audio Class 2.0
This crate provides a USB Audio Class 2.0 implementation for
[usb-device](https://crates.io/crates/usb-device). It implements all
required elements of the specification, however many controls are not
implemented (e.g. mixers, effects).
Device behaviour is driven by implementing the `ClockSource` and
`AudioHandler` traits to configure the audio pipeline and source/sink data
to/from USB.
Example (creates a UAC2 device with in and out streams):
```rust
let mut audio = YourTraitImpl {...};
let config = UsbAudioClassConfig::new(usb_speed, FunctionCode::IoBox, &mut audio)
// base_id is USB entity ID, id 1 is always taken by the clock source, and each stream builds 2 entities
.with_output_config(TerminalConfig::builder().base_id(2).build())
.with_input_config(TerminalConfig::builder().base_id(4).build());
let mut uac2 = config.build(&usb_bus).unwrap();
let mut usb_dev = usbd_uac2::builder(&usb_bus, UsbVidPid(0x1209, 0x0001))
.strings(&[StringDescriptors::default()
.manufacturer("usbd_uac2")
.product("example")])
.unwrap()
.max_packet_size_0(64) // Required to be 64 on HS
.unwrap()
.build();
```
No work needs to be done in the poll loop, the class implementation will
call your trait callbacks as required, just call the usb poll as usual:
```rust
loop {
usb_dev.poll(&mut [&mut uac2]);
}
```
See the trait documentation or examples for additional details.
+50 -5
View File
@@ -1,3 +1,47 @@
//! USB Audio Class 2.0
//!
//! This crate provides a USB Audio Class 2.0 implementation for
//! [usb-device](https://crates.io/crates/usb-device). It implements all
//! required elements of the specification, however many controls are not
//! implemented (e.g. mixers, effects).
//!
//! Device behaviour is driven by implementing the `ClockSource` and
//! `AudioHandler` traits to configure the audio pipeline and source/sink data
//! to/from USB.
//!
//! Example (creates a UAC2 device with in and out streams):
//!
//! ```ignore
//! let mut audio = YourTraitImpl {...};
//!
//! let config = UsbAudioClassConfig::new(usb_speed, FunctionCode::IoBox, &mut audio)
//! // base_id is USB entity ID, id 1 is always taken by the clock source, and each stream builds 2 entities
//! .with_output_config(TerminalConfig::builder().base_id(2).build())
//! .with_input_config(TerminalConfig::builder().base_id(4).build());
//!
//! let mut uac2 = config.build(&usb_bus).unwrap();
//!
//! let mut usb_dev = usbd_uac2::builder(&usb_bus, UsbVidPid(0x1209, 0x0001))
//! .strings(&[StringDescriptors::default()
//! .manufacturer("usbd_uac2")
//! .product("example")])
//! .unwrap()
//! .max_packet_size_0(64) // Required to be 64 on HS
//! .unwrap()
//! .build();
//! ```
//!
//! No work needs to be done in the poll loop, the class implementation will
//! call your trait callbacks as required, just call the usb poll as usual:
//!
//! ```ignore
//! loop {
//! usb_dev.poll(&mut [&mut uac2]);
//! }
//! ```
//!
//! See the trait documentation or examples for additional details.
#![no_std]
#![allow(dead_code)]
@@ -9,11 +53,12 @@ mod log;
use core::cmp::Ordering;
use core::marker::PhantomData;
use byteorder_embedded_io::{LittleEndian, ReadBytesExt, WriteBytesExt};
use constants::*;
use descriptors::*;
#[allow(unused_imports)]
use log::*;
use byteorder_embedded_io::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_traits::{ConstZero, ToPrimitive};
use usb_device::control::{Recipient, Request, RequestType};
use usb_device::device::{DEFAULT_ALTERNATE_SETTING, UsbDeviceBuilder, UsbVidPid};
@@ -936,8 +981,8 @@ impl<'a, B: UsbBus, AU: AudioHandler<'a, B> + ClockSource> UsbClass<B>
break;
}
Err(UsbError::WouldBlock) => break,
Err(err) => {
debug!("EP OUT error {:?}", err);
Err(_err) => {
debug!("EP OUT error {:?}", _err);
}
}
}
@@ -962,8 +1007,8 @@ impl<'a, B: UsbBus, AU: AudioHandler<'a, B> + ClockSource> UsbAudioClass<'a, B,
UsbSpeed::Low | UsbSpeed::Full => fb_ep.write(&fb.to_bytes_10_14()),
UsbSpeed::High | UsbSpeed::Super => fb_ep.write(&fb.to_bytes_12_13()),
};
if let Err(e) = r {
warn!(" feedback IN failed {:?}", e);
if let Err(_e) = r {
warn!(" feedback IN failed {:?}", _e);
}
} else {
debug!(" feedback callback returned None");
+16 -5
View File
@@ -7,25 +7,36 @@ pub use defmt::{debug, error, info, trace, warn};
mod no_defmt {
#[macro_export]
macro_rules! trace {
($($t:tt)*) => {};
($($t:tt)*) => {
()
};
}
#[macro_export]
macro_rules! debug {
($($t:tt)*) => {};
($($t:tt)*) => {
()
};
}
#[macro_export]
macro_rules! info {
($($t:tt)*) => {};
($($t:tt)*) => {
()
};
}
#[macro_export]
macro_rules! warn {
($($t:tt)*) => {};
($($t:tt)*) => {
()
};
}
#[macro_export]
macro_rules! error {
($($t:tt)*) => {};
($($t:tt)*) => {
()
};
}
}
#[allow(unused_imports)]
#[cfg(not(feature = "defmt"))]
pub use no_defmt::*;