fix nominal_fb and max packet size for non-integral rates

This commit is contained in:
2026-05-15 13:36:25 -07:00
parent e2edb1d468
commit 066c5dbf96
+16 -3
View File
@@ -15,7 +15,7 @@ use constants::*;
use descriptors::*; use descriptors::*;
use log::*; use log::*;
use num_traits::ConstZero; use num_traits::{ConstZero, ToPrimitive};
use usb_device::control::{Recipient, Request, RequestType}; use usb_device::control::{Recipient, Request, RequestType};
use usb_device::device::DEFAULT_ALTERNATE_SETTING; use usb_device::device::DEFAULT_ALTERNATE_SETTING;
use usb_device::endpoint::{self, Endpoint, EndpointDirection, In, Out}; use usb_device::endpoint::{self, Endpoint, EndpointDirection, In, Out};
@@ -115,6 +115,10 @@ impl UsbIsochronousFeedback {
pub fn new_frac(int: u16, frac: u16) -> Self { pub fn new_frac(int: u16, frac: u16) -> Self {
Self { int, frac } Self { int, frac }
} }
pub fn new_float(rate: f32) -> Self {
let fb = (rate * 65536.0 + 0.5) as u32;
Self::new(fb)
}
/// Assumed 16.16, not either of the USB formats /// Assumed 16.16, not either of the USB formats
pub fn new(value: u32) -> Self { pub fn new(value: u32) -> Self {
Self { Self {
@@ -487,6 +491,10 @@ impl<'a, B: UsbBus, CS: UsbAudioClockImpl, AU: UsbAudioClass<'a, B>>
.max; .max;
let control_iface = alloc.interface(); let control_iface = alloc.interface();
let nominal_fb = UsbIsochronousFeedback::new_float(
self.clock_impl.get_sample_rate().to_f32().unwrap() / audio_rate.to_f32().unwrap(),
);
let mut ac = AudioClass { let mut ac = AudioClass {
control_iface, control_iface,
clock_impl: self.clock_impl, clock_impl: self.clock_impl,
@@ -502,6 +510,7 @@ impl<'a, B: UsbBus, CS: UsbAudioClockImpl, AU: UsbAudioClass<'a, B>>
out_ep: 0, out_ep: 0,
fb_ep: 0, fb_ep: 0,
speed, speed,
nominal_fb,
audio_rate, audio_rate,
}; };
@@ -510,7 +519,7 @@ impl<'a, B: UsbBus, CS: UsbAudioClockImpl, AU: UsbAudioClass<'a, B>>
let endpoint = alloc.isochronous( let endpoint = alloc.isochronous(
config.sync_type, config.sync_type,
IsochronousUsageType::Data, IsochronousUsageType::Data,
(max_rate.div_ceil(audio_rate) * config.bytes_per_frame()) as u16, ((max_rate.div_ceil(audio_rate) + 1) * config.bytes_per_frame()) as u16, // headroom of 1 sample for rate control
interval, interval,
); );
let feedback_ep = alloc.isochronous( let feedback_ep = alloc.isochronous(
@@ -537,7 +546,7 @@ impl<'a, B: UsbBus, CS: UsbAudioClockImpl, AU: UsbAudioClass<'a, B>>
let endpoint = alloc.isochronous( let endpoint = alloc.isochronous(
config.sync_type, config.sync_type,
IsochronousUsageType::Data, IsochronousUsageType::Data,
(max_rate.div_ceil(audio_rate) * config.bytes_per_frame()) as u16, ((max_rate.div_ceil(audio_rate) + 1) * config.bytes_per_frame()) as u16, // headroom of 1 sample for rate control
interval, interval,
); );
let alt_setting = DEFAULT_ALTERNATE_SETTING; let alt_setting = DEFAULT_ALTERNATE_SETTING;
@@ -669,6 +678,7 @@ pub struct AudioClass<'a, B: UsbBus, CS: UsbAudioClockImpl, AU: UsbAudioClass<'a
out_ep: usize, out_ep: usize,
fb_ep: usize, fb_ep: usize,
speed: UsbSpeed, speed: UsbSpeed,
nominal_fb: UsbIsochronousFeedback,
audio_rate: u32, // audio packet rate in hz audio_rate: u32, // audio packet rate in hz
} }
@@ -1179,6 +1189,9 @@ impl<'a, B: UsbBus, CS: UsbAudioClockImpl, AU: UsbAudioClass<'a, B>> AudioClass<
Ok(rate) => { Ok(rate) => {
debug!(" SET SamplingFreqControl CUR {}", rate); debug!(" SET SamplingFreqControl CUR {}", rate);
self.clock_impl.set_sample_rate(rate).ok(); self.clock_impl.set_sample_rate(rate).ok();
self.nominal_fb = UsbIsochronousFeedback::new_float(
rate.to_f32().unwrap() / self.audio_rate.to_f32().unwrap(),
);
xfer.accept().ok(); xfer.accept().ok();
} }
Err(e) => { Err(e) => {